전처리 및 후처리 IRP

[KMDF에만 적용]

드라이버가 IRP를 처리하기 전이나 후에 IRP(IRP)를 가로채야 하는 경우 드라이버는 WdfDeviceInitAssignWdmIrpPreprocessCallback 을 호출하여 주요 I/O 함수 코드에 대한 EvtDeviceWdmIrpPreprocess 이벤트 콜백 함수를 등록하고, 필요에 따라 주 코드와 연결된 특정 부 I/O 함수 코드에 대해 EvtDeviceWdmIrpPreprocess 이벤트 콜백 함수를 등록할 수 있습니다. 그 후 프레임워크는 드라이버가 지정된 주 함수 및 부 함수 코드가 포함된 IRP를 받을 때마다 드라이버의 EvtDeviceWdmIrpPreprocess 콜백 함수를 호출합니다.

EvtDeviceWdmIrpPreprocess 콜백 함수는 IRP를 전처리하는 데 필요한 모든 작업을 수행할 수 있으며, 드라이버가 프레임워크에서 지원하지 않는 IRP를 처리하지 않는 한 IRP를 프레임워크로 반환하려면 WdfDeviceWdmDispatchPreprocessedIrp를 호출해야 합니다.

드라이버가 WdfDeviceWdmDispatchPreprocessedIrp를 호출한 후 프레임워크는 드라이버가 EvtDeviceWdmIrpPreprocess 콜백 함수를 제공하지 않은 경우와 동일한 방식으로 IRP를 처리합니다. IRP의 I/O 함수 코드가 프레임워크가 드라이버에 전달하는 코드인 경우 드라이버는 요청 개체로 IRP를 다시 받습니다.

하위 수준 드라이버가 IRP를 완료한 후 드라이버가 IRP를 사후 처리해야 하는 경우 드라이버의 EvtDeviceWdmIrpPreprocess 콜백 함수는 IoSetCompletionRoutine을 호출하여 WdfDeviceWdmDispatchPreprocessedIrp를 호출하기 전에 IoCompletion 루틴을 설정할 수 있습니다.

드라이버가 WdfDeviceInitAssignWdmIrpPreprocessCallback을 호출한 후 프레임워크는 I/O 관리자가 모든 IRP에 추가 I/O 스택 위치를 추가하도록 하여 EvtDeviceWdmIrpPreprocess 콜백 함수가 IoCompletion 루틴을 설정할 수 있도록 합니다. 콜백 함수는 WdfDeviceWdmDispatchPreprocessedIrp를 호출하기 전에 IRP의 I/O 스택 위치 포인터를 업데이트해야 합니다.

WdfDeviceWdmDispatchPreprocessedIrp 호출

I/O 관리자는 IRP에 추가 I/O 스택 위치를 추가하므로 EvtDeviceWdmIrpPreprocess 콜백 함수는 WdfDeviceWdmDispatchPreprocessedIrp를 호출하기 전에 IoSkipCurrentIrpStackLocation 또는 IoCopyCurrentIrpStackLocationToNext(IRP에서 다음 I/O 스택 위치를 설정)를 호출해야 합니다.

드라이버가 IRP를 전처리하지만 IRP를 후처리하지 않는 경우 드라이버는 IRP에 대한 IoCompletion 루틴을 설정할 필요가 없으며 다음 코드 예제와 같이 IoSkipCurrentIrpStackLocation을 호출할 수 있습니다.

NTSTATUS
  EvtDeviceMyIrpPreprocess(
    IN WDFDEVICE Device,
    IN OUT PIRP Irp
    )
{
//
// Perform IRP preprocessing operations here.
//
...
//
// Deliver the IRP back to the framework. 
//
IoSkipCurrentIrpStackLocation(Irp);
return WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
}

드라이버가 IRP를 사후 처리하는 경우 드라이버는 IoCopyCurrentIrpStackLocationToNext를 호출한 다음, 다음 코드 예제와 같이 IoSetCompletionRoutine 을 호출하여 IRP에 대한 IoCompletion 루틴을 설정해야 합니다.

NTSTATUS
  EvtDeviceMyIrpPreprocess(
    IN WDFDEVICE Device,
    IN OUT PIRP Irp
    )
{
//
// Perform IRP preprocessing operations here, if needed.
//
...
//
// Set a completion routine and deliver the IRP back to
// the framework. 
//
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(
                       Irp,
                       MyIrpCompletionRoutine,
                       NULL,
                       TRUE,
                       TRUE,
                       TRUE
                      );
return WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
}

드라이버의 EvtDeviceWdmIrpPreprocess 콜백 함수가 수신하는 디바이스 개체가 PDO(물리적 디바이스 개체)를 나타내고 IRP의 주요 함수 코드가 IRP_MJ_PNP 또는 IRP_MJ_POWER 경우 드라이버는 IoCopyCurrentIrpStackLocationToNext를 호출하지 않아야 합니다(따라서 IoCompletion 루틴을 설정하지 않아야 합니다). 그렇지 않으면 드라이버 검증 도구 에서 오류를 보고합니다.

IoCopyCurrentIrpStackLocationToNext, IoSkipCurrentIrpStackLocationIoSetCompletionRoutine을 호출하는 시기에 대한 자세한 내용은 드라이버 스택 아래로 IRP 전달을 참조하세요.