FPC (как и большое число 'free' компиляторов), более заточен на работу с линкером LD, которым к сожалению не удалось получить нормально работающий в "subsystem: native" бинарник. Однако если учесть некоторые нюансы, то cборку можно произвести и другими линкерами, как например Watcom и Microsoft Link. Это делает возможным компиляцию драйвера, подключение ресурсов и частей кода на других языках, и т.п Единственное что необходимо учесть - вызвы из внешних библиотек обьявлять более тщательно к примеру: Код (Text): procedure IoDeleteDevice (DeviceObject:pointer); stdcall; external name 'IoDeleteDevice'; // procedure Sleep(dwMilliseconds: DWORD); stdcall; external name '_Sleep@4'; Собственно и всё, в целом же написать, драйвер на FPC ничуть не сложнее чем на других языках... Для примера - вариант известного "GiveIO", вариант "содраный" с дельфов, практически в 1:1 (при его компиляции следует задать опцию -Sd ( совместимость с delphi). Код (Text): library GiveIO; {$I ntddk} var IOPM : array [0..$2000] of byte; const DevStr = '\Device\GiveIO'; DosStr = '\DosDevices\GiveIO'; UdevStr : UNICODE_STRING = (Length:0); UdosStr : UNICODE_STRING = (Length:0); IOPM_size = $2000; IOPM_local: pointer = @IOPM; function DrvCreateDispatch (DrvObj:PDRIVER_OBJECT;Irp:pointer):integer; stdcall; begin Ke386IoSetAccessProcess (IoGetCurrentProcess, 1); RtlZeroMemory (IOPM_local, $2000); Ke386SetIoAccessMap (1, IOPM_local); IoCompleteRequest (Irp, 0); DrvCreateDispatch := 0; end; procedure DrvUnload (DrvObj:PDRIVER_OBJECT); stdcall; begin IoDeleteSymbolicLink (UDosStr); IoDeleteDevice (DrvObj.DeviceObject); end; function _DriverEntry (DrvObj: PDRIVER_OBJECT; RegistryPath :pointer):integer;stdcall; //export ; var DeviceObject : pointer; begin RTlInitUnicodeString (UdevStr, devStr); RTlInitUnicodeString (UdosStr, dosStr); IoCreateDevice (DrvObj,0,@UDevStr,FILE_DEVICE_UNKNOWN,0,false,DeviceObject); IoCreateSymbolicLink (UDosStr, UDevStr); DrvObj.CreateDispatch := DrvCreateDispatch; DrvObj.DriverUnload := DrvUnload; Result := STATUS_SUCCESS; end; asm jmp _DriverEntry end. FPC создает COFF файл самостоятельно, без создания промежуточного asm файла с вызовом соответствующей тулзы, (хотя об этом можно попросить), и здесь нужно, обратить внимание на опцию -CX. C ней, помимо основного *XXX.o файла, сгенерируеться дополнительный COFF обьектник в виде "ARCH" библиотеки, (файл вида libXXX.a), наиболее подходящий для скармливания линкеру Поскольку структуры и данные в ней будут разбиты по мелким частям, многие избыточные зависимости и данные (которые может напихать FPC), просто "сойдут на нет", и линкер соберет готовый бинарь, очень чисто, исключительно из самого необходимого. В итоге, для окончательной сборки понадобиться простейшая заглушка (MASM): Код (Text): .386 .model flat extern PASCALMAIN:proc .code _NtProcessStartup proc jmp PASCALMAIN _NtProcessStartup endp FPC_INITIALIZEUNITS proc retn FPC_INITIALIZEUNITS endp end. зы: Free Pascal Compiler поддерживает, COM интерфейсы, что позволяет написать, многофункиональный WDM драйвер. В аттаче также прога по работе с дровиной и зажиганию ламп клавы, собраная также в лучших дзенских традициях Спасибо за внимание!)))
Кстати, приложение пользовательского уровня на "Free Pascal +M$ Link" получаеться тоже не сложным.))) Код (Text): program kb_leds; //some kernel32 prototypes procedure Sleep(dwMilliseconds: DWORD); stdcall; external name '_Sleep@4'; procedure CloseHandle(hObject: THandle); stdcall;external name '_CloseHandle@4'; function CreateFileA(lpFileName: PAnsiChar; dwDesiredAccess, dwShareMode: Cardinal; lpSecurityAttributes: pointer; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: Cardinal): Cardinal; stdcall; external name '_CreateFileA@28'; //the best random functiion :) var RandSeed:integer=0; function Random(eax:integer):integer; asm imul edx,RandSeed,08088405h inc edx mov RandSeed,edx mul edx mov eax,edx end; //lowlewel holy shit procedure outKB (_al:byte); asm out $60,al end; function inpKB:byte; asm in al, $60 end; label loop; begin CloseHandle (CreateFileA('\\.\\giveio', $80000000, 0, nil, 3, $80, 0)); loop: outKB ($ED); outKB (random(5)); Sleep(100); if inpKB > $80 then goto loop; outKB ($ED); outKB (0); end. если еще не окончательно профакал свой брайн, то попробуй сам себе ответить на этот, "чиста-бокланский" вопрос, гденибудь подальше от моей замечательной темы))))
Я лично не против написания дров на Паскале (ИМХО язык замечательный). Тормозит только отсутствие нормального DDK. Когда-то горел желанием развить имеющийся DDDK 0.4, но "перегорел". Вот если б собрать команду энтузиастов и повторить подвиг Four-F...
Да а там писать то неособо, по сути копи-пастишь с C/C++, с минимальными правками))) И будет вам DDK)))
v0id В целом, очень компактный, не больше, чем на асм-е ps В основном юзал FPC в Linux, и остался хорошего впечатления, от этой тулзы (просто не знаю что без него там делал - наверно плакалъ бы). Вобщем так и пришла икея, опробовать его и на системном уровне винды. pps А почему бы и нет?