windows驱动开发13.驱动与应用程序通信
1. windows应用程序进程间怎么互相通信?
方法一:共享内存
方法二:共享内存
方法三:网络通信
方法一:管道通信的完整代码
管道通信需要一个服务端与一个客户端。在服务端创建管道,在客户端读取管道。
1.server.c
1 | // server.c : This file contains the 'main' function. Program execution begins and ends there. |
2.client.c
1 | // client.cpp : This file contains the 'main' function. Program execution begins and ends there. |
2. 驱动程序与应用程序怎么通信?
应用层程序中需要创建文件后打开文件来发送消息。
驱动程序中需要添加创建文件->打开文件->接受控制码->关闭文件,这四种基本功能。
| 应用层调用方式 | 驱动层处理方式 | 描述 |
|---|---|---|
DeviceIoControl |
IRP_MJ_DEVICE_CONTROL |
最灵活、最常用于应用层与驱动通信 |
ReadFile / WriteFile |
IRP_MJ_READ / IRP_MJ_WRITE |
用于数据读写 |
CreateFile |
IRP_MJ_CREATE |
打开设备 |
CloseHandle |
IRP_MJ_CLOSE |
关闭设备句柄 |
1.在驱动程序中处理创建设备消息与关闭设备消息。
应用层程序代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main() {
//创建设备
HANDLE hDevice = CreateFile(
L"\\\\.\\MyMinimalDevice",
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
printf("无法打开设备: 错误码 = %d\n", GetLastError());
return 1;
}
printf("设备打开成功。\n");
//关闭设备
CloseHandle(hDevice);
return 0;
}驱动程序代码
1 |
|
2.添加read与write功能
用户层程序使用ReadFile 和 WriteFile通信
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
BOOL WriteToDevice(HANDLE hDevice, const char* data, DWORD length) {
DWORD bytesWritten;
return WriteFile(hDevice, data, length, &bytesWritten, NULL);
}
BOOL ReadFromDevice(HANDLE hDevice, char* buffer, DWORD bufferSize, DWORD* bytesRead) {
return ReadFile(hDevice, buffer, bufferSize, bytesRead, NULL);
}
int main() {
HANDLE hDevice = CreateFileA(
DEVICE_NAME,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL
);
if (hDevice == INVALID_HANDLE_VALUE) {
printf("打开设备失败: %d\n", GetLastError());
return 1;
}
const char* message = "Hello from user!";
if (!WriteToDevice(hDevice, message, (DWORD)strlen(message))) {
printf("写入失败: %d\n", GetLastError());
CloseHandle(hDevice);
return 1;
}
char buffer[BUFFER_SIZE] = {0};
DWORD bytesRead = 0;
if (!ReadFromDevice(hDevice, buffer, BUFFER_SIZE, &bytesRead)) {
printf("读取失败: %d\n", GetLastError());
CloseHandle(hDevice);
return 1;
}
printf("读取成功 (%lu 字节): %.*s\n", bytesRead, bytesRead, buffer);
CloseHandle(hDevice);
return 0;
}驱动程序添加read与write消息处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
PDEVICE_OBJECT g_DeviceObject = NULL;
// 缓冲区及长度(简单实现:全局模拟内存)
CHAR g_Buffer[BUFFER_SIZE] = { 0 };
ULONG g_BufferLength = 0;
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
VOID UnloadDriver(PDRIVER_OBJECT DriverObject);
NTSTATUS DispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS DispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS DispatchRead(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS DispatchWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS CreateDeviceAndSymbolicLink(PDRIVER_OBJECT DriverObject);
VOID DeleteDeviceAndSymbolicLink();
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(RegistryPath);
NTSTATUS status = CreateDeviceAndSymbolicLink(DriverObject);
if (!NT_SUCCESS(status)) return status;
DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
DriverObject->DriverUnload = UnloadDriver;
Log("Minimal Driver loaded.\n");
return STATUS_SUCCESS;
}
VOID UnloadDriver(PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
DeleteDeviceAndSymbolicLink();
Log("Minimal Driver unloaded.\n");
}
NTSTATUS DispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
Log("IRP_MJ_CREATE received\n");
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
Log("IRP_MJ_CLOSE received\n");
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
ULONG length = stack->Parameters.Read.Length;
ULONG bytesToCopy = min(length, g_BufferLength);
if (bytesToCopy > 0)
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, g_Buffer, bytesToCopy);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = bytesToCopy;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
Log("IRP_MJ_READ done\n");
return STATUS_SUCCESS;
}
NTSTATUS DispatchWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
ULONG length = stack->Parameters.Write.Length;
ULONG bytesToCopy = min(length, BUFFER_SIZE);
RtlCopyMemory(g_Buffer, Irp->AssociatedIrp.SystemBuffer, bytesToCopy);
g_BufferLength = bytesToCopy;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = bytesToCopy;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
Log("IRP_MJ_WRITE done\n");
return STATUS_SUCCESS;
}
NTSTATUS CreateDeviceAndSymbolicLink(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING deviceName = RTL_CONSTANT_STRING(DEVICE_NAME);
UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(SYMBOLIC_NAME);
NTSTATUS status = IoCreateDevice(
DriverObject,
0,
&deviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&g_DeviceObject
);
if (!NT_SUCCESS(status))
return status;
// —— 关键:开启 Buffered I/O
g_DeviceObject->Flags |= DO_BUFFERED_IO;
status = IoCreateSymbolicLink(&symLinkName, &deviceName);
if (!NT_SUCCESS(status)) {
IoDeleteDevice(g_DeviceObject);
return status;
}
return STATUS_SUCCESS;
}
VOID DeleteDeviceAndSymbolicLink()
{
UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(SYMBOLIC_NAME);
IoDeleteSymbolicLink(&symLinkName);
if (g_DeviceObject) IoDeleteDevice(g_DeviceObject);
}
3. 在驱动程序中添加控制码功能,根据控制码来处理创建设置与关闭设备的消息
1.驱动层代码
1 |
|
应用层代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
static HANDLE DeviceHandle = NULL;
int main()
{
DeviceHandle = CreateFileW(
DEVICE_PATH, // 这里改为 "\\\\.\\MyDriver"
GENERIC_READ | GENERIC_WRITE, // 读写权限
0, // 通常设备不需要共享,设为 0 即可
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (DeviceHandle == INVALID_HANDLE_VALUE)
{
wchar_t msg[256];
wsprintfW(msg, L"打开设备失败!\nHandle=%p, Error=%d",
DeviceHandle, GetLastError());
MessageBoxW(NULL, msg, L"Error", MB_OK);
return 1;
}
// 这里只做了打开/关闭,驱动会打印 CreateFile/CloseHandle 的日志
CloseHandle(DeviceHandle);
return 0;
}
4.使用控制码从应用层发送消息给驱动层
- 用户层程序调用控制码发送消息
1 |
|
2.驱动程序新增控制码支持
1 |
|
5.添加驱动程序向应用层发送消息的功能
用户层程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
BOOL WriteMessageToDriver(HANDLE hDevice, const char* msg)
{
DWORD returned;
return DeviceIoControl(
hDevice,
IOCTL_SEND_MESSAGE,
(LPVOID)msg,
(DWORD)strlen(msg),
NULL,
0,
&returned,
NULL);
}
BOOL ReadMessageFromDriver(HANDLE hDevice, char* outBuffer, DWORD bufSize)
{
DWORD returned;
return DeviceIoControl(
hDevice,
IOCTL_GET_MESSAGE,
NULL,
0,
outBuffer,
bufSize,
&returned,
NULL);
}
int main()
{
HANDLE hDevice = CreateFile(
DEVICE_NAME,
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
printf("无法打开设备: 错误码 = %lu\n", GetLastError());
return 1;
}
// 写入消息
const char* msg = "Hello Kernel!";
if (WriteMessageToDriver(hDevice, msg))
printf("已发送消息: %s\n", msg);
else
printf("发送失败!错误码 = %lu\n", GetLastError());
// 读取返回消息
char buffer[MAX_BUFFER] = { 0 };
if (ReadMessageFromDriver(hDevice, buffer, sizeof(buffer)))
printf("从驱动读取到: %s\n", buffer);
else
printf("读取失败!错误码 = %lu\n", GetLastError());
CloseHandle(hDevice);
return 0;
}驱动程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// 控制码定义
char g_LastMessage[MAX_BUFFER_SIZE] = "Default Kernel Message";
PDEVICE_OBJECT g_DeviceObject = NULL;
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
VOID UnloadDriver(PDRIVER_OBJECT DriverObject);
NTSTATUS DispatchAll(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS CreateDeviceAndSymbolicLink(PDRIVER_OBJECT DriverObject);
VOID DeleteDeviceAndSymbolicLink();
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(RegistryPath);
NTSTATUS status = CreateDeviceAndSymbolicLink(DriverObject);
if (!NT_SUCCESS(status)) return status;
for (int i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; ++i)
DriverObject->MajorFunction[i] = DispatchAll;
DriverObject->DriverUnload = UnloadDriver;
Log("Driver loaded\n");
return STATUS_SUCCESS;
}
VOID UnloadDriver(PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
DeleteDeviceAndSymbolicLink();
Log("Driver unloaded\n");
}
NTSTATUS DispatchAll(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
ULONG majorFunc = stack->MajorFunction;
NTSTATUS status = STATUS_SUCCESS;
switch (majorFunc)
{
case IRP_MJ_CREATE:
Log("Device opened\n");
break;
case IRP_MJ_CLOSE:
Log("Device closed\n");
break;
case IRP_MJ_DEVICE_CONTROL:
{
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
char* buffer = (char*)Irp->AssociatedIrp.SystemBuffer;
ULONG inLen = stack->Parameters.DeviceIoControl.InputBufferLength;
ULONG outLen = stack->Parameters.DeviceIoControl.OutputBufferLength;
switch (code)
{
case IOCTL_SEND_MESSAGE:
if (buffer && inLen > 0)
{
RtlZeroMemory(g_LastMessage, MAX_BUFFER_SIZE);
RtlCopyMemory(g_LastMessage, buffer, min(inLen, MAX_BUFFER_SIZE - 1));
Log("Received from user: %s;\n", g_LastMessage);
}
else
{
Log("Empty user message\n");
}
Irp->IoStatus.Information = 0;
break;
case IOCTL_GET_MESSAGE:
if (buffer && outLen > 0)
{
size_t msgLen = strnlen(g_LastMessage, MAX_BUFFER_SIZE);
size_t copyLen = min(msgLen + 1, outLen);
RtlCopyMemory(buffer, g_LastMessage, copyLen);
Irp->IoStatus.Information = (ULONG)copyLen;
Log("Message returned to user\n");
}
else
{
Irp->IoStatus.Information = 0;
Log("Invalid output buffer\n");
}
break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
Log("Unknown IOCTL\n");
break;
}
break;
}
default:
Log("Unhandled IRP\n");
break;
}
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS CreateDeviceAndSymbolicLink(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING deviceName = RTL_CONSTANT_STRING(DEVICE_NAME);
UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(SYMBOLIC_NAME);
NTSTATUS status = IoCreateDevice(
DriverObject,
0,
&deviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&g_DeviceObject
);
if (!NT_SUCCESS(status)) return status;
status = IoCreateSymbolicLink(&symLinkName, &deviceName);
if (!NT_SUCCESS(status)) {
IoDeleteDevice(g_DeviceObject);
g_DeviceObject = NULL;
}
return status;
}
VOID DeleteDeviceAndSymbolicLink()
{
UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(SYMBOLIC_NAME);
IoDeleteSymbolicLink(&symLinkName);
if (g_DeviceObject) {
IoDeleteDevice(g_DeviceObject);
g_DeviceObject = NULL;
}
}
6.驱动层与应用层程序通信的完整框架
用户层程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
HANDLE OpenDevice()
{
HANDLE hDevice = CreateFile(
DEVICE_NAME,
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
printf("无法打开设备,错误码 = %lu\n", GetLastError());
else
printf("设备已打开。\n");
return hDevice;
}
// --- IOCTL 通信 ---
BOOL SendMessageToDriver(HANDLE hDevice, const char* message)
{
DWORD returned;
BOOL result = DeviceIoControl(
hDevice,
IOCTL_SEND_MESSAGE,
(LPVOID)message,
(DWORD)strlen(message),
NULL,
0,
&returned,
NULL);
if (!result)
printf("发送失败(IOCTL),错误码 = %lu\n", GetLastError());
return result;
}
BOOL ReceiveMessageFromDriver(HANDLE hDevice, char* buffer, DWORD bufferSize)
{
DWORD returned;
BOOL result = DeviceIoControl(
hDevice,
IOCTL_GET_MESSAGE,
NULL,
0,
buffer,
bufferSize,
&returned,
NULL);
if (!result)
printf("读取失败(IOCTL),错误码 = %lu\n", GetLastError());
return result;
}
// --- ReadFile/WriteFile 测试 ---
BOOL WriteToDriver(HANDLE hDevice, const char* message)
{
DWORD written = 0;
BOOL result = WriteFile(
hDevice,
message,
(DWORD)strlen(message),
&written,
NULL);
if (!result)
printf("WriteFile 失败,错误码 = %lu\n", GetLastError());
else
printf("WriteFile 写入了 %lu 字节。\n", written);
return result;
}
BOOL ReadFromDriver(HANDLE hDevice, char* buffer, DWORD bufferSize)
{
DWORD bytesRead = 0;
BOOL result = ReadFile(
hDevice,
buffer,
bufferSize,
&bytesRead,
NULL);
if (!result)
printf("ReadFile 失败,错误码 = %lu\n", GetLastError());
else
printf("ReadFile 读取了 %lu 字节。\n", bytesRead);
return result;
}
// --- 主函数 ---
int main()
{
HANDLE hDevice = OpenDevice();
if (hDevice == INVALID_HANDLE_VALUE) return 1;
const char* msg = "Hello Kernel via IOCTL!";
if (SendMessageToDriver(hDevice, msg))
printf("已发送 (IOCTL): %s\n", msg);
char buffer[MAX_BUFFER] = { 0 };
if (ReceiveMessageFromDriver(hDevice, buffer, sizeof(buffer)))
printf("接收到 (IOCTL): %s\n", buffer);
// --- 使用 WriteFile 写入 ---
const char* msg2 = "Hello Kernel via WriteFile!";
if (WriteToDriver(hDevice, msg2))
printf("已写入 (WriteFile): %s\n", msg2);
// --- 使用 ReadFile 读取 ---
ZeroMemory(buffer, sizeof(buffer));
if (ReadFromDriver(hDevice, buffer, sizeof(buffer)))
printf("接收到 (ReadFile): %s\n", buffer);
CloseHandle(hDevice);
return 0;
}驱动程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
// 内核全局缓冲
static char g_LastMessage[MAX_BUFFER_SIZE] = "Default Kernel Message";
static PDEVICE_OBJECT g_DeviceObject = NULL;
// 前向声明
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
VOID UnloadDriver(PDRIVER_OBJECT DriverObject);
NTSTATUS DispatchCommon(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS CreateDeviceAndSymbolicLink(PDRIVER_OBJECT DriverObject);
VOID DeleteDeviceAndSymbolicLink();
// 驱动入口
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(RegistryPath);
Log("Driver loaded\n");
NTSTATUS status = CreateDeviceAndSymbolicLink(DriverObject);
if (!NT_SUCCESS(status)) {
Log("CreateDevice failed: 0x%X\n", status);
return status;
}
// 分发
DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCommon;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchCommon;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchCommon;
DriverObject->MajorFunction[IRP_MJ_READ] = DispatchCommon;
DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchCommon;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
DriverObject->DriverUnload = UnloadDriver;
return STATUS_SUCCESS;
}
// 卸载例程
VOID UnloadDriver(PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
DeleteDeviceAndSymbolicLink();
Log("Driver unloaded\n");
}
// 创建设备 + 符号链接
NTSTATUS CreateDeviceAndSymbolicLink(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING devName = RTL_CONSTANT_STRING(DEVICE_NAME);
UNICODE_STRING symName = RTL_CONSTANT_STRING(SYMBOLIC_NAME);
NTSTATUS status = IoCreateDevice(
DriverObject,
0,
&devName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&g_DeviceObject
);
if (!NT_SUCCESS(status)) return status;
// —— 关键:启用 Buffered I/O,否则 SystemBuffer 在 Read/Write/IOCTL 下可能为 NULL
g_DeviceObject->Flags |= DO_BUFFERED_IO;
status = IoCreateSymbolicLink(&symName, &devName);
if (!NT_SUCCESS(status)) {
IoDeleteDevice(g_DeviceObject);
g_DeviceObject = NULL;
}
return status;
}
// 删除设备 + 符号链接
VOID DeleteDeviceAndSymbolicLink()
{
UNICODE_STRING symName = RTL_CONSTANT_STRING(SYMBOLIC_NAME);
IoDeleteSymbolicLink(&symName);
if (g_DeviceObject) {
IoDeleteDevice(g_DeviceObject);
g_DeviceObject = NULL;
}
}
// Create/Close/Cleanup/Read/Write 都走这里
NTSTATUS DispatchCommon(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status = STATUS_SUCCESS;
ULONG info = 0;
switch (stack->MajorFunction)
{
case IRP_MJ_CREATE:
Log("Device opened\n");
break;
case IRP_MJ_CLOSE:
Log("Device closed\n");
break;
case IRP_MJ_CLEANUP:
Log("Device cleanup\n");
break;
case IRP_MJ_READ:
{
// 只用 METHOD_BUFFERED,SystemBuffer 一定有效
char* userBuf = (char*)Irp->AssociatedIrp.SystemBuffer;
ULONG outLen = stack->Parameters.Read.Length;
if (userBuf && outLen > 0) {
size_t msgLen = strnlen(g_LastMessage, MAX_BUFFER_SIZE);
size_t copyLen = min((size_t)outLen, msgLen + 1);
RtlCopyMemory(userBuf, g_LastMessage, copyLen);
info = (ULONG)copyLen;
Log("Handled IRP_MJ_READ, %u bytes\n", info);
}
else {
status = STATUS_INVALID_PARAMETER;
}
break;
}
case IRP_MJ_WRITE:
{
char* buffer = (char*)Irp->AssociatedIrp.SystemBuffer;
ULONG writeLen = stack->Parameters.Write.Length;
if (buffer && writeLen > 0)
{
RtlZeroMemory(g_LastMessage, MAX_BUFFER_SIZE);
RtlCopyMemory(g_LastMessage, buffer,
min((size_t)writeLen, MAX_BUFFER_SIZE - 1));
Log("Write from user: %s;\n", g_LastMessage);
info = writeLen; // <-- 把写入长度告诉 I/O 管理器
}
else
{
status = STATUS_INVALID_PARAMETER;
}
Log("Handled IRP_MJ_WRITE, %u bytes\n", info);
break;
}
default:
status = STATUS_INVALID_DEVICE_REQUEST;
Log("Unknown IRP in DispatchCommon: 0x%X\n", stack->MajorFunction);
break;
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = info;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
// 只有 IOCTL 走这里
NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
ULONG inLen = stack->Parameters.DeviceIoControl.InputBufferLength;
ULONG outLen = stack->Parameters.DeviceIoControl.OutputBufferLength;
char* buffer = (char*)Irp->AssociatedIrp.SystemBuffer;
NTSTATUS status = STATUS_SUCCESS;
ULONG info = 0;
switch (code)
{
case IOCTL_SEND_MESSAGE:
if (buffer && inLen > 0) {
RtlZeroMemory(g_LastMessage, MAX_BUFFER_SIZE);
RtlCopyMemory(g_LastMessage, buffer, min((size_t)inLen, MAX_BUFFER_SIZE - 1));
Log("Received from user (IOCTL): %s\n", g_LastMessage);
}
else {
status = STATUS_INVALID_PARAMETER;
Log("Empty IOCTL_SEND_MESSAGE\n");
}
break;
case IOCTL_GET_MESSAGE:
if (buffer && outLen > 0) {
size_t msgLen = strnlen(g_LastMessage, MAX_BUFFER_SIZE);
size_t copyLen = min((size_t)outLen, msgLen + 1);
RtlCopyMemory(buffer, g_LastMessage, copyLen);
info = (ULONG)copyLen;
Log("Returned to user (IOCTL): %s\n", g_LastMessage);
}
else {
status = STATUS_INVALID_PARAMETER;
Log("Invalid IOCTL_GET_MESSAGE buffer\n");
}
break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
Log("Unknown IOCTL: 0x%X\n", code);
break;
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = info;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
7. 应用向驱动发送结构体. 应用向驱动发送结构体
用户层应用程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63// user_app.c
typedef struct _MY_MESSAGE {
int Id;
char Text[128];
} MY_MESSAGE, * PMY_MESSAGE;
HANDLE OpenDevice()
{
HANDLE hDevice = CreateFile(
DEVICE_NAME, GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
printf("无法打开设备,错误码 = %lu\n", GetLastError());
else
printf("设备已打开。\n");
return hDevice;
}
BOOL SendStructToDriver(HANDLE hDevice, MY_MESSAGE* msg)
{
DWORD returned;
return DeviceIoControl(hDevice, IOCTL_SEND_STRUCT, msg, sizeof(MY_MESSAGE),
NULL, 0, &returned, NULL);
}
BOOL ReceiveStructFromDriver(HANDLE hDevice, MY_MESSAGE* msg)
{
DWORD returned;
return DeviceIoControl(hDevice, IOCTL_GET_STRUCT, NULL, 0,
msg, sizeof(MY_MESSAGE), &returned, NULL);
}
int main()
{
HANDLE hDevice = OpenDevice();
if (hDevice == INVALID_HANDLE_VALUE) return 1;
MY_MESSAGE msg = { .Id = 1 };
strcpy_s(msg.Text, sizeof(msg.Text), "Hello from user!");
if (SendStructToDriver(hDevice, &msg))
printf("已发送结构体: Id=%d, Text=%s\n", msg.Id, msg.Text);
else
printf("发送结构体失败。\n");
MY_MESSAGE reply = { 0 };
if (ReceiveStructFromDriver(hDevice, &reply))
printf("从驱动接收到: Id=%d, Text=%s\n", reply.Id, reply.Text);
else
printf("接收结构体失败。\n");
CloseHandle(hDevice);
return 0;
}驱动程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// mydriver.c
typedef struct _MY_MESSAGE {
int Id;
char Text[128];
} MY_MESSAGE, * PMY_MESSAGE;
MY_MESSAGE g_StoredMessage = { 0 };
NTSTATUS DispatchCreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
VOID UnloadDriver(PDRIVER_OBJECT DriverObject);
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(RegistryPath);
Log("Driver loaded\n");
UNICODE_STRING devName = RTL_CONSTANT_STRING(L"\\Device\\MyMinimalDevice");
UNICODE_STRING symLink = RTL_CONSTANT_STRING(L"\\DosDevices\\MyMinimalDevice");
PDEVICE_OBJECT devObj;
NTSTATUS status = IoCreateDevice(DriverObject, 0, &devName,
FILE_DEVICE_UNKNOWN, 0, FALSE, &devObj);
if (!NT_SUCCESS(status)) return status;
IoCreateSymbolicLink(&symLink, &devName);
DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
DriverObject->DriverUnload = UnloadDriver;
return STATUS_SUCCESS;
}
VOID UnloadDriver(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING symLink = RTL_CONSTANT_STRING(L"\\DosDevices\\MyMinimalDevice");
IoDeleteSymbolicLink(&symLink);
IoDeleteDevice(DriverObject->DeviceObject);
Log("Driver unloaded\n");
}
NTSTATUS DispatchCreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
Log("Open/Close\n");
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
NTSTATUS status = STATUS_SUCCESS;
ULONG_PTR info = 0;
switch (code)
{
case IOCTL_SEND_STRUCT:
{
PMY_MESSAGE pMsg = (PMY_MESSAGE)Irp->AssociatedIrp.SystemBuffer;
if (pMsg) {
RtlCopyMemory(&g_StoredMessage, pMsg, sizeof(MY_MESSAGE));
Log("qi:Received struct: Id=%d, Text=%s;\n", pMsg->Id, pMsg->Text);
}
break;
}
case IOCTL_GET_STRUCT:
{
PMY_MESSAGE pOut = (PMY_MESSAGE)Irp->AssociatedIrp.SystemBuffer;
if (pOut) {
g_StoredMessage.Id += 1000;
strcpy_s(g_StoredMessage.Text, sizeof(g_StoredMessage.Text), "Reply from kernel");
RtlCopyMemory(pOut, &g_StoredMessage, sizeof(MY_MESSAGE));
info = sizeof(MY_MESSAGE);
Log("Returned struct to user\n");
}
break;
}
default:
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = info;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
8.分配动态内存传递结构体数据实现双向通信
用户层程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
typedef struct _MY_MESSAGE {
int Id;
char Text[128];
} MY_MESSAGE, * PMY_MESSAGE;
HANDLE OpenDevice()
{
HANDLE hDevice = CreateFileW(
DEVICE_NAME, GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
printf("无法打开设备,错误码 = %lu\n", GetLastError());
else
printf("设备已打开。\n");
return hDevice;
}
BOOL SendStructToDriver(HANDLE hDevice, PMY_MESSAGE msg)
{
DWORD returned;
return DeviceIoControl(hDevice, IOCTL_SEND_STRUCT, msg, sizeof(MY_MESSAGE),
NULL, 0, &returned, NULL);
}
BOOL ReceiveStructFromDriver(HANDLE hDevice, PMY_MESSAGE msg)
{
DWORD returned;
return DeviceIoControl(hDevice, IOCTL_GET_STRUCT, NULL, 0,
msg, sizeof(MY_MESSAGE), &returned, NULL);
}
int main()
{
HANDLE hDevice = OpenDevice();
if (hDevice == INVALID_HANDLE_VALUE) return 1;
PMY_MESSAGE msg = (PMY_MESSAGE)malloc(sizeof(MY_MESSAGE));
if (!msg) return 1;
msg->Id = 1;
strcpy_s(msg->Text, sizeof(msg->Text), "Hello from user!");
if (SendStructToDriver(hDevice, msg))
printf("已发送结构体: Id=%d, Text=%s\n", msg->Id, msg->Text);
else
printf("发送结构体失败。\n");
if (ReceiveStructFromDriver(hDevice, msg))
printf("从驱动接收到: Id=%d, Text=%s\n", msg->Id, msg->Text);
else
printf("接收结构体失败。\n");
free(msg);
CloseHandle(hDevice);
return 0;
}驱动程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// mydriver.c
typedef struct _MY_MESSAGE {
int Id;
char Text[128];
} MY_MESSAGE, * PMY_MESSAGE;
PMY_MESSAGE g_StoredMessage = NULL;
NTSTATUS DispatchCreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
VOID UnloadDriver(PDRIVER_OBJECT DriverObject);
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(RegistryPath);
Log("Driver loaded\n");
UNICODE_STRING devName = RTL_CONSTANT_STRING(L"\\Device\\MyMinimalDevice");
UNICODE_STRING symLink = RTL_CONSTANT_STRING(L"\\DosDevices\\MyMinimalDevice");
PDEVICE_OBJECT devObj;
NTSTATUS status = IoCreateDevice(DriverObject, 0, &devName,
FILE_DEVICE_UNKNOWN, 0, FALSE, &devObj);
if (!NT_SUCCESS(status)) return status;
IoCreateSymbolicLink(&symLink, &devName);
DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
DriverObject->DriverUnload = UnloadDriver;
return STATUS_SUCCESS;
}
VOID UnloadDriver(PDRIVER_OBJECT DriverObject)
{
if (g_StoredMessage) {
ExFreePoolWithTag(g_StoredMessage, POOL_TAG);
g_StoredMessage = NULL;
}
UNICODE_STRING symLink = RTL_CONSTANT_STRING(L"\\DosDevices\\MyMinimalDevice");
IoDeleteSymbolicLink(&symLink);
IoDeleteDevice(DriverObject->DeviceObject);
Log("Driver unloaded\n");
}
NTSTATUS DispatchCreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
Log("Open/Close\n");
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
NTSTATUS status = STATUS_SUCCESS;
ULONG_PTR info = 0;
switch (code)
{
case IOCTL_SEND_STRUCT:
{
PMY_MESSAGE pMsg = (PMY_MESSAGE)Irp->AssociatedIrp.SystemBuffer;
if (pMsg) {
if (g_StoredMessage)
ExFreePoolWithTag(g_StoredMessage, POOL_TAG);
g_StoredMessage = (PMY_MESSAGE)ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(MY_MESSAGE), POOL_TAG);
if (g_StoredMessage) {
RtlCopyMemory(g_StoredMessage, pMsg, sizeof(MY_MESSAGE));
Log("Received struct: Id=%d, Text=%s\n", pMsg->Id, pMsg->Text);
Log("Receivedd struct: Id=%d, Text=%s\n", g_StoredMessage->Id, g_StoredMessage->Text);
}
else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
}
break;
}
case IOCTL_GET_STRUCT:
{
PMY_MESSAGE pOut = (PMY_MESSAGE)Irp->AssociatedIrp.SystemBuffer;
if (pOut && g_StoredMessage) {
g_StoredMessage->Id += 1000;
RtlStringCchCopyA(g_StoredMessage->Text, sizeof(g_StoredMessage->Text), "Reply from kernel");
RtlCopyMemory(pOut, g_StoredMessage, sizeof(MY_MESSAGE));
info = sizeof(MY_MESSAGE);
Log("Returned struct to user\n");
}
else {
status = STATUS_NOT_FOUND;
}
break;
}
default:
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = info;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
9. 完整的应用与驱动通信读取物理内存
R0
1 |
|
R3
1 |
|
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
