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

📄 namesup.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 2 页
字号:
    WCHAR BiasedShortNameBuffer[ BYTE_COUNT_8_DOT_3 / sizeof( WCHAR ) ];

    GENERATE_NAME_CONTEXT NameContext;

    ULONG BiasedDirentOffset;

    ULONG MaximumBaseBytes;
    ULONG BaseNameOffset;

    PWCHAR NextWchar;
    WCHAR ThisWchar;
    USHORT Length;

    BOOLEAN FoundTilde = FALSE;

    OEM_STRING OemName;
    USHORT OemNameOffset = 0;
    BOOLEAN OverflowBuffer = FALSE;

    PAGED_CODE();

    //
    //  Initialize the short string to use the input buffer.
    //

    ShortName.Buffer = ShortNameBuffer;
    ShortName.MaximumLength = BYTE_COUNT_8_DOT_3;

    //
    //  Initialize the name context.
    //

    RtlZeroMemory( &NameContext, sizeof( GENERATE_NAME_CONTEXT ));

    //
    //  We now have the unicode name for the input string.  Go ahead and generate
    //  the short name.
    //

    RtlGenerate8dot3Name( FileName, TRUE, &NameContext, &ShortName );

    //
    //  We now have the generic short name.  We want incorporate the dirent offset
    //  into the name in order to reduce the chance of name conflicts.  We will use
    //  a tilde character followed by a character representation of the dirent offset.
    //  This will be the hexadecimal representation of the dirent offset in the directory.
    //  It is actuall this offset divided by 32 since we don't need the full
    //  granularity.
    //

    BiasedDirentOffset = DirentOffset >> SHORT_NAME_SHIFT;

    //
    //  Point to a local buffer to store the offset string.  We start
    //  at the end of the buffer and work backwards.
    //

    NextWchar = Add2Ptr( BiasedShortNameBuffer,
                         BYTE_COUNT_8_DOT_3,
                         PWCHAR );

    BiasedShortName.MaximumLength = BYTE_COUNT_8_DOT_3;

    //
    //  Generate an OEM version of the string so that we can check for double
    //  byte characters.
    //
    
    Status = RtlUnicodeStringToOemString(&OemName, &ShortName, TRUE);

    //
    //  If this failed, bail out. Don't expect any problems other than no mem.
    //
    
    if (!NT_SUCCESS( Status)) {

        ASSERT( STATUS_INSUFFICIENT_RESOURCES == Status);
        CdRaiseStatus( IrpContext, Status);
    }
    
    Length = 0;

    //
    //  Now add the characters for the dirent offset.  We need to start
    //  from the least significant digit and work backwards.
    //

    do {

        NextWchar -= 1;

        ThisWchar = (WCHAR) (BiasedDirentOffset & 0x0000000f);

        //
        //  Store in the next character.  Bias against either '0' or 'A'
        //

        if (ThisWchar <= 9) {

            *NextWchar = ThisWchar + L'0';

        } else {

            *NextWchar = ThisWchar + L'A' - 0xA;
        }

        Length += sizeof( WCHAR );

        //
        //  Shift out the low 4 bits of the offset.
        //

        BiasedDirentOffset >>= 4;

    } while (BiasedDirentOffset != 0);

    //
    //  Now store in the tilde character.
    //

    NextWchar -= 1;
    *NextWchar = L'~';
    Length += sizeof( WCHAR );

    //
    //  Set the length of this string.
    //

    BiasedShortName.Length = Length;
    BiasedShortName.Buffer = NextWchar;

    //
    //  Figure out the maximum number of characters we can copy of the base
    //  name.  We subract the number of characters in the dirent string from 8.
    //  We will copy this many characters or stop when we reach a '.' character
    //  or a '~' character in the name.
    //

    MaximumBaseBytes = 16 - Length;

    BaseNameOffset = 0;

    //
    //  Keep copying from the base name until we hit a '.', '~'  or the end of
    //  the short name.
    //

    NextWchar = ShortFileName;
    Length = 0;

    while ((BaseNameOffset < ShortName.Length) &&
           (ShortName.Buffer[BaseNameOffset / 2] != L'.')) {

        //
        //  Remember if we found a tilde character in the short name,
        //  so we don't copy it or anything following it.
        //

        if (ShortName.Buffer[BaseNameOffset / 2] == L'~') {

            FoundTilde = TRUE;
        }

        //
        // We need to consider the DBCS code page,  because Unicode characters
        // may use 2 bytes as DBCS characters.
        //

        if (FsRtlIsLeadDbcsCharacter(OemName.Buffer[OemNameOffset])) {

            OemNameOffset += 2;

            if ((OemNameOffset + (BiasedShortName.Length / sizeof(WCHAR))) > 8)  {
            
                OverflowBuffer = TRUE;
            }
        }
        else  {
        
            OemNameOffset++;
        }

        //
        //  Only copy the bytes if we still have space for the dirent string.
        //

        if (!FoundTilde && !OverflowBuffer && (BaseNameOffset < MaximumBaseBytes)) {

            *NextWchar = ShortName.Buffer[BaseNameOffset / 2];
            Length += sizeof( WCHAR );
            NextWchar += 1;
        }

        BaseNameOffset += 2;
    }

    RtlFreeOemString(&OemName);

    //
    //  Now copy the dirent string into the biased name buffer.
    //

    RtlCopyMemory( NextWchar,
                   BiasedShortName.Buffer,
                   BiasedShortName.Length );

    Length += BiasedShortName.Length;
    NextWchar += (BiasedShortName.Length / sizeof( WCHAR ));

    //
    //  Now copy any remaining bytes over to the biased short name.
    //

    if (BaseNameOffset != ShortName.Length) {

        RtlCopyMemory( NextWchar,
                       &ShortName.Buffer[BaseNameOffset / 2],
                       ShortName.Length - BaseNameOffset );

        Length += (ShortName.Length - (USHORT) BaseNameOffset);
    }

    //
    //  The final short name is stored in the user's buffer.
    //

    *ShortByteCount = Length;
}


BOOLEAN
CdIsNameInExpression (
    IN PIRP_CONTEXT IrpContext,
    IN PCD_NAME CurrentName,
    IN PCD_NAME SearchExpression,
    IN ULONG  WildcardFlags,
    IN BOOLEAN CheckVersion
    )

/*++

Routine Description:

    This routine will compare two CdName strings.  We assume that if this
    is to be a case-insensitive search then they are already upcased.

    We compare the filename portions of the name and if they match we
    compare the version strings if requested.

Arguments:

    CurrentName - Filename from the disk.

    SearchExpression - Filename expression to use for match.

    WildcardFlags - Flags field which indicates which parts of the
        search expression might have wildcards.  These flags are the
        same as in the Ccb flags field.

    CheckVersion - Indicates whether we should check both the name and the
        version strings or just the name.

Return Value:

    BOOLEAN - TRUE if the expressions match, FALSE otherwise.

--*/

{
    BOOLEAN Match = TRUE;
    PAGED_CODE();

    //
    //  If there are wildcards in the expression then we call the
    //  appropriate FsRtlRoutine.
    //

    if (FlagOn( WildcardFlags, CCB_FLAG_ENUM_NAME_EXP_HAS_WILD )) {

        Match = FsRtlIsNameInExpression( &SearchExpression->FileName,
                                         &CurrentName->FileName,
                                         FALSE,
                                         NULL );

    //
    //  Otherwise do a direct memory comparison for the name string.
    //

    } else {

        if ((CurrentName->FileName.Length != SearchExpression->FileName.Length) ||
            (!RtlEqualMemory( CurrentName->FileName.Buffer,
                              SearchExpression->FileName.Buffer,
                              CurrentName->FileName.Length ))) {

            Match = FALSE;
        }
    }

    //
    //  Check the version numbers if requested by the user and we have a
    //  match on the name and the version number is present.
    //

    if (Match && CheckVersion && SearchExpression->VersionString.Length &&
        !FlagOn( WildcardFlags, CCB_FLAG_ENUM_VERSION_MATCH_ALL )) {

        //
        //  If there are wildcards in the expression then call the
        //  appropriate search expression.
        //

        if (FlagOn( WildcardFlags, CCB_FLAG_ENUM_VERSION_EXP_HAS_WILD )) {

            Match = FsRtlIsNameInExpression( &SearchExpression->VersionString,
                                             &CurrentName->VersionString,
                                             FALSE,
                                             NULL );

        //
        //  Otherwise do a direct memory comparison for the name string.
        //

        } else {

            if ((CurrentName->VersionString.Length != SearchExpression->VersionString.Length) ||
                (!RtlEqualMemory( CurrentName->VersionString.Buffer,
                                  SearchExpression->VersionString.Buffer,
                                  CurrentName->VersionString.Length ))) {

                Match = FALSE;
            }
        }
    }

    return Match;
}


ULONG
CdShortNameDirentOffset (
    IN PIRP_CONTEXT IrpContext,
    IN PUNICODE_STRING Name
    )

/*++

Routine Description:

    This routine is called to examine a name to see if the dirent offset string is contained.
    This consists of a tilde character followed by the offset represented as a hexadecimal
    characters.  We don't do any other checks to see if this is a short name.  We
    catch that later outside this routine.

Arguments:

    Name - This is the CdName to examine.

Return Value:

    ULONG - MAXULONG if there is no valid dirent offset string embedded, otherwise the
        convert the value to numeric form.

--*/

{
    ULONG ResultOffset = MAXULONG;
    ULONG RemainingByteCount = Name->Length;

    BOOLEAN FoundTilde = FALSE;

    PWCHAR NextWchar;

    PAGED_CODE();

    //
    //  Walk through the name until we either reach the end of the name
    //  or find a tilde character.
    //

    for (NextWchar = Name->Buffer;
         RemainingByteCount != 0;
         NextWchar += 1, RemainingByteCount -= sizeof( WCHAR )) {

        //
        //  Check if this is a dot.  Stop constructing any string if
        //  we found a dot.
        //

        if (*NextWchar == L'.') {

            break;
        }

        //
        //  If we already found a tilde then check this character as a
        //  valid character.  It must be a digit or A to F.
        //

        if (FoundTilde) {

            if ((*NextWchar < L'0') ||
                (*NextWchar > L'F') ||
                ((*NextWchar > L'9') && (*NextWchar < 'A'))) {

                ResultOffset = MAXULONG;
                break;
            }

            //
            //  Shift the result by 4 bits and add in this new character.
            //

            ResultOffset <<= 4;

            if (*NextWchar < L'A') {

                ResultOffset += *NextWchar - L'0';

            } else {

                ResultOffset += (*NextWchar - L'A') + 10;
            }

            continue;
        }

        //
        //  If this is a tilde then start building the dirent string.
        //

        if (*NextWchar == L'~') {

            FoundTilde = TRUE;
            ResultOffset = 0;
        }
    }

    return ResultOffset;
}


//
//  Local support routine
//

FSRTL_COMPARISON_RESULT
CdFullCompareNames (
    IN PIRP_CONTEXT IrpContext,
    IN PUNICODE_STRING NameA,
    IN PUNICODE_STRING NameB
    )

/*++

Routine Description:

    This function compares two names as fast as possible.  Note that since
    this comparison is case sensitive we can do a direct memory comparison.

Arguments:

    NameA & NameB - The names to compare.

Return Value:

    COMPARISON - returns

        LessThan    if NameA < NameB lexicalgraphically,
        GreaterThan if NameA > NameB lexicalgraphically,
        EqualTo     if NameA is equal to NameB

--*/

{
    SIZE_T i;
    ULONG MinLength = NameA->Length;
    FSRTL_COMPARISON_RESULT Result = LessThan;

    PAGED_CODE();

    //
    //  Figure out the minimum of the two lengths
    //

    if (NameA->Length > NameB->Length) {

        MinLength = NameB->Length;
        Result = GreaterThan;

    } else if (NameA->Length == NameB->Length) {

        Result = EqualTo;
    }

    //
    //  Loop through looking at all of the characters in both strings
    //  testing for equalilty, less than, and greater than
    //

    i = RtlCompareMemory( NameA->Buffer, NameB->Buffer, MinLength );

    if (i < MinLength) {

        //
        //  We know the offset of the first character which is different.
        //

        return ((NameA->Buffer[ i / 2 ] < NameB->Buffer[ i / 2 ]) ?
                 LessThan :
                 GreaterThan);
    }

    //
    //  The names match up to the length of the shorter string.
    //  The shorter string lexically appears first.
    //

    return Result;
}



⌨️ 快捷键说明

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