Исходный код драйвера для прямого доступа к портам (LPT, COM и др.) компьютера. Для лучшего понимания устройства и работы драйвера, можете прочитать эту статью.
; Драйвер для прямого доступа к портам компьютера - pbdriverio.sys. Declare DriverEntry(*DriverObject, *RegistryPath) ; Точка входа в программу. !public PureBasicStart !section '.code' code readable executable align 8 !PureBasicStart: *A=@DriverEntry() !jmp [p_A] ; Декларация функций для FASM. !extrn PB_PeekL !extrn PB_PokeL !extrn PB_PeekB !extrn PB_PokeB ;!extrn _DbgPrint !extrn _IoCompleteRequest@8 !extrn _RtlInitUnicodeString@8 !extrn _IoCreateDevice@28 !extrn _IoDeleteDevice@4 !extrn _IoCreateSymbolicLink@8 !extrn _IoDeleteSymbolicLink@4 ; Импорт функций ядра. Import "ntoskrnl.lib" IoCompleteRequest(*IRP, PriorityBoost) RtlInitUnicodeString(*UString, *String) IoCreateDevice(*DriverObject, DeviceExtensionSize, *UDeviceName, DeviceType, DeviceCharacteristics, Exclusive, *DeviceObject) IoDeleteDevice(*DeviceObject) IoCreateSymbolicLink(*SymbolicLinkName, *DeviceName) IoDeleteSymbolicLink(*SymbolicLinkName) EndImport ; ImportC "ntoskrnl.lib" ; DbgPrint(a.s) ; EndImport #IOCTL_READ_PORT_UCHAR = $200 #IOCTL_WRITE_PORT_UCHAR = $400 ; Прямая запись в порт. Procedure.b InPort(Port.u) Protected Result.b=0 EnableASM MOV DX, Port IN al,DX MOV Result, al DisableASM ProcedureReturn Result EndProcedure ; Прямое чтение из порта. Procedure OutPort(Port.u, Byte.a) EnableASM MOV al, Byte MOV DX, Port OUT DX, al DisableASM EndProcedure Procedure DeviceIoControl(*DeviceObject.DEVICE_OBJECT, *pIrp.IRP) Protected ntStatus, *Point, *Stack.IO_STACK_LOCATION *Stack = *pIrp\Tail\Overlay\CurrentStackLocation inBuffersize = *Stack\Parameters\DeviceIoControl\InputBufferLength outBuffersize = *Stack\Parameters\DeviceIoControl\OutputBufferLength CtrlBuff = PeekL(*pIrp\SystemBuffer) address = CtrlBuff & $FFFF Byte.a = (CtrlBuff>>16)&255 Code = *Stack\Parameters\DeviceIoControl\IoControlCode Select Code Case #IOCTL_READ_PORT_UCHAR InByte.b=InPort(address) PokeB(*pIrp\SystemBuffer, InByte) *pIrp\IoStatus\Information = 1 Case #IOCTL_WRITE_PORT_UCHAR OutPort(address, Byte) *pIrp\IoStatus\Information = 0 Default ntStatus = #STATUS_UNSUCCESSFUL *pIrp\IoStatus\Information = 0 EndSelect ntStatus = #STATUS_SUCCESS *pIrp\IoStatus\Status = ntStatus IoCompleteRequest(*pIrp, #IO_NO_INCREMENT) ProcedureReturn ntStatus EndProcedure Procedure CreateDispatch(*DeviceObject.DEVICE_OBJECT, *pIrp.IRP) *pIrp\IoStatus\Information = 0 *pIrp\IoStatus\Status = #STATUS_SUCCESS IoCompleteRequest(*pIrp, #IO_NO_INCREMENT) ProcedureReturn #STATUS_SUCCESS EndProcedure Procedure UnloadDriver(*DriverObject.DRIVER_OBJECT) Protected uniDOSString.UNICODE_STRING RtlInitUnicodeString(@uniDOSString, ?DosDevices) IoDeleteSymbolicLink (@uniDOSString) IoDeleteDevice(*DriverObject\DeviceObject) EndProcedure Procedure DriverEntry(*DriverObject.DRIVER_OBJECT, *RegistryPath.UNICODE_STRING) Protected deviceObject.DEVICE_OBJECT Protected uniNameString.UNICODE_STRING Protected uniDOSString.UNICODE_STRING RtlInitUnicodeString(@uniNameString, ?Device) RtlInitUnicodeString(@uniDOSString, ?DosDevices) status = IoCreateDevice(*DriverObject, 0, @uniNameString, #FILE_DEVICE_UNKNOWN, 0, #False, @deviceObject) If status <> #STATUS_SUCCESS ProcedureReturn status EndIf status = IoCreateSymbolicLink(@uniDOSString, @uniNameString) If status <> #STATUS_SUCCESS IoDeleteDevice(@deviceObject) ; Мы должны сами убирать "хвосты" в режиме ядра! ProcedureReturn status EndIf *DriverObject\DriverUnload = @UnloadDriver() *DriverObject\MajorFunction[#IRP_MJ_CREATE] = @CreateDispatch() *DriverObject\MajorFunction[#IRP_MJ_DEVICE_CONTROL] = @DeviceIoControl() ProcedureReturn #STATUS_SUCCESS EndProcedure ; DataSection Device: !du '\Device\pbdriverio', 0, 0 DosDevices: !du '\DosDevices\pbdriverio', 0, 0 EndDataSection
Это аналог довольно известного драйвера, используемого в библиотеке inpout32.dll.
Компилируем его с помощью PureBasic.
Скачать драйвер, а так же аналог указанной библиотеки, названный PB_IO.dll (в месте с исходными текстами и примерами использования), можно здесь http://pure-basic.narod.ru/forum_files/ … ver_IO.zip
Примечательно что PB_IO.dll при той же функциональности, имеет в три раза меньший размер чем inpout32.dll (12 КБ PB_IO.dll и 32 КБ inpout32.dll). Теперь вы понимаете сколько "мусора" в inpout32.dll?
Скриншот одного из примеров его использования, измеряющий температуру процессора и системной платы (будет работать не на всех компьютерах).
Код примера.
CompilerIf Defined(PBIO_OK, #PB_Constant)=0 Enumeration #PBIO_OK #PBIO_ErrCopyDriver #PBIO_ErrInstallDriver #PBIO_ErrAccess EndEnumeration CompilerEndIf If OpenLibrary(2, "..\PB_IO.dll")=0 MessageRequester("", "Нет PB_IO.dll.", #MB_OK|#MB_ICONERROR) End EndIf Prototype Inp(PortAddress.u) Prototype Out(PortAddress.u, Byte.a) Prototype Status() Prototype.f Version() Global Inp.Inp =GetFunction(2, "Inp") Global Out.Out =GetFunction(2, "Out") Status.Status = GetFunction(2, "Status") Version.Version =GetFunction(2, "Version") #ADR_REG = $295 ;Это адреса регистров системной платы, с помощью которых можно узнать температуру #DATA_REG = $296 Procedure Termo() ; Эта процедура вызывается по таймеру каждую секунду Out(#ADR_REG, $2B) ; Получает текущую температуру процессора x=Inp(#DATA_REG) SetGadgetItemText(0,0,StrU(x, #PB_Byte)+" °C",1) ; отображаем её в таблице Out(#ADR_REG, $29) ; Получает текущую температуру системной платы x=Inp(#DATA_REG) SetGadgetItemText(0,1,StrU(x, #PB_Byte)+" °C",1) ; отображаем её в таблице EndProcedure Err = Status() If Err<>#PBIO_OK MessageRequester("", "Ошибка драйвера "+Str(Err)) EndIf OpenWindow(0,0,0,274,80,"TermoControl",#PB_Window_MinimizeGadget|#PB_Window_Invisible|#PB_Window_ScreenCentered) ListIconGadget(0,2,4,270,70,"Имя",120,#PB_ListIcon_GridLines) ; Таблица SetGadgetFont(0,LoadFont(0,"MS Sans Serif",10) ) ; Шрифт используемый в таблице AddGadgetColumn(0, 1, "Температура", 140) ; Добавление колонки в таблицу AddGadgetItem(0, 0, "Процессор") ; Добавление строк в таблицу AddGadgetItem(0, 1, "Мат. плата") Termo() AddWindowTimer(0,2,1000) ; Таймер. HideWindow(0,0) ; Отображение окна Repeat ; Главный цикл программы Event=WaitWindowEvent() If Event=#PB_Event_Timer Termo() EndIf Until Event=#PB_Event_CloseWindow