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

[Относится к KMDF и UMDF]

Метод WdfRequestMarkCancelable позволяет отменить указанный запрос ввода-вывода.

Синтаксис

void WdfRequestMarkCancelable(
  [in] WDFREQUEST             Request,
  [in] PFN_WDF_REQUEST_CANCEL EvtRequestCancel
);

Параметры

[in] Request

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

[in] EvtRequestCancel

Указатель на определяемую драйвером функцию обратного вызова EvtRequestCancel , которую платформа вызывает при отмене запроса ввода-вывода.

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

None

Remarks

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

После того как драйвер получит запрос ввода-вывода от платформы, драйвер может вызвать WdfRequestMarkCancelable или, начиная с KMDF версии 1.9, WdfRequestMarkCancelableEx , чтобы сделать запрос отмененным.

При вызове WdfRequestMarkCancelable драйвер должен указать функцию обратного вызова EvtRequestCancel . Платформа вызывает функцию обратного вызова, если диспетчер ввода-вывода или другой драйвер пытается отменить запрос ввода-вывода.

Выбор между WdfRequestMarkCancelable и WdfRequestMarkCancelableEx

Если драйвер использует автоматическую синхронизацию платформы, драйвер может вызвать WdfRequestMarkCancelable или WdfRequestMarkCancelableEx.

Если драйвер не использует автоматическую синхронизацию, он должен вызывать WdfRequestMarkCancelableEx вместо WdfRequestMarkCancelable по следующим причинам:

  • Если указанный запрос уже отменен, WdfRequestMarkCancelable вызывает функцию обратного вызова EvtRequestCancel драйвера перед возвратом. Если драйвер получает спин-блокировку перед вызовом WdfRequestMarkCancelable и пытается получить ту же спин-блокировку внутри EvtRequestCancel, один и тот же поток дважды пытается получить одну и ту же спин-блокировку, вызывая взаимоблокировку.
  • Однако, поскольку WdfRequestMarkCancelableEx никогда не вызывает EvtRequestCancel, этот сценарий не происходит. Если запрос уже отменен, WdfRequestMarkCancelableEx возвращает STATUS_CANCELLED. Если драйвер получает спин-блокировку (которая устанавливает для IRQL значение DISPATCH_LEVEL) перед вызовом WdfRequestMarkCancelableEx и освобождает спин-блокировку (которая устанавливает irQL в значение PASSIVE_LEVEL) после возврата WdfRequestMarkCancelableEx , функция обратного вызова EvtRequestCancel не будет вызываться до освобождения спин-блокировки. Таким образом, взаимоблокировка не возникает, даже если функция обратного вызова EvtRequestCancel использует ту же спин-блокировку.

Обработка запроса после включения отмены

После вызова драйвером WdfRequestMarkCancelable для включения отмены запрос остается отменяемым, пока драйвер владеет объектом запроса, если только драйвер не вызывает WdfRequestUnmarkCancelable.

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

Если драйвер вызывает WdfRequestForwardToIoQueue для переадресации запроса в другую очередь, применяются следующие правила:

  • Запросы ввода-вывода нельзя отменить, если ваш драйвер перенаправит их в другую очередь.

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

  • Пока запрос находится во второй очереди, платформа владеет им и может отменить его, не уведомляя драйвер.

    Если драйвер требует уведомления об отмене (чтобы он мог освободить все ресурсы, выделенные перед вызовом WdfRequestForwardToIoQueue), драйвер должен зарегистрировать функцию обратного вызова EvtIoCanceledOnQueue и использовать контекстную память для запроса для хранения сведений о ресурсах запроса.

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

Примеры

В следующем примере кода показаны части двух функций обратного вызова:

  • Функция обратного вызова EvtIoRead , которая выполняет работу, зависят от запроса (например, создает вложенные запросы для отправки в целевой объект ввода-вывода), а затем включает отмену полученного запроса ввода-вывода.
  • Функция обратного вызова EvtRequestCancel , которая отменяет запрос ввода-вывода.
Драйвер должен использовать автоматическую синхронизацию платформы.
VOID
MyEvtIoRead(
    IN WDFQUEUE  Queue,
    IN WDFREQUEST  Request,
    IN size_t  Length
    )
{
...
    // Perform request-specific work here
    // (such as creating subrequests 
    // to send to an I/O target). 
...
    WdfRequestMarkCancelable(
                             Request,
                             MyEvtRequestCancel
                             );
    }
...
}
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
                       );
}

Требования

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

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

EvtRequestCancel

WdfRequestComplete

WdfRequestForwardToIoQueue

WdfRequestMarkCancelableEx

WdfRequestUnmarkCancelable