内核层
#include <ntddk.h>
#define CTRL_CODE1 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define CTRL_CODE2 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define CTRL_CODE3 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_NEITHER, FILE_ANY_ACCESS)
// 创建一个设备对象
NTSTATUS CreateDevice(PDRIVER_OBJECT DriverObject, PUNICODE_STRING DeviceName, PUNICODE_STRING SymbolName, UINT32 DO)
{
PDEVICE_OBJECT DeviceObject = NULL;
// 1. 创建一个设备对象
NTSTATUS Status = IoCreateDevice(DriverObject, 0, DeviceName,
FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject);
if (NT_SUCCESS(Status))
{
// 2. 添加符号链接名
Status = IoCreateSymbolicLink(SymbolName, DeviceName);
// 3. 设置设备的通讯方式
DeviceObject->Flags |= DO;
}
// 4. 设置返回值
return Status;
}
NTSTATUS DefaultProc(struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
// 1. 设置处理的字节数量
Irp->IoStatus.Information = 0;
// 2. 设置状态
Irp->IoStatus.Status = STATUS_SUCCESS;
// 3. 表示已完成所有IRP处理
IoCompleteRequest(Irp, IO_NO_INCREMENT);
// 4. 设置返回值
return STATUS_SUCCESS;
}
NTSTATUS CreateProc(struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
// 1. 设置处理的字节数量
Irp->IoStatus.Information = 0;
// 2. 设置状态
Irp->IoStatus.Status = STATUS_SUCCESS;
// 3. 表示已完成所有IRP处理
IoCompleteRequest(Irp, IO_NO_INCREMENT);
// 4. 设置返回值
return Irp->IoStatus.Status;
}
NTSTATUS WriteProc(struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
PIO_STACK_LOCATION pstack = IoGetCurrentIrpStackLocation(Irp);
ULONG WriteSize = pstack->Parameters.Write.Length;
char *Buffer = NULL;
// 判断读写方式
if (Irp->AssociatedIrp.SystemBuffer)
Buffer = Irp->AssociatedIrp.SystemBuffer;
else if (Irp->MdlAddress)
Buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
else if (Irp->UserBuffer)
Buffer = Irp->UserBuffer;
// 对该地址区域写入一些数据,让程序读出去
KdPrint(("%S\n", Buffer));
Irp->IoStatus.Information = WriteSize;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS ReadProc(struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
char *Buffer = NULL;
// 判断读写方式
if (Irp->AssociatedIrp.SystemBuffer)
Buffer = Irp->AssociatedIrp.SystemBuffer;
else if (Irp->MdlAddress)
Buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
else if (Irp->UserBuffer)
Buffer = Irp->UserBuffer;
// 对该地址区域写入一些数据,让程序读出去
RtlCopyMemory(Buffer, L"Hello 15PB", 22);
Irp->IoStatus.Information = 1;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DeviceIoCtrlProc(struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(Irp);
ULONG CtrlCode = pStack->Parameters.DeviceIoControl.IoControlCode;
ULONG OutputLength = pStack->Parameters.DeviceIoControl.OutputBufferLength;
ULONG Information = 0;
switch (CtrlCode)
{
case CTRL_CODE1:
{
char *Buffer = Irp->AssociatedIrp.SystemBuffer;
KdPrint(("%S\n", Buffer));
Information = 64;
Buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
RtlCopyMemory(Buffer, L"CTRL_CODE1 - METHOD_IN_DIRECT\n", Information);
break;
}
case CTRL_CODE2:
{
char *Buffer = Irp->AssociatedIrp.SystemBuffer;
KdPrint(("%S\n", Buffer));
Information = 62;
RtlCopyMemory(Buffer, L"CTRL_CODE2 - METHOD_BUFFERED\n", Information);
break;
}
case CTRL_CODE3:
{
char *Buffer = Irp->UserBuffer;
Information = 60;
RtlCopyMemory(Buffer, L"CTRL_CODE3 - METHOD_NEITHER\n", Information);
break;
}
default:
KdPrint(("failed!\n"));
break;
}
// 1. 设置处理的字节数量
Irp->IoStatus.Information = OutputLength;
// 2. 设置状态
Irp->IoStatus.Status = STATUS_SUCCESS;
// 3. 表示已完成所有IRP处理
IoCompleteRequest(Irp, IO_NO_INCREMENT);
// 4. 设置返回值
return STATUS_SUCCESS;
}
// 卸载函数
void DriverUnload(PDRIVER_OBJECT DriverObject)
{
// 获取设备对象链表
PDEVICE_OBJECT DeviceObject = DriverObject->DeviceObject;
for (int i = 0; i < 3; ++i)
{
IoDeleteDevice(DriverObject->DeviceObject);
DeviceObject = DeviceObject->NextDevice;
}
// 卸载设备符号名
UNICODE_STRING SymbolLinkName1 = RTL_CONSTANT_STRING(L"\\DosDevices\\devicelink1");
UNICODE_STRING SymbolLinkName2 = RTL_CONSTANT_STRING(L"\\DosDevices\\devicelink2");
UNICODE_STRING SymbolLinkName3 = RTL_CONSTANT_STRING(L"\\DosDevices\\devicelink3");
IoDeleteSymbolicLink(&SymbolLinkName1);
IoDeleteSymbolicLink(&SymbolLinkName2);
IoDeleteSymbolicLink(&SymbolLinkName3);
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING UnicodeString)
{
DbgBreakPoint();
UNREFERENCED_PARAMETER(UnicodeString);
// 创建不同读写方式的设备
UNICODE_STRING DeviceName1 = RTL_CONSTANT_STRING(L"\\Device\\device1");
UNICODE_STRING SymbolName1 = RTL_CONSTANT_STRING(L"\\DosDevices\\devicelink1");
if (NT_SUCCESS(CreateDevice(DriverObject, &DeviceName1, &SymbolName1, DO_BUFFERED_IO)))
KdPrint(("Create device success: \\Device\\device1\n"));
UNICODE_STRING DeviceName2 = RTL_CONSTANT_STRING(L"\\Device\\device2");
UNICODE_STRING SymbolName2 = RTL_CONSTANT_STRING(L"\\DosDevices\\devicelink2");
if (NT_SUCCESS(CreateDevice(DriverObject, &DeviceName2, &SymbolName2, DO_DIRECT_IO)))
KdPrint(("Create device success: \\Device\\device2\n"));
UNICODE_STRING DeviceName3 = RTL_CONSTANT_STRING(L"\\Device\\device3");
UNICODE_STRING SymbolName3 = RTL_CONSTANT_STRING(L"\\DosDevices\\devicelink3");
if (NT_SUCCESS(CreateDevice(DriverObject, &DeviceName3, &SymbolName3, 0)))
KdPrint(("Create device success: \\Device\\device3\n"));
// 设置卸载函数
DriverObject->DriverUnload = DriverUnload;
// 初始化IRP派遣函数
for (UINT32 i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
DriverObject->MajorFunction[i] = DefaultProc;
DriverObject->MajorFunction[IRP_MJ_CREATE] = CreateProc;
DriverObject->MajorFunction[IRP_MJ_READ] = ReadProc;
DriverObject->MajorFunction[IRP_MJ_WRITE] = WriteProc;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceIoCtrlProc;
return STATUS_SUCCESS;
}
应用层
#include <cstdio>
#include <windows.h>
#define CTRL_CODE1 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define CTRL_CODE2 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define CTRL_CODE3 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_NEITHER, FILE_ANY_ACCESS)
int main()
{
// 创建内核对象的设备对象连接
HANDLE DeviceHandle1 = CreateFile(L"\\\\.\\devicelink1", FILE_ALL_ACCESS,
FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE DeviceHandle2 = CreateFile(L"\\\\.\\devicelink2", FILE_ALL_ACCESS,
FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE DeviceHandle3 = CreateFile(L"\\\\.\\devicelink3", FILE_ALL_ACCESS,
FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
WCHAR ReadBuffer[100] = { 0 };
DWORD ReadByte = 0;
// 发送消息
printf("device1 - DO_BUFFERED_IO:\n");
WriteFile(DeviceHandle1, L"device1 - DO_BUFFERED_IO", 52, &ReadByte, NULL);
printf("device1 - Write: %d\n", ReadByte);
ReadFile(DeviceHandle1, ReadBuffer, 100, &ReadByte, NULL);
wprintf(L"device1 - Read: %d(%s)\n", ReadByte, ReadBuffer);
printf("device2 - DO_DIRECT_IO:\n");
WriteFile(DeviceHandle2, L"device1 - DO_DIRECT_IO", 48, &ReadByte, NULL);
printf("device2 - Write: %d\n", ReadByte);
ReadFile(DeviceHandle2, ReadBuffer, 100, &ReadByte, NULL);
wprintf(L"device2 - Read: %d(%s)\n", ReadByte, ReadBuffer);
/*printf("device3 - NULL:\n");
WriteFile(DeviceHandle3, L"device1 - NULL", 32, &ReadByte, NULL);
printf("device3 - Write: %d\n", ReadByte);
ReadFile(DeviceHandle3, ReadBuffer, 100, &ReadByte, NULL);
printf("device3 - Read: %d(%Ls)\n", ReadByte, ReadBuffer);*/
DeviceIoControl(DeviceHandle1, CTRL_CODE1, (LPVOID)L"CTRL_CODE1", 24, ReadBuffer, 100, &ReadByte, NULL);
wprintf(L"device1 - CTRL_CODE1: %d - %s\n", ReadByte, ReadBuffer);
DeviceIoControl(DeviceHandle1, CTRL_CODE2, (LPVOID)L"CTRL_CODE2", 24, ReadBuffer, 100, &ReadByte, NULL);
wprintf(L"device1 - CTRL_CODE2: %d - %s\n", ReadByte, ReadBuffer);
DeviceIoControl(DeviceHandle1, CTRL_CODE3, (LPVOID)L"CTRL_CODE3", 24, ReadBuffer, 100, &ReadByte, NULL);
wprintf(L"device1 - CTRL_CODE3: %d - %s\n", ReadByte, ReadBuffer);
system("pause");
return 0;
}