Поделиться через


Преобработка и постобработка IRP

[Применяется только к KMDF]

Если драйвер должен перехватывать пакет запроса ввода-вывода (IRP) до или после того, как платформа обрабатывает IRP, драйвер может вызвать WdfDeviceInitAssignWdmIrpPreprocessCallback , чтобы зарегистрировать функцию обратного вызова события EvtDeviceWdmIrpPreprocess для основного кода функции ввода-вывода и при необходимости для конкретных дополнительных кодов функций ввода-вывода, связанных с основным кодом. Впоследствии платформа вызывает функцию обратного вызова EvtDeviceWdmIrpPreprocess драйвера, когда драйвер получает IRP, содержащий указанный основной и дополнительный код функции.

Функция обратного вызова EvtDeviceWdmIrpPreprocess может выполнять все необходимые действия для предварительной обработки IRP, а затем вызывать WdfDeviceWdmDispatchPreprocessedIrp для возврата IRP в платформу, если драйвер не обрабатывает IRP, который не поддерживается платформой.

После вызова драйвером WdfDeviceWdmDispatchPreprocessedIrp платформа обрабатывает IRP так же, как это было бы, если бы драйвер не предоставил функцию обратного вызова EvtDeviceWdmIrpPreprocess . Если код функции ввода-вывода IRP является кодом, который платформа передает драйверам, драйвер снова получит IRP в качестве объекта запроса.

Если драйверу необходимо выполнить постобработку IRP после того, как драйвер более низкого уровня завершает IRP, функция обратного вызова EvtDeviceWdmIrpPreprocess драйвера может вызвать IoSetCompletionRoutine , чтобы задать подпрограмму IoCompletion перед вызовом WdfDeviceWdmDispatchPreprocessedIrp.

После того как драйвер вызывает WdfDeviceInitAssignWdmIrpPreprocessCallback, платформа заставляет диспетчер ввода-вывода добавить дополнительное расположение стека ввода-вывода во все irP, чтобы функция обратного вызова EvtDeviceWdmIrpPreprocess могло задать подпрограмму IoCompletion . Функция обратного вызова должна обновить указатель расположения стека ввода-вывода IRP перед вызовом WdfDeviceWdmDispatchPreprocessedIrp.

Вызов WdfDeviceWdmDispatchPreprocessedIrp

Так как диспетчер ввода-вывода добавляет дополнительное расположение стека ввода-вывода в IRP, функция обратного вызова EvtDeviceWdmIrpPreprocess должна вызвать IoSkipCurrentIrpStackLocation или IoCopyCurrentIrpStackLocationToNext (чтобы настроить следующее расположение стека ввода-вывода в IRP) перед вызовом WdfDeviceWdmDispatchPreprocessedIrp.

Если драйвер выполняет предварительную обработку IRP, но не выполняет постобработку IRP, драйверу не нужно задавать подпрограмму IoCompletion для IRP и может вызывать 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 , чтобы задать подпрограмму IoCompletion для IRP, как показано в следующем примере кода.

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);
}

Драйвер не должен вызывать IoCopyCurrentIrpStackLocationToNext (и поэтому не должен задавать подпрограмму IoCompletion ), если объект устройства обрабатывает, что функция обратного вызова EvtDeviceWdmIrpPreprocess драйвера представляет объект физического устройства (PDO), и если код основной функции IRP IRP_MJ_PNP или IRP_MJ_POWER. В противном случае средство проверки драйверов сообщит об ошибке.

Дополнительные сведения о том, когда следует вызывать IoCopyCurrentIrpStackLocationToNext, IoSkipCurrentIrpStackLocation и IoSetCompletionRoutine, см. в разделе Передача irP в стек драйверов.