Author: ion Date: Fri Jun 30 08:29:32 2006 New Revision: 22706
URL: http://svn.reactos.org/svn/reactos?rev=22706&view=rev Log: - Add more tracing/name decoration/comments. - Bugcheck if cancelling and IRP that's already been completed. - Bugcheck if attempting to call a driver with an IRP that's already past its maximum stack size. - Make sure that when we free an IRP, it's not associated to a thread anymore, nor having any drivers that think it's valid.
Modified: trunk/reactos/ntoskrnl/io/irp.c
Modified: trunk/reactos/ntoskrnl/io/irp.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/irp.c?rev=22706... ============================================================================== --- trunk/reactos/ntoskrnl/io/irp.c (original) +++ trunk/reactos/ntoskrnl/io/irp.c Fri Jun 30 08:29:32 2006 @@ -13,6 +13,10 @@ #include <ntoskrnl.h> #define NDEBUG #include <internal/debug.h> + +/* Undefine some macros we implement here */ +#undef IoCallDriver +#undef IoCompleteRequest
ULONG IopTraceLevel = IO_IRP_DEBUG;
@@ -843,40 +847,61 @@ */ BOOLEAN NTAPI -IoCancelIrp(PIRP Irp) -{ - KIRQL oldlvl; - PDRIVER_CANCEL CancelRoutine; - - DPRINT("IoCancelIrp(Irp 0x%p)\n",Irp); - - IoAcquireCancelSpinLock(&oldlvl); - - Irp->Cancel = TRUE; - - CancelRoutine = IoSetCancelRoutine(Irp, NULL); - if (CancelRoutine == NULL) - { - IoReleaseCancelSpinLock(oldlvl); - return(FALSE); - } - - Irp->CancelIrql = oldlvl; - CancelRoutine(IoGetCurrentIrpStackLocation(Irp)->DeviceObject, Irp); - return(TRUE); -} - -/* - * @name IoCancelThreadIo +IoCancelIrp(IN PIRP Irp) +{ + KIRQL OldIrql; + PDRIVER_CANCEL CancelRoutine; + + /* Acquire the cancel lock and cancel the IRP */ + IOTRACE(IO_IRP_DEBUG, + "%s - Canceling IRP %p\n", + __FUNCTION__, + Irp); + + IoAcquireCancelSpinLock(&OldIrql); + Irp->Cancel = TRUE; + + /* Clear the cancel routine and get the old one */ + CancelRoutine = IoSetCancelRoutine(Irp, NULL); + if (CancelRoutine) + { + /* We had a routine, make sure the IRP isn't completed */ + if (Irp->CurrentLocation > (Irp->StackCount + 1)) + { + /* It is, bugcheck */ + KeBugCheckEx(CANCEL_STATE_IN_COMPLETED_IRP, + (ULONG_PTR)Irp, + 0, + 0, + 0); + } + + /* Set the cancel IRQL And call the routine */ + Irp->CancelIrql = OldIrql; + CancelRoutine(IoGetCurrentIrpStackLocation(Irp)->DeviceObject, Irp); + return TRUE; + } + + /* Otherwise, release the cancel lock and fail */ + IoReleaseCancelSpinLock(OldIrql); + return FALSE; +} + +/* + * @implemented */ VOID NTAPI -IoCancelThreadIo(PETHREAD Thread) +IoCancelThreadIo(IN PETHREAD Thread) { PIRP Irp; KIRQL OldIrql; ULONG Retries = 3000; LARGE_INTEGER Interval; + IOTRACE(IO_IRP_DEBUG, + "%s - Canceling IRPs for Thread %p\n", + __FUNCTION__, + Thread);
/* Raise to APC to protect the IrpList */ OldIrql = KfRaiseIrql(APC_LEVEL); @@ -904,19 +929,16 @@ * Don't stay here forever if some broken driver doesn't complete * the IRP. */ - if (Retries-- == 0) IopRemoveThreadIrp(); + if (!(Retries--)) IopRemoveThreadIrp();
/* Raise the IRQL Again */ OldIrql = KfRaiseIrql(APC_LEVEL); } - + /* We're done, lower the IRQL */ KfLowerIrql(OldIrql); }
-#ifdef IoCallDriver -#undef IoCallDriver -#endif /* * @implemented */ @@ -932,7 +954,6 @@ /* * @implemented */ -#undef IoCompleteRequest VOID NTAPI IoCompleteRequest(PIRP Irp, @@ -949,6 +970,7 @@ NTAPI IoEnqueueIrp(IN PIRP Irp) { + /* This is the same as calling IoQueueThreadIrp */ IoQueueThreadIrp(Irp); }
@@ -966,11 +988,17 @@ /* Get the Driver Object */ DriverObject = DeviceObject->DriverObject;
- /* Set the Stack Location */ - IoSetNextIrpStackLocation(Irp); - - /* Get the current one */ - Param = IoGetCurrentIrpStackLocation(Irp); + /* Decrease the current location and check if */ + Irp->CurrentLocation--; + if (Irp->CurrentLocation <= 0) + { + /* This IRP ran out of stack, bugcheck */ + KeBugCheckEx(NO_MORE_IRP_STACK_LOCATIONS, (ULONG_PTR)Irp, 0, 0, 0); + } + + /* Now update the stack location */ + Param = IoGetNextIrpStackLocation(Irp); + Irp->Tail.Overlay.CurrentStackLocation = Param;
/* Get the Device Object */ Param->DeviceObject = DeviceObject; @@ -980,9 +1008,6 @@ Irp); }
-#ifdef IoCompleteRequest -#undef IoCompleteRequest -#endif /* * @implemented */ @@ -1242,7 +1267,15 @@ PNPAGED_LOOKASIDE_LIST List; PP_NPAGED_LOOKASIDE_NUMBER ListType = LookasideSmallIrpList; PKPRCB Prcb; - + IOTRACE(IO_IRP_DEBUG, + "%s - Freeing IRPs %p\n", + __FUNCTION__, + Irp); + + /* Make sure the Thread IRP list is empty and that it OK to free it */ + ASSERT(IsListEmpty(&Irp->ThreadListEntry)); + ASSERT(Irp->CurrentLocation >= Irp->StackCount); + /* If this was a pool alloc, free it with the pool */ if (!(Irp->AllocationFlags & IRP_ALLOCATED_FIXED_SIZE)) { @@ -1252,10 +1285,7 @@ else { /* Check if this was a Big IRP */ - if (Irp->StackCount != 1) - { - ListType = LookasideLargeIrpList; - } + if (Irp->StackCount != 1) ListType = LookasideLargeIrpList;
/* Get the PRCB */ Prcb = KeGetCurrentPrcb(); @@ -1284,7 +1314,7 @@ } }
- /* The free was within dhe Depth */ + /* The free was within the Depth */ if (Irp) { InterlockedPushEntrySList(&List->L.ListHead,