Загальна інформація

Компіляція даного прикладу можлива тільки з Delphi 3. Delphi 2
не був випробуваний у зв'язку з його відсутністю, об'єктні фали створені Delphi 4
відкидаються Microsoft ® Linker 5.12.8181 як файли невідомого формату.
При
написанні даного матеріалу були використані Microsoft ® Macro Assembler ver.
6.11d і Microsoft ® Incremental Linker ver. 5.12.8181 з поставки Windows 98DDK

Введення


VxD драйвера діляться два типи:
Практично можливе створення драйвера підтримує обидва типи
завантаження.

Нам необхідний динамічно завантажуваний VxD драйвер (далі "VxD") т.к. такий
драйвер можна буде без перезавантаження Windows завантажувати з Win32 ® додатків
використовуючи процедуру CreateFile().

Коли
Win32 додаток відкриває дескриптор для VxD, віртуальний пристрій VWIN32
використовуючи сервіс LoadDevice завантажує VxD-драйвер в пам'ять і посилає
інформаційне повідомлення W32_DEVICEIOCONTROL
завантаженому VxD.


Таким чином для побудови VxD необхідно обробляти як мінімум три
системних повідомлення:



Собщение SYS_DYNAMIC_DEVICE_INIT надсилається при спробі динамічного завантаження
VxD, SYS_DYNAMIC_DEVICE_EXIT надсилається при спробі динамічної вивантаженні. З
обробників повідомлень для підтвердження успіху необхідно повернути VXD_SUCCESS в
регістрі AX
Повідомлення W32_DEVICEIOCONTROL
має наступні значення для параметра dwService


Завантажувальний модуль (vxdmain.asm)


При зверненні до
процедурам знаходяться в модулях Delphi треба врахувати для fastcall-процедур до
імені додається на початку символ "@"

extrn SysDynamicDeviceInit :PROC
extrn SysDynamicDeviceExit :PROC
extrn W32DeviceIoControl :PROC

Control_0 proc
cmp eax, SYS_DYNAMIC_DEVICE_INIT
jnz short chkSysDynExit
call SysDynamicDeviceInit
cmp eax, 1
retn
;————-

chkSysDynExit:
cmp eax, SYS_DYNAMIC_DEVICE_EXIT
jnz short chkDevIOCtl
call SysDynamicDeviceExit
cmp eax, 1
retn
;————-
chkDevIOCtl:
cmp eax, W32_DEVICEIOCONTROL
jnz short loc_ret
push esi
push edx
push ebx
push ecx
call W32DeviceIoControl
cmp eax, 1
retn
;————-
loc_ret:
clc
retn

Control_0 endp


Delphi створює код для ініціалізації / деініціалізацію модулів, звертаючись до
зовнішнім процедурам HandleFinaly і initialization навіть якщо блоки initilization і
finalization в модулі відсутні. Створимо порожню "заглушку" для цих процедур
і оголосимо їх доступними для зовнішніх модулів.


Public @@HandleFinally
Public @initialization

@@HandleFinally:
@initialization:
ret

end.

Процедурний модуль (vxdProcs.pas)


procedure ShellMessage(Handle, Flags : integer;
const Message, Caption : PChar;
Callback, ReferenceData : pointer); stdcall; assembler;
asm
mov ebx, Handle // virtual machine handle
mov eax, Flags // message box flags
mov ecx, Message // address of message text
mov edi, Caption // address of caption text
mov esi, Callback // address of callback
mov edx, ReferenceData // reference data for callback

int 20H // VxDCall
dd 170004h // Shell_Message
end;

const
Copyright : PChar = “(c) 1999 Emil Biserov, “+
“fatty@mail.primorye.ru, http://dinfo.da.ru”;

function SysDynamicDeviceInit : INTEGER;
begin
ShellMessage(0, $10, Copyright,
“SysDynInit: Hello from Delphi VxD !!!”, nil, nil);
Result := VXD_SUCCESS;
end;

function SysDynamicDeviceExit : INTEGER;
begin
ShellMessage(0, $10, Copyright,
“SysDynDevExit: Bye from Delphi VxD !!!”, nil, nil);
Result := VXD_SUCCESS;
end;

var
Str : array [0..16] of char;

function W32DeviceIoControl(dwService : INTEGER;
dwDDB : INTEGER;
hDevice : INTEGER;
lpDIOCParms : pointer) : INTEGER;
begin
ShellMessage(0, $10, Copyright, “W32DevIOCtl”, nil, nil);

if (dwService = DIOC_OPEN) then
begin
Result := NO_ERROR;
end
//
//
else if (dwService = DIOC_CLOSEHANDLE) then
begin
Result := VXD_SUCCESS;
end
else if (dwService > MAX_PASVXD_W32_API) then
begin
Result := ERROR_NOT_SUPPORTED;
end
else
begin
Result := VXD_SUCCESS;
end;
end;


Інструмент для завантаження / розвантаження VxD


Представляє з себе просту форму з двома кнопками. Наведу лише методи для
відкриття та закриття VxD драйвера.

const
VxDName = “.DELPHIIO.VXD”;

function TVxDTestForm.OpenVxDDriver: boolean;
begin
HVxDHandle: = CreateFile (VxDName, 0,0, nil, 0, FILE_FLAG_DELETE_ON_CLOSE, 0);
Result := HVxDHandle <> INVALID_HANDLE_VALUE;
end;

procedure TVxDTestForm.CloseVxDDriver;
begin
if HVxDHandle <> INVALID_HANDLE_VALUE then begin
CloseHandle(HVxDHandle);
HVxDHandle := INVALID_HANDLE_VALUE;
end;
end;


Вивантаження невикористаного модуля можна робити автоматично, вказавши в
параметрах CreateFile (,,,,, FILE_FLAG_DELETE_ON_CLOSE,). У даному випадку система
при кожному відкритті дескриптора до VxD буде збільшувати внутрішній лічильник
використання на 1 і віднімати 1 при закритті дескриптора. При значенні лічильника
рівному нулю VxD буде автоматично вивантажено.


Висновки


Драйвера на Delphi писати можна. Але от тільки чи варто?
Використання VxD
має сенс тільки для використання Windows 3.1 і Windows 95. Та й доступ до
апаратних ресурсів в них набагато прозоріше ніж Windows NT/2000. Windows 98,
Windows NT і Windows2000 підтримують нову модель драйверів WDM 1.0/2.0,
використовує формат PE (Portable Executable) і (приблизно) проблем буде
менше, ніж з VxD і його LE (Linear Executable) форматом драйверів.


Матеріали MSDN



  1. Supporting
    Input-Output Control in VxDs
  2. Loading
    and Opening the VxD
  3. Opening
    the VxD
  4. Calling
    DeviceIoControl on Windows 95/98

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*