📄 jiurl键盘驱动 4.htm
字号:
DeviceName ,调用时不为空,说明这个设备对象有名字。在我这里这个名字是
"\Device\KeyboardClass0"。<BR><BR>调用 ExAllocatePool 为 kbdclass
的输入数据队列分配内存,分配内存的大小为
deviceExtension->KeyboardAttributes.InputDataQueueLength。而
deviceExtension->KeyboardAttributes.InputDataQueueLength 是由
Globals.InitExtension.KeyboardAttributes.InputDataQueueLength 赋值的。而
Globals.InitExtension.KeyboardAttributes.InputDataQueueLength 是在 kbdclass
的 DriverEntry 中初始化的。即读取注册表
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Kbdclass\Parameters\KeyboardDataQueueSize
,然后乘以 sizeof(KEYBOARD_INPUT_DATA)。<BR><BR>deviceExtension->InputData
保存申请空间的首地址。<BR>然后调用
KbdInitializeDataQueue,初始化, <BR>deviceExtension->InputCount =
0;<BR>deviceExtension->DataIn =
deviceExtension->InputData;<BR>deviceExtension->DataOut =
deviceExtension->InputData;<BR>也就是开始的时候,DataIn,DataOut
都指向输入数据队列的开头。<BR><BR>调用 IoAttachDeviceToDeviceStack 将产生的 kbdclass
的设备对象放入键盘设备栈。现在键盘设备栈就已经连接完了。<BR><BR>kbdclass!KbdSendConnectRequest 以一个
CONNECT_DATA ,IOCTL_INTERNAL_KEYBOARD_CONNECT 为参数调用
IoBuildDeviceIoControlRequest,创建一个 IRP_MJ_INTERNAL_DEVICE_CONTROL 的 IRP
,调用 IoCallDriver 传给 i8024prt。这个 CONNECT_DATA 中有kbdclass处理输入数据的回调函数
kbdclass!KeyboardClassServiceCallback 的地址。IoCallDriver 根据这个 IRP ,调用
i8042prt!I8xInternalDeviceControl。在 i8042prt!I8xInternalDeviceControl
中会把这个 CONNECT_DATA 保存在 kbExtension->ConnectData
中。这样,以后i8042prt得到了按键的数据以后,就可以调用kbdclass指定的这个回调函数,让 kbdclass
作出处理。这里i8042prt!I8xInternalDeviceControl 处理
IOCTL_INTERNAL_KEYBOARD_CONNECT
的部分,还早在这时就给上一层一个设置hook机会,如果在这时设置hook,可能会对初始化的某些过程hoot,不过 kbdclass
对此没有处理。<BR><BR>[IRP_MJ_PNP IRP_MN_QUERY_LEGACY_BUS_INFORMATION]<BR><BR>#
ChildEBP RetAddr Args to Child <BR>00 f901f638 8041f54b fe4f5df0
fe4fea08 fe4f5df0 kbdclass!KeyboardPnP(struct _DEVICE_OBJECT *
DeviceObject = 0xfe4f5df0, struct _IRP * Irp = 0xfe4fea08) (CONV:
stdcall)<BR>01 f901f64c 8049cb91 f901f6bc fe4dd730 fe4fedc0
nt!IopfCallDriver+0x35 (FPO: [0,0,2])<BR>02 f901f678 8048f328 fe4f5df0
f901f698 f901f6c4 nt!IopSynchronousCall+0xca (FPO: [Non-Fpo])<BR>03
f901f6bc 804a4bd1 fe4dd730 00000000 fe4fedc0
nt!IopQueryLegacyBusInformation+0x2c (FPO: [Non-Fpo])<BR>04 f901f77c
8054f1bb 80000048 00000005 f901f800 nt!IopCallDriverAddDevice+0x634 (FPO:
[Non-Fpo])<BR>05 f901f798 804e504e fe4fed68 f901f864 fe4d6368
nt!IopProcessAddDevicesWorker+0x6c (FPO: [2,0,3])<BR>06 f901f7a8 8054f184
fe4d6368 8054f147 f901f864 nt!IopForAllChildDeviceNodes+0x1f (FPO:
[3,0,1])<BR>07 f901f7c4 804e504e fe4d6368 f901f864 fe4e7c28
nt!IopProcessAddDevicesWorker+0x3d (FPO: [2,0,3])<BR>08 f901f7d4 8054f184
fe4e7c28 8054f147 f901f864 nt!IopForAllChildDeviceNodes+0x1f (FPO:
[3,0,1])<BR>09 f901f7f0 804e504e fe4e7c28 f901f864 fe5181a8
nt!IopProcessAddDevicesWorker+0x3d (FPO: [2,0,3])<BR>0a f901f800 8054f184
fe5181a8 8054f147 f901f864 nt!IopForAllChildDeviceNodes+0x1f (FPO:
[3,0,1])<BR>0b f901f81c 804e504e fe5181a8 f901f864 fe51b5e8
nt!IopProcessAddDevicesWorker+0x3d (FPO: [2,0,3])<BR>0c f901f82c 8054f184
fe51b5e8 8054f147 f901f864 nt!IopForAllChildDeviceNodes+0x1f (FPO:
[3,0,1])<BR>0d f901f848 8054f114 fe51b5e8 f901f864 00000003
nt!IopProcessAddDevicesWorker+0x3d (FPO: [2,0,3])<BR>0e f901f86c 8054dfdf
fe51baa8 0000ffff 00000003 nt!IopProcessAddDevices+0x59 (FPO:
[Non-Fpo])<BR>0f f901f8c0 8054c5c9 00000000 00000032 00000000
nt!IopInitializeSystemDrivers+0x25 (FPO: [Non-Fpo])<BR>10 f901fa58
8054b35a 80087000 00000000 00000000 nt!IoInitSystem+0x644 (FPO:
[Non-Fpo])<BR>11 f901fda8 804524f6 80087000 00000000 00000000
nt!Phase1Initialization+0x71b (FPO: [Non-Fpo])<BR>12 f901fddc 80465b62
8054aca6 80087000 00000000 nt!PspSystemThreadStartup+0x69 (FPO:
[Non-Fpo])<BR>13 00000000 00000000 00000000 00000000 00000000
nt!KiThreadStartup+0x16<BR><BR>IO 管理器向键盘设备栈发 IRP_MJ_PNP
IRP_MN_QUERY_LEGACY_BUS_INFORMATION 的 IRP。<BR><BR>这将导致
kbdclass!KeyboardPnP 被执行,我们从 kbdclass!KeyboardPnP 的传入参数 Irp 可以知道,这个 IRP
是哪种 IRP。<BR><BR>kbdclass 和 i8042prt 对 IRP_MJ_PNP
IRP_MN_QUERY_LEGACY_BUS_INFORMATION 的 IRP
都没有处理,向下传。<BR><BR><BR>[IRP_MJ_PNP
IRP_MN_FILTER_RESOURCE_REQUIREMENTS]<BR><BR># ChildEBP RetAddr Args to
Child <BR>00 f901f6f4 8041f54b fe4f5df0 fe4fea08 fe4f5df0
kbdclass!KeyboardPnP(struct _DEVICE_OBJECT * DeviceObject = 0xfe4f5df0,
struct _IRP * Irp = 0xfe4fea08)+0x9 (CONV: stdcall)<BR>01 f901f708
8048f468 e12bf298 fe4fed68 f901f7c0 nt!IopfCallDriver+0x35 (FPO:
[0,0,2])<BR>02 f901f734 8048f2dc fe4f5df0 e12b4ee8 f901f794
nt!IopFilterResourceRequirementsCall+0xdb (FPO: [Non-Fpo])<BR>03 f901f79c
8048dff9 fe4dd730 e12b4ee8 e12bf201 nt!IopQueryDeviceResources+0x211 (FPO:
[Non-Fpo])<BR>04 f901f7d0 8048df26 e12bf288 e12bf5c4 f901f7f8
nt!IopGetResourceRequirementsForAssignTable+0xc6 (FPO: [Non-Fpo])<BR>05
f901f800 8048f0ac f901f84c f901f850 00000000 nt!IopAllocateResources+0xa0
(FPO: [Non-Fpo])<BR>06 f901f844 8048edf6 00000017 e12bf288 00000001
nt!IopAssignResourcesToDevices+0xd9 (FPO: [Non-Fpo])<BR>07 f901f86c
8054e005 fe51baa8 00000000 00000001 nt!IopProcessAssignResources+0xe8
(FPO: [Non-Fpo])<BR>08 f901f8c0 8054c5c9 00000000 00000032 00000000
nt!IopInitializeSystemDrivers+0x4b (FPO: [Non-Fpo])<BR>09 f901fa58
8054b35a 80087000 00000000 00000000 nt!IoInitSystem+0x644 (FPO:
[Non-Fpo])<BR>0a f901fda8 804524f6 80087000 00000000 00000000
nt!Phase1Initialization+0x71b (FPO: [Non-Fpo])<BR>0b f901fddc 80465b62
8054aca6 80087000 00000000 nt!PspSystemThreadStartup+0x69 (FPO:
[Non-Fpo])<BR>0c 00000000 00000000 00000000 00000000 00000000
nt!KiThreadStartup+0x16<BR><BR>IO 管理器向键盘设备栈发 IRP_MJ_PNP
IRP_MN_FILTER_RESOURCE_REQUIREMENTS 的 IRP。<BR><BR>kbdclass!KeyboardPnP 对
IRP_MJ_PNP IRP_MN_FILTER_RESOURCE_REQUIREMENTS 没处理,向下传。<BR>i8042prt!I8xPnP
处理 IRP_MJ_PNP IRP_MN_FILTER_RESOURCE_REQUIREMENTS 的部分中,首先把这个 IRP
向下传。之后会调用函数
i8042prt!I8xFilterResourceRequirements。i8042prt!I8xFilterResourceRequirements中会把传入的端口信息保存在
Globals.ControllerData->KnownPorts 中,除此之外,没有作什么值得注意的处理。<BR><BR>DDK
中说,pnp管理器发 IRP_MN_FILTER_RESOURCE_REQUIREMENTS IRP
,是给驱动一个调整和修改资源的一个机会。<BR><BR>我们来看一看系统打算给键盘驱动分配的资源。<BR><BR>使用 WinDbg 的 !irp
命令来查看传入 IRP。<BR><BR>kd> !irp fe4fea08<BR>Irp is active with 6 stacks 6
is current (= 0xfe4feb2c)<BR>No Mdl Thread fe4f47e0: Irp stack
trace. <BR>cmd flg cl Device File Completion-Context<BR>[ 0, 0] 0 0
00000000 00000000 00000000-00000000 <BR><BR>Args: 00000000 00000000
00000000 00000000<BR>[ 0, 0] 0 0 00000000 00000000
00000000-00000000 <BR><BR>Args: 00000000 00000000 00000000
00000000<BR>[ 0, 0] 0 0 00000000 00000000
00000000-00000000 <BR><BR>Args: 00000000 00000000 00000000
00000000<BR>[ 0, 0] 0 0 00000000 00000000
00000000-00000000 <BR><BR>Args: 00000000 00000000 00000000
00000000<BR>[ 0, 0] 0 0 00000000 00000000
00000000-00000000 <BR><BR>Args: 00000000 00000000 00000000
00000000<BR>>[ 1b, d] 0 0 fe4f5df0 00000000
00000000-00000000 <BR>\Driver\Kbdclass<BR>Args: e12b4ee8 00000000
00000000 00000000<BR><BR>看到当前 IO_STACK_LOCATION 的 MajorFunction 为
0x1b,MinorFunction 为 0xd。即 MajorFunction 为 IRP_MJ_PNP,MinorFunction 为
IRP_MN_FILTER_RESOURCE_REQUIREMENTS。<BR><BR>详细的看看当前的 IO_STACK_LOCATION
,<BR><BR>kd> !strct io_stack_location fe4feb2c<BR>struct
_IO_STACK_LOCATION (sizeof=36)<BR>+00 byte MajorFunction = 1b .<BR>+01
byte MinorFunction = 0d .<BR>+02 byte Flags = 00 .<BR>+03 byte Control =
00 .<BR>+04 union __unnamed19 Parameters<BR>+04 struct __unnamed42
FilterResourceRequirements<BR>+04 struct _IO_RESOURCE_REQUIREMENTS_LIST
*IoResourceRequirementList = E12B4EE8<BR>+14 struct _DEVICE_OBJECT
*DeviceObject = FE4F5DF0<BR>+18 struct _FILE_OBJECT *FileObject =
00000000<BR>+1c function *CompletionRoutine = 00000000<BR>+20 void
*Context = 00000000<BR><BR>传入了一个指向 IO_RESOURCE_REQUIREMENTS_LIST
结构的指针。<BR>我们使用 WinDbg 的 !ioreslist 看看这个 IO_RESOURCE_REQUIREMENTS_LIST
中的资源<BR><BR>kd> !ioreslist e12b4ee8<BR>IoResList at 0xe12b4ee8 :
Interface 0xf Bus 0 Slot 0<BR>Reserved Values = {0x00000030, 0x00000201,
0x05000000}<BR>Alternative 0 (Version 1.1)<BR>Preferred Descriptor 0 -
NonArbitrated/ConfigData (0x80) Shared (0x3)<BR>Flags (0000)
- <BR>Data: : 0x1 0x5 0x180200<BR>Preferred Descriptor 1 - Port (0x1)
Device Exclusive (0x1)<BR>Flags (0x11) - PORT_IO
16_BIT_DECODE <BR>0x000001 byte range with alignment 0x000001<BR>60 -
0x60<BR>Preferred Descriptor 2 - Port (0x1) Device Exclusive
(0x1)<BR>Flags (0x11) - PORT_IO 16_BIT_DECODE <BR>0x000001 byte range
with alignment 0x000001<BR>64 - 0x64<BR>Preferred Descriptor 3 - Interrupt
(0x2) Device Exclusive (0x1)<BR>Flags (0x01) - LATCHED <BR>0x1 -
0x1<BR><BR>可以看到,系统打算给键盘驱动分配的资源有,两个端口,一个
0x60,一个0x64。一个中断,IRQ为1。<BR><BR>[IRP_MJ_PNP IRP_MN_START_DEVICE]<BR><BR>#
ChildEBP RetAddr Args to Child <BR>00 f901f6a4 8041f54b fe4f5df0
fe4fea08 fe4f5df0 kbdclass!KeyboardPnP(struct _DEVICE_OBJECT *
DeviceObject = 0xfe4f5df0, struct _IRP * Irp = 0xfe4fea08)+0x9 (CONV:
stdcall)<BR>01 f901f6b8 8049cb91 00020000 fe4fed68 00000000
nt!IopfCallDriver+0x35 (FPO: [0,0,2])<BR>02 f901f6e4 804289ce fe4f5df0
f901f704 f901f72c nt!IopSynchronousCall+0xca (FPO: [Non-Fpo])<BR>03
f901f730 8048e06a fe4dd730 00000000 fe4fed68 nt!IopStartDevice+0x127 (FPO:
[Non-Fpo])<BR>04 f901f764 8048e040 fe4fed68 f901f88c 00000000
nt!IopStartAndEnumerateDevice+0x22 (FPO: [Non-Fpo])<BR>05 f901f784
804e504e fe4fed68 f901f88c fe4d6368 nt!IopProcessStartDevicesWorker+0x72
(FPO: [Non-Fpo])<BR>06 f901f794 804a4670 fe4d6368 804a4618 f901f88c
nt!IopForAllChildDeviceNodes+0x1f (FPO: [3,0,1])<BR>07 f901f7b8 804e504e
fe4d6368 f901f88c fe4e7c28 nt!IopProcessStartDevicesWorker+0x55 (FPO:
[Non-Fpo])<BR>08 f901f7c8 804a4670 fe4e7c28 804a4618 f901f88c
nt!IopForAllChildDeviceNodes+0x1f (FPO: [3,0,1])<BR>09 f901f7ec 804e504e
fe4e7c28 f901f88c fe5181a8 nt!IopProcessStartDevicesWorker+0x55 (FPO:
[Non-Fpo])<BR>0a f901f7fc 804a4670 fe5181a8 804a4618 f901f88c
nt!IopForAllChildDeviceNodes+0x1f (FPO: [3,0,1])<BR>0b f901f820 804e504e
fe5181a8 f901f88c fe51b5e8 nt!IopProcessStartDevicesWorker+0x55 (FPO:
[Non-Fpo])<BR>0c f901f830 804a4670 fe51b5e8 804a4618 f901f88c
nt!IopForAllChildDeviceNodes+0x1f (FPO: [3,0,1])<BR>0d f901f854 804a4607
fe51b5e8 f901f88c 00000003 nt!IopProcessStartDevicesWorker+0x55 (FPO:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -