mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 17:42:58 +00:00
- 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:
parent
78277ca08f
commit
caaa87bbdc
1 changed files with 66 additions and 36 deletions
|
@ -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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue