[FASTFAT]
[reactos.git] / reactos / drivers / filesystems / fastfat / misc.c
index 751514d..39e5896 100644 (file)
@@ -51,6 +51,10 @@ const char* MajorFunctionNames[] =
 
 static LONG QueueCount = 0;
 
+static VOID VfatFreeIrpContext(PVFAT_IRP_CONTEXT);
+static PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT, PIRP);
+static NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT);
+
 /* FUNCTIONS ****************************************************************/
 
 static
@@ -69,27 +73,18 @@ VfatLockControl(
 
     if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
     {
-        Status = STATUS_INVALID_DEVICE_REQUEST;
-        goto Fail;
+        return STATUS_INVALID_DEVICE_REQUEST;
     }
 
     if (*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY)
     {
-        Status = STATUS_INVALID_PARAMETER;
-        goto Fail;
+        return STATUS_INVALID_PARAMETER;
     }
 
+    IrpContext->Flags &= ~IRPCONTEXT_COMPLETE;
     Status = FsRtlProcessFileLock(&Fcb->FileLock,
                                   IrpContext->Irp,
                                   NULL);
-
-    VfatFreeIrpContext(IrpContext);
-    return Status;
-
-Fail:
-    IrpContext->Irp->IoStatus.Status = Status;
-    IoCompleteRequest(IrpContext->Irp, (CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
-    VfatFreeIrpContext(IrpContext);
     return Status;
 }
 
@@ -100,6 +95,8 @@ VfatDeviceControl(
 {
     IoSkipCurrentIrpStackLocation(IrpContext->Irp);
 
+    IrpContext->Flags &= ~IRPCONTEXT_COMPLETE;
+
     return IoCallDriver(IrpContext->DeviceExt->StorageDevice, IrpContext->Irp);
 }
 
@@ -108,50 +105,108 @@ NTSTATUS
 VfatDispatchRequest(
     IN PVFAT_IRP_CONTEXT IrpContext)
 {
+    NTSTATUS Status;
+
     DPRINT("VfatDispatchRequest (IrpContext %p), is called for %s\n", IrpContext,
            IrpContext->MajorFunction >= IRP_MJ_MAXIMUM_FUNCTION ? "????" : MajorFunctionNames[IrpContext->MajorFunction]);
 
     ASSERT(IrpContext);
 
+    FsRtlEnterFileSystem();
+
     switch (IrpContext->MajorFunction)
     {
         case IRP_MJ_CLOSE:
-            return VfatClose(IrpContext);
+            Status = VfatClose(IrpContext);
+            break;
+
         case IRP_MJ_CREATE:
-         return VfatCreate(IrpContext);
+            Status = VfatCreate(IrpContext);
+            break;
+
         case IRP_MJ_READ:
-            return VfatRead (IrpContext);
+            Status = VfatRead(IrpContext);
+            break;
+
         case IRP_MJ_WRITE:
-            return VfatWrite (IrpContext);
+            Status = VfatWrite (IrpContext);
+            break;
+
         case IRP_MJ_FILE_SYSTEM_CONTROL:
-            return VfatFileSystemControl(IrpContext);
+            Status = VfatFileSystemControl(IrpContext);
+            break;
+
         case IRP_MJ_QUERY_INFORMATION:
-            return VfatQueryInformation (IrpContext);
+            Status = VfatQueryInformation (IrpContext);
+            break;
+
         case IRP_MJ_SET_INFORMATION:
-            return VfatSetInformation (IrpContext);
+            Status = VfatSetInformation (IrpContext);
+            break;
+
         case IRP_MJ_DIRECTORY_CONTROL:
-            return VfatDirectoryControl(IrpContext);
+            Status = VfatDirectoryControl(IrpContext);
+            break;
+
         case IRP_MJ_QUERY_VOLUME_INFORMATION:
-            return VfatQueryVolumeInformation(IrpContext);
+            Status = VfatQueryVolumeInformation(IrpContext);
+            break;
+
         case IRP_MJ_SET_VOLUME_INFORMATION:
-            return VfatSetVolumeInformation(IrpContext);
+            Status = VfatSetVolumeInformation(IrpContext);
+            break;
+
         case IRP_MJ_LOCK_CONTROL:
-            return VfatLockControl(IrpContext);
+            Status = VfatLockControl(IrpContext);
+            break;
+
         case IRP_MJ_DEVICE_CONTROL:
-            return VfatDeviceControl(IrpContext);
+            Status = VfatDeviceControl(IrpContext);
+            break;
+
         case IRP_MJ_CLEANUP:
-            return VfatCleanup(IrpContext);
+            Status = VfatCleanup(IrpContext);
+            break;
+
         case IRP_MJ_FLUSH_BUFFERS:
-            return VfatFlush(IrpContext);
+            Status = VfatFlush(IrpContext);
+            break;
+
         case IRP_MJ_PNP:
-            return VfatPnp(IrpContext);
+            Status = VfatPnp(IrpContext);
+            break;
+
         default:
             DPRINT1("Unexpected major function %x\n", IrpContext->MajorFunction);
-            IrpContext->Irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
-            IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
-            VfatFreeIrpContext(IrpContext);
-            return STATUS_DRIVER_INTERNAL_ERROR;
+            Status = STATUS_DRIVER_INTERNAL_ERROR;
+    }
+
+    ASSERT((!(IrpContext->Flags & IRPCONTEXT_COMPLETE) && !(IrpContext->Flags & IRPCONTEXT_QUEUE)) ||
+           ((IrpContext->Flags & IRPCONTEXT_COMPLETE) && !(IrpContext->Flags & IRPCONTEXT_QUEUE)) ||
+           (!(IrpContext->Flags & IRPCONTEXT_COMPLETE) && (IrpContext->Flags & IRPCONTEXT_QUEUE)));
+
+    if (IrpContext->Flags & IRPCONTEXT_COMPLETE)
+    {
+        IrpContext->Irp->IoStatus.Status = Status;
+        IoCompleteRequest(IrpContext->Irp, IrpContext->PriorityBoost);
+    }
+
+    if (IrpContext->Flags & IRPCONTEXT_QUEUE)
+    {
+        /* Reset our status flags before queueing the IRP */
+        IrpContext->Flags |= IRPCONTEXT_COMPLETE;
+        IrpContext->Flags &= ~IRPCONTEXT_QUEUE;
+        Status = VfatQueueRequest(IrpContext);
+    }
+    else
+    {
+        /* Unless the IRP was queued, always free the IRP context */
+        VfatFreeIrpContext(IrpContext);
     }
+
+    FsRtlExitFileSystem();
+
+    return Status;
 }
 
 NTSTATUS
@@ -177,13 +232,12 @@ VfatBuildRequest(
     }
     else
     {
-        FsRtlEnterFileSystem();
         Status = VfatDispatchRequest(IrpContext);
-        FsRtlExitFileSystem();
     }
     return Status;
 }
 
+static
 VOID
 VfatFreeIrpContext(
     PVFAT_IRP_CONTEXT IrpContext)
@@ -192,6 +246,7 @@ VfatFreeIrpContext(
     ExFreeToNPagedLookasideList(&VfatGlobalData->IrpContextLookasideList, IrpContext);
 }
 
+static
 PVFAT_IRP_CONTEXT
 VfatAllocateIrpContext(
     PDEVICE_OBJECT DeviceObject,
@@ -218,7 +273,7 @@ VfatAllocateIrpContext(
         MajorFunction = IrpContext->MajorFunction = IrpContext->Stack->MajorFunction;
         IrpContext->MinorFunction = IrpContext->Stack->MinorFunction;
         IrpContext->FileObject = IrpContext->Stack->FileObject;
-        IrpContext->Flags = 0;
+        IrpContext->Flags = IRPCONTEXT_COMPLETE;
         if (MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
             MajorFunction == IRP_MJ_DEVICE_CONTROL ||
             MajorFunction == IRP_MJ_SHUTDOWN)
@@ -233,6 +288,7 @@ VfatAllocateIrpContext(
         }
         KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
         IrpContext->RefCount = 0;
+        IrpContext->PriorityBoost = IO_NO_INCREMENT;
     }
     return IrpContext;
 }
@@ -248,11 +304,10 @@ VfatDoRequest(
     InterlockedDecrement(&QueueCount);
     DPRINT("VfatDoRequest(IrpContext %p), MajorFunction %x, %d\n",
            IrpContext, ((PVFAT_IRP_CONTEXT)IrpContext)->MajorFunction, QueueCount);
-    FsRtlEnterFileSystem();
     VfatDispatchRequest((PVFAT_IRP_CONTEXT)IrpContext);
-    FsRtlExitFileSystem();
 }
 
+static
 NTSTATUS
 VfatQueueRequest(
     PVFAT_IRP_CONTEXT IrpContext)
@@ -262,6 +317,8 @@ VfatQueueRequest(
 
     ASSERT(IrpContext != NULL);
     ASSERT(IrpContext->Irp != NULL);
+    ASSERT(!(IrpContext->Flags & IRPCONTEXT_QUEUE) &&
+           (IrpContext->Flags & IRPCONTEXT_COMPLETE));
 
     IrpContext->Flags |= IRPCONTEXT_CANWAIT;
     IoMarkIrpPending(IrpContext->Irp);
@@ -272,15 +329,14 @@ VfatQueueRequest(
 
 PVOID
 VfatGetUserBuffer(
-    IN PIRP Irp)
+    IN PIRP Irp,
+    IN BOOLEAN Paging)
 {
     ASSERT(Irp);
 
     if (Irp->MdlAddress)
     {
-        /* This call may be in the paging path, so use maximum priority */
-        /* FIXME: call with normal priority in the non-paging path */
-        return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
+        return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, (Paging ? HighPagePriority : NormalPagePriority));
     }
     else
     {