Функция WdfRequestUnmarkCancelable (wdfrequest.h)
[Применимо к KMDF и UMDF]
Метод WdfRequestUnmarkCancelable отключает отмену указанного запроса ввода-вывода.
Синтаксис
NTSTATUS WdfRequestUnmarkCancelable(
[in] WDFREQUEST Request
);
Параметры
[in] Request
Дескриптор объекта запроса платформы.
Возвращаемое значение
WdfRequestUnmarkCancelable возвращает STATUS_SUCCESS, если операция выполнена успешно. В противном случае этот метод может возвращать одно из следующих значений:
Код возврата | Описание |
---|---|
|
Входной параметр недопустим или запрос уже нельзя отменить. |
|
Драйвер не является владельцем запроса. |
|
Запрос отменен. |
Этот метод также может возвращать другие значения 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) |