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

📄 namesup.c

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

Copyright (c) 1991  Microsoft Corporation

Module Name:

    NameSup.c

Abstract:

    This module implements the Udfs Name support routines

Author:

    Dan Lovinger    [DanLo]     9-October-1996

Revision History:

--*/

#include "UdfProcs.h"

//
//  The Bug check file id for this module
//

#define BugCheckFileId                   (UDFS_BUG_CHECK_NAMESUP)

//
//  The local debug trace level
//

#define Dbg                              (UDFS_DEBUG_LEVEL_NAMESUP)

//
//  Local constants
//

static CONST CHAR UdfCrcChar[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ#_~-@";

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, UdfCandidateShortName)
#pragma alloc_text(PAGE, UdfCheckLegalCS0Dstring)
#pragma alloc_text(PAGE, UdfConvertCS0DstringToUnicode)
#pragma alloc_text(PAGE, UdfDissectName)
#pragma alloc_text(PAGE, UdfFullCompareNames)
#pragma alloc_text(PAGE, UdfGenerate8dot3Name)
#pragma alloc_text(PAGE, UdfIs8dot3Name)
#pragma alloc_text(PAGE, UdfIsNameInExpression)
#pragma alloc_text(PAGE, UdfRenderNameToLegalUnicode)
#endif


INLINE
ULONG
NativeDosCharLength (
    IN WCHAR Wchar
    )

/*++

Routine Description:

    This routine is a translation layer for asking how big a given UNICODE
    character will be when converted to OEM.  Aside from adding more material
    to the kernel export table, this is how ya do it.

Arguments:

    Wchar - pointer to the character

Return Value:

    Size in bytes.

--*/

{
    NTSTATUS Status;
    CHAR OemBuf[2];
    ULONG Length;

    Status = RtlUpcaseUnicodeToOemN( OemBuf,
                                     sizeof(OemBuf),
                                     &Length,
                                     &Wchar,
                                     sizeof(WCHAR));
    
    ASSERT( NT_SUCCESS( Status ));

    return Length;
}


VOID
UdfDissectName (
    IN PIRP_CONTEXT IrpContext,
    IN OUT PUNICODE_STRING RemainingName,
    OUT PUNICODE_STRING FinalName
    )

/*++

Routine Description:

    This routine is called to strip off leading components of the name strings.  We search
    for either the end of the string or separating characters.  The input remaining
    name strings should have neither a trailing or leading backslash.

Arguments:

    RemainingName - Remaining name.

    FinalName - Location to store next component of name.

Return Value:

    None.

--*/

{
    ULONG NameLength;
    PWCHAR NextWchar;

    PAGED_CODE();

    //
    //  Check inputs.
    //

    ASSERT_IRP_CONTEXT( IrpContext );

    //
    //  Find the offset of the next component separators.
    //

    for (NameLength = 0, NextWchar = RemainingName->Buffer;
         (NameLength < RemainingName->Length) && (*NextWchar != L'\\');
         NameLength += sizeof( WCHAR) , NextWchar += 1);

    //
    //  Adjust all the strings by this amount.
    //

    FinalName->Buffer = RemainingName->Buffer;

    FinalName->MaximumLength = FinalName->Length = (USHORT) NameLength;

    //
    //  If this is the last component then set the RemainingName lengths to zero.
    //

    if (NameLength == RemainingName->Length) {

        RemainingName->Length = 0;

    //
    //  Otherwise we adjust the string by this amount plus the separating character.
    //

    } else {

        RemainingName->MaximumLength -= (USHORT) (NameLength + sizeof( WCHAR ));
        RemainingName->Length -= (USHORT) (NameLength + sizeof( WCHAR ));
        RemainingName->Buffer = Add2Ptr( RemainingName->Buffer,
                                         NameLength + sizeof( WCHAR ),
                                         PWCHAR );
    }

    return;
}


BOOLEAN
UdfIs8dot3Name (
    IN PIRP_CONTEXT IrpContext,
    IN UNICODE_STRING FileName
    )

/*++

Routine Description:

    This routine checks if the name follows the 8.3 name conventions.  We check for
    the name length and whether the characters are valid.

Arguments:

    FileName - String of bytes containing the name.

Return Value:

    BOOLEAN - TRUE if this name is a legal 8.3 name, FALSE otherwise.

--*/

{
    CHAR DbcsNameBuffer[ BYTE_COUNT_8_DOT_3 ];
    STRING DbcsName;

    PWCHAR NextWchar;
    ULONG Count;

    ULONG DotCount = 0;
    BOOLEAN LastCharDot = FALSE;

    PAGED_CODE();

    //
    //  Check inputs.
    //

    ASSERT_IRP_CONTEXT( IrpContext );

    //
    //  The length must be less than 24 bytes.
    //

    ASSERT( FileName.Length != 0 );
    if (FileName.Length > BYTE_COUNT_8_DOT_3) {

        return FALSE;
    }

    //
    //  Walk though and check for a space character.
    //

    NextWchar = FileName.Buffer;
    Count = 0;

    do {

        //
        //  No spaces allowed.
        //

        if (*NextWchar == L' ') { return FALSE; }

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

            //
            //  Not an 8.3 name if more than 1 dot or more than 8 characters
            //  remaining.  (It is legal for the dot to be in the ninth
            //  position)
            //

            if ((DotCount > 0) ||
                (Count > 8 * sizeof( WCHAR ))) {

                return FALSE;
            }

            DotCount += 1;
            LastCharDot = TRUE;

        } else {

            LastCharDot = FALSE;
        }

        Count += 2;
        NextWchar += 1;

    } while (Count < FileName.Length);

    //
    //  We can't have a period at the end of the name.
    //

    if (LastCharDot) {

        return FALSE;
    }

    //
    //  Create an Oem name to use to check for a valid short name.
    //

    DbcsName.MaximumLength = BYTE_COUNT_8_DOT_3;
    DbcsName.Buffer = DbcsNameBuffer;

    if (!NT_SUCCESS( RtlUnicodeStringToCountedOemString( &DbcsName,
                                                         &FileName,
                                                         FALSE ))) {

        return FALSE;
    }

    //
    //  We have now initialized the Oem string.  Call the FsRtl package to check for a
    //  valid FAT name.
    //

    return FsRtlIsFatDbcsLegal( DbcsName, FALSE, FALSE, FALSE );
}


BOOLEAN
UdfCandidateShortName (
    IN PIRP_CONTEXT IrpContext,
    IN PUNICODE_STRING Name
    )

/*++

Routine Description:

    This routine is called to determine if the input name could be a generated
    short name.

Arguments:

    Name - Pointer to the name to stare at.

Return Value:

    BOOLEAN True if it is possible that this is a shortname, False otherwise.

--*/

{
    ULONG Index, SubIndex;
    BOOLEAN LooksShort = FALSE;
    
    PAGED_CODE();

    //
    //  Check inputs.
    //

    ASSERT_IRP_CONTEXT( IrpContext );

    //
    //  The length can't be larger than an 8.3 name and must be
    //  at least as big as the uniqifier stamp.
    //

    ASSERT( Name->Length != 0 );
    
    if (Name->Length > BYTE_COUNT_8_DOT_3 ||
        Name->Length < DOS_CRC_LEN * sizeof(WCHAR)) {

        return FALSE;
    }
    
    //
    //  Walk across the name looking for the uniquifier stamp.  The stamp
    //  is of the form #<hex><hex><hex> so if we can stop before the end
    //  of the full name.
    //
    
    for ( Index = 0;
          Index <= (Name->Length / sizeof(WCHAR)) - DOS_CRC_LEN;
          Index++ ) {

        //
        //  Is the current character the stamp UDF uses to offset the stamp?
        //
        
        if (Name->Buffer[Index] == CRC_MARK) {
        
            //
            //  We may potentially have just a CRC at the end
            //  of the name OR have a period following.  If we
            //  do, it is reasonable to think the name may be
            //  a generated shorty.
            //
            //  #123 (a very special case - orignal name was ".")
            //  FOO#123
            //  FOO#123.TXT
            //
            
            if (Index == (Name->Length / sizeof(WCHAR)) - DOS_CRC_LEN ||
                Name->Buffer[Index + DOS_CRC_LEN] == PERIOD) {

                LooksShort = TRUE;
                break;
            }
        }
    }

    return LooksShort;
}


VOID
UdfGenerate8dot3Name (
    IN PIRP_CONTEXT IrpContext,
    IN PUNICODE_STRING FileName,
    OUT PUNICODE_STRING ShortFileName
    )

/*++

Routine Description:

    This routine is called to generate a short name from the given long name.  We will
    generate a short name from the given long name.

    The short form is to convert all runs of illegal characters to "_" and tack
    on a base41 representation of the CRC of the original name.  The algorithm is
    nearly directly lifted from the UDF (2.01 proposed!) standard, so apologies for the
    style clash.
    
Arguments:

    FileName - String of bytes containing the name.

    ShortFileName - Pointer to the string to store the short name into.
        
Return Value:

    None.

--*/

{
    INT16 index;
    INT16 targetIndex;
    INT16 crcIndex;
    INT16 extLen;
    INT16 nameLen;
    INT16 charLen;
    INT16 overlayBytes;
    INT16 bytesLeft;
    UNICODE_CHAR current;
    BOOLEAN needsCRC;
    UNICODE_CHAR ext[DOS_EXT_LEN];

    //
    //  So as to lift as directly as possible from the standard, chunk things around.
    //
 
    PWCHAR dosName = ShortFileName->Buffer;
    PWCHAR udfName = FileName->Buffer;
    LONG udfNameLen = FileName->Length / sizeof(WCHAR);
    
    needsCRC = FALSE;

    /* Start at the end of the UDF file name and scan for a period */
    /* ('.').  This will be where the DOS extension starts (if     */
    /* any).                                                       */
    index = udfNameLen;
    while (index-- > 0) {
        if (udfName[index] == PERIOD)
            break;
    }

    if (index < 0) {
        /* There name was scanned to the beginning of the buffer   */

⌨️ 快捷键说明

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