WdfRequestMarkCancelableEx - NtDoc

Native API online documentation, based on the System Informer (formerly Process Hacker) phnt headers
// wdfrequest.h

NTSTATUS WdfRequestMarkCancelableEx(
  [in] WDFREQUEST             Request,
  [in] PFN_WDF_REQUEST_CANCEL EvtRequestCancel
);

View the official Windows Driver Kit DDI reference

NtDoc

No description available.

Windows Driver Kit DDI reference (nf-wdfrequest-wdfrequestmarkcancelableex)

WdfRequestMarkCancelableEx function

Description

[Applies to KMDF and UMDF]

The WdfRequestMarkCancelableEx method enables cancellation of a specified I/O request.

Parameters

Request [in]

A handle to a framework request object.

EvtRequestCancel [in]

A pointer to a driver-defined EvtRequestCancel callback function, which the framework calls if it cancels the I/O request.

Return value

WdfRequestMarkCancelableEx returns STATUS_SUCCESS if it successfully enables cancellation of the specified I/O request. Otherwise, this method might return one of the following values:

Return code Description
STATUS_CANCELLED The I/O request has been canceled. See Remarks for more info.
STATUS_INVALID_DEVICE_REQUEST * The driver does not own the I/O request.
* The I/O request is already cancelable.

This method might also return other NTSTATUS values.

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

Remarks

After your driver has received an I/O request from the framework, the driver can call WdfRequestMarkCancelable or, starting with KMDF version 1.9, WdfRequestMarkCancelableEx to make the request cancelable. For info on choosing between the two methods, see WdfRequestMarkCancelable.

When calling WdfRequestMarkCancelableEx, your driver must specify an EvtRequestCancel callback function. The framework calls the callback function if the I/O manager or another driver is attempting to cancel the I/O request.

If WdfRequestMarkCancelableEx returns failure, the driver must perform the same cancellation activities that the EvtRequestCancel callback function performs. For example:

  1. Finish or stop processing the request, along with subrequests that it might have created.
  2. Call WdfRequestComplete, specifying a status value of STATUS_CANCELLED.

See the code examples below for implementation.

Because WdfRequestMarkCancelableEx never calls EvtRequestCancel, this method is safe from the deadlock risk described in the Remarks of WdfRequestMarkCancelable.

Processing a request after enabling cancellation

After a driver calls WdfRequestMarkCancelableEx to enable canceling, the request remains cancelable while the driver owns the request object, unless the driver calls WdfRequestUnmarkCancelable.

If a driver has called WdfRequestMarkCancelableEx, and if the driver's EvtRequestCancel callback function has not executed and called WdfRequestComplete, the driver must call WdfRequestUnmarkCancelable before it calls WdfRequestComplete outside of the EvtRequestCancel callback function.

If the driver calls WdfRequestForwardToIoQueue to forward the request to a different queue, the following rules apply:

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

Examples

The following code examples show parts of two callback functions:

In the first example, the driver is using the framework's automatic synchronization. In the second example, the driver is providing its own synchronization by using spinlocks.

Example 1: A driver that uses automatic synchronization.

VOID
MyEvtIoRead(
    IN WDFQUEUE  Queue,
    IN WDFREQUEST  Request,
    IN size_t  Length
    )
{
...
    NTSTATUS status;
...
    // Perform request-specific work here
    // (such as creating subrequests
    // to send to an I/O target).
...
    status = WdfRequestMarkCancelableEx(
                                        Request,
                                        MyEvtRequestCancel
                                        );

    if (!NT_SUCCESS(status)) {
       // Remove request-specific work here, because
       // we don't want the work to be done if the
       // request was canceled or an error occurred.

        WdfRequestComplete (Request, status);
    }
...
}

VOID
MyEvtRequestCancel(
    IN WDFREQUEST  Request
 )
{
    // Remove request-specific work here, because
    // we don't want the work to be done if the
    // request was canceled.

    WdfRequestComplete(
                       Request,
                       STATUS_CANCELLED
                       );
}

Example 2: A driver that uses its own synchronization.

VOID
MyEvtIoRead(
    IN WDFQUEUE  Queue,
    IN WDFREQUEST  Request,
    IN size_t  Length
    )
{
...
    NTSTATUS status;
...
    WdfSpinlockAcquire(MyCancelSpinLock);
    // Perform request-specific work here
    // (such as creating subrequests
    // to send to an I/O target).
...
    status = WdfRequestMarkCancelableEx(
                                        Request,
                                        MyEvtRequestCancel
                                        );

    if (!NT_SUCCESS(status)) {
        // Remove request-specific work here, because
        // we don't want the work to be done if the
        // request was canceled or an error occurred.
     }
    WdfSpinlockRelease(MyCancelSpinLock);
    if (!NT_SUCCESS(status)) {
        WdfRequestComplete (
                            Request,
                            Status
                            );
    }
...
}
VOID
MyEvtRequestCancel(
    IN WDFREQUEST  Request
 )
{
    WdfSpinlockAcquire(MyCancelSpinLock);
    // Remove request-specific work here, because
    // we don't want the work to be done if the
    // request was canceled.
    WdfSpinlockRelease(MyCancelSpinLock);
    WdfRequestComplete (Request, STATUS_CANCELLED);
}

See also

EvtRequestCancel

WdfRequestComplete

WdfRequestForwardToIoQueue

WdfRequestMarkCancelable

WdfRequestUnmarkCancelable