Prefácio
Use Delphi 3.0 para escrever um driver de dispositivo VxD. Ele compila e passa no Delphi 3. Não há teste no Delphi 2. O arquivo objeto M$ Linker 5.12.8181 criado pelo Delphi 4 não pode ser reconhecido. do Macro Assembler versão 6.11d, o vinculador é M$ Incremental Linker versão 5.12.8181. , eles vêm do Windows 98DDK (http://www.microsoft.com/ddk/ddk98.htm).
introduzir
Existem dois tipos de drivers de dispositivo VxD para Windows:
1. VxD estático, carregado no sistema operacional e existente permanentemente na memória;
2. VxD dinâmico, que é carregado na memória quando necessário. Após o uso, feche o VxD para liberar a memória.
InPRise Delphi tem a capacidade de criar qualquer tipo de driver de dispositivo VxD. Abaixo apresentaremos como criar VxD dinâmico.
Quando um aplicativo Win32 abre um dispositivo "virtual" VxD, o VWIN32 usa LoadDevice para carregar o VxD na memória e cria uma mensagem W32_DEVICEIOCONTROL e a envia para o VxD.
Em outras palavras, o VxD deve responder pelo menos às duas mensagens do sistema a seguir e escrever uma das seguintes funções:
SYS_DYNAMIC_DEVICE_INIT
SYS_DYNAMIC_DEVICE_EXIT
Função W32_DEVICEIOCONTROL.
A mensagem SYS_DYNAMIC_DEVICE_INIT é enviada para VxD ao tentar carregar VxD, e a mensagem SYS_DYNAMIC_DEVICE_EXIT é enviada para VxD ao tentar trocar dinamicamente. O manipulador da mensagem deve retornar o sinalizador VXD_SUCCESS no registro AX após o processamento bem-sucedido.
O parâmetro dwService de W32_DEVICEIOCONTROL possui os seguintes valores:
DIOC_OPEN é enviado quando o VxD tenta uma operação aberta por meio da função CreateFile() (após a mensagem SYS_DYNAMIC_DEVICE_INIT) e retorna NO_ERROR (0) se for bem-sucedido;
DIOC_CLOSEHANDLE Enviado quando o VxD tenta uma operação de fechamento por meio da função CloseHandle() (antes de SYS_DYNAMIC_DEVICE_EXIT)
Todos os outros valores > 0 significam uma chamada de função diferente (fornecida por dwIoControlCode) quando o VxD é chamado pela função DeviceIoControl.
Iniciar módulo (vxdmain.asm)
...
extrn SysDynamicDeviceInit:PROC
extrn SysDynamicDeviceExit:PROC
externo W32DeviceIoControl:PROC
...
PÚBLICO DELPHIIO_DDB
Público @@HandleFinalmente
@inicialização pública
...
Processo Control_0
cmp eax, SYS_DYNAMIC_DEVICE_INIT
jnz curto chkSysDynExit
chamar SysDynamicDeviceInit
cmp eax, 1
retn
;-------------
chkSysDynExit:
cmp eax, SYS_DYNAMIC_DEVICE_EXIT
jnz curto chkDevIOCtl
chamar SysDynamicDeviceExit
cmp eax, 1
retn
;-------------
chkDevIOCtl:
cmp eax, W32_DEVICEIOCONTROL
jnz curto loc_ret
empurre esi
empurrar edx
pushebx
pushecx
chamar W32DeviceIoControl
cmp eax, 1
retn
;-------------
loc_ret:
clc
retn
Control_0 final
@@HandleFinalmente:
@inicialização:
ret
_LTEXT termina
FIM
O Delphi chamará os procedimentos externos HandleFinaly e inicialização para a inicialização/finalização da unidade, mesmo que a inicialização/finalização não exista na unidade. Portanto, criamos uma entrada de procedimento externo vazia no arquivo de inicialização da montagem.
Unidade principal do programa Delphi (vxdProcs.pas)
...
procedimento ShellMessage(Handle, Flags: inteiro; const Mensagem, Legenda: PChar;
Retorno de chamada, ReferenceData: ponteiro);
asm
mov ebx, Handle // identificador da máquina virtual
mov eax, Flags // sinalizadores de caixa de mensagem
mov ecx, Mensagem // endereço do texto da mensagem
mov edi, Legenda // endereço do texto da legenda
mov esi, Callback // endereço do retorno de chamada
mov edx, ReferenceData // dados de referência para retorno de chamada
interno 20H //VxDCall
dd 170004h //Shell_Message
fim;
função SysDynamicDeviceInit: INTEGER;
começar
ShellMessage(0, $10, Copyright, 'SysDynInit: Olá do Delphi VxD !!!', nil, nil);
Resultado:= VXD_SUCCESS;
fim;
função SysDynamicDeviceExit: INTEGER;
começar
ShellMessage(0, $10, Copyright, 'SysDynDevExit: Tchau do Delphi VxD !!!', nil, nil);
Resultado:= VXD_SUCCESS;
fim;
função W32DeviceIoControl(dwService: INTEGER;
dwDDB: INTEIRO;
hDispositivo: INTEGER;
lpDIOCParms: ponteiro): INTEGER;
começar
ShellMessage(0, $10, Direitos autorais, 'W32DevIOCtl', nulo, nulo);
se (dwService = DIOC_OPEN) então
começar
Resultado: = NO_ERROR;
fim
senão se (dwService = DIOC_CLOSEHANDLE) então
começar
Resultado:= VXD_SUCCESS;
fim
senão se (dwService > MAX_PASVXD_W32_API) então
começar
Resultado: = ERROR_NOT_SUPPORTED;
fim
outro
começar
Resultado:= VXD_SUCCESS;
fim;
fim;
...
[Tradutor: Ok, o driver de dispositivo VxD simples foi escrito. Você pode usá-lo como modelo para escrever drivers de dispositivos VxD. ]
Apêndice 1: Make.bat
D:VISUAL~198DDKBINWin98ml -coff -DBLD_COFF -DIS_32 -W2 -c -Cx -Zm -DMASM6 vxdmain.asm
chame dcc3.bat -J vxdprocs.pas
D:VISUAL~198DDKBINlink /DEF:vxddef.def /VXD vxdmain.obj vxdprocs /OUT:delphiio.vxd
Apêndice 2:
Agora vamos escrever um programa de teste para o VxD, com dois botões: um para abrir o VxD; outro para fechar o VxD;
const
VxDName = '/.DELPHIIO.VXD';
...
função TVxDTestForm.OpenVxDDriver: booleano;
começar
HVxDHandle := CreateFile(VxDName,0,0,nil,0,FILE_FLAG_DELETE_ON_CLOSE,0);
Resultado:= HVxDHandle <> INVALID_HANDLE_VALUE;
fim;
procedimento TVxDTestForm.CloseVxDDriver;
começar
se HVxDHandle <> INVALID_HANDLE_VALUE então comece
CloseHandle(HVxDHandle);
HVxDHandle := INVALID_HANDLE_VALUE;
fim;
fim