键盘过滤

键盘过滤

PDO:Physical Device Object,字面意义是物理设备,暂时可以这么理解:PDO为设备栈中最下面的那个设备对象

键盘工作原理:P121页;简述:当键盘有按键按下/松开时,将会触发中断处理函数,中断服务例程由键盘驱动提供,键盘的驱动会从端口读取扫描码,经过处理后,将获取到的数据提交给IRP,将会有对应线程对该IRP进行读取获取键盘信息。

一般来说一个PS/2的键盘的设备栈(没有安装其它键盘过滤驱动的话)为:顶层设备对象为KbdClass驱动生成的设备对象,中间层的设备对象是驱动8042prt生成的设备对象,底层设备对象是驱动ACPI生成的设备对象,

无须关心上面的细节,只需要知道一个正规的键盘过滤驱动一般是去绑定KbdClass驱动生成的设备对象。

键盘过滤的框架

  • 找到并绑定所有的键盘设备。

    • KbdClass驱动名为\Driver\Kbdclass,通过ObReferenceObjectByName,可以打开该驱动。
    • 通过设备链遍历KbdClass驱动的设备对象,利用IoCreateDevice创建过滤设备对象,使用IoAttachDeviceToDeviceStack绑定每一个设备即可绑定到所有的键盘设备,将该API返回的参数以设备扩展的方式保存,方便直接下发IRP给下层设备对象。
  • 设置相应的IRP回调,需要关心的有IRP_MJ_READ(因为要过滤的就是读取按键信息)、IRP_MJ_POWER(因为这类请求需要使用PoCallDriver和一个PoStartNextPowerIrp来向下层设备发送IRP)、IRP_MJ_PNP(当设备被插拔时的分发函数)、以及相应的卸载函数。

    • IRP_MJ_READ

      当截到read的irp请求时,应该有一个全局变量计数器对其进行+1操作,目的是为了在卸载驱动的时候,等待该全局变量计数器归0再去卸载,不然会造成irp完成例程还没结束时就卸载的情况,此时就会蓝屏。

      因为读取的IRP还没下发,所以并不知道读取了什么内容,只能通过设置完成例程来获取IRP读取的内容。通过如下代码拷贝栈空间,设置IRP完成例程来读取键盘的内容。

      IoCopyCurrentIrpStackLocationToNext(Irp);
      IoSetCompletionRoutine( Irp, c2pReadComplete, 
              DeviceObject, TRUE, TRUE, TRUE ); 
      

      在完成例程中可以通过如下代码来获取所有读取的内容,也可以修改读取的内容来讲LOCK键改成CTRL键,当完成例程结束时还需要将全局变量-1.

      if( NT_SUCCESS( Irp->IoStatus.Status ) ) 
           {
             
              // 获得读请求完成后输出的缓冲区
              buf = Irp->AssociatedIrp.SystemBuffer;
      		KeyData = (PKEYBOARD_INPUT_DATA)buf;
              // 获得这个缓冲区的长度。一般的说返回值有多长都保存在
              // Information中。
              buf_len = Irp->IoStatus.Information;
              numKeys = buf_len / sizeof(KEYBOARD_INPUT_DATA);
              //… 这里可以做进一步的处理。我这里很简单的打印出所有的扫
              // 描码。
              //for(i=0;i<buf_len;++i)
      		for(i=0;i<numKeys;++i)
              {
             
                  //DbgPrint("ctrl2cap: %2x\r\n", buf[i]);
      			DbgPrint("\n");
      			DbgPrint("numKeys : %d",numKeys);
      			DbgPrint("ScanCode: %x ", KeyData->MakeCode ); 
      			DbgPrint("%s\n", KeyData->Flags ?"Up" : "Down" );
      			print_keystroke((UCHAR)KeyData->MakeCode);
      
      			if( KeyData->MakeCode == CAPS_LOCK) 
      			{
              
      				KeyData->MakeCode = LCONTROL; 
      			} 
              
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值