一、winIO介绍
WinIO程序库允许在32位的Windows应用程序中直接对I/O端口和物理内存进行存取操作。通过使用一种内核模式的设备驱动器和其它几种底层编程技巧,它绕过了Windows系统的保护机制。
WinIo可以到官方网站:http://www.internals.com/utilities_main.htm(已经淘汰了,可以去这里下载WinIo 3.0 for Windows)去下载,里面包含了帮助文档和源码。
因为需要加载驱动,程序要以管理员权限运行,已经在win10 64验证成功
为了省去动态加载DLL,再动态获取函数地址去调用的麻烦,用官方的DLL源码,编译生成WinIo.lib
现在介绍64bit平台32位应用程序IO操作
二、WinIo64.sys签名
官方有说到:64位版本的Windows只加载设备驱动程序,这些驱动程序由一个公共CA签发的代码签名证书签署,如Verisign、Thawte等。WinIo64 除非获得了代码签名证书,否则系统不能部署在生产机器上。所以呢,你可以通过签名让其正常使用,软件公司都有签名认证,要么就自己去买个签名,要么只能在windows测试模式下用。
1.开启测试模式
- Open an elevated command window by right-clicking the icon and clicking "Run as Administrator".(管理员模式运行CMD)
- Type the following command to enable test-signing:(输入以下命令开启测试模式)
bcdedit.exe /set TESTSIGNING ON
- Reboot the machine (重启)
-
-
对端口的读取可以尝试内联汇编。
-
2.安装winIO64.sys
-
简单点就是开启测试模式,然后安装WinIo64.sys的测试签名
1.打开 WinIO64.sys的属性框,翻到“数字签名”选项卡,点击“详细信息”
2.在新出来的对话框中点击“查看证书”
3.在又新出来的对话框中点击“安装证书”
4.点击“下一步”,然后选择“将所有的证书放入下列存储”
5.点击浏览,选择“受信任的根证书发布机构”三、编译winIO.lib
1.由于winIO源代码用到了_inp等函数,而这些函数在VS2015后又不支持了,所以用VS2013以下去编译
2.得到WinIo32.dll,WinIo32.lib,WinIo64.dll,WinIo64.lib
如果是64bit平台32应用程序,就用WinIo32.dll,WinIo32.lib,WinIo64.sys
-
如果是64bit平台64应用程序,就用WinIo64.dll,WinIo64.lib,WinIo64.sys
-
如果是32bit平台32应用程序,就用WinIo32.dll,WinIo32.lib,WinIo32.sys
-
如果是32bit平台64应用程序,就用WinIo64.dll,WinIo64.lib,WinIo32.sys
-
3.提取头文件
#ifndef WINIO_H #define WINIO_H //#include "..\drv\winio_nt.h"//修改如下,然后把winio_nt.h跟winio.h放到一起 #include "winio_nt.h" #ifndef WINIO_DLL #define WINIO_API _declspec(dllimport) #else #define WINIO_API #endif extern "C" { WINIO_API bool _stdcall InitializeWinIo(); WINIO_API void _stdcall ShutdownWinIo(); WINIO_API PBYTE _stdcall MapPhysToLin(tagPhysStruct &PhysStruct); WINIO_API bool _stdcall UnmapPhysicalMemory(tagPhysStruct &PhysStruct); WINIO_API bool _stdcall GetPhysLong(PBYTE pbPhysAddr, PDWORD pdwPhysVal); WINIO_API bool _stdcall SetPhysLong(PBYTE pbPhysAddr, DWORD dwPhysVal); WINIO_API bool _stdcall GetPortVal(WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize); WINIO_API bool _stdcall SetPortVal(WORD wPortAddr, DWORD dwPortVal, BYTE bSize); WINIO_API bool _stdcall InstallWinIoDriver(PWSTR pszWinIoDriverPath, bool IsDemandLoaded = false); WINIO_API bool _stdcall RemoveWinIoDriver(); } extern HANDLE hDriver; extern bool IsWinIoInitialized; extern bool g_Is64BitOS; bool _stdcall StartWinIoDriver(); bool _stdcall StopWinIoDriver(); #endif
-
四、案例
1.源代码,管理员模式
WinIo32.dll,WinIo32.lib,winio.h,winio_nt.h放到编译根目录
-
系统CMOS端口内存地址。cmos拥有两个端口号分别是70h和71h,偏移量02是硬件时间的分钟
}#include "stdafx.h" #include <windows.h> #include "winio.h" //winio头文件 #pragma comment(lib,"winio32.lib") //包含winio库 void main(void) { unsigned short BASE = 0x71; int iPort = 2; // 初始化WinIo if (!InitializeWinIo()) { printf( "Error In InitializeWinIo!\n"); exit(1); } int DI_data; DWORD *p=new DWORD; DI_data = GetPortVal(BASE+iPort,p,4); printf("return value= %d\n", DI_data); printf("receives the value obtained from the port= %x\n", *p); ShutdownWinIo(); //关闭WinIo
2.运行
WinIo32.dll,WinIo64.sys放到程序根目录
现在提供编译好的lib库和案例:http://download.csdn.net/detail/greless/9856752