作者:mickeylan
Delphi能不能开发Windows的驱动程序(这里的驱动程序当然不是指VxD了^_^)一直是广大Delphi fans关注的问题。姑且先不说能或者不能,我们先来看看用Delphi开发驱动程序需要解决哪些技术上问题。
Delphi的链接器是无法生成Windows内核模式程序的,因此用delphi无法直接生成驱动程序。M$的链接器是可以生成Windows内核模式程序的,那么是否可以用Delphi生成目标文件,然后用M$链接呢?要这么做必须要解决以下的问题:
Delphi生成的目标文件是OMF格式的,而M$ link虽然声称支持OMF格式的目标文件,但基本无用。最好能将OMF格式转换成COFF格式,EliCZ大侠的OMF2D正好可以解决这个问题。解决了目标格式的问题,一切都OK了吗?远没这么简单。继续之前,让我们先来看一下著名的DDDK吧。
DDDK(Delphi Driver Development Kit)是The Hacker Defender Project team发布的一个用Delphi开发Windows驱动程序的工具包,目前最新版是0.0.4版。DDDK是将常用的驱动API用Delphi做了层包装放在DDDK单元中,就像下面这样:
unit DDDK; interface const NtKernel='ntoskrnl.exe'; …… procedure IoCompleteRequest(Irp:PIrp;PriorityBoost:Integer); stdcall; …… implementation procedure krnlIoCompleteRequest(Irp:PIrp;PriorityBoost:Integer); stdcall; external NtKernel name 'IoCompleteRequest'; procedure IoCompleteRequest(Irp:PIrp;PriorityBoost:Integer); stdcall; begin krnlIoCompleteRequest(Irp,PriorityBoost); end; …… |
LIBRARY HAL.DLL EXPORTS ExAcquireFastMutex ExReleaseFastMutex ExTryToAcquireFastMutex HalAcquireDisplayOwnership HalAdjustResourceList HalAllProcessorsStarted …… |
unit beeper; interface uses windows, DDDK, hal; function _DriverEntry(DriverObject:PDriverObject;RegistryPath:PUnicodeString):NTSTATUS; stdcall; implementation const TIMER_FREQUENCY:DWORD = 1193167; {1,193,167 Hz} OCTAVE:DWORD = 2; {octave multiplier} PITCH_C:DWORD = 523; {C - 523,25 Hz} PITCH_Cs:DWORD = 554; {C# - 554,37 Hz} PITCH_D:DWORD = 587; {D - 587,33 Hz} PITCH_Ds:DWORD = 622; {D# - 622,25 Hz} PITCH_E:DWORD = 659; {E - 659,25 Hz} PITCH_F:DWORD = 698; {F - 698,46 Hz} PITCH_Fs:DWORD = 740; {F# - 739,99 Hz} PITCH_G:DWORD = 784; {G - 783,99 Hz} PITCH_Gs:DWORD = 831; {G# - 830,61 Hz} PITCH_A:DWORD = 880; {A - 880,00 Hz} PITCH_As:DWORD = 988; {B - 987,77 Hz} PITCH_H:DWORD = 1047; {H - 1046,50 Hz} { We are going to play c-major chord } DELAY:DWORD = $18000000; {for my ~800mHz box} TONE_1:DWORD = 1141; TONE_2:DWORD = 905; TONE_3:DWORD = 1568; {for HalMakeBeep} STATUS_DEVICE_CONFIGURATION_ERROR:DWORD = $00C0000182; procedure MakeBeep1(dwPitch: DWORD); stdcall; assembler; asm cli mov al, 10110110b out 43h, al mov eax, dwPitch out 42h, al mov al, ah out 42h, al {Turn speaker ON} in al, 61h or al, 11b out 61h, al sti push eax mov eax, DELAY @@1: dec eax jnz @@1 pop eax cli {Turn speaker OFF} in al, 61h and al, 11111100b out 61h, al sti end; procedure MakeBeep2(dwPitch: DWORD); stdcall; var dwPort, i: DWORD; begin asm cli; end; WRITE_PORT_UCHAR(PUCHAR($43), $b6); WRITE_PORT_UCHAR(PUCHAR($42), dwPitch and $FF); WRITE_PORT_UCHAR(PUCHAR($42), ((dwPitch shr 8) and $FF)); dwPort := READ_PORT_UCHAR(PUCHAR($61)); dwPort := dwPort or 3; WRITE_PORT_UCHAR(PUCHAR($61), dwPort); asm sti end; for i := 1 to DELAY do begin end; asm cli end; { Turn speaker OFF } dwPort := READ_PORT_UCHAR(PUCHAR($61)); dwPort := dwPort and $FC; WRITE_PORT_UCHAR(PUCHAR($61), dwPort); asm sti end; end; function _DriverEntry(DriverObject:PDriverObject;RegistryPath:PUnicodeString):NTSTATUS; stdcall; var i: integer; begin MakeBeep1(TONE_1); MakeBeep2(TONE_2); HalMakeBeep(TONE_3); for i := 1 to DELAY do begin end; HalMakeBeep(0); Result := STATUS_DEVICE_CONFIGURATION_ERROR; end; end. |
unit hal; interface uses Windows; const NtHal = 'hal.dll'; function HalMakeBeep(Frequency: ULONG):BOOLEAN; stdcall; function READ_PORT_UCHAR(Port:PUCHAR):UCHAR; stdcall; procedure WRITE_PORT_UCHAR(Port: PUCHAR; Value: UCHAR); stdcall; implementation function HalMakeBeep(Frequency: ULONG):BOOLEAN; stdcall; external NtHal name '_HalMakeBeep'; function READ_PORT_UCHAR(Port:PUCHAR):UCHAR; stdcall; external NtHal name '_READ_PORT_UCHAR'; procedure WRITE_PORT_UCHAR(Port: PUCHAR; Value: UCHAR); stdcall; external NtHal name '_WRITE_PORT_UCHAR'; end. |