+/*
+ * @implemented
+ */
+VOID
+RxCancelBlockingOperation(
+ IN OUT PRX_CONTEXT RxContext)
+{
+ PFOBX Fobx;
+ BOOLEAN PostRequest;
+ C_ASSERT(FIELD_OFFSET(RX_CONTEXT, IoStatusBlock.Status) == 100);
+
+ PAGED_CODE();
+
+ Fobx = (PFOBX)RxContext->pFobx;
+ PostRequest = FALSE;
+
+ /* Acquire the pipe mutex */
+ ExAcquireFastMutex(&RxContextPerFileSerializationMutex);
+
+ /* If that's a blocking pipe operation which is not the CCB one, then handle it */
+ if (BooleanFlagOn(RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION) &&
+ RxContext->RxContextSerializationQLinks.Flink != NULL &&
+ RxContext != CONTAINING_RECORD(&Fobx->Specific.NamedPipe.ReadSerializationQueue, RX_CONTEXT, RxContextSerializationQLinks) &&
+ RxContext != CONTAINING_RECORD(&Fobx->Specific.NamedPipe.WriteSerializationQueue, RX_CONTEXT, RxContextSerializationQLinks))
+ {
+ /* Clear it! */
+ ClearFlag(RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION);
+
+ /* Drop it off the list */
+ RemoveEntryList(&RxContext->RxContextSerializationQLinks);
+ RxContext->RxContextSerializationQLinks.Flink = NULL;
+ RxContext->RxContextSerializationQLinks.Blink = NULL;
+
+ /* Set we've been cancelled */
+ RxContext->IoStatusBlock.Status = STATUS_CANCELLED;
+
+ /*
+ * If it's async, we'll post completion, otherwise, we signal to waiters
+ * it's being cancelled
+ */
+ if (BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION))
+ {
+ PostRequest = TRUE;
+ }
+ else
+ {
+ RxSignalSynchronousWaiter(RxContext);
+ }
+ }
+
+ /* Done */
+ ExReleaseFastMutex(&RxContextPerFileSerializationMutex);
+
+ /* Post if async */
+ if (PostRequest)
+ {
+ RxFsdPostRequest(RxContext);
+ }
+}
+