mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[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:
parent
e15874b491
commit
52f0726817
1 changed files with 333 additions and 232 deletions
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue