/* FUNCTIONS ****************************************************************/
-#ifndef LIBCAPTIVE
VOID STDCALL
IoFreeIrp(PIRP Irp)
ExFreePool(Irp);
}
+#ifndef LIBCAPTIVE
PIRP STDCALL
IoMakeAssociatedIrp(PIRP Irp,
AssocIrp = IoAllocateIrp(StackSize,FALSE);
UNIMPLEMENTED;
+ return NULL;
}
#endif /* LIBCAPTIVE */
assert(Irp != NULL);
memset(Irp, 0, PacketSize);
+ Irp->Type = IO_TYPE_IRP;
Irp->Size = PacketSize;
Irp->StackCount = StackSize;
Irp->CurrentLocation = StackSize;
* FUNCTION: Sends an IRP to the next lower driver
*/
{
- NTSTATUS Status;
PDRIVER_OBJECT DriverObject;
PIO_STACK_LOCATION Param;
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])
+ KeBugCheck(0);
+ return DriverObject->MajorFunction[Param->MajorFunction](DeviceObject, Irp);
}
(KPRIORITY)(*SystemArgument2));
}
+#endif /* LIBCAPTIVE */
VOID FASTCALL
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);
+
+ if (IoGetCurrentIrpStackLocation(Irp)->Control & SL_PENDING_RETURNED)
+ {
+ Irp->PendingReturned = TRUE;
+ }
- for (i=Irp->CurrentLocation;i<Irp->StackCount;i++)
+ for (i=Irp->CurrentLocation;i<(ULONG)Irp->StackCount;i++)
{
- if (Irp->Stack[i].CompletionRoutine != NULL)
+ /*
+ 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))))
+ {
+ 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)
{
- IoSkipCurrentIrpStackLocation(Irp);
+ Irp->PendingReturned = TRUE;
}
}
+
if (Irp->PendingReturned)
{
DPRINT("Dispatching APC\n");
+#ifndef LIBCAPTIVE
KeInitializeApc(&Irp->Tail.Apc,
&Irp->Tail.Overlay.Thread->Tcb,
0,
(PVOID)(ULONG)PriorityBoost,
KernelMode);
DPRINT("Finished dispatching APC\n");
+#else /* !LIBCAPTIVE */
+ KeBugCheck(0);
+#endif /* !LIBCAPTIVE */
}
else
{
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);
}
}
}
/* 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)