⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 create.c

📁 windows 2000中的UDF文件系统的驱动程序.只有读的功能,不支持未关闭的盘片.只支持UDF2.0以下版本,不支持VAT格式的UDF.
💻 C
📖 第 1 页 / 共 5 页
字号:

            //
            //  Do the prefix search to find the longest matching name.
            //

            CurrentLcb = UdfFindPrefix( IrpContext,
                                        &CurrentFcb,
                                        &RemainingName,
                                        IgnoreCase );
        }

        //
        //  At this point CurrentFcb points at the lowest Fcb in the tree for this
        //  file name, CurrentLcb is that name, and RemainingName is the rest of the
        //  name we have to do any directory traversals for.
        //

        //
        //  If the remaining name length is zero then we have found our
        //  target.
        //

        if (RemainingName.Length == 0) {

            //
            //  If this is a file so verify the user didn't want to open
            //  a directory.
            //

            if (SafeNodeType( CurrentFcb ) == UDFS_NTC_FCB_DATA) {

                if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH ) ||
                    FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) {

                    try_leave( Status = STATUS_NOT_A_DIRECTORY );
                }

                //
                //  The only create disposition we allow is OPEN.
                //

                if ((CreateDisposition != FILE_OPEN) &&
                    (CreateDisposition != FILE_OPEN_IF)) {

                    try_leave( Status = STATUS_ACCESS_DENIED );
                }

                try_leave( Status = UdfOpenExistingFcb( IrpContext,
                                                         IrpSp,
                                                         &CurrentFcb,
                                                         CurrentLcb,
                                                         UserFileOpen,
                                                         IgnoreCase,
                                                         RelatedCcb ));

            //
            //  This is a directory.  Verify the user didn't want to open
            //  as a file.
            //

            } else if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE )) {

                try_leave( Status = STATUS_FILE_IS_A_DIRECTORY );

            //
            //  Open the file as a directory.
            //

            } else {

                //
                //  The only create disposition we allow is OPEN.
                //

                if ((CreateDisposition != FILE_OPEN) &&
                    (CreateDisposition != FILE_OPEN_IF)) {

                    try_leave( Status = STATUS_ACCESS_DENIED );
                }

                try_leave( Status = UdfOpenExistingFcb( IrpContext,
                                                         IrpSp,
                                                         &CurrentFcb,
                                                         CurrentLcb,
                                                         UserDirectoryOpen,
                                                         IgnoreCase,
                                                         RelatedCcb ));
            }
        }

        //
        //  We have more work to do.  We have a starting Fcb which we own shared.
        //  We also have the remaining name to parse.  Walk through the name
        //  component by component looking for the full name.
        //

        //
        //  Our starting Fcb better be a directory.
        //

        if (!FlagOn( CurrentFcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {

            try_leave( Status = STATUS_OBJECT_PATH_NOT_FOUND );
        }

        //
        //  If we can't wait then post this request.
        //

        if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {

            UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT );
        }

        //
        //  Prepare the enumeration context for use.
        //
        
        UdfInitializeDirContext( IrpContext, &DirContext );
        CleanupDirContext = TRUE;

        while (TRUE) {

            ShortNameMatch = FALSE;

            //
            //  Split off the next component from the name.
            //

            UdfDissectName( IrpContext,
                            &RemainingName,
                            &FinalName );

            //
            //  Go ahead and look this entry up in the directory.
            //

            FoundEntry = UdfFindDirEntry( IrpContext,
                                          CurrentFcb,
                                          &FinalName,
                                          IgnoreCase,
                                          FALSE,
                                          &DirContext );

            //
            //  If we didn't find the entry then check if the current name
            //  is a possible short name.
            //

            if (!FoundEntry && UdfCandidateShortName( IrpContext, &FinalName)) {

                //
                //  If the name looks like it could be a short name, try to find
                //  a matching real directory entry.
                //

                ShortNameMatch =
                FoundEntry = UdfFindDirEntry( IrpContext,
                                              CurrentFcb,
                                              &FinalName,
                                              IgnoreCase,
                                              TRUE,
                                              &DirContext );
            }

            //
            //  If we didn't find a match then check what the caller was trying to do to
            //  determine which error code to return.
            //
    
            if (!FoundEntry) {
    
                if ((CreateDisposition == FILE_OPEN) ||
                    (CreateDisposition == FILE_OVERWRITE)) {
    
                    try_leave( Status = STATUS_OBJECT_NAME_NOT_FOUND );
                }
    
                //
                //  Any other operation return STATUS_ACCESS_DENIED.
                //
    
                try_leave( Status = STATUS_ACCESS_DENIED );
            }

            //
            //  If this is an ignore case open then copy the exact case
            //  in the file object name.
            //

            if (IgnoreCase && !ShortNameMatch) {

                ASSERT( FinalName.Length == DirContext.ObjectName.Length );
                
                RtlCopyMemory( FinalName.Buffer,
                               DirContext.ObjectName.Buffer,
                               DirContext.ObjectName.Length );
            }

            //
            //  If we have found the last component then break out to open for the caller.
            //

            if (RemainingName.Length == 0) {

                break;
            }
            
            //
            //  The object we just found must be a directory.
            //

            if (!FlagOn( DirContext.Fid->Flags, NSR_FID_F_DIRECTORY )) {

                try_leave( Status = STATUS_OBJECT_PATH_NOT_FOUND );
            }

            //
            //  Now open an Fcb for this intermediate index Fcb.
            //

            UdfOpenObjectFromDirContext( IrpContext,
                                         IrpSp,
                                         Vcb,
                                         &CurrentFcb,
                                         ShortNameMatch,
                                         IgnoreCase,
                                         &DirContext,
                                         FALSE,
                                         NULL );
        }
        
        //
        //  Make sure our opener is about to get what they expect.
        //

        if ((FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH ) ||
             FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) &&
            !FlagOn( DirContext.Fid->Flags, NSR_FID_F_DIRECTORY )) {

            try_leave( Status = STATUS_NOT_A_DIRECTORY );
        
        }

        if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE ) &&
            FlagOn( DirContext.Fid->Flags, NSR_FID_F_DIRECTORY )) {

            try_leave( Status = STATUS_FILE_IS_A_DIRECTORY );
        }

        //
        //  The only create disposition we allow is OPEN.
        //

        if ((CreateDisposition != FILE_OPEN) &&
            (CreateDisposition != FILE_OPEN_IF)) {

            try_leave( Status = STATUS_ACCESS_DENIED );
        }

        //
        //  Open the object for the caller.
        //

        try_leave( Status = UdfOpenObjectFromDirContext( IrpContext,
                                                         IrpSp,
                                                         Vcb,
                                                         &CurrentFcb,
                                                         ShortNameMatch,
                                                         IgnoreCase,
                                                         &DirContext,
                                                         TRUE,
                                                         RelatedCcb ));
    } finally {
        
        //
        //  Cleanup the enumeration context if initialized.
        //

        if (CleanupDirContext) {

            UdfCleanupDirContext( IrpContext, &DirContext );
        }

        //
        //  The result of this open could be success, pending or some error
        //  condition.
        //

        if (AbnormalTermination()) {


            //
            //  In the error path we start by calling our teardown routine if we
            //  have a CurrentFcb.
            //

            if (CurrentFcb != NULL) {

                BOOLEAN RemovedFcb;

                UdfTeardownStructures( IrpContext, CurrentFcb, FALSE, &RemovedFcb );

                if (RemovedFcb) {

                    CurrentFcb = NULL;
                }
            }
            
            //
            //  No need to complete the request.
            //

            IrpContext = NULL;
            Irp = NULL;

        //
        //  If we posted this request through the oplock package we need
        //  to show that there is no reason to complete the request.
        //

        } else if (Status == STATUS_PENDING) {

            IrpContext = NULL;
            Irp = NULL;
        }

        //
        //  Release the Current Fcb if still acquired.
        //

        if (CurrentFcb != NULL) {

            UdfReleaseFcb( IrpContext, CurrentFcb );
        }

        //
        //  Release the Vcb.
        //

        UdfReleaseVcb( IrpContext, Vcb );

        //
        //  Call our completion routine.  It will handle the case where either
        //  the Irp and/or IrpContext are gone.
        //

        UdfCompleteRequest( IrpContext, Irp, Status );
    }

    return Status;
}


//
//  Local support routine
//

NTSTATUS
UdfNormalizeFileNames (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN BOOLEAN OpenByFileId,
    IN BOOLEAN IgnoreCase,
    IN TYPE_OF_OPEN RelatedTypeOfOpen,
    IN PCCB RelatedCcb OPTIONAL,
    IN PUNICODE_STRING RelatedFileName OPTIONAL,
    IN OUT PUNICODE_STRING FileName,
    IN OUT PUNICODE_STRING RemainingName
    )

/*++

Routine Description:

    This routine is called to store the full name and upcased name into the
    filename buffer.  We only upcase the portion yet to parse.  We also
    check for a trailing backslash and lead-in double backslashes.  This
    routine also verifies the mode of the related open against the name
    currently in the filename.

Arguments:

    Vcb - Vcb for this volume.

    OpenByFileId - Indicates if the filename should be a 64 bit FileId.

    IgnoreCase - Indicates if this open is a case-insensitive operation.

    RelatedTypeOfOpen - Indicates the type of the related file object.

    RelatedCcb - Ccb for the related open.  Ignored if no relative open.

    RelatedFileName - FileName buffer for related open.  Ignored if no
        relative open.

    FileName - FileName to update in this routine.  The name should
        either be a 64-bit FileId or a Unicode string.

    RemainingName - Name with the remaining portion of the name.  This
        will begin after the related name and any separator.  For a
        non-relative open we also step over the initial separator.

Return Value:

    NTSTATUS - STATUS_SUCCESS if the names are OK, appropriate error code
        otherwise.

--*/

{
    ULONG RemainingNameLength;
    ULONG RelatedNameLength = 0;
    ULONG SeparatorLength = 0;

    ULONG BufferLength;

    UNICODE_STRING NewFileName;

    PAGED_CODE();

    //
    //  If this is the first pass then we need to build the full name and
    //  check for name compatibility.
    //

    if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_FULL_NAME )) {

        //
        //  Deal with the regular file name case first.
        //

        if (!OpenByFileId) {

            //
            //  Here is the  "M A R K   L U C O V S K Y"  hack.
            //
            //  It's here because Mark says he can't avoid sending me double beginning
            //  backslashes via the Win32 layer.
            //

            if ((FileName->Length > sizeof( WCHAR )) &&
                (FileName->Buffer[1] == L'\\') &&
                (FileName->Buffer[0] == L'\\')) {

                //
                //  If there are still two beginning backslashes, the name is bogus.
                //

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -