Figure 2   Simple and Incomplete IRP Queuing

// the queue and spinlock should be part of each device context
LIST_ENTRY    irpQueue;
KSPIN_LOCK    irpQueueSpinLock;

VOID InitIrpQueue()
{
    InitializeListHead(&irpQueue);
    KeInitializeSpinLock(&irpQueueSpinLock);
}

VOID EnqueueIrp(PIRP Irp)
{
    KIRQL oldIrql;
 
    something is missing here!

    KeAcquireSpinLock(&irpQueueSpinLock, &oldIrql);
    InsertTailList( &irpQueue, &Irp->Tail.Overlay.ListEntry);
    KeReleaseSpinLock(&irpQueueSpinLock, oldIrql);
}

PIRP DequeueIrp()
{
    KIRQL oldIrql;
    PLIST_ENTRY listEntry;
    PIRP nextIrp = NULL;

    KeAcquireSpinLock(&irpQueueSpinLock, &oldIrql);
    listEntry = RemoveHeadList(&irpQueue);
    KeReleaseSpinLock(&irpQueueSpinLock, oldIrql);
    if (listEntry){
        nextIrp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);
    }

    // something is missing here!

    return nextIrp;
}

Figure 3   IRP Queuing with Cancellation

// the queue and spinlock should be part of each device context
LIST_ENTRY    irpQueue;
KSPIN_LOCK    irpQueueSpinLock;

VOID InitIrpQueue()
{
    InitializeListHead(&irpQueue);
    KeInitializeSpinLock(&irpQueueSpinLock);
}

NTSTATUS EnqueueIrp(PIRP Irp)
{
    PDRIVER_CANCEL  oldCancelRoutine;
    KIRQL oldIrql;
    NTSTATUS status;

    KeAcquireSpinLock(&irpQueueSpinLock, &oldIrql);

    // must set a cancel routine before checking the Cancel flag
    oldCancelRoutine = IoSetCancelRoutine(Irp, IrpCancelRoutine);
    ASSERT(!oldCancelRoutine);

    if (Irp->Cancel){
        // This IRP has already been cancelled, so complete it now.
        // We must clear the cancel routine before completing the IRP.
        // We must release the spinlock before calling out of the driver.
        IoSetCancelRoutine(Irp, NULL);
        KeReleaseSpinLock(&irpQueueSpinLock, oldIrql);
        status = Irp->IoStatus.Status = STATUS_CANCELLED;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
    }
    else {
        // This macro sets a bit in the current stack location to indicate that
        // the IRP may complete on a different thread.
        IoMarkIrpPending(Irp);

        InsertTailList( &irpQueue, &Irp->Tail.Overlay.ListEntry);
        KeReleaseSpinLock(&irpQueueSpinLock, oldIrql);
        status = STATUS_SUCCESS;
    }

    return status;
}

Figure 4   IRP Dequeuing with Cancellation

PIRP DequeueIrp()
{
    KIRQL oldIrql;
    PIRP nextIrp = NULL;

    KeAcquireSpinLock(&irpQueueSpinLock, &oldIrql);

    while (!nextIrp && !IsListEmpty(&irpQueue)){
        PLIST_ENTRY  listEntry = RemoveHeadList(&irpQueue);

        nextIrp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);
        IoSetCancelRoutine(nextIrp, NULL);
        if (nextIrp->Cancel){
            // This IRP was just cancelled.
            // The cancel routine may or may not have been called,
            // but it doesn't matter because it will not find the IRP in the
            // list.
            // Must release the spinlock when calling outside the driver to
            // complete the IRP.
            KeReleaseSpinLock(&irpQueueSpinLock, oldIrql);
            nextIrp->IoStatus.Status = STATUS_CANCELLED;
            IoCompleteRequest(nextIrp, IO_NO_INCREMENT);
            KeAcquireSpinLock(&irpQueueSpinLock, &oldIrql);
            nextIrp = NULL;
        }
    }

    KeReleaseSpinLock(&irpQueueSpinLock, oldIrql);
    return nextIrp;
}

Figure 5   IrpCancelRoutine

VOID IrpCancelRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    KIRQL oldIrql;
    PIRP firstIrp = NULL, irpToComplete = NULL;

    // In this implementation, I don't assume that the IRP being cancelled is
    // in the queue;
    // I only complete the IRP if it IS in the queue.

    KeAcquireSpinLock(&irpQueueSpinLock, &oldIrql);

    while (!IsListEmpty(&irpQueue)){
        PLIST_ENTRY listEntry;
        PIRP thisIrp;

        listEntry = RemoveHeadList(&irpQueue);
        thisIrp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);

        if (thisIrp == Irp){
            // This is the IRP being cancelled; we'll complete it after we
            // release the spinlock
            ASSERT(thisIrp->Cancel);
            irpToComplete = thisIrp;

            // keep looping so that order of the remaining IRPs is preserved
        }
        else {
            // This is not the IRP being cancelled, so put it back
            if (thisIrp == firstIrp){
                // finished going through the list
                InsertHeadList(&irpQueue, listEntry);
                break;
            }
            else {
                InsertTailList(&irpQueue, listEntry);

                if (!firstIrp){
                    firstIrp = thisIrp;
                }
            }
        }
    }

    KeReleaseSpinLock(&irpQueueSpinLock, oldIrql);

    // Finally, release the global cancel spinlock whether or not we are
    // completing this IRP
    IoReleaseCancelSpinLock(Irp->CancelIrql);

    if (irpToComplete){
        // complete this cancelled IRP only if it was in the list
        irpToComplete ->IoStatus.Status = STATUS_CANCELLED;
        IoCompleteRequest(irpToComplete, IO_NO_INCREMENT);
    }
}