Formatting, add annotations, use doxygen style comments, no functional change

svn path=/trunk/; revision=57953
This commit is contained in:
Timo Kreuzer 2012-12-19 23:33:57 +00:00
parent a011b6bc32
commit ed547ad4a5

View file

@ -30,13 +30,13 @@
#include <ntifs.h> #include <ntifs.h>
static VOID NTAPI IopCsqCancelRoutine(PDEVICE_OBJECT DeviceObject, /*!
PIRP Irp) * @brief Cancel routine that is installed on any IRP that this library manages
/* *
* FUNCTION: Cancel routine that is installed on any IRP that this library manages * @param DeviceObject
* ARGUMENTS: * @param Irp
* [Called back by the system] *
* NOTES: * @note
* - We assume that Irp->Tail.Overlay.DriverContext[3] has either a IO_CSQ * - We assume that Irp->Tail.Overlay.DriverContext[3] has either a IO_CSQ
* or an IO_CSQ_IRP_CONTEXT in it, but we have to figure out which it is * or an IO_CSQ_IRP_CONTEXT in it, but we have to figure out which it is
* - By the time this routine executes, the I/O Manager has already cleared * - By the time this routine executes, the I/O Manager has already cleared
@ -46,135 +46,152 @@ static VOID NTAPI IopCsqCancelRoutine(PDEVICE_OBJECT DeviceObject,
* system * system
* - May be called at high IRQL * - May be called at high IRQL
*/ */
_Function_class_(DRIVER_CANCEL)
static
VOID
NTAPI
IopCsqCancelRoutine(
_Inout_ PDEVICE_OBJECT DeviceObject,
_Inout_ _IRQL_uses_cancel_ PIRP Irp)
{ {
PIO_CSQ Csq; PIO_CSQ Csq;
KIRQL Irql; KIRQL Irql;
/* First things first: */ /* First things first: */
IoReleaseCancelSpinLock(Irp->CancelIrql); IoReleaseCancelSpinLock(Irp->CancelIrql);
/* We could either get a context or just a csq */ /* We could either get a context or just a csq */
Csq = (PIO_CSQ)Irp->Tail.Overlay.DriverContext[3]; Csq = (PIO_CSQ)Irp->Tail.Overlay.DriverContext[3];
if(Csq->Type == IO_TYPE_CSQ_IRP_CONTEXT) if(Csq->Type == IO_TYPE_CSQ_IRP_CONTEXT)
{ {
PIO_CSQ_IRP_CONTEXT Context = (PIO_CSQ_IRP_CONTEXT)Csq; PIO_CSQ_IRP_CONTEXT Context = (PIO_CSQ_IRP_CONTEXT)Csq;
Csq = Context->Csq; Csq = Context->Csq;
/* clean up context while we're here */ /* clean up context while we're here */
Context->Irp = NULL; Context->Irp = NULL;
} }
/* Now that we have our CSQ, complete the IRP */ /* Now that we have our CSQ, complete the IRP */
Csq->CsqAcquireLock(Csq, &Irql); Csq->CsqAcquireLock(Csq, &Irql);
Csq->CsqRemoveIrp(Csq, Irp); Csq->CsqRemoveIrp(Csq, Irp);
Csq->CsqReleaseLock(Csq, Irql); Csq->CsqReleaseLock(Csq, Irql);
Csq->CsqCompleteCanceledIrp(Csq, Irp); Csq->CsqCompleteCanceledIrp(Csq, Irp);
} }
NTSTATUS NTAPI IoCsqInitialize(PIO_CSQ Csq, /*!
PIO_CSQ_INSERT_IRP CsqInsertIrp, * @brief Set up a CSQ struct to initialize the queue
PIO_CSQ_REMOVE_IRP CsqRemoveIrp, *
PIO_CSQ_PEEK_NEXT_IRP CsqPeekNextIrp, * @param Csq - Caller-allocated non-paged space for our IO_CSQ to be initialized
PIO_CSQ_ACQUIRE_LOCK CsqAcquireLock, * @param CsqInsertIrp - Insert routine
PIO_CSQ_RELEASE_LOCK CsqReleaseLock, * @param CsqRemoveIrp - Remove routine
PIO_CSQ_COMPLETE_CANCELED_IRP CsqCompleteCanceledIrp) * @param CsqPeekNextIrp - Routine to paeek at the next IRP in queue
/* * @param CsqAcquireLock - Acquire the queue's lock
* FUNCTION: Set up a CSQ struct to initialize the queue * @param CsqReleaseLock - Release the queue's lock
* ARGUMENTS: * @param CsqCompleteCanceledIrp - Routine to complete IRPs when they are canceled
* Csq: Caller-allocated non-paged space for our IO_CSQ to be initialized *
* CsqInsertIrp: Insert routine * @return
* CsqRemoveIrp: Remove routine
* CsqPeekNextIrp: Routine to paeek at the next IRP in queue
* CsqAcquireLock: Acquire the queue's lock
* CsqReleaseLock: Release the queue's lock
* CsqCompleteCanceledIrp: Routine to complete IRPs when they are canceled
* RETURNS:
* - STATUS_SUCCESS in all cases * - STATUS_SUCCESS in all cases
* NOTES: *
* @note
* - Csq must be non-paged, as the queue is manipulated with a held spinlock * - Csq must be non-paged, as the queue is manipulated with a held spinlock
*/ */
NTSTATUS
NTAPI
IoCsqInitialize(
_Out_ PIO_CSQ Csq,
_In_ PIO_CSQ_INSERT_IRP CsqInsertIrp,
_In_ PIO_CSQ_REMOVE_IRP CsqRemoveIrp,
_In_ PIO_CSQ_PEEK_NEXT_IRP CsqPeekNextIrp,
_In_ PIO_CSQ_ACQUIRE_LOCK CsqAcquireLock,
_In_ PIO_CSQ_RELEASE_LOCK CsqReleaseLock,
_In_ PIO_CSQ_COMPLETE_CANCELED_IRP CsqCompleteCanceledIrp)
{ {
Csq->Type = IO_TYPE_CSQ; Csq->Type = IO_TYPE_CSQ;
Csq->CsqInsertIrp = CsqInsertIrp; Csq->CsqInsertIrp = CsqInsertIrp;
Csq->CsqRemoveIrp = CsqRemoveIrp; Csq->CsqRemoveIrp = CsqRemoveIrp;
Csq->CsqPeekNextIrp = CsqPeekNextIrp; Csq->CsqPeekNextIrp = CsqPeekNextIrp;
Csq->CsqAcquireLock = CsqAcquireLock; Csq->CsqAcquireLock = CsqAcquireLock;
Csq->CsqReleaseLock = CsqReleaseLock; Csq->CsqReleaseLock = CsqReleaseLock;
Csq->CsqCompleteCanceledIrp = CsqCompleteCanceledIrp; Csq->CsqCompleteCanceledIrp = CsqCompleteCanceledIrp;
Csq->ReservePointer = NULL; Csq->ReservePointer = NULL;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
NTSTATUS NTAPI IoCsqInitializeEx(PIO_CSQ Csq, /*!
PIO_CSQ_INSERT_IRP_EX CsqInsertIrpEx, * @brief Set up a CSQ struct to initialize the queue (extended version)
PIO_CSQ_REMOVE_IRP CsqRemoveIrp, *
PIO_CSQ_PEEK_NEXT_IRP CsqPeekNextIrp, * @param Csq - Caller-allocated non-paged space for our IO_CSQ to be initialized
PIO_CSQ_ACQUIRE_LOCK CsqAcquireLock, * @param CsqInsertIrpEx - Extended insert routine
PIO_CSQ_RELEASE_LOCK CsqReleaseLock, * @param CsqRemoveIrp - Remove routine
PIO_CSQ_COMPLETE_CANCELED_IRP CsqCompleteCanceledIrp) * @param CsqPeekNextIrp - Routine to paeek at the next IRP in queue
/* * @param CsqAcquireLock - Acquire the queue's lock
* FUNCTION: Set up a CSQ struct to initialize the queue (extended version) * @param CsqReleaseLock - Release the queue's lock
* ARGUMENTS: * @param CsqCompleteCanceledIrp - Routine to complete IRPs when they are canceled
* Csq: Caller-allocated non-paged space for our IO_CSQ to be initialized *
* CsqInsertIrpEx: Extended insert routine * @return
* CsqRemoveIrp: Remove routine
* CsqPeekNextIrp: Routine to paeek at the next IRP in queue
* CsqAcquireLock: Acquire the queue's lock
* CsqReleaseLock: Release the queue's lock
* CsqCompleteCanceledIrp: Routine to complete IRPs when they are canceled
* RETURNS:
* - STATUS_SUCCESS in all cases * - STATUS_SUCCESS in all cases
* NOTES: * @note
* - Csq must be non-paged, as the queue is manipulated with a held spinlock * - Csq must be non-paged, as the queue is manipulated with a held spinlock
*/ */
NTSTATUS
NTAPI
IoCsqInitializeEx(
_Out_ PIO_CSQ Csq,
_In_ PIO_CSQ_INSERT_IRP_EX CsqInsertIrpEx,
_In_ PIO_CSQ_REMOVE_IRP CsqRemoveIrp,
_In_ PIO_CSQ_PEEK_NEXT_IRP CsqPeekNextIrp,
_In_ PIO_CSQ_ACQUIRE_LOCK CsqAcquireLock,
_In_ PIO_CSQ_RELEASE_LOCK CsqReleaseLock,
_In_ PIO_CSQ_COMPLETE_CANCELED_IRP CsqCompleteCanceledIrp)
{ {
Csq->Type = IO_TYPE_CSQ_EX; Csq->Type = IO_TYPE_CSQ_EX;
Csq->CsqInsertIrp = (PIO_CSQ_INSERT_IRP)CsqInsertIrpEx; Csq->CsqInsertIrp = (PIO_CSQ_INSERT_IRP)CsqInsertIrpEx;
Csq->CsqRemoveIrp = CsqRemoveIrp; Csq->CsqRemoveIrp = CsqRemoveIrp;
Csq->CsqPeekNextIrp = CsqPeekNextIrp; Csq->CsqPeekNextIrp = CsqPeekNextIrp;
Csq->CsqAcquireLock = CsqAcquireLock; Csq->CsqAcquireLock = CsqAcquireLock;
Csq->CsqReleaseLock = CsqReleaseLock; Csq->CsqReleaseLock = CsqReleaseLock;
Csq->CsqCompleteCanceledIrp = CsqCompleteCanceledIrp; Csq->CsqCompleteCanceledIrp = CsqCompleteCanceledIrp;
Csq->ReservePointer = NULL; Csq->ReservePointer = NULL;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
VOID NTAPI IoCsqInsertIrp(PIO_CSQ Csq, /*!
PIRP Irp, * @brief Insert an IRP into the CSQ
PIO_CSQ_IRP_CONTEXT Context) *
/* * @param Csq - Pointer to the initialized CSQ
* FUNCTION: Insert an IRP into the CSQ * @param Irp - Pointer to the IRP to queue
* ARGUMENTS: * @param Context - Context record to track the IRP while queued
* Csq: Pointer to the initialized CSQ *
* Irp: Pointer to the IRP to queue * @return
* Context: Context record to track the IRP while queued
* NOTES:
* - Just passes through to IoCsqInsertIrpEx, with no InsertContext * - Just passes through to IoCsqInsertIrpEx, with no InsertContext
*/ */
VOID
NTAPI
IoCsqInsertIrp(
_Inout_ PIO_CSQ Csq,
_Inout_ PIRP Irp,
_Out_opt_ PIO_CSQ_IRP_CONTEXT Context)
{ {
IoCsqInsertIrpEx(Csq, Irp, Context, 0); IoCsqInsertIrpEx(Csq, Irp, Context, 0);
} }
NTSTATUS NTAPI IoCsqInsertIrpEx(PIO_CSQ Csq, /*!
PIRP Irp, * @brief Insert an IRP into the CSQ, with additional tracking context
PIO_CSQ_IRP_CONTEXT Context, *
PVOID InsertContext) * @param Csq - Pointer to the initialized CSQ
/* * @param Irp - Pointer to the IRP to queue
* FUNCTION: Insert an IRP into the CSQ, with additional tracking context * @param Context - Context record to track the IRP while queued
* ARGUMENTS: * @param InsertContext - additional data that is passed through to CsqInsertIrpEx
* Csq: Pointer to the initialized CSQ *
* Irp: Pointer to the IRP to queue * @note
* Context: Context record to track the IRP while queued
* InsertContext: additional data that is passed through to CsqInsertIrpEx
* NOTES:
* - Passes the additional context through to the driver-supplied callback, * - Passes the additional context through to the driver-supplied callback,
* which can be used with more sophistocated queues * which can be used with more sophistocated queues
* - Marks the IRP pending in all cases * - Marks the IRP pending in all cases
@ -183,205 +200,222 @@ NTSTATUS NTAPI IoCsqInsertIrpEx(PIO_CSQ Csq,
* I'm sure I have gotten the details wrong on a fine point or two, but * I'm sure I have gotten the details wrong on a fine point or two, but
* basically this works with the MS-supplied samples. * basically this works with the MS-supplied samples.
*/ */
NTSTATUS
NTAPI
IoCsqInsertIrpEx(
_Inout_ PIO_CSQ Csq,
_Inout_ PIRP Irp,
_Out_opt_ PIO_CSQ_IRP_CONTEXT Context,
_In_opt_ PVOID InsertContext)
{ {
NTSTATUS Retval = STATUS_SUCCESS; NTSTATUS Retval = STATUS_SUCCESS;
KIRQL Irql; KIRQL Irql;
Csq->CsqAcquireLock(Csq, &Irql); Csq->CsqAcquireLock(Csq, &Irql);
do do
{ {
/* mark all irps pending -- says so in the cancel sample */ /* mark all irps pending -- says so in the cancel sample */
IoMarkIrpPending(Irp); IoMarkIrpPending(Irp);
/* set up the context if we have one */ /* set up the context if we have one */
if(Context) if(Context)
{ {
Context->Type = IO_TYPE_CSQ_IRP_CONTEXT; Context->Type = IO_TYPE_CSQ_IRP_CONTEXT;
Context->Irp = Irp; Context->Irp = Irp;
Context->Csq = Csq; Context->Csq = Csq;
Irp->Tail.Overlay.DriverContext[3] = Context; Irp->Tail.Overlay.DriverContext[3] = Context;
} }
else else
Irp->Tail.Overlay.DriverContext[3] = Csq; Irp->Tail.Overlay.DriverContext[3] = Csq;
/* /*
* NOTE! This is very sensitive to order. If you set the cancel routine * NOTE! This is very sensitive to order. If you set the cancel routine
* *before* you queue the IRP, our cancel routine will get called back for * *before* you queue the IRP, our cancel routine will get called back for
* an IRP that isn't in its queue. * an IRP that isn't in its queue.
* *
* There are three possibilities: * There are three possibilities:
* 1) We get an IRP, we queue it, and it is valid the whole way * 1) We get an IRP, we queue it, and it is valid the whole way
* 2) We get an IRP, and the IO manager cancels it before we're done here * 2) We get an IRP, and the IO manager cancels it before we're done here
* 3) We get an IRP, queue it, and the IO manager cancels it. * 3) We get an IRP, queue it, and the IO manager cancels it.
* *
* #2 is is a booger. * #2 is is a booger.
* *
* When the IO manger receives a request to cancel an IRP, it sets the cancel * When the IO manger receives a request to cancel an IRP, it sets the cancel
* bit in the IRP's control byte to TRUE. Then, it looks to see if a cancel * bit in the IRP's control byte to TRUE. Then, it looks to see if a cancel
* routine is set. If it isn't, the IO manager just returns to the caller. * routine is set. If it isn't, the IO manager just returns to the caller.
* If there *is* a routine, it gets called. * If there *is* a routine, it gets called.
* *
* If we test for cancel first and then set the cancel routine, there is a spot * If we test for cancel first and then set the cancel routine, there is a spot
* between test and set that the IO manager can cancel us without our knowledge, * between test and set that the IO manager can cancel us without our knowledge,
* so we miss a cancel request. That is bad. * so we miss a cancel request. That is bad.
* *
* If we set a routine first and then test for cancel, we race with our completion * If we set a routine first and then test for cancel, we race with our completion
* routine: We set the routine, the IO Manager sets cancel, we test cancel and find * routine: We set the routine, the IO Manager sets cancel, we test cancel and find
* it is TRUE. Meanwhile the IO manager has called our cancel routine already, so * it is TRUE. Meanwhile the IO manager has called our cancel routine already, so
* we can't complete the IRP because it'll rip it out from under the cancel routine. * we can't complete the IRP because it'll rip it out from under the cancel routine.
* *
* The IO manager does us a favor though: it nulls out the cancel routine in the IRP * The IO manager does us a favor though: it nulls out the cancel routine in the IRP
* before calling it. Therefore, if we test to see if the cancel routine is NULL * before calling it. Therefore, if we test to see if the cancel routine is NULL
* (after we have just set it), that means our own cancel routine is already working * (after we have just set it), that means our own cancel routine is already working
* on the IRP, and we can just return quietly. Otherwise, we have to de-queue the * on the IRP, and we can just return quietly. Otherwise, we have to de-queue the
* IRP and cancel it ourselves. * IRP and cancel it ourselves.
* *
* We have to go through all of this mess because this API guarantees that we will * We have to go through all of this mess because this API guarantees that we will
* never return having left a canceled IRP in the queue. * never return having left a canceled IRP in the queue.
*/ */
/* Step 1: Queue the IRP */ /* Step 1: Queue the IRP */
if(Csq->Type == IO_TYPE_CSQ) if(Csq->Type == IO_TYPE_CSQ)
Csq->CsqInsertIrp(Csq, Irp); Csq->CsqInsertIrp(Csq, Irp);
else else
{ {
PIO_CSQ_INSERT_IRP_EX pCsqInsertIrpEx = (PIO_CSQ_INSERT_IRP_EX)Csq->CsqInsertIrp; PIO_CSQ_INSERT_IRP_EX pCsqInsertIrpEx = (PIO_CSQ_INSERT_IRP_EX)Csq->CsqInsertIrp;
Retval = pCsqInsertIrpEx(Csq, Irp, InsertContext); Retval = pCsqInsertIrpEx(Csq, Irp, InsertContext);
if(Retval != STATUS_SUCCESS) if(Retval != STATUS_SUCCESS)
break; break;
} }
/* Step 2: Set our cancel routine */ /* Step 2: Set our cancel routine */
(void)IoSetCancelRoutine(Irp, IopCsqCancelRoutine); (void)IoSetCancelRoutine(Irp, IopCsqCancelRoutine);
/* Step 3: Deal with an IRP that is already canceled */ /* Step 3: Deal with an IRP that is already canceled */
if(!Irp->Cancel) if(!Irp->Cancel)
break; break;
/* /*
* Since we're canceled, see if our cancel routine is already running * Since we're canceled, see if our cancel routine is already running
* If this is NULL, the IO Manager has already called our cancel routine * If this is NULL, the IO Manager has already called our cancel routine
*/ */
if(!IoSetCancelRoutine(Irp, NULL)) if(!IoSetCancelRoutine(Irp, NULL))
break; break;
/* OK, looks like we have to de-queue and complete this ourselves */ /* OK, looks like we have to de-queue and complete this ourselves */
Csq->CsqRemoveIrp(Csq, Irp); Csq->CsqRemoveIrp(Csq, Irp);
Csq->CsqCompleteCanceledIrp(Csq, Irp); Csq->CsqCompleteCanceledIrp(Csq, Irp);
if(Context) if(Context)
Context->Irp = NULL; Context->Irp = NULL;
} }
while(0); while(0);
Csq->CsqReleaseLock(Csq, Irql); Csq->CsqReleaseLock(Csq, Irql);
return Retval; return Retval;
} }
PIRP NTAPI IoCsqRemoveIrp(PIO_CSQ Csq, /*!
PIO_CSQ_IRP_CONTEXT Context) * @brief Remove anb IRP from the queue
/* *
* FUNCTION: Remove anb IRP from the queue * @param Csq - Queue to remove the IRP from
* ARGUMENTS: * @param Context - Context record containing the IRP to be dequeued
* Csq: Queue to remove the IRP from *
* Context: Context record containing the IRP to be dequeued * @return
* RETURNS:
* - Pointer to an IRP if we found it * - Pointer to an IRP if we found it
* NOTES: *
* @note
* - Don't forget that we can be canceled any time up to the point * - Don't forget that we can be canceled any time up to the point
* where we unset our cancel routine * where we unset our cancel routine
*/ */
PIRP
NTAPI
IoCsqRemoveIrp(
_Inout_ PIO_CSQ Csq,
_Inout_ PIO_CSQ_IRP_CONTEXT Context)
{ {
KIRQL Irql; KIRQL Irql;
PIRP Irp = NULL; PIRP Irp = NULL;
Csq->CsqAcquireLock(Csq, &Irql); Csq->CsqAcquireLock(Csq, &Irql);
do do
{ {
/* It's possible that this IRP could have been canceled */ /* It's possible that this IRP could have been canceled */
Irp = Context->Irp; Irp = Context->Irp;
if(!Irp) if(!Irp)
break; break;
/* Unset the cancel routine and see if it has already been canceled */ /* Unset the cancel routine and see if it has already been canceled */
if(!IoSetCancelRoutine(Irp, NULL)) if(!IoSetCancelRoutine(Irp, NULL))
{ {
/* /*
* already gone, return NULL --> NOTE that we cannot touch this IRP *or* the context, * already gone, return NULL --> NOTE that we cannot touch this IRP *or* the context,
* since the context is being simultaneously twiddled by the cancel routine * since the context is being simultaneously twiddled by the cancel routine
*/ */
Irp = NULL; Irp = NULL;
break; break;
} }
/* This IRP is valid and is ours. Dequeue it, fix it up, and return */ /* This IRP is valid and is ours. Dequeue it, fix it up, and return */
Csq->CsqRemoveIrp(Csq, Irp); Csq->CsqRemoveIrp(Csq, Irp);
Context = (PIO_CSQ_IRP_CONTEXT)InterlockedExchangePointer(&Irp->Tail.Overlay.DriverContext[3], NULL); Context = (PIO_CSQ_IRP_CONTEXT)InterlockedExchangePointer(&Irp->Tail.Overlay.DriverContext[3], NULL);
if(Context && Context->Type == IO_TYPE_CSQ_IRP_CONTEXT) if(Context && Context->Type == IO_TYPE_CSQ_IRP_CONTEXT)
Context->Irp = NULL; Context->Irp = NULL;
} }
while(0); while(0);
Csq->CsqReleaseLock(Csq, Irql); Csq->CsqReleaseLock(Csq, Irql);
return Irp; return Irp;
} }
PIRP NTAPI IoCsqRemoveNextIrp(PIO_CSQ Csq, /*!
PVOID PeekContext) * @brief IoCsqRemoveNextIrp - Removes the next IRP from the queue
/* *
* FUNCTION: IoCsqRemoveNextIrp - Removes the next IRP from the queue * @param Csq - Queue to remove the IRP from
* ARGUMENTS: * @param PeekContext - Identifier of the IRP to be removed
* Csq: Queue to remove the IRP from *
* PeekContext: Identifier of the IRP to be removed * @return
* RETURNS:
* Pointer to the IRP that was removed, or NULL if one * Pointer to the IRP that was removed, or NULL if one
* could not be found * could not be found
* NOTES: *
* @note
* - This function is sensitive to yet another race condition. * - This function is sensitive to yet another race condition.
* The basic idea is that we have to return the first IRP that * The basic idea is that we have to return the first IRP that
* we get that matches the PeekContext >that is not already canceled<. * we get that matches the PeekContext >that is not already canceled<.
* Therefore, we have to do a trick similar to the one done in Insert * Therefore, we have to do a trick similar to the one done in Insert
* above. * above.
*/ */
PIRP
NTAPI
IoCsqRemoveNextIrp(
_Inout_ PIO_CSQ Csq,
_In_opt_ PVOID PeekContext)
{ {
KIRQL Irql; KIRQL Irql;
PIRP Irp = NULL; PIRP Irp = NULL;
PIO_CSQ_IRP_CONTEXT Context; PIO_CSQ_IRP_CONTEXT Context;
Csq->CsqAcquireLock(Csq, &Irql); Csq->CsqAcquireLock(Csq, &Irql);
while((Irp = Csq->CsqPeekNextIrp(Csq, Irp, PeekContext))) while((Irp = Csq->CsqPeekNextIrp(Csq, Irp, PeekContext)))
{ {
/* /*
* If the cancel routine is gone, we're already canceled, * If the cancel routine is gone, we're already canceled,
* and are spinning on the queue lock in our own cancel * and are spinning on the queue lock in our own cancel
* routine. Move on to the next candidate. It'll get * routine. Move on to the next candidate. It'll get
* removed by the cance routine. * removed by the cance routine.
*/ */
if(!IoSetCancelRoutine(Irp, NULL)) if(!IoSetCancelRoutine(Irp, NULL))
continue; continue;
Csq->CsqRemoveIrp(Csq, Irp); Csq->CsqRemoveIrp(Csq, Irp);
/* Unset the context stuff and return */ /* Unset the context stuff and return */
Context = (PIO_CSQ_IRP_CONTEXT)InterlockedExchangePointer(&Irp->Tail.Overlay.DriverContext[3], NULL); Context = (PIO_CSQ_IRP_CONTEXT)InterlockedExchangePointer(&Irp->Tail.Overlay.DriverContext[3], NULL);
if(Context && Context->Type == IO_TYPE_CSQ_IRP_CONTEXT) if(Context && Context->Type == IO_TYPE_CSQ_IRP_CONTEXT)
Context->Irp = NULL; Context->Irp = NULL;
break; break;
} }
Csq->CsqReleaseLock(Csq, Irql); Csq->CsqReleaseLock(Csq, Irql);
return Irp; return Irp;
} }