Рабочие процедуры драйвера
Рабочие процедуры драйвера (в англоязычной литературе по драйверам они всегда называются dispatch routines) регистрируются драйвером во время работы DriverEntry. Фактически, таким образом драйвер сообщает Диспетчеру ввода/вывода о своих намерениях, какого типа запросы (то есть IRP_MJ_Xxx коды) он собирается поддерживать.
В тот момент, когда инициализируется запрос ввода/вывода, Диспетчер ввода/вывода в первую очередь создает пакет IRP, чтобы зафиксировать след запроса, факт его прохождения. Наряду с другой информацией, в этом IRP пакете (в ячейках стека IRP пакета) в поле MajorFunction сохраняется код IRP_MJ_Xxx для того, чтобы однозначно идентифицировать тип этого запроса.
Код IRP_MJ_Xxx используется Диспетчером ввода/вывода для того, чтобы извлечь из массива MajorFunction объекта драйвера указатель на нужную для обработки запроса процедуру драйвера. В том случае, если драйвер не поддерживает запрошенную операцию, то соответствующий элемент MajorFunction указывает на код внутри Диспетчера ввода/вывода (поскольку драйвер предоставил в таком случае Диспетчеру ввода/вывода право распорядиться по собственному усмотрению), а именно — на функцию _IoInvalidDeviceRequest, который возвращает клиенту драйвера сообщение об ошибке. Таким образом, инициатива обеспечения каждого нужного кода IRP_MJ_Xxx собственной обрабатывающей процедурой принадлежит автору драйвера.
Метод объявления процедур ввода/вывода позволяет также объявить одну процедуру (функцию драйвера) для обслуживания нескольких запросов ввода/вывода. Для этого нужно лишь поместить адрес такой универсальной (если она действительно для этого предназначена) функции в нескольких ячейках массива MajorFunction, как это было показано выше для DriverEntry фильтр-драйвера. Так как пакет IRP содержит код IRP_MJ_Xxx, то с его помощью всегда можно восстановить точный код требующегося действия.
Не следует выполнять внутри DriverEntry операции над позициями в массиве MajorFunction, соответствующих функциям ввода/вывода, не поддерживаемым драйвером.