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


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

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

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

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

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

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

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

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

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

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

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

    Дополнительные сведения о процедурах IoCompletion см. в разделе Завершение irP.

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

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

    • STATUS_PENDING

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

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

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

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

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

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

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

  3. Возврат STATUS_PENDING.