前段时间想写一个简单的键盘驱动,就找网上找了一些文档看看。JIURL的键盘驱动5篇文章都很精彩,让人很快就能明白键盘驱动的原理。一般情况微软建议写的键盘驱动都是属于keyboard filter driver,它位于kbdclass和i8042prt驱动之间。利用IOCTL_INTERNAL_KEYBOARD_CONNECT来挂接KeyboardClassServiceCallback,然后在I8042KeyboardIsrDpc程序调用KeyboardClassServiceCallback。在NTDDK的中i8042prt驱动源码中可以看到,KeyboardClassServiceCallback中已经把i8042输入队列的数据直接放到了irp的systembuffer中,只有在systembuffer中放不下的才会放到kbdclass的输入队列。利用IOCTL_INTERNAL_KEYBOARD_DISCONNECT来解除对KeyboardClassServiceCallback的调用。
在SysInternals上看到了ctrl2cap,它的用途很简单,就是把cap-locks键重新映射为left-ctrl键,具作者说是以前在unix的机器上习惯了按cap-locks键,没有用过unix,也不知道什么原因。这个驱动的设计和keyboardfilter driver有一些区别,它是位于kbdclass之上的,它首先截获来自win32k!RawInputThread的IRP_MJ_READ,设置read completion callback函数,然后再调用IoCallDriver把IRP_MJ_READ发送到kbdclass driver,在read completion callback函数中修改了键盘缓冲区的MAKECODE。
这两个程序在安装的时候有些区别,keyboard filter driver是安装在Keyboard Port之上的UpperFilter,而ctrl2cap这类键盘驱动是安装在Keyboard Class之上的UpperFilter。我觉得倒不是ctrl2cap的作者说的不用写inf文件的缘故。
另外在网上还到有人在问,说是按照NTDDK的kbfiltr修改的程序,用来屏蔽insert键没用。查看了一下他的代码,居然是模仿ctrl2cap的程序来做的,也是处理的IRP_MJ_READ。可是它是按照keyboard filter driver来安装。查看kbdclass源码中的KeyboardClassRead根本就没有IRP_MJ_READ分派到下一层的驱动中去,直接在本层中处理的。所以当然不会调用到keyboard filter driver中的IRP_MJ_READ处理函数了。