WdfRequestUnmarkCancelable function

[Applies to KMDF and UMDF]

The WdfRequestUnmarkCancelable method disables cancellation of a specified I/O request.

Syntax

NTSTATUS WdfRequestUnmarkCancelable(
  WDFREQUEST Request
);

Parameters

Request

A handle to a framework request object.

Return Value

WdfRequestUnmarkCancelable returns STATUS_SUCCESS if the operation succeeds. Otherwise, this method might return one of the following values:

Return code Description
STATUS_INVALID_PARAMETER
An input parameter is invalid or the request is already not cancelable.
STATUS_INVALID_DEVICE_REQUEST
The driver does not own the request.
STATUS_CANCELLED
The request has been canceled.
 

This method might also return other NTSTATUS values.

A bug check occurs if the driver supplies an invalid object handle.

Remarks

A driver can call WdfRequestUnmarkCancelable to disable cancellation of an I/O request, if the driver previously called WdfRequestMarkCancelable or WdfRequestMarkCancelableEx to enable cancellation of the request.

If WdfRequestUnmarkCancelable returns a value other than STATUS_CANCELLED, the driver's EvtRequestCancel callback function will not be called for the request.

If the driver previously called WdfRequestMarkCancelable or WdfRequestMarkCancelableEx, the driver's EvtRequestCancel callback function can call WdfRequestComplete with a Status parameter of STATUS_CANCELLED. The EvtRequestCancel callback function does not have to call WdfRequestUnmarkCancelable. If the driver calls WdfRequestComplete outside of its EvtRequestCancel callback function, the driver must first call WdfRequestUnmarkCancelable.

However, the driver must not call WdfRequestUnmarkCancelable after EvtRequestCancel calls WdfRequestComplete. In the following Example section, the example stores a local copy of the request handle and then clears it when the EvtRequestCancel callback function calls WdfRequestComplete. The driver does not call WdfRequestUnmarkCancelable if the local copy of the request handle has been cleared. This example uses the framework's automatic synchronization to synchronize the callback functions.

Note that calling WdfObjectReference to add an additional reference to the request object does not enable your driver to call WdfRequestUnmarkCancelable after the driver's EvtRequestCancel callback function calls WdfRequestComplete.

If WdfRequestUnmarkCancelable returns STATUS_CANCELLED, and then EvtRequestCancel completes the request, the driver must not subsequently use the request object.

If WdfRequestUnmarkCancelable returns STATUS_CANCELLED, the driver must not complete the request before the framework calls EvtRequestCancel. Otherwise, the framework might call the driver's EvtRequestCancel with an invalid request. For related code examples, please see IWDFIoRequest::UnmarkCancelable.

For more information about WdfRequestUnmarkCancelable, see Canceling I/O Requests.

Examples

The following code example provides simplified versions of the EvtIoRead, EvtRequestCancel and EvtTimerFunc callback functions that the ECHO sample driver contains. This example shows how to call WdfRequestMarkCancelable, WdfRequestUnmarkCancelable, and WdfRequestComplete in a driver that uses the framework's automatic synchronization. (The ECHO sample uses device-level synchronization.)

If your driver does not use the framework's automatic synchronization, see the two examples on IWDFIoRequest::UnmarkCancelable. While written for a UMDF driver, these examples demonstrate techniques you can use to manage synchronization between the cancel callback and another thread that calls the Unmark routine.

VOID
  EchoEvtIoRead(
    IN WDFQUEUE  Queue,
    IN WDFREQUEST  Request,
    IN size_t  Length
    )
{
    PQUEUE_CONTEXT queueContext = QueueGetContext(Queue);
// Prepare for read operation here.
// (See the Echo sample driver for details.) 

... // Enable cancellation. WdfRequestMarkCancelable( Request, EchoEvtRequestCancel );

// Save the request handle. We'll clear it after
// we call WdfRequestComplete.
queueContext->CurrentRequest = Request;
return

}

VOID EchoEvtRequestCancel( IN WDFREQUEST Request ) { PQUEUE_CONTEXT queueContext = QueueGetContext(WdfRequestGetIoQueue(Request));

WdfRequestComplete(
                   Request,
                   STATUS_CANCELLED,
 );
// Clear the request handle so EchEvtTimerFunc will
// know that we called WdfRequestComplete.
queueContext->CurrentRequest = NULL;

return;

}

VOID EchoEvtTimerFunc( IN WDFTIMER Timer ) { NTSTATUS Status; WDFREQUEST Request; WDFQUEUE queue; PQUEUE_CONTEXT queueContext;

// Retrieve our saved copy of the request handle.
queue = WdfTimerGetParentObject(Timer);
queueContext = QueueGetContext(queue);
Request = queueContext->CurrentRequest;

// We cannot call WdfRequestUnmarkCancelable
// after a request completes, so check here to see
// if EchoEvtRequestCancel cleared our saved
// request handle. 
if( Request != NULL ) {
    Status = WdfRequestUnmarkCancelable(Request);
    if(Status != STATUS_CANCELLED) {
        queueContext->CurrentRequest = NULL;
        Status = queueContext->CurrentStatus;
        WdfRequestComplete(
                           Request,
                           Status
                           );
    }
}

return;

}

Requirements

   
Target Platform Universal
Minimum KMDF version 1.0
Minimum UMDF version 2.0
Header wdfrequest.h (include Wdf.h)
Library Wdf01000.sys (KMDF); WUDFx02000.dll (UMDF)
IRQL "<=DISPATCH_LEVEL"
DDI compliance rules CompleteCanceledReq, DeferredRequestCompleted, DriverCreate, EvtIoStopCancel, InvalidReqAccess, InvalidReqAccessLocal, KmdfIrql, KmdfIrql2, MarkCancOnCancReqLocal, ReqIsCancOnCancReq, ReqMarkCancelableSend, ReqNotCanceledLocal

See Also

EvtRequestCancel

WdfRequestComplete

WdfRequestMarkCancelable

WdfRequestMarkCancelableEx