+ KIRQL OldIrql;
+ PLIST_ENTRY Entry;
+ PRX_CONTEXT RxContext;
+
+ /* Lock our contexts list */
+ KeAcquireSpinLock(&RxStrucSupSpinLock, &OldIrql);
+
+ /* Now, find a context that matches the cancelled IRP */
+ Entry = RxActiveContexts.Flink;
+ while (Entry != &RxActiveContexts)
+ {
+ RxContext = CONTAINING_RECORD(Entry, RX_CONTEXT, ContextListEntry);
+ Entry = Entry->Flink;
+
+ /* Found! */
+ if (RxContext->CurrentIrp == Irp)
+ {
+ break;
+ }
+ }
+
+ /* If we reached the end of the list, we didn't find any context, so zero the buffer
+ * If the context is already under cancellation, forget about it too
+ */
+ if (Entry == &RxActiveContexts || BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_CANCELLED))
+ {
+ RxContext = NULL;
+ }
+ else
+ {
+ /* Otherwise, reference it and mark it cancelled */
+ SetFlag(RxContext->Flags, RX_CONTEXT_FLAG_CANCELLED);
+ InterlockedIncrement((volatile long *)&RxContext->ReferenceCount);
+ }
+
+ /* Done with the contexts list */
+ KeReleaseSpinLock(&RxStrucSupSpinLock, OldIrql);
+
+ /* And done with the cancellation, we'll do it now */
+ IoReleaseCancelSpinLock(Irp->CancelIrql);
+
+ /* If we have a context to cancel */
+ if (RxContext != NULL)
+ {
+ /* We cannot executed at dispatch, so queue a deferred cancel */
+ if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
+ {
+ RxDispatchToWorkerThread(RxFileSystemDeviceObject, CriticalWorkQueue, RxpCancelRoutine, RxContext);
+ }
+ /* Cancel now! */
+ else
+ {
+ RxpCancelRoutine(RxContext);
+ }
+ }