Создание драйверов. Часть 2. Начинаем наращивать наш драйвер, будем использовать скелет, который мы создали в прошлой статье. В данном примере мне хотелось бы объяснить, как осуществляется «общение» с драйвером. Для этого как Вы знаете, существует API функция:
BOOL DeviceIoControl(
HANDLE hDevice, // хэндл устройства
DWORD dwIoControlCode, // управляющий код
LPVOID lpInBuffer, // передаваемый буфер данных
DWORD nInBufferSize, // размер буфера данных
LPVOID lpOutBuffer, // возвращаемый буфер данных
DWORD nOutBufferSize, // размер буфера данный
LPDWORD lpBytesReturned, // подсчет возвратившихся байтов
LPOVERLAPPED lpOverlapped // указатель на структуру OVERLAPPED
);
Данная функция используется в загрузчике драйвера, ниже представлен код загрузчика, где выделенным показано, что нужно добавить:
#include <windows.h> #include <iostream> #include <conio.h> using namespace std; void ErrorView(); int main() { cout<<" ------------------- "<<endl; cout<<"| Loader is running |"<<endl; cout<<" ------------------- "<<endl; SC_HANDLE sch = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); if(sch) { SC_HANDLE schService = CreateService(sch, "MyFirstDriver","MyFirstDriver",SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL, "C:\\MyFirstDriver\\sys\\objchk\\i386\\MyFirstDriver.sys", NULL,NULL,NULL,NULL,NULL); if(schService) { if(StartService(schService,NULL,NULL)) { HANDLE hHandl = CreateFile("\\\\.\\MyFirstDriver", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,NULL); if(hHandl != INVALID_HANDLE_VALUE) { DWORD dwReturnBytes; if(!DeviceIoControl(hHandl, NULL,/*(*/NULL,NULL,/*)(*/NULL,NULL/*)*/, &dwReturnBytes,NULL)) {cout<<"Error ControlService..."<<endl;ErrorView();} /*****/ unsigned long ioctl = 0x801; if(!DeviceIoControl(hHandl, ioctl,/*(*/NULL,NULL,/*)(*/NULL,NULL/*)*/, &dwReturnBytes,NULL)) {cout<<"Error ControlService..."<<endl;ErrorView();} ioctl = 0x802; if(!DeviceIoControl(hHandl, ioctl,/*(*/NULL,NULL,/*)(*/NULL,NULL/*)*/, &dwReturnBytes,NULL)) {cout<<"Error ControlService..."<<endl;ErrorView();} /*****/ /**/if(CloseHandle(hHandl)) {cout<<"CloseHandle - status ok"<<endl;} else{cout<<"Error CloseHandle..."<<endl;ErrorView();}/**/ SERVICE_STATUS ServiceStatus; /**/if(ControlService(schService,SERVICE_CONTROL_STOP,&ServiceStatus)) {cout<<"ControlService - status ok"<<endl;} else{cout<<"Error ControlService..."<<endl;ErrorView();}/**/ /**/if(DeleteService(schService)) {cout<<"DeleteService - status ok"<<endl;} else{cout<<"Error DeleteService..."<<endl;ErrorView();}/**/ /**/if(CloseServiceHandle(schService)) {cout<<"CloseServiceHandle - status ok"<<endl;} else{cout<<"Error CloseServiceHandle..."<<endl;ErrorView();}/**/ /**/if(CloseServiceHandle(sch)) {cout<<"CloseServiceHandle - status ok"<<endl;} else{cout<<"Error CloseServiceHandle..."<<endl;ErrorView();}/**/ }else{cout<<"Error CreateFile..."<<endl;ErrorView();} }else{cout<<"Error StartService..."<<endl;ErrorView();} }else{cout<<"Error CreateService..."<<endl;ErrorView();} }else{cout<<"Error OpenSCManager..."<<endl;ErrorView();} cout<<" ------------------- "<<endl; cout<<"| Loader is stopped |"<<endl; cout<<" ------------------- "<<endl; cout<<"Press any key to continue"<<endl; while(!getch()); return 0; } void ErrorView() { LPVOID lpMsgBuf;FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER| FORMAT_MESSAGE_FROM_SYSTEM| FORMAT_MESSAGE_IGNORE_INSERTS, NULL,GetLastError(), MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf,0,NULL);CharToOem((LPTSTR)lpMsgBuf, (LPTSTR)lpMsgBuf); cout<<(LPCTSTR)lpMsgBuf<<endl; LocalFree(lpMsgBuf); } [/cpp] В коде драйвера необходимо добавить в функцию обработчика IOCTL запросов следующее: [cpp] #include "ntddk.h" /*--------------------------------------------------------------*/ NTSTATUS MyFirstDriverCreate (IN PDEVICE_OBJECT fdo, IN PIRP irp); NTSTATUS MyFirstDriverClose (IN PDEVICE_OBJECT fdo, IN PIRP irp); NTSTATUS MyFirstDriverControl (IN PDEVICE_OBJECT fdo, IN PIRP irp); VOID MyFirstDriverUnload (IN PDRIVER_OBJECT fdo); /*--------------------------------------------------------------*/ NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath) { NTSTATUS status; PDEVICE_OBJECT fdo; UNICODE_STRING devName; UNICODE_STRING devLink; #if DBG DbgPrint("in DriverEntry"); #endif DriverObject->DriverUnload = MyFirstDriverUnload; DriverObject->MajorFunction[IRP_MJ_CREATE] = MyFirstDriverCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = MyFirstDriverClose; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyFirstDriverControl; RtlInitUnicodeString(&devName,L"\\Device\\MyFirstDriver"); status = IoCreateDevice(DriverObject,sizeof(PDEVICE_OBJECT),&devName,FILE_DEVICE_UNKNOWN,0,FALSE,&fdo); if(!NT_SUCCESS(status))return status; #if DBG DbgPrint("IoCreateDevice status ok"); #endif RtlInitUnicodeString(&devLink,L"\\??\\MyFirstDriver"); status = IoCreateSymbolicLink(&devLink,&devName); if(!NT_SUCCESS(status)) { IoDeleteDevice( fdo ); return status; } #if DBG DbgPrint("DriverEntry STATUS_SUCCESS"); #endif return STATUS_SUCCESS; } /*--------------------------------------------------------------*/ NTSTATUS MyFirstDriverCreate(IN PDEVICE_OBJECT fdo, IN PIRP irp) { #if DBG DbgPrint("Run MyFirstDriverCreate"); #endif irp->IoStatus.Status = STATUS_SUCCESS; irp->IoStatus.Information = 0; IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS MyFirstDriverClose(IN PDEVICE_OBJECT fdo, IN PIRP irp) { #if DBG DbgPrint("Run MyFirstDriverClose"); #endif irp->IoStatus.Status = STATUS_SUCCESS; irp->IoStatus.Information = 0; IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS MyFirstDriverControl (IN PDEVICE_OBJECT fdo, IN PIRP irp) { /**********************************************************************/ PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(irp); ULONG ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; if(ControlCode == 0x801) { #if DBG DbgPrint("IoControlCode 0x801: %d",ControlCode); #endif } if(ControlCode == 0x802) { #if DBG DbgPrint("IoControlCode 0x802: %d",ControlCode); #endif } /**********************************************************************/ irp->IoStatus.Status = STATUS_SUCCESS; irp->IoStatus.Information = 0; IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } VOID MyFirstDriverUnload(IN PDRIVER_OBJECT fdo) { UNICODE_STRING deviceLink; RtlInitUnicodeString(&deviceLink,L"\\??\\MyFirstDriver"); IoDeleteSymbolicLink(&deviceLink); IoDeleteDevice(fdo->DeviceObject); #if DBG DbgPrint("Run MyFirstDriverUnload - delete link"); #endif } /*--------------------------------------------------------------*/
Как Вы видите мы использовали новую для нас функцию IoGetCurrentIrpStackLocation, которая в качестве аргумента принимает указатель на IRP – это пакет запроса, который представляет из себя структуру состоящую из двух частей. Функция возвращает указатель на стек ввода/вывода для данного драйвера. Стек ввода/вывода тоже представляет из себя структуру, описание которой Вы сможете найти в заголовочных файлах «wdm.h» или «ntddk.h». Получив указатель, мы проверяем управляющий код, и соответственно выводим отладочную информацию.