Создание драйверов. Часть 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». Получив указатель, мы проверяем управляющий код, и соответственно выводим отладочную информацию.
