Reworked code for handling of asynchonous i/o requests.
[reactos.git] / reactos / drivers / fs / vfat / finfo.c
index ae51f7e..cb4c67b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: finfo.c,v 1.8 2001/06/12 12:35:42 ekohl Exp $
+/* $Id: finfo.c,v 1.11 2001/11/02 22:47:36 hbirr Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -30,7 +30,6 @@ VfatGetStandardInformation(PVFATFCB FCB,
  */
 {
   PDEVICE_EXTENSION DeviceExtension;
-  unsigned long AllocSize;
 
   if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION))
     return STATUS_BUFFER_OVERFLOW;
@@ -45,25 +44,12 @@ VfatGetStandardInformation(PVFATFCB FCB,
   RtlZeroMemory(StandardInfo,
                sizeof(FILE_STANDARD_INFORMATION));
 
-  /* Make allocsize a rounded up multiple of BytesPerCluster */
-  AllocSize = ((FCB->entry.FileSize + DeviceExtension->BytesPerCluster - 1) /
-              DeviceExtension->BytesPerCluster) *
-    DeviceExtension->BytesPerCluster;
-
-  StandardInfo->AllocationSize = RtlConvertUlongToLargeInteger (AllocSize);
-  StandardInfo->EndOfFile =
-    RtlConvertUlongToLargeInteger (FCB->entry.FileSize);
+  StandardInfo->AllocationSize = FCB->RFCB.AllocationSize;
+  StandardInfo->EndOfFile = FCB->RFCB.FileSize;
   StandardInfo->NumberOfLinks = 0;
-  StandardInfo->DeletePending = FALSE;
-  if ((FCB->entry.Attrib & 0x10) > 0)
-    {
-      StandardInfo->Directory = TRUE;
-    }
-  else
-    {
-      StandardInfo->Directory = FALSE;
-    }
-  
+  StandardInfo->DeletePending = FCB->Flags & FCB_DELETE_PENDING ? TRUE : FALSE;
+  StandardInfo->Directory = FCB->entry.Attrib & 0x10 ? TRUE : FALSE;
+
   *BufferLength -= sizeof(FILE_STANDARD_INFORMATION);
   return(STATUS_SUCCESS);
 }
@@ -145,11 +131,65 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
                              PDEVICE_OBJECT DeviceObject,
                              PFILE_DISPOSITION_INFORMATION DispositionInfo)
 {
+  KIRQL oldIrql;
+  VFATFCB tmpFcb;
+  WCHAR star[2];
+  ULONG Index;
+  NTSTATUS Status = STATUS_SUCCESS;
+  int count;
+
+  PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
+
   DPRINT ("FsdSetDispositionInformation()\n");
 
-  FileObject->DeletePending = DispositionInfo->DoDeleteFile;
+  assert (DeviceExt != NULL);
+  assert (DeviceExt->BytesPerCluster != 0);
+  assert (FCB != NULL);
 
-  return (STATUS_SUCCESS);
+  if (!wcscmp(FCB->PathName, L"\\") || !wcscmp(FCB->ObjectName, L"..")
+    || !wcscmp(FCB->ObjectName, L"."))
+  {
+    // we cannot delete a '.', '..' or the root directory
+    return STATUS_ACCESS_DENIED;
+  }
+  if (DispositionInfo->DoDeleteFile)
+  {
+    KeAcquireSpinLock (&DeviceExt->FcbListLock, &oldIrql);
+    count = FCB->RefCount;
+    if (FCB->RefCount > 1)
+      Status = STATUS_ACCESS_DENIED;
+    else
+    {
+      FCB->Flags |= FCB_DELETE_PENDING;
+      FileObject->DeletePending = TRUE;
+    }
+    KeReleaseSpinLock(&DeviceExt->FcbListLock, oldIrql);
+    DPRINT("RefCount:%d\n", count);
+    if (NT_SUCCESS(Status) && vfatFCBIsDirectory(DeviceExt, FCB))
+    {
+      memset (&tmpFcb, 0, sizeof(VFATFCB));
+      tmpFcb.ObjectName = tmpFcb.PathName;
+      star[0] = L'*';
+      star[1] = 0;
+      // skip '.' and '..', start by 2
+      Index = 2;
+      Status = FindFile (DeviceExt, &tmpFcb, FCB, star, &Index, NULL);
+      if (NT_SUCCESS(Status))
+      {
+        DPRINT1("found: \'%S\'\n", tmpFcb.PathName);
+        Status = STATUS_DIRECTORY_NOT_EMPTY;
+        FCB->Flags &= ~FCB_DELETE_PENDING;
+        FileObject->DeletePending = FALSE;
+      }
+      else
+      {
+        Status = STATUS_SUCCESS;
+      }
+    }
+  }
+  else
+    FileObject->DeletePending = FALSE;
+  return Status;
 }
 
 static NTSTATUS
@@ -182,70 +222,89 @@ VfatGetNameInformation(PFILE_OBJECT FileObject,
   return STATUS_SUCCESS;
 }
 
+static NTSTATUS
+VfatGetInternalInformation(PVFATFCB Fcb,
+                          PFILE_INTERNAL_INFORMATION InternalInfo,
+                          PULONG BufferLength)
+{
+  assert (InternalInfo);
+  assert (Fcb);
+
+  if (*BufferLength < sizeof(FILE_INTERNAL_INFORMATION))
+    return STATUS_BUFFER_OVERFLOW;
+  // FIXME: get a real index, that can be used in a create operation
+  InternalInfo->IndexNumber.QuadPart = 0;
+  *BufferLength -= sizeof(FILE_INTERNAL_INFORMATION);
+  return STATUS_SUCCESS;
+}
+
 
 
-NTSTATUS STDCALL
-VfatQueryInformation(PDEVICE_OBJECT DeviceObject,
-                    PIRP Irp)
+NTSTATUS VfatQueryInformation(PVFAT_IRP_CONTEXT IrpContext)
 /*
  * FUNCTION: Retrieve the specified file information
  */
 {
-  PIO_STACK_LOCATION Stack;
   FILE_INFORMATION_CLASS FileInformationClass;
-  PFILE_OBJECT FileObject = NULL;
   PVFATFCB FCB = NULL;
-//   PVFATCCB CCB = NULL;
 
   NTSTATUS RC = STATUS_SUCCESS;
   PVOID SystemBuffer;
   ULONG BufferLength;
 
   /* PRECONDITION */
-  assert (DeviceObject != NULL);
-  assert (Irp != NULL);
+  assert (IrpContext);
 
   /* INITIALIZATION */
-  Stack = IoGetCurrentIrpStackLocation (Irp);
-  FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass;
-  FileObject = Stack->FileObject;
-//   CCB = (PVFATCCB)(FileObject->FsContext2);
-//   FCB = CCB->Buffer; // Should be CCB->FCB???
-  FCB = ((PVFATCCB) (FileObject->FsContext2))->pFcb;
-
-  SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
-  BufferLength = Stack->Parameters.QueryFile.Length;
-  
+  FileInformationClass = IrpContext->Stack->Parameters.QueryFile.FileInformationClass;
+  FCB = ((PVFATCCB) IrpContext->FileObject->FsContext2)->pFcb;
+
+  SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
+  BufferLength = IrpContext->Stack->Parameters.QueryFile.Length;
+
+  if (!(FCB->Flags & FCB_IS_PAGE_FILE))
+  {
+     if (!ExAcquireResourceSharedLite(&FCB->MainResource, IrpContext->Flags & IRPCONTEXT_CANWAIT))
+     {
+        return VfatQueueRequest (IrpContext);
+     }
+  }
+
+
   switch (FileInformationClass)
     {
     case FileStandardInformation:
       RC = VfatGetStandardInformation(FCB,
-                                     DeviceObject,
+                                     IrpContext->DeviceObject,
                                      SystemBuffer,
                                      &BufferLength);
       break;
     case FilePositionInformation:
-      RC = VfatGetPositionInformation(FileObject,
+      RC = VfatGetPositionInformation(IrpContext->FileObject,
                                      FCB,
-                                     DeviceObject,
+                                     IrpContext->DeviceObject,
                                      SystemBuffer,
                                      &BufferLength);
       break;
     case FileBasicInformation:
-      RC = VfatGetBasicInformation(FileObject,
+      RC = VfatGetBasicInformation(IrpContext->FileObject,
                                   FCB,
-                                  DeviceObject,
+                                  IrpContext->DeviceObject,
                                   SystemBuffer,
                                   &BufferLength);
       break;
     case FileNameInformation:
-      RC = VfatGetNameInformation(FileObject,
+      RC = VfatGetNameInformation(IrpContext->FileObject,
                                  FCB,
-                                 DeviceObject,
+                                 IrpContext->DeviceObject,
                                  SystemBuffer,
                                  &BufferLength);
       break;
     case FileInternalInformation:
+      RC = VfatGetInternalInformation(FCB,
+                                     SystemBuffer,
+                                     &BufferLength);
+      break;
     case FileAlternateNameInformation:
     case FileAllInformation:
       RC = STATUS_NOT_IMPLEMENTED;
@@ -254,61 +313,72 @@ VfatQueryInformation(PDEVICE_OBJECT DeviceObject,
       RC = STATUS_NOT_SUPPORTED;
     }
 
-  Irp->IoStatus.Status = RC;
+  if (!(FCB->Flags & FCB_IS_PAGE_FILE))
+  {
+     ExReleaseResourceLite(&FCB->MainResource);
+  }
+  IrpContext->Irp->IoStatus.Status = RC;
   if (NT_SUCCESS(RC))
-    Irp->IoStatus.Information =
-      Stack->Parameters.QueryFile.Length - BufferLength;
+    IrpContext->Irp->IoStatus.Information =
+      IrpContext->Stack->Parameters.QueryFile.Length - BufferLength;
   else
-    Irp->IoStatus.Information = 0;
-  IoCompleteRequest(Irp,
-                   IO_NO_INCREMENT);
+    IrpContext->Irp->IoStatus.Information = 0;
+  IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
+  VfatFreeIrpContext(IrpContext);
 
   return RC;
 }
 
-NTSTATUS STDCALL
-VfatSetInformation(PDEVICE_OBJECT DeviceObject,
-                  PIRP Irp)
+NTSTATUS VfatSetInformation(PVFAT_IRP_CONTEXT IrpContext)
 /*
  * FUNCTION: Retrieve the specified file information
  */
 {
-  PIO_STACK_LOCATION Stack;
   FILE_INFORMATION_CLASS FileInformationClass;
-  PFILE_OBJECT FileObject = NULL;
   PVFATFCB FCB = NULL;
-//   PVFATCCB CCB = NULL;
   NTSTATUS RC = STATUS_SUCCESS;
   PVOID SystemBuffer;
 
   /* PRECONDITION */
-  assert(DeviceObject != NULL);
-  assert(Irp != NULL);
+  assert(IrpContext);
 
-  DPRINT("VfatSetInformation(DeviceObject %x, Irp %x)\n", DeviceObject, Irp);
+  DPRINT("VfatSetInformation(IrpContext %x)\n", IrpContext);
 
   /* INITIALIZATION */
-  Stack = IoGetCurrentIrpStackLocation (Irp);
-  FileInformationClass = Stack->Parameters.SetFile.FileInformationClass;
-  FileObject = Stack->FileObject;
-  FCB = ((PVFATCCB) (FileObject->FsContext2))->pFcb;
-  SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
+  FileInformationClass = IrpContext->Stack->Parameters.SetFile.FileInformationClass;
+  FCB = ((PVFATCCB) IrpContext->FileObject->FsContext2)->pFcb;
+  SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
 
   DPRINT("FileInformationClass %d\n", FileInformationClass);
   DPRINT("SystemBuffer %x\n", SystemBuffer);
 
+  if (FCB->Flags & FCB_IS_PAGE_FILE)
+  {
+     if (!ExAcquireResourceExclusiveLite(&FCB->PagingIoResource, IrpContext->Flags & IRPCONTEXT_CANWAIT))
+     {
+        return VfatQueueRequest (IrpContext);
+     }
+  }
+  else
+  {
+     if (!ExAcquireResourceExclusiveLite(&FCB->MainResource, IrpContext->Flags & IRPCONTEXT_CANWAIT))
+     {
+        return VfatQueueRequest (IrpContext);
+     }
+  }
+
   switch (FileInformationClass)
     {
     case FilePositionInformation:
-      RC = VfatSetPositionInformation(FileObject,
+      RC = VfatSetPositionInformation(IrpContext->FileObject,
                                      FCB,
-                                     DeviceObject,
+                                     IrpContext->DeviceObject,
                                      SystemBuffer);
       break;
     case FileDispositionInformation:
-      RC = VfatSetDispositionInformation(FileObject,
+      RC = VfatSetDispositionInformation(IrpContext->FileObject,
                                         FCB,
-                                        DeviceObject,
+                                        IrpContext->DeviceObject,
                                         SystemBuffer);
       break;
     case FileBasicInformation:
@@ -321,10 +391,19 @@ VfatSetInformation(PDEVICE_OBJECT DeviceObject,
       RC = STATUS_NOT_SUPPORTED;
     }
 
-  Irp->IoStatus.Status = RC;
-  Irp->IoStatus.Information = 0;
-  IoCompleteRequest(Irp,
-                   IO_NO_INCREMENT);
+  if (FCB->Flags & FCB_IS_PAGE_FILE)
+  {
+     ExReleaseResourceLite(&FCB->PagingIoResource);
+  }
+  else
+  {
+     ExReleaseResourceLite(&FCB->MainResource);
+  }
+
+  IrpContext->Irp->IoStatus.Status = RC;
+  IrpContext->Irp->IoStatus.Information = 0;
+  IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
+  VfatFreeIrpContext(IrpContext);
 
   return RC;
 }