WdfRequestMarkCancelableEx 함수(wdfrequest.h)
[KMDF 및 UMDF에 적용]
WdfRequestMarkCancelableEx 메서드를 사용하면 지정된 I/O 요청을 취소할 수 있습니다.
구문
NTSTATUS WdfRequestMarkCancelableEx(
[in] WDFREQUEST Request,
[in] PFN_WDF_REQUEST_CANCEL EvtRequestCancel
);
매개 변수
[in] Request
프레임워크 요청 개체에 대한 핸들입니다.
[in] EvtRequestCancel
I/O 요청을 취소하는 경우 프레임워크가 호출하는 드라이버 정의 EvtRequestCancel 콜백 함수에 대한 포인터입니다.
반환 값
WdfRequestMarkCancelableEx 는 지정된 I/O 요청을 성공적으로 취소할 수 있으면 STATUS_SUCCESS 반환합니다. 그렇지 않으면 이 메서드는 다음 값 중 하나를 반환할 수 있습니다.
반환 코드 | 설명 |
---|---|
|
I/O 요청이 취소되었습니다. 자세한 내용은 비고를 참조하세요. |
|
|
이 메서드는 다른 NTSTATUS 값을 반환할 수도 있습니다.
드라이버가 잘못된 개체 핸들을 제공하는 경우 버그 검사 발생합니다.
설명
드라이버가 프레임워크에서 I/O 요청을 받은 후 드라이버는 WdfRequestMarkCancelable 을 호출하거나 KMDF 버전 1.9부터 WdfRequestMarkCancelableEx 를 호출하여 요청을 취소할 수 있도록 할 수 있습니다. 두 메서드 중에서 선택하는 방법에 대한 자세한 내용은 WdfRequestMarkCancelable을 참조하세요.
WdfRequestMarkCancelableEx를 호출할 때 드라이버는 EvtRequestCancel 콜백 함수를 지정해야 합니다. I/O 관리자 또는 다른 드라이버가 I/O 요청을 취소하려고 하는 경우 프레임워크는 콜백 함수를 호출합니다.
WdfRequestMarkCancelableEx가 실패를 반환하는 경우 드라이버는 EvtRequestCancel 콜백 함수가 수행하는 것과 동일한 취소 작업을 수행해야 합니다. 예를 들면 다음과 같습니다.
- 생성되었을 수 있는 하위 쿼리와 함께 요청 처리를 완료하거나 중지합니다.
- WdfRequestComplete를 호출하여 STATUS_CANCELLED 상태 값을 지정합니다.
WdfRequestMarkCancelableEx는 EvtRequestCancel을 호출하지 않으므로 이 메서드는 WdfRequestMarkCancelable의 설명에 설명된 교착 상태 위험으로부터 안전합니다.
취소를 사용하도록 설정한 후 요청 처리
드라이버가 WdfRequestMarkCancelableEx를 호출하여 취소를 사용하도록 설정한 후에는 드라이버가 WdfRequestUnmarkCancelable을 호출하지 않는 한 드라이버가 요청 개체를 소유하는 동안 요청을 취소할 수 있습니다.드라이버가 WdfRequestMarkCancelableEx를 호출하고 드라이버의 EvtRequestCancel 콜백 함수가 실행되지 않고 WdfRequestComplete를 호출한 경우 드라이버는 EvtRequestCancel 콜백 함수 외부에서 WdfRequestComplete를 호출하기 전에 WdfRequestUnmarkCancelable을 호출해야 합니다.
드라이버가 WdfRequestForwardToIoQueue 를 호출하여 요청을 다른 큐로 전달하는 경우 다음 규칙이 적용됩니다.
-
드라이버가 다른 큐로 전달할 때 I/O 요청을 취소할 수 없습니다.
일반적으로 드라이버는 WdfRequestForwardToIoQueue 를 호출하기 전에 요청을 취소할 수 있도록 WdfRequestMarkCancelableEx를 호출해서는 안 됩니다. 드라이버가 요청을 취소할 수 있도록 하는 경우 WdfRequestForwardToIoQueue를 호출하기 전에 취소를 사용하지 않도록 설정하려면 WdfRequestUnmarkCancelable을 호출해야 합니다.
-
요청이 두 번째 큐에 있는 동안 프레임워크는 요청을 소유하고 드라이버에 알리지 않고 취소할 수 있습니다.
드라이버에 취소 알림이 필요한 경우( WdfRequestForwardToIoQueue를 호출하기 전에 할당되었을 수 있는 리소스의 할당을 취소할 수 있도록) 드라이버는 EvtIoCanceledOnQueue 콜백 함수를 등록해야 하며 요청 관련 컨텍스트 메모리를 사용하여 요청의 리소스에 대한 정보를 저장해야 합니다.
- 프레임워크가 두 번째 큐에서 요청을 큐에서 제거하고 드라이버에 전달한 후 드라이버는 WdfRequestMarkCancelableEx 를 호출하여 취소를 사용하도록 설정할 수 있습니다.
예제
다음 코드 예제에서는 두 콜백 함수의 일부를 보여 줍니다.
- 요청별 작업(예: I/O 대상에 보낼 하위 쿼리 만들기)을 수행한 다음 수신된 I/O 요청을 취소하는 EvtIoRead 콜백 함수입니다.
- I/O 요청을 취소하는 EvtRequestCancel 콜백 함수입니다.
예제 1: 자동 동기화를 사용하는 드라이버입니다.
VOID
MyEvtIoRead(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t Length
)
{
...
NTSTATUS status;
...
// Perform request-specific work here
// (such as creating subrequests
// to send to an I/O target).
...
status = WdfRequestMarkCancelableEx(
Request,
MyEvtRequestCancel
);
if (!NT_SUCCESS(status)) {
// Remove request-specific work here, because
// we don't want the work to be done if the
// request was canceled or an error occurred.
WdfRequestComplete (Request, status);
}
...
}
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
);
}
예제 2: 자체 동기화를 사용하는 드라이버입니다.
VOID
MyEvtIoRead(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t Length
)
{
...
NTSTATUS status;
...
WdfSpinlockAcquire(MyCancelSpinLock);
// Perform request-specific work here
// (such as creating subrequests
// to send to an I/O target).
...
status = WdfRequestMarkCancelableEx(
Request,
MyEvtRequestCancel
);
if (!NT_SUCCESS(status)) {
// Remove request-specific work here, because
// we don't want the work to be done if the
// request was canceled or an error occurred.
}
WdfSpinlockRelease(MyCancelSpinLock);
if (!NT_SUCCESS(status)) {
WdfRequestComplete (
Request,
Status
);
}
...
}
VOID
MyEvtRequestCancel(
IN WDFREQUEST Request
)
{
WdfSpinlockAcquire(MyCancelSpinLock);
// Remove request-specific work here, because
// we don't want the work to be done if the
// request was canceled.
WdfSpinlockRelease(MyCancelSpinLock);
WdfRequestComplete (Request, STATUS_CANCELLED);
}
요구 사항
요구 사항 | 값 |
---|---|
대상 플랫폼 | 유니버설 |
최소 KMDF 버전 | 1.9 |
최소 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) |