IofCallDriver(): Non-handled 'IRP_MJ_FLUSH_BUFFERS' is silently ignored.
[reactos.git] / ntoskrnl / io / irp.c
index b45f350..cfaf255 100644 (file)
@@ -45,7 +45,6 @@
 
 /* FUNCTIONS ****************************************************************/
 
-#ifndef LIBCAPTIVE
 
 VOID STDCALL
 IoFreeIrp(PIRP Irp)
@@ -58,6 +57,7 @@ IoFreeIrp(PIRP Irp)
   ExFreePool(Irp);
 }
 
+#ifndef LIBCAPTIVE
 
 PIRP STDCALL
 IoMakeAssociatedIrp(PIRP Irp,
@@ -74,6 +74,7 @@ IoMakeAssociatedIrp(PIRP Irp,
   
   AssocIrp = IoAllocateIrp(StackSize,FALSE);
   UNIMPLEMENTED;
+  return NULL;
 }
 
 #endif /* LIBCAPTIVE */
@@ -93,6 +94,7 @@ IoInitializeIrp(PIRP Irp,
   assert(Irp != NULL);
 
   memset(Irp, 0, PacketSize);
+  Irp->Type = IO_TYPE_IRP;
   Irp->Size = PacketSize;
   Irp->StackCount = StackSize;
   Irp->CurrentLocation = StackSize;
@@ -107,7 +109,6 @@ IofCallDriver(PDEVICE_OBJECT DeviceObject,
   * FUNCTION: Sends an IRP to the next lower driver
  */
 {
-  NTSTATUS Status;
   PDRIVER_OBJECT DriverObject;
   PIO_STACK_LOCATION Param;
   
@@ -120,20 +121,27 @@ IofCallDriver(PDEVICE_OBJECT DeviceObject,
 
   assert(DriverObject);
 
-  Param = IoGetNextIrpStackLocation(Irp);
+  IoSetNextIrpStackLocation(Irp);
+  Param = IoGetCurrentIrpStackLocation(Irp);
 
   DPRINT("IrpSp 0x%X\n", Param);
   
-  Irp->Tail.Overlay.CurrentStackLocation--;
-  Irp->CurrentLocation--;
-  
+  Param->DeviceObject = DeviceObject;
+
   DPRINT("MajorFunction %d\n", Param->MajorFunction);
   DPRINT("DriverObject->MajorFunction[Param->MajorFunction] %x\n",
-        DriverObject->MajorFunction[Param->MajorFunction]);
-  Status = DriverObject->MajorFunction[Param->MajorFunction](DeviceObject,
-                                                            Irp);
+    DriverObject->MajorFunction[Param->MajorFunction]);
 
-  return(Status);
+  if (!DriverObject->MajorFunction[Param->MajorFunction])
+    {
+      if (Param->MajorFunction==IRP_MJ_FLUSH_BUFFERS)
+       {
+         ObDereferenceObject(Param->FileObject);
+         return STATUS_SUCCESS;
+       }
+      KeBugCheck(0);
+    }
+  return DriverObject->MajorFunction[Param->MajorFunction](DeviceObject, Irp);
 }
 
 
@@ -211,6 +219,13 @@ IopCompleteRequest(struct _KAPC* Apc,
                          (KPRIORITY)(*SystemArgument2));
 }
 
+#endif /* LIBCAPTIVE */
+
+
+#ifdef LIBCAPTIVE
+/* file-scope of libcaptive/io/irp.c: */
+extern void IofCompleteRequest_register_APC(PIRP Irp,CCHAR PriorityBoost);
+#endif /* LIBCAPTIVE */
 
 VOID FASTCALL
 IofCompleteRequest(PIRP Irp,
@@ -224,36 +239,75 @@ IofCompleteRequest(PIRP Irp,
  *                         thread making the request
  */
 {
-   unsigned int i;
-   NTSTATUS Status;
-   
+   ULONG             i;
+   NTSTATUS          Status;
+   PDEVICE_OBJECT    DeviceObject;
+
    DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d) Event %x THread %x\n",
-          Irp,PriorityBoost, Irp->UserEvent, PsGetCurrentThread());
+      Irp,PriorityBoost, Irp->UserEvent, PsGetCurrentThread());
+
+   assert(Irp->CancelRoutine == NULL);
+   assert(Irp->IoStatus.Status != STATUS_PENDING);
 
-   for (i=Irp->CurrentLocation;i<Irp->StackCount;i++)
+   if (IoGetCurrentIrpStackLocation(Irp)->Control & SL_PENDING_RETURNED)
    {
-      if (Irp->Stack[i].CompletionRoutine != NULL)
+      Irp->PendingReturned = TRUE;
+   }
+
+   for (i=Irp->CurrentLocation;i<(ULONG)Irp->StackCount;i++)
+   {
+      /*
+      Completion routines expect the current irp stack location to be the same as when
+      IoSetCompletionRoutine was called to set them. A side effect is that completion
+      routines set by highest level drivers without their own stack location will receive
+      an invalid current stack location (at least it should be considered as invalid).
+      Since the DeviceObject argument passed is taken from the current stack, this value
+      is also invalid (NULL).
+      */
+      if (Irp->CurrentLocation < Irp->StackCount - 1)
       {
-        Status = Irp->Stack[i].CompletionRoutine(
-                                            Irp->Stack[i].DeviceObject,
-                                            Irp,
-                                            Irp->Stack[i].CompletionContext);
-        if (Status == STATUS_MORE_PROCESSING_REQUIRED)
-        {
-           return;
-        }
+         IoSetPreviousIrpStackLocation(Irp);
+         DeviceObject = IoGetCurrentIrpStackLocation(Irp)->DeviceObject;
       }
-      if (Irp->Stack[i].Control & SL_PENDING_RETURNED)
+      else
       {
-        Irp->PendingReturned = TRUE;
+         DeviceObject = NULL;
       }
-      if (Irp->CurrentLocation < Irp->StackCount - 1)
+
+      if (Irp->Stack[i].CompletionRoutine != NULL &&
+         ((NT_SUCCESS(Irp->IoStatus.Status) && (Irp->Stack[i].Control & SL_INVOKE_ON_SUCCESS)) ||
+         (!NT_SUCCESS(Irp->IoStatus.Status) && (Irp->Stack[i].Control & SL_INVOKE_ON_ERROR)) ||
+         (Irp->Cancel && (Irp->Stack[i].Control & SL_INVOKE_ON_CANCEL))))
       {
-        IoSkipCurrentIrpStackLocation(Irp);
+         Status = Irp->Stack[i].CompletionRoutine(DeviceObject,
+                                                  Irp,
+                                                  Irp->Stack[i].CompletionContext);
+
+         if (Status == STATUS_MORE_PROCESSING_REQUIRED)
+         {
+           if (Irp->UserIosb)
+              {
+                 *Irp->UserIosb=Irp->IoStatus;
+              }
+            return;
+         }
+      }
+   
+      if (IoGetCurrentIrpStackLocation(Irp)->Control & SL_PENDING_RETURNED)
+      {
+         Irp->PendingReturned = TRUE;
       }
    }
+
    if (Irp->PendingReturned)
      {
+#ifdef LIBCAPTIVE
+       /* FIXME: Why the hell should we bother with some damned APCs?!?
+        * Call it directly below!
+        */
+       DPRINT("IofCompleteRequest() dispatching APC: using g_idle_add_full()\n");
+       IofCompleteRequest_register_APC(Irp,PriorityBoost);
+#else /* !LIBCAPTIVE */
        DPRINT("Dispatching APC\n");
        KeInitializeApc(&Irp->Tail.Apc,
                        &Irp->Tail.Overlay.Thread->Tcb,
@@ -268,6 +322,7 @@ IofCompleteRequest(PIRP Irp,
                         (PVOID)Irp,
                         (PVOID)(ULONG)PriorityBoost,
                         KernelMode);
+#endif /* !LIBCAPTIVE */
        DPRINT("Finished dispatching APC\n");
      }
    else
@@ -310,12 +365,18 @@ IoIsOperationSynchronous(IN PIRP Irp)
 
   /* Check the FILE_OBJECT's flags first. */
   FileObject = IoGetCurrentIrpStackLocation(Irp)->FileObject;
+  if (FileObject == NULL)
+    KeBugCheck(0);
   if (!(FO_SYNCHRONOUS_IO & FileObject->Flags))
     {
       /* Check IRP's flags. */
       Flags = Irp->Flags;
       if (!((IRP_SYNCHRONOUS_API | IRP_SYNCHRONOUS_PAGING_IO) & Flags))
        {
+#ifdef LIBCAPTIVE
+         /* libcaptive is fully single-thread/single-process synchronous model. */
+         return TRUE;
+#endif /* LIBCAPTIVE */
          return(FALSE);
        }
     }
@@ -329,9 +390,14 @@ IoIsOperationSynchronous(IN PIRP Irp)
     }
 
   /* Otherwise, it is an asynchronous operation. */
+#ifdef LIBCAPTIVE
+  /* libcaptive is fully single-thread/single-process synchronous model. */
+  return TRUE;
+#endif /* LIBCAPTIVE */
   return(FALSE);
 }
 
+#ifndef LIBCAPTIVE
 
 VOID STDCALL
 IoEnqueueIrp(IN PIRP Irp)
@@ -339,6 +405,7 @@ IoEnqueueIrp(IN PIRP Irp)
   UNIMPLEMENTED;
 }
 
+#endif /* LIBCAPTIVE */
 
 VOID STDCALL
 IoSetTopLevelIrp(IN PIRP Irp)
@@ -349,7 +416,6 @@ IoSetTopLevelIrp(IN PIRP Irp)
   Thread->TopLevelIrp->TopLevelIrp = Irp;
 }
 
-#endif /* LIBCAPTIVE */
 
 PIRP STDCALL
 IoGetTopLevelIrp(VOID)