Reworked code for handling of asynchonous i/o requests.
[reactos.git] / reactos / drivers / fs / vfat / volume.c
index 6e5c4ee..2044bff 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: volume.c,v 1.3 2000/06/29 23:35:51 dwelch Exp $
+/* $Id: volume.c,v 1.14 2001/11/02 22:47:36 hbirr Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -11,7 +11,6 @@
 
 #include <ddk/ntddk.h>
 #include <wchar.h>
-#include <ddk/cctypes.h>
 
 #define NDEBUG
 #include <debug.h>
 
 /* FUNCTIONS ****************************************************************/
 
-NTSTATUS FsdGetFsVolumeInformation(PFILE_OBJECT FileObject,
-                                   PVFATFCB FCB,
-                                   PDEVICE_OBJECT DeviceObject,
-                                   PFILE_FS_VOLUME_INFORMATION FsVolumeInfo)
+static NTSTATUS
+FsdGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject,
+                         PFILE_FS_VOLUME_INFORMATION FsVolumeInfo,
+                         PULONG BufferLength)
 {
-    DPRINT("FsdGetFsVolumeInformation()\n");
-    DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo);
+  ULONG LabelLength;
 
-    if (!FsVolumeInfo)
-        return(STATUS_SUCCESS);
+  DPRINT("FsdGetFsVolumeInformation()\n");
+  DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo);
+  DPRINT("BufferLength %lu\n", *BufferLength);
 
+  LabelLength = DeviceObject->Vpb->VolumeLabelLength;
 
-    /* valid entries */
-    FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber;
-    FsVolumeInfo->VolumeLabelLength  = DeviceObject->Vpb->VolumeLabelLength;
-    wcscpy (FsVolumeInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabel);
+  DPRINT("Required length %lu\n", (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength*sizeof(WCHAR)));
+  DPRINT("LabelLength %lu\n", LabelLength);
+  DPRINT("Label %S\n", DeviceObject->Vpb->VolumeLabel);
 
-    /* dummy entries */
-    FsVolumeInfo->VolumeCreationTime.QuadPart = 0;
-    FsVolumeInfo->SupportsObjects = FALSE;
+  if (*BufferLength < sizeof(FILE_FS_VOLUME_INFORMATION))
+    return STATUS_INFO_LENGTH_MISMATCH;
 
-    DPRINT("Finished FsdGetFsVolumeInformation()\n");
+  if (*BufferLength < (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength*sizeof(WCHAR)))
+    return STATUS_BUFFER_OVERFLOW;
 
-    return(STATUS_SUCCESS);
+  /* valid entries */
+  FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber;
+  FsVolumeInfo->VolumeLabelLength = LabelLength * sizeof (WCHAR);
+  wcscpy(FsVolumeInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabel);
+
+  /* dummy entries */
+  FsVolumeInfo->VolumeCreationTime.QuadPart = 0;
+  FsVolumeInfo->SupportsObjects = FALSE;
+
+  DPRINT("Finished FsdGetFsVolumeInformation()\n");
+
+  *BufferLength -= (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength * sizeof(WCHAR));
+
+  DPRINT("BufferLength %lu\n", *BufferLength);
+
+  return(STATUS_SUCCESS);
 }
 
 
-NTSTATUS FsdGetFsAttributeInformation(PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo)
+static NTSTATUS
+FsdGetFsAttributeInformation(PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo,
+                            PULONG BufferLength)
 {
-    DPRINT("FsdGetFsAttributeInformation()\n");
-    DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo);
+  DPRINT("FsdGetFsAttributeInformation()\n");
+  DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo);
+  DPRINT("BufferLength %lu\n", *BufferLength);
+  DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 6));
+
+  if (*BufferLength < sizeof (FILE_FS_ATTRIBUTE_INFORMATION))
+    return STATUS_INFO_LENGTH_MISMATCH;
+
+  if (*BufferLength < (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 6))
+    return STATUS_BUFFER_OVERFLOW;
 
-    if (!FsAttributeInfo)
-        return(STATUS_SUCCESS);
+  FsAttributeInfo->FileSystemAttributes =
+    FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK;
+  FsAttributeInfo->MaximumComponentNameLength = 255;
+  FsAttributeInfo->FileSystemNameLength = 6;
+  wcscpy(FsAttributeInfo->FileSystemName, L"FAT");
 
-    FsAttributeInfo->FileSystemAttributes = FS_CASE_IS_PRESERVED;
-    FsAttributeInfo->MaximumComponentNameLength = 255;
-    FsAttributeInfo->FileSystemNameLength = 3;
-    wcscpy (FsAttributeInfo->FileSystemName, L"FAT");
+  DPRINT("Finished FsdGetFsAttributeInformation()\n");
 
-    DPRINT("Finished FsdGetFsAttributeInformation()\n");
+  *BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 6);
+  DPRINT("BufferLength %lu\n", *BufferLength);
 
-    return(STATUS_SUCCESS);
+  return(STATUS_SUCCESS);
 }
 
-NTSTATUS FsdGetFsSizeInformation(PDEVICE_OBJECT DeviceObject,
-                                 PFILE_FS_SIZE_INFORMATION FsSizeInfo)
+
+static NTSTATUS
+FsdGetFsSizeInformation(PDEVICE_OBJECT DeviceObject,
+                       PFILE_FS_SIZE_INFORMATION FsSizeInfo,
+                       PULONG BufferLength)
 {
-    PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
+  PDEVICE_EXTENSION DeviceExt;
+  NTSTATUS Status;
+
+  DPRINT("FsdGetFsSizeInformation()\n");
+  DPRINT("FsSizeInfo = %p\n", FsSizeInfo);
 
-    DPRINT("FsdGetFsSizeInformation()\n");
-    DPRINT("FsSizeInfo = %p\n", FsSizeInfo);
+  if (*BufferLength < sizeof(FILE_FS_SIZE_INFORMATION))
+    return(STATUS_BUFFER_OVERFLOW);
 
-    if (!FsSizeInfo)
-        return(STATUS_SUCCESS);
+  DeviceExt = DeviceObject->DeviceExtension;
 
-    if (DeviceExt->FatType == FAT32)
+  if (DeviceExt->FatType == FAT32)
     {
-        struct _BootSector32 *BootSect = (struct _BootSector32 *)DeviceExt->Boot;
+      struct _BootSector32 *BootSect =
+       (struct _BootSector32 *) DeviceExt->Boot;
 
-        if (BootSect->Sectors)
-            FsSizeInfo->TotalAllocationUnits.QuadPart = BootSect->Sectors;
-        else
-            FsSizeInfo->TotalAllocationUnits.QuadPart = BootSect->SectorsHuge;
+      FsSizeInfo->TotalAllocationUnits.QuadPart = ((BootSect->Sectors ? BootSect->Sectors : BootSect->SectorsHuge)-DeviceExt->dataStart)/BootSect->SectorsPerCluster;
 
-        FsSizeInfo->AvailableAllocationUnits.QuadPart =
-            FAT32CountAvailableClusters(DeviceExt);
+      Status = FAT32CountAvailableClusters(DeviceExt,
+                                          &FsSizeInfo->AvailableAllocationUnits);
 
-        FsSizeInfo->SectorsPerAllocationUnit = BootSect->SectorsPerCluster;
-        FsSizeInfo->BytesPerSector = BootSect->BytesPerSector;
+      FsSizeInfo->SectorsPerAllocationUnit = BootSect->SectorsPerCluster;
+      FsSizeInfo->BytesPerSector = BootSect->BytesPerSector;
     }
-    else
+  else
     {
-        struct _BootSector *BootSect = (struct _BootSector *)DeviceExt->Boot;
-
-        if (BootSect->Sectors)
-            FsSizeInfo->TotalAllocationUnits.QuadPart = BootSect->Sectors;
-        else
-            FsSizeInfo->TotalAllocationUnits.QuadPart = BootSect->SectorsHuge;
-
-        if (DeviceExt->FatType == FAT16)
-            FsSizeInfo->AvailableAllocationUnits.QuadPart =
-                FAT16CountAvailableClusters(DeviceExt);
-        else
-            FsSizeInfo->AvailableAllocationUnits.QuadPart =
-                FAT12CountAvailableClusters(DeviceExt);
-
-        FsSizeInfo->SectorsPerAllocationUnit = BootSect->SectorsPerCluster;
-        FsSizeInfo->BytesPerSector = BootSect->BytesPerSector;
+      struct _BootSector *BootSect = (struct _BootSector *) DeviceExt->Boot;
+
+      FsSizeInfo->TotalAllocationUnits.QuadPart = ((BootSect->Sectors ? BootSect->Sectors : BootSect->SectorsHuge)-DeviceExt->dataStart)/BootSect->SectorsPerCluster;
+
+      if (DeviceExt->FatType == FAT16)
+       Status = FAT16CountAvailableClusters(DeviceExt,
+                                            &FsSizeInfo->AvailableAllocationUnits);
+      else
+       Status = FAT12CountAvailableClusters(DeviceExt,
+                                            &FsSizeInfo->AvailableAllocationUnits);
+      FsSizeInfo->SectorsPerAllocationUnit = BootSect->SectorsPerCluster;
+      FsSizeInfo->BytesPerSector = BootSect->BytesPerSector;
     }
 
-    DPRINT("Finished FsdGetFsSizeInformation()\n");
+  DPRINT("Finished FsdGetFsSizeInformation()\n");
+  if (NT_SUCCESS(Status))
+    *BufferLength -= sizeof(FILE_FS_SIZE_INFORMATION);
+
+  return(Status);
+}
+
 
-    return(STATUS_SUCCESS);
+static NTSTATUS
+FsdGetFsDeviceInformation(PFILE_FS_DEVICE_INFORMATION FsDeviceInfo,
+                         PULONG BufferLength)
+{
+  DPRINT("FsdGetFsDeviceInformation()\n");
+  DPRINT("FsDeviceInfo = %p\n", FsDeviceInfo);
+  DPRINT("BufferLength %lu\n", *BufferLength);
+  DPRINT("Required length %lu\n", sizeof(FILE_FS_DEVICE_INFORMATION));
+
+  if (*BufferLength < sizeof(FILE_FS_DEVICE_INFORMATION))
+    return(STATUS_BUFFER_OVERFLOW);
+
+  FsDeviceInfo->DeviceType = FILE_DEVICE_DISK;
+  FsDeviceInfo->Characteristics = 0; /* FIXME: fix this !! */
+
+  DPRINT("FsdGetFsDeviceInformation() finished.\n");
+
+  *BufferLength -= sizeof(FILE_FS_DEVICE_INFORMATION);
+  DPRINT("BufferLength %lu\n", *BufferLength);
+
+  return(STATUS_SUCCESS);
 }
 
 
-NTSTATUS VfatQueryVolumeInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+static NTSTATUS
+FsdSetFsLabelInformation(PDEVICE_OBJECT DeviceObject,
+                        PFILE_FS_LABEL_INFORMATION FsLabelInfo)
+{
+  DPRINT("FsdSetFsLabelInformation()\n");
+
+  return(STATUS_NOT_IMPLEMENTED);
+}
+
+
+NTSTATUS VfatQueryVolumeInformation(PVFAT_IRP_CONTEXT IrpContext)
 /*
- * FUNCTION: Retrieve the specified file information
+ * FUNCTION: Retrieve the specified volume information
  */
 {
-   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
-   FILE_INFORMATION_CLASS FileInformationClass =
-     Stack->Parameters.QueryVolume.FileInformationClass;
-   PFILE_OBJECT FileObject = NULL;
-   PVFATFCB FCB = NULL;
-//   PVfatCCB CCB = NULL;
-
-   NTSTATUS RC = STATUS_SUCCESS;
-   void *SystemBuffer;
-
-   /* PRECONDITION */
-   assert(DeviceObject != NULL);
-   assert(Irp != NULL);
-
-   DPRINT("FsdQueryVolumeInformation(DeviceObject %x, Irp %x)\n",
-          DeviceObject,Irp);
-
-   /* INITIALIZATION */
-   Stack = IoGetCurrentIrpStackLocation(Irp);
-   FileInformationClass = Stack->Parameters.QueryVolume.FileInformationClass;
-   FileObject = Stack->FileObject;
-//   CCB = (PVfatCCB)(FileObject->FsContext2);
-//   FCB = CCB->Buffer; // Should be CCB->FCB???
-   FCB = ((PVFATCCB)(FileObject->FsContext2))->pFcb;
-
-  // FIXME : determine Buffer for result :
-  if (Irp->MdlAddress) 
-    SystemBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
+  FS_INFORMATION_CLASS FsInformationClass;
+  NTSTATUS RC = STATUS_SUCCESS;
+  PVOID SystemBuffer;
+  ULONG BufferLength;
+
+  /* PRECONDITION */
+  assert(IrpContext);
+
+  DPRINT("VfatQueryVolumeInformation(IrpContext %x)\n", IrpContext);
+
+  if (!ExAcquireResourceSharedLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource, IrpContext->Flags & IRPCONTEXT_CANWAIT))
+  {
+     return VfatQueueRequest (IrpContext);
+  }
+
+  /* INITIALIZATION */
+  FsInformationClass = IrpContext->Stack->Parameters.QueryVolume.FsInformationClass;
+  BufferLength = IrpContext->Stack->Parameters.QueryVolume.Length;
+  SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
+
+
+  DPRINT ("FsInformationClass %d\n", FsInformationClass);
+  DPRINT ("SystemBuffer %x\n", SystemBuffer);
+
+  switch (FsInformationClass)
+    {
+    case FileFsVolumeInformation:
+      RC = FsdGetFsVolumeInformation(IrpContext->DeviceObject,
+                                    SystemBuffer,
+                                    &BufferLength);
+      break;
+
+    case FileFsAttributeInformation:
+      RC = FsdGetFsAttributeInformation(SystemBuffer,
+                                       &BufferLength);
+      break;
+
+    case FileFsSizeInformation:
+      RC = FsdGetFsSizeInformation(IrpContext->DeviceObject,
+                                  SystemBuffer,
+                                  &BufferLength);
+      break;
+
+    case FileFsDeviceInformation:
+      RC = FsdGetFsDeviceInformation(SystemBuffer,
+                                    &BufferLength);
+      break;
+
+    default:
+      RC = STATUS_NOT_SUPPORTED;
+    }
+
+  ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource);
+  IrpContext->Irp->IoStatus.Status = RC;
+  if (NT_SUCCESS(RC))
+    IrpContext->Irp->IoStatus.Information =
+      IrpContext->Stack->Parameters.QueryVolume.Length - BufferLength;
   else
-    SystemBuffer = Irp->UserBuffer;
-//   SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
-
-   DPRINT("FileInformationClass %d\n",FileInformationClass);
-   DPRINT("SystemBuffer %x\n",SystemBuffer);
-
-   switch (FileInformationClass)
-   {
-      case FileFsVolumeInformation:
-         RC = FsdGetFsVolumeInformation(FileObject,
-                                        FCB,
-                                        DeviceObject,
-                                        SystemBuffer);
-         break;
-
-      case FileFsAttributeInformation:
-         RC = FsdGetFsAttributeInformation(SystemBuffer);
-         break;
-
-      case FileFsSizeInformation:
-         RC = FsdGetFsSizeInformation(DeviceObject, SystemBuffer);
-         break;
-
-      default:
-         RC=STATUS_NOT_IMPLEMENTED;
-   }
-
-   Irp->IoStatus.Status = RC;
-   Irp->IoStatus.Information = 0;
-   IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-   return RC;
+    IrpContext->Irp->IoStatus.Information = 0;
+  IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
+  VfatFreeIrpContext(IrpContext);
+
+  return RC;
 }
 
 
+NTSTATUS VfatSetVolumeInformation(PVFAT_IRP_CONTEXT IrpContext)
+/*
+ * FUNCTION: Set the specified volume information
+ */
+{
+  FS_INFORMATION_CLASS FsInformationClass;
+  NTSTATUS Status = STATUS_SUCCESS;
+  PVOID SystemBuffer;
+  ULONG BufferLength;
+
+  /* PRECONDITION */
+  assert(IrpContext);
+
+  DPRINT1("VfatSetVolumeInformation(IrpContext %x)\n", IrpContext);
+
+  if (!ExAcquireResourceExclusiveLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource, IrpContext->Flags & IRPCONTEXT_CANWAIT))
+  {
+     return VfatQueueRequest (IrpContext);
+  }
+
+  FsInformationClass = IrpContext->Stack->Parameters.SetVolume.FsInformationClass;
+  BufferLength = IrpContext->Stack->Parameters.SetVolume.Length;
+  SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
+
+  DPRINT1("FsInformationClass %d\n", FsInformationClass);
+  DPRINT1("BufferLength %d\n", BufferLength);
+  DPRINT1("SystemBuffer %x\n", SystemBuffer);
+
+  switch(FsInformationClass)
+    {
+    case FileFsLabelInformation:
+      Status = FsdSetFsLabelInformation(IrpContext->DeviceObject,
+                                       SystemBuffer);
+      break;
+
+    default:
+      Status = STATUS_NOT_SUPPORTED;
+    }
+
+  ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource);
+  IrpContext->Irp->IoStatus.Status = Status;
+  IrpContext->Irp->IoStatus.Information = 0;
+  IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
+  VfatFreeIrpContext(IrpContext);
+
+  return(Status);
+}
+
+/* EOF */