Vorwort
Verwenden Sie Delphi 3.0, um einen VxD-Gerätetreiber zu schreiben. Er wird unter Delphi 3 kompiliert und besteht keinen Test. Die von Delphi 4 erstellte Objektdatei M$ Linker 5.12.8181 kann nicht erkannt werden. Der hier verwendete Assembler ist M$ 's Macro Assembler Version 6.11d, der Linker ist M$ Incremental Linker Version 5.12.8181 , sie stammen von Windows 98DDK (http://www.microsoft.com/ddk/ddk98.htm).
einführen
Es gibt zwei Arten von VxD-Gerätetreibern für Windows:
1. Statisches VxD, geladen in das Betriebssystem und dauerhaft im Speicher vorhanden;
2. Dynamisches VxD, das bei Bedarf in den Speicher geladen wird. Schließen Sie nach der Verwendung das VxD, um den Speicher freizugeben.
InPRise Delphi bietet die Möglichkeit, jede Art von VxD-Gerätetreiber zu erstellen. Im Folgenden stellen wir vor, wie man dynamisches VxD erstellt.
Wenn eine Win32-Anwendung ein „virtuelles“ VxD-Gerät öffnet, verwendet VWIN32 LoadDevice, um das VxD in den Speicher zu laden, erstellt eine Nachricht W32_DEVICEIOCONTROL und sendet sie an das VxD.
Das heißt, VxD sollte mindestens auf die folgenden beiden Systemmeldungen reagieren und eine der folgenden Funktionen schreiben:
SYS_DYNAMIC_DEVICE_INIT
SYS_DYNAMIC_DEVICE_EXIT
W32_DEVICEIOCONTROL-Funktion.
Die Nachricht SYS_DYNAMIC_DEVICE_INIT wird an VxD gesendet, wenn versucht wird, VxD zu laden, und die Nachricht SYS_DYNAMIC_DEVICE_EXIT wird an VxD gesendet, wenn versucht wird, dynamisch auszutauschen. Der Handler der Nachricht sollte nach erfolgreicher Verarbeitung das VXD_SUCCESS-Flag im Register AX zurückgeben.
Der dwService-Parameter von W32_DEVICEIOCONTROL hat die folgenden Werte:
DIOC_OPEN wird gesendet, wenn VxD versucht, einen Öffnungsvorgang über die Funktion CreateFile() durchzuführen (nach der SYS_DYNAMIC_DEVICE_INIT-Nachricht), und gibt bei Erfolg NO_ERROR (0) zurück;
DIOC_CLOSEHANDLE Wird gesendet, wenn VxD versucht, einen Schließvorgang über die Funktion CloseHandle() durchzuführen (vor SYS_DYNAMIC_DEVICE_EXIT).
Alle anderen Werte > 0 bedeuten einen anderen Funktionsaufruf (gegeben durch dwIoControlCode), wenn der VxD von der DeviceIoControl-Funktion aufgerufen wird.
Modul starten (vxdmain.asm)
...
extrn SysDynamicDeviceInit:PROC
extrn SysDynamicDeviceExit:PROC
extrn W32DeviceIoControl:PROC
...
PUBLIC DELPHIIO_DDB
Öffentliches @@HandleFinally
Öffentliche @Initialisierung
...
Control_0 proc
cmp eax, SYS_DYNAMIC_DEVICE_INIT
jnz kurz chkSysDynExit
Rufen Sie SysDynamicDeviceInit auf
cmp eax, 1
zurück
;-------------
chkSysDynExit:
cmp eax, SYS_DYNAMIC_DEVICE_EXIT
jnz kurz chkDevIOCtl
Rufen Sie SysDynamicDeviceExit auf
cmp eax, 1
zurück
;-------------
chkDevIOCtl:
cmp eax, W32_DEVICEIOCONTROL
jnz kurz loc_ret
drücke esi
edx drücken
pushebx
pushecx
Rufen Sie W32DeviceIoControl auf
cmp eax, 1
zurück
;-------------
loc_ret:
clc
zurück
Control_0 endp
@@HandleFinally:
@Initialisierung:
im Ruhestand
_LTEXT endet
ENDE
Delphi ruft die externen Prozeduren HandleFinaly und initialization für die Initialisierung/Finalisierung der Unit auf, auch wenn die Initialisierung/Finalisierung in der Unit nicht vorhanden ist. Daher erstellen wir einen leeren externen Prozedureintrag in der Assembly-Startdatei.
Hauptprogrammeinheit von Delphi (vxdProcs.pas)
...
procedure ShellMessage(Handle, Flags: integer; const Message, Caption: PChar;
Callback, ReferenceData : pointer); stdcall;
asm
mov ebx, Handle // Handle der virtuellen Maschine
mov eax, Flags // Meldungsfeld-Flags
mov ecx, Message // Adresse des Nachrichtentextes
mov edi, Caption // Adresse des Untertiteltextes
mov esi, Callback // Adresse des Rückrufs
mov edx, ReferenceData // Referenzdaten für Rückruf
int 20H // VxDCall
dd 170004h // Shell_Message
Ende;
Funktion SysDynamicDeviceInit: INTEGER;
beginnen
ShellMessage(0, $10, Copyright, 'SysDynInit: Hallo von Delphi VxD !!!', nil, nil);
Ergebnis := VXD_SUCCESS;
Ende;
Funktion SysDynamicDeviceExit: INTEGER;
beginnen
ShellMessage(0, $10, Copyright, 'SysDynDevExit: Bye from Delphi VxD !!!', nil, nil);
Ergebnis := VXD_SUCCESS;
Ende;
Funktion W32DeviceIoControl(dwService : INTEGER;
dwDDB: INTEGER;
hDevice: INTEGER;
lpDIOCParms : Zeiger) : INTEGER;
beginnen
ShellMessage(0, $10, Copyright, 'W32DevIOCtl', nil, nil);
if (dwService = DIOC_OPEN) dann
beginnen
Ergebnis := NO_ERROR;
Ende
sonst wenn (dwService = DIOC_CLOSEHANDLE) dann
beginnen
Ergebnis := VXD_SUCCESS;
Ende
sonst wenn (dwService > MAX_PASVXD_W32_API) dann
beginnen
Ergebnis := ERROR_NOT_SUPPORTED;
Ende
anders
beginnen
Ergebnis := VXD_SUCCESS;
Ende;
Ende;
...
[Übersetzer: Ok, der einfache VxD-Gerätetreiber wurde geschrieben. Sie können es als Vorlage zum Schreiben von VxD-Gerätetreibern verwenden. ]
Anhang 1: Make.bat
D:VISUAL~198DDKBINWin98ml -coff -DBLD_COFF -DIS_32 -W2 -c -Cx -Zm -DMASM6 vxdmain.asm
Rufen Sie dcc3.bat -J vxdprocs.pas auf
D:VISUAL~198DDKBINlink /DEF:vxddef.def /VXD vxdmain.obj vxdprocs /OUT:delphiio.vxd
Anhang 2:
Schreiben wir nun ein Testprogramm für VxD mit zwei Schaltflächen: eine zum Öffnen von VxD und eine zum Schließen von VxD.
const
VxDName = '/.DELPHIIO.VXD';
...
Funktion TVxDTestForm.OpenVxDDriver: boolean;
beginnen
HVxDHandle := CreateFile(VxDName,0,0,nil,0,FILE_FLAG_DELETE_ON_CLOSE,0);
Ergebnis := HVxDHandle <> INVALID_HANDLE_VALUE;
Ende;
Prozedur TVxDTestForm.CloseVxDDriver;
beginnen
Wenn HVxDHandle <> INVALID_HANDLE_VALUE, dann beginnen
CloseHandle(HVxDHandle);
HVxDHandle := INVALID_HANDLE_VALUE;
Ende;
Ende