Reworked code for handling of asynchonous i/o requests.
[reactos.git] / reactos / drivers / fs / vfat / dir.c
index e2ad098..7dc3f39 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * $Id: dir.c,v 1.21 2001/11/02 22:44:34 hbirr Exp $
+ *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
  * FILE:             services/fs/vfat/dir.c
 
 */
 
-#include <wchar.h>
-#include <internal/string.h>
 #include <ddk/ntddk.h>
-#include <ddk/cctypes.h>
-#include <ddk/zwtypes.h>
+#include <wchar.h>
 
 #define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
 
 #include "vfat.h"
 
-//days from 1st January
-static const int MonthsDF1[2][12] =
-{
-    { 0,31, 59, 90,120,151,181,212,243,273,304,334 },
-    { 0,31, 60, 91,121,152,182,213,244,274,305,335 }
-};
-static __inline int IsLeapYear(int Year)
-{
-  return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0;
-}
+
 // function like DosDateTimeToFileTime
-BOOL fsdDosDateTimeToFileTime(WORD wDosDate,WORD wDosTime, TIME *FileTime)
+BOOL FsdDosDateTimeToFileTime (WORD wDosDate, WORD wDosTime, TIME * FileTime)
 {
- WORD Day,Month,Year,Second,Minute,Hour;
- long long int *pTime=(long long int *)FileTime;
- long long int mult;
-  Day=wDosDate&0x001f;
-  Month= (wDosDate&0x00e0)>>5;//1=January
-  Year= ((wDosDate&0xff00)>>8)+1980;
-  Second=(wDosTime&0x001f)<<1;
-  Minute=(wDosTime&0x07e0)>>5;
-  Hour=  (wDosTime&0xf100)>>11;
-  mult=10000000;
-  *pTime=Second*mult;
-  mult *=60;
-  *pTime +=Minute*mult;
-  mult *=60;
-  *pTime +=Hour*mult;
-  mult *=24;
-  *pTime +=(Day-1)*mult;
-  if((Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0))
-    *pTime += MonthsDF1[1][Month-1];
-  else
-    *pTime += MonthsDF1[0][Month-1];
-  *pTime +=(Year-1601)*mult*365
-           +(Year-1601)/4
-           -(Year-1601)/100
-           +(Year-1601)/400;
+  PDOSTIME pdtime = (PDOSTIME) & wDosTime;
+  PDOSDATE pddate = (PDOSDATE) & wDosDate;
+  TIME_FIELDS TimeFields;
+
+  if (FileTime == NULL)
+    return FALSE;
+
+  TimeFields.Milliseconds = 0;
+  TimeFields.Second = pdtime->Second * 2;
+  TimeFields.Minute = pdtime->Minute;
+  TimeFields.Hour = pdtime->Hour;
+
+  TimeFields.Day = pddate->Day;
+  TimeFields.Month = pddate->Month;
+  TimeFields.Year = 1980 + pddate->Year;
+
+  RtlTimeFieldsToTime (&TimeFields, (PLARGE_INTEGER) FileTime);
+
   return TRUE;
 }
-#define DosDateTimeToFileTime fsdDosDateTimeToFileTime
 
 
+// function like FileTimeToDosDateTime
+BOOL
+FsdFileTimeToDosDateTime (TIME * FileTime, WORD * pwDosDate, WORD * pwDosTime)
+{
+  PDOSTIME pdtime = (PDOSTIME) pwDosTime;
+  PDOSDATE pddate = (PDOSDATE) pwDosDate;
+  TIME_FIELDS TimeFields;
+
+  if (FileTime == NULL)
+    return FALSE;
 
+  RtlTimeToTimeFields ((PLARGE_INTEGER) FileTime, &TimeFields);
 
-unsigned long vfat_wstrlen(PWSTR s)
+  if (pdtime)
+    {
+      pdtime->Second = TimeFields.Second / 2;
+      pdtime->Minute = TimeFields.Minute;
+      pdtime->Hour = TimeFields.Hour;
+    }
+
+  if (pddate)
+    {
+      pddate->Day = TimeFields.Day;
+      pddate->Month = TimeFields.Month;
+      pddate->Year = TimeFields.Year - 1980;
+    }
+
+  return TRUE;
+}
+
+
+
+unsigned long
+vfat_wstrlen (PWSTR s)
 {
-        WCHAR c=' ';
-        unsigned int len=0;
+  WCHAR c = ' ';
+  unsigned int len = 0;
 
-        while(c!=0) {
-                c=*s;
-                s++;
-                len++;
-        };
-        s-=len;
+  while (c != 0)
+    {
+      c = *s;
+      s++;
+      len++;
+    };
+  s -= len;
 
-        return len-1;
+  return len - 1;
 }
+
 #define DWORD_ROUND_UP(x) ( (((ULONG)(x))%32) ? ((((ULONG)x)&(~0x1f))+0x20) : ((ULONG)x) )
 
-NTSTATUS FsdGetFileNameInformation(PVfatFCB pFcb,
-         PFILE_NAMES_INFORMATION pInfo,ULONG BufferLength)
+NTSTATUS
+VfatGetFileNameInformation (PVFATFCB pFcb,
+                          PFILE_NAMES_INFORMATION pInfo, ULONG BufferLength)
 {
- ULONG Length;
-  Length=vfat_wstrlen(pFcb->ObjectName);
-  if( (sizeof(FILE_DIRECTORY_INFORMATION)+Length) >BufferLength)
-     return STATUS_BUFFER_OVERFLOW;
-  pInfo->FileNameLength=Length;
-  pInfo->NextEntryOffset=DWORD_ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION)+Length);
-  memcpy(pInfo->FileName,pFcb->ObjectName
-     ,sizeof(WCHAR)*(pInfo->FileNameLength));
+  ULONG Length;
+  Length = vfat_wstrlen (pFcb->ObjectName);
+  if ((sizeof (FILE_DIRECTORY_INFORMATION) + Length * sizeof(WCHAR)) > BufferLength)
+    return STATUS_BUFFER_OVERFLOW;
+  pInfo->FileNameLength = Length;
+  pInfo->NextEntryOffset =
+    DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + Length * sizeof(WCHAR));
+  memcpy (pInfo->FileName, pFcb->ObjectName,
+         sizeof (WCHAR) * (pInfo->FileNameLength));
   return STATUS_SUCCESS;
 }
 
-NTSTATUS FsdGetFileDirectoryInformation(PVfatFCB pFcb,
-          PDEVICE_EXTENSION DeviceExt,
-          PFILE_DIRECTORY_INFORMATION pInfo,ULONG BufferLength)
+NTSTATUS
+VfatGetFileDirectoryInformation (PVFATFCB pFcb,
+                               PDEVICE_EXTENSION DeviceExt,
+                               PFILE_DIRECTORY_INFORMATION pInfo,
+                               ULONG BufferLength)
 {
- unsigned long long AllocSize;
- ULONG Length;
-  Length=vfat_wstrlen(pFcb->ObjectName);
-  if( (sizeof(FILE_DIRECTORY_INFORMATION)+Length) >BufferLength)
-     return STATUS_BUFFER_OVERFLOW;
-  pInfo->FileNameLength=Length;
-  pInfo->NextEntryOffset=DWORD_ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION)+Length);
-  memcpy(pInfo->FileName,pFcb->ObjectName
-     ,sizeof(WCHAR)*(pInfo->FileNameLength));
+  unsigned long long AllocSize;
+  ULONG Length;
+  Length = vfat_wstrlen (pFcb->ObjectName);
+  if ((sizeof (FILE_DIRECTORY_INFORMATION) + Length * sizeof(WCHAR)) > BufferLength)
+    return STATUS_BUFFER_OVERFLOW;
+  pInfo->FileNameLength = Length;
+  pInfo->NextEntryOffset =
+    DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + Length * sizeof(WCHAR));
+  memcpy (pInfo->FileName, pFcb->ObjectName,
+         sizeof (WCHAR) * (pInfo->FileNameLength));
 //      pInfo->FileIndex=;
-  DosDateTimeToFileTime(pFcb->entry.CreationDate,pFcb->entry.CreationTime
-      ,&pInfo->CreationTime);
-  DosDateTimeToFileTime(pFcb->entry.AccessDate,0
-      ,&pInfo->LastAccessTime);
-  DosDateTimeToFileTime(pFcb->entry.UpdateDate,pFcb->entry.UpdateTime
-      ,&pInfo->LastWriteTime);
-  DosDateTimeToFileTime(pFcb->entry.UpdateDate,pFcb->entry.UpdateTime
-      ,&pInfo->ChangeTime);
-  pInfo->EndOfFile=RtlConvertUlongToLargeInteger(pFcb->entry.FileSize);
+  FsdDosDateTimeToFileTime (pFcb->entry.CreationDate,
+                           pFcb->entry.CreationTime, &pInfo->CreationTime);
+  FsdDosDateTimeToFileTime (pFcb->entry.AccessDate, 0,
+                           &pInfo->LastAccessTime);
+  FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime,
+                           &pInfo->LastWriteTime);
+  FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime,
+                           &pInfo->ChangeTime);
+  pInfo->EndOfFile = RtlConvertUlongToLargeInteger (pFcb->entry.FileSize);
   /* Make allocsize a rounded up multiple of BytesPerCluster */
-  AllocSize = ((pFcb->entry.FileSize +  DeviceExt->BytesPerCluster - 1) /
-          DeviceExt->BytesPerCluster) *
-          DeviceExt->BytesPerCluster;
+  AllocSize = ((pFcb->entry.FileSize + DeviceExt->BytesPerCluster - 1) /
+              DeviceExt->BytesPerCluster) * DeviceExt->BytesPerCluster;
   pInfo->AllocationSize.QuadPart = AllocSize;
-  pInfo->FileAttributes=pFcb->entry.Attrib;
+  pInfo->FileAttributes = pFcb->entry.Attrib;
 
   return STATUS_SUCCESS;
 }
 
-NTSTATUS FsdGetFileFullDirectoryInformation(PVfatFCB pFcb,
-          PDEVICE_EXTENSION DeviceExt,
-          PFILE_FULL_DIRECTORY_INFORMATION pInfo,ULONG BufferLength)
+NTSTATUS
+VfatGetFileFullDirectoryInformation (PVFATFCB pFcb,
+                                   PDEVICE_EXTENSION DeviceExt,
+                                   PFILE_FULL_DIRECTORY_INFORMATION pInfo,
+                                   ULONG BufferLength)
 {
- unsigned long long AllocSize;
- ULONG Length;
-  Length=vfat_wstrlen(pFcb->ObjectName);
-  if( (sizeof(FILE_FULL_DIRECTORY_INFORMATION)+Length) >BufferLength)
-     return STATUS_BUFFER_OVERFLOW;
-  pInfo->FileNameLength=Length;
-  pInfo->NextEntryOffset=DWORD_ROUND_UP(sizeof(FILE_FULL_DIRECTORY_INFORMATION)+Length);
-  memcpy(pInfo->FileName,pFcb->ObjectName
-     ,sizeof(WCHAR)*(pInfo->FileNameLength));
+  unsigned long long AllocSize;
+  ULONG Length;
+  Length = vfat_wstrlen (pFcb->ObjectName);
+  if ((sizeof (FILE_FULL_DIRECTORY_INFORMATION) + Length * sizeof(WCHAR)) > BufferLength)
+    return STATUS_BUFFER_OVERFLOW;
+  pInfo->FileNameLength = Length;
+  pInfo->NextEntryOffset =
+    DWORD_ROUND_UP (sizeof (FILE_FULL_DIRECTORY_INFORMATION) + Length * sizeof(WCHAR));
+  memcpy (pInfo->FileName, pFcb->ObjectName,
+         sizeof (WCHAR) * (pInfo->FileNameLength));
 //      pInfo->FileIndex=;
-  DosDateTimeToFileTime(pFcb->entry.CreationDate,pFcb->entry.CreationTime
-      ,&pInfo->CreationTime);
-  DosDateTimeToFileTime(pFcb->entry.AccessDate,0
-      ,&pInfo->LastAccessTime);
-  DosDateTimeToFileTime(pFcb->entry.UpdateDate,pFcb->entry.UpdateTime
-      ,&pInfo->LastWriteTime);
-  DosDateTimeToFileTime(pFcb->entry.UpdateDate,pFcb->entry.UpdateTime
-      ,&pInfo->ChangeTime);
-  pInfo->EndOfFile=RtlConvertUlongToLargeInteger(pFcb->entry.FileSize);
+  FsdDosDateTimeToFileTime (pFcb->entry.CreationDate,
+                           pFcb->entry.CreationTime, &pInfo->CreationTime);
+  FsdDosDateTimeToFileTime (pFcb->entry.AccessDate, 0,
+                           &pInfo->LastAccessTime);
+  FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime,
+                           &pInfo->LastWriteTime);
+  FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime,
+                           &pInfo->ChangeTime);
+  pInfo->EndOfFile = RtlConvertUlongToLargeInteger (pFcb->entry.FileSize);
   /* Make allocsize a rounded up multiple of BytesPerCluster */
-  AllocSize = ((pFcb->entry.FileSize +  DeviceExt->BytesPerCluster - 1) /
-          DeviceExt->BytesPerCluster) *
-          DeviceExt->BytesPerCluster;
+  AllocSize = ((pFcb->entry.FileSize + DeviceExt->BytesPerCluster - 1) /
+              DeviceExt->BytesPerCluster) * DeviceExt->BytesPerCluster;
   pInfo->AllocationSize.QuadPart = AllocSize;
-  pInfo->FileAttributes=pFcb->entry.Attrib;
+  pInfo->FileAttributes = pFcb->entry.Attrib;
 //      pInfo->EaSize=;
   return STATUS_SUCCESS;
 }
 
-NTSTATUS FsdGetFileBothInformation(PVfatFCB pFcb,
-          PDEVICE_EXTENSION DeviceExt,
-          PFILE_BOTH_DIRECTORY_INFORMATION pInfo,ULONG BufferLength)
+NTSTATUS
+VfatGetFileBothInformation (PVFATFCB pFcb,
+                          PDEVICE_EXTENSION DeviceExt,
+                          PFILE_BOTH_DIRECTORY_INFORMATION pInfo,
+                          ULONG BufferLength)
 {
- short i;
- unsigned long long AllocSize;
- ULONG Length;
-  Length=vfat_wstrlen(pFcb->ObjectName);
-  if( (sizeof(FILE_BOTH_DIRECTORY_INFORMATION)+Length) >BufferLength)
-     return STATUS_BUFFER_OVERFLOW;
-  pInfo->FileNameLength=Length;
-  pInfo->NextEntryOffset=DWORD_ROUND_UP(sizeof(FILE_BOTH_DIRECTORY_INFORMATION)+Length);
-  memcpy(pInfo->FileName,pFcb->ObjectName
-     ,sizeof(WCHAR)*(pInfo->FileNameLength));
+  short i;
+  unsigned long long AllocSize;
+  ULONG Length;
+  Length = vfat_wstrlen (pFcb->ObjectName);
+  if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length * sizeof(WCHAR)) > BufferLength)
+    return STATUS_BUFFER_OVERFLOW;
+  pInfo->FileNameLength = Length;
+  pInfo->NextEntryOffset =
+    DWORD_ROUND_UP (sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length * sizeof(WCHAR));
+  memcpy (pInfo->FileName, pFcb->ObjectName,
+         sizeof (WCHAR) * (pInfo->FileNameLength));
 //      pInfo->FileIndex=;
-  DosDateTimeToFileTime(pFcb->entry.CreationDate,pFcb->entry.CreationTime
-      ,&pInfo->CreationTime);
-  DosDateTimeToFileTime(pFcb->entry.AccessDate,0
-      ,&pInfo->LastAccessTime);
-  DosDateTimeToFileTime(pFcb->entry.UpdateDate,pFcb->entry.UpdateTime
-      ,&pInfo->LastWriteTime);
-  DosDateTimeToFileTime(pFcb->entry.UpdateDate,pFcb->entry.UpdateTime
-      ,&pInfo->ChangeTime);
-  pInfo->EndOfFile=RtlConvertUlongToLargeInteger(pFcb->entry.FileSize);
+  FsdDosDateTimeToFileTime (pFcb->entry.CreationDate,
+                           pFcb->entry.CreationTime, &pInfo->CreationTime);
+  FsdDosDateTimeToFileTime (pFcb->entry.AccessDate, 0,
+                           &pInfo->LastAccessTime);
+  FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime,
+                           &pInfo->LastWriteTime);
+  FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime,
+                           &pInfo->ChangeTime);
+  pInfo->EndOfFile = RtlConvertUlongToLargeInteger (pFcb->entry.FileSize);
   /* Make allocsize a rounded up multiple of BytesPerCluster */
-  AllocSize = ((pFcb->entry.FileSize +  DeviceExt->BytesPerCluster - 1) /
-          DeviceExt->BytesPerCluster) *
-          DeviceExt->BytesPerCluster;
+  AllocSize = ((pFcb->entry.FileSize + DeviceExt->BytesPerCluster - 1) /
+              DeviceExt->BytesPerCluster) * DeviceExt->BytesPerCluster;
   pInfo->AllocationSize.QuadPart = AllocSize;
-  pInfo->FileAttributes=pFcb->entry.Attrib;
+  pInfo->FileAttributes = pFcb->entry.Attrib;
 //      pInfo->EaSize=;
-  for (i=0;i<8 && (pFcb->entry.Filename[i]!=' ') ;i++)
-    pInfo->ShortName[i]=pFcb->entry.Filename[i];
-  pInfo->ShortNameLength=i;
-  pInfo->ShortName[i]='.';
-  for (i=0 ;i<3 && (pFcb->entry.Ext[i]!=' ') ;i++)
-    pInfo->ShortName[i+1+pInfo->ShortNameLength]=pFcb->entry.Ext[i];
-  if(i) pInfo->ShortNameLength += (i+1);
+  for (i = 0; i < 8 && (pFcb->entry.Filename[i] != ' '); i++)
+    pInfo->ShortName[i] = pFcb->entry.Filename[i];
+  pInfo->ShortNameLength = i;
+  pInfo->ShortName[i] = '.';
+  for (i = 0; i < 3 && (pFcb->entry.Ext[i] != ' '); i++)
+    pInfo->ShortName[i + 1 + pInfo->ShortNameLength] = pFcb->entry.Ext[i];
+  if (i)
+    pInfo->ShortNameLength += (i + 1);
   return STATUS_SUCCESS;
 }
 
-NTSTATUS DoQuery(PDEVICE_OBJECT DeviceObject, PIRP Irp,PIO_STACK_LOCATION Stack)
+NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext)
 {
- NTSTATUS RC=STATUS_SUCCESS;
- long BufferLength = 0;
- PUNICODE_STRING pSearchPattern = NULL;
- FILE_INFORMATION_CLASS FileInformationClass;
- unsigned long FileIndex = 0;
- unsigned char *Buffer = NULL;
- PFILE_NAMES_INFORMATION Buffer0 = NULL;
- PFILE_OBJECT pFileObject = NULL;
- PVfatFCB pFcb;
- VfatFCB tmpFcb;
- PVfatCCB pCcb;
- PDEVICE_EXTENSION DeviceExt;
- WCHAR star[5],*pCharPattern;
- unsigned long OldEntry,OldSector;
-  DeviceExt = DeviceObject->DeviceExtension;
-  // Obtain the callers parameters
-  BufferLength = Stack->Parameters.QueryDirectory.Length;
-  pSearchPattern = Stack->Parameters.QueryDirectory.FileName;
-  FileInformationClass = Stack->Parameters.QueryDirectory.FileInformationClass;
-  FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
-  pFileObject = Stack->FileObject;
-  pCcb =(PVfatCCB)pFileObject->FsContext2;
+  NTSTATUS RC = STATUS_SUCCESS;
+  long BufferLength = 0;
+  PUNICODE_STRING pSearchPattern = NULL;
+  FILE_INFORMATION_CLASS FileInformationClass;
+  unsigned long FileIndex = 0;
+  unsigned char *Buffer = NULL;
+  PFILE_NAMES_INFORMATION Buffer0 = NULL;
+  PVFATFCB pFcb;
+  VFATFCB tmpFcb;
+  PVFATCCB pCcb;
+  WCHAR star[5], *pCharPattern;
+  unsigned long OldEntry, OldSector;
+
+  pCcb = (PVFATCCB) IrpContext->FileObject->FsContext2;
   pFcb = pCcb->pFcb;
-  if(Stack->Flags & SL_RESTART_SCAN)
-  {//FIXME : what is really use of RestartScan ?
-    pCcb->StartEntry=pCcb->StartSector=0;
-  }
-  // determine Buffer for result :
-  if (Irp->MdlAddress) 
-    Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
-  else
-    Buffer = Irp->UserBuffer;
-  DPRINT("Buffer=%x tofind=%w\n",Buffer,pSearchPattern->Buffer);
-  if (pSearchPattern==NULL)
+
+  if (!ExAcquireResourceSharedLite(&pFcb->MainResource, IrpContext->Flags & IRPCONTEXT_CANWAIT))
   {
-    star[0]='*';
-    star[1]=0;
-    pCharPattern=star;
+     return STATUS_PENDING;
   }
-  else pCharPattern=pSearchPattern->Buffer;
-  tmpFcb.ObjectName=tmpFcb.PathName;
-  while(RC==STATUS_SUCCESS && BufferLength >0)
-  {
-    OldSector=pCcb->StartSector;
-    OldEntry=pCcb->StartEntry;
-    if(OldSector)pCcb->StartEntry++;
-    RC=FindFile(DeviceExt,&tmpFcb,pFcb,pCharPattern,&pCcb->StartSector,&pCcb->StartEntry);
-DPRINT("Found %w,RC=%x, sector %x entry %x\n",tmpFcb.ObjectName,RC
- ,pCcb->StartSector,pCcb->StartEntry);
-    if (NT_SUCCESS(RC))
-    {
-      switch(FileInformationClass)
-      {
-       case FileNameInformation:
-        RC=FsdGetFileNameInformation(&tmpFcb
-              ,(PFILE_NAMES_INFORMATION)Buffer,BufferLength);
-        break;
-       case FileDirectoryInformation:
-        RC= FsdGetFileDirectoryInformation(&tmpFcb
-              ,DeviceExt,(PFILE_DIRECTORY_INFORMATION)Buffer,BufferLength);
-        break;
-       case FileFullDirectoryInformation :
-        RC= FsdGetFileFullDirectoryInformation(&tmpFcb
-              ,DeviceExt,(PFILE_FULL_DIRECTORY_INFORMATION)Buffer,BufferLength);
-        break;
-       case FileBothDirectoryInformation :
-        RC=FsdGetFileBothInformation(&tmpFcb
-              ,DeviceExt,(PFILE_BOTH_DIRECTORY_INFORMATION)Buffer,BufferLength);
-        break;
-       default:
-        RC=STATUS_INVALID_INFO_CLASS;
-      }
+
+  // Obtain the callers parameters
+  BufferLength = IrpContext->Stack->Parameters.QueryDirectory.Length;
+  pSearchPattern = IrpContext->Stack->Parameters.QueryDirectory.FileName;
+  FileInformationClass =
+    IrpContext->Stack->Parameters.QueryDirectory.FileInformationClass;
+  FileIndex = IrpContext->Stack->Parameters.QueryDirectory.FileIndex;
+  if (IrpContext->Stack->Flags & SL_RESTART_SCAN)
+    {                          //FIXME : what is really use of RestartScan ?
+      pCcb->StartEntry = pCcb->StartSector = 0;
     }
-    else
+  // determine Buffer for result :
+  if (IrpContext->Irp->MdlAddress)
+    Buffer = MmGetSystemAddressForMdl (IrpContext->Irp->MdlAddress);
+  else
+    Buffer = IrpContext->Irp->UserBuffer;
+  DPRINT ("Buffer=%x tofind=%S\n", Buffer, pSearchPattern->Buffer);
+  if (pSearchPattern == NULL)
     {
-      if(Buffer0) Buffer0->NextEntryOffset=0;
-      break;
+      star[0] = '*';
+      star[1] = 0;
+      pCharPattern = star;
     }
-    if(RC==STATUS_BUFFER_OVERFLOW)
+  else
+    pCharPattern = pSearchPattern->Buffer;
+  tmpFcb.ObjectName = tmpFcb.PathName;
+  while (RC == STATUS_SUCCESS && BufferLength > 0)
     {
-      if(Buffer0) Buffer0->NextEntryOffset=0;
-      pCcb->StartSector=OldSector;
-      pCcb->StartEntry=OldEntry;
-      break;
+      OldSector = pCcb->StartSector;
+      OldEntry = pCcb->StartEntry;
+      if (OldSector)
+       pCcb->StartEntry++;
+      RC =
+       FindFile (IrpContext->DeviceExt, &tmpFcb, pFcb, pCharPattern, &pCcb->StartEntry, NULL);
+    pCcb->StartSector = 1;
+      DPRINT ("Found %S,RC=%x, sector %x entry %x\n", tmpFcb.ObjectName, RC,
+             pCcb->StartSector, pCcb->StartEntry);
+      if (NT_SUCCESS (RC))
+       {
+         switch (FileInformationClass)
+           {
+           case FileNameInformation:
+             RC =
+               VfatGetFileNameInformation (&tmpFcb,
+                                          (PFILE_NAMES_INFORMATION) Buffer,
+                                          BufferLength);
+             break;
+           case FileDirectoryInformation:
+             RC =
+               VfatGetFileDirectoryInformation (&tmpFcb, IrpContext->DeviceExt,
+                                               (PFILE_DIRECTORY_INFORMATION)
+                                               Buffer, BufferLength);
+             break;
+           case FileFullDirectoryInformation:
+             RC =
+               VfatGetFileFullDirectoryInformation (&tmpFcb, IrpContext->DeviceExt,
+                                                   (PFILE_FULL_DIRECTORY_INFORMATION)
+                                                   Buffer, BufferLength);
+             break;
+           case FileBothDirectoryInformation:
+             RC =
+               VfatGetFileBothInformation (&tmpFcb, IrpContext->DeviceExt,
+                                          (PFILE_BOTH_DIRECTORY_INFORMATION)
+                                          Buffer, BufferLength);
+             break;
+           default:
+             RC = STATUS_INVALID_INFO_CLASS;
+           }
+       }
+      else
+       {
+         if (Buffer0)
+           Buffer0->NextEntryOffset = 0;
+         break;
+       }
+      if (RC == STATUS_BUFFER_OVERFLOW)
+       {
+         if (Buffer0)
+           Buffer0->NextEntryOffset = 0;
+         pCcb->StartSector = OldSector;
+         pCcb->StartEntry = OldEntry;
+         break;
+       }
+      Buffer0 = (PFILE_NAMES_INFORMATION) Buffer;
+      Buffer0->FileIndex = FileIndex++;
+      if (IrpContext->Stack->Flags & SL_RETURN_SINGLE_ENTRY)
+       break;
+      BufferLength -= Buffer0->NextEntryOffset;
+      Buffer += Buffer0->NextEntryOffset;
     }
-    Buffer0=(PFILE_NAMES_INFORMATION)Buffer;
-    Buffer0->FileIndex=FileIndex++;
-    if(Stack->Flags & SL_RETURN_SINGLE_ENTRY) break;
-    BufferLength -= Buffer0->NextEntryOffset;
-    Buffer += Buffer0->NextEntryOffset;
+  if (Buffer0)
+    Buffer0->NextEntryOffset = 0;
+  if (FileIndex > 0)
+    RC = STATUS_SUCCESS;
+
+  if (IrpContext->Flags & IRPCONTEXT_CANWAIT)
+  {
+     ExReleaseResourceLite(&pFcb->MainResource);
   }
-  if(Buffer0) Buffer0->NextEntryOffset=0;
-  if(FileIndex>0) return STATUS_SUCCESS;
+
   return RC;
 }
 
 
-NTSTATUS FsdDirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+NTSTATUS VfatDirectoryControl (PVFAT_IRP_CONTEXT IrpContext)
 /*
  * FUNCTION: directory control : read/write directory informations
  */
 {
- NTSTATUS RC = STATUS_SUCCESS;
- PFILE_OBJECT FileObject = NULL;
- PIO_STACK_LOCATION Stack;
-   Stack = IoGetCurrentIrpStackLocation(Irp);
-   CHECKPOINT;
-   FileObject = Stack->FileObject;
-   switch (Stack->MinorFunction)
-   {
+  NTSTATUS RC = STATUS_SUCCESS;
+  CHECKPOINT;
+  switch (IrpContext->MinorFunction)
+    {
     case IRP_MN_QUERY_DIRECTORY:
-      RC=DoQuery(DeviceObject,Irp,Stack);
+      RC = DoQuery (IrpContext);
       break;
     case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
-      DPRINT(" vfat, dir : change\n");
-      RC=STATUS_NOT_IMPLEMENTED;
+      DPRINT (" vfat, dir : change\n");
+      RC = STATUS_NOT_IMPLEMENTED;
       break;
     default:
       // error
-      DbgPrint("unexpected minor function %x in VFAT driver\n",Stack->MinorFunction);
-       RC = STATUS_INVALID_DEVICE_REQUEST;
-       break;
-   }
-   Irp->IoStatus.Status = RC;
-   Irp->IoStatus.Information = 0;
-   
-   IoCompleteRequest(Irp, IO_NO_INCREMENT);
-   return RC;
+      DbgPrint ("unexpected minor function %x in VFAT driver\n",
+               IrpContext->MinorFunction);
+      RC = STATUS_INVALID_DEVICE_REQUEST;
+      break;
+    }
+  if (RC == STATUS_PENDING)
+  {
+     RC = VfatQueueRequest(IrpContext);
+  }
+  else
+  {
+    IrpContext->Irp->IoStatus.Status = RC;
+    IrpContext->Irp->IoStatus.Information = 0;
+    IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT);
+    VfatFreeIrpContext(IrpContext);
+  }
+  return RC;
 }
 
+