Процедура DriverEntry
Диспетчер ввода/вывода вызывает данную процедуру при загрузке драйвера. Возможно, это произойдет в процессе загрузки операционной системы, но драйвер может быть загружен и динамически в любое время, как это было сделано с драйвером Example.sys в главе 3. Процедура DriverEntry решает первоочередные задачи, в частности, регистрацию в специальном массиве адресов других драйверных процедур (для того, чтобы Диспетчер ввода/вывода имел возможность позже производить их вызов по адресу). В случае если драйвер не работает по модели WDM (legacy драйвер, драйвер "в-стиле-NT"), то в этой же начальной процедуре можно провести локализацию оборудования, которое будет обслуживать драйвер, выделить или подтвердить использование аппаратных ресурсов (портов ввода/вывода, прерываний, каналов DMA) и предоставить имя, видимое всей остальной системе, для каждого обнаруженного устройства. Для WDM драйверов, поддерживающих спецификацию PnP, процесс определения аппаратных ресурсов откладывается на более позднее время и выполняется драйверной процедурой AddDevice.
Строго говоря, определенное имя (то есть DriverEntry) должно быть только лишь у этой "входной" процедуры. Имена остальных драйверных процедур не столь жестко определены, поскольку они не будут никому известны, за исключением обладателя исходного текста или хакера-исследователя, работающего с отладочной версией. От остальных процедур в системе остаются только их адреса, и к ним предъявляется требование иметь определенный интерфейс вызова, согласованный по типу получаемых и возвращаемых параметров. Поэтому все приведенные в книге имена драйверных процедур можно рассматривать как "говорящие фамилии", кратко описывающие назначение этих процедур. При разработке собственных драйверов можно использовать любые названия. |
Здесь все запросы будут приводить к вызову функции myPassIrpDown, которая занимается только лишь переадресацией запросов нижним драйверам в стеке WDM драйверов. Исключение составит функция-обработчик IOCTL запросов, которые будут поступать в функцию DeviceControlRoutine фильтр-драйвера.
Помимо регистрации функций, процедура DriverEntry драйвера "в-стиле-NT" может выполнять следующую работу:
В случае, если процедура DriverEntry обнаружила, что некоторые действия, которые она должна выполнить как часть подготовки к запуску драйвера, не могут быть выполнены сейчас, но в будущем (после загрузки некоторых других драйверов, например) это станет возможным, то DriverEntry должна зарегистрировать собственную процедуру, которая завершит инициализацию чуть позже.
Регистрация такой процедуры выполняется системным вызовом IoRegisterDriverReinitialization (см. таблицу 8.2).
Таблица 8.2. Параметры системного вызова IoRegisterDriverReinitialization
VOID IoRegisterDriverReinitialization | IRQL == PASSIVE_LEVEL |
Параметры | Регистрирует функцию драйвера для отложенной инициализации |
IN PDRIVER_OBJECT pDriverObject | Указатель на объект драйвера |
IN PDRIVER_REINITIALIZE DriverReinitializationRoutine | Указатель на процедуру реинициализации, предоставляемую драйвером (см. таблицу 8.3 ниже). |
IN PVOID Context | Контекстный указатель, который получит регистрируемая функция при вызове |
Возвращаемое значение | void |
VOID myReinitializeFunction | IRQL == PASSIVE_LEVEL |
Параметры | Функция драйвера, регистрируемая для выполнения отложенной инициализации |
IN PDRIVER_OBJECT pDriverObject | Указатель на объект драйвера |
IN PVOID Context | Контекстный блок, указанный при регистрации |
IN ULONG | Количество вызовов процедуры ре-инициализации (отсчет от 0) |
Возвращаемое значение | void |