Программирование драйверов Windows

       

Создание IRP пакетов вызовом IoBuildDeviceIoControlRequest


Последняя из трех упомянутых, предназначенных функций для создания IRP пакетов, IoBuildDeviceIoControlRequest (таблица 9.14) также призвана облегчить этот процесс. Этот весьма полезный вызов предназначен для построения пакетов IRP, обслуживающих ввод/вывод устройств с большими вариациями в поведении и с использованием пользовательских IOCTL кодов запросов.

Таблица 9.14. Описание прототипа функции IoBuildDeviceIoControlRequest



PIRP IoBuildDeviceIoControlRequest IRQL == PASSIVE_LEVEL
Параметры Формирует IRP пакет (с выделением памяти), описывающий обращение с IOCTL запросом
IN ULONG IoControlCode Код IOCTL, принимаемый (допускаемый) к обработке целевым устройством
IN PDEVICE_OBJECT pTargetDevice Объект устройства, которому предназначен формируемый пакет IRP
IN PVOID pInputBuffer Адрес буфера ввода/вывода, передаваемого драйверу нижнего уровня
IN ULONG inputLenght Длина буфера pInputBuffer в байтах
OUT PVOID pOutputBuffer Адрес буфера ввода/вывода для данных, возвращаемых драйвером нижнего уровня
IN ULONG outputLenght Длина буфера pOutputBuffer в байтах
IN BOOLEAN InternalDeviceIoControl TRUE &#8212 буден сформирован IRP пакет с кодом IRP_MJ_INTERNAL_DEVICE_CONTROL

FALSE &#8212 с кодом IRP_MJ_DEVICE_CONTROL

IN PREVENT pEvent Объект события (event object), используемый для сообщения об окончании ввода/вывода
OUT PIO_STATUS_BLOCK pIosb Для получения завершающего статуса операций ввода/вывода
Возвращаемое значение • Адрес нового пакета IRP либо

• NULL &#8212 невозможно создать новый IRP

Следует также отметить, что этот вызов может конструировать IRP как с синхронным способом обработки, так и асинхронным. Для получения "синхронного" IRP в функцию необходимо просто передать адрес инициализированного объекта события. После того как IRP пакет будет передан нижнему драйверу вызовом IoCallDriver, следует использовать KeWaitForSingleObject для организации ожидания сигнала от этого объекта события. Когда драйвер нижнего уровня завершит обработку IRP, Диспетчер ввода/вывода переведет объект события в "сигнальное" состояние, и в результате будет разбужен драйвер, который "организовал" весь этот процесс.
Блок данных по указателю pIosb сообщает об окончательном состоянии пакета IRP. Так же, как и в случае с IoBuildSynchronousFsdRequest, следует аккуратнее работать в многопоточном режиме.

Диспетчер ввода/вывода автоматически выполняет очистку и освобождение IRP пакетов, созданных по вызову IoBuildDeviceIoControlRequest по завершении их обработки, включая подключенные к этому пакету системные буферные области или MDL. Для запуска такой очистки драйвер должен просто сделать вызов IoCompleteRequest.

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

Метод буферизации, который указан в IOCTL коде, влияет на формирование IRP пакета. В том случае, если IOCTL код описан как METHOD_BUFFERED, внутри вызова IoBuildDeviceIoControlRequest выполняется выделение области нестраничной памяти, куда производится копирование содержимого буфера по адресу pInputBuffer. Когда обработка IRP завершается, содержимое буфера в нестраничном пуле автоматически копируется в область памяти по адресу pOutputBuffer.

В случае, если IOCTL код содержит флаги METHOD_OUT_DIRECY или METHOD_IN_DIRECT, то IoBuildDeviceIoControlRequest всегда выполняет построение MDL списка для буфера pOutputBuffer и всегда использует буфер в нестраничной памяти для буфера pInputBuffer, независимо

от того, указан ли METHOD_IN_DIRECT или METHOD_OUT_DIRECT. В общем-то, формирование IRP пакета в обоих случаях происходит совершенно аналогично тому, как если бы в Win32 обрабатывался вызов DeviceIoControl, поступивший из приложения пользовательского режима.


Содержание раздела