WdfRequestUnmarkCancelable 함수(wdfrequest.h)
[KMDF 및 UMDF에 적용]
WdfRequestUnmarkCancelable 메서드는 지정된 I/O 요청의 취소를 사용하지 않도록 설정합니다.
구문
NTSTATUS WdfRequestUnmarkCancelable(
[in] WDFREQUEST Request
);
매개 변수
[in] Request
프레임워크 요청 개체에 대한 핸들입니다.
반환 값
WdfRequestUnmarkCancelable 은 작업이 성공하면 STATUS_SUCCESS 반환합니다. 그렇지 않으면 이 메서드는 다음 값 중 하나를 반환할 수 있습니다.
반환 코드 | 설명 |
---|---|
|
입력 매개 변수가 잘못되었거나 요청을 취소할 수 없습니다. |
|
드라이버는 요청을 소유하지 않습니다. |
|
요청이 취소되었습니다. |
이 메서드는 다른 NTSTATUS 값을 반환할 수도 있습니다.
드라이버가 잘못된 개체 핸들을 제공하는 경우 버그 검사 발생합니다.
설명
드라이버가 이전에 WdfRequestMarkCancelable 또는 WdfRequestMarkCancelableEx 를 호출하여 요청 취소를 사용하도록 설정한 경우 드라이버는 WdfRequestUnmarkCancelable 을 호출하여 I/O 요청 취소를 사용하지 않도록 설정할 수 있습니다 .
WdfRequestUnmarkCancelable이 STATUS_CANCELLED 이외의 값을 반환하는 경우 드라이버의 EvtRequestCancel 콜백 함수는 요청에 대해 호출되지 않습니다.
이전에 WdfRequestMarkCancelable 또는 WdfRequestMarkCancelableEx라는 드라이버의 경우 드라이버의 EvtRequestCancel 콜백 함수는 STATUS_CANCELLED Status 매개 변수를 사용하여 WdfRequestComplete를 호출할 수 있습니다. EvtRequestCancel 콜백 함수는 WdfRequestUnmarkCancelable을 호출할 필요가 없습니다. 드라이버가 EvtRequestCancel 콜백 함수 외부에서 WdfRequestComplete를 호출하는 경우 드라이버는 먼저 WdfRequestUnmarkCancelable을 호출해야 합니다.
그러나 EvtRequestCancel이 WdfRequestComplete 를 호출한 후에는 드라이버가 WdfRequestUnmarkCancelable 을 호출해서는 안 됩니다. 다음 예제 섹션에서 예제는 요청 핸들의 로컬 복사본을 저장한 다음 EvtRequestCancel 콜백 함수가 WdfRequestComplete를 호출할 때 이를 지웁니다. 요청 핸들의 로컬 복사본이 지워진 경우 드라이버는 WdfRequestUnmarkCancelable 을 호출하지 않습니다. 이 예제에서는 프레임워크의 자동 동기화 를 사용하여 콜백 함수를 동기화합니다.
WdfObjectReference를 호출하여 요청 개체에 대한 추가 참조를 추가해도 드라이버의 EvtRequestCancel 콜백 함수가 WdfRequestComplete를 호출한 후에는 드라이버가 WdfRequestUnmarkCancelable을 호출할 수 없습니다.
WdfRequestUnmarkCancelable이 STATUS_CANCELLED 반환한 다음 EvtRequestCancel이 요청을 완료하는 경우 드라이버는 이후에 요청 개체를 사용하지 않아야 합니다.
WdfRequestUnmarkCancelable이 STATUS_CANCELLED 반환하는 경우 프레임워크가 EvtRequestCancel을 호출하기 전에 드라이버가 요청을 완료하지 않아야 합니다. 그렇지 않으면 프레임워크가 잘못된 요청으로 드라이버의 EvtRequestCancel 을 호출할 수 있습니다. 관련 코드 예제는 IWDFIoRequest::UnmarkCancelable을 참조하세요.
WdfRequestUnmarkCancelable에 대한 자세한 내용은 I/O 요청 취소를 참조하세요.
예제
다음 코드 예제에서는 ECHO 샘플 드라이버에 포함된 EvtIoRead, EvtRequestCancel 및 EvtTimerFunc 콜백 함수의 간소화된 버전을 제공합니다. 이 예제에서는 프레임워크의 자동 동기화를 사용하는 드라이버에서 WdfRequestMarkCancelable, WdfRequestUnmarkCancelable 및 WdfRequestComplete를 호출하는 방법을 보여 줍니다. (ECHO 샘플은 디바이스 수준 동기화를 사용합니다.)
드라이버가 프레임워크의 자동 동기화를 사용하지 않는 경우 IWDFIoRequest::UnmarkCancelable의 두 예제를 참조하세요. 이러한 예제에서는 UMDF 드라이버를 위해 작성되는 동안 취소 콜백과 표시 해제 루틴을 호출하는 다른 스레드 간의 동기화를 관리하는 데 사용할 수 있는 기술을 보여 줍니다.
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), ReqIsCancOnCancReq(kmdf), ReqMarkCancelableSend(kmdf), ReqNotCanceledLocal(kmdf) |