update for HEAD-2003091401
[reactos.git] / ntoskrnl / io / cleanup.c
index 5fc68f6..8f8ab27 100644 (file)
 
 /* FUNCTIONS ***************************************************************/
 
-VOID STDCALL
-IopCompleteRequest1(struct _KAPC* Apc,
-                   PKNORMAL_ROUTINE* NormalRoutine,
-                   PVOID* NormalContext,
-                   PVOID* SystemArgument1,
-                   PVOID* SystemArgument2)
-{
-   PIRP Irp;
-   CCHAR PriorityBoost;
-   PIO_STACK_LOCATION IoStack;
-   PFILE_OBJECT FileObject;
-   
-   DPRINT("IopCompleteRequest1()\n");
-   
-   Irp = (PIRP)(*SystemArgument1);
-   PriorityBoost = (CCHAR)(LONG)(*SystemArgument2);
-   
-   IoStack = &Irp->Stack[(ULONG)Irp->CurrentLocation];
-   FileObject = IoStack->FileObject;
-   
-   (*SystemArgument1) = (PVOID)Irp->UserIosb;
-   (*SystemArgument2) = (PVOID)Irp->IoStatus.Information;
-   
-   if (Irp->UserIosb!=NULL)
-     {
-       *Irp->UserIosb=Irp->IoStatus;
-     }
-
-   if (Irp->UserEvent)
-   {
-      KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE);
-   }
-
-   if (!(Irp->Flags & IRP_PAGING_IO) && FileObject)
-   {
-      // if the event is not the one in the file object, it needs dereferenced
-      if (Irp->UserEvent && Irp->UserEvent != &FileObject->Event)
-        ObDereferenceObject(Irp->UserEvent);
-
-      if (IoStack->MajorFunction != IRP_MJ_CLOSE)
-      {
-        ObDereferenceObject(FileObject);
-      }
-   }
-   
-   IoFreeIrp(Irp);
-
-}
-
 VOID IoDeviceControlCompletion(PDEVICE_OBJECT DeviceObject,
                               PIRP Irp,
                               PIO_STACK_LOCATION IoStack)
 {
    ULONG IoControlCode;
-   
-   IoControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
+   ULONG OutputBufferLength;
+
+   if (IoStack->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL)
+     {
+       IoControlCode = 
+        ((PEXTENDED_IO_STACK_LOCATION)IoStack)->Parameters.FileSystemControl.FsControlCode;
+       OutputBufferLength = 
+        ((PEXTENDED_IO_STACK_LOCATION)IoStack)->Parameters.FileSystemControl.OutputBufferLength;
+     }
+   else
+     {
+       IoControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
+       OutputBufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
+     }
    
    switch (IO_METHOD_FROM_CTL_CODE(IoControlCode))
      {
@@ -86,11 +49,10 @@ VOID IoDeviceControlCompletion(PDEVICE_OBJECT DeviceObject,
        /* copy output buffer back and free it */
        if (Irp->AssociatedIrp.SystemBuffer)
          {
-            if (IoStack->Parameters.DeviceIoControl.OutputBufferLength)
+            if (OutputBufferLength)
               {
                  RtlCopyMemory(Irp->UserBuffer,
                                Irp->AssociatedIrp.SystemBuffer,
-                               IoStack->Parameters.DeviceIoControl.
                                OutputBufferLength);
               }
             ExFreePool (Irp->AssociatedIrp.SystemBuffer);
@@ -103,11 +65,10 @@ VOID IoDeviceControlCompletion(PDEVICE_OBJECT DeviceObject,
        /* copy output buffer back and free it */
         if (Irp->AssociatedIrp.SystemBuffer)
          {
-            if (IoStack->Parameters.DeviceIoControl.OutputBufferLength)
+            if (OutputBufferLength)
               {
                  RtlCopyMemory(Irp->UserBuffer,
                                Irp->AssociatedIrp.SystemBuffer,
-                               IoStack->Parameters.DeviceIoControl.
                                OutputBufferLength);
               }
            ExFreePool (Irp->AssociatedIrp.SystemBuffer);
@@ -175,103 +136,156 @@ VOID IoVolumeInformationCompletion(PDEVICE_OBJECT DeviceObject,
 {
 }
 
-VOID IoSecondStageCompletion(PIRP Irp, CCHAR PriorityBoost)
+
+VOID STDCALL
+IoSecondStageCompletion_KernelApcRoutine(
+    IN PKAPC Apc,
+    IN OUT PKNORMAL_ROUTINE *NormalRoutine,
+    IN OUT PVOID *NormalContext,
+    IN OUT PVOID *SystemArgument1,
+    IN OUT PVOID *SystemArgument2
+    )
+{
+   IoFreeIrp((PIRP)(*SystemArgument1));
+}
+
+
+VOID STDCALL
+IoSecondStageCompletion_RundownApcRoutine(
+   IN PKAPC Apc
+   )
+{
+   PIRP Irp;
+
+   Irp = CONTAINING_RECORD(Apc, IRP, Tail.Apc);
+   IoFreeIrp(Irp);
+}
+
+
 /*
  * FUNCTION: Performs the second stage of irp completion for read/write irps
- * ARGUMENTS:
- *          Irp = Irp to completion
- *          FromDevice = True if the operation transfered data from the device
+ * 
+ * Called as a special kernel APC or directly from IofCompleteRequest()
  */
+VOID STDCALL
+IoSecondStageCompletion(
+   PKAPC Apc,
+   PKNORMAL_ROUTINE* NormalRoutine,
+   PVOID* NormalContext,
+   PVOID* SystemArgument1,
+   PVOID* SystemArgument2)
+
 {
-   PIO_STACK_LOCATION IoStack;
-   PDEVICE_OBJECT DeviceObject;
-   PFILE_OBJECT FileObject;
-   
-   DPRINT("IoSecondStageCompletion(Irp %x, PriorityBoost %d)\n",
-         Irp, PriorityBoost);
+   PIO_STACK_LOCATION   IoStack;
+   PDEVICE_OBJECT       DeviceObject;
+   PFILE_OBJECT         OriginalFileObject;
+   PIRP                 Irp;
+   CCHAR                PriorityBoost;
+
+   OriginalFileObject = (PFILE_OBJECT)(*NormalContext);
+   Irp = (PIRP)(*SystemArgument1);
+   PriorityBoost = (CCHAR)(LONG)(*SystemArgument2);
    
    IoStack = &Irp->Stack[(ULONG)Irp->CurrentLocation];
-   FileObject = IoStack->FileObject;
-   
    DeviceObject = IoStack->DeviceObject;
-   
+
+   DPRINT("IoSecondStageCompletion(Irp %x, PriorityBoost %d)\n", Irp, PriorityBoost);
+
    switch (IoStack->MajorFunction)
      {
       case IRP_MJ_CREATE:
       case IRP_MJ_FLUSH_BUFFERS:
-         /* NOP */
+       /* NOP */
        break;
-       
+   
       case IRP_MJ_READ:
       case IRP_MJ_WRITE:
        IoReadWriteCompletion(DeviceObject,Irp,IoStack);
        break;
-       
+   
       case IRP_MJ_DEVICE_CONTROL:
       case IRP_MJ_INTERNAL_DEVICE_CONTROL:
+      case IRP_MJ_FILE_SYSTEM_CONTROL:
        IoDeviceControlCompletion(DeviceObject, Irp, IoStack);
        break;
-       
+   
       case IRP_MJ_QUERY_VOLUME_INFORMATION:
       case IRP_MJ_SET_VOLUME_INFORMATION:
        IoVolumeInformationCompletion(DeviceObject, Irp, IoStack);
        break;
-       
+   
       default:
        break;
      }
    
-   if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL)
-     {
-       PKTHREAD Thread;
-       PKNORMAL_ROUTINE UserApcRoutine;
-       PVOID UserApcContext;
-       
-       DPRINT("Dispatching APC\n");
-       Thread = &Irp->Tail.Overlay.Thread->Tcb;
-       UserApcRoutine = (PKNORMAL_ROUTINE)
-         Irp->Overlay.AsynchronousParameters.UserApcRoutine;
-       UserApcContext = (PVOID)
-         Irp->Overlay.AsynchronousParameters.UserApcContext;
-       KeInitializeApc(&Irp->Tail.Apc,
-                       Thread,
-                       0,
-                       IopCompleteRequest1,
-                       NULL,
-                       UserApcRoutine,
-                       UserMode,
-                       UserApcContext);
-       KeInsertQueueApc(&Irp->Tail.Apc,
-                        Irp,
-                        (PVOID)(LONG)PriorityBoost,
-                        KernelMode);
-       return;
-     }
-   
-   DPRINT("Irp->UserIosb %x &Irp->UserIosb %x\n", 
-          Irp->UserIosb,
-          &Irp->UserIosb);
    if (Irp->UserIosb!=NULL)
-     {
-       *Irp->UserIosb=Irp->IoStatus;
-     }
+   {
+      *Irp->UserIosb=Irp->IoStatus;
+   }
 
    if (Irp->UserEvent)
    {
       KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE);
    }
 
-   if (!(Irp->Flags & IRP_PAGING_IO) && FileObject)
+   //Windows NT File System Internals, page 169
+   if (OriginalFileObject)
    {
-      // if the event is not the one in the file object, it needs dereferenced
-      if (Irp->UserEvent && Irp->UserEvent != &FileObject->Event)
-        ObDereferenceObject(Irp->UserEvent);
+      if (Irp->UserEvent == NULL)
+      {
+         KeSetEvent(&OriginalFileObject->Event,PriorityBoost,FALSE);         
+      }
+      else if (OriginalFileObject->Flags & FO_SYNCHRONOUS_IO && Irp->UserEvent != &OriginalFileObject->Event)
+      {
+         KeSetEvent(&OriginalFileObject->Event,PriorityBoost,FALSE);         
+      }
+   }
 
+   //Windows NT File System Internals, page 154
+   if (!(Irp->Flags & IRP_PAGING_IO) && OriginalFileObject)
+   {
+      // if the event is not the one in the file object, it needs dereferenced   
+      if (Irp->UserEvent && Irp->UserEvent != &OriginalFileObject->Event)   
+      {
+         ObDereferenceObject(Irp->UserEvent);
+      }
+  
       if (IoStack->MajorFunction != IRP_MJ_CLOSE)
       {
-        ObDereferenceObject(FileObject);
+         ObDereferenceObject(OriginalFileObject);
       }
    }
 
+   if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL)
+   {
+      PKNORMAL_ROUTINE UserApcRoutine;
+      PVOID UserApcContext;
+   
+      DPRINT("Dispatching user APC\n");
+
+      UserApcRoutine = (PKNORMAL_ROUTINE)Irp->Overlay.AsynchronousParameters.UserApcRoutine;
+      UserApcContext = (PVOID)Irp->Overlay.AsynchronousParameters.UserApcContext;
+
+      KeInitializeApc(  &Irp->Tail.Apc,
+                        KeGetCurrentThread(),
+                        OriginalApcEnvironment,
+                        IoSecondStageCompletion_KernelApcRoutine,
+                        IoSecondStageCompletion_RundownApcRoutine,
+                        UserApcRoutine,
+                        UserMode,
+                        UserApcContext);
+
+      KeInsertQueueApc( &Irp->Tail.Apc,
+                        Irp,
+                        NULL,
+                        PriorityBoost);
+
+      //NOTE: kernel (or rundown) routine frees the IRP
+
+      return;
+
+   }
+
    IoFreeIrp(Irp);
+   
 }