static VOID NTAPI IopCsqCancelRoutine( _Inout_ PDEVICE_OBJECT DeviceObject, _Inout_ _IRQL_uses_cancel_ PIRP Irp) { PIO_CSQ Csq; KIRQL Irql; /* First things first: */ IoReleaseCancelSpinLock(Irp->CancelIrql); /* We could either get a context or just a csq */ Csq = (PIO_CSQ)Irp->Tail.Overlay.DriverContext[3]; if(Csq->Type == IO_TYPE_CSQ_IRP_CONTEXT) { PIO_CSQ_IRP_CONTEXT Context = (PIO_CSQ_IRP_CONTEXT)Csq; Csq = Context->Csq; /* clean up context while we're here */ Context->Irp = NULL; } /* Now that we have our CSQ, complete the IRP */ Csq->CsqAcquireLock(Csq, &Irql); Csq->CsqRemoveIrp(Csq, Irp); Csq->CsqReleaseLock(Csq, Irql); Csq->CsqCompleteCanceledIrp(Csq, Irp); }
VOID IopCsqCancelRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine removes the IRP that's associated with a context from the queue. It's expected that this routine will be called from a timer or DPC or other threads which complete an IO. Note that the IRP associated with this context could already have been freed. Arguments: Csq - Pointer to the cancel queue. Context - Context associated with Irp. Return Value: Returns the IRP associated with the context. If the value is not NULL, the IRP was successfully retrieved and can be used safely. If the value is NULL, the IRP was already canceled. --*/ { KIRQL irql; PIO_CSQ_IRP_CONTEXT irpContext; PIO_CSQ cfq; UNREFERENCED_PARAMETER (DeviceObject); IoReleaseCancelSpinLock(Irp->CancelIrql); irpContext = Irp->Tail.Overlay.DriverContext[3]; if (irpContext->Type == IO_TYPE_CSQ_IRP_CONTEXT) { cfq = irpContext->Csq; } else if ((irpContext->Type == IO_TYPE_CSQ) || (irpContext->Type == IO_TYPE_CSQ_EX)) { cfq = (PIO_CSQ)irpContext; } else { // // Bad type // ASSERT(0); return; } ASSERT(cfq); cfq->ReservePointer = NULL; // Force drivers to be good citizens cfq->CsqAcquireLock(cfq, &irql); cfq->CsqRemoveIrp(cfq, Irp); // // Break the association if necessary. // if (irpContext != (PIO_CSQ_IRP_CONTEXT)cfq) { irpContext->Irp = NULL; Irp->Tail.Overlay.DriverContext[3] = NULL; } cfq->CsqReleaseLock(cfq, irql); cfq->CsqCompleteCanceledIrp(cfq, Irp); }