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

📄 dirsup.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 5 页
字号:
                ((*Dirent)->Attributes == FAT_DIRENT_ATTR_LFN)) {

                PLFN_DIRENT Lfn;

                Lfn = (PLFN_DIRENT)*Dirent;

                if (LfnInProgress) {

                    //
                    //  Check for a proper continuation of the Lfn in progress.
                    //

                    if ((Lfn->Ordinal & FAT_LAST_LONG_ENTRY) ||
                        (Lfn->Ordinal == 0) ||
                        (Lfn->Ordinal != Ordinal - 1) ||
                        (Lfn->Checksum != LfnChecksum) ||
                        (Lfn->MustBeZero != 0)) {

                        //
                        //  The Lfn is not proper, stop constructing it.
                        //

                        LfnInProgress = FALSE;

                    } else {

                        ASSERT( ((LfnIndex % 13) == 0) && LfnIndex );

                        LfnIndex -= 13;

                        RtlCopyMemory( &LongFileName->Buffer[LfnIndex+0],
                                       &Lfn->Name1[0],
                                       5*sizeof(WCHAR) );

                        RtlCopyMemory( &LongFileName->Buffer[LfnIndex+5],
                                       &Lfn->Name2[0],
                                       6 * sizeof(WCHAR) );

                        RtlCopyMemory( &LongFileName->Buffer[LfnIndex+11],
                                       &Lfn->Name3[0],
                                       2 * sizeof(WCHAR) );

                        Ordinal = Lfn->Ordinal;
                        LfnByteOffset = *ByteOffset;
                    }
                }

                //
                //  Now check (maybe again) if we should analyze this entry
                //  for a possible last entry.
                //

                if ((!LfnInProgress) &&
                    (Lfn->Ordinal & FAT_LAST_LONG_ENTRY) &&
                    ((Lfn->Ordinal & ~FAT_LAST_LONG_ENTRY) <= MAX_LFN_DIRENTS) &&
                    (Lfn->MustBeZero == 0)) {

                    BOOLEAN CheckTail = FALSE;

                    Ordinal = Lfn->Ordinal & ~FAT_LAST_LONG_ENTRY;

                    //
                    //  We're usually permissive (following the lead of Win9x) when we find
                    //  malformation of the LFN dirent pile.  I'm not sure this is a good idea,
                    //  so I'm going to trigger corruption on this particularly ugly one.  Perhaps
                    //  we should come back and redo the original code here with this in mind in the
                    //  future.
                    //

                    if (Ordinal == 0) {

                        //
                        //  First LFN in the pile was zero marked as the last. This is never
                        //  possible since oridinals are 1-based.
                        //

                        FatPopUpFileCorrupt( IrpContext, ParentDirectory );
                        FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
                    }

                    LfnIndex = (Ordinal - 1) * 13;

                    FatEnsureStringBufferEnough( LongFileName, 
                                                 (USHORT)((LfnIndex + 13) << 1));

                    RtlCopyMemory( &LongFileName->Buffer[LfnIndex+0],
                                   &Lfn->Name1[0],
                                   5*sizeof(WCHAR));

                    RtlCopyMemory( &LongFileName->Buffer[LfnIndex+5],
                                   &Lfn->Name2[0],
                                   6 * sizeof(WCHAR) );

                    RtlCopyMemory( &LongFileName->Buffer[LfnIndex+11],
                                   &Lfn->Name3[0],
                                   2 * sizeof(WCHAR) );

                    //
                    //  Now compute the Lfn size and make sure that the tail
                    //  bytes are correct.
                    //

                    while (LfnIndex != (ULONG)Ordinal * 13) {

                        if (!CheckTail) {

                            if (LongFileName->Buffer[LfnIndex] == 0x0000) {

                                LfnSize = LfnIndex;
                                CheckTail = TRUE;
                            }

                        } else {

                            if (LongFileName->Buffer[LfnIndex] != 0xffff) {

                                break;
                            }
                        }

                        LfnIndex += 1;
                    }

                    //
                    //  If we exited this loop prematurely, the LFN is not valid.
                    //

                    if (LfnIndex == (ULONG)Ordinal * 13) {

                        //
                        //  If we didn't find the NULL terminator, then the size
                        //  is LfnIndex.
                        //

                        if (!CheckTail) {

                            LfnSize = LfnIndex;
                        }

                        LfnIndex -= 13;
                        LfnInProgress = TRUE;
                        LfnChecksum = Lfn->Checksum;
                        LfnByteOffset = *ByteOffset;
                    }
                }

                //
                //  Move on to the next dirent.
                //

                goto GetNextDirent;
            }

            //
            //  If this is the volume label, skip.  Note that we never arrive here
            //  while building the LFN.  If we did, we weren't asked to find LFNs
            //  and that is another good reason to skip this LFN fragment.
            //

            if (FlagOn((*Dirent)->Attributes, FAT_DIRENT_ATTR_VOLUME_ID)) {

                //
                //  If we actually were asked to hand back volume labels,
                //  do it.
                //
                
                if (FlagOn(Ccb->Flags, CCB_FLAG_MATCH_VOLUME_ID)) {

                    break;
                }

                goto GetNextDirent;
            }

            //
            //  We may have just stepped off a valid Lfn run.  Check to see if
            //  it is indeed valid for the following dirent.
            //

            if (LfnInProgress &&
                (*ByteOffset == LfnByteOffset + sizeof(DIRENT)) &&
                (LfnIndex == 0) &&
                (FatComputeLfnChecksum(*Dirent) == LfnChecksum)) {

                ASSERT( Ordinal == 1);

                FoundValidLfn = TRUE;
                LongFileName->Length = (USHORT)(LfnSize * sizeof(WCHAR));

            } else {

                FoundValidLfn = FALSE;
            }

            //
            //  If we are supposed to match all entries, then match this entry.
            //

            if (FlagOn(Ccb->Flags, CCB_FLAG_MATCH_ALL)) {

                break;
            }

            //
            //  Check against the short name given if one was.
            //

            if (!FlagOn( Ccb->Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE )) {

                if (Ccb->ContainsWildCards) {

                    //
                    //  If we get one, note that all out parameters are already set.
                    //

                    (VOID)Fat8dot3ToString( IrpContext, (*Dirent), FALSE, &Name );

                    //
                    //  For fat we special case the ".." dirent because we want it to
                    //  match ????????.??? and to do that we change ".." to "." before
                    //  calling the Fsrtl routine.  But only do this if the expression
                    //  is greater than one character long.
                    //

                    if ((Name.Length == 2) &&
                        (Name.Buffer[0] == '.') &&
                        (Name.Buffer[1] == '.') &&
                        (Ccb->OemQueryTemplate.Wild.Length > 1)) {

                        Name.Length = 1;
                    }

                    if (FatIsNameInExpression( IrpContext,
                                               Ccb->OemQueryTemplate.Wild,
                                               Name)) {

                        DebugTrace( 0, Dbg, "Entry found: Name = \"%Z\"\n", &Name);
                        DebugTrace( 0, Dbg, "             VBO  = %08lx\n", *ByteOffset);

                        if (FileNameDos) {

                            *FileNameDos = TRUE;
                        }

                        break;
                    }

                } else {

                    //
                    //  Do the quickest 8.3 equivalency check possible
                    //

                    if (!FlagOn((*Dirent)->Attributes, FAT_DIRENT_ATTR_VOLUME_ID) &&
                        (*(PULONG)&(Ccb->OemQueryTemplate.Constant[0]) == *(PULONG)&((*Dirent)->FileName[0])) &&
                        (*(PULONG)&(Ccb->OemQueryTemplate.Constant[4]) == *(PULONG)&((*Dirent)->FileName[4])) &&
                        (*(PUSHORT)&(Ccb->OemQueryTemplate.Constant[8]) == *(PUSHORT)&((*Dirent)->FileName[8])) &&
                        (*(PUCHAR)&(Ccb->OemQueryTemplate.Constant[10]) == *(PUCHAR)&((*Dirent)->FileName[10]))) {

                        DebugTrace( 0, Dbg, "Entry found.\n", 0);

                        if (FileNameDos) {

                            *FileNameDos = TRUE;
                        }

                        break;
                    }
                }
            }

            //
            //  No matches were found with the short name.  If an LFN exists,
            //  use it for the search.
            //

            if (FoundValidLfn) {

                //
                //  First do a quick check here for different sized constant
                //  name and expression before upcasing.
                //

                if (!Ccb->ContainsWildCards &&
                    Ccb->UnicodeQueryTemplate.Length != (USHORT)(LfnSize * sizeof(WCHAR))) {

                    //
                    //  Move on to the next dirent.
                    //

                    FoundValidLfn = FALSE;
                    LongFileName->Length = 0;

                    goto GetNextDirent;
                }

                //
                //  We need to upcase the name we found.
                //  We need a buffer.  Try to avoid doing an allocation.
                //

                FatEnsureStringBufferEnough( &UpcasedLfn, 
                                             LongFileName->Length);

                Status = RtlUpcaseUnicodeString( &UpcasedLfn,
                                                 LongFileName,
                                                 FALSE );

                if (!NT_SUCCESS(Status)) {

                    FatNormalizeAndRaiseStatus( IrpContext, Status );
                }

                //
                //  Do the compare
                //

                if (Ccb->ContainsWildCards) {

                    if (FsRtlIsNameInExpression( &Ccb->UnicodeQueryTemplate,
                                                 &UpcasedLfn,
                                                 TRUE,
                                                 NULL )) {

                        break;
                    }

                } else {

                    if (FsRtlAreNamesEqual( &Ccb->UnicodeQueryTemplate,
                                            &UpcasedLfn,
                                            BooleanFlagOn( Ccb->Flags, CCB_FLAG_QUERY_TEMPLATE_MIXED ),
                                            NULL )) {

                        break;
                    }
                }
            }

            //
            //  This long name was not a match.  Zero out the Length field.
            //

            if (FoundValidLfn) {

                FoundValidLfn = FALSE;
                LongFileName->Length = 0;
            }

GetNextDirent:

            //
            //  Move on to the next dirent.
            //

            *ByteOffset += sizeof(DIRENT);
            *Dirent += 1;
        }

    } finally {

        FatFreeStringBuffer( &UpcasedLfn);
    }

    DebugTrace(-1, Dbg, "FatLocateDirent -> (VOID)\n", 0);

    TimerStop(Dbg,"FatLocateDirent");

    return;
}


VOID
FatLocateSimpleOemDirent (
    IN PIRP_CONTEXT IrpContext,
    IN PDCB ParentDirectory,
    IN POEM_STRING FileName,
    OUT PDIRENT *Dirent,
    OUT PBCB *Bcb,
    OUT PVBO ByteOffset
    )

/*++

Routine Description:

    This routine locates on the disk an undelted simple Oem dirent.  By simple
    I mean that FileName cannot contain any extended characters, and we do
    not search LFNs or return them.

Arguments:

    ParentDirectory - Supplies the DCB for the directory in which
        to search

    FileName - Supplies the filename to search for.  The name may contain
        wild cards

    OffsetToStartSearchFrom - Supplies the VBO within the parent directory
        from which to start looking for another real dirent.

    Dirent - Receives a pointer to the located dirent if one was found
        or NULL otherwise.

    Bcb - Receives the Bcb for the located dirent if one was found or
        NULL otherwise.

    ByteOffset - Receives the VBO within the Parent directory for
        the located dirent if one was found, or 0 otherwise.

Return Value:

    None.

--*/

{
    CCB LocalCcb;

    PAGED_CODE();

    //
    //  Note, this routine is called rarely, so performance is not critical.
    //  Just fill in a Ccb structure on my stack with the values that are
    //  required.
    //

⌨️ 快捷键说明

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