Enabled caching for FAT32 partitions.
[reactos.git] / reactos / drivers / fs / vfat / volume.c
index 03b05de..907b9c2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: volume.c,v 1.1 1999/12/11 21:14:49 dwelch Exp $
+/* $Id: volume.c,v 1.11 2001/07/20 08:00:21 ekohl Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
 
 /* INCLUDES *****************************************************************/
 
-#include <wchar.h>
-#include <internal/string.h>
 #include <ddk/ntddk.h>
-#include <ddk/cctypes.h>
+#include <wchar.h>
 
 #define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
 
 #include "vfat.h"
 
 /* FUNCTIONS ****************************************************************/
 
-NTSTATUS FsdGetFsVolumeInformation(PFILE_OBJECT FileObject,
-                                   PVFATFCB FCB,
-                                   PDEVICE_OBJECT DeviceObject,
-                                   PFILE_FS_VOLUME_INFORMATION FsVolumeInfo)
+static NTSTATUS
+FsdGetFsVolumeInformation(PFILE_OBJECT FileObject,
+                         PVFATFCB FCB,
+                         PDEVICE_OBJECT DeviceObject,
+                         PFILE_FS_VOLUME_INFORMATION FsVolumeInfo,
+                         PULONG BufferLength)
 {
-    DPRINT("FsdGetFsVolumeInformation()\n");
-    DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo);
-
-    if (!FsVolumeInfo)
-        return(STATUS_SUCCESS);
-
-
-    /* valid entries */
-    FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber;
-    FsVolumeInfo->VolumeLabelLength  = DeviceObject->Vpb->VolumeLabelLength;
-    wcscpy (FsVolumeInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabel);
-
-    /* dummy entries */
-    FsVolumeInfo->VolumeCreationTime.QuadPart = 0;
-    FsVolumeInfo->SupportsObjects = FALSE;
+  ULONG LabelLength;
+  
+  DPRINT("FsdGetFsVolumeInformation()\n");
+  DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo);
+  DPRINT("BufferLength %lu\n", *BufferLength);
+  DPRINT("Required length %lu\n", (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength));
+  
+  LabelLength = DeviceObject->Vpb->VolumeLabelLength;
+  DPRINT("LabelLength %lu\n", LabelLength);
+  
+  /* FIXME: This does not work correctly! Why?? */
+//  if (*BufferLength < (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength));
+//    return(STATUS_BUFFER_OVERFLOW);
+
+  /* valid entries */
+  FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber;
+  FsVolumeInfo->VolumeLabelLength = LabelLength;
+  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);
+  
+  DPRINT("BufferLength %lu\n", *BufferLength);
+  
+  return(STATUS_SUCCESS);
+}
 
-    DPRINT("Finished FsdGetFsVolumeInformation()\n");
 
-    return(STATUS_SUCCESS);
+static NTSTATUS
+FsdGetFsAttributeInformation(PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo,
+                            PULONG BufferLength)
+{
+  DPRINT("FsdGetFsAttributeInformation()\n");
+  DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo);
+  DPRINT("BufferLength %lu\n", *BufferLength);
+  DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 6));
+  
+  /* FIXME: This does not work correctly! Why?? */
+//  if (*BufferLength < (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 6));
+//    return(STATUS_BUFFER_OVERFLOW);
+  
+  FsAttributeInfo->FileSystemAttributes =
+    FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK;
+  FsAttributeInfo->MaximumComponentNameLength = 255;
+  FsAttributeInfo->FileSystemNameLength = 6;
+  wcscpy(FsAttributeInfo->FileSystemName, L"FAT");
+  
+  DPRINT("Finished FsdGetFsAttributeInformation()\n");
+  
+  *BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 6);
+  DPRINT("BufferLength %lu\n", *BufferLength);
+  
+  return(STATUS_SUCCESS);
 }
 
 
-NTSTATUS FsdGetFsAttributeInformation(PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo)
+static NTSTATUS
+FsdGetFsSizeInformation(PDEVICE_OBJECT DeviceObject,
+                       PFILE_FS_SIZE_INFORMATION FsSizeInfo,
+                       PULONG BufferLength)
 {
-    DPRINT("FsdGetFsAttributeInformation()\n");
-    DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo);
-
-    if (!FsAttributeInfo)
-        return(STATUS_SUCCESS);
+  PDEVICE_EXTENSION DeviceExt;
+  NTSTATUS Status;
+  
+  DPRINT("FsdGetFsSizeInformation()\n");
+  DPRINT("FsSizeInfo = %p\n", FsSizeInfo);
+  
+  /* FIXME: This does not work correctly! Why?? */
+//  if (*BufferLength < sizeof(FILE_FS_SIZE_INFORMATION));
+//    return(STATUS_BUFFER_OVERFLOW);
+  
+  DeviceExt = DeviceObject->DeviceExtension;
+  
+  if (DeviceExt->FatType == FAT32)
+    {
+      struct _BootSector32 *BootSect =
+       (struct _BootSector32 *) DeviceExt->Boot;
 
-    FsAttributeInfo->FileSystemAttributes = FS_CASE_IS_PRESERVED;
-    FsAttributeInfo->MaximumComponentNameLength = 255;
-    FsAttributeInfo->FileSystemNameLength = 3;
-    wcscpy (FsAttributeInfo->FileSystemName, L"FAT");
+      FsSizeInfo->TotalAllocationUnits.QuadPart = ((BootSect->Sectors ? BootSect->Sectors : BootSect->SectorsHuge)-DeviceExt->dataStart)/BootSect->SectorsPerCluster;
 
-    DPRINT("Finished FsdGetFsAttributeInformation()\n");
+      Status = FAT32CountAvailableClusters(DeviceExt,
+                                          &FsSizeInfo->AvailableAllocationUnits);
 
-    return(STATUS_SUCCESS);
+      FsSizeInfo->SectorsPerAllocationUnit = BootSect->SectorsPerCluster;
+      FsSizeInfo->BytesPerSector = BootSect->BytesPerSector;
+    }
+  else
+    {
+      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");
+  if (NT_SUCCESS(Status))
+    *BufferLength -= sizeof(FILE_FS_SIZE_INFORMATION);
+  
+  return(Status);
 }
 
-NTSTATUS FsdGetFsSizeInformation(PDEVICE_OBJECT DeviceObject,
-                                 PFILE_FS_SIZE_INFORMATION FsSizeInfo)
+
+static NTSTATUS
+FsdGetFsDeviceInformation(PFILE_FS_DEVICE_INFORMATION FsDeviceInfo,
+                         PULONG BufferLength)
 {
-    PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
+  DPRINT("FsdGetFsDeviceInformation()\n");
+  DPRINT("FsDeviceInfo = %p\n", FsDeviceInfo);
+  DPRINT("BufferLength %lu\n", *BufferLength);
+  DPRINT("Required length %lu\n", sizeof(FILE_FS_DEVICE_INFORMATION));
+  
+  /* FIXME: This does not work correctly! Why?? */
+//  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);
+}
 
-    DPRINT("FsdGetFsSizeInformation()\n");
-    DPRINT("FsSizeInfo = %p\n", FsSizeInfo);
 
-    if (!FsSizeInfo)
-        return(STATUS_SUCCESS);
+static NTSTATUS
+FsdSetFsLabelInformation(PDEVICE_OBJECT DeviceObject,
+                        PFILE_FS_LABEL_INFORMATION FsLabelInfo)
+{
+  DPRINT("FsdSetFsLabelInformation()\n");
+  
+  return(STATUS_NOT_IMPLEMENTED);
+}
 
-    if (DeviceExt->FatType == FAT32)
-    {
-        struct _BootSector32 *BootSect = (struct _BootSector32 *)DeviceExt->Boot;
 
-        if (BootSect->Sectors)
-            FsSizeInfo->TotalAllocationUnits.QuadPart = BootSect->Sectors;
-        else
-            FsSizeInfo->TotalAllocationUnits.QuadPart = BootSect->SectorsHuge;
+NTSTATUS STDCALL
+VfatQueryVolumeInformation(PDEVICE_OBJECT DeviceObject,
+                          PIRP Irp)
+/*
+ * FUNCTION: Retrieve the specified volume information
+ */
+{
+  PIO_STACK_LOCATION Stack;
+  FS_INFORMATION_CLASS FsInformationClass;
+  PFILE_OBJECT FileObject = NULL;
+  PVFATFCB FCB = NULL;
+  NTSTATUS RC = STATUS_SUCCESS;
+  PVOID SystemBuffer;
+  ULONG BufferLength;
+
+  /* PRECONDITION */
+  assert(DeviceObject != NULL);
+  assert(Irp != NULL);
+
+  DPRINT("FsdQueryVolumeInformation(DeviceObject %x, Irp %x)\n",
+        DeviceObject, Irp);
+
+  /* INITIALIZATION */
+  Stack = IoGetCurrentIrpStackLocation (Irp);
+  FsInformationClass = Stack->Parameters.QueryVolume.FsInformationClass;
+  BufferLength = Stack->Parameters.QueryVolume.Length;
+  SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
+  FileObject = Stack->FileObject;
+//   CCB = (PVfatCCB)(FileObject->FsContext2);
+//   FCB = CCB->Buffer; // Should be CCB->FCB???
+  FCB = ((PVFATCCB) (FileObject->FsContext2))->pFcb;
 
-        FsSizeInfo->AvailableAllocationUnits.QuadPart =
-            FAT32CountAvailableClusters(DeviceExt);
+  DPRINT ("FsInformationClass %d\n", FsInformationClass);
+  DPRINT ("SystemBuffer %x\n", SystemBuffer);
 
-        FsSizeInfo->SectorsPerAllocationUnit = BootSect->SectorsPerCluster;
-        FsSizeInfo->BytesPerSector = BootSect->BytesPerSector;
-    }
-    else
+  switch (FsInformationClass)
     {
-        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;
+    case FileFsVolumeInformation:
+      RC = FsdGetFsVolumeInformation(FileObject,
+                                    FCB,
+                                    DeviceObject,
+                                    SystemBuffer,
+                                    &BufferLength);
+      break;
+
+    case FileFsAttributeInformation:
+      RC = FsdGetFsAttributeInformation(SystemBuffer,
+                                       &BufferLength);
+      break;
+
+    case FileFsSizeInformation:
+      RC = FsdGetFsSizeInformation(DeviceObject,
+                                  SystemBuffer,
+                                  &BufferLength);
+      break;
+
+    case FileFsDeviceInformation:
+      RC = FsdGetFsDeviceInformation(SystemBuffer,
+                                    &BufferLength);
+      break;
+
+    default:
+      RC = STATUS_NOT_SUPPORTED;
     }
 
-    DPRINT("Finished FsdGetFsSizeInformation()\n");
+  Irp->IoStatus.Status = RC;
+  if (NT_SUCCESS(RC))
+    Irp->IoStatus.Information =
+      Stack->Parameters.QueryVolume.Length - BufferLength;
+  else
+    Irp->IoStatus.Information = 0;
+  IoCompleteRequest(Irp,
+                   IO_NO_INCREMENT);
 
-    return(STATUS_SUCCESS);
+  return RC;
 }
 
 
-NTSTATUS VfatQueryVolumeInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+NTSTATUS STDCALL
+VfatSetVolumeInformation(PDEVICE_OBJECT DeviceObject,
+                        PIRP Irp)
 /*
- * FUNCTION: Retrieve the specified file information
+ * FUNCTION: Set 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;
+  PIO_STACK_LOCATION Stack;
+  FS_INFORMATION_CLASS FsInformationClass;
+//  PFILE_OBJECT FileObject = NULL;
+//  PVFATFCB FCB = NULL;
+  NTSTATUS Status = STATUS_SUCCESS;
+  PVOID SystemBuffer;
+  ULONG BufferLength;
+
+  /* PRECONDITION */
+  assert(DeviceObject != NULL);
+  assert(Irp != NULL);
+
+  DPRINT("FsdSetVolumeInformation(DeviceObject %x, Irp %x)\n",
+        DeviceObject,
+        Irp);
+
+  Stack = IoGetCurrentIrpStackLocation(Irp);
+  FsInformationClass = Stack->Parameters.SetVolume.FsInformationClass;
+  BufferLength = Stack->Parameters.SetVolume.Length;
+  SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
+//  FileObject = Stack->FileObject;
+//  FCB = ((PVFATCCB) (FileObject->FsContext2))->pFcb;
+
+  DPRINT("FsInformationClass %d\n", FsInformationClass);
+  DPRINT("BufferLength %d\n", BufferLength);
+  DPRINT("SystemBuffer %x\n", SystemBuffer);
+
+  switch(FsInformationClass)
+    {
+    case FileFsLabelInformation:
+      Status = FsdSetFsLabelInformation(DeviceObject,
+                                       SystemBuffer);
+      break;
 
-  // FIXME : determine Buffer for result :
-  if (Irp->MdlAddress) 
-    SystemBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
-  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;
-}
+    default:
+      Status = STATUS_NOT_SUPPORTED;
+    }
 
+  Irp->IoStatus.Status = Status;
+  Irp->IoStatus.Information = 0;
+  IoCompleteRequest(Irp,
+                   IO_NO_INCREMENT);
+
+  return(Status);
+}
 
+/* EOF */