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

📄 dirsup.c

📁 windows 2000中的UDF文件系统的驱动程序.只有读的功能,不支持未关闭的盘片.只支持UDF2.0以下版本,不支持VAT格式的UDF.
💻 C
📖 第 1 页 / 共 3 页
字号:
        //  It doesn't hurt to be pedantic about initialization, so do it all.
        //
        
        DirContext->PureObjectName.Length =
        DirContext->CaseObjectName.Length =
        DirContext->ObjectName.Length = UdfUnicodeDirectoryNames[SELF_ENTRY].Length;
        
        DirContext->PureObjectName.MaximumLength =
        DirContext->CaseObjectName.MaximumLength =
        DirContext->ObjectName.MaximumLength = UdfUnicodeDirectoryNames[SELF_ENTRY].MaximumLength;

        DirContext->PureObjectName.Buffer = 
        DirContext->CaseObjectName.Buffer = 
        DirContext->ObjectName.Buffer = UdfUnicodeDirectoryNames[SELF_ENTRY].Buffer;

        //
        //  All done.
        //

        DebugTrace((  0, Dbg, "Self Entry case\n" ));
        DebugTrace(( -1, Dbg, "UdfUpdateDirNames -> VOID\n" ));
        
        return;
    }
    
    //
    //  Handle the case of the parent directory entry.
    //

    if (FlagOn( DirContext->Fid->Flags, NSR_FID_F_PARENT )) {

        //
        //  Parent entries must occur at the front of the directory and
        //  have a fid length of zero (13346 4/14.4.4).
        //

        if (FlagOn( DirContext->Flags, DIR_CONTEXT_FLAG_SEEN_NONCONSTANT ) ||
            DirContext->Fid->FileIDLen != 0) {

            UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
        }

        //
        //  Note that we have seen the parent entry.
        //

        SetFlag( DirContext->Flags, DIR_CONTEXT_FLAG_SEEN_PARENT );
        
        //
        //  It doesn't hurt to be pedantic about initialization, so do it all.
        //
        
        DirContext->PureObjectName.Length =
        DirContext->CaseObjectName.Length =
        DirContext->ObjectName.Length = UdfUnicodeDirectoryNames[PARENT_ENTRY].Length;
        
        DirContext->PureObjectName.MaximumLength =
        DirContext->CaseObjectName.MaximumLength =
        DirContext->ObjectName.MaximumLength = UdfUnicodeDirectoryNames[PARENT_ENTRY].MaximumLength;

        DirContext->PureObjectName.Buffer = 
        DirContext->CaseObjectName.Buffer = 
        DirContext->ObjectName.Buffer = UdfUnicodeDirectoryNames[PARENT_ENTRY].Buffer;

        //
        //  All done.
        //

        DebugTrace((  0, Dbg, "Parent Entry case\n" ));
        DebugTrace(( -1, Dbg, "UdfUpdateDirNames -> VOID\n" ));
        
        return;
    }

    //
    //  We now know that we will need to convert the name in a real FID, so figure out where
    //  it sits in the descriptor.
    //
    
    NameDstring = Add2Ptr( DirContext->Fid, ISONsrFidConstantSize + DirContext->Fid->ImpUseLen, PUCHAR );
     
    //
    //  Every directory must record a parent entry.
    //
    
    if (!FlagOn( DirContext->Flags, DIR_CONTEXT_FLAG_SEEN_PARENT)) {
    
        UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
    }
    
    //
    //  Note that we are proceeding into the non-constant portion of a directory.
    //
    
    SetFlag( DirContext->Flags, DIR_CONTEXT_FLAG_SEEN_NONCONSTANT );
    
    //
    //  Make sure the dstring is good CS0
    //
    
    UdfCheckLegalCS0Dstring( IrpContext,
                             NameDstring,
                             DirContext->Fid->FileIDLen,
                             0,
                             FALSE );
    
    //
    //  Don't bother allocating tiny buffers - always make sure we get enough for an 8.3 name.
    //

    BufferLength =
    NameLength = Max( BYTE_COUNT_8_DOT_3, UdfCS0DstringUnicodeSize( IrpContext,
                                                                    NameDstring,
                                                                    DirContext->Fid->FileIDLen) );

    //
    //  Illegality is both actual illegal characters and too many characters.
    //
    
    ContainsIllegal = (!UdfCS0DstringContainsLegalCharacters( NameDstring, DirContext->Fid->FileIDLen ) ||
                       (NameLength / sizeof( WCHAR )) > MAX_LEN);

    
    //
    //  If we're illegal, we will need more characters to hold the uniqifying stamp.
    //
    
    if (ContainsIllegal) {

        BufferLength = (NameLength += (CRC_LEN * sizeof(WCHAR)));
    }
    
    
    //
    //  If we need to build a case insensitive name, need more space.
    //
        
    if (IgnoreCase) {

        BufferLength += NameLength;
    }
    
    //
    //  If we need to render the names due to illegal characters, more space again.
    //
        
    if (ContainsIllegal) {

        BufferLength += NameLength;
    
    } else {

        //
        //  Make sure the names aren't seperated. If more illegal names are found we can
        //  resplit the buffer but until then avoid the expense of having to copy bytes
        //  ... odds are that illegal characters are going to be a rarish occurance.
        //
        
        DirContext->PureObjectName.Buffer = DirContext->ObjectName.Buffer;
    }

    DebugTrace(( 0, Dbg,
                 "Ob %s%sneeds %d bytes (%d byte chunks), have %d\n",
                 (IgnoreCase? "Ic " : ""),
                 (ContainsIllegal? "Ci " : ""),
                 BufferLength,
                 NameLength,
                 DirContext->AllocLength ));

    //
    //  Check if we need more space for the names.  We will need more if the name size is greater
    //  than the maximum we can currently store, or if we have stumbled across illegal characters
    //  and the current Pure name is not seperated from the exposed Object name.
    //
    //  Note that IgnoreCase remains constant across usage of a context so we don't have to wonder
    //  if it has been seperated from the ObjectName - it'll always be correct.
    //
    
    if ((NameLength > DirContext->ObjectName.MaximumLength) ||
        (ContainsIllegal && DirContext->ObjectName.Buffer == DirContext->PureObjectName.Buffer)) {

        DebugTrace(( 0, Dbg, "Resizing buffers\n" ));
        
        //
        //  For some reason the sizing is not good for the current name we have to unroll.  Figure
        //  out if we can break up the current allocation in a different way before falling back
        //  to a new allocation.
        //

        if (DirContext->AllocLength >= BufferLength) {

            //
            //  So we can still use the current allocation.  Chop it up into the required number
            //  of chunks.
            //

            DirContext->PureObjectName.MaximumLength =
            DirContext->CaseObjectName.MaximumLength =
            DirContext->ObjectName.MaximumLength = DirContext->AllocLength / (1 +
                                                                              (IgnoreCase? 1 : 0) +
                                                                              (ContainsIllegal? 1 : 0));

            DebugTrace(( 0, Dbg, 
                         "... by resplit into %d byte chunks\n",
                         DirContext->ObjectName.MaximumLength ));
            
            //
            //  Set the buffer pointers up.  Required adjustment will occur below.
            //
                
            DirContext->PureObjectName.Buffer = 
            DirContext->CaseObjectName.Buffer = 
            DirContext->ObjectName.Buffer = DirContext->NameBuffer;
        
        } else {

            DebugTrace(( 0, Dbg, "... by allocating new pool\n" ));
            
            //
            //  Oh well, no choice but to fall back into the pool.  Drop our previous hunk.
            //
            
            UdfFreePool( &DirContext->NameBuffer );
            DirContext->AllocLength = 0;
            
            //
            //  The names share an allocation for efficiency.
            //
            
            DirContext->PureObjectName.MaximumLength =
            DirContext->CaseObjectName.MaximumLength =
            DirContext->ObjectName.MaximumLength = NameLength;
    
            DirContext->NameBuffer =
            DirContext->PureObjectName.Buffer = 
            DirContext->CaseObjectName.Buffer = 
            DirContext->ObjectName.Buffer = FsRtlAllocatePoolWithTag( UdfPagedPool,
                                                                      BufferLength,
                                                                      TAG_FILE_NAME );

            DirContext->AllocLength = BufferLength;
        }
        
        //
        //  In the presence of the "as appropriate" names, adjust the buffer locations.  Note
        //  that ObjectName.Buffer is always the base of the allocated space.
        //
        
        if (IgnoreCase) {

            DirContext->CaseObjectName.Buffer = Add2Ptr( DirContext->ObjectName.Buffer, 
                                                         DirContext->ObjectName.MaximumLength,
                                                         PWCHAR );
        }

        if (ContainsIllegal) {
            
            DirContext->PureObjectName.Buffer = Add2Ptr( DirContext->CaseObjectName.Buffer,
                                                         DirContext->CaseObjectName.MaximumLength,
                                                         PWCHAR );
        }
    }

    ASSERT( BufferLength <= DirContext->AllocLength );

    //
    //  Convert the dstring.
    //
    
    UdfConvertCS0DstringToUnicode( IrpContext,
                                   NameDstring,
                                   DirContext->Fid->FileIDLen,
                                   0,
                                   &DirContext->PureObjectName );

    //
    //  If illegal characters were present, run the name through the UDF transmogrifier.
    //

    if (ContainsIllegal) {

        UdfRenderNameToLegalUnicode( IrpContext,
                                     &DirContext->PureObjectName,
                                     &DirContext->ObjectName );

    //
    //  The ObjectName is the same as the PureObjectName.
    //

    } else {

        DirContext->ObjectName.Length = DirContext->PureObjectName.Length;
    }

    //
    //  Upcase the result if required.
    //

    if (IgnoreCase) {

        UdfUpcaseName( IrpContext,
                       &DirContext->ObjectName,
                       &DirContext->CaseObjectName );
    }

    DebugTrace(( -1, Dbg, "UdfUpdateDirNames -> VOID\n" ));
    
    return;
}


BOOLEAN
UdfFindDirEntry (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb,
    IN PUNICODE_STRING Name,
    IN BOOLEAN IgnoreCase,
    IN BOOLEAN ShortName,
    IN PDIR_ENUM_CONTEXT DirContext
    )

/*++

Routine Description:

    This routine walks the directory specified for an entry which matches the input
    criteria.

Arguments:

    Fcb - the directory to search
    
    Name - name to search for
    
    IgnoreCase - whether this search should be case-insensitive (Name will already
        be upcased)
        
    ShortName - whether the name should be searched for according to short name rules
    
    DirContext - context structure to use and return results in

Return Value:

    BOOLEAN True if a matching directory entry is being returned, False otherwise.

--*/

{
    PUNICODE_STRING MatchName;

    PAGED_CODE();

    //
    //  Check inputs.
    //

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_FCB_INDEX( Fcb );

    DebugTrace(( +1, Dbg,
                 "UdfFindDirEntry, Fcb=%08x Name=\"%wZ\" Ignore=%u Short=%u, DC=%08x\n",
                 Fcb,
                 Name,
                 IgnoreCase,
                 ShortName,
                 DirContext ));

    //
    //  Depending on the kind of search we are performing a different flavor of the found name
    //  wil be used in the comparison.
    //
    
    if (ShortName) {

        MatchName = &DirContext->ShortObjectName;
    
    } else {

        MatchName = &DirContext->CaseObjectName;
    }


    //
    //  Go get the first entry.
    //

    UdfLookupInitialDirEntry( IrpContext,
                              Fcb,
                              DirContext,
                              NULL );

    //
    //  Now loop looking for a good match.
    //
    
    do {

        //
        //  If it is deleted, we obviously aren't interested in it.
        //
        
        if (FlagOn( DirContext->Fid->Flags, NSR_FID_F_DELETED )) {

            continue;
        }

        UdfUpdateDirNames( IrpContext,
                           DirContext,
                           IgnoreCase );
            
        
        //
        //  If this is a constant entry, just keep going.

⌨️ 快捷键说明

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