使用WinIO访问底层端口&寄存器

在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;      

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值