Reworked code for handling of asynchonous i/o requests.
[reactos.git] / reactos / drivers / fs / vfat / iface.c
index 18fac83..efd37ce 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: iface.c,v 1.56 2001/07/17 07:48:06 ekohl Exp $
+/* $Id: iface.c,v 1.59 2001/11/02 22:47:36 hbirr Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -8,14 +8,14 @@
  * UPDATE HISTORY:
  *    ??           Created
  *   24-10-1998   Fixed bugs in long filename support
- *                Fixed a bug that prevented unsuccessful file open requests 
+ *                Fixed a bug that prevented unsuccessful file open requests
  *                being reported
- *                Now works with long filenames that span over a sector 
+ *                Now works with long filenames that span over a sector
  *                boundary
  *   28-10-1998   Reads entire FAT into memory
  *                VFatReadSector modified to read in more than one sector at a
  *                time
- *   7-11-1998    Fixed bug that assumed that directory data could be 
+ *   7-11-1998    Fixed bug that assumed that directory data could be
  *                fragmented
  *   8-12-1998    Added FAT32 support
  *                Added initial writability functions
@@ -46,7 +46,7 @@ static NTSTATUS
 VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount,
                  PBOOLEAN RecognizedFS)
 /*
- * FUNCTION: Tests if the device contains a filesystem that can be mounted 
+ * FUNCTION: Tests if the device contains a filesystem that can be mounted
  *           by this fsd
  */
 {
@@ -58,10 +58,10 @@ VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount,
    Status = VfatReadSectors(DeviceToMount, 0, 1, (UCHAR *) Boot);
    if (!NT_SUCCESS(Status))
      {
-       return Status;
+       return(Status);
      }
 
-   DPRINT("Boot->SysType %.5s\n", Boot->SysType);
+   DPRINT1("Boot->SysType %.5s\n", Boot->SysType);
    if (strncmp(Boot->SysType, "FAT12", 5) == 0 ||
        strncmp(Boot->SysType, "FAT16", 5) == 0 ||
        strncmp(((struct _BootSector32 *) (Boot))->SysType, "FAT32", 5) == 0)
@@ -75,12 +75,13 @@ VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount,
 
    ExFreePool(Boot);
 
-   return STATUS_SUCCESS;
+   return(STATUS_SUCCESS);
 }
 
 
 static NTSTATUS
-VfatMountDevice (PDEVICE_EXTENSION DeviceExt, PDEVICE_OBJECT DeviceToMount)
+VfatMountDevice(PDEVICE_EXTENSION DeviceExt,
+               PDEVICE_OBJECT DeviceToMount)
 /*
  * FUNCTION: Mounts the device
  */
@@ -95,7 +96,7 @@ VfatMountDevice (PDEVICE_EXTENSION DeviceExt, PDEVICE_OBJECT DeviceToMount)
    Status = VfatReadSectors(DeviceToMount, 0, 1, (UCHAR *) DeviceExt->Boot);
    if (!NT_SUCCESS(Status))
      {
-       return Status;
+       return(Status);
      }
 
    DeviceExt->FATStart = DeviceExt->Boot->ReservedSectors;
@@ -136,10 +137,10 @@ VfatMountDevice (PDEVICE_EXTENSION DeviceExt, PDEVICE_OBJECT DeviceToMount)
        DbgPrint("FAT32\n");
        DeviceExt->FatType = FAT32;
        DeviceExt->rootDirectorySectors = DeviceExt->Boot->SectorsPerCluster;
-       DeviceExt->rootStart =
-         DeviceExt->FATStart + DeviceExt->Boot->FATCount
+       DeviceExt->dataStart = DeviceExt->FATStart + DeviceExt->Boot->FATCount
          * ((struct _BootSector32 *) (DeviceExt->Boot))->FATSectors32;
-        DeviceExt->dataStart = DeviceExt->rootStart;
+       DeviceExt->rootStart = ClusterToSector (DeviceExt,
+         ((struct _BootSector32 *)(DeviceExt->Boot))->RootCluster);
      }
    else
      {
@@ -147,121 +148,218 @@ VfatMountDevice (PDEVICE_EXTENSION DeviceExt, PDEVICE_OBJECT DeviceToMount)
        DeviceExt->FatType = FAT16;
      }
 
-   return STATUS_SUCCESS;
+   return(STATUS_SUCCESS);
 }
 
 
 static NTSTATUS
-VfatMount (PDEVICE_OBJECT DeviceToMount)
+VfatMount (PVFAT_IRP_CONTEXT IrpContext)
 /*
  * FUNCTION: Mount the filesystem
  */
 {
-   PDEVICE_OBJECT DeviceObject;
-   PDEVICE_EXTENSION DeviceExt;
-   BOOLEAN RecognizedFS;
-   NTSTATUS Status;
-
-   Status = VfatHasFileSystem (DeviceToMount, &RecognizedFS);
-   if (!NT_SUCCESS(Status))
-     {
-       return Status;
-     }
-
-   if (RecognizedFS == FALSE)
-     {
-       DPRINT("VFAT: Unrecognized Volume\n");
-       return STATUS_UNRECOGNIZED_VOLUME;
-     }
-
-   DPRINT("VFAT: Recognized volume\n");
-
-   Status = IoCreateDevice(VfatDriverObject,
-                          sizeof (DEVICE_EXTENSION),
-                          NULL,
-                          FILE_DEVICE_FILE_SYSTEM,
-                          0,
-                          FALSE,
-                          &DeviceObject);
-   if (!NT_SUCCESS(Status))
-     {
-       return Status;
-     }
-
-   DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
-   DeviceExt = (PVOID) DeviceObject->DeviceExtension;
-   /* use same vpb as device disk */
-   DeviceObject->Vpb = DeviceToMount->Vpb;
-   Status = VfatMountDevice (DeviceExt, DeviceToMount);
-   if (!NT_SUCCESS(Status))
-     {
-       /* FIXME: delete device object */
-       return Status;
-     }
-
-   DeviceObject->Vpb->Flags |= VPB_MOUNTED;
-   DeviceExt->StorageDevice = IoAttachDeviceToDeviceStack(DeviceObject,
-                                                         DeviceToMount);
-   DeviceExt->StreamStorageDevice = IoCreateStreamFileObject(NULL,
-                                                            DeviceExt->StorageDevice);
-   if (DeviceExt->FatType == FAT16)
-     Status = CcRosInitializeFileCache(DeviceExt->StreamStorageDevice,
-                                      &DeviceExt->StorageBcb,
-                                      CACHEPAGESIZE(DeviceExt));
-   else
-     Status = CcRosInitializeFileCache(DeviceExt->StreamStorageDevice,
-                                      &DeviceExt->StorageBcb,
-                                      PAGESIZE);
-   if (!NT_SUCCESS(Status))
-     {
-       /* FIXME: delete device object */
-       return Status;
-     }
-
-   if (DeviceExt->FatType == FAT12)
-     {
-       DeviceExt->Fat12StorageDevice = 
-         IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice);
-       Status = CcRosInitializeFileCache(DeviceExt->Fat12StorageDevice,
-                                      &DeviceExt->Fat12StorageBcb,
-                                      PAGESIZE * 3);
-       if (!NT_SUCCESS(Status))
-         {
-            /* FIXME: delete device object */
-            return Status;
-         }
-     }
-   ExInitializeResourceLite (&DeviceExt->DirResource);
-   ExInitializeResourceLite (&DeviceExt->FatResource);
-
-   KeInitializeSpinLock (&DeviceExt->FcbListLock);
-   InitializeListHead (&DeviceExt->FcbListHead);
-
-   /* read serial number */
-   if (DeviceExt->FatType == FAT12 || DeviceExt->FatType == FAT16)
-     DeviceObject->Vpb->SerialNumber =
-       ((struct _BootSector *) (DeviceExt->Boot))->VolumeID;
-   else if (DeviceExt->FatType == FAT32)
-     DeviceObject->Vpb->SerialNumber =
-       ((struct _BootSector32 *) (DeviceExt->Boot))->VolumeID;
-
-   /* read volume label */
-   ReadVolumeLabel(DeviceExt, DeviceObject->Vpb);
-
-   return STATUS_SUCCESS;
+  PDEVICE_OBJECT DeviceObject = NULL;
+  PDEVICE_EXTENSION DeviceExt = NULL;
+  BOOLEAN RecognizedFS;
+  NTSTATUS Status;
+  PVFATFCB Fcb = NULL;
+  PVFATCCB Ccb = NULL;
+
+  DPRINT1("VfatMount(IrpContext %x)\n", IrpContext);
+
+  assert (IrpContext);
+
+  if (IrpContext->DeviceObject != VfatDriverObject->DeviceObject)
+  {
+     // Only allowed on the main device object
+     Status = STATUS_INVALID_DEVICE_REQUEST;
+     goto ByeBye;
+  }
+
+  Status = VfatHasFileSystem (IrpContext->Stack->Parameters.Mount.DeviceObject, &RecognizedFS);
+  if (!NT_SUCCESS(Status))
+  {
+     goto ByeBye;
+  }
+
+  if (RecognizedFS == FALSE)
+  {
+     DPRINT("VFAT: Unrecognized Volume\n");
+     Status = STATUS_UNRECOGNIZED_VOLUME;
+     goto ByeBye;
+  }
+
+  DPRINT("VFAT: Recognized volume\n");
+
+  Status = IoCreateDevice(VfatDriverObject,
+                         sizeof (DEVICE_EXTENSION),
+                         NULL,
+                         FILE_DEVICE_FILE_SYSTEM,
+                         0,
+                         FALSE,
+                         &DeviceObject);
+  if (!NT_SUCCESS(Status))
+  {
+    goto ByeBye;
+  }
+
+  DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
+  DeviceExt = (PVOID) DeviceObject->DeviceExtension;
+  RtlZeroMemory(DeviceExt, sizeof(DEVICE_EXTENSION));
+
+  /* use same vpb as device disk */
+  DeviceObject->Vpb = IrpContext->Stack->Parameters.Mount.DeviceObject->Vpb;
+  Status = VfatMountDevice(DeviceExt, IrpContext->Stack->Parameters.Mount.DeviceObject);
+  if (!NT_SUCCESS(Status))
+  {
+    /* FIXME: delete device object */
+    goto ByeBye;
+  }
+
+#if 1
+  DbgPrint("BytesPerSector:     %d\n", DeviceExt->Boot->BytesPerSector);
+  DbgPrint("SectorsPerCluster:  %d\n", DeviceExt->Boot->SectorsPerCluster);
+  DbgPrint("ReservedSectors:    %d\n", DeviceExt->Boot->ReservedSectors);
+  DbgPrint("FATCount:           %d\n", DeviceExt->Boot->FATCount);
+  DbgPrint("RootEntries:        %d\n", DeviceExt->Boot->RootEntries);
+  DbgPrint("Sectors:            %d\n", DeviceExt->Boot->Sectors);
+  DbgPrint("FATSectors:         %d\n", DeviceExt->Boot->FATSectors);
+  DbgPrint("SectorsPerTrack:    %d\n", DeviceExt->Boot->SectorsPerTrack);
+  DbgPrint("Heads:              %d\n", DeviceExt->Boot->Heads);
+  DbgPrint("HiddenSectors:      %d\n", DeviceExt->Boot->HiddenSectors);
+  DbgPrint("SectorsHuge:        %d\n", DeviceExt->Boot->SectorsHuge);
+  DbgPrint("RootStart:          %d\n", DeviceExt->rootStart);
+  DbgPrint("DataStart:          %d\n", DeviceExt->dataStart);
+  if (DeviceExt->FatType == FAT32)
+    {
+      DbgPrint("FATSectors32:       %d\n",
+              ((struct _BootSector32*)(DeviceExt->Boot))->FATSectors32);
+      DbgPrint("RootCluster:        %d\n",
+              ((struct _BootSector32*)(DeviceExt->Boot))->RootCluster);
+      DbgPrint("FSInfoSector:       %d\n",
+              ((struct _BootSector32*)(DeviceExt->Boot))->FSInfoSector);
+      DbgPrint("BootBackup:         %d\n",
+              ((struct _BootSector32*)(DeviceExt->Boot))->BootBackup);
+    }
+#endif
+  DeviceObject->Vpb->Flags |= VPB_MOUNTED;
+  DeviceExt->StorageDevice = IoAttachDeviceToDeviceStack(DeviceObject, IrpContext->Stack->Parameters.Mount.DeviceObject);
+
+  DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice);
+  Fcb = vfatNewFCB(NULL);
+  if (Fcb == NULL)
+  {
+    Status = STATUS_INSUFFICIENT_RESOURCES;
+    goto ByeBye;
+  }
+  Ccb = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB);
+  if (Ccb == NULL)
+  {
+    Status =  STATUS_INSUFFICIENT_RESOURCES;
+    goto ByeBye;
+  }
+  memset(Ccb, 0, sizeof (VFATCCB));
+  DeviceExt->FATFileObject->Flags = DeviceExt->FATFileObject->Flags | FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ;
+  DeviceExt->FATFileObject->FsContext = (PVOID) &Fcb->RFCB;
+  DeviceExt->FATFileObject->FsContext2 = Ccb;
+  DeviceExt->FATFileObject->SectionObjectPointers = &Fcb->SectionObjectPointers;
+  Ccb->pFcb = Fcb;
+  Ccb->PtrFileObject = DeviceExt->FATFileObject;
+  Fcb->FileObject = DeviceExt->FATFileObject;
+  Fcb->pDevExt = (PDEVICE_EXTENSION)DeviceExt->StorageDevice;
+
+  Fcb->Flags = FCB_IS_FAT;
+
+  if (DeviceExt->Boot->Sectors != 0)
+  {
+    DeviceExt->NumberOfClusters = (DeviceExt->Boot->Sectors - DeviceExt->dataStart)
+                                    / DeviceExt->Boot->SectorsPerCluster + 2;
+  }
+  else
+  {
+    DeviceExt->NumberOfClusters = (DeviceExt->Boot->SectorsHuge - DeviceExt->dataStart)
+                                    / DeviceExt->Boot->SectorsPerCluster + 2;
+  }
+  if (DeviceExt->FatType == FAT32)
+  {
+    Fcb->RFCB.FileSize.QuadPart = ((struct _BootSector32 *)DeviceExt->Boot)->FATSectors32 * BLOCKSIZE;
+    Fcb->RFCB.ValidDataLength.QuadPart = ((struct _BootSector32 *)DeviceExt->Boot)->FATSectors32 * BLOCKSIZE;
+    Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP(((struct _BootSector32 *)DeviceExt->Boot)->FATSectors32 * BLOCKSIZE, CACHEPAGESIZE(DeviceExt));
+    Status = CcRosInitializeFileCache(DeviceExt->FATFileObject, &Fcb->RFCB.Bcb, CACHEPAGESIZE(DeviceExt));
+  }
+  else
+  {
+    if (DeviceExt->FatType == FAT16)
+    {
+      Fcb->RFCB.FileSize.QuadPart = DeviceExt->Boot->FATSectors * BLOCKSIZE;
+      Fcb->RFCB.ValidDataLength.QuadPart = DeviceExt->Boot->FATSectors * BLOCKSIZE;
+      Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP(DeviceExt->Boot->FATSectors * BLOCKSIZE, CACHEPAGESIZE(DeviceExt));
+      Status = CcRosInitializeFileCache(DeviceExt->FATFileObject, &Fcb->RFCB.Bcb, CACHEPAGESIZE(DeviceExt));
+    }
+    else
+    {
+      Fcb->RFCB.FileSize.QuadPart = DeviceExt->Boot->FATSectors * BLOCKSIZE;
+      Fcb->RFCB.ValidDataLength.QuadPart = DeviceExt->Boot->FATSectors * BLOCKSIZE;
+      Fcb->RFCB.AllocationSize.QuadPart = 2 * PAGESIZE;
+      Status = CcRosInitializeFileCache(DeviceExt->FATFileObject, &Fcb->RFCB.Bcb, 2 * PAGESIZE);
+    }
+  }
+  if (!NT_SUCCESS (Status))
+  {
+     DbgPrint ("CcRosInitializeFileCache failed\n");
+     goto ByeBye;
+  }
+
+  DeviceExt->LastAvailableCluster = 0;
+  ExInitializeResourceLite(&DeviceExt->DirResource);
+  ExInitializeResourceLite(&DeviceExt->FatResource);
+
+  KeInitializeSpinLock(&DeviceExt->FcbListLock);
+  InitializeListHead(&DeviceExt->FcbListHead);
+
+  /* read serial number */
+  if (DeviceExt->FatType == FAT12 || DeviceExt->FatType == FAT16)
+    DeviceObject->Vpb->SerialNumber =
+      ((struct _BootSector *) (DeviceExt->Boot))->VolumeID;
+  else if (DeviceExt->FatType == FAT32)
+    DeviceObject->Vpb->SerialNumber =
+      ((struct _BootSector32 *) (DeviceExt->Boot))->VolumeID;
+
+  /* read volume label */
+  ReadVolumeLabel(DeviceExt,  DeviceObject->Vpb);
+  Status = STATUS_SUCCESS;
+
+ByeBye:
+
+  if (!NT_SUCCESS(Status))
+  {
+     // cleanup
+     if (DeviceExt && DeviceExt->FATFileObject)
+        ObDereferenceObject (DeviceExt->FATFileObject);
+     if (Fcb)
+        ExFreePool(Fcb);
+     if (Ccb)
+        ExFreePool(Ccb);
+     if (DeviceObject)
+       IoDeleteDevice(DeviceObject);
+  }
+  return Status;
 }
 
 
-NTSTATUS STDCALL
-VfatFileSystemControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
+NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext)
 /*
  * FUNCTION: File system control
  */
 {
-   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation (Irp);
+
    NTSTATUS Status;
 
-   switch (Stack->MinorFunction)
+   DPRINT1("VfatFileSystemControl(IrpContext %x)\n", IrpContext);
+
+   assert (IrpContext);
+
+   switch (IrpContext->MinorFunction)
      {
        case IRP_MN_USER_FS_REQUEST:
           DPRINT1("VFAT FSC: IRP_MN_USER_FS_REQUEST\n");
@@ -269,7 +367,7 @@ VfatFileSystemControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
           break;
 
        case IRP_MN_MOUNT_VOLUME:
-          Status = VfatMount(Stack->Parameters.Mount.DeviceObject);
+          Status = VfatMount(IrpContext);
           break;
 
        case IRP_MN_VERIFY_VOLUME:
@@ -278,15 +376,15 @@ VfatFileSystemControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
           break;
 
        default:
-          DPRINT1("VFAT FSC: MinorFunction %d\n", Stack->MinorFunction);
+          DPRINT1("VFAT FSC: MinorFunction %d\n", IrpContext->MinorFunction);
           Status = STATUS_INVALID_DEVICE_REQUEST;
           break;
      }
 
-   Irp->IoStatus.Status = Status;
-   Irp->IoStatus.Information = 0;
+   IrpContext->Irp->IoStatus.Status = Status;
+   IrpContext->Irp->IoStatus.Information = 0;
 
-   IoCompleteRequest (Irp, IO_NO_INCREMENT);
+   IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT);
    return (Status);
 }
 
@@ -325,24 +423,24 @@ DriverEntry(PDRIVER_OBJECT _DriverObject,
      }
 
    DeviceObject->Flags = DO_DIRECT_IO;
-   VfatDriverObject->MajorFunction[IRP_MJ_CLOSE] = VfatClose;
-   VfatDriverObject->MajorFunction[IRP_MJ_CREATE] = VfatCreate;
-   VfatDriverObject->MajorFunction[IRP_MJ_READ] = VfatRead;
-   VfatDriverObject->MajorFunction[IRP_MJ_WRITE] = VfatWrite;
+   VfatDriverObject->MajorFunction[IRP_MJ_CLOSE] = VfatBuildRequest;
+   VfatDriverObject->MajorFunction[IRP_MJ_CREATE] = VfatBuildRequest;
+   VfatDriverObject->MajorFunction[IRP_MJ_READ] = VfatBuildRequest;
+   VfatDriverObject->MajorFunction[IRP_MJ_WRITE] = VfatBuildRequest;
    VfatDriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
-     VfatFileSystemControl;
+     VfatBuildRequest;
    VfatDriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] =
-     VfatQueryInformation;
+     VfatBuildRequest;
    VfatDriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] =
-     VfatSetInformation;
+     VfatBuildRequest;
    VfatDriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =
-     VfatDirectoryControl;
+     VfatBuildRequest;
    VfatDriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] =
-     VfatQueryVolumeInformation;
+     VfatBuildRequest;
    VfatDriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] =
-     VfatSetVolumeInformation;
+     VfatBuildRequest;
    VfatDriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = VfatShutdown;
-   VfatDriverObject->MajorFunction[IRP_MJ_CLEANUP] = VfatCleanup;
+   VfatDriverObject->MajorFunction[IRP_MJ_CLEANUP] = VfatBuildRequest;
 
    VfatDriverObject->DriverUnload = NULL;