Как мы уже указывали, статический драйвер загружается при загрузке системы и
остается в памяти до завершения работы операционной системы. Удобнее всего
загрузить драйвер, указав строку device=имя_драйвера
в секции
[386enh]
файла SYSTEM.INI
. Можно также использовать
системный реестр:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\key\StaticVxD=pathname
.
Первое, однако, более удобно, т.к. в случае ошибки в VXD-драйвере можно
исключить его запуск, отредактировав файл SYSTEM.INI
в MS DOS.
При установке виртуальных драйверов VMM посылает драйверам следующие три сообщения в порядке списка.
SysCriticalInit
- посылается при переключении в защищенный
режим, но до разрешения прерываний.
Device_Init
- посылается после разрешения прерываний. Именно это
сообщение чаще всего используется виртуальными драйверами для проведения
начальной инициализации.
Init_Complete
- последнее сообщение, посылаемое виртуальным
драйверам при загрузке системы.
Получив сообщение и выполнив необходимую работу, драйвер должен сбросить флаг переноса и возвратить управление системе.
Перед тем как произвести выгрузку, статические виртуальные драйверы также получают сообщения.
System_Exit2
- сообщение посылается перед выгрузкой системы.
Микропроцессор находится еще в защищенном режиме.
Sys_Critical_Exit2
- следующее сообщение перед выгрузкой
системы.
Device_Reboot_Notify2
- сообщают виртуальным драйверам, что
система "собирается" выгружаться. Прерывания еще доступны.
Crit_Reboot_Notify2
- аналогичное предыдущему сообщению, но
прерывания недоступны.
Обратимся теперь к программе на Рис. 4.7.3. Этот драйвер выводит сообщение при активизации виртуальной машины (например, создание консоли или просто запуск DOS-приложения) и при ее деактивизации. В драйвере мы использовали две сервисные функции: получить дескриптор системной виртуальной машины и вывести сообщение. Рассмотрим эти функции:
Get_sys_vm_handle
- получить дескриптор системной виртуальной
машины. Причем дескриптор возвращается в регистре EBX
.
SHELL_Message
— вывести сообщение. Параметры хранятся в
регистрах:
EBX
— дескриптор виртуальной машины.EAX
- флаг сообщения, напримерMB_OK
.ECX
- 32-битный адрес строки-сообщения.EDI
- 32-битный адрес строки-заголовка.ESI
- адрес функции - реакции на действие пользователя. Если функции нет, тогда0
.EDX
- адрес данных, которые будут посылаться функции.
И еще, при выходе драйвер должен очищать флаг переноса. В нашем случае
очистка флага переноса обусловлена правильным выполнением функции
SHELL_Message
.
IV
В последнем разделе главы мы рассмотрим динамические виртуальные драйверы. Существует три способа загрузки виртуальных динамических драйверов.
- Поместить драйвер в каталог
\SYSTEM\IOSUBSYS
. Драйверы из этого директория загружаются супервизором ввода- вывода. - Использовать сервис
VxDLDR
. Эту сервисную функцию можно вызывать только из виртуальных драйверов. - Использовать функцию
CreateFile
.
Именно последним способом загрузки динамических драйверов мы сейчас и займемся. Схема использования динамических виртуальных драйверов следующая:
- Открываем драйвер с помощью функции
CreateFile
. При удачном открытии функция возвращает идентификатор, который затем используется при вызове функций экспортируемых данным драйвером. - Используем функции динамического драйвера посредством вызова функции API
DeviceIoControl
. - Закрываем драйвер с помощью
CloseHandle
, при этом он автоматически выгружается из памяти.
Перейдем теперь к программе загрузки динамического драйвера. Программа
показана на Рис. 4.7.4. Она загружает драйвер msg.vxd
и вызывает
сервис 3 драйвера.
; файл FILES1.ASM .386P ; плоская модель .MODEL FLAT, stdcall ; константы STD_INPUT_HANDLE equ -10 FILE_FLAG_DELETE_ON_CLOSE equ 4000000h ; прототипы внешних процедур EXTERN GetStdHandle@4:NEAR EXTERN ExitProcess@4:NEAR EXTERN GetCommandLineA@0:NEAR EXTERN CreateFileA@28:NEAR EXTERN CloseHandle@4:NEAR EXTERN MessageBoxA@16:NEAR EXTERN ReadConsoleA@20:NEAR EXTERN DeviceIoControl@32:NEAR ; ;------------------------------------------------ ;директивы компоновщику для подключения библиотек includelib c:\masm32\lib\user32.lib includelib c:\masm32\lib\kernel32.lib ;------------------------------------------------ ; ; сегмент данных _DATA SEGMENT DWORD PUBLIC USE32 'DATA' HANDL DWORD ? HFILE DWORD ? BUF DB "\\.\msg.vxd",0 CAP DB "Окно сообщения",0 MES DB "Ошибка загрузки драйвера",0 BUFER DB 20 DUP (0) LENS DWORD ? ; количество выведенных символов MES1 DB "Вызов сервиса OK!",0 _DATA ENDS ; сегмент кода _TEXT SEGMENT DWORD PUBLIC USE32 'CODE' START: ; получить HANDLE ввода PUSH STD_INPUT_HANDLE CALL GetStdHandle@4 MOV HANDL,EAX ; открыть файл PUSH 0 PUSH FILE_FLAG_DELETE_ON_CLOSE PUSH 0 PUSH 0 PUSH 0 PUSH 0 PUSH OFFSET BUF CALL CreateFileA@28 CMP EAX,-1 JE _ERR MOV HFILE,EAX ; вызов сервиса VXD PUSH 0 PUSH 0 PUSH 0 PUSH 0 PUSH 18 PUSH OFFSET MES1 PUSH 3 ; номер сервиса PUSH HFILE CALL DeviceIoControl@32 ; ждать клавиши ENTER PUSH 0 PUSH OFFSET LENS PUSH 200 PUSH OFFSET BUFER PUSH HANDL CALL ReadConsoleA@20 ; закрыть и выгрузить драйвер PUSH HFILE CALL CloseHandle@4 _EXIT: ; конец работы программы PUSH 0 CALL ExitProcess@4 _ERR: PUSH 0 ; MB_OK PUSH OFFSET CAP PUSH OFFSET MES PUSH 0 ; дескриптор окна CALL MessageBoxA@16 JMP _EXIT _TEXT ENDS END START