Функция WdfRequestUnmarkCancelable (wdfrequest.h)

[Применимо к KMDF и UMDF]

Метод WdfRequestUnmarkCancelable отключает отмену указанного запроса ввода-вывода.

Синтаксис

NTSTATUS WdfRequestUnmarkCancelable(
  [in] WDFREQUEST Request
);

Параметры

[in] Request

Дескриптор объекта запроса платформы.

Возвращаемое значение

WdfRequestUnmarkCancelable возвращает STATUS_SUCCESS, если операция выполнена успешно. В противном случае этот метод может возвращать одно из следующих значений:

Код возврата Описание
STATUS_INVALID_PARAMETER
Входной параметр недопустим или запрос уже нельзя отменить.
STATUS_INVALID_DEVICE_REQUEST
Драйвер не является владельцем запроса.
STATUS_CANCELLED
Запрос отменен.
 

Этот метод также может возвращать другие значения NTSTATUS.

Ошибка проверка возникает, если драйвер предоставляет недопустимый дескриптор объекта.

Комментарии

Драйвер может вызвать WdfRequestUnmarkCancelable , чтобы отключить отмену запроса ввода-вывода, если драйвер ранее назывался WdfRequestMarkCancelable или WdfRequestMarkCancelableEx , чтобы включить отмену запроса.

Если WdfRequestUnmarkCancelable возвращает значение, отличное от STATUS_CANCELLED, функция обратного вызова EvtRequestCancel драйвера не будет вызываться для запроса.

Если драйвер ранее назывался WdfRequestMarkCancelable или WdfRequestMarkCancelableEx, функция обратного вызова EvtRequestCancel драйвера может вызывать WdfRequestComplete с параметром Status STATUS_CANCELLED. Функция обратного вызова EvtRequestCancel не требует вызова WdfRequestUnmarkCancelable. Если драйвер вызывает WdfRequestComplete вне функции обратного вызова EvtRequestCancel , драйвер должен сначала вызвать WdfRequestUnmarkCancelable.

Однако драйвер не должен вызывать WdfRequestUnmarkCancelable после того , как EvtRequestCancel вызывает WdfRequestComplete. В следующем разделе пример сохраняет локальную копию дескриптора запроса, а затем очищает ее, когда функция обратного вызова EvtRequestCancel вызывает WdfRequestComplete. Драйвер не вызывает WdfRequestUnmarkCancelable , если удалена локальная копия дескриптора запроса. В этом примере используется автоматическая синхронизация платформы для синхронизации функций обратного вызова.

Обратите внимание, что вызов WdfObjectReference для добавления дополнительной ссылки на объект запроса не позволяет драйверу вызывать WdfRequestUnmarkCancelable после того, как функция обратного вызова EvtRequestCancel драйвера вызывает WdfRequestComplete.

Если WdfRequestUnmarkCancelable возвращает STATUS_CANCELLED, а затем EvtRequestCancel завершает запрос, драйвер не должен впоследствии использовать объект запроса.

Если WdfRequestUnmarkCancelable возвращает STATUS_CANCELLED, драйвер не должен выполнять запрос, прежде чем платформа вызовет EvtRequestCancel. В противном случае платформа может вызвать EvtRequestCancel драйвера с недопустимым запросом. Примеры связанного кода см. в разделе IWDFIoRequest::UnmarkCancelable.

Дополнительные сведения о WdfRequestUnmarkCancelable см. в разделе Отмена запросов ввода-вывода.

Примеры

В следующем примере кода представлены упрощенные версии функций обратного вызова EvtIoRead, EvtRequestCancel и EvtTimerFunc , которые содержит пример драйвера ECHO . В этом примере показано, как вызвать WdfRequestMarkCancelable, WdfRequestUnmarkCancelable и WdfRequestComplete в драйвере, который использует автоматическую синхронизацию платформы. (В примере ECHO используется синхронизация на уровне устройства.)

Если драйвер не использует автоматическую синхронизацию платформы, см. два примера в IWDFIoRequest::UnmarkCancelable. Хотя эти примеры написаны для драйвера UMDF, демонстрируют методы, которые можно использовать для управления синхронизацией между обратным вызовом отмены и другим потоком, который вызывает подпрограмму unmark .

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;
}

Требования

Требование Значение
Целевая платформа Универсальное
Минимальная версия KMDF 1,0
Минимальная версия UMDF 2,0
Верхняя часть wdfrequest.h (включая Wdf.h)
Библиотека Wdf01000.sys (KMDF); WUDFx02000.dll (UMDF)
IRQL <=DISPATCH_LEVEL
Правила соответствия DDI CompleteCanceledReq(kmdf), DeferredRequestCompleted(kmdf), DriverCreate(kmdf), EvtIoStopCancel(kmdf), InvalidReqAccess(kmdf), InvalidReqAccessLocal(kmdf), KmdfIrql(kmdf), KmdfIrql2(kmdf), KmdfIrqlExplicit(kmdf), MarkCancOnCancReqLocal(kmdf), ReqIsCancOnCancReqReq(kmdf), ReqMarkCancelableSend(kmdf), ReqNotCanceledLocal(kmdf)

См. также раздел

EvtRequestCancel

WdfRequestComplete

WdfRequestMarkCancelable

WdfRequestMarkCancelableEx