Skip to content

Instantly share code, notes, and snippets.

@HoShiMin
Last active September 3, 2016 18:28
Show Gist options
  • Save HoShiMin/cb0936c6521414275128 to your computer and use it in GitHub Desktop.
Save HoShiMin/cb0936c6521414275128 to your computer and use it in GitHub Desktop.
API для работы с драйверами
unit DriversAPI;
{
Автор: HoShiMin, 2016
Основные понятия:
IRP - I/O Request Packet, передаваемые драйверу данные
Имя драйвера - имя службы драйвера
Имя устройства - указано в ДРАЙВЕРЕ, ему посылать IOCTL!
IOCTL - пользовательский контрольный код:
0x000 : 0x7FF - зарезервировано Microsoft
0x800 : 0xFFF - определяется пользователем
RawIOCTL - пользовательский код (IOCTL), переведённый в системный вид
с помощью функции GenerateIOCTL (см. ниже):
Параметры GenerateIOCTL:
DeviceType - определяет устройство:
0х0000 : 0х7FFF - зарезервировано Microsoft
0х8000 : 0хFFFF - определяется пользователем
IOCTL - контрольный код:
0x000 : 0x7FF - зарезервировано Microsoft
0x800 : 0xFFF - определяется пользователем
AccessMethod - тип доступа к буферу:
METHOD_BUFFERED:
Драйвер:
Входной буфер в pIrp->AssociatedIrp.SystemBuffer
Выходной буфер - выходные данные копировать во входной буфер,
размер выходных данных определяется размером
наибольшего буфера
Клиент:
Передавать и получать данные во входном буфере
METHOD_IN_DIRECT или METHOD_OUT_DIRECT:
Драйвер:
Входной буфер в pIrp->AssociatedIrp.SystemBuffer
Выходной буфер в pIrp->MdlAddress
Клиент:
Зависит от драйвера, в общем случае отправлять данные во входном буфере,
получать - в выходном, в частном случае выходной буфер получать во входном
METHOD_NEITHER:
Драйвер:
Входной буфер в Parameters.DeviceIoControl.Type3InputBuffer (IO_STACK_LOCATION)
Выходной буфер в pIrp->UserBuffer
Клиент:
Отправка данных во входном буфере
Получение данных в выходном буфере
### ВНИМАНИЕ! Неверный тип доступа к буферу может вызвать BSOD!
Подробнее о типах доступа к буферу:
http://msdn.microsoft.com/en-us/library/windows/hardware/ff540663(v=vs.85).aspx
http://blagin.ru/sozdanie-drajverov-chast-4-obmen-dannymi/
http://drp.su/ru/driver_dev/08_06.htm
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*** Отключение проверки подписи драйверов на 64х-битных ОС:
В консоли набрать:
* Отключение проверки цифровой подписи (разрешить устанавливать неподписанные драйвера):
bcdedit.exe /set loadoptions DISABLE_INTEGRITY_CHECKS
bcdedit.exe /set TESTSIGNING ON
* Включение проверки цифровой подписи (запретить устанавливать неподписанные драйвера):
bcdedit.exe /set loadoptions ENABLE_INTEGRITY_CHECKS
bcdedit.exe /set TESTSIGNING OFF
* Включение поддержки ядерной отладки (kernel-debugging) для WinDbg и Kernel Debugger из WDK:
bcdedit.exe /debug on - включить
bcdedit.exe /debug off - выключить
После выполнения необходимо перезагрузить Windows
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
interface
uses
Windows, WinSvc, SysUtils;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const
METHOD_BUFFERED = 0;
METHOD_IN_DIRECT = 1;
METHOD_OUT_DIRECT = 2;
METHOD_NEITHER = 3;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Определение разрядности Windows:
function Is64BitWindows: BOOL;
// Текст последней ошибки:
function LastError: string;
// Приводит IOCTL к системному виду:
function GenerateIOCTL(DeviceType, FunctionNumber, AccessMethod, Access: LongWord): LongWord; inline;
// Получить дескриптор устройства, которому будем посылать IOCTL (DeviceName указан в ДРАЙВЕРЕ! Это НЕ имя службы драйвера):
function GetDeviceHandle(const DeviceName: string): THandle; inline;
// Отправка IOCTL драйверу (устройству):
function SendIOCTL(hDevice: THandle; IOCTL: LongWord; InputBuffer: Pointer; InputBufferSize: LongWord; OutputBuffer: Pointer; OutputBufferSize: LongWord; BytesReturned: PLongWord = nil; Method: LongWord = METHOD_NEITHER): Boolean; inline; overload;
function SendIOCTL(const DeviceName: string; IOCTL: LongWord; InputBuffer: Pointer; InputBufferSize: LongWord; OutputBuffer: Pointer; OutputBufferSize: LongWord; BytesReturned: PLongWord = nil; Method: LongWord = METHOD_NEITHER): Boolean; inline; overload;
function SendRawIOCTL(hDevice: THandle; RawIOCTL: LongWord; InputBuffer: Pointer; InputBufferSize: LongWord; OutputBuffer: Pointer; OutputBufferSize: LongWord; BytesReturned: PLongWord = nil): Boolean; inline; overload;
function SendRawIOCTL(const DeviceName: string; RawIOCTL: LongWord; InputBuffer: Pointer; InputBufferSize: LongWord; OutputBuffer: Pointer; OutputBufferSize: LongWord; BytesReturned: PLongWord = nil): Boolean; inline; overload;
// "Ручные" установка, запуск, остановка и удаление драйвера:
function CreateDriverService(const DriverPath, DriverName: string): THandle;
function OpenDriverService (const DriverName: string): THandle;
function StartDriverService (hService: THandle): Boolean;
function StopDriverService (hService: THandle): Boolean;
function DeleteDriverService(hService: THandle): Boolean;
function CloseService (hService: THandle): LongBool;
// "Автоматические" установка, запуск, остановка и удаление драйвера:
function InstallDriver(const DriverPath, DriverName: string): Boolean;
function DeleteDriver(const DriverName: string): Boolean;
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
implementation
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
function Is64BitWindows: BOOL;
{$IFNDEF CPUX64}
var
IsWow64Process: function(hProcess: THandle; Wow64Process: PBOOL): BOOL; stdcall;
Wow64Process: BOOL;
{$ENDIF}
begin
{$IFDEF CPUX64}
Result := True;
{$ELSE}
IsWow64Process := GetProcAddress(GetModuleHandle(kernel32), 'IsWow64Process');
Wow64Process := False;
if Assigned(IsWow64Process) then Wow64Process := IsWow64Process(GetCurrentProcess, @Wow64Process) and Wow64Process;
Result := Wow64Process;
{$ENDIF}
end;
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
function LastError: string;
var
Buffer: PChar;
ErrorCode: LongWord;
const
BufferSize = 1024;
begin
ErrorCode := GetLastError;
GetMem(Buffer, BufferSize);
FillChar(Buffer^, BufferSize, #0);
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM,
nil,
ErrorCode,
LANG_NEUTRAL,
Buffer,
BufferSize,
nil
);
Result := '(0x' + IntToHex(ErrorCode, 8) + ') ' + Copy(Buffer, 1, Length(Buffer) - 2);
FreeMem(Buffer);
end;
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
function GenerateIOCTL(DeviceType, FunctionNumber, AccessMethod, Access: LongWord): LongWord; inline;
begin
Result := (DeviceType shl 16) or (Access shl 14) or (FunctionNumber shl 2) or AccessMethod;
end;
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
function GetDeviceHandle(const DeviceName: string): THandle; inline;
begin
Result := CreateFile(
PChar('\\.\' + DeviceName),
GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL or FILE_ATTRIBUTE_SYSTEM,
0
);
end;
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
function SendIOCTL(hDevice: THandle; IOCTL: LongWord; InputBuffer: Pointer; InputBufferSize: LongWord; OutputBuffer: Pointer; OutputBufferSize: LongWord; BytesReturned: PLongWord = nil; Method: LongWord = METHOD_NEITHER): Boolean; inline; overload;
var
RawIOCTL: LongWord;
RawBytesReturned: LongWord;
begin
RawIOCTL := GenerateIOCTL($8000, IOCTL, Method, FILE_ANY_ACCESS);
Result := DeviceIoControl(hDevice, RawIOCTL, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize, RawBytesReturned, nil);
if BytesReturned <> nil then BytesReturned^ := RawBytesReturned;
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function SendIOCTL(const DeviceName: string; IOCTL: LongWord; InputBuffer: Pointer; InputBufferSize: LongWord; OutputBuffer: Pointer; OutputBufferSize: LongWord; BytesReturned: PLongWord = nil; Method: LongWord = METHOD_NEITHER): Boolean; inline; overload;
var
hDevice: THandle;
RawIOCTL: LongWord;
RawBytesReturned: LongWord;
begin
Result := False;
hDevice := GetDeviceHandle(DeviceName);
if hDevice = INVALID_HANDLE_VALUE then Exit;
RawIOCTL := GenerateIOCTL($8000, IOCTL, Method, FILE_ANY_ACCESS);
Result := DeviceIoControl(hDevice, RawIOCTL, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize, RawBytesReturned, nil);
if BytesReturned <> nil then BytesReturned^ := RawBytesReturned;
CloseHandle(hDevice);
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function SendRawIOCTL(hDevice: THandle; RawIOCTL: LongWord; InputBuffer: Pointer; InputBufferSize: LongWord; OutputBuffer: Pointer; OutputBufferSize: LongWord; BytesReturned: PLongWord = nil): Boolean; inline; overload;
var
RawBytesReturned: LongWord;
begin
Result := DeviceIoControl(hDevice, RawIOCTL, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize, RawBytesReturned, nil);
if BytesReturned <> nil then BytesReturned^ := RawBytesReturned;
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function SendRawIOCTL(const DeviceName: string; RawIOCTL: LongWord; InputBuffer: Pointer; InputBufferSize: LongWord; OutputBuffer: Pointer; OutputBufferSize: LongWord; BytesReturned: PLongWord = nil): Boolean; inline; overload;
var
hDevice: THandle;
RawBytesReturned: LongWord;
begin
Result := False;
hDevice := GetDeviceHandle(DeviceName);
if hDevice = INVALID_HANDLE_VALUE then Exit;
Result := DeviceIoControl(hDevice, RawIOCTL, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize, RawBytesReturned, nil);
if BytesReturned <> nil then BytesReturned^ := RawBytesReturned;
CloseHandle(hDevice);
end;
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
function CreateDriverService(const DriverPath, DriverName: string): THandle;
var
hSCManager: THandle;
begin
Result := 0;
// Открываем менеджер сервисов:
hSCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
if hSCManager = 0 then Exit;
// Создаём сервис:
Result := CreateService(
hSCManager,
PChar(DriverName),
PChar(DriverName),
SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER,
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
PChar(DriverPath),
nil,
nil,
nil,
nil,
nil
);
CloseServiceHandle(hSCManager);
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function OpenDriverService(const DriverName: string): THandle;
var
hSCManager: THandle;
begin
Result := 0;
hSCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
if hSCManager = 0 then Exit;
Result := OpenService(hSCManager, PChar(DriverName), SERVICE_ALL_ACCESS);
CloseServiceHandle(hSCManager);
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function StartDriverService(hService: THandle): Boolean;
type
PPWideChar = ^PWideChar;
begin
Result := StartService(hService, 0, PPWideChar(nil)^);
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function StopDriverService(hService: THandle): Boolean;
var
ServiceStatus: _SERVICE_STATUS;
begin
Result := ControlService(hService, SERVICE_CONTROL_STOP, ServiceStatus);
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function DeleteDriverService(hService: THandle): Boolean;
begin
Result := DeleteService(hService);
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function CloseService(hService: THandle): LongBool;
begin
Result := CloseServiceHandle(hService);
end;
//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
function InstallDriver(const DriverPath, DriverName: string): Boolean;
var
hService: THandle;
begin
Result := False;
hService := CreateDriverService(DriverPath, DriverName);
if hService = 0 then Exit;
Result := StartDriverService(hService);
CloseServiceHandle(hService);
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function DeleteDriver(const DriverName: string): Boolean;
var
hService: THandle;
begin
Result := False;
hService := OpenDriverService(DriverName);
if hService = 0 then Exit;
Result := StopDriverService(hService) and DeleteDriverService(hService);
CloseServiceHandle(hService);
end;
end.
@NanoNik
Copy link

NanoNik commented Sep 3, 2016

memes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment