Передача 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 Дополнительные irP.
Все драйверы для устройства должны иметь возможность реагировать на PnP IRP, если драйвер в стеке не сбой IRP. (См. следующий рисунок.)
Ни один драйвер для устройства не может предположить, что это единственный драйвер, который будет реагировать на PnP IRP. Рассмотрим, например, драйвер функции, который отвечает на запрос IRP_MN_QUERY_CAPABILITIES и завершает IRP, не передавая его следующему драйверу. Сообщается ни о одной из возможностей, поддерживаемых более низкими драйверами, таких как уникальный идентификатор экземпляра или возможности управления питанием, поддерживаемые родительским драйвером автобуса.
PnP IRP перемещает резервную копию стека устройства, когда драйвер родительского автобуса вызывает IoCompleteRequest , а диспетчер ввода-вывода вызывает все подпрограммы IoCompletion, зарегистрированные драйвером функции или драйверами фильтров.
При получении PnP IRP драйвер функции или фильтра должен выполнять следующие действия:
- Если драйвер выполняет действия в ответ на IRP:
- Выполните соответствующие действия.
- Задайте для Irp-IoStatus.Status> соответствующее состояние, например STATUS_SUCCESS. Задайте Irp-IoStatus.Information>, если это необходимо для IRP.
- Настройте следующее расположение стека с помощью IoSkipCurrentIrpStackLocation или IoCopyCurrentIrpStackLocationToNext. Вызовите последнюю подпрограмму, если вы задали процедуру IoCompletion .
- При необходимости задайте подпрограмму IoCompletion .
- Не завершайте IRP. (Не вызывайте IoCompleteRequest.) Водитель родительского автобуса завершит IRP.
- Если драйвер не выполняет действий для этого IRP, он просто готовится к передаче IRP следующему драйверу:
- Вызовите IoSkipCurrentIrpStackLocation , чтобы удалить расположение стека из IRP.
- Не устанавливайте поля в Irp-IoStatus>.
- Не устанавливайте подпрограмму IoCompletion .
- Не завершайте IRP. (Не вызывайте IoCompleteRequest.) Водитель родительского автобуса завершит IRP.
Если драйвер функции или фильтра не завершил работу IRP, он передает его в драйвер следующего уровня ниже с помощью IoCallDriver. Драйвер имеет указатель на следующий ниже драйвер; этот указатель был возвращен из вызова IoAttachDeviceToDeviceStack в процедуре AddDevice более высокого драйвера.
Драйвер родительского автобуса завершает IRP после выполнения любых задач по реагированию на IRP. После того как драйвер шины вызывает IoCompleteRequest, диспетчер ввода-вывода вызывает все подпрограммы IoCompletion , зарегистрированные драйверами функций или фильтров для устройства.