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

Диспетчер PnP использует IRP для указания драйверам на необходимость запуска, остановки и удаления устройств, а также для запроса информации у драйверов об их устройствах. Все PnP IRP имеют основной код функции IRP_MJ_PNP, и все драйверы PnP должны предоставлять подпрограмму DispatchPnP для обслуживания этого кода функции. Диспетчер PnP инициализирует Irp-IoStatus.Status в STATUS_NOT_SUPPORTED при отправке IRP. Дополнительные сведения см. в разделе "Подпрограммы DispatchPnP".

Список второстепенных IRP для PnP см. в разделе Plug and Play Minor IRPs.

Все драйверы для устройства должны иметь возможность реагировать на PnP IRP, если ни один из драйверов в стеке не завершает IRP с ошибкой. (См. следующий рисунок.)

схема, иллюстрирующая передачу IRP plug and play вниз по стеку устройств.

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

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

Функция или драйвер фильтра должны выполнять следующие действия при получении PnP IRP:

  • Если драйвер выполняет действия в ответ на IRP:
    1. Выполните соответствующие действия.
    2. Задайте для Irp-IoStatus.Status> соответствующее состояние, например STATUS_SUCCESS. Установите Irp-IoStatus.Information>, если это подходит для IRP.
    3. Настройте следующее расположение стека с помощью IoSkipCurrentIrpStackLocation или IoCopyCurrentIrpStackLocationToNext. Вызовите последнюю процедуру, если вы задали процедуру IoCompletion.
    4. При необходимости задайте подпрограмму IoCompletion .
    5. Не завершайте IRP. (Не вызывайте IoCompleteRequest.) Родительский драйвер шины завершит IRP.
  • Если драйвер не выполняет действия для этого IRP, он просто готовится передать IRP следующему драйверу:
    1. Вызовите IoSkipCurrentIrpStackLocation , чтобы удалить расположение стека из IRP.
    2. Не устанавливайте поля в Irp-IoStatus>.
    3. Не устанавливайте подпрограмму IoCompletion .
    4. Не завершайте IRP. (Не вызывайте IoCompleteRequest.) Драйвер родительской шины завершит IRP.

Если функция или драйвер фильтра не вызвали сбой IRP, в этом случае драйвер передает IRP следующему нижнему драйверу с помощью IoCallDriver. Драйвер имеет указатель на следующий нижний драйвер; этот указатель был возвращен из вызова IoAttachDeviceToDeviceStack в подпрограмме AddDevice более высокого драйвера.

Родительский драйвер шины завершает IRP после выполнения любых задач для реагирования на IRP. Когда драйвер шины вызывает IoCompleteRequest, диспетчер ввода-вывода вызывает все подпрограммы IoCompletion , зарегистрированные функцией или драйверами фильтра для устройства.