WinIO头文件
#ifndef WINIO_H
#define WINIO_H
//#include "..\drv\winio_nt.h"
#include "winio_nt.h"
#ifndef WINIO_DLL
#define WINIO_API _declspec(dllimport)
#else
#define WINIO_API
#endif
extern "C"
{
////初始化WinIO函数库
WINIO_API bool _stdcall InitializeWinIo();
// 关闭WinIO函数库
WINIO_API void _stdcall ShutdownWinIo();
// 将物理内存映射到一个32位应用程序的线性地址空间
WINIO_API PBYTE _stdcall MapPhysToLin(tagPhysStruct &PhysStruct);
// 物理映射线性:使用此函数解除原先使用MapPhysToLin函数映射的一段物理内存区域,该区域被映射到
// 所属的线性地址空间
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);
// 安装WinIODriver
WINIO_API bool _stdcall InstallWinIoDriver(PWSTR pszWinIoDriverPath, bool IsDemandLoaded = false);
// 移除WinIODriver
WINIO_API bool _stdcall RemoveWinIoDriver();
}
extern HANDLE hDriver;
extern bool IsWinIoInitialized;
extern bool g_Is64BitOS;
bool _stdcall StartWinIoDriver();
bool _stdcall StopWinIoDriver();
#endif函数
初始化
本函数初始化
WioIO函数库。必须在调用所有其他
函数之前调用本函数。
bool _stdcall InitializeWinlo();关闭WinIO
在内存中
清除WinIO库,必须在中止函数之前或者不需要WinIO库时调用
void _stdcall ShutdownWinIo();读
从一个
输入或输出端口读取一个字节/字/双字数据
bool _stdcall GetPortVal(WORD wPortAddr,PDWORD pwdPortVal,BYTE bSize);
// wPortAddr :输入输出端口地址
// pdwPortVal : 指向双字变量的指针, 接收从端口得到的数据
// bSize : 需要读的字节数,可以是1(BYTE),2(WORD) or 4(DWORD)写
将
一个字节/字/双字的数据写入输入或输出接口
bool _stdcall SetPortVal(WORD wPortAddr, DWORD dwPortVal, BYTE bSize);
// wPortAddr 输入输出口地址
// dwPortVal 要写入口的数据
// bSize 要写的数据个数 可以是1(BYTE),2(WORD) or 4(DWORD)物理内存映射
将
物理内存映射到一个32位应用程序的线性地址空间
PBYTE _stdcall MapPhysToLin(PBYTE pbPhysAddr, DWORD dwPhysSize, HANDLE *pPhysicalMemoryHandle);
// pbPhyAddr -- 指向物理地址的指针
// dwPhySize -- 需要映射的字节数
// uPhysicalMemoryHandle 变量指针,如果调用成功,负责接收物理内存句柄,随后本句柄在调用UnmapPhysicalMemory函数时作为其第一个参数
// 案例
PBYTE pbLinAddr;
HANDLE PhysicalMemoryHandle;
pbLinAddr = MapPhysToLin(0xA0000, 65536, &PhysicalMemoryHandle);把物理地址范围
0xA0000 - 0xAFFFF的地址空间映射与应用的线性地址空间。返回值为一个与物理地址0xA0000相关的线性地址。如出现错误,则返回值NULL
物理映射线性
使用本函数解除原先使用
MapPhysToLin函数映射的一段物理内存区域,该区域被映射到应用程序所属的线性地址空间
bool _stdcall UnmapPhysicalMemory(HANDLE PhysicalMemoryHandle,PBYTE pbLinAddr);PhysicalMemoryHandle–物理内存区域的句柄,此参数由MapPhysToLin函数的调用返回pbLinAddr–MapPhysToLin– 函数调用返回的线性地址。
读双字数据
从指定的
物理地址读取一个双字数据
bool _stdcall GetPhysLong(PBYTE pbPhysAddr,PDWORD pdwPhysVal);
// pbPhysAddr -- 指向物理地址的指针
// pdwPhysVal -- 指向一个双字变量的指针,接收从物理内存中传来的数据
// 成功 返回 非零值
// 失败 返回 零值双字型写入物理地址
将一个
双字型数据写入指定的物理地址
bool _stdcall SetPhysLong(PBYTE pbPhysAddr,DWORD dwphysVal);
// pbPhysAddr -- 指向物理地址的指针
// pdwPhysVal -- 指向待写入物理内存地址的双字型数据GetProcAddress函数
用于
获取DLL中导出函数的地址(显式链接使用)
GetProcAddress将DLL模块处理(由LoadLibrary,或GetModuleHandle返回的参数),并采用要调用的函数的名称或函数的导出序号因为通过
指针调用DLL函数,并且没有编译时类型检查,所以确保参数正确,以便不会超过在堆栈上分配的内存以及导致访问冲突。帮助提供类型安全的一种方法时查看导出函数的函数原型,并为函数指针创建匹配的typedef。
官方demo
#include "windows.h"
typedef HRESULT (CALLBACK* LPFNDLLFUNC1)(DWORD,UINT*);
HRESULT LoadAndCallSomeFunction(DWORD dwParam1, UINT * puParam2)
{
HINSTANCE hDLL; // Handle to DLL
LPFNDLLFUNC1 lpfnDllFunc1; // Function pointer
HRESULT hrReturnVal;
hDLL = LoadLibrary("MyDLL");
if (NULL != hDLL)
{
lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL, "DLLFunc1");
if (NULL != lpfnDllFunc1)
{
// call the function
hrReturnVal = lpfnDllFunc1(dwParam1, puParam2);
}
else
{
// report the error
hrReturnVal = ERROR_DELAY_LOAD_FAILED;
}
FreeLibrary(hDLL);
}
else
{
hrReturnVal = ERROR_DELAY_LOAD_FAILED;
}
return hrReturnVal;
}
如何指定调用GetProcAddress时所需的函数取决于DLL的生成方式。仅当要
链接到DLL使用模块定义(.def)文件生成,并且序号随函数在DLL.def文件的EXPORTS节中列出时,才能获取导出序号。如果DLL具有许多导出函数,则与使用函数名称相比,使用导出需要调用GetProcAddress会稍微快一些,因为导出序号充当DLL导出表中的索引。使用导出序号,GetProcAddress可以直接查找函数,而不是将指定名称与DLL导出表中的函数名进行比较。但是当仅当可控制将序号分配给.def文件中的导出函数时,才应使用导出序号调用GetProcAddress
Qt环境搭建
pro文件
DEFINES += WINIO_DLL
unix|win32: LIBS += -L$$PWD/./ -lWinIo64
RESOURCES += \
source.qrc头文件存储函数指针
typedef bool( _stdcall* LS_GetPhysLong)(PBYTE pbPhysAddr, PDWORD pdwPhysVal);
typedef bool( _stdcall* LS_SetPhysLong)(PBYTE pbPhysAddr, DWORD dwPhysVal);
typedef bool( _stdcall* LS_InitializeWinIo)();
typedef bool( _stdcall* LS_ShutdownWinIo)();
typedef bool( _stdcall* LS_GetPortVal)(WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize);
typedef bool( _stdcall* LS_SetPortVal)(WORD wPortAddr, DWORD dwPortVal, BYTE bSize);
// 对函数指针进行重定义。
LS_GetPhysLong Lib_GetPhysLong;
LS_SetPhysLong Lib_SetPhysLong;
LS_InitializeWinIo Lib_InitializeWinIo;
LS_ShutdownWinIo Lib_ShutdownWinIo;
LS_SetPortVal Lib_SetPortVal;
LS_GetPortVal Lib_GetPortVal;
HMODULE m_hDllFile; // 初始化WinIO文件函数初始化
放到函数的头文件中
//加载动态链接库,并通过GetProcAddress方法调用取函数空间地址
// @ 传入所需的动态链接库
// 返回m_hDllFile将作为GetProcAddress去调用WinIO的函数地址使用
m_hDllFile = LoadLibrary(L"WinIo64");
if(m_hDllFile == NULL)
{
Bugart("加载WinIo64失败");
}
// 对函数指针初始化Lib_InitializeWinIo -> InitializeWinIo
Lib_InitializeWinIo=(LP_InitializeWinIo)::GetProcAddress(m_hDllFile,"InitializeWinIo");
if(NULL == Lib_InitializeWinIo)
{
Bugart("load error Lib_InitializeWinIo ");
}
//qDebug()<< "后:"<< Lib_InitializeWinIo;
// 函数指针初始化 Lib_ShutdownWinIo -> ShutdownWinIo
Lib_ShutdownWinIo=(LP_ShutdownWinIo)::GetProcAddress(m_hDllFile,"ShutdownWinIo");
if(NULL == Lib_ShutdownWinIo)
{
Bugart("load error Lib_ShutdownWinIo ");
}
// 函数指针初始化 Lib_GetPhysLong -> GetPhysLong
Lib_GetPhysLong=(LP_GetPhysLong)::GetProcAddress(m_hDllFile,"GetPhysLong");
if(NULL == Lib_GetPhysLong)
{
Bugart("load error Lib_GetPhysLong ");
}
// 函数 Lib_SetPhysLong -> SetPhysLong
Lib_SetPhysLong=(LP_SetPhysLong)::GetProcAddress(m_hDllFile,"SetPhysLong");
if(NULL == Lib_SetPhysLong)
{
Bugart("load error Lib_SetPhysLong ");
}
Lib_SetPortVal=(LP_SetPortVal)::GetProcAddress(m_hDllFile,"SetPortVal");
if(NULL==Lib_SetPortVal)
{
Bugart("load error Lib_SetPortVal ");
}
// 初始化操作
Lib_GetPortVal=(LP_GetPortVal)::GetProcAddress(m_hDllFile,"GetPortVal");
if(NULL==Lib_GetPortVal)
{
Bugart("load error Lib_GetPortVal ");
}Qt WinIO调用
-
确保自己 系统处于
测试模式\n -
以管理员权限运行
CMD\n -
在输入框输入\n
bcdedit /set testsigning on # 并执行 重启即可进入测试模- 确保使用
管理员权限打开软件\n -
- 确保
使用的版本与设备型号一致\n
- 确保
-
- 确保将
软件目录的WinIo64.sys文件的签名安装到本地。
- 确保将
- 右键点击
WinIo64.sys - 点击属性\n * 点击上面的数字签名
- 选择第一个签名,查看详细信息
- 选择
查看证书 - 选择
安装证书 - 存储位置选择
本地计算机,点击下一步 将所有的证书都放入下列 存储- 点击浏览 ,选择
受信任的根证书颁发机构 - 点击
确认 - 点击
下一步 - 点击
完成导入成功即可