- 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.

svn path=/trunk/; revision=22706
This commit is contained in:
Alex Ionescu 2006-06-30 04:29:32 +00:00
parent 78277ca08f
commit caaa87bbdc

View file

@ -14,6 +14,10 @@
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
/* Undefine some macros we implement here */
#undef IoCallDriver
#undef IoCompleteRequest
ULONG IopTraceLevel = IO_IRP_DEBUG; ULONG IopTraceLevel = IO_IRP_DEBUG;
/* PRIVATE FUNCTIONS ********************************************************/ /* PRIVATE FUNCTIONS ********************************************************/
@ -843,40 +847,61 @@ IoBuildSynchronousFsdRequest(IN ULONG MajorFunction,
*/ */
BOOLEAN BOOLEAN
NTAPI NTAPI
IoCancelIrp(PIRP Irp) IoCancelIrp(IN PIRP Irp)
{ {
KIRQL oldlvl; KIRQL OldIrql;
PDRIVER_CANCEL CancelRoutine; PDRIVER_CANCEL CancelRoutine;
DPRINT("IoCancelIrp(Irp 0x%p)\n",Irp); /* Acquire the cancel lock and cancel the IRP */
IOTRACE(IO_IRP_DEBUG,
IoAcquireCancelSpinLock(&oldlvl); "%s - Canceling IRP %p\n",
__FUNCTION__,
Irp);
IoAcquireCancelSpinLock(&OldIrql);
Irp->Cancel = TRUE; Irp->Cancel = TRUE;
/* Clear the cancel routine and get the old one */
CancelRoutine = IoSetCancelRoutine(Irp, NULL); CancelRoutine = IoSetCancelRoutine(Irp, NULL);
if (CancelRoutine == NULL) if (CancelRoutine)
{ {
IoReleaseCancelSpinLock(oldlvl); /* We had a routine, make sure the IRP isn't completed */
return(FALSE); if (Irp->CurrentLocation > (Irp->StackCount + 1))
{
/* It is, bugcheck */
KeBugCheckEx(CANCEL_STATE_IN_COMPLETED_IRP,
(ULONG_PTR)Irp,
0,
0,
0);
} }
Irp->CancelIrql = oldlvl; /* Set the cancel IRQL And call the routine */
Irp->CancelIrql = OldIrql;
CancelRoutine(IoGetCurrentIrpStackLocation(Irp)->DeviceObject, Irp); CancelRoutine(IoGetCurrentIrpStackLocation(Irp)->DeviceObject, Irp);
return(TRUE); return TRUE;
}
/* Otherwise, release the cancel lock and fail */
IoReleaseCancelSpinLock(OldIrql);
return FALSE;
} }
/* /*
* @name IoCancelThreadIo * @implemented
*/ */
VOID VOID
NTAPI NTAPI
IoCancelThreadIo(PETHREAD Thread) IoCancelThreadIo(IN PETHREAD Thread)
{ {
PIRP Irp; PIRP Irp;
KIRQL OldIrql; KIRQL OldIrql;
ULONG Retries = 3000; ULONG Retries = 3000;
LARGE_INTEGER Interval; LARGE_INTEGER Interval;
IOTRACE(IO_IRP_DEBUG,
"%s - Canceling IRPs for Thread %p\n",
__FUNCTION__,
Thread);
/* Raise to APC to protect the IrpList */ /* Raise to APC to protect the IrpList */
OldIrql = KfRaiseIrql(APC_LEVEL); OldIrql = KfRaiseIrql(APC_LEVEL);
@ -904,7 +929,7 @@ IoCancelThreadIo(PETHREAD Thread)
* Don't stay here forever if some broken driver doesn't complete * Don't stay here forever if some broken driver doesn't complete
* the IRP. * the IRP.
*/ */
if (Retries-- == 0) IopRemoveThreadIrp(); if (!(Retries--)) IopRemoveThreadIrp();
/* Raise the IRQL Again */ /* Raise the IRQL Again */
OldIrql = KfRaiseIrql(APC_LEVEL); OldIrql = KfRaiseIrql(APC_LEVEL);
@ -914,9 +939,6 @@ IoCancelThreadIo(PETHREAD Thread)
KfLowerIrql(OldIrql); KfLowerIrql(OldIrql);
} }
#ifdef IoCallDriver
#undef IoCallDriver
#endif
/* /*
* @implemented * @implemented
*/ */
@ -932,7 +954,6 @@ IoCallDriver(PDEVICE_OBJECT DeviceObject,
/* /*
* @implemented * @implemented
*/ */
#undef IoCompleteRequest
VOID VOID
NTAPI NTAPI
IoCompleteRequest(PIRP Irp, IoCompleteRequest(PIRP Irp,
@ -949,6 +970,7 @@ VOID
NTAPI NTAPI
IoEnqueueIrp(IN PIRP Irp) IoEnqueueIrp(IN PIRP Irp)
{ {
/* This is the same as calling IoQueueThreadIrp */
IoQueueThreadIrp(Irp); IoQueueThreadIrp(Irp);
} }
@ -966,11 +988,17 @@ IofCallDriver(PDEVICE_OBJECT DeviceObject,
/* Get the Driver Object */ /* Get the Driver Object */
DriverObject = DeviceObject->DriverObject; DriverObject = DeviceObject->DriverObject;
/* Set the Stack Location */ /* Decrease the current location and check if */
IoSetNextIrpStackLocation(Irp); 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);
}
/* Get the current one */ /* Now update the stack location */
Param = IoGetCurrentIrpStackLocation(Irp); Param = IoGetNextIrpStackLocation(Irp);
Irp->Tail.Overlay.CurrentStackLocation = Param;
/* Get the Device Object */ /* Get the Device Object */
Param->DeviceObject = DeviceObject; Param->DeviceObject = DeviceObject;
@ -980,9 +1008,6 @@ IofCallDriver(PDEVICE_OBJECT DeviceObject,
Irp); Irp);
} }
#ifdef IoCompleteRequest
#undef IoCompleteRequest
#endif
/* /*
* @implemented * @implemented
*/ */
@ -1242,6 +1267,14 @@ IoFreeIrp(PIRP Irp)
PNPAGED_LOOKASIDE_LIST List; PNPAGED_LOOKASIDE_LIST List;
PP_NPAGED_LOOKASIDE_NUMBER ListType = LookasideSmallIrpList; PP_NPAGED_LOOKASIDE_NUMBER ListType = LookasideSmallIrpList;
PKPRCB Prcb; 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 this was a pool alloc, free it with the pool */
if (!(Irp->AllocationFlags & IRP_ALLOCATED_FIXED_SIZE)) if (!(Irp->AllocationFlags & IRP_ALLOCATED_FIXED_SIZE))
@ -1252,10 +1285,7 @@ IoFreeIrp(PIRP Irp)
else else
{ {
/* Check if this was a Big IRP */ /* Check if this was a Big IRP */
if (Irp->StackCount != 1) if (Irp->StackCount != 1) ListType = LookasideLargeIrpList;
{
ListType = LookasideLargeIrpList;
}
/* Get the PRCB */ /* Get the PRCB */
Prcb = KeGetCurrentPrcb(); Prcb = KeGetCurrentPrcb();
@ -1284,7 +1314,7 @@ IoFreeIrp(PIRP Irp)
} }
} }
/* The free was within dhe Depth */ /* The free was within the Depth */
if (Irp) if (Irp)
{ {
InterlockedPushEntrySList(&List->L.ListHead, InterlockedPushEntrySList(&List->L.ListHead,