Reworked code for handling of asynchonous i/o requests.
[reactos.git] / reactos / drivers / fs / vfat / dir.c
index 74edb30..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
@@ -99,11 +101,11 @@ VfatGetFileNameInformation (PVFATFCB pFcb,
 {
   ULONG Length;
   Length = vfat_wstrlen (pFcb->ObjectName);
-  if ((sizeof (FILE_DIRECTORY_INFORMATION) + Length) > BufferLength)
+  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);
+    DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + Length * sizeof(WCHAR));
   memcpy (pInfo->FileName, pFcb->ObjectName,
          sizeof (WCHAR) * (pInfo->FileNameLength));
   return STATUS_SUCCESS;
@@ -118,11 +120,11 @@ VfatGetFileDirectoryInformation (PVFATFCB pFcb,
   unsigned long long AllocSize;
   ULONG Length;
   Length = vfat_wstrlen (pFcb->ObjectName);
-  if ((sizeof (FILE_DIRECTORY_INFORMATION) + Length) > BufferLength)
+  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);
+    DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + Length * sizeof(WCHAR));
   memcpy (pInfo->FileName, pFcb->ObjectName,
          sizeof (WCHAR) * (pInfo->FileNameLength));
 //      pInfo->FileIndex=;
@@ -153,11 +155,11 @@ VfatGetFileFullDirectoryInformation (PVFATFCB pFcb,
   unsigned long long AllocSize;
   ULONG Length;
   Length = vfat_wstrlen (pFcb->ObjectName);
-  if ((sizeof (FILE_FULL_DIRECTORY_INFORMATION) + Length) > BufferLength)
+  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);
+    DWORD_ROUND_UP (sizeof (FILE_FULL_DIRECTORY_INFORMATION) + Length * sizeof(WCHAR));
   memcpy (pInfo->FileName, pFcb->ObjectName,
          sizeof (WCHAR) * (pInfo->FileNameLength));
 //      pInfo->FileIndex=;
@@ -189,11 +191,11 @@ VfatGetFileBothInformation (PVFATFCB pFcb,
   unsigned long long AllocSize;
   ULONG Length;
   Length = vfat_wstrlen (pFcb->ObjectName);
-  if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength)
+  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);
+    DWORD_ROUND_UP (sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length * sizeof(WCHAR));
   memcpy (pInfo->FileName, pFcb->ObjectName,
          sizeof (WCHAR) * (pInfo->FileNameLength));
 //      pInfo->FileIndex=;
@@ -223,8 +225,7 @@ VfatGetFileBothInformation (PVFATFCB pFcb,
   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;
@@ -233,32 +234,35 @@ DoQuery (PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION Stack)
   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;
+
+  pCcb = (PVFATCCB) IrpContext->FileObject->FsContext2;
+  pFcb = pCcb->pFcb;
+
+  if (!ExAcquireResourceSharedLite(&pFcb->MainResource, IrpContext->Flags & IRPCONTEXT_CANWAIT))
+  {
+     return STATUS_PENDING;
+  }
+
   // Obtain the callers parameters
-  BufferLength = Stack->Parameters.QueryDirectory.Length;
-  pSearchPattern = Stack->Parameters.QueryDirectory.FileName;
+  BufferLength = IrpContext->Stack->Parameters.QueryDirectory.Length;
+  pSearchPattern = IrpContext->Stack->Parameters.QueryDirectory.FileName;
   FileInformationClass =
-    Stack->Parameters.QueryDirectory.FileInformationClass;
-  FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
-  pFileObject = Stack->FileObject;
-  pCcb = (PVFATCCB) pFileObject->FsContext2;
-  pFcb = pCcb->pFcb;
-  if (Stack->Flags & SL_RESTART_SCAN)
+    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;
     }
   // determine Buffer for result :
-  if (Irp->MdlAddress)
-    Buffer = MmGetSystemAddressForMdl (Irp->MdlAddress);
+  if (IrpContext->Irp->MdlAddress)
+    Buffer = MmGetSystemAddressForMdl (IrpContext->Irp->MdlAddress);
   else
-    Buffer = Irp->UserBuffer;
+    Buffer = IrpContext->Irp->UserBuffer;
   DPRINT ("Buffer=%x tofind=%S\n", Buffer, pSearchPattern->Buffer);
   if (pSearchPattern == NULL)
     {
@@ -276,8 +280,8 @@ DoQuery (PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION Stack)
       if (OldSector)
        pCcb->StartEntry++;
       RC =
-       FindFile (DeviceExt, &tmpFcb, pFcb, pCharPattern, &pCcb->StartSector,
-                 &pCcb->StartEntry);
+       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))
@@ -292,19 +296,19 @@ DoQuery (PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION Stack)
              break;
            case FileDirectoryInformation:
              RC =
-               VfatGetFileDirectoryInformation (&tmpFcb, DeviceExt,
+               VfatGetFileDirectoryInformation (&tmpFcb, IrpContext->DeviceExt,
                                                (PFILE_DIRECTORY_INFORMATION)
                                                Buffer, BufferLength);
              break;
            case FileFullDirectoryInformation:
              RC =
-               VfatGetFileFullDirectoryInformation (&tmpFcb, DeviceExt,
+               VfatGetFileFullDirectoryInformation (&tmpFcb, IrpContext->DeviceExt,
                                                    (PFILE_FULL_DIRECTORY_INFORMATION)
                                                    Buffer, BufferLength);
              break;
            case FileBothDirectoryInformation:
              RC =
-               VfatGetFileBothInformation (&tmpFcb, DeviceExt,
+               VfatGetFileBothInformation (&tmpFcb, IrpContext->DeviceExt,
                                           (PFILE_BOTH_DIRECTORY_INFORMATION)
                                           Buffer, BufferLength);
              break;
@@ -328,7 +332,7 @@ DoQuery (PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION Stack)
        }
       Buffer0 = (PFILE_NAMES_INFORMATION) Buffer;
       Buffer0->FileIndex = FileIndex++;
-      if (Stack->Flags & SL_RETURN_SINGLE_ENTRY)
+      if (IrpContext->Stack->Flags & SL_RETURN_SINGLE_ENTRY)
        break;
       BufferLength -= Buffer0->NextEntryOffset;
       Buffer += Buffer0->NextEntryOffset;
@@ -336,27 +340,28 @@ DoQuery (PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION Stack)
   if (Buffer0)
     Buffer0->NextEntryOffset = 0;
   if (FileIndex > 0)
-    return STATUS_SUCCESS;
+    RC = STATUS_SUCCESS;
+
+  if (IrpContext->Flags & IRPCONTEXT_CANWAIT)
+  {
+     ExReleaseResourceLite(&pFcb->MainResource);
+  }
+
   return RC;
 }
 
 
-NTSTATUS STDCALL
-VfatDirectoryControl (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)
+  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");
@@ -365,14 +370,21 @@ VfatDirectoryControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
     default:
       // error
       DbgPrint ("unexpected minor function %x in VFAT driver\n",
-               Stack->MinorFunction);
+               IrpContext->MinorFunction);
       RC = STATUS_INVALID_DEVICE_REQUEST;
       break;
     }
-  Irp->IoStatus.Status = RC;
-  Irp->IoStatus.Information = 0;
-
-  IoCompleteRequest (Irp, IO_NO_INCREMENT);
+  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;
 }