IRP_MN_QUERY_INTERFACE

Запрос IRP_MN_QUERY_INTERFACE позволяет драйверу экспортировать интерфейс прямого вызова в другие драйверы.

Драйвер шины, экспортируемый интерфейсом, должен обрабатывать этот запрос для своих дочерних устройств (дочерних PDO). Функция и фильтр могут при необходимости обрабатывать этот запрос.

"Интерфейс" в этом контексте состоит из одной или нескольких подпрограмм и, возможно, данных, экспортированных драйвером или набором драйверов. Интерфейс имеет структуру, описывающую его содержимое, и GUID, определяющий его тип.

Например, драйвер шины PCMCIA экспортирует интерфейс типа GUID_PCMCIA_INTERFACE_STANDARD, содержащий подпрограммы для таких операций, как получение условия защиты от записи карта памяти PCMCIA. Драйвер функции для такого карта памяти может отправить запрос IRP_MN_QUERY_INTERFACE родительскому драйверу шины PCMCIA, чтобы получить указатели на подпрограммы интерфейса PCMCIA.

Примечание

При вводе новой версии существующего интерфейса создайте новый GUID вместо изменения полей Размер или Версия структуры INTERFACE . Дополнительные сведения см. в разделе Использование интерфейсов Driver-Defined.

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

Значение

0x08

Основной код

IRP_MJ_PNP

При отправке

Драйвер или системный компонент отправляет этот IRP для получения сведений об интерфейсе, экспортируемом драйвером для устройства.

Драйвер или системный компонент отправляет этот IRP по IRQL = PASSIVE_LEVEL в произвольном контексте потока.

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

Входные параметры

Элемент Parameters.QueryInterface структуры IO_STACK_LOCATION сам по себе является структурой, описывающей запрашиваемый интерфейс. Структура содержит следующие сведения:

CONST GUID *InterfaceType;
USHORT Size;
USHORT Version;
PINTERFACE Interface;
PVOID InterfaceSpecificData

Члены структуры определяются следующим образом:

InterfaceType
Указывает на GUID, который идентифицирует запрашиваемый интерфейс. Guid может быть для системного интерфейса, например GUID_BUS_INTERFACE_STANDARD, или пользовательского интерфейса. Идентификаторы GUID для системных интерфейсов перечислены в разделе Wdmguid.h. Идентификаторы GUID для пользовательских интерфейсов должны создаваться с помощью Uuidgen.

Размер
Указывает размер запрашиваемого интерфейса. Драйверы, обрабатывающие этот IRP, не должны возвращать структуру INTERFACE , превышающую размер байтов.

Версия
Указывает версию запрашиваемого интерфейса.

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

Интерфейс
Указывает на структуру, в которой возвращается запрошенный интерфейс. Эта структура должна содержать структуру INTERFACE в качестве первого члена. Компонент, отправляя IRP, выделяет эту структуру из страничной памяти.

Драйвер, экспортируемый интерфейсом, определяет новый тип структуры, содержащий структуру INTERFACE , а также элементы для подпрограмм и (или) данных в интерфейсе. (Драйвер также определяет GUID для интерфейса, как описано в элементе InterfaceType выше.)

Драйвер, экспортируемый интерфейсом, определяет среду выполнения для каждой подпрограммы в интерфейсе, включая IRQL, по которому можно вызывать подпрограмму, и т. д.

InterfaceSpecificData
Указывает дополнительные сведения о запрашиваемом интерфейсе.

Для некоторых интерфейсов компонент, отправляющий IRP, указывает дополнительные сведения в этом поле. Как правило, это поле имеет значение NULL , а InterfaceType и Version достаточно для идентификации запрашиваемого интерфейса.

Выходные параметры

При успешном выполнении драйвер заполняет элементы структуры Parameters.QueryInterface.Interface .

Блок состояния ввода-вывода

Драйвер задает для Irp-IoStatus.Status> значение STATUS_SUCCESS или соответствующее состояние ошибки.

При успешном выполнении водитель автобуса устанавливает значение Irp-IoStatus.Information> равным нулю.

Если драйвер функции или фильтра не обрабатывает этот IRP, он вызывает IoSkipCurrentIrpStackLocation и передает IRP следующему драйверу. Такой драйвер не должен изменять Irp-IoStatus.Status> и не должен завершить IRP.

Если водитель автобуса не экспортирует запрошенный интерфейс и, следовательно, не обрабатывает этот IRP для дочернего PDO, водитель автобуса оставляет Irp-IoStatus.Status> как есть и завершает IRP.

Операция

Драйвер обрабатывает этот IRP, если параметры указывают интерфейс, поддерживаемый драйвером.

Драйвер не должен ставить этот IRP в очередь, если IRP запрашивает интерфейс, который не поддерживается драйвером. Драйвер должен проверка Parameters.QueryInterface.InterfaceType в своей структуре IO_STACK_LOCATION. Если интерфейс не поддерживается драйвером, драйвер должен передать IRP следующему более низкому драйверу в стеке устройств без блокировки.

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

Если драйвер, который позже отправляет IRP (драйвер x), передает интерфейс другому драйверу ( драйверу y), то драйвер x должен увеличивать число ссылок интерфейса, а драйвер y должен уменьшать его.

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

Интерфейсы могут быть зависящими от шины или независимыми от шины. Интерфейсы, относящиеся к шине, определяются в файлах заголовков для этих автобусов. Система определяет независимый от шины интерфейс BUS_INTERFACE_STANDARD для экспорта стандартных интерфейсов шины.

Общие правила обработки Plug and Play дополнительных irP см. в Plug and Play.

Этот IRP используется специально для передачи стандартных точек входа между многоуровневые драйверы режима ядра для устройства. Не путайте интерфейсы, предоставляемые этим IRP, с интерфейсами устройств. Интерфейс устройства используется в основном для предоставления пути к устройству для использования компонентами пользовательского режима или другими компонентами ядра. Дополнительные сведения об интерфейсах устройств см. в разделе Классы интерфейса устройства.

Отправка этого IRP

Сведения об отправке IRP см. в разделе Обработка irPs . Следующие действия применяются специально к этому IRP:

  • Выделите структуру INTERFACE из выстраивного пула и инициализируйте ее нулями. Если интерфейс будет вызываться по адресу IRQL >= DISPATCH_LEVEL на основе контракта интерфейса, вызывающий объект может скопировать содержимое в память, выделенную из непагированного пула.

  • Задайте значения в следующем расположении стека ввода-вывода для IRP: задайте для параметра MajorFunctionзначение IRP_MJ_PNP, для параметра MinorFunction— IRP_MN_QUERY_INTERFACE и задайте соответствующие значения в Parameters.QueryInterface.

  • Инициализируйте IoStatus.Status для STATUS_NOT_SUPPORTED.

  • Отмените выделение IRP и структуры INTERFACE , когда они больше не нужны.

  • Используйте подпрограммы интерфейса и параметр контекста, как описано в спецификации для интерфейса.

  • Уменьшение количества ссылок с помощью подпрограммы InterfaceDereference , когда интерфейс больше не нужен. Не вызывайте подпрограммы интерфейса после разыменовки интерфейса.

Драйвер обычно отправляет это IRP в верхнюю часть стека устройств, в котором подключен драйвер. Если драйвер отправляет этот IRP в другой стек устройств, драйвер должен зарегистрироваться для получения уведомления о целевом устройстве на другом устройстве, если другое устройство не является предком устройства, которое обслуживает драйвер. Такой драйвер вызывает IoRegisterPlugPlayNotification с eventCategoryEventCategoryTargetDeviceChange. Когда драйвер получает уведомление типа GUID_TARGET_DEVICE_QUERY_REMOVE, драйвер должен разыменовыть интерфейс. Драйвер может запрашивать интерфейс, если он получает последующее уведомление GUID_TARGET_DEVICE_REMOVE_CANCELLED.

Требования

Заголовок

Wdm.h (включая Wdm.h, Ntddk.h или Ntifs.h)

См. также раздел

BUS_INTERFACE_STANDARD

ИНТЕРФЕЙС

IoRegisterPlugPlayNotification