基于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;
}

转载于:https://www.cnblogs.com/honeynm/p/4096456.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值