[FASTFAT] Allow partial returns on directory info query for first entry.

This mimics what MS FastFAT does and fixes (a bit) ntdll_winetest:directory.
It still crashes, but go farther.

CORE-13367
This commit is contained in:
Pierre Schweitzer 2017-12-09 10:58:19 +01:00
parent e15874b491
commit 52f0726817
No known key found for this signature in database
GPG key ID: 7545556C3D585B0B

View file

@ -91,20 +91,43 @@ NTSTATUS
VfatGetFileNameInformation( VfatGetFileNameInformation(
PVFAT_DIRENTRY_CONTEXT DirContext, PVFAT_DIRENTRY_CONTEXT DirContext,
PFILE_NAMES_INFORMATION pInfo, PFILE_NAMES_INFORMATION pInfo,
ULONG BufferLength) ULONG BufferLength,
PULONG Written,
BOOLEAN First)
{ {
if ((sizeof(FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength) NTSTATUS Status;
return STATUS_BUFFER_OVERFLOW; ULONG BytesToCopy = 0;
pInfo->FileNameLength = DirContext->LongNameU.Length; *Written = 0;
pInfo->NextEntryOffset = ULONG_ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION) + Status = STATUS_BUFFER_OVERFLOW;
DirContext->LongNameU.Length);
RtlCopyMemory(pInfo->FileName, if (FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName) > BufferLength)
DirContext->LongNameU.Buffer, return Status;
DirContext->LongNameU.Length);
return STATUS_SUCCESS; if (First || (BufferLength >= FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName) + DirContext->LongNameU.Length))
{
pInfo->FileNameLength = DirContext->LongNameU.Length;
*Written = FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName);
pInfo->NextEntryOffset = 0;
if (BufferLength > FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName))
{
BytesToCopy = min(DirContext->LongNameU.Length, BufferLength - FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName));
RtlCopyMemory(pInfo->FileName,
DirContext->LongNameU.Buffer,
BytesToCopy);
*Written += BytesToCopy;
if (BytesToCopy == DirContext->LongNameU.Length)
{
pInfo->NextEntryOffset = ULONG_ROUND_UP(sizeof(FILE_NAMES_INFORMATION) +
BytesToCopy);
Status = STATUS_SUCCESS;
}
}
}
return Status;
} }
static static
@ -113,90 +136,115 @@ VfatGetFileDirectoryInformation(
PVFAT_DIRENTRY_CONTEXT DirContext, PVFAT_DIRENTRY_CONTEXT DirContext,
PDEVICE_EXTENSION DeviceExt, PDEVICE_EXTENSION DeviceExt,
PFILE_DIRECTORY_INFORMATION pInfo, PFILE_DIRECTORY_INFORMATION pInfo,
ULONG BufferLength) ULONG BufferLength,
PULONG Written,
BOOLEAN First)
{ {
if ((sizeof(FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength) NTSTATUS Status;
return STATUS_BUFFER_OVERFLOW; ULONG BytesToCopy = 0;
pInfo->FileNameLength = DirContext->LongNameU.Length; *Written = 0;
pInfo->NextEntryOffset = ULONG_ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION) + Status = STATUS_BUFFER_OVERFLOW;
DirContext->LongNameU.Length);
/* pInfo->FileIndex = ; */
RtlCopyMemory(pInfo->FileName, if (FIELD_OFFSET(FILE_DIRECTORY_INFORMATION, FileName) > BufferLength)
DirContext->LongNameU.Buffer, return Status;
DirContext->LongNameU.Length);
if (vfatVolumeIsFatX(DeviceExt)) if (First || (BufferLength >= FIELD_OFFSET(FILE_DIRECTORY_INFORMATION, FileName) + DirContext->LongNameU.Length))
{ {
FsdDosDateTimeToSystemTime(DeviceExt, pInfo->FileNameLength = DirContext->LongNameU.Length;
DirContext->DirEntry.FatX.CreationDate, /* pInfo->FileIndex = ; */
DirContext->DirEntry.FatX.CreationTime,
&pInfo->CreationTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.FatX.AccessDate,
DirContext->DirEntry.FatX.AccessTime,
&pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.FatX.UpdateDate,
DirContext->DirEntry.FatX.UpdateTime,
&pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime; *Written = FIELD_OFFSET(FILE_DIRECTORY_INFORMATION, FileName);
pInfo->NextEntryOffset = 0;
if (BooleanFlagOn(DirContext->DirEntry.FatX.Attrib, FILE_ATTRIBUTE_DIRECTORY)) if (BufferLength > FIELD_OFFSET(FILE_DIRECTORY_INFORMATION, FileName))
{ {
pInfo->EndOfFile.QuadPart = 0; BytesToCopy = min(DirContext->LongNameU.Length, BufferLength - FIELD_OFFSET(FILE_DIRECTORY_INFORMATION, FileName));
pInfo->AllocationSize.QuadPart = 0; RtlCopyMemory(pInfo->FileName,
DirContext->LongNameU.Buffer,
BytesToCopy);
*Written += BytesToCopy;
if (BytesToCopy == DirContext->LongNameU.Length)
{
pInfo->NextEntryOffset = ULONG_ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION) +
BytesToCopy);
Status = STATUS_SUCCESS;
}
}
if (vfatVolumeIsFatX(DeviceExt))
{
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.FatX.CreationDate,
DirContext->DirEntry.FatX.CreationTime,
&pInfo->CreationTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.FatX.AccessDate,
DirContext->DirEntry.FatX.AccessTime,
&pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.FatX.UpdateDate,
DirContext->DirEntry.FatX.UpdateTime,
&pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime;
if (BooleanFlagOn(DirContext->DirEntry.FatX.Attrib, FILE_ATTRIBUTE_DIRECTORY))
{
pInfo->EndOfFile.QuadPart = 0;
pInfo->AllocationSize.QuadPart = 0;
}
else
{
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.FatX.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.FatX.FileSize,
DeviceExt->FatInfo.BytesPerCluster);
}
pInfo->FileAttributes = DirContext->DirEntry.FatX.Attrib & 0x3f;
} }
else else
{ {
pInfo->EndOfFile.u.HighPart = 0; FsdDosDateTimeToSystemTime(DeviceExt,
pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.FatX.FileSize; DirContext->DirEntry.Fat.CreationDate,
/* Make allocsize a rounded up multiple of BytesPerCluster */ DirContext->DirEntry.Fat.CreationTime,
pInfo->AllocationSize.u.HighPart = 0; &pInfo->CreationTime);
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.FatX.FileSize, FsdDosDateTimeToSystemTime(DeviceExt,
DeviceExt->FatInfo.BytesPerCluster); DirContext->DirEntry.Fat.AccessDate,
0,
&pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.Fat.UpdateDate,
DirContext->DirEntry.Fat.UpdateTime,
&pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime;
if (BooleanFlagOn(DirContext->DirEntry.Fat.Attrib, FILE_ATTRIBUTE_DIRECTORY))
{
pInfo->EndOfFile.QuadPart = 0;
pInfo->AllocationSize.QuadPart = 0;
}
else
{
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.Fat.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.Fat.FileSize,
DeviceExt->FatInfo.BytesPerCluster);
}
pInfo->FileAttributes = DirContext->DirEntry.Fat.Attrib & 0x3f;
} }
pInfo->FileAttributes = DirContext->DirEntry.FatX.Attrib & 0x3f;
}
else
{
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.Fat.CreationDate,
DirContext->DirEntry.Fat.CreationTime,
&pInfo->CreationTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.Fat.AccessDate,
0,
&pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.Fat.UpdateDate,
DirContext->DirEntry.Fat.UpdateTime,
&pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime;
if (BooleanFlagOn(DirContext->DirEntry.Fat.Attrib, FILE_ATTRIBUTE_DIRECTORY))
{
pInfo->EndOfFile.QuadPart = 0;
pInfo->AllocationSize.QuadPart = 0;
}
else
{
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.Fat.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.Fat.FileSize,
DeviceExt->FatInfo.BytesPerCluster);
}
pInfo->FileAttributes = DirContext->DirEntry.Fat.Attrib & 0x3f;
} }
return STATUS_SUCCESS; return Status;
} }
static static
@ -205,71 +253,94 @@ VfatGetFileFullDirectoryInformation(
PVFAT_DIRENTRY_CONTEXT DirContext, PVFAT_DIRENTRY_CONTEXT DirContext,
PDEVICE_EXTENSION DeviceExt, PDEVICE_EXTENSION DeviceExt,
PFILE_FULL_DIR_INFORMATION pInfo, PFILE_FULL_DIR_INFORMATION pInfo,
ULONG BufferLength) ULONG BufferLength,
PULONG Written,
BOOLEAN First)
{ {
if ((sizeof(FILE_FULL_DIR_INFORMATION) + DirContext->LongNameU.Length) > BufferLength) NTSTATUS Status;
return STATUS_BUFFER_OVERFLOW; ULONG BytesToCopy = 0;
pInfo->FileNameLength = DirContext->LongNameU.Length; *Written = 0;
pInfo->NextEntryOffset = ULONG_ROUND_UP(sizeof(FILE_FULL_DIR_INFORMATION) + Status = STATUS_BUFFER_OVERFLOW;
DirContext->LongNameU.Length);
/* pInfo->FileIndex = ; */
/* pInfo->EaSize = ; */
RtlCopyMemory(pInfo->FileName, if (FIELD_OFFSET(FILE_FULL_DIR_INFORMATION, FileName) > BufferLength)
DirContext->LongNameU.Buffer, return Status;
DirContext->LongNameU.Length);
if (vfatVolumeIsFatX(DeviceExt)) if (First || (BufferLength >= FIELD_OFFSET(FILE_FULL_DIR_INFORMATION, FileName) + DirContext->LongNameU.Length))
{ {
FsdDosDateTimeToSystemTime(DeviceExt, pInfo->FileNameLength = DirContext->LongNameU.Length;
DirContext->DirEntry.FatX.CreationDate, /* pInfo->FileIndex = ; */
DirContext->DirEntry.FatX.CreationTime, pInfo->EaSize = 0;
&pInfo->CreationTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.FatX.AccessDate,
DirContext->DirEntry.FatX.AccessTime,
&pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.FatX.UpdateDate,
DirContext->DirEntry.FatX.UpdateTime,
&pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime; *Written = FIELD_OFFSET(FILE_FULL_DIR_INFORMATION, FileName);
pInfo->EndOfFile.u.HighPart = 0; pInfo->NextEntryOffset = 0;
pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.FatX.FileSize; if (BufferLength > FIELD_OFFSET(FILE_FULL_DIR_INFORMATION, FileName))
/* Make allocsize a rounded up multiple of BytesPerCluster */ {
pInfo->AllocationSize.u.HighPart = 0; BytesToCopy = min(DirContext->LongNameU.Length, BufferLength - FIELD_OFFSET(FILE_FULL_DIR_INFORMATION, FileName));
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.FatX.FileSize, RtlCopyMemory(pInfo->FileName,
DeviceExt->FatInfo.BytesPerCluster); DirContext->LongNameU.Buffer,
pInfo->FileAttributes = DirContext->DirEntry.FatX.Attrib & 0x3f; BytesToCopy);
} *Written += BytesToCopy;
else
{
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.Fat.CreationDate,
DirContext->DirEntry.Fat.CreationTime,
&pInfo->CreationTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.Fat.AccessDate,
0,
&pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.Fat.UpdateDate,
DirContext->DirEntry.Fat.UpdateTime,
&pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime; if (BytesToCopy == DirContext->LongNameU.Length)
pInfo->EndOfFile.u.HighPart = 0; {
pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.Fat.FileSize; pInfo->NextEntryOffset = ULONG_ROUND_UP(sizeof(FILE_FULL_DIR_INFORMATION) +
/* Make allocsize a rounded up multiple of BytesPerCluster */ BytesToCopy);
pInfo->AllocationSize.u.HighPart = 0; Status = STATUS_SUCCESS;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.Fat.FileSize, }
DeviceExt->FatInfo.BytesPerCluster); }
pInfo->FileAttributes = DirContext->DirEntry.Fat.Attrib & 0x3f;
if (vfatVolumeIsFatX(DeviceExt))
{
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.FatX.CreationDate,
DirContext->DirEntry.FatX.CreationTime,
&pInfo->CreationTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.FatX.AccessDate,
DirContext->DirEntry.FatX.AccessTime,
&pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.FatX.UpdateDate,
DirContext->DirEntry.FatX.UpdateTime,
&pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime;
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.FatX.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.FatX.FileSize,
DeviceExt->FatInfo.BytesPerCluster);
pInfo->FileAttributes = DirContext->DirEntry.FatX.Attrib & 0x3f;
}
else
{
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.Fat.CreationDate,
DirContext->DirEntry.Fat.CreationTime,
&pInfo->CreationTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.Fat.AccessDate,
0,
&pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.Fat.UpdateDate,
DirContext->DirEntry.Fat.UpdateTime,
&pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime;
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.Fat.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.Fat.FileSize,
DeviceExt->FatInfo.BytesPerCluster);
pInfo->FileAttributes = DirContext->DirEntry.Fat.Attrib & 0x3f;
}
} }
return STATUS_SUCCESS; return Status;
} }
static static
@ -278,110 +349,124 @@ VfatGetFileBothInformation(
PVFAT_DIRENTRY_CONTEXT DirContext, PVFAT_DIRENTRY_CONTEXT DirContext,
PDEVICE_EXTENSION DeviceExt, PDEVICE_EXTENSION DeviceExt,
PFILE_BOTH_DIR_INFORMATION pInfo, PFILE_BOTH_DIR_INFORMATION pInfo,
ULONG BufferLength) ULONG BufferLength,
PULONG Written,
BOOLEAN First)
{ {
if ((sizeof(FILE_BOTH_DIR_INFORMATION) + DirContext->LongNameU.Length) > BufferLength) NTSTATUS Status;
return STATUS_BUFFER_OVERFLOW; ULONG BytesToCopy = 0;
pInfo->EaSize = 0; *Written = 0;
Status = STATUS_BUFFER_OVERFLOW;
if (vfatVolumeIsFatX(DeviceExt)) if (FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName) > BufferLength)
return Status;
if (First || (BufferLength >= FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName) + DirContext->LongNameU.Length))
{ {
pInfo->FileNameLength = DirContext->LongNameU.Length; pInfo->FileNameLength = DirContext->LongNameU.Length;
pInfo->EaSize = 0;
RtlCopyMemory(pInfo->FileName, *Written = FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName);
DirContext->LongNameU.Buffer, pInfo->NextEntryOffset = 0;
DirContext->LongNameU.Length); if (BufferLength > FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName))
pInfo->NextEntryOffset = ULONG_ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION) +
DirContext->LongNameU.Length);
pInfo->ShortName[0] = 0;
pInfo->ShortNameLength = 0;
/* pInfo->FileIndex = ; */
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.FatX.CreationDate,
DirContext->DirEntry.FatX.CreationTime,
&pInfo->CreationTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.FatX.AccessDate,
DirContext->DirEntry.FatX.AccessTime,
&pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.FatX.UpdateDate,
DirContext->DirEntry.FatX.UpdateTime,
&pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime;
if (BooleanFlagOn(DirContext->DirEntry.FatX.Attrib, FILE_ATTRIBUTE_DIRECTORY))
{ {
pInfo->EndOfFile.QuadPart = 0; BytesToCopy = min(DirContext->LongNameU.Length, BufferLength - FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName));
pInfo->AllocationSize.QuadPart = 0; RtlCopyMemory(pInfo->FileName,
DirContext->LongNameU.Buffer,
BytesToCopy);
*Written += BytesToCopy;
if (BytesToCopy == DirContext->LongNameU.Length)
{
pInfo->NextEntryOffset = ULONG_ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION) +
BytesToCopy);
Status = STATUS_SUCCESS;
}
}
if (vfatVolumeIsFatX(DeviceExt))
{
pInfo->ShortName[0] = 0;
pInfo->ShortNameLength = 0;
/* pInfo->FileIndex = ; */
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.FatX.CreationDate,
DirContext->DirEntry.FatX.CreationTime,
&pInfo->CreationTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.FatX.AccessDate,
DirContext->DirEntry.FatX.AccessTime,
&pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.FatX.UpdateDate,
DirContext->DirEntry.FatX.UpdateTime,
&pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime;
if (BooleanFlagOn(DirContext->DirEntry.FatX.Attrib, FILE_ATTRIBUTE_DIRECTORY))
{
pInfo->EndOfFile.QuadPart = 0;
pInfo->AllocationSize.QuadPart = 0;
}
else
{
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.FatX.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.FatX.FileSize,
DeviceExt->FatInfo.BytesPerCluster);
}
pInfo->FileAttributes = DirContext->DirEntry.FatX.Attrib & 0x3f;
} }
else else
{ {
pInfo->EndOfFile.u.HighPart = 0; pInfo->ShortNameLength = (CCHAR)DirContext->ShortNameU.Length;
pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.FatX.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */ RtlCopyMemory(pInfo->FileName,
pInfo->AllocationSize.u.HighPart = 0; DirContext->LongNameU.Buffer,
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.FatX.FileSize, DirContext->LongNameU.Length);
DeviceExt->FatInfo.BytesPerCluster);
/* pInfo->FileIndex = ; */
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.Fat.CreationDate,
DirContext->DirEntry.Fat.CreationTime,
&pInfo->CreationTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.Fat.AccessDate,
0,
&pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.Fat.UpdateDate,
DirContext->DirEntry.Fat.UpdateTime,
&pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime;
if (BooleanFlagOn(DirContext->DirEntry.Fat.Attrib, FILE_ATTRIBUTE_DIRECTORY))
{
pInfo->EndOfFile.QuadPart = 0;
pInfo->AllocationSize.QuadPart = 0;
}
else
{
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.Fat.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.Fat.FileSize, DeviceExt->FatInfo.BytesPerCluster);
}
pInfo->FileAttributes = DirContext->DirEntry.Fat.Attrib & 0x3f;
} }
pInfo->FileAttributes = DirContext->DirEntry.FatX.Attrib & 0x3f;
}
else
{
pInfo->FileNameLength = DirContext->LongNameU.Length;
pInfo->NextEntryOffset = ULONG_ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION) +
DirContext->LongNameU.Length);
RtlCopyMemory(pInfo->ShortName,
DirContext->ShortNameU.Buffer,
DirContext->ShortNameU.Length);
pInfo->ShortNameLength = (CCHAR)DirContext->ShortNameU.Length;
RtlCopyMemory(pInfo->FileName,
DirContext->LongNameU.Buffer,
DirContext->LongNameU.Length);
/* pInfo->FileIndex = ; */
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.Fat.CreationDate,
DirContext->DirEntry.Fat.CreationTime,
&pInfo->CreationTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.Fat.AccessDate,
0,
&pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime(DeviceExt,
DirContext->DirEntry.Fat.UpdateDate,
DirContext->DirEntry.Fat.UpdateTime,
&pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime;
if (BooleanFlagOn(DirContext->DirEntry.Fat.Attrib, FILE_ATTRIBUTE_DIRECTORY))
{
pInfo->EndOfFile.QuadPart = 0;
pInfo->AllocationSize.QuadPart = 0;
}
else
{
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.Fat.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.Fat.FileSize, DeviceExt->FatInfo.BytesPerCluster);
}
pInfo->FileAttributes = DirContext->DirEntry.Fat.Attrib & 0x3f;
} }
return STATUS_SUCCESS; return Status;
} }
static static
@ -402,6 +487,7 @@ DoQuery(
VFAT_DIRENTRY_CONTEXT DirContext; VFAT_DIRENTRY_CONTEXT DirContext;
WCHAR LongNameBuffer[LONGNAME_MAX_LENGTH + 1]; WCHAR LongNameBuffer[LONGNAME_MAX_LENGTH + 1];
WCHAR ShortNameBuffer[13]; WCHAR ShortNameBuffer[13];
ULONG Written;
PIO_STACK_LOCATION Stack = IrpContext->Stack; PIO_STACK_LOCATION Stack = IrpContext->Stack;
@ -517,6 +603,7 @@ DoQuery(
DirContext.ShortNameU.Buffer = ShortNameBuffer; DirContext.ShortNameU.Buffer = ShortNameBuffer;
DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer); DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
Written = 0;
while ((Status == STATUS_SUCCESS) && (BufferLength > 0)) while ((Status == STATUS_SUCCESS) && (BufferLength > 0))
{ {
Status = FindFile(IrpContext->DeviceExt, Status = FindFile(IrpContext->DeviceExt,
@ -536,28 +623,36 @@ DoQuery(
case FileNameInformation: case FileNameInformation:
Status = VfatGetFileNameInformation(&DirContext, Status = VfatGetFileNameInformation(&DirContext,
(PFILE_NAMES_INFORMATION)Buffer, (PFILE_NAMES_INFORMATION)Buffer,
BufferLength); BufferLength,
&Written,
Buffer0 == NULL);
break; break;
case FileDirectoryInformation: case FileDirectoryInformation:
Status = VfatGetFileDirectoryInformation(&DirContext, Status = VfatGetFileDirectoryInformation(&DirContext,
IrpContext->DeviceExt, IrpContext->DeviceExt,
(PFILE_DIRECTORY_INFORMATION)Buffer, (PFILE_DIRECTORY_INFORMATION)Buffer,
BufferLength); BufferLength,
&Written,
Buffer0 == NULL);
break; break;
case FileFullDirectoryInformation: case FileFullDirectoryInformation:
Status = VfatGetFileFullDirectoryInformation(&DirContext, Status = VfatGetFileFullDirectoryInformation(&DirContext,
IrpContext->DeviceExt, IrpContext->DeviceExt,
(PFILE_FULL_DIR_INFORMATION)Buffer, (PFILE_FULL_DIR_INFORMATION)Buffer,
BufferLength); BufferLength,
&Written,
Buffer0 == NULL);
break; break;
case FileBothDirectoryInformation: case FileBothDirectoryInformation:
Status = VfatGetFileBothInformation(&DirContext, Status = VfatGetFileBothInformation(&DirContext,
IrpContext->DeviceExt, IrpContext->DeviceExt,
(PFILE_BOTH_DIR_INFORMATION)Buffer, (PFILE_BOTH_DIR_INFORMATION)Buffer,
BufferLength); BufferLength,
&Written,
Buffer0 == NULL);
break; break;
default: default:
@ -591,6 +686,12 @@ DoQuery(
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
IrpContext->Irp->IoStatus.Information = Stack->Parameters.QueryDirectory.Length - BufferLength; IrpContext->Irp->IoStatus.Information = Stack->Parameters.QueryDirectory.Length - BufferLength;
} }
else
{
ASSERT(Status != STATUS_SUCCESS || BufferLength == 0);
ASSERT(Written <= Stack->Parameters.QueryDirectory.Length);
IrpContext->Irp->IoStatus.Information = Written;
}
ExReleaseResourceLite(&pFcb->MainResource); ExReleaseResourceLite(&pFcb->MainResource);
ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource); ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);