- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
驱动程序设计课程大作业--键盘过滤驱动程序设计
驱动程序设计课程大作业
键盘过滤驱动程序设计
班级:
姓名:
学号:
2009年2月11日
一、主要设计思路
目标:键盘过滤驱动。
利用驱动分层机制,使用过滤驱动捕获键盘的扫描码并保存下来;应用程序定时访问驱动程序取回扫描码,转换成相应的按键名称并显示;通过应用程序设定按键映射,应用程序将指令传送给驱动程序,以实现将指定的按键消息转换成其他按键。
键盘过滤驱动是工作在异步模式下的。系统为了得到一个按键操作,首先要发送一个IRP_MJ_READ消息到驱动的设备栈,驱动收到这个IRP后,会一直保持这个IRP为未确定(pending)态,因为当时并没有按键操作。直到一个键被真正的按下,驱动此时就会立刻完成这个IRP,并将刚按下的键的相关数据做为该IRP的返回值。在该IRP带着对应的数据返回后,操作系统将这些值传递给对应的事件系统来处理,然后系统紧接着又会立刻发送一个IRP_MJ_READ请求,等待下次的按键操作,重复以上的步骤。
为了实现截获键盘消息,需要在过滤驱动程序中创建一个挂接到物理键盘设备上层的过滤驱动设备。系统发送的IRP_MJ_READ消息会首先到达过滤驱动设备,这样就可以有机会给IRP_MJ_READ设置指定的完成例程,然后将消息下传给物理键盘设备。当有按键动作发生时,IRP_MJ_READ消息在完成后就会调用指定的完成例程,这时就可以在完成例程中读出键盘动作的内容,或者修改这些信息,以实现按键的映射。
标准的按键扫描码和ASCII码没有直接的对应关系,大部分按键的扫描码为一个字节;部分功能键为两个字节,且都以0xE0为高字节。但实验中发现,IRP中返回的按键信息和标准的扫描码并不全等。在KEYBOARD_INPUT_DATA结构中,MakeCode字段仅包含了一个字节的编码,还要同时参照Flags字段的内容才能判断出按键的扫描码。
下表是KEYBOARD_INPUT_DATA结构中两个字段的内容与其所代表的按键动作的对应关系。当Flags=0或1时,说明按下的按键是扫描码为一个字节的按键;若Flags=2或3,则说明按下的是扫描码为两个字节的按键,而MakeCode中只保留扫描码的低字节。
Flags MakeCode 动作 0 等于扫描码 按下 1 等于扫描码 松开 2 扫描码的低字节 按下 3 扫描码的低字节 松开 若使用指定的内容改写返回值中的KEYBOARD_INPUT_DATA结构,就可以改变按键的作用,实现按键映射的功能。
除了IRP_MJ_READ以外,对于其他发送给键盘设备的消息,到达过滤驱动设备时就可以不做处理,直接下传给键盘设备,以保证系统的正常工作。
在完成例程中将每次捕获得到的扫描码保存起来,应用程序每隔一定的时间(100ms)读取一次并将其清空,再根据扫描码查表得到相应按键的名称,这样就可以做到在应用程序中实时的显示键盘动作。用户在应用程序中设定好按键映射的对应关系后,可以通过IRP_MJ_DEVICE_CONTROL消息将映射关系发送给过滤驱动程序,还是在完成例程中实现按键的映射替代。
模块的划分、实现及说明
具体实现分为驱动程序和应用程序两大部分。驱动程序用C和WindowsXP DDK实现,应用程序通过VC++ 6.0基于MFC实现。在调试和测试中使用了DriverMonitor和Dbgview等工具。
下面分别介绍其中主要部分的实现:
(一)驱动程序部分
DEVICE_EXTENSION的定义
//定义设备扩展对象
typedef struct _DEVICE_EXTENSION {
PDRIVER_OBJECT pDriver; //对应的驱动
PDEVICE_OBJECT pDevice; //驱动对应的设备对象
PDEVICE_OBJECT pKBDevice; //挂接到的键盘设备
UNICODE_STRING ustrDeviceName; //设备名称
UNICODE_STRING ustrSymLinkName; //符号链接名
ULONG IrpPendingCount; //运行中的IRP数量
ULONG LastScanCode; //最近获得的键盘扫描码
ULONG SetCode[2]; //按键映射规则:SetCode[0]-SetCode[1]
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
DriverEntry
主要任务是填写MajorFunction数组、设置卸载例程,并调用CreateDevice函数。对所关心的一些消息分别设置回调函数,为其他消息设置通用处理函数。
//通用事件处理例程
for (i=0; i=IRP_MJ_MAXIMUM_
原创力文档


文档评论(0)