[NTFS] - In the NtfsAddFilenameToDirectory() function, rename DirectoryContext parame...
[reactos.git] / drivers / filesystems / ntfs / dispatch.c
index 1c00ea0..53d7930 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
-/* GLOBALS *****************************************************************/
-
+static LONG QueueCount = 0;
 
 /* FUNCTIONS ****************************************************************/
 
+static WORKER_THREAD_ROUTINE NtfsDoRequest;
+
+static
+NTSTATUS
+NtfsQueueRequest(PNTFS_IRP_CONTEXT IrpContext)
+{
+    InterlockedIncrement(&QueueCount);
+    DPRINT("NtfsQueueRequest(IrpContext %p), %d\n", IrpContext, QueueCount);
+
+    ASSERT(!(IrpContext->Flags & IRPCONTEXT_QUEUE) &&
+           (IrpContext->Flags & IRPCONTEXT_COMPLETE));
+    IrpContext->Flags |= IRPCONTEXT_CANWAIT;
+    IoMarkIrpPending(IrpContext->Irp);
+    ExInitializeWorkItem(&IrpContext->WorkQueueItem, NtfsDoRequest, IrpContext);
+    ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
+
+    return STATUS_PENDING;
+}
+
+static
+NTSTATUS
+NtfsDispatch(PNTFS_IRP_CONTEXT IrpContext)
+{
+    PIRP Irp = IrpContext->Irp;
+    NTSTATUS Status = STATUS_UNSUCCESSFUL;
+
+    TRACE_(NTFS, "NtfsDispatch()\n");
+
+    FsRtlEnterFileSystem();
+
+    NtfsIsIrpTopLevel(Irp);
+
+    switch (IrpContext->MajorFunction)
+    {
+        case IRP_MJ_QUERY_VOLUME_INFORMATION:
+            Status = NtfsQueryVolumeInformation(IrpContext);
+            break;
+
+        case IRP_MJ_SET_VOLUME_INFORMATION:
+            Status = NtfsSetVolumeInformation(IrpContext);
+            break;
+
+        case IRP_MJ_QUERY_INFORMATION:
+            Status = NtfsQueryInformation(IrpContext);
+            break;
+
+        case IRP_MJ_SET_INFORMATION:
+            if (!NtfsGlobalData->EnableWriteSupport)
+            {
+                DPRINT1("NTFS write-support is EXPERIMENTAL and is disabled by default!\n");
+                Status = STATUS_ACCESS_DENIED;
+            }
+            else
+            {
+                Status = NtfsSetInformation(IrpContext);
+            }
+            break;
+
+        case IRP_MJ_DIRECTORY_CONTROL:
+            Status = NtfsDirectoryControl(IrpContext);
+            break;
+
+        case IRP_MJ_READ:
+            Status = NtfsRead(IrpContext);
+            break;
+
+        case IRP_MJ_DEVICE_CONTROL:
+            Status = NtfsDeviceControl(IrpContext);
+             break;
+
+        case IRP_MJ_WRITE:
+            if (!NtfsGlobalData->EnableWriteSupport)
+            {
+                DPRINT1("NTFS write-support is EXPERIMENTAL and is disabled by default!\n");
+                Status = STATUS_ACCESS_DENIED;
+            }
+            else
+            {
+                Status = NtfsWrite(IrpContext);
+            }
+            break;
+
+        case IRP_MJ_CLOSE:
+            Status = NtfsClose(IrpContext);
+            break;
+
+        case IRP_MJ_CLEANUP:
+            Status = NtfsCleanup(IrpContext);
+            break;
+
+        case IRP_MJ_CREATE:
+            Status = NtfsCreate(IrpContext);
+            break;
+
+        case IRP_MJ_FILE_SYSTEM_CONTROL:
+            Status = NtfsFileSystemControl(IrpContext);
+            break;
+    }
+
+    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)
+    {
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(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 = NtfsQueueRequest(IrpContext);
+    }
+    else
+    {
+        ExFreeToNPagedLookasideList(&NtfsGlobalData->IrpContextLookasideList, IrpContext);
+    }
+
+    IoSetTopLevelIrp(NULL);
+    FsRtlExitFileSystem();
+
+    return Status;
+}
+
+static
+VOID
+NTAPI
+NtfsDoRequest(PVOID IrpContext)
+{
+    InterlockedDecrement(&QueueCount);
+    DPRINT("NtfsDoRequest(IrpContext %p), MajorFunction %x, %d\n",
+           IrpContext, ((PNTFS_IRP_CONTEXT)IrpContext)->MajorFunction, QueueCount);
+    NtfsDispatch((PNTFS_IRP_CONTEXT)IrpContext);
+}
+
 /*
  * FUNCTION: This function manages IRP for various major functions
  * ARGUMENTS:
  *           Irp = IRP to be passed to internal functions
  * RETURNS: Status of I/O Request
  */
-NTSTATUS NTAPI
+NTSTATUS
+NTAPI
 NtfsFsdDispatch(PDEVICE_OBJECT DeviceObject,
                 PIRP Irp)
 {
-  PNTFS_IRP_CONTEXT IrpContext = NULL;
-  NTSTATUS Status = STATUS_UNSUCCESSFUL;
-  
-  TRACE_(NTFS, "NtfsFsdDispatch()\n");
-  
-  FsRtlEnterFileSystem();
-  ASSERT(DeviceObject);
-  ASSERT(Irp);
-  
-  NtfsIsIrpTopLevel(Irp);
-  
-  IrpContext = NtfsAllocateIrpContext(DeviceObject, Irp);
-  if (IrpContext)
-  {
-    switch (IrpContext->MajorFunction)
+    PNTFS_IRP_CONTEXT IrpContext = NULL;
+    NTSTATUS Status;
+
+    TRACE_(NTFS, "NtfsFsdDispatch()\n");
+
+    IrpContext = NtfsAllocateIrpContext(DeviceObject, Irp);
+    if (IrpContext == NULL)
     {
-      case IRP_MJ_QUERY_VOLUME_INFORMATION:
-      {
-        Status = NtfsQueryVolumeInformation(IrpContext);
-        break;
-      }
-      case IRP_MJ_SET_VOLUME_INFORMATION:
-      {
-        Status = NtfsSetVolumeInformation(IrpContext);
-        break;
-      }
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
     }
-  }
-  else
-    Status = STATUS_INSUFFICIENT_RESOURCES;
-       
-  Irp->IoStatus.Status = Status;
-  IoCompleteRequest(Irp, IO_NO_INCREMENT);
-       
-       if (IrpContext)
-    ExFreePoolWithTag(IrpContext, 'PRIN');
-       
-  IoSetTopLevelIrp(NULL);
-  FsRtlExitFileSystem();
-  return Status;
+    else
+    {
+        Status = NtfsDispatch(IrpContext);
+    }
+
+     return Status;
 }