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
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
|
/*
Windows 内核下串口过滤设备的简单演示 驱动程序代码
编译方法参见makefile. TAB = 8
*/
#include <ntddk.h>
#include <wdm.h>
#include <ntstrsafe.h>
#include <process.h>
#define CCP_MAX_COM_ID 32
#define DEVICE_NAME L"\\Device\\DevComCap"
#define SYS_LINK_NAME L"\\??\\SysLinkComCap"
typedef struct tagDeviceExt {
ULONG bFlags; //TRUE表示过滤设备, FALSE就是我们自己的设备了
PIRP pCurrentIrp;
PDEVICE_OBJECT pDeviceObj;
PDEVICE_OBJECT pLowDeviceObj;
UNICODE_STRING USzDeviceName;
UNICODE_STRING USzSysLinkName;
} DEVICE_EXT, *PDEVICE_EXT;
//===========================================================================
//驱动卸载例程
//===========================================================================
VOID DriverUnLoad( PDRIVER_OBJECT pDriverObj ) {
PDEVICE_EXT pDeviceExt = NULL;
PDEVICE_OBJECT pNextDeviceObj = NULL;
pNextDeviceObj = pDriverObj->DeviceObject;
//---------------------------------------------------------------------------
//遍历所有的设备进行取消绑定, 删除
//---------------------------------------------------------------------------
while ( pNextDeviceObj != NULL ) {
pDeviceExt = pNextDeviceObj->DeviceExtension;
//如果当前还有Irp处理, 那么取消
if ( pDeviceExt->pCurrentIrp ) {
IoCancelIrp( pDeviceExt->pCurrentIrp );
}
//如果有符号链接, 删除
if ( ( pDeviceExt->USzSysLinkName ).Buffer ) {
IoDeleteSymbolicLink( &( pDeviceExt->USzSysLinkName ) );
}
//取消绑定
if ( pDeviceExt->pLowDeviceObj ) {
IoDetachDevice( pDeviceExt->pLowDeviceObj );
}
//删除设备
IoDeleteDevice( pDeviceExt->pDeviceObj );
pNextDeviceObj = pNextDeviceObj->NextDevice;
if ( ( pDeviceExt->USzDeviceName ).Buffer ) {
KdPrint ( ( "删除%wZ设备成功!\n", &( pDeviceExt->USzDeviceName ) ) );
} else {
KdPrint ( ( "删除过滤设备成功!\n" ) );
}
}
}
//===========================================================================
//写入Irp处理例程
//===========================================================================
NTSTATUS DispatchWrite( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
ULONG ulBufLen, j;
ULONG ulUserBufLen;
PUCHAR pBuf = NULL;
PUCHAR pUserBuf = NULL;
PDEVICE_EXT pDeviceExt = NULL;
PDEVICE_OBJECT pNextDevice = NULL;
PIO_STACK_LOCATION pStack = NULL;
PIO_STACK_LOCATION pUserStack = NULL;
//---------------------------------------------------------------------------
pStack = IoGetCurrentIrpStackLocation( pIrp );
//获取写长度
ulBufLen = pStack->Parameters.Write.Length;
//获取缓冲区
if( pIrp->MdlAddress != NULL ) {
pBuf = ( PUCHAR )MmGetSystemAddressForMdlSafe( pIrp->MdlAddress , NormalPagePriority );
} else {
pBuf = ( PUCHAR )pIrp->UserBuffer;
}
if( pBuf == NULL ) {
pBuf = ( PUCHAR )pIrp->AssociatedIrp.SystemBuffer;
}
KdPrint ( ( "写入Irp处理例程!\n" ) );
//打印数据
for( j = 0; j < ulBufLen; j++ ) {
KdPrint( ( "数据: 0x%X %c\n", pBuf[j], pBuf[j] ) );
}
//---------------------------------------------------------------------------
//如果与我们通信的3环Irp被挂起了, 那么这里就可以返回了
//---------------------------------------------------------------------------
pNextDevice = ( pDeviceObj->DriverObject )->DeviceObject;
while ( pNextDevice != NULL ) {
pDeviceExt = pNextDevice->DeviceExtension;
ASSERT( pDeviceExt );
if ( pDeviceExt->pCurrentIrp ) {
//获取R3那边读取请求的Irp
pUserStack = IoGetCurrentIrpStackLocation( pDeviceExt->pCurrentIrp );
//缓冲区长度
ulUserBufLen = pUserStack->Parameters.Write.Length;
//映射R3那边的地址到高2G这边来
pUserBuf = MmGetSystemAddressForMdlSafe( pDeviceExt->pCurrentIrp->MdlAddress,
NormalPagePriority );
//如果缓冲区传递错误了
if ( !pUserBuf ) {
pDeviceExt->pCurrentIrp->IoStatus.Status = STATUS_INVALID_PARAMETER;
pDeviceExt->pCurrentIrp->IoStatus.Information = 0;
} else {
//如果用户态那边的缓冲区太少, 返回错误
if ( ulUserBufLen < ulBufLen ) {
pDeviceExt->pCurrentIrp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
pDeviceExt->pCurrentIrp->IoStatus.Information = 0;
} else {
//条件都够了那么就Copy内存过去
RtlCopyMemory( pUserBuf, pBuf, ulBufLen );
pDeviceExt->pCurrentIrp->IoStatus.Status = STATUS_SUCCESS;
pDeviceExt->pCurrentIrp->IoStatus.Information = ulBufLen;
}
}
IoCompleteRequest( pDeviceExt->pCurrentIrp, IO_NO_INCREMENT );
pDeviceExt->pCurrentIrp = NULL;
pDeviceExt = NULL;
break;
}
//遍历下一个设备
pNextDevice = pNextDevice->NextDevice;
}
//---------------------------------------------------------------------------
// 这些请求直接下发执行即可, 需要其他处理, 这里搞
IoSkipCurrentIrpStackLocation( pIrp );
pDeviceExt = pDeviceObj->DeviceExtension;
ASSERT( pDeviceExt->pLowDeviceObj );
return IoCallDriver( pDeviceExt->pLowDeviceObj, pIrp );
}
//===========================================================================
//R3那边发送的读取Irp取消例程
//===========================================================================
VOID OnCancelIRP( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
PDEVICE_EXT pDeviceExt = NULL;
//释放Cancel自旋锁
IoReleaseCancelSpinLock( pIrp->CancelIrql );
pDeviceExt = pDeviceObj->DeviceExtension;
ASSERT( pDeviceExt );
if ( pDeviceExt->pCurrentIrp == pIrp ) {
pDeviceExt->pCurrentIrp = NULL;
}
//设置完成状态为STATUS_CANCELLED
pIrp->IoStatus.Status = STATUS_CANCELLED;
pIrp->IoStatus.Information = 0;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
}
//===========================================================================
//R3那边过来读取请求. 将其挂起
//===========================================================================
NTSTATUS DispatchRead( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
NTSTATUS Status;
PDEVICE_EXT pDeviceExt = NULL;
PAGED_CODE();
pDeviceExt = pDeviceObj->DeviceExtension;
ASSERT( pDeviceExt );
//---------------------------------------------------------------------------
//这边请求也有我们自己创建的设备发送的和, 过滤发送的这里注意区别
//---------------------------------------------------------------------------
if ( !pDeviceExt->bFlags ) {
pDeviceExt->pCurrentIrp = pIrp;
//将IRP设置为挂起
IoMarkIrpPending( pIrp );
//设置取消例程
IoSetCancelRoutine( pIrp, OnCancelIRP );
KdPrint ( ( "R3读取请求来了一次!\n" ) );
//返回pending状态
Status = STATUS_PENDING;
} else {
KdPrint ( ( "过滤了一次读取请求!\n" ) );
IoSkipCurrentIrpStackLocation( pIrp );
Status = IoCallDriver( pDeviceExt->pLowDeviceObj, pIrp );
}
return Status;
}
//===========================================================================
//所有不关心的Irp处理
//===========================================================================
NTSTATUS DispatchRoutine( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
NTSTATUS Status;
PDEVICE_EXT pDeviceExt = NULL;
PIO_STACK_LOCATION pStack = NULL;
pStack = IoGetCurrentIrpStackLocation( pIrp );
pDeviceExt = pDeviceObj->DeviceExtension;
//前面我们创建的设备是不会有这个消息的
if( pStack->MajorFunction == IRP_MJ_POWER ) {
//直接跳过当前堆栈, 发送给下层设备
PoStartNextPowerIrp( pIrp );
IoSkipCurrentIrpStackLocation( pIrp );
KdPrint ( ( "电源Irp来了一次!\n" ) );
Status = PoCallDriver( pDeviceExt->pLowDeviceObj, pIrp );
} else {
KdPrint ( ( "不关心的Irp来了一次!\n" ) );
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
if ( pDeviceExt->bFlags ) {
// 这些请求直接下发执行即可
IoSkipCurrentIrpStackLocation( pIrp );
Status = IoCallDriver( pDeviceExt->pLowDeviceObj, pIrp );
} else {
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
Status = STATUS_SUCCESS;
}
}
return Status;
}
//===========================================================================
// 绑定串口设备
//===========================================================================
NTSTATUS _AttachDevice( PDEVICE_OBJECT pDeviceObj, PDEVICE_OBJECT pTargetDevObj ) {
NTSTATUS Status;
PDEVICE_EXT pDeviceExt = NULL;
PDEVICE_OBJECT pLowDeviceObj = NULL;
//获取设备扩展
pDeviceExt = pDeviceObj->DeviceExtension;
ASSERT( pDeviceExt );
Status = IoAttachDeviceToDeviceStackSafe( pDeviceObj, pTargetDevObj,
&( pDeviceExt->pLowDeviceObj ) );
if ( !NT_SUCCESS( Status ) ) {
KdPrint ( ( "绑定设备失败!\n" ) );
return Status;
}
//设置过滤设备属性(很重要)
pDeviceObj->DeviceType = pTargetDevObj->DeviceType;
pDeviceObj->Characteristics = pTargetDevObj->Characteristics;
pDeviceObj->Flags &= ~DO_DEVICE_INITIALIZING;
pDeviceObj->Flags |= DO_POWER_PAGABLE;
pDeviceObj->Flags |= pTargetDevObj->Flags & ( DO_DIRECT_IO | DO_BUFFERED_IO );
return STATUS_SUCCESS;
}
//===========================================================================
//创建设备用于和R3通信
//pDriverObj 驱动对象指针
//pDeviceObjName 设备对象名称
//pSysLinkName 设备对象的符号链接名称(可以为NULL)
//bFlags 是否是绑定设备的标记
//pDeviceObj 二级指针, 用于返回设备对象
//===========================================================================
NTSTATUS _CreateDevice( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pDeviceObjName,
PUNICODE_STRING pSysLinkName, ULONG bFlags, PDEVICE_OBJECT* pDeviceObj ) {
NTSTATUS Status;
PDEVICE_EXT pDeviceExt = NULL;
Status = IoCreateDevice( pDriverObj, sizeof( DEVICE_EXT ), pDeviceObjName,
FILE_DEVICE_UNKNOWN, 0, TRUE, pDeviceObj );
if ( !NT_SUCCESS( Status ) ) {
KdPrint ( ( "创建%wZ设备失败!\n", pDeviceObjName ) );
return Status;
}
if ( pSysLinkName ) {
Status = IoCreateSymbolicLink( pSysLinkName, pDeviceObjName );
if ( !NT_SUCCESS( Status ) ) {
KdPrint ( ( "创建%wZ符号链接失败!\n", pSysLinkName ) );
IoDeleteDevice( *pDeviceObj );
return Status;
}
}
pDeviceExt = ( *pDeviceObj )->DeviceExtension;
ASSERT( pDeviceExt );
//设置设备属性, 因为这个设备不是过滤设备, 所以bFlags为False
RtlZeroMemory( pDeviceExt, sizeof( DEVICE_EXT ) );
pDeviceExt->pDeviceObj = *pDeviceObj;
pDeviceExt->bFlags = bFlags;
if ( pDeviceObjName ) {
pDeviceExt->USzDeviceName = *pDeviceObjName;
}
if ( pSysLinkName ) {
pDeviceExt->USzSysLinkName = *pSysLinkName;
}
return Status;
}
//===========================================================================
//绑定所有的串口设备
//pDriverObj 驱动对象
//===========================================================================
VOID _AttachAllComs( PDRIVER_OBJECT pDriverObj ) {
ULONG i;
NTSTATUS Status;
WCHAR wSzName[32];
UNICODE_STRING USzName;
PDEVICE_OBJECT pDeviceObj = NULL;
PFILE_OBJECT pTargetFileObj = NULL;
PDEVICE_OBJECT pTargetDevObj = NULL;
for( i = 0; i < CCP_MAX_COM_ID; i++, pTargetDevObj = NULL, pDeviceObj = NULL ) {
RtlZeroMemory( &wSzName, sizeof( wSzName ) );
RtlStringCchPrintfW( wSzName, sizeof( wSzName ), L"\\Device\\Serial%d", i );
RtlInitUnicodeString( &USzName, wSzName );
//通过设备名称获取到对象的指针
Status = IoGetDeviceObjectPointer( &USzName, FILE_ALL_ACCESS,
&pTargetFileObj, &pTargetDevObj );
if ( Status == STATUS_SUCCESS ) {
//绑定成功这里要马上释放文件对象句柄
ObDereferenceObject( pTargetFileObj );
}
if( pTargetDevObj == NULL ) {
KdPrint( ( "设备无效绑定失败: %wZ\n", &USzName ) );
continue;
}
Status = _CreateDevice( pDriverObj, NULL, NULL, TRUE, &pDeviceObj );
if ( !NT_SUCCESS( Status ) ) {
KdPrint ( ( "创建过滤设备失败!\n" ) );
continue;
}
ASSERT( pDeviceObj != NULL );
//绑定底层串口设备
Status = _AttachDevice( pDeviceObj, pTargetDevObj );
if ( !NT_SUCCESS( Status ) ) {
if ( pDeviceObj ) {
IoDeleteDevice( pDeviceObj );
}
continue;
}
KdPrint( ( "绑定了设备:%wZ!\n", &USzName ) );
}
}
//===========================================================================
//驱动入口
//===========================================================================
#pragma code_seg( "INIT", "DriverEntry" )
NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pUSzRegPath ) {
ULONG i;
NTSTATUS Status;
PDEVICE_OBJECT pDeviceObj = NULL;
UNICODE_STRING USzDeviceName = RTL_CONSTANT_STRING( DEVICE_NAME );
UNICODE_STRING USzSysLinkName = RTL_CONSTANT_STRING( SYS_LINK_NAME );
//---------------------------------------------------------------------------
Status = _CreateDevice( pDriverObj, &USzDeviceName, &USzSysLinkName,
FALSE, &pDeviceObj );
if ( !NT_SUCCESS( Status ) ) {
KdPrint ( ( "创建通信设备失败!\n" ) );
return Status;
}
KdPrint ( ( "%wZ设备创建成功!\n", &USzDeviceName ) );
//设备缓冲区操作方式
pDeviceObj->Flags |= DO_DIRECT_IO;
//绑定所有的串口设备
_AttachAllComs( pDriverObj );
//---------------------------------------------------------------------------
//设置分发函数例程
for( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++ ) {
pDriverObj->MajorFunction[i] = &DispatchRoutine;
}
pDriverObj->MajorFunction[IRP_MJ_READ] = &DispatchRead;
pDriverObj->MajorFunction[IRP_MJ_WRITE] = &DispatchWrite;
pDriverObj->DriverUnload = &DriverUnLoad;
//---------------------------------------------------------------------------
KdPrint ( ( "驱动入口执行完毕!\n" ) );
return Status;
}
|