📄 dirctrl.c
字号:
} else {
if (!FatAcquireSharedFcb( IrpContext, Dcb )) {
DebugTrace(0, Dbg, "FatQueryDirectory -> Enqueue to Fsp\n", 0);
Status = FatFsdPostRequest( IrpContext, Irp );
DebugTrace(-1, Dbg, "FatQueryDirectory -> %08lx\n", Status);
return Status;
}
}
try {
ULONG BaseLength;
ULONG BytesConverted;
//
// If we are in the Fsp now because we had to wait earlier,
// we must map the user buffer, otherwise we can use the
// user's buffer directly.
//
Buffer = FatMapUserBuffer( IrpContext, Irp );
//
// Make sure the Dcb is still good.
//
FatVerifyFcb( IrpContext, Dcb );
//
// Determine where to start the scan. Highest priority is given
// to the file index. Lower priority is the restart flag. If
// neither of these is specified, then the Vbo offset field in the
// Ccb is used.
//
if (IndexSpecified) {
CurrentVbo = FileIndex + sizeof( DIRENT );
} else if (RestartScan) {
CurrentVbo = 0;
} else {
CurrentVbo = Ccb->OffsetToStartSearchFrom;
}
//
// If this is the first try then allocate a buffer for the file
// name.
//
if (InitialQuery) {
//
// If either:
//
// - No name was specified
// - An empty name was specified
// - We received a '*'
// - The user specified the DOS equivolent of ????????.???
//
// then match all names.
//
if ((UniArgFileName == NULL) ||
(UniArgFileName->Length == 0) ||
(UniArgFileName->Buffer == NULL) ||
((UniArgFileName->Length == sizeof(WCHAR)) &&
(UniArgFileName->Buffer[0] == L'*')) ||
((UniArgFileName->Length == 12*sizeof(WCHAR)) &&
(RtlEqualMemory( UniArgFileName->Buffer,
Fat8QMdot3QM,
12*sizeof(WCHAR) )))) {
Ccb->ContainsWildCards = TRUE;
SetFlag( Ccb->Flags, CCB_FLAG_MATCH_ALL );
} else {
BOOLEAN ExtendedName = FALSE;
OEM_STRING LocalBestFit;
//
// First and formost, see if the name has wild cards.
//
Ccb->ContainsWildCards =
FsRtlDoesNameContainWildCards( UniArgFileName );
//
// Now check to see if the name contains any extended
// characters
//
for (i=0; i < UniArgFileName->Length / sizeof(WCHAR); i++) {
if (UniArgFileName->Buffer[i] >= 0x80) {
ExtendedName = TRUE;
break;
}
}
//
// OK, now do the conversions we need.
//
if (ExtendedName) {
Status = RtlUpcaseUnicodeString( &Ccb->UnicodeQueryTemplate,
UniArgFileName,
TRUE );
if (!NT_SUCCESS(Status)) {
try_return( Status );
}
SetFlag( Ccb->Flags, CCB_FLAG_FREE_UNICODE );
//
// Upcase the name and convert it to the Oem code page.
//
Status = RtlUpcaseUnicodeStringToCountedOemString( &LocalBestFit,
UniArgFileName,
TRUE );
//
// If this conversion failed for any reason other than
// an unmappable character fail the request.
//
if (!NT_SUCCESS(Status)) {
if (Status == STATUS_UNMAPPABLE_CHARACTER) {
SetFlag( Ccb->Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE );
} else {
try_return( Status );
}
} else {
SetFlag( Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT );
}
} else {
PVOID Buffers;
//
// This case is optimized because I know I only have to
// worry about a-z.
//
Buffers = FsRtlAllocatePoolWithTag( PagedPool,
UniArgFileName->Length +
UniArgFileName->Length / sizeof(WCHAR),
TAG_FILENAME_BUFFER );
Ccb->UnicodeQueryTemplate.Buffer = Buffers;
Ccb->UnicodeQueryTemplate.Length = UniArgFileName->Length;
Ccb->UnicodeQueryTemplate.MaximumLength = UniArgFileName->Length;
LocalBestFit.Buffer = (PUCHAR)Buffers + UniArgFileName->Length;
LocalBestFit.Length = UniArgFileName->Length / sizeof(WCHAR);
LocalBestFit.MaximumLength = LocalBestFit.Length;
SetFlag( Ccb->Flags, CCB_FLAG_FREE_UNICODE );
for (i=0; i < UniArgFileName->Length / sizeof(WCHAR); i++) {
WCHAR c = UniArgFileName->Buffer[i];
LocalBestFit.Buffer[i] = (UCHAR)
(Ccb->UnicodeQueryTemplate.Buffer[i] =
(c < 'a' ? c : c <= 'z' ? c - ('a' - 'A') : c));
}
}
//
// At this point we now have the upcased unicode name,
// and the two Oem names if they could be represented in
// this code page.
//
// Now determine if the Oem names are legal for what we
// going to try and do. Mark them as not usable is they
// are not legal. Note that we can optimize extended names
// since they are actually both the same string.
//
if (!FlagOn( Ccb->Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE ) &&
!FatIsNameShortOemValid( IrpContext,
LocalBestFit,
Ccb->ContainsWildCards,
FALSE,
FALSE )) {
if (ExtendedName) {
RtlFreeOemString( &LocalBestFit );
ClearFlag( Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT );
}
SetFlag( Ccb->Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE );
}
//
// OK, now both locals oem strings correctly reflect their
// usability. Now we want to load up the Ccb structure.
//
// Now we will branch on two paths of wheather the name
// is wild or not.
//
if (!FlagOn( Ccb->Flags, CCB_FLAG_SKIP_SHORT_NAME_COMPARE )) {
if (Ccb->ContainsWildCards) {
Ccb->OemQueryTemplate.Wild = LocalBestFit;
} else {
FatStringTo8dot3( IrpContext,
LocalBestFit,
&Ccb->OemQueryTemplate.Constant );
if (FlagOn(Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT)) {
RtlFreeOemString( &LocalBestFit );
ClearFlag( Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT );
}
}
}
}
//
// We convert to shared access.
//
FatConvertToSharedFcb( IrpContext, Dcb );
}
LastEntry = 0;
NextEntry = 0;
switch (FileInformationClass) {
case FileDirectoryInformation:
BaseLength = FIELD_OFFSET( FILE_DIRECTORY_INFORMATION,
FileName[0] );
break;
case FileFullDirectoryInformation:
BaseLength = FIELD_OFFSET( FILE_FULL_DIR_INFORMATION,
FileName[0] );
break;
case FileIdFullDirectoryInformation:
BaseLength = FIELD_OFFSET( FILE_ID_FULL_DIR_INFORMATION,
FileName[0] );
break;
case FileNamesInformation:
BaseLength = FIELD_OFFSET( FILE_NAMES_INFORMATION,
FileName[0] );
break;
case FileBothDirectoryInformation:
BaseLength = FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION,
FileName[0] );
break;
case FileIdBothDirectoryInformation:
BaseLength = FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION,
FileName[0] );
break;
default:
try_return( Status = STATUS_INVALID_INFO_CLASS );
}
//
// At this point we are about to enter our query loop. We have
// determined the index into the directory file to begin the
// search. LastEntry and NextEntry are used to index into the user
// buffer. LastEntry is the last entry we've added, NextEntry is
// current one we're working on. If NextEntry is non-zero, then
// at least one entry was added.
//
while ( TRUE ) {
VBO NextVbo;
ULONG FileNameLength;
ULONG BytesRemainingInBuffer;
DebugTrace(0, Dbg, "FatQueryDirectory -> Top of loop\n", 0);
//
// If the user had requested only a single match and we have
// returned that, then we stop at this point.
//
if (ReturnSingleEntry && NextEntry != 0) {
try_return( Status );
}
//
// We call FatLocateDirent to lock down the next matching dirent.
//
FatLocateDirent( IrpContext,
Dcb,
Ccb,
CurrentVbo,
&Dirent,
&Bcb,
&NextVbo,
NULL,
&LongFileName);
//
// If we didn't receive a dirent, then we are at the end of the
// directory. If we have returned any files, we exit with
// success, otherwise we return STATUS_NO_MORE_FILES.
//
if (!Dirent) {
DebugTrace(0, Dbg, "FatQueryDirectory -> No dirent\n", 0);
if (NextEntry == 0) {
UpdateCcb = FALSE;
if (InitialQuery) {
Status = STATUS_NO_SUCH_FILE;
} else {
Status = STATUS_NO_MORE_FILES;
}
}
try_return( Status );
}
//
// Protect access to the user buffer with an exception handler.
// Since (at our request) IO doesn't buffer these requests, we have
// to guard against a user messing with the page protection and other
// such trickery.
//
try {
if (LongFileName.Length == 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -