Создание VxD на Visual C++ без ассемблерных модулей - Структура и функционирование драйвера
ОГЛАВЛЕНИЕ
Структура и функционирование драйвера
VxD представляет собой 32-разрядный исполняемый файл формата LE (Linear Executable), который является частным случаем DLL. Система может вызывать VxD тремя различными способами:
- Через диспетчер системных сообщений.
- Через таблицу обработчиков сервисных функций.
- Через точки входа интерфейсов прикладных программ.
Функции драйвера могут также вызываться в результате запроса самого драйвера — в ответ на прерывания от устройств, вызов перехваченных функций или программных прерываний, при наступлении различных событий и т.п.
Секции файла драйвера
Загружаемый файл драйвера стандартным образом может делиться на секции (сегменты) с различными атрибутами (резидентный, изначально загруженный, уничтожаемый и т.п.). Документация Microsoft утверждает, что секции должны иметь определенные имена, однако это сделано лишь для удобства пользования стандартным макросами и фактически система распознает лишь сами атрибуты секций.
Рекомендованы следующие имена и классы секций для модуля VxD:
- _LTEXT, _LDATA (класс LCODE) — 32-разрядные секции резидентных кода и данных, которые должны находиться в памяти постоянно. В эти секции включаются процедуры и данные диспетчера системных сообщений, сервисных функций и API, обработчиков прерываний, а также те фрагменты драйвера, для которых нужна предельная скорость выполнения;
- _PTEXT, _PDATA (класс PCODE) — 32-разрядные секции выгружаемых, или откачиваемых, (pageable) кода и данных, которые в процессе работы системы могут быть автоматически выгружены (paged, swapped) на диск для освобождения системной памяти. Подсистема подкачки VMM автоматически возвращает выгруженные страницы в память в момент запроса к ним, однако такие запросы допускаются только в обычном режиме работы и недопустимы при обработке прерываний или критических системных функций;
- _ITEXT, _IDATA (класс ICODE) — 32-разрядные секции кода и данных, используемых только при инициализации драйвера. После отработки драйвером функции инициализации VMM автоматически удаляет эти секции из памяти;
- _RTEXT (класс RCODE) — 16-разрядная секция, в которой размещаются код и данные, используемые при инициализации в реальном режиме (real mode) на этапе начальной загрузки системы. Имеет смысл только для статических драйверов.
Блок описателя драйвера
Ключевым элементом драйвера является структура данных DDB (Device Descriptor Block — блок описателя устройства), которая описывает параметры драйвера. DDB содержит следующие важнейшие поля:
- Идентификация устройства (драйвера) — имя модуля драйвера (максимум восемь символов) и его идентификатор.
- Версия драйвера — старший (major) и младший (minor) номера версий, определяющих функциональность драйвера (устройства).
- Адрес процедуры диспетчера системных сообщений — адрес функции диспетчера, которая будет вызываться для обработки системных сообщений, посылаемых драйверу.
- Адрес и размер таблицы обработчиков сервисных функций — адрес таблицы указателей (адресов) индивидуальных процедур, которые будут вызываться для выполнения сервисных функций, и количество сервисных функций, выполняемых драйвером.
- Адреса обработчиков функций API — адреса индивидуальных процедур, которые вызываются для обработки запросов API от 16-разрядных программ (виртуальных машин DOS и программ Win16).
Символическое имя, назначенное DDB, должно быть описано в модуле драйвера в качестве первой экспортируемой точки входа (exported entry). Сам DDB должен находиться в одной секции резидентного кода вместе с диспетчером системных сообщений.