Предисловие
Используйте Delphi 3.0 для написания драйвера устройства VxD. Он компилируется и проходит под Delphi 3. В Delphi 2 нет тестов. Объектный файл M$ Linker 5.12.8181, созданный Delphi 4, не может быть распознан. Здесь используется ассемблер M$. Macro Assembler версии 6.11d, компоновщик — M$ Incremental Linker версии 5.12.8181. они взяты из Windows 98DDK (http://www.microsoft.com/ddk/ddk98.htm).
представлять
Существует два типа драйверов устройств VxD для Windows:
1. Статический VxD, загруженный в операционную систему и постоянно существующий в памяти;
2. Динамический VxD, который загружается в память при необходимости. После использования закройте VxD, чтобы освободить память.
InPRise Delphi позволяет создавать драйверы устройств VxD любого типа. Ниже мы расскажем, как создавать динамические VxD.
Когда приложение Win32 открывает «виртуальное» устройство VxD, VWIN32 использует LoadDevice для загрузки VxD в память, создает сообщение W32_DEVICEIOCONTROL и отправляет его VxD.
То есть VxD должен как минимум ответить на следующие два системных сообщения и написать одну из следующих функций:
SYS_DYNAMIC_DEVICE_INIT
SYS_DYNAMIC_DEVICE_EXIT
Функция W32_DEVICEIOCONTROL.
Сообщение SYS_DYNAMIC_DEVICE_INIT отправляется в VxD при попытке загрузить VxD, а сообщение SYS_DYNAMIC_DEVICE_EXIT отправляется в VxD при попытке динамического обмена. Обработчик сообщения должен вернуть флаг VXD_SUCCESS в регистре AX после успешной обработки.
Параметр dwService W32_DEVICEIOCONTROL имеет следующие значения:
DIOC_OPEN отправляется, когда VxD пытается выполнить операцию открытия с помощью функции CreateFile() (после сообщения SYS_DYNAMIC_DEVICE_INIT), и в случае успеха возвращает NO_ERROR (0);
DIOC_CLOSEHANDLE Отправляется, когда VxD пытается выполнить операцию закрытия с помощью функции CloseHandle() (до SYS_DYNAMIC_DEVICE_EXIT).
Все остальные значения > 0 означают другой вызов функции (заданный dwIoControlCode), когда VxD вызывается функцией DeviceIoControl.
Стартовый модуль (vxdmain.asm)
...
extrn SysDynamicDeviceInit:PROC
extrn SysDynamicDeviceExit:PROC
экстрн W32DeviceIoControl:PROC
...
ПУБЛИЧНЫЙ DELPHIIO_DDB
Публичный @@HandleFinally
Публичная @инициализация
...
Процесс Control_0
cmp eax, SYS_DYNAMIC_DEVICE_INIT
jnz короткий chkSysDynExit
вызвать SysDynamicDeviceInit
cmp eax, 1
ретн
;-------------
chkSysDynExit:
cmp eax, SYS_DYNAMIC_DEVICE_EXIT
jnz короткий chkDevIOCtl
вызвать SysDynamicDeviceExit
cmp eax, 1
ретн
;-------------
chkDevIOCtl:
cmp eax, W32_DEVICEIOCONTROL
jnz короткий loc_ret
нажать esi
нажать edx
pushebx
pushecx
вызвать W32DeviceIoControl
cmp eax, 1
ретн
;-------------
лок_рет:
клк
ретн
Конечная точка Control_0
@@HandleНаконец:
@инициализация:
в отставку
_LTEXT заканчивается
КОНЕЦ
Delphi вызовет внешние процедуры HandleFinaly и инициализацию для инициализации/финализации модуля, даже если инициализация/финализация в модуле не существует. Поэтому мы создаем пустую запись внешней процедуры в файле запуска сборки.
Основной программный модуль Delphi (vxdProcs.pas)
...
процедура ShellMessage(Handle, Флаги: целое число; const Сообщение, Заголовок: PChar;
Обратный вызов, ReferenceData: указатель);
Асм
mov ebx, Handle // дескриптор виртуальной машины
mov eax, Flags // флаги окна сообщения
mov ecx, Message // адрес текста сообщения
mov edi, Caption // адрес текста подписи
mov esi, Callback // адрес обратного вызова
mov edx, ReferenceData // справочные данные для обратного вызова
int 20H // VxDCall
дд 170004h // Shell_Message
конец;
функция SysDynamicDeviceInit: INTEGER;
начинать
ShellMessage(0, $10, Copyright, 'SysDynInit: Привет от Delphi VxD !!!', ноль, ноль);
Результат: = VXD_SUCCESS;
конец;
функция SysDynamicDeviceExit: INTEGER;
начинать
ShellMessage(0, $10, Copyright, 'SysDynDevExit: Пока из Delphi VxD !!!', ноль, ноль);
Результат: = VXD_SUCCESS;
конец;
функция W32DeviceIoControl (dwService: INTEGER;
dwDDB: ЦЕЛОЕ ЧИСЛО;
hУстройство: ЦЕЛОЕ;
lpDIOCParms: указатель): INTEGER;
начинать
ShellMessage(0, $10, Copyright, 'W32DevIOCtl', ноль, ноль);
если (dwService = DIOC_OPEN), то
начинать
Результат:= НЕТ_ОШИБКИ;
конец
иначе если (dwService = DIOC_CLOSEHANDLE), то
начинать
Результат: = VXD_SUCCESS;
конец
иначе если (dwService > MAX_PASVXD_W32_API), то
начинать
Результат: = ERROR_NOT_SUPPORTED;
конец
еще
начинать
Результат: = VXD_SUCCESS;
конец;
конец;
...
[Переводчик: Хорошо, простой драйвер устройства VxD написан. Вы можете использовать его как шаблон для написания драйверов устройств VxD. ]
Приложение 1: Make.bat
D:VISUAL~198DDKBINWin98ml -coff -DBLD_COFF -DIS_32 -W2 -c -Cx -Zm -DMASM6 vxdmain.asm
вызовите dcc3.bat -J vxdprocs.pas
D:VISUAL~198DDKBINlink /DEF:vxddef.def /VXD vxdmain.obj vxdprocs /OUT:delphiio.vxd
Приложение 2:
Теперь давайте напишем тестовую программу для VxD с двумя кнопками: одна для открытия VxD, другая для закрытия VxD;
константа
VxDName = '/.DELPHIIO.VXD';
...
функция TVxDTestForm.OpenVxDDriver: логическое значение;
начинать
HVxDHandle:= CreateFile(VxDName,0,0,nil,0,FILE_FLAG_DELETE_ON_CLOSE,0);
Результат: = HVxDHandle <> INVALID_HANDLE_VALUE;
конец;
процедура TVxDTestForm.CloseVxDDriver;
начинать
если HVxDHandle <> INVALID_HANDLE_VALUE, то начнем
CloseHandle(HVxDHandle);
HVxDHandle:= INVALID_HANDLE_VALUE;
конец;
конец