1998-12-30 19:01:23 +00:00
|
|
|
/*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
2003-10-11 17:51:56 +00:00
|
|
|
* FILE: drivers/fs/vfat/dir.c
|
1998-12-30 19:01:23 +00:00
|
|
|
* PURPOSE: VFAT Filesystem : directory control
|
|
|
|
* UPDATE HISTORY:
|
|
|
|
19-12-1998 : created
|
|
|
|
|
|
|
|
*/
|
1999-03-19 05:55:55 +00:00
|
|
|
|
1998-12-30 19:01:23 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include "vfat.h"
|
|
|
|
|
1999-05-15 17:25:02 +00:00
|
|
|
|
1999-01-04 12:02:38 +00:00
|
|
|
// function like DosDateTimeToFileTime
|
2005-01-12 10:46:13 +00:00
|
|
|
BOOLEAN
|
2005-01-12 12:33:57 +00:00
|
|
|
FsdDosDateTimeToSystemTime (PDEVICE_EXTENSION DeviceExt, USHORT DosDate, USHORT DosTime, PLARGE_INTEGER SystemTime)
|
1998-12-30 19:01:23 +00:00
|
|
|
{
|
2005-01-12 12:33:57 +00:00
|
|
|
PDOSTIME pdtime = (PDOSTIME) &DosTime;
|
|
|
|
PDOSDATE pddate = (PDOSDATE) &DosDate;
|
1999-05-15 17:25:02 +00:00
|
|
|
TIME_FIELDS TimeFields;
|
2004-11-06 13:44:57 +00:00
|
|
|
LARGE_INTEGER LocalTime;
|
1998-12-30 19:01:23 +00:00
|
|
|
|
2004-11-06 13:44:57 +00:00
|
|
|
if (SystemTime == NULL)
|
1999-05-15 17:25:02 +00:00
|
|
|
return FALSE;
|
1998-12-30 19:01:23 +00:00
|
|
|
|
1999-05-15 17:25:02 +00:00
|
|
|
TimeFields.Milliseconds = 0;
|
1999-12-16 23:08:17 +00:00
|
|
|
TimeFields.Second = pdtime->Second * 2;
|
1999-05-15 17:25:02 +00:00
|
|
|
TimeFields.Minute = pdtime->Minute;
|
|
|
|
TimeFields.Hour = pdtime->Hour;
|
|
|
|
|
|
|
|
TimeFields.Day = pddate->Day;
|
|
|
|
TimeFields.Month = pddate->Month;
|
2005-02-24 20:47:07 +00:00
|
|
|
TimeFields.Year = (CSHORT)(DeviceExt->BaseDateYear + pddate->Year);
|
1999-05-15 17:25:02 +00:00
|
|
|
|
2004-11-06 13:44:57 +00:00
|
|
|
RtlTimeFieldsToTime (&TimeFields, &LocalTime);
|
|
|
|
ExLocalTimeToSystemTime(&LocalTime, SystemTime);
|
1999-05-15 17:25:02 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
1998-12-30 19:01:23 +00:00
|
|
|
|
1999-12-16 23:08:17 +00:00
|
|
|
// function like FileTimeToDosDateTime
|
2005-01-12 10:46:13 +00:00
|
|
|
BOOLEAN
|
|
|
|
FsdSystemTimeToDosDateTime (PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER SystemTime, USHORT *pDosDate, USHORT *pDosTime)
|
1999-12-16 23:08:17 +00:00
|
|
|
{
|
2005-01-12 10:46:13 +00:00
|
|
|
PDOSTIME pdtime = (PDOSTIME) pDosTime;
|
|
|
|
PDOSDATE pddate = (PDOSDATE) pDosDate;
|
1999-12-16 23:08:17 +00:00
|
|
|
TIME_FIELDS TimeFields;
|
2004-11-06 13:44:57 +00:00
|
|
|
LARGE_INTEGER LocalTime;
|
1999-12-16 23:08:17 +00:00
|
|
|
|
2004-11-06 13:44:57 +00:00
|
|
|
if (SystemTime == NULL)
|
1999-12-16 23:08:17 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2004-11-06 13:44:57 +00:00
|
|
|
ExSystemTimeToLocalTime (SystemTime, &LocalTime);
|
|
|
|
RtlTimeToTimeFields (&LocalTime, &TimeFields);
|
1999-12-16 23:08:17 +00:00
|
|
|
|
|
|
|
if (pdtime)
|
2000-12-29 23:17:12 +00:00
|
|
|
{
|
|
|
|
pdtime->Second = TimeFields.Second / 2;
|
|
|
|
pdtime->Minute = TimeFields.Minute;
|
|
|
|
pdtime->Hour = TimeFields.Hour;
|
|
|
|
}
|
1999-12-16 23:08:17 +00:00
|
|
|
|
|
|
|
if (pddate)
|
2000-12-29 23:17:12 +00:00
|
|
|
{
|
|
|
|
pddate->Day = TimeFields.Day;
|
|
|
|
pddate->Month = TimeFields.Month;
|
2005-01-12 10:46:13 +00:00
|
|
|
pddate->Year = (USHORT) (TimeFields.Year - DeviceExt->BaseDateYear);
|
2000-12-29 23:17:12 +00:00
|
|
|
}
|
1999-12-16 23:08:17 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2005-01-12 10:46:13 +00:00
|
|
|
#define ULONG_ROUND_UP(x) ROUND_UP((x), (sizeof(ULONG)))
|
1998-12-30 19:01:23 +00:00
|
|
|
|
2005-10-06 21:39:18 +00:00
|
|
|
static NTSTATUS
|
2003-10-11 17:51:56 +00:00
|
|
|
VfatGetFileNameInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
|
|
|
|
PFILE_NAMES_INFORMATION pInfo, ULONG BufferLength)
|
1998-12-30 19:01:23 +00:00
|
|
|
{
|
2003-10-11 17:51:56 +00:00
|
|
|
if ((sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
|
2000-12-29 23:17:12 +00:00
|
|
|
return STATUS_BUFFER_OVERFLOW;
|
2003-10-11 17:51:56 +00:00
|
|
|
pInfo->FileNameLength = DirContext->LongNameU.Length;
|
2000-12-29 23:17:12 +00:00
|
|
|
pInfo->NextEntryOffset =
|
2005-01-12 10:46:13 +00:00
|
|
|
ULONG_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
|
2004-12-05 16:31:51 +00:00
|
|
|
RtlCopyMemory (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
|
1998-12-30 19:01:23 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2005-10-06 21:39:18 +00:00
|
|
|
static NTSTATUS
|
2003-10-11 17:51:56 +00:00
|
|
|
VfatGetFileDirectoryInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
|
|
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
|
|
PFILE_DIRECTORY_INFORMATION pInfo,
|
|
|
|
ULONG BufferLength)
|
1998-12-30 19:01:23 +00:00
|
|
|
{
|
2003-10-11 17:51:56 +00:00
|
|
|
if ((sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
|
2000-12-29 23:17:12 +00:00
|
|
|
return STATUS_BUFFER_OVERFLOW;
|
2003-10-11 17:51:56 +00:00
|
|
|
pInfo->FileNameLength = DirContext->LongNameU.Length;
|
2000-12-29 23:17:12 +00:00
|
|
|
pInfo->NextEntryOffset =
|
2005-01-12 10:46:13 +00:00
|
|
|
ULONG_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
|
2004-12-05 16:31:51 +00:00
|
|
|
RtlCopyMemory (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
|
1998-12-30 19:01:23 +00:00
|
|
|
// pInfo->FileIndex=;
|
2004-12-05 16:31:51 +00:00
|
|
|
if (DeviceExt->Flags & VCB_IS_FATX)
|
|
|
|
{
|
|
|
|
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.CreationDate,
|
|
|
|
DirContext->DirEntry.FatX.CreationTime,
|
2004-11-06 13:44:57 +00:00
|
|
|
&pInfo->CreationTime);
|
2004-12-05 16:31:51 +00:00
|
|
|
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.AccessDate,
|
|
|
|
DirContext->DirEntry.FatX.AccessTime,
|
2004-11-06 13:44:57 +00:00
|
|
|
&pInfo->LastAccessTime);
|
2004-12-05 16:31:51 +00:00
|
|
|
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.UpdateDate,
|
|
|
|
DirContext->DirEntry.FatX.UpdateTime,
|
2004-11-06 13:44:57 +00:00
|
|
|
&pInfo->LastWriteTime);
|
2004-12-05 16:31:51 +00:00
|
|
|
pInfo->ChangeTime = pInfo->LastWriteTime;
|
|
|
|
if (DirContext->DirEntry.FatX.Attrib & FILE_ATTRIBUTE_DIRECTORY)
|
|
|
|
{
|
2005-08-24 18:29:45 +00:00
|
|
|
pInfo->EndOfFile.QuadPart = 0;
|
|
|
|
pInfo->AllocationSize.QuadPart = 0;
|
2004-12-05 16:31:51 +00:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
2004-05-23 13:34:32 +00:00
|
|
|
else
|
2004-12-05 16:31:51 +00:00
|
|
|
{
|
|
|
|
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 (DirContext->DirEntry.Fat.Attrib & FILE_ATTRIBUTE_DIRECTORY)
|
|
|
|
{
|
2005-08-24 18:29:45 +00:00
|
|
|
pInfo->EndOfFile.QuadPart = 0;
|
|
|
|
pInfo->AllocationSize.QuadPart = 0;
|
2004-12-05 16:31:51 +00:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
1998-12-30 22:48:14 +00:00
|
|
|
|
1998-12-30 19:01:23 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2005-10-06 21:39:18 +00:00
|
|
|
static NTSTATUS
|
2003-10-11 17:51:56 +00:00
|
|
|
VfatGetFileFullDirectoryInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
|
|
|
|
PDEVICE_EXTENSION DeviceExt,
|
2005-01-12 11:07:31 +00:00
|
|
|
PFILE_FULL_DIR_INFORMATION pInfo,
|
2003-10-11 17:51:56 +00:00
|
|
|
ULONG BufferLength)
|
1998-12-30 19:01:23 +00:00
|
|
|
{
|
2005-01-12 11:07:31 +00:00
|
|
|
if ((sizeof (FILE_FULL_DIR_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
|
2000-12-29 23:17:12 +00:00
|
|
|
return STATUS_BUFFER_OVERFLOW;
|
2003-10-11 17:51:56 +00:00
|
|
|
pInfo->FileNameLength = DirContext->LongNameU.Length;
|
2000-12-29 23:17:12 +00:00
|
|
|
pInfo->NextEntryOffset =
|
2005-01-12 11:07:31 +00:00
|
|
|
ULONG_ROUND_UP (sizeof (FILE_FULL_DIR_INFORMATION) + DirContext->LongNameU.Length);
|
2004-12-05 16:31:51 +00:00
|
|
|
RtlCopyMemory (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
|
1998-12-30 19:01:23 +00:00
|
|
|
// pInfo->FileIndex=;
|
2004-12-05 16:31:51 +00:00
|
|
|
if (DeviceExt->Flags & VCB_IS_FATX)
|
|
|
|
{
|
|
|
|
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.CreationDate,
|
|
|
|
DirContext->DirEntry.FatX.CreationTime,
|
2004-11-06 13:44:57 +00:00
|
|
|
&pInfo->CreationTime);
|
2004-12-05 16:31:51 +00:00
|
|
|
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,
|
2004-11-06 13:44:57 +00:00
|
|
|
0, &pInfo->LastAccessTime);
|
2004-12-05 16:31:51 +00:00
|
|
|
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.UpdateDate,
|
|
|
|
DirContext->DirEntry.Fat.UpdateTime,
|
2004-11-06 13:44:57 +00:00
|
|
|
&pInfo->LastWriteTime);
|
2004-12-05 16:31:51 +00:00
|
|
|
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;
|
|
|
|
}
|
1998-12-30 19:01:23 +00:00
|
|
|
// pInfo->EaSize=;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2005-10-06 21:39:18 +00:00
|
|
|
static NTSTATUS
|
2003-10-11 17:51:56 +00:00
|
|
|
VfatGetFileBothInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
|
|
|
|
PDEVICE_EXTENSION DeviceExt,
|
2005-01-12 11:07:31 +00:00
|
|
|
PFILE_BOTH_DIR_INFORMATION pInfo,
|
2003-10-11 17:51:56 +00:00
|
|
|
ULONG BufferLength)
|
1998-12-30 19:01:23 +00:00
|
|
|
{
|
2005-01-12 11:07:31 +00:00
|
|
|
if ((sizeof (FILE_BOTH_DIR_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
|
2000-12-29 23:17:12 +00:00
|
|
|
return STATUS_BUFFER_OVERFLOW;
|
2005-05-08 02:16:32 +00:00
|
|
|
|
2004-12-05 16:31:51 +00:00
|
|
|
if (DeviceExt->Flags & VCB_IS_FATX)
|
|
|
|
{
|
|
|
|
pInfo->FileNameLength = DirContext->LongNameU.Length;
|
|
|
|
RtlCopyMemory(pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
|
2005-05-08 02:16:32 +00:00
|
|
|
pInfo->NextEntryOffset =
|
2005-01-12 11:07:31 +00:00
|
|
|
ULONG_ROUND_UP (sizeof (FILE_BOTH_DIR_INFORMATION) + DirContext->LongNameU.Length);
|
2004-12-05 16:31:51 +00:00
|
|
|
pInfo->ShortName[0] = 0;
|
|
|
|
pInfo->ShortNameLength = 0;
|
|
|
|
// pInfo->FileIndex=;
|
|
|
|
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.CreationDate,
|
|
|
|
DirContext->DirEntry.FatX.CreationTime,
|
2004-11-06 13:44:57 +00:00
|
|
|
&pInfo->CreationTime);
|
2004-12-05 16:31:51 +00:00
|
|
|
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.AccessDate,
|
|
|
|
DirContext->DirEntry.FatX.AccessTime,
|
2004-11-06 13:44:57 +00:00
|
|
|
&pInfo->LastAccessTime);
|
2004-12-05 16:31:51 +00:00
|
|
|
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.UpdateDate,
|
|
|
|
DirContext->DirEntry.FatX.UpdateTime,
|
2004-11-06 13:44:57 +00:00
|
|
|
&pInfo->LastWriteTime);
|
2004-12-05 16:31:51 +00:00
|
|
|
pInfo->ChangeTime = pInfo->LastWriteTime;
|
|
|
|
if (DirContext->DirEntry.FatX.Attrib & FILE_ATTRIBUTE_DIRECTORY)
|
|
|
|
{
|
2005-08-24 18:29:45 +00:00
|
|
|
pInfo->EndOfFile.QuadPart = 0;
|
|
|
|
pInfo->AllocationSize.QuadPart = 0;
|
2004-12-05 16:31:51 +00:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
2004-05-23 13:34:32 +00:00
|
|
|
else
|
2004-12-05 16:31:51 +00:00
|
|
|
{
|
|
|
|
pInfo->FileNameLength = DirContext->LongNameU.Length;
|
2005-05-08 02:16:32 +00:00
|
|
|
pInfo->NextEntryOffset =
|
2005-01-12 11:07:31 +00:00
|
|
|
ULONG_ROUND_UP (sizeof (FILE_BOTH_DIR_INFORMATION) + DirContext->LongNameU.Length);
|
2004-12-05 16:31:51 +00:00
|
|
|
RtlCopyMemory(pInfo->ShortName, DirContext->ShortNameU.Buffer, DirContext->ShortNameU.Length);
|
2005-02-24 20:47:07 +00:00
|
|
|
pInfo->ShortNameLength = (CCHAR)DirContext->ShortNameU.Length;
|
2004-12-05 16:31:51 +00:00
|
|
|
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 (DirContext->DirEntry.Fat.Attrib & FILE_ATTRIBUTE_DIRECTORY)
|
|
|
|
{
|
2005-08-24 18:29:45 +00:00
|
|
|
pInfo->EndOfFile.QuadPart = 0;
|
|
|
|
pInfo->AllocationSize.QuadPart = 0;
|
2004-12-05 16:31:51 +00:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
2004-05-23 13:34:32 +00:00
|
|
|
pInfo->EaSize=0;
|
1998-12-30 19:01:23 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2005-10-06 21:39:18 +00:00
|
|
|
static NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext)
|
1998-12-30 19:01:23 +00:00
|
|
|
{
|
2000-12-29 23:17:12 +00:00
|
|
|
NTSTATUS RC = STATUS_SUCCESS;
|
|
|
|
long BufferLength = 0;
|
|
|
|
PUNICODE_STRING pSearchPattern = NULL;
|
|
|
|
FILE_INFORMATION_CLASS FileInformationClass;
|
|
|
|
unsigned char *Buffer = NULL;
|
|
|
|
PFILE_NAMES_INFORMATION Buffer0 = NULL;
|
|
|
|
PVFATFCB pFcb;
|
|
|
|
PVFATCCB pCcb;
|
2005-08-11 19:11:17 +00:00
|
|
|
BOOLEAN FirstQuery = FALSE;
|
|
|
|
BOOLEAN FirstCall = TRUE;
|
2003-10-11 17:51:56 +00:00
|
|
|
VFAT_DIRENTRY_CONTEXT DirContext;
|
2005-01-13 20:54:13 +00:00
|
|
|
WCHAR LongNameBuffer[LONGNAME_MAX_LENGTH + 1];
|
2003-10-11 17:51:56 +00:00
|
|
|
WCHAR ShortNameBuffer[13];
|
2004-12-23 12:39:16 +00:00
|
|
|
|
|
|
|
PIO_STACK_LOCATION Stack = IrpContext->Stack;
|
2001-11-02 22:47:36 +00:00
|
|
|
|
|
|
|
pCcb = (PVFATCCB) IrpContext->FileObject->FsContext2;
|
2003-02-13 22:24:19 +00:00
|
|
|
pFcb = (PVFATFCB) IrpContext->FileObject->FsContext;
|
2001-11-02 22:47:36 +00:00
|
|
|
|
2003-10-11 17:51:56 +00:00
|
|
|
// determine Buffer for result :
|
|
|
|
BufferLength = Stack->Parameters.QueryDirectory.Length;
|
2003-12-13 14:25:04 +00:00
|
|
|
#if 0
|
|
|
|
/* Do not probe the user buffer until SEH is available */
|
2003-10-11 17:51:56 +00:00
|
|
|
if (IrpContext->Irp->RequestorMode != KernelMode &&
|
2005-05-08 02:16:32 +00:00
|
|
|
IrpContext->Irp->MdlAddress == NULL &&
|
2003-10-11 17:51:56 +00:00
|
|
|
IrpContext->Irp->UserBuffer != NULL)
|
|
|
|
{
|
|
|
|
ProbeForWrite(IrpContext->Irp->UserBuffer, BufferLength, 1);
|
|
|
|
}
|
2003-12-13 14:25:04 +00:00
|
|
|
#endif
|
2003-10-11 17:51:56 +00:00
|
|
|
Buffer = VfatGetUserBuffer(IrpContext->Irp);
|
|
|
|
|
2003-07-24 19:00:42 +00:00
|
|
|
if (!ExAcquireResourceSharedLite(&pFcb->MainResource,
|
|
|
|
(BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
|
2003-10-11 17:51:56 +00:00
|
|
|
{
|
|
|
|
RC = VfatLockUserBuffer(IrpContext->Irp, BufferLength, IoWriteAccess);
|
|
|
|
if (NT_SUCCESS(RC))
|
|
|
|
{
|
|
|
|
RC = STATUS_PENDING;
|
|
|
|
}
|
|
|
|
return RC;
|
|
|
|
}
|
2001-11-02 22:47:36 +00:00
|
|
|
|
2003-10-11 17:51:56 +00:00
|
|
|
/* Obtain the callers parameters */
|
2005-01-12 12:06:15 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
/* HACKHACK: Bug in the MS ntifs.h header:
|
|
|
|
* FileName is really a PUNICODE_STRING, not a PSTRING */
|
|
|
|
pSearchPattern = (PUNICODE_STRING)Stack->Parameters.QueryDirectory.FileName;
|
|
|
|
#else
|
2003-08-07 11:47:33 +00:00
|
|
|
pSearchPattern = Stack->Parameters.QueryDirectory.FileName;
|
2005-01-12 12:06:15 +00:00
|
|
|
#endif
|
2000-12-29 23:17:12 +00:00
|
|
|
FileInformationClass =
|
2003-08-07 11:47:33 +00:00
|
|
|
Stack->Parameters.QueryDirectory.FileInformationClass;
|
2002-02-05 21:31:03 +00:00
|
|
|
if (pSearchPattern)
|
|
|
|
{
|
2003-10-11 17:51:56 +00:00
|
|
|
if (!pCcb->SearchPattern.Buffer)
|
|
|
|
{
|
2005-08-11 19:11:17 +00:00
|
|
|
FirstQuery = TRUE;
|
2003-10-11 17:51:56 +00:00
|
|
|
pCcb->SearchPattern.MaximumLength = pSearchPattern->Length + sizeof(WCHAR);
|
2007-11-20 15:26:17 +00:00
|
|
|
pCcb->SearchPattern.Buffer = ExAllocatePoolWithTag(NonPagedPool, pCcb->SearchPattern.MaximumLength, TAG_VFAT);
|
2003-10-11 17:51:56 +00:00
|
|
|
if (!pCcb->SearchPattern.Buffer)
|
|
|
|
{
|
|
|
|
ExReleaseResourceLite(&pFcb->MainResource);
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
RtlCopyUnicodeString(&pCcb->SearchPattern, pSearchPattern);
|
|
|
|
pCcb->SearchPattern.Buffer[pCcb->SearchPattern.Length / sizeof(WCHAR)] = 0;
|
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
}
|
2003-10-11 17:51:56 +00:00
|
|
|
else if (!pCcb->SearchPattern.Buffer)
|
2002-02-05 21:31:03 +00:00
|
|
|
{
|
2005-08-11 19:11:17 +00:00
|
|
|
FirstQuery = TRUE;
|
2003-10-11 17:51:56 +00:00
|
|
|
pCcb->SearchPattern.MaximumLength = 2 * sizeof(WCHAR);
|
2007-11-20 15:26:17 +00:00
|
|
|
pCcb->SearchPattern.Buffer = ExAllocatePoolWithTag(NonPagedPool, 2 * sizeof(WCHAR), TAG_VFAT);
|
2003-10-11 17:51:56 +00:00
|
|
|
if (!pCcb->SearchPattern.Buffer)
|
|
|
|
{
|
|
|
|
ExReleaseResourceLite(&pFcb->MainResource);
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
pCcb->SearchPattern.Buffer[0] = L'*';
|
|
|
|
pCcb->SearchPattern.Buffer[1] = 0;
|
|
|
|
pCcb->SearchPattern.Length = sizeof(WCHAR);
|
2002-02-05 21:31:03 +00:00
|
|
|
}
|
2002-03-18 22:37:13 +00:00
|
|
|
|
2002-02-05 21:31:03 +00:00
|
|
|
if (IrpContext->Stack->Flags & SL_INDEX_SPECIFIED)
|
2003-10-11 17:51:56 +00:00
|
|
|
{
|
2005-08-11 19:11:17 +00:00
|
|
|
DirContext.DirIndex = pCcb->Entry = Stack->Parameters.QueryDirectory.FileIndex;
|
2003-10-11 17:51:56 +00:00
|
|
|
}
|
2005-08-11 19:11:17 +00:00
|
|
|
else if (FirstQuery || (IrpContext->Stack->Flags & SL_RESTART_SCAN))
|
2003-10-11 17:51:56 +00:00
|
|
|
{
|
|
|
|
DirContext.DirIndex = pCcb->Entry = 0;
|
|
|
|
}
|
1999-01-04 12:02:38 +00:00
|
|
|
else
|
2003-10-11 17:51:56 +00:00
|
|
|
{
|
|
|
|
DirContext.DirIndex = pCcb->Entry;
|
|
|
|
}
|
|
|
|
|
2007-11-21 16:50:07 +00:00
|
|
|
DPRINT ("Buffer=%p tofind=%wZ\n", Buffer, &pCcb->SearchPattern);
|
2003-10-11 17:51:56 +00:00
|
|
|
|
|
|
|
DirContext.LongNameU.Buffer = LongNameBuffer;
|
|
|
|
DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
|
|
|
|
DirContext.ShortNameU.Buffer = ShortNameBuffer;
|
|
|
|
DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
|
2002-02-05 21:31:03 +00:00
|
|
|
|
|
|
|
while (RC == STATUS_SUCCESS && BufferLength > 0)
|
1999-01-04 12:02:38 +00:00
|
|
|
{
|
2005-05-08 02:16:32 +00:00
|
|
|
RC = FindFile (IrpContext->DeviceExt, pFcb,
|
2003-10-11 17:51:56 +00:00
|
|
|
&pCcb->SearchPattern, &DirContext, FirstCall);
|
|
|
|
pCcb->Entry = DirContext.DirIndex;
|
|
|
|
DPRINT ("Found %wZ, RC=%x, entry %x\n", &DirContext.LongNameU, RC, pCcb->Entry);
|
|
|
|
FirstCall = FALSE;
|
|
|
|
if (NT_SUCCESS (RC))
|
|
|
|
{
|
|
|
|
switch (FileInformationClass)
|
|
|
|
{
|
|
|
|
case FileNameInformation:
|
|
|
|
RC = VfatGetFileNameInformation (&DirContext,
|
2005-05-08 02:16:32 +00:00
|
|
|
(PFILE_NAMES_INFORMATION) Buffer,
|
2003-10-11 17:51:56 +00:00
|
|
|
BufferLength);
|
|
|
|
break;
|
|
|
|
case FileDirectoryInformation:
|
2005-05-08 02:16:32 +00:00
|
|
|
RC = VfatGetFileDirectoryInformation (&DirContext,
|
2003-10-11 17:51:56 +00:00
|
|
|
IrpContext->DeviceExt,
|
2005-05-08 02:16:32 +00:00
|
|
|
(PFILE_DIRECTORY_INFORMATION) Buffer,
|
2003-10-11 17:51:56 +00:00
|
|
|
BufferLength);
|
|
|
|
break;
|
|
|
|
case FileFullDirectoryInformation:
|
2005-05-08 02:16:32 +00:00
|
|
|
RC = VfatGetFileFullDirectoryInformation (&DirContext,
|
2003-10-11 17:51:56 +00:00
|
|
|
IrpContext->DeviceExt,
|
2005-05-08 02:16:32 +00:00
|
|
|
(PFILE_FULL_DIR_INFORMATION) Buffer,
|
2003-10-11 17:51:56 +00:00
|
|
|
BufferLength);
|
|
|
|
break;
|
|
|
|
case FileBothDirectoryInformation:
|
2005-05-08 02:16:32 +00:00
|
|
|
RC = VfatGetFileBothInformation (&DirContext,
|
2003-10-11 17:51:56 +00:00
|
|
|
IrpContext->DeviceExt,
|
2005-05-08 02:16:32 +00:00
|
|
|
(PFILE_BOTH_DIR_INFORMATION) Buffer,
|
2003-10-11 17:51:56 +00:00
|
|
|
BufferLength);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
RC = STATUS_INVALID_INFO_CLASS;
|
|
|
|
}
|
|
|
|
if (RC == STATUS_BUFFER_OVERFLOW)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-08-11 19:11:17 +00:00
|
|
|
if (FirstQuery)
|
2003-10-11 17:51:56 +00:00
|
|
|
{
|
|
|
|
RC = STATUS_NO_SUCH_FILE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RC = STATUS_NO_MORE_FILES;
|
|
|
|
}
|
2002-02-05 21:31:03 +00:00
|
|
|
break;
|
2003-10-11 17:51:56 +00:00
|
|
|
}
|
|
|
|
Buffer0 = (PFILE_NAMES_INFORMATION) Buffer;
|
2005-08-11 19:11:17 +00:00
|
|
|
Buffer0->FileIndex = DirContext.DirIndex;
|
2003-10-11 17:51:56 +00:00
|
|
|
pCcb->Entry = ++DirContext.DirIndex;
|
2005-08-11 19:11:17 +00:00
|
|
|
BufferLength -= Buffer0->NextEntryOffset;
|
2003-10-11 17:51:56 +00:00
|
|
|
if (IrpContext->Stack->Flags & SL_RETURN_SINGLE_ENTRY)
|
2002-02-05 21:31:03 +00:00
|
|
|
{
|
2003-10-11 17:51:56 +00:00
|
|
|
break;
|
2002-02-05 21:31:03 +00:00
|
|
|
}
|
2003-10-11 17:51:56 +00:00
|
|
|
Buffer += Buffer0->NextEntryOffset;
|
1998-12-30 19:01:23 +00:00
|
|
|
}
|
2003-10-11 17:51:56 +00:00
|
|
|
if (Buffer0)
|
2002-02-02 14:04:55 +00:00
|
|
|
{
|
2003-10-11 17:51:56 +00:00
|
|
|
Buffer0->NextEntryOffset = 0;
|
|
|
|
RC = STATUS_SUCCESS;
|
2005-05-05 11:05:05 +00:00
|
|
|
IrpContext->Irp->IoStatus.Information = Stack->Parameters.QueryDirectory.Length - BufferLength;
|
|
|
|
|
1998-12-30 19:01:23 +00:00
|
|
|
}
|
2002-03-18 22:37:13 +00:00
|
|
|
ExReleaseResourceLite(&pFcb->MainResource);
|
1998-12-30 19:01:23 +00:00
|
|
|
return RC;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-11-02 22:47:36 +00:00
|
|
|
NTSTATUS VfatDirectoryControl (PVFAT_IRP_CONTEXT IrpContext)
|
1998-12-30 19:01:23 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: directory control : read/write directory informations
|
|
|
|
*/
|
|
|
|
{
|
2000-12-29 23:17:12 +00:00
|
|
|
NTSTATUS RC = STATUS_SUCCESS;
|
2005-05-05 11:05:05 +00:00
|
|
|
IrpContext->Irp->IoStatus.Information = 0;
|
2001-11-02 22:47:36 +00:00
|
|
|
switch (IrpContext->MinorFunction)
|
2000-12-29 23:17:12 +00:00
|
|
|
{
|
1998-12-30 19:01:23 +00:00
|
|
|
case IRP_MN_QUERY_DIRECTORY:
|
2001-11-02 22:47:36 +00:00
|
|
|
RC = DoQuery (IrpContext);
|
1998-12-30 19:01:23 +00:00
|
|
|
break;
|
|
|
|
case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
|
2000-12-29 23:17:12 +00:00
|
|
|
DPRINT (" vfat, dir : change\n");
|
|
|
|
RC = STATUS_NOT_IMPLEMENTED;
|
1998-12-30 19:01:23 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// error
|
2000-12-29 23:17:12 +00:00
|
|
|
DbgPrint ("unexpected minor function %x in VFAT driver\n",
|
2001-11-02 22:47:36 +00:00
|
|
|
IrpContext->MinorFunction);
|
2000-12-29 23:17:12 +00:00
|
|
|
RC = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
break;
|
|
|
|
}
|
2001-11-02 22:47:36 +00:00
|
|
|
if (RC == STATUS_PENDING)
|
|
|
|
{
|
|
|
|
RC = VfatQueueRequest(IrpContext);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
IrpContext->Irp->IoStatus.Status = RC;
|
|
|
|
IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT);
|
|
|
|
VfatFreeIrpContext(IrpContext);
|
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
return RC;
|
|
|
|
}
|
2001-07-05 01:51:53 +00:00
|
|
|
|
|
|
|
|