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
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
|
/*
Windows 内核下键盘过滤设备的简单演示 驱动层代码
编译方法参见makefile. TAB = 8
*/
#include <ntddk.h>
#include "KeyBoard.h"
#define DEVICE_NAME L"\\\\Device\\\\DevKeyBoardCap"
#define SYS_LINK_NAME L"\\\\??\\\\SysLinkKeyBoardCap"
#define KBD_DRIVER_NAME L"\\\\Driver\\\\Kbdclass" // Kbdclass驱动的名字
//---------------------------------------------------------------------------
typedef struct tagDeviceExt {
ULONG bFlags; //TRUE表示过滤设备, FALSE就是我们自己的设备了
PIRP pCurrentIrp;
PIRP pRoxyIrp; //代理Irp
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 ) {
pDeviceExt = pNextDeviceObj->DeviceExtension;
ASSERT( pDeviceExt );
//如果有未决的Irp
if ( pDeviceExt->pCurrentIrp ) {
IoCancelIrp( pDeviceExt->pCurrentIrp );
}
//如果还有自己的代理irp
if ( pDeviceExt->pRoxyIrp ) {
IoCancelIrp( pDeviceExt->pRoxyIrp );
}
//取消绑定
if ( pDeviceExt->pLowDeviceObj ) {
IoDetachDevice( pDeviceExt->pLowDeviceObj );
}
//删除符号链接
if ( pDeviceExt->USzSysLinkName.Buffer ) {
IoDeleteSymbolicLink( &pDeviceExt->USzSysLinkName );
}
//删除设备
IoDeleteDevice( pDeviceExt->pDeviceObj );
if ( pDeviceExt->USzDeviceName.Buffer ) {
KdPrint ( ( "删除%wZ设备成功!\n", &pDeviceExt->USzDeviceName ) );
} else {
KdPrint ( ( "删除无名设备成功1\n" ) );
}
pNextDeviceObj = pNextDeviceObj->NextDevice;
}
}
//===========================================================================
//创建设备用于和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;
PAGED_CODE();
//---------------------------------------------------------------------------
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;
}
//===========================================================================
//绑定Kbdclass下的所有设备对象
//pDriverObj :驱动对象
//返回值 :状态
//===========================================================================
NTSTATUS _AttachAllKeyBoards( PDRIVER_OBJECT pDriverObj ) {
NTSTATUS Status;
PDRIVER_OBJECT pKbdDriverObj = NULL;
PDEVICE_OBJECT pTagetDeviceObj = NULL;
PDEVICE_OBJECT pFilterDeviceObj = NULL;
PDEVICE_OBJECT pLowerDeviceObj = NULL;
PDEVICE_EXT pDeviceExt = NULL;
POBJECT_HEADER ObjHeader = NULL;
POBJECT_HEADER_NAME_INFO ObjName = NULL;
UNICODE_STRING USzKbdClass = RTL_CONSTANT_STRING( KBD_DRIVER_NAME );
PAGED_CODE();
//---------------------------------------------------------------------------
Status = ObReferenceObjectByName( &USzKbdClass, OBJ_CASE_INSENSITIVE,
NULL, 0, IoDriverObjectType, KernelMode,
NULL, &pKbdDriverObj );
if ( !NT_SUCCESS( Status ) ) {
return Status;
} else {
// 这个打开需要解应用。早点解除了免得之后忘记。
ObDereferenceObject( pKbdDriverObj );
}
//---------------------------------------------------------------------------
//遍历Kbdclass下所有的设备对象, 进行绑定
pTagetDeviceObj = pKbdDriverObj->DeviceObject;
while ( pTagetDeviceObj ) {
//创建和R3通信的设备Flags = FALSE
Status = _CreateDevice( pDriverObj, NULL, NULL, TRUE, &pFilterDeviceObj );
if ( !NT_SUCCESS( Status ) ) {
KdPrint ( ( "创建过滤设备失败!\n" ) );
return Status;
}
Status = IoAttachDeviceToDeviceStackSafe( pFilterDeviceObj, pTagetDeviceObj,
&pLowerDeviceObj );
if ( !NT_SUCCESS( Status ) ) {
KdPrint ( ( "绑定设备失败!\n" ) );
IoDeleteDevice( pFilterDeviceObj );
pFilterDeviceObj = NULL;
return Status;
}
//设置设备扩展属性
pDeviceExt = pFilterDeviceObj->DeviceExtension;
pDeviceExt->pLowDeviceObj = pLowerDeviceObj;
pDeviceExt->pDeviceObj = pFilterDeviceObj;
//设置过滤设备的属性(重要, 不要设置错了)
pFilterDeviceObj->DeviceType = pLowerDeviceObj->DeviceType;
pFilterDeviceObj->Characteristics = pLowerDeviceObj->Characteristics;
pFilterDeviceObj->StackSize = pLowerDeviceObj->StackSize + 1;
pFilterDeviceObj->Flags |= pLowerDeviceObj->Flags
& ( DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE );
//---------------------------------------------------------------------------
//得到对象头
ObjHeader = OBJECT_TO_OBJECT_HEADER( pLowerDeviceObj );
ASSERT( ObjHeader != NULL );
//查询设备名称
ObjName = OBJECT_HEADER_TO_NAME_INFO( ObjHeader );
KdPrint ( ( "绑定%wZ设备成功!\n", &ObjName->Name ) );
//---------------------------------------------------------------------------
//遍历下一个设备
pTagetDeviceObj = pTagetDeviceObj->NextDevice;
}
return Status;
}
//===========================================================================
//所有不关心的的Irp处理
//===========================================================================
NTSTATUS DispatchRoutine( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
PDEVICE_EXT pDeviceExt = NULL;
pDeviceExt = pDeviceObj->DeviceExtension;
ASSERT( pDeviceExt );
//---------------------------------------------------------------------------
//过滤设备不关心的Irp处理
if ( pDeviceExt->bFlags ) {
IoSkipCurrentIrpStackLocation( pIrp );
KdPrint ( ( "不关心的Irp来了一次!n" ) );
//这里返回值应该返回底层设备返回的值(注意了)
return IoCallDriver( pDeviceExt->pLowDeviceObj, pIrp );
//---------------------------------------------------------------------------
//我们和R3设备之间的通信
} else {
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
KdPrint ( ( "R3不关心的Irp来了一次!\n" ) );
return STATUS_SUCCESS;
}
}
//===========================================================================
//在键盘设备的读取请求中, 完成我们自己创建的R3设备
//pDriverObj :驱动对象
//pBuf :欲Copy到3环的缓冲区
//ulBufLen :缓冲区长度
//===========================================================================
NTSTATUS _CompletionR3Read( PDRIVER_OBJECT pDriverObj, PUCHAR pBuf, ULONG ulBufLen ) {
ULONG ulUserBufLen;
PUCHAR pUserBuf = NULL;
PDEVICE_EXT pDeviceExt = NULL;
PDEVICE_OBJECT pNextDevice = NULL;
PIO_STACK_LOCATION pUserStack = NULL;
//遍历所有设备找到我们自己和R3通信的设备
pNextDevice = pDriverObj->DeviceObject;
ASSERT( pNextDevice != NULL );
for( ; pNextDevice != NULL; pNextDevice = pNextDevice->NextDevice ) {
pDeviceExt = pNextDevice->DeviceExtension;
ASSERT( pDeviceExt );
if ( !pDeviceExt->pCurrentIrp || pDeviceExt->bFlags ) {
continue;
}
//获取R3那边读取请求的Irp
pUserStack = IoGetCurrentIrpStackLocation( pDeviceExt->pCurrentIrp );
ASSERT( pUserStack != NULL );
//缓冲区长度
ulUserBufLen = pUserStack->Parameters.Read.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;
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
//===========================================================================
//读取请求的完成例程, 这边如果有我们自己创建设备的挂起的Irp那么就会在这里完成
//===========================================================================
NTSTATUS CompletionRead( PDEVICE_OBJECT pDeviceObj, PIRP pIrp, PVOID pContext ) {
ULONG ulBufLen, i;
NTSTATUS Status;
PUCHAR pBuf = NULL;
PIO_STACK_LOCATION pStack = NULL;
PAGED_CODE();
//---------------------------------------------------------------------------
pStack = IoGetCurrentIrpStackLocation( pIrp );
//判断请求是否成功, 不成功处理是没有意义的
if ( NT_SUCCESS( pIrp->IoStatus.Status ) ) {
//获取读取请求的缓冲区, 和长度
pBuf = pIrp->AssociatedIrp.SystemBuffer;
ulBufLen = pIrp->IoStatus.Information;
for( i = 0; i < ulBufLen; i++ ) {
KdPrint ( ( "%3X", pBuf[i] ) );
}
KdPrint ( ( "\n" ) );
//这里保存起自己的Irp, 用于在卸载时发送取消消息
( ( PDEVICE_EXT )pDeviceObj->DeviceExtension )->pRoxyIrp = pIrp;
//---------------------------------------------------------------------------
//如果与我们通信的3环Irp被挂起了, 那么这里就可以返回了
//---------------------------------------------------------------------------
Status = _CompletionR3Read( pDeviceObj->DriverObject,
pBuf, ulBufLen );
if ( !NT_SUCCESS( Status ) ) {
KdPrint ( ( "R3那边的读取请求完成失败!\n" ) );
} else {
KdPrint ( ( "R3那边的请求成功完成!\n" ) );
}
}
//---------------------------------------------------------------------------
//进入此函数标志底层驱动设备将IRP完成
KdPrint( ( "Completion:读取请求的完成例程\n" ) );
if ( pIrp->PendingReturned ) {
//传播pending位
IoMarkIrpPending( pIrp );
}
return pIrp->IoStatus.Status;
}
//===========================================================================
//我们和R3通信设备的取消例程
//===========================================================================
VOID OnCancelIRP( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
PDEVICE_EXT pDeviceExt = NULL;
PAGED_CODE_LOCKED();
//---------------------------------------------------------------------------
//释放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 );
KdPrint ( ( "和R3的通信设备取消例程被调用!\n" ) );
}
//===========================================================================
//读取请求过滤
//===========================================================================
NTSTATUS DispatchRead( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
PDEVICE_EXT pDeviceExt = NULL;
PIO_STACK_LOCATION pStack = NULL;
pDeviceExt = pDeviceObj->DeviceExtension;
ASSERT( pDeviceExt );
//---------------------------------------------------------------------------
//如果是过滤设备
if ( pDeviceExt->bFlags ) {
//这句一直都没有搞明白,
if ( pIrp->CurrentLocation == 1 ) {
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
pStack = IoGetCurrentIrpStackLocation( pIrp );
IoCopyCurrentIrpStackLocationToNext( pIrp );
//设置完成例程
IoSetCompletionRoutine( pIrp, &CompletionRead, pDeviceObj, TRUE, TRUE, TRUE );
KdPrint ( ( "键盘读取请求来了, 我们设置了一个回调例程!\n" ) );
return IoCallDriver( pDeviceExt->pLowDeviceObj, pIrp );
//---------------------------------------------------------------------------
//如果是我们自己创建的设备
} else {
//如果这里为TRUE, 那么肯定是上次没有来得及处理的Irp, 那么取消
if ( pDeviceExt->pCurrentIrp ) {
IoCancelIrp( pDeviceExt->pCurrentIrp );
pDeviceExt->pCurrentIrp = NULL;
}
pDeviceExt->pCurrentIrp = pIrp;
//将IRP设置为挂起
IoMarkIrpPending( pIrp );
//设置取消例程
IoSetCancelRoutine( pIrp, OnCancelIRP );
KdPrint ( ( "R3读取请求来了一次!\n" ) );
//返回pending状态
return STATUS_PENDING;
}
}
//===========================================================================
//写入请求处理例程
//===========================================================================
NTSTATUS DispatchWrite( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
PDEVICE_EXT pDeviceExt = NULL;
pDeviceExt = pDeviceObj->DeviceExtension;
//如果是过滤设备
if ( pDeviceExt->bFlags ) {
IoSkipCurrentIrpStackLocation( pIrp );
//这里返回值应该返回底层设备返回的值(注意了)
return IoCallDriver( pDeviceExt->pLowDeviceObj, pIrp );
//---------------------------------------------------------------------------
//如果是我们自己创建的设备
} else {
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
}
//===========================================================================
//电源设备请求
//===========================================================================
NTSTATUS DispatchPower( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
PDEVICE_EXT pDeviceExt = NULL;
pDeviceExt = pDeviceObj->DeviceExtension;
//如果是过滤设备
if ( pDeviceExt->bFlags ) {
PoStartNextPowerIrp( pIrp );
IoSkipCurrentIrpStackLocation( pIrp );
//返回底层设备返回的值
return PoCallDriver( pDeviceExt->pLowDeviceObj, pIrp );
//---------------------------------------------------------------------------
//如果是我们自己创建的设备
} else {
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
}
//===========================================================================
//驱动程序入口
//===========================================================================
#pragma code_seg( "INIT", "DriverEntry" )
NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath ) {
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 );
//---------------------------------------------------------------------------
//创建和R3通信的设备Flags = FALSE
Status = _CreateDevice( pDriverObj, &USzDeviceName, &USzSysLinkName,
FALSE, &pDeviceObj );
if ( !NT_SUCCESS( Status ) ) {
KdPrint ( ( "创建和R3通信的设备失败!\n" ) );
return Status;
}
ASSERT( pDeviceObj != NULL );
//设置缓冲区操作方式(操作设备的时候老是用=不用|=
pDeviceObj->Flags |= DO_DIRECT_IO;
pDeviceObj->Flags &= ~DO_DEVICE_INITIALIZING;
//---------------------------------------------------------------------------
//绑定所有的键盘设备
Status = _AttachAllKeyBoards( pDriverObj );
if ( !NT_SUCCESS( Status ) ) {
KdPrint ( ( "绑定KbdClass设备失败!\n" ) );
return Status;
}
//---------------------------------------------------------------------------
//设置分发函数
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->MajorFunction[IRP_MJ_POWER] = &DispatchPower;
pDriverObj->DriverUnload = &DriverUnLoad;
KdPrint ( ( "DriverEntry执行完毕!\n" ) );
//---------------------------------------------------------------------------
return Status;
}
|