使用WinIO访问底层端口&寄存器
来源:互联网 发布:域名批量查询软件 编辑:程序博客网 时间:2024/05/18 01:25
一
在window系统中应用层程序没有权限访问底层,为了实现端口或者寄存器操作,就要借助高权限的程序。一般是将winio.dll 加载到驱动,借道实现底层操作。就好像我们借助驱动程序操作外设一样。
64位系统的应用层是兼容32位程序的,但驱动层是不能向下兼容的,所以winio64和winio32要用对。
WinIo可以到官方网站:http://www.internals.com/去下载,里面包含了帮助文档和源码。
因为需要加载驱动,程序要以管理员权限运行,我用的是64位WIN7系统,还需要对WinIo64.sys做交叉签名才能正常加载,没有签名的同学需要使用32位系统或使用测试模式。为了省去动态加载DLL,再动态获取函数地址去调用的麻烦,用官方的DLL源码,编译生成WinIo.lib,添加一行#pragmacomment(lib,"WinIo.lib"),修改一下winio.h,然后include就可以了。
二 winio.dll中提供的函数:
bool _stdcall InitializeWinIo();
本函数初始化WioIO函数库。
必须在调用所有其它功能函数之前调用本函数。
void _stdcall ShutdownWinIo();
本函数在内存中清除WinIO库
本函数必须在中止应用函数之前或者不再需要WinIO库时调用,
bool _stdcall GetPortVal(WORD wPortAddr, PDWORD pdwPortVal, 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).
PBYTE _stdcall MapPhysToLin(PBYTE pbPhysAddr, DWORD dwPhysSize, HANDLE *pPhysicalMemoryHandle)
使用此函数将物理内存的一部分映射到一个32位应用程序的线性地址空间。
下面是一个例子:
PBYTE pbLinAddr;
HANDLE PhysicalMemoryHandle;
pbLinAddr = MapPhysToLin(0xA0000, 65536, &PhysicalMemoryHandle);
该函数将把物理地址范围为0xA0000 - 0xAFFFF的地址空间映射到与应用程序对应的线性地址空间。 返回值为一个与物理地址0xA0000相关的线性地址。如果出现错误,则返回值为NULL。
参数:
pbPhysAddr – 指向物理地址的指针
dwPhysSize – 需要映射的字节数
pPhysicalMemoryHandle – 变量指针,如果调用成功,负责接收物理内存句柄。随后本句柄在调用UnmapPhysicalMemory函数时作为其第一个参数。
bool _stdcall UnmapPhysicalMemory(HANDLE PhysicalMemoryHandle, PBYTE
pbLinAddr)
使用本函数解除原先使用MapPhysToLin函数映射的一段线性物理内存区域,该区域被映射到应用程序所属的线性地址空间。
Windows 9x 应用程序不需要调用此函数。
参数:
PhysicalMemoryHandle – 物理内存区域所属的句柄,此参数由对MapPhysToLin函数的调用返回。
pbLinAddr – MapPhysToLin函数调用返回的线性地址。
bool _stdcall GetPhysLong(PBYTE pbPhysAddr, PDWORD pdwPhysVal);
从指定的物理地址读取一个双字数据。
参数:
pbPhysAddr – 指向物理地址的指针。
pdwPhysVal – 指向一个双字变量的指针,接收从物理内存中传来的数据。
如果此函数调用成功,返回一个非零值。
如果函数调用失败,则返回一个零值。
bool _stdcall SetPhysLong(PBYTE pbPhysAddr, DWORD dwPhysVal);
将一个双字型数据写入指定的物理地址。
参数:
pbPhysAddr – 指向物理地址的指针。
pdwPhysVal – 指定待写入物理内存地址出的双字型数据。
三 调用
MFC:
[DllImport("WinIo64.dll")]
public static extern bool InitializeWinIo();
BCB: 用函数指针来实现的
typedef bool (_stdcall *pfInitializeWinIo)(); //定义函数指针类型
typedef void (_stdcall *pfShutdownWinIo)();
typedef PBYTE (_stdcall *pfMapPhysToLin)(tagPhysStruct &PhysStruct);
typedef bool (_stdcall *pfUnmapPhysicalMemory)(tagPhysStruct &PhysStruct);
typedef bool (_stdcall *pfGetPhysLong)(PBYTE pbPhysAddr, PDWORD pdwPhysVal);
typedef bool (_stdcall *pfSetPhysLong)(PBYTE pbPhysAddr, DWORD dwPhysVal);
typedef bool (_stdcall *pfGetPortVal)(WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize);
typedef bool (_stdcall *pfSetPortVal)(WORD wPortAddr, DWORD dwPortVal, BYTE bSize);
typedef bool (_stdcall *pfInstallWinIoDriver)(PSTR pszWinIoDriverPath, bool IsDemandLoaded);
typedef bool (_stdcall *pfRemoveWinIoDriver)();
pfInitializeWinIo XX_InitializeWinIo; //定义函数指针
pfShutdownWinIo XX_ShutdownWinIo;
pfMapPhysToLin XX_MapPhysToLin;
pfUnmapPhysicalMemory XX_UnmapPhysicalMemory;
pfGetPhysLong XX_GetPhysLong;
pfSetPhysLong XX_SetPhysLong;
pfGetPortVal XX_GetPortVal;
pfSetPortVal XX_SetPortVal;
pfInstallWinIoDriver XX_InstallWinIoDriver;
pfRemoveWinIoDriver XX_RemoveWinIoDriver;
hWinIo = LoadLibrary("WinIo32.dll"); //载入动态链接档
if ( hWinIo != NULL )
{
XX_InitializeWinIo = (pfInitializeWinIo)GetProcAddress(hWinIo, "InitializeWinIo") ; //获取函数接口地址
XX_ShutdownWinIo = (pfShutdownWinIo)GetProcAddress(hWinIo, "ShutdownWinIo");
XX_MapPhysToLin = (pfMapPhysToLin)GetProcAddress(hWinIo, "MapPhysToLin");
XX_GetPhysLong = (pfGetPhysLong)GetProcAddress(hWinIo, "GetPhysLong");
XX_UnmapPhysicalMemory = (pfUnmapPhysicalMemory)GetProcAddress(hWinIo, "UnmapPhysicalMemory");
XX_GetPortVal = (pfGetPortVal)GetProcAddress(hWinIo, "GetPortVal");
XX_SetPortVal = (pfSetPortVal)GetProcAddress(hWinIo, "SetPortVal");
}
调用:
unsigned long v = 0;
XX_GetPortVal(p, &v, 2); // 要读的地址, 读回的数据,数据的字节数
释放资源
FreeLibrary(hWinIo);
hWinIo = NULL;
四 .使用
比如要访问superio 83627 ,SuperIO 的入口地址是:SuperIO_Cfg = 0x295; SuperIO_Dat = 0x296;
XX_SetPortVal(0x295,0x5D, 1);
Sleep(50);
XX_GetPortVal(0x296 , &buffer,1);
- 使用WinIO访问底层端口&寄存器
- 使用WinIo直接访问IO
- 使用WinIo直接访问IO
- 使用winio对直接访问IO PORT
- WinIO--Windows应用程序访问Port端口和物理内存
- winio的使用
- winio的使用
- WinIo 使用集锦
- Winio.dll的使用
- WinIo使用笔记
- 【汇编语言/底层开发】3、通过寄存器进行内存访问
- winio
- winio
- winio
- winio
- 端口寄存器
- 2440中IO端口PULL-UP寄存器如何使用
- STM32使用BSRR和BRR寄存器快速操作GPIO端口
- MIUI拖动效果
- C++之友元学习笔记
- Win7报错“部分便笺的元数据已被损坏” 80%解决问题
- 消息队列的使用场景
- android支持的命令
- 使用WinIO访问底层端口&寄存器
- eclipse导入maven项目时报错 org.apache.maven.archiver.MavenArchiver.getManifest
- SLF4J 教程
- python入门系列19―——GUI wxpython入门
- Android音视频API(android.media.projection):概览
- spring的普通类中如何取session和request对像
- 美味的海鲜面
- 微信小程序 Node.js (基础六) Buffer(缓冲区)
- 天下没有免费的午餐