Ring0:
#define DEVICE_OBJECT_NAME L"\\Device\\MaDeviceObjectName" //驱动之间通信
#define DEVICE_LINK_NAME L"\\DosDevices\\MaDeviceLinkName" //Ring0 和Ring3 之间通信
#define IOCTL_NEITHER_NORMAL(i) \
CTL_CODE \
( \
FILE_DEVICE_UNKNOWN, \
0x800 + i /*+ 0x100*/, \
METHOD_NEITHER, \
FILE_ANY_ACCESS \
)
创建设备对象
RtlInitUnicodeString(&DeviceObjectName, DEVICE_OBJECT_NAME);
//创建一个与Rin3进行通信的设备对象 CDO
Status = IoCreateDevice(
DriverObject, //驱动对象
0,
&DeviceObjectName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&DeviceObject); //设备对象
创建符号链接名:
RtlInitUnicodeString(&DeviceLinkName, DEVICE_LINK_NAME);
if (!NT_SUCCESS(Status = IoCreateSymbolicLink(
&DeviceLinkName,
&DeviceObjectName
)))
设置派遣例程:
//设置派遣例程
DriverObject->MajorFunction[IRP_MJ_CREATE] = CreateThroughDispatch;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = CloseThroughDispatch;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ControlThroughDispatch;
Ring3:
打开设备对象,获取句柄
//通过Ring0的设备对象的设备链接名进行打开获取设备对象句柄
DeviceHandle = CreateFile(_T("\\\\.\\MaDeviceLinkName"), GENERIC_READ
| GENERIC_WRITE, FILE_SHARE_READ |FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
向设备发送请求IO
DeviceIoControl(m_DeviceHandle, IocControlCode, /*IO控制码 */
InputBuffer, InputBufferLength, OutBuffer, OutBufferLength, &v1, NULL)
BOOL WINAPI DeviceIoControl(_In_ HANDLE hDevice, //设备句柄
_In_ DWORD dwIoControlCode, //控制码
_In_opt_ LPVOID lpInBuffer,
_In_ DWORD nInBufferSize,
_Out_opt_ LPVOID lpOutBuffer,
_In_ DWORD nOutBufferSize,
_Out_opt_ LPDWORD lpBytesReturned,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
IoControlCode:
其中最重要的就是dwIoControlCode,它是由宏 CTL_CODE 组成的。
#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)
DeviceType(设备类型,高16位(16-31位))
Access(访问限制,14-15位)
Function(功能2-13位)0~0x7ff为微软保留,0x800~0xfff由程序员自己定义
Method(I/O访问内存使用方式)有四种:
#define METHOD_BUFFERED 0
#define METHOD_IN_DIRECT 1
#define METHOD_OUT_DIRECT 2
#define METHOD_NEITHER 3
METHOD_BUFFERED:缓冲方式
系统将用户的所有输入输出都经过pIrp->AssociatedIrp.SystemBuffer来缓冲
METHOD_IN_DIRECT 和 METHOD_OUT_DIRECT :直接方式
系统会将输入缓冲在pIrp->AssociatedIrp.SystemBuffer中,并将输出缓冲区锁定,然后在内核模式下重新映射一段地址。
系统对Ring3的输入缓冲区进行缓冲,但是对Ring3的输出缓冲区并没有缓冲,而是在内核中进行了锁定。
METHOD_IN_DIRECT 和 METHOD_OUT_DIRECT方式的区别,仅在于打开设备的权限上,当以只读权限打开设备时,METHOD_IN_DIRECT方式的IoControl将会成功,而METHOD_OUT_DIRECT方式将会失败。如果以读写权限打开设备,两种方式都会成功。
METHOD_NEITHER :
驱动程序可以通过pIrpStack->Parameters.DeviceIoControl.Type3InputBuffer得到Ring3的输入缓冲区地址(其中pIrpStack是IoGetCurrentIrpStackLocation(pIrp)的返回);通过pIrp-> UserBuffer得到Ring3的输出缓冲区地址