Отмена IRP ожидания или пробуждения

Только драйвер, отправляющий IRP ожидания или пробуждения, может отменить этот IRP.

Драйверу может потребоваться отменить ожидающее ожидание или пробуждение IRP в следующих случаях:

  • Драйвер получает запрос PnP IRP_MN_STOP_DEVICE, IRP_MN_QUERY_REMOVE_DEVICE, IRP_MN_REMOVE_DEVICE или IRP_MN_SURPRISE_REMOVAL для устройства. Драйвер должен повторно выпустить IRP ожидания и пробуждения (PoRequestPowerIrp) после перезапуска устройства.

  • Система переходит в спящий режим, но устройство не должно быть включено для пробуждения системы.

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

  • Система переходит в спящий режим, из которого устройство не может разбудить его. Это значит, что он входит в состояние, меньшее, чем значение SystemWake , указанное в его DEVICE_CAPABILITIES структуре.

  • Устройство входит в состояние питания, из которого оно не может реагировать на сигнал пробуждения. То есть он входит в состояние, меньшее, чем значение DeviceWake , указанное в его DEVICE_CAPABILITIES структуре.

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

Драйвер не должен отменять IRP ожидания или пробуждения, которое он не отправил.

Отмена подпрограмм для irP ожидания и пробуждения

Многие драйверы функций и автобусов должны задавать процедуры отмены для ожидающих выполнения irP ожидания и пробуждения; Следующие типы драйверов должны задавать такие подпрограммы:

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

  • Драйверы, которые отправляют запросы IRP_MN_WAIT_WAKE драйверам родительских устройств.

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

В процедуре отмены ожидания и пробуждения драйвер должен выполнить следующие действия:

  1. Вызовите IoSetCancelRoutine , чтобы сбросить процедуру Отмены для IRP до NULL.

  2. Вызовите IoReleaseCancelSpinLock, передав CancelIRQL , указанный в IRP, чтобы освободить блокировку отмены спина для IRP.

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

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

  4. Измените все необходимые параметры устройства. Например, драйвер модема отключит параметр пробуждения устройства.

  5. Задайте для Irp-IoStatus.Status> значение STATUS_CANCELLED.

  6. Вызовите IoCompleteRequest , чтобы завершить IRP ожидания и пробуждения, указав IO_NO_INCREMENT.

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

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