基于WinIO 3.0实现驱动级键盘模拟输入

基于WinIO 3.0实现驱动级键盘模拟输入

一个业务场景需要使用驱动级的键盘模拟,折腾了2天,总结一下,为后人节省时间。

限制条件:

1.需要真实PC机,虚拟机不行

2.仅支持PS/2 键盘(指外接键盘,笔记本直接使用是没问题的)

实现:

关于WinIO没啥好说的,自行查阅吧。

直接上可执行代码,注意红色注释部分,网上很多资料这几个不对导致不能有正确结果

测试程序里扣出来的,请先行初始化调用InitializeWinIo();

#define KBC_CMD 0x64
#define KBC_DATA 0x60

void KBCWait4IBE()
{
 DWORD dwVal=0;

do
 {
  GetPortVal(KBC_CMD,&dwVal,1);
 }
 while(dwVal   &   0x00000002);     //其他条件均不正确

}

void KEY_DOWN(int vk_in)
{
 bool bRet  = false;
 unsigned int myscancode;
 myscancode=MapVirtualKey(BYTE(vk_in),0);
 KBCWait4IBE();
 bRet = SetPortVal(KBC_CMD,0xD2,1);
 KBCWait4IBE();
 bRet = SetPortVal(KBC_DATA,0xE2,1);
 KBCWait4IBE();
 bRet = SetPortVal(KBC_CMD,0xD2,1);
 KBCWait4IBE();
 bRet = SetPortVal(KBC_DATA,myscancode,1);
}

void KEY_UP(int vk_in)
{
 bool bRet  = false;
 unsigned myscancode;
 myscancode=MapVirtualKey(BYTE(vk_in),0);
 KBCWait4IBE();
 bRet = SetPortVal(KBC_CMD,0xD2,1);
 KBCWait4IBE();
 bRet = SetPortVal(KBC_DATA,0xE0,1);
 KBCWait4IBE();
 bRet = SetPortVal(KBC_CMD,0xD2,1);
 KBCWait4IBE();

bRet = SetPortVal(KBC_DATA,(myscancode|0x80),1); //此处需要与上0x80
}

void Key_Press(int vk_in)
{
//  sti() ;

KEY_DOWN(vk_in);
 Sleep(150);
 KEY_UP(vk_in);
 Sleep(150);
}

void InputString(CString &strInput)
{
 int nLen = strInput.GetLength();

for (int i = 0; i < nLen; i++)
 {
  short nKey = VkKeyScan(strInput.GetAt(i));    //注:由ASCII码转成按键码
  bool bShift = (nKey & 0x100);                 //shift键是否按下检查

long n = GetKeyState(VK_CAPITAL);             //Caps键是否按下检查

Key_Press(nKey);
 }

}

void CWinIOTestDlg::OnButton1()
{
 // TODO: Add your control notification handler code here

CString strInput;
 
  CWnd* pWnd =
  GetDlgItem( IDC_EDIT1 );

pWnd->GetWindowText(strInput);

Sleep(4000);     //可以不用,我测试时留时间给自己切换窗口用的

InputString(strInput);

}

void CWinIOTestDlg::OnCancel()
{
 // TODO: Add extra cleanup here
     ShutdownWinIo();
 CDialog::OnCancel();
}

另WinIO 3.0的32位系统代码有点问题,在某些密码输入控件下输入会抛特权指令异常(privileged instruction)

解决方法也很简单(自己找解决办法搞了一天),修改WinIO代码为如下所示,重新编译生成DLL即可

Port32.cpp

// ---------------------------------------------------- //
//                      WinIo v3.0                      //
//     Direct Hardware Access Under Windows //
//           Copyright 1998-2010 Yariv Kaplan           //
//               http://www.internals.com               //
// ---------------------------------------------------- //

#include <windows.h>
#include <winioctl.h>
#include <conio.h>
#include "port32.h"
#include "..\drv\winio_nt.h"
#include "winio.h"

bool _stdcall GetPortVal(WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize)
{
 if (!IsWinIoInitialized)
 {
  return false;
 }

#ifdef _WIN64
 tagPortStruct PortStruct;
 DWORD dwBytesReturned;

PortStruct.bSize = bSize;
 PortStruct.wPortAddr = wPortAddr;

return DeviceIoControl(hDriver, IOCTL_WINIO_READPORT, &PortStruct, sizeof(PortStruct),
  pdwPortVal, sizeof(DWORD), &dwBytesReturned, NULL);

#elif _WIN32
 // If this is a 64 bit OS, we must use the driver to access I/O ports even if the application is 32 bit
 //if (g_Is64BitOS)
 {
  tagPortStruct PortStruct;
  DWORD dwBytesReturned;

PortStruct.bSize = bSize;
  PortStruct.wPortAddr = wPortAddr;

return DeviceIoControl(hDriver, IOCTL_WINIO_READPORT, &PortStruct, sizeof(PortStruct),
   pdwPortVal, sizeof(DWORD), &dwBytesReturned, NULL);
 }

#endif

return true;
}

bool _stdcall SetPortVal(WORD wPortAddr, DWORD dwPortVal, BYTE bSize)
{
 if (!IsWinIoInitialized)
 {
  return false;
 }

#ifdef _WIN64
 tagPortStruct PortStruct;
 DWORD dwBytesReturned;

PortStruct.bSize = bSize;
 PortStruct.dwPortVal = dwPortVal;
 PortStruct.wPortAddr = wPortAddr;

return DeviceIoControl(hDriver, IOCTL_WINIO_WRITEPORT, &PortStruct, sizeof(PortStruct),
  NULL, 0, &dwBytesReturned, NULL);
#elif _WIN32
 // If this is a 64 bit OS, we must use the driver to access I/O ports even if the application is 32 bit
 //if (g_Is64BitOS)
 {
  tagPortStruct PortStruct;
  DWORD dwBytesReturned;

PortStruct.bSize = bSize;
  PortStruct.dwPortVal = dwPortVal;
  PortStruct.wPortAddr = wPortAddr;

return DeviceIoControl(hDriver, IOCTL_WINIO_WRITEPORT, &PortStruct, sizeof(PortStruct),
   NULL, 0, &dwBytesReturned, NULL);
 }

#endif

return true;
}

时间: 2024-10-06 15:15:07

基于WinIO 3.0实现驱动级键盘模拟输入的相关文章

WinIo驱动级键盘模拟编程

WinIo驱动级键盘模拟编程 前天无聊,翻翻自己的兴趣项目文件夹,发现了这个放下很久的项目!那是大三时候的事了.当时是为了提高我魔兽三的按键速度,用了个叫移花接木的软件,把键盘的键位改了.的确是有所帮助,但这是共享软件,用40次就不能再用了除非注册.于是乎就有了做一个类似的软件出来,在网上搜索了一把发现WinIo模拟按键是最可靠的了,就决定向这方向钻进去了.哎...技术不够,看了很久的技术文章和代码也只是了解了一点,而且那时MFC技术还没到家根本做不出什么能用的东西来...后来听个兄弟说:反汇编

联想A800新蜂ROM V1.1 基于官方4.0.4精简省电稳定

ROM介绍 [出品]:新蜂工作室(基于官方) 1.源于官方:基于最稳定官方底包制作. 2.深度精简:自带APK数量从原厂包的131个减少到90个,精简31% 3.ROM包大小从原厂314MB精简到166MB,比原厂减少47%; 4.稳定流畅:经专业测试,与各种软件完美兼容,长时间稳定运行,安全流畅. 5.通过新蜂工作室独有技术,大幅提升系统运行效率,开机时长从原厂25s减少到20s,提速20%,启动后剩余内存从原厂203MB增加到223MB,提升10%. 6.极度省电:增加新蜂独有省电逻辑,待机

曝光了所谓基于安卓5.0的htc sense 6界面截图

新浪科技消息称近日国外rom开发都liabtoorer曝光了所谓基于安卓5.0的htc sense 6界面截图.据说该截图来自于htc one m8,从截图看,新界面看起来全是卡片的样子,但还是基本延续了sense以往的风格,预计htc会将该版本作米sense 6.5推送更新,不过到时候还会不会依旧四下巴呢.HTC刚上安卓5.0,最近外媒sammebiie又曝光了一段三量galaxy s5 运行基于安卓5.0的touch wiz的视频,从视频看,新系统在保留了touchwiz风格的同时依旧是卡片

基于Qt5.5.0的sql,C++备忘录软件的编写

我的第一个软件. 基于Qt5.5.0的 sql ,C++备忘录软件version1.0的编写 我用的Qt版本是5.5.0免配置编译器的版本,这里附上我使用的软件下载地址:http://download.qt.io/official_releases/qt/5.5/5.5.0/ 下载 qt-opensource-windows-x86-mingw492-5.5.0.exe即可. 话不多说,第一先是基于Qt5.5.0的sql的配置,这里详见我的另外一篇博客:http://www.cnblogs.co

一个基于cocos2d-x 3.0和Box2d的demo小程序

p图demo小应用.想怎么p就怎么p 本文參考于http://blog.csdn.net/xiaominghimi/article/details/6776096和http://www.cnblogs.com/liufan9/archive/2013/04/11/3012275.html. 于上面基于cocos2d-x 2.0不一样的地方,本本是基于cocos2d-x 3.0. 首先.当然是下载和安装cocos2d-x 3.0了,网址:http://www.cocos2d-iphone.org/

springmvc源码浅析(基于spring3.1.0)

请求处理过程:通过url找到对应Controller类中处理请求的方法,执行方法返回结果视图的过程.大致分为三个步骤: 其一,ApplicationContext初始化时建立所有url和controller类的对应关系(用Map保存); 其二,根据请求url找到对应的controller,并从controller中找到处理请求的方法; 其三,执行方法处理请求,并返回结果视图. 我们首先看第一个步骤,也就是建立Map<url,controller>关系的部分.第一部分的入口类为Applicati

基于Qt5.5.0的sql数据库、SDK_tts文本语音朗读的CET四六级单词背诵系统软件的编写V1.0

作者:小波 QQ:463431476 请关注我的博客园:http://www.cnblogs.com/xiaobo-Linux/  感觉我要火~~这比我是装定了!! 我的第二款软件:CET四六级单词背诵软件.基于QT5.5.0.sql数据库.以及TTS文本识别语音单词朗读的一款软件. 第一款软件的sql数据库软件的编写:http://www.cnblogs.com/xiaobo-Linux/p/4676950.html 现在来讲解我的第二款高大上的代码: 这个是.pro的代码,其中axconta

基于Linux 3.0.8 Samsung FIMC(S5PV210) 的摄像头驱动框架解读

作者:咕唧咕唧liukun321 来自:http://blog.csdn.net/liukun321 FIMC这个名字应该是从S5P100开始出现的,在s5pv210里面的定义是摄像头接口,但是它同样具有图像数据颜色空间转换的作用.而exynos4412对它的定义看起来更清晰些,摄像头接口被定义为FIMC-LITE .颜色空间转换的硬件结构被定义为FIMC-IS.不多说了,我们先来看看Linux3.0.8 三星的BSP包中与fimc驱动相关的文件. 上面的源码文件组成了整个fimc的驱动框架.通

谈谈基于OAuth 2.0的第三方认证 [下篇]

从安全的角度来讲,<中篇> 介绍的Implicit类型的Authorization Grant存在这样的两个问题:其一,授权服务器没有对客户端应用进行认证,因为获取Access Token的请求只提供了客户端应用的ClientID而没有提供其ClientSecret:其二,Access Token是授权服务器单独颁发给客户端应用的,照理说对于其他人(包括拥有被访问资源的授权者)应该是不可见的.Authorization Code类型的Authorization Grant很好地解决了这两个问题