Функция 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 , чтобы включить отмену.
Примеры
В следующем примере кода показаны части двух функций обратного вызова:
- Функция обратного вызова 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) |