📄 dirctrl.c
字号:
//
// Now we have an entry to return to our caller. We'll convert
// the name from the form in the dirent to a <name>.<ext> form.
// We'll case on the type of information requested and fill up
// the user buffer if everything fits.
//
Fat8dot3ToString( IrpContext, Dirent, TRUE, &Fat8Dot3String );
//
// Determine the UNICODE length of the file name.
//
FileNameLength = RtlOemStringToCountedUnicodeSize(&Fat8Dot3String);
//
// Here are the rules concerning filling up the buffer:
//
// 1. The Io system garentees that there will always be
// enough room for at least one base record.
//
// 2. If the full first record (including file name) cannot
// fit, as much of the name as possible is copied and
// STATUS_BUFFER_OVERFLOW is returned.
//
// 3. If a subsequent record cannot completely fit into the
// buffer, none of it (as in 0 bytes) is copied, and
// STATUS_SUCCESS is returned. A subsequent query will
// pick up with this record.
//
BytesRemainingInBuffer = UserBufferLength - NextEntry;
if ( (NextEntry != 0) &&
( (BaseLength + FileNameLength > BytesRemainingInBuffer) ||
(UserBufferLength < NextEntry) ) ) {
DebugTrace(0, Dbg, "Next entry won't fit\n", 0);
try_return( Status = STATUS_SUCCESS );
}
ASSERT( BytesRemainingInBuffer >= BaseLength );
//
// Zero the base part of the structure.
//
RtlZeroMemory( &Buffer[NextEntry], BaseLength );
switch ( FileInformationClass ) {
//
// Now fill the base parts of the strucure that are applicable.
//
case FileBothDirectoryInformation:
case FileFullDirectoryInformation:
case FileIdBothDirectoryInformation:
case FileIdFullDirectoryInformation:
DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file full directory information\n", 0);
//
// Get the Ea file length.
//
FullDirInfo = (PFILE_FULL_DIR_INFORMATION)&Buffer[NextEntry];
//
// If the EAs are corrupt, ignore the error. We don't want
// to abort the directory query.
//
try {
FatGetEaLength( IrpContext,
Vcb,
Dirent,
&FullDirInfo->EaSize );
} except(EXCEPTION_EXECUTE_HANDLER) {
FatResetExceptionState( IrpContext );
FullDirInfo->EaSize = 0;
}
case FileDirectoryInformation:
DirInfo = (PFILE_DIRECTORY_INFORMATION)&Buffer[NextEntry];
FatGetDirTimes( IrpContext, Dirent, DirInfo );
DirInfo->EndOfFile.QuadPart = Dirent->FileSize;
if (!FlagOn( Dirent->Attributes, FAT_DIRENT_ATTR_DIRECTORY )) {
DirInfo->AllocationSize.QuadPart =
(((Dirent->FileSize + DiskAllocSize - 1) / DiskAllocSize) *
DiskAllocSize );
}
DirInfo->FileAttributes = Dirent->Attributes != 0 ?
Dirent->Attributes :
FILE_ATTRIBUTE_NORMAL;
DirInfo->FileIndex = NextVbo;
DirInfo->FileNameLength = FileNameLength;
DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String);
break;
case FileNamesInformation:
DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file names information\n", 0);
NamesInfo = (PFILE_NAMES_INFORMATION)&Buffer[NextEntry];
NamesInfo->FileIndex = NextVbo;
NamesInfo->FileNameLength = FileNameLength;
DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String );
break;
default:
FatBugCheck( FileInformationClass, 0, 0 );
}
BytesConverted = 0;
Status = RtlOemToUnicodeN( (PWCH)&Buffer[NextEntry + BaseLength],
BytesRemainingInBuffer - BaseLength,
&BytesConverted,
Fat8Dot3String.Buffer,
Fat8Dot3String.Length );
//
// Check for the case that a single entry doesn't fit.
// This should only get this far on the first entry
//
if (BytesConverted < FileNameLength) {
ASSERT( NextEntry == 0 );
Status = STATUS_BUFFER_OVERFLOW;
}
//
// Set up the previous next entry offset
//
*((PULONG)(&Buffer[LastEntry])) = NextEntry - LastEntry;
//
// And indicate how much of the user buffer we have currently
// used up. We must compute this value before we long align
// ourselves for the next entry
//
Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information ) +
BaseLength + BytesConverted;
//
// If something happened with the conversion, bail here.
//
if ( !NT_SUCCESS( Status ) ) {
try_return( NOTHING );
}
} else {
ULONG ShortNameLength;
FileNameLength = LongFileName.Length;
//
// Here are the rules concerning filling up the buffer:
//
// 1. The Io system garentees that there will always be
// enough room for at least one base record.
//
// 2. If the full first record (including file name) cannot
// fit, as much of the name as possible is copied and
// STATUS_BUFFER_OVERFLOW is returned.
//
// 3. If a subsequent record cannot completely fit into the
// buffer, none of it (as in 0 bytes) is copied, and
// STATUS_SUCCESS is returned. A subsequent query will
// pick up with this record.
//
BytesRemainingInBuffer = UserBufferLength - NextEntry;
if ( (NextEntry != 0) &&
( (BaseLength + FileNameLength > BytesRemainingInBuffer) ||
(UserBufferLength < NextEntry) ) ) {
DebugTrace(0, Dbg, "Next entry won't fit\n", 0);
try_return( Status = STATUS_SUCCESS );
}
ASSERT( BytesRemainingInBuffer >= BaseLength );
//
// Zero the base part of the structure.
//
RtlZeroMemory( &Buffer[NextEntry], BaseLength );
switch ( FileInformationClass ) {
//
// Now fill the base parts of the strucure that are applicable.
//
case FileBothDirectoryInformation:
case FileIdBothDirectoryInformation:
BothDirInfo = (PFILE_BOTH_DIR_INFORMATION)&Buffer[NextEntry];
//
// Now we have an entry to return to our caller. We'll convert
// the name from the form in the dirent to a <name>.<ext> form.
// We'll case on the type of information requested and fill up
// the user buffer if everything fits.
//
Fat8dot3ToString( IrpContext, Dirent, FALSE, &Fat8Dot3String );
ASSERT( Fat8Dot3String.Length <= 12 );
Status = RtlOemToUnicodeN( &BothDirInfo->ShortName[0],
12*sizeof(WCHAR),
&ShortNameLength,
Fat8Dot3String.Buffer,
Fat8Dot3String.Length );
ASSERT( Status != STATUS_BUFFER_OVERFLOW );
ASSERT( ShortNameLength <= 12*sizeof(WCHAR) );
//
// Copy the length into the dirinfo structure. Note
// that the LHS below is a USHORT, so it can not
// be specificed as the OUT parameter above.
//
BothDirInfo->ShortNameLength = (UCHAR)ShortNameLength;
//
// If something happened with the conversion, bail here.
//
if ( !NT_SUCCESS( Status ) ) {
try_return( NOTHING );
}
case FileFullDirectoryInformation:
case FileIdFullDirectoryInformation:
DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file full directory information\n", 0);
//
// Get the Ea file length.
//
FullDirInfo = (PFILE_FULL_DIR_INFORMATION)&Buffer[NextEntry];
//
// If the EAs are corrupt, ignore the error. We don't want
// to abort the directory query.
//
try {
FatGetEaLength( IrpContext,
Vcb,
Dirent,
&FullDirInfo->EaSize );
} except(EXCEPTION_EXECUTE_HANDLER) {
FatResetExceptionState( IrpContext );
FullDirInfo->EaSize = 0;
}
case FileDirectoryInformation:
DirInfo = (PFILE_DIRECTORY_INFORMATION)&Buffer[NextEntry];
FatGetDirTimes( IrpContext, Dirent, DirInfo );
DirInfo->EndOfFile.QuadPart = Dirent->FileSize;
if (!FlagOn( Dirent->Attributes, FAT_DIRENT_ATTR_DIRECTORY )) {
DirInfo->AllocationSize.QuadPart = (
(( Dirent->FileSize
+ DiskAllocSize - 1 )
/ DiskAllocSize )
* DiskAllocSize );
}
DirInfo->FileAttributes = Dirent->Attributes != 0 ?
Dirent->Attributes :
FILE_ATTRIBUTE_NORMAL;
DirInfo->FileIndex = NextVbo;
DirInfo->FileNameLength = FileNameLength;
DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String);
break;
case FileNamesInformation:
DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file names information\n", 0);
NamesInfo = (PFILE_NAMES_INFORMATION)&Buffer[NextEntry];
NamesInfo->FileIndex = NextVbo;
NamesInfo->FileNameLength = FileNameLength;
DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String );
break;
default:
FatBugCheck( FileInformationClass, 0, 0 );
}
BytesConverted = BytesRemainingInBuffer - BaseLength >= FileNameLength ?
FileNameLength :
BytesRemainingInBuffer - BaseLength;
RtlCopyMemory( &Buffer[NextEntry + BaseLength],
&LongFileName.Buffer[0],
BytesConverted );
//
// Set up the previous next entry offset
//
*((PULONG)(&Buffer[LastEntry])) = NextEntry - LastEntry;
//
// And indicate how much of the user buffer we have currently
// used up. We must compute this value before we long align
// ourselves for the next entry
//
Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information ) +
BaseLength + BytesConverted;
//
// Check for the case that a single entry doesn't fit.
// This should only get this far on the first entry.
//
if (BytesConverted < FileNameLength) {
ASSERT( NextEntry == 0 );
try_return( Status = STATUS_BUFFER_OVERFLOW );
}
}
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -