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


Обработка запроса IRP_MN_QUERY_REMOVE_DEVICE

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

Диспетчер PnP отправляет этот IRP на PASSIVE_LEVEL IRQL в контексте системного потока.

Перед отправкой этого IRP в драйверы для устройства выполняется следующее:

  • Уведомляет все приложения пользовательского режима, зарегистрированные для получения уведомлений на устройстве (или связанном устройстве).

    К ним относятся приложения, зарегистрированные для уведомления на устройстве, на одном из потомков устройства (дочернее устройство, дочерний элемент дочернего устройства и т. д.) или на одном из отношений удаления устройства. Приложение регистрирует такое уведомление, вызывая RegisterDeviceNotification.

    В ответ на это уведомление приложение либо готовится к удалению устройства (закрывает дескриптор устройства), либо завершает запрос неудачно.

  • Уведомляет все драйверы режима ядра, зарегистрированные для получения уведомлений на устройстве (или связанном устройстве).

    Сюда входят драйверы, зарегистрированные для уведомления на устройстве, на одном из потомков устройства или на одном из отношений удаления устройства. Драйвер регистрирует это уведомление, вызывая IoRegisterPlugPlayNotification с категорией событий EventCategoryTargetDeviceChange.

    В ответ на это уведомление драйвер либо готовится к удалению устройства (закрывает дескриптор устройства), либо завершает запрос неудачно.

  • Отправляет IRP_MN_QUERY_REMOVE_DEVICE IRP в драйверы потомков устройства.

  • (Системы Windows 2000 и более поздние версии) Если на устройстве подключена файловая система, диспетчер PnP отправляет запрос на удаление запроса в файловую систему и все фильтры файловой системы. При наличии открытых дескрипторов для устройства файловая система обычно завершает запрос на удаление запроса. В противном случае файловая система обычно блокирует том, чтобы предотвратить успешное создание в будущем. Если подключенная файловая система не поддерживает запрос на удаление запроса, диспетчер PnP завершает запрос на удаление запроса для устройства.

Если все описанные выше действия выполнены, диспетчер PnP отправляет IRP_MN_QUERY_REMOVE_DEVICE драйверам устройства.

Запрос IRP_MN_QUERY_REMOVE_DEVICE обрабатывается сначала верхним драйвером в стеке устройств, а затем каждым следующим драйвером ниже. Драйвер обрабатывает удаление IRP в своей подпрограмме DispatchPnP .

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

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

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

    • Удаление устройства может привести к потере данных.

    • Если компонент имеет открытый дескриптор для устройства. (Эта проблема возникает только в Windows 98/Me. Windows 2000 и более поздние версии Windows отслеживают открытые дескрипторы и завершают запрос ошибкой, если после завершения IRP_MN_QUERY_REMOVE_DEVICE имеются открытые дескрипторы.)

    • Если драйвер был уведомлен (через IRP_MN_DEVICE_USAGE_NOTIFICATION IRP), что устройство находится в пути к файлу подкачки, аварийного дампа или гибернации.

    • Если драйвер имеет неоплаченную ссылку на интерфейс для устройства. То есть драйвер предоставил интерфейс в ответ на запрос IRP_MN_QUERY_INTERFACE , и интерфейс не разыменовывали.

  2. Если устройство не удается удалить, выполните запрос и удалите IRP.

    Задайте для Irp-IoStatus.Status> соответствующее состояние ошибки (обычно STATUS_UNSUCCESSFUL), вызовите IoCompleteRequest с IO_NO_INCREMENT и вернитесь из подпрограммы DispatchPnP драйвера. Не передавайте IRP следующему драйверу нижнего уровня.

  3. Если драйвер ранее отправил IRP_MN_WAIT_WAKE запрос на включение пробуждения устройства, отмените IRP ожидания пробуждения.

  4. Запишите предыдущее состояние PnP устройства.

    Драйвер должен записать состояние PnP, в которое находилось устройство, когда драйвер получил запрос IRP_MN_QUERY_REMOVE_DEVICE , так как драйвер должен вернуть устройство в это состояние, если запрос отменен (IRP_MN_CANCEL_REMOVE_DEVICE). Предыдущее состояние обычно "запущено", то есть состояние, которое устройство вводит, когда драйвер успешно завершает запрос IRP_MN_START_DEVICE .

    Однако возможны и другие предыдущие состояния. Например, пользователь мог отключить устройство с помощью диспетчер устройств. Или в ответ на запрос IRP_MN_QUERY_CAPABILITIES , драйвер родительской шины (или драйвер фильтра в драйвере шины) мог сообщить, что оборудование устройства отключено. В любом случае драйвер для отключенного устройства может получить запрос IRP_MN_QUERY_REMOVE_DEVICE до получения запроса IRP_MN_START_DEVICE .

  5. Завершите IRP:

    В драйвере функции или фильтра:

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

    • Настройте следующее расположение стека с помощью IoSkipCurrentIrpStackLocation и передайте IRP следующему более низкому драйверу с помощью IoCallDriver.

    • Распространение состояния из IoCallDriver в качестве состояния возврата из подпрограммы DispatchPnP .

    • Не завершайте IRP.

    В водителе автобуса:

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

    • Заполните IRP (IoCompleteRequest) IO_NO_INCREMENT.

    • Возвращается из подпрограммы DispatchPnP .

Если какой-либо драйвер в стеке устройств не IRP_MN_QUERY_REMOVE_DEVICE, диспетчер PnP отправляет IRP_MN_CANCEL_REMOVE_DEVICE в стек устройств. Это не позволяет драйверам требовать подпрограмму IoCompletion для IRP с удалением запроса, чтобы определить, произошел ли сбой IRP в более низком драйвере.

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