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

📄 namesup.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 2 页
字号:
Arguments:

    Fcb - Supplies the file.

Return Value:

    None

--*/

{
    if (Fcb->FullFileName.Buffer == NULL) {

        UNICODE_STRING Lfn;
        PFCB TmpFcb = Fcb;
        PFCB StopFcb;
        PWCHAR TmpBuffer;
        ULONG PathLength = 0;

        //
        //  We will assume we do this infrequently enough, that it's OK to
        //  to a pool allocation here.
        //

        Lfn.Length = 0;
        Lfn.MaximumLength = MAX_LFN_CHARACTERS * sizeof(WCHAR);
        Lfn.Buffer = FsRtlAllocatePoolWithTag( PagedPool,
                                               MAX_LFN_CHARACTERS * sizeof(WCHAR),
                                               TAG_FILENAME_BUFFER );

        try {

            //
            //  First determine how big the name will be.  If we find an
            //  ancestor with a FullFileName, our work is easier.
            //

            while (TmpFcb != Fcb->Vcb->RootDcb) {

                if ((TmpFcb != Fcb) && (TmpFcb->FullFileName.Buffer != NULL)) {

                    PathLength += TmpFcb->FullFileName.Length;

                    Fcb->FullFileName.Buffer = FsRtlAllocatePoolWithTag( PagedPool,
                                                                         PathLength,
                                                                         TAG_FILENAME_BUFFER );

                    RtlCopyMemory( Fcb->FullFileName.Buffer,
                                   TmpFcb->FullFileName.Buffer,
                                   TmpFcb->FullFileName.Length );

                    break;
                }

                PathLength += TmpFcb->FinalNameLength + sizeof(WCHAR);

                TmpFcb = TmpFcb->ParentDcb;
            }

            //
            //  If FullFileName.Buffer is still NULL, allocate it.
            //

            if (Fcb->FullFileName.Buffer == NULL) {

                Fcb->FullFileName.Buffer = FsRtlAllocatePoolWithTag( PagedPool,
                                                                     PathLength,
                                                                     TAG_FILENAME_BUFFER );
            }

            StopFcb = TmpFcb;

            TmpFcb = Fcb;
            TmpBuffer =  Fcb->FullFileName.Buffer + PathLength / sizeof(WCHAR);

            Fcb->FullFileName.Length =
            Fcb->FullFileName.MaximumLength = (USHORT)PathLength;

            while (TmpFcb != StopFcb) {

                FatGetUnicodeNameFromFcb( IrpContext,
                                          TmpFcb,
                                          &Lfn );

                TmpBuffer -= Lfn.Length / sizeof(WCHAR);

                RtlCopyMemory( TmpBuffer, Lfn.Buffer, Lfn.Length );

                TmpBuffer -= 1;

                *TmpBuffer = L'\\';

                TmpFcb = TmpFcb->ParentDcb;
            }

        } finally {

            if (AbnormalTermination()) {

                if (Fcb->FullFileName.Buffer) {

                    ExFreePool( Fcb->FullFileName.Buffer );
                    Fcb->FullFileName.Buffer = NULL;
                }
            }

            ExFreePool( Lfn.Buffer );
        }
    }
}

VOID
FatUnicodeToUpcaseOem (
    IN PIRP_CONTEXT IrpContext,
    IN POEM_STRING OemString,
    IN PUNICODE_STRING UnicodeString
    )

/*++

Routine Description:

    This routine is our standard routine for trying to use stack space
    if possible when calling RtlUpcaseUnicodeStringToCountedOemString().

    If an unmappable character is encountered, we set the destination
    length to 0.

Arguments:

    OemString - Specifies the destination string.  Space is already assumed to
        be allocated.  If there is not enough, then we allocate enough
        space.

    UnicodeString - Specifies the source string.

Return Value:

    None.

--*/

{
    NTSTATUS Status;

    Status = RtlUpcaseUnicodeStringToCountedOemString( OemString,
                                                       UnicodeString,
                                                       FALSE );

    if (Status == STATUS_BUFFER_OVERFLOW) {

        OemString->Buffer = NULL;
        OemString->Length = 0;
        OemString->MaximumLength = 0;

        Status = RtlUpcaseUnicodeStringToCountedOemString( OemString,
                                                           UnicodeString,
                                                           TRUE );
    }

    if (!NT_SUCCESS(Status)) {

        if (Status == STATUS_UNMAPPABLE_CHARACTER) {

            OemString->Length = 0;

        } else {

            FatNormalizeAndRaiseStatus( IrpContext, Status );
        }
    }

    return;
}


VOID
FatSelectNames (
    IN PIRP_CONTEXT IrpContext,
    IN PDCB Parent,
    IN POEM_STRING OemName,
    IN PUNICODE_STRING UnicodeName,
    IN OUT POEM_STRING ShortName,
    IN PUNICODE_STRING SuggestedShortName OPTIONAL,
    IN OUT BOOLEAN *AllLowerComponent,
    IN OUT BOOLEAN *AllLowerExtension,
    IN OUT BOOLEAN *CreateLfn
    )

/*++

Routine Description:

    This routine takes the original UNICODE string that the user specified,
    and the upcased Oem equivolent.  This routine then decides if the OemName
    is acceptable for dirent, or whether a short name has to be manufactured.

    Two values are returned to the caller.  One tells the caller if the name
    happens to be all lower case < 0x80.  In this special case we don't
    have to create an Lfn.  Also we tell the caller if it must create an LFN.

Arguments:

    OemName -  Supplies the proposed short Oem name.

    ShortName - If this OemName is OK for storeage in a dirent it is copied to
        this string, otherwise this string is filled with a name that is OK.
        If OemName and ShortName are the same string, no copy is done.

    UnicodeName - Provides the original final name.

    SuggestedShortName - a first-try short name to try before auto-generation
        is used

    AllLowerComponent - Returns whether this component was all lower case.

    AllLowerExtension - Returns wheather the extension was all lower case.

    CreateLfn - Tells the caller if we must create an LFN for the UnicodeName or
        SuggestedLongName

Return Value:

    None.

--*/

{
    BOOLEAN GenerateShortName;
    
    PAGED_CODE();

    //
    //  First see if we must generate a short name.
    //

    if ((OemName->Length == 0) ||
        !FatIsNameShortOemValid( IrpContext, *OemName, FALSE, FALSE, FALSE ) ||
        FatSpaceInName( IrpContext, UnicodeName )) {

        WCHAR ShortNameBuffer[12];
        UNICODE_STRING ShortUnicodeName;
        GENERATE_NAME_CONTEXT Context;
        BOOLEAN TrySuggestedShortName;

        PDIRENT Dirent;
        PBCB Bcb = NULL;
        ULONG ByteOffset;
        NTSTATUS Status;

        GenerateShortName = TRUE;

        TrySuggestedShortName = (SuggestedShortName != NULL);
    
        //
        //  Now generate a short name.
        //

        ShortUnicodeName.Length = 0;
        ShortUnicodeName.MaximumLength = 12 * sizeof(WCHAR);
        ShortUnicodeName.Buffer = ShortNameBuffer;

        RtlZeroMemory( &Context, sizeof( GENERATE_NAME_CONTEXT ) );

        try {
            
            while ( TRUE ) {

                FatUnpinBcb( IrpContext, Bcb );

                if (TrySuggestedShortName) {

                    //
                    //  Try our caller's candidate first. Note that this must have
                    //  been uppercased previously.
                    //

                    ShortUnicodeName.Length = SuggestedShortName->Length;
                    ShortUnicodeName.MaximumLength = SuggestedShortName->MaximumLength;
                    ShortUnicodeName.Buffer = SuggestedShortName->Buffer;

                    TrySuggestedShortName = FALSE;

                } else {

                    RtlGenerate8dot3Name( UnicodeName, TRUE, &Context, &ShortUnicodeName );
                }

                //
                //  We have a candidate, make sure it doesn't exist.
                //

                Status = RtlUnicodeStringToCountedOemString( ShortName,
                                                             &ShortUnicodeName,
                                                             FALSE );

                ASSERT( Status == STATUS_SUCCESS );

                FatLocateSimpleOemDirent( IrpContext,
                                          Parent,
                                          ShortName,
                                          &Dirent,
                                          &Bcb,
                                          &ByteOffset );

                if (Bcb == NULL) {

                    leave;

                }
            }

        } finally {
            
            FatUnpinBcb( IrpContext, Bcb );
        }

    } else {

        //
        //  Only do this copy if the two string are indeed different.
        //

        if (ShortName != OemName) {

            ShortName->Length = OemName->Length;
            RtlCopyMemory( ShortName->Buffer, OemName->Buffer, OemName->Length );
        }

        GenerateShortName = FALSE;
    }

    //
    //  Now see if the caller will have to use unicode string as an LFN
    //

    if (GenerateShortName) {

        *CreateLfn = TRUE;
        *AllLowerComponent = FALSE;
        *AllLowerExtension = FALSE;

    } else {

        FatEvaluateNameCase( IrpContext,
                             UnicodeName,
                             AllLowerComponent,
                             AllLowerExtension,
                             CreateLfn );
    }

    return;
}


VOID
FatEvaluateNameCase (
    IN PIRP_CONTEXT IrpContext,
    IN PUNICODE_STRING UnicodeName,
    IN OUT BOOLEAN *AllLowerComponent,
    IN OUT BOOLEAN *AllLowerExtension,
    IN OUT BOOLEAN *CreateLfn
    )

/*++

Routine Description:

    This routine takes a UNICODE string and sees if it is eligible for
    the special case optimization.

Arguments:

    UnicodeName - Provides the original final name.

    AllLowerComponent - Returns whether this compoent was all lower case.

    AllLowerExtension - Returns wheather the extension was all lower case.

    CreateLfn - Tells the call if we must create an LFN for the UnicodeName.

Return Value:

    None.

--*/

{
    ULONG i;
    UCHAR Uppers = 0;
    UCHAR Lowers = 0;

    BOOLEAN ExtensionPresent = FALSE;

    *CreateLfn = FALSE;

    for (i = 0; i < UnicodeName->Length / sizeof(WCHAR); i++) {

        WCHAR c;

        c = UnicodeName->Buffer[i];

        if ((c >= 'A') && (c <= 'Z')) {

            Uppers += 1;

        } else if ((c >= 'a') && (c <= 'z')) {

            Lowers += 1;

        } else if ((c >= 0x0080) && FatData.CodePageInvariant) {

            break;
        }

        //
        //  If we come to a period, figure out if the extension was
        //  all one case.
        //

        if (c == L'.') {

            *CreateLfn = (Lowers != 0) && (Uppers != 0);

            *AllLowerComponent = !(*CreateLfn) && (Lowers != 0);

            ExtensionPresent = TRUE;

            //
            //  Now reset the uppers and lowers count.
            //

            Uppers = Lowers = 0;
        }
    }

    //
    //  Now check again for creating an LFN.
    //

    *CreateLfn = (*CreateLfn ||
                  (i != UnicodeName->Length / sizeof(WCHAR)) ||
                  ((Lowers != 0) && (Uppers != 0)));

    //
    //  Now we know the final state of CreateLfn, update the two
    //  "AllLower" booleans.
    //

    if (ExtensionPresent) {

        *AllLowerComponent = !(*CreateLfn) && *AllLowerComponent;
        *AllLowerExtension = !(*CreateLfn) && (Lowers != 0);

    } else {

        *AllLowerComponent = !(*CreateLfn) && (Lowers != 0);
        *AllLowerExtension = FALSE;
    }

    return;
}


BOOLEAN
FatSpaceInName (
    IN PIRP_CONTEXT IrpContext,
    IN PUNICODE_STRING UnicodeName
    )

/*++

Routine Description:

    This routine takes a UNICODE string and sees if it contains any spaces.

Arguments:

    UnicodeName - Provides the final name.

Return Value:

    BOOLEAN - TRUE if it does, FALSE if it doesn't.

--*/

{
    ULONG i;

    for (i=0; i < UnicodeName->Length/sizeof(WCHAR); i++) {

        if (UnicodeName->Buffer[i] == L' ') {
            return TRUE;
        }
    }

    return FALSE;
}


⌨️ 快捷键说明

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