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


Передача IRP вниз по стеку драйверов

Когда подпрограмма отправки драйвера получает IRP, она должна вызвать IoGetCurrentIrpStackLocation, чтобы проверить собственное расположение стека ввода-вывода и удостовериться в корректности всех параметров. Если драйвер не может удовлетворить и завершить сам запрос, он может выполнить одно из следующих действий:

  • Передайте IRP для дальнейшей обработки драйверами нижнего уровня.

  • Создайте один или несколько новых IRPs и передайте их в драйверы нижнего уровня.

Драйвер более высокого уровня должен передать запрос ввода-вывода следующему драйверу следующим образом:

  1. Если драйвер передает входной IRP следующему нижестоящему драйверу, подпрограмма диспетчера должна вызвать IoSkipCurrentIrpStackLocation или IoCopyCurrentIrpStackLocationToNext, чтобы настроить позицию в стеке ввода-вывода следующего нижестоящего драйвера.

    Если драйвер вызывает IoAllocateIrp для выделения одного или нескольких дополнительных irps для более низких драйверов, подпрограмма диспетчера должна инициализировать расположение стека ввода-вывода следующего уровня драйвера, выполнив действия, описанные в разделе "Обработка irPs" в драйвере Intermediate-Level.

    Подпрограмма отправки может изменить некоторые параметры в расположении ввода-вывода следующего уровня драйвера для определенных запросов. Например, драйвер более высокого уровня может изменить параметры для большого запроса на передачу, если базовое устройство имеет известное ограничение в емкости передачи, и повторно использовать IRP для отправки запросов на частичные передачи в базовый драйвер устройства.

  2. Вызовите IoSetCompletionRoutine.

    Если подпрограмма отправки передает полученную IRP в следующий нижний драйвер, установка подпрограммы IoCompletion является необязательным, но полезной, так как подпрограмма может выполнять такие задачи, как определить, как более низкие драйверы завершили запрос, повторно использовать IRP для частичной передачи, обновлять любое состояние, которое драйвер поддерживает, если он отслеживает irPs, и повторить запрос, возвращенный ошибкой.

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

    Дополнительные сведения о подпрограммах IoCompletion см. в разделе "Завершение IRPs".

  3. Вызов IoCallDriver с каждым IRP для обработки более низкими драйверами.

  4. Возвращает соответствующее значение NTSTATUS, например:

    • СТАТУС_ОЖИДАЕТ

      Драйвер обычно возвращает STATUS_PENDING, если входной IRP является асинхронным запросом, например IRP_MJ_READ или IRP_MJ_WRITE.

    • Результат вызова IoCallDriver

      Драйвер часто возвращает результат вызова IoCallDriver , если входной IRP является синхронным запросом, например IRP_MJ_CREATE.

Драйвер устройства низкого уровня передает любой IRP, который он не может завершить в своей подпрограмме отправки в другие подпрограммы драйверов следующим образом:

  1. Вызовите IoMarkIrpPending с входным IRP.

  2. Вызов IoStartPacket для передачи или очереди IRP в подпрограмму StartIo драйвера, если драйвер не управляет собственной внутренней очередью IRP, как описано вDriver-Managed очередях IRP.

    Если драйвер не имеет подпрограммы StartIo , но обрабатывает отменяемые irps, он должен зарегистрировать подпрограмму Отмены или реализовать очередь IRP с безопасностью отмены. Для получения дополнительной информации о подпрограммах отмены, см. Отмена IRP.

  3. Вернуть STATUS_PENDING.