|
|
C++ 代码封装成一个标准的 32 位 DLL,导出 PCI 地址操作和 WinRing0 初始化函数,供其他语言(如 C#、Python、VB)调用。
完整 DLL 源码
PciHelper.h
cpp
#pragma once
#ifdef PCIHELPER_EXPORTS
#define PCIHELPER_API __declspec(dllexport)
#else
#define PCIHELPER_API __declspec(dllimport)
#endif
// 初始化和清理
extern "C" PCIHELPER_API BOOL InitPciAccess();
extern "C" PCIHELPER_API void CleanupPciAccess();
// 地址转换函数
extern "C" PCIHELPER_API DWORD PciBusDevFunc(BYTE bus, BYTE dev, BYTE func);
extern "C" PCIHELPER_API BYTE PciGetBus(DWORD address);
extern "C" PCIHELPER_API BYTE PciGetDev(DWORD address);
extern "C" PCIHELPER_API BYTE PciGetFunc(DWORD address);
// PCI 读写函数
extern "C" PCIHELPER_API BOOL ReadPciDword(DWORD address, BYTE reg, DWORD* value);
extern "C" PCIHELPER_API BOOL ReadPciWord(DWORD address, BYTE reg, WORD* value);
extern "C" PCIHELPER_API BOOL ReadPciByte(DWORD address, BYTE reg, BYTE* value);
extern "C" PCIHELPER_API BOOL WritePciDword(DWORD address, BYTE reg, DWORD value);
extern "C" PCIHELPER_API BOOL WritePciWord(DWORD address, BYTE reg, WORD value);
extern "C" PCIHELPER_API BOOL WritePciByte(DWORD address, BYTE reg, BYTE value);
// 获取错误码
extern "C" PCIHELPER_API DWORD GetLastPciError();
PciHelper.cpp
cpp
#include <windows.h>
#include "PciHelper.h"
#include "OlsApi.h" // WinRing0 头文件
static DWORD g_lastError = 0;
BOOL InitPciAccess()
{
if (!InitializeOls())
{
g_lastError = GetDllStatus();
return FALSE;
}
g_lastError = 0;
return TRUE;
}
void CleanupPciAccess()
{
DeinitializeOls();
}
DWORD PciBusDevFunc(BYTE bus, BYTE dev, BYTE func)
{
return ((bus & 0xFF) << 8) | ((dev & 0x1F) << 3) | (func & 7);
}
BYTE PciGetBus(DWORD address)
{
return (BYTE)((address >> 8) & 0xFF);
}
BYTE PciGetDev(DWORD address)
{
return (BYTE)((address >> 3) & 0x1F);
}
BYTE PciGetFunc(DWORD address)
{
return (BYTE)(address & 7);
}
BOOL ReadPciDword(DWORD address, BYTE reg, DWORD* value)
{
g_lastError = 0;
if (!value) return FALSE;
BOOL result = ReadPciConfigDword(address, reg, value);
if (!result) g_lastError = GetDllStatus();
return result;
}
BOOL ReadPciWord(DWORD address, BYTE reg, WORD* value)
{
g_lastError = 0;
if (!value) return FALSE;
BOOL result = ReadPciConfigWord(address, reg, value);
if (!result) g_lastError = GetDllStatus();
return result;
}
BOOL ReadPciByte(DWORD address, BYTE reg, BYTE* value)
{
g_lastError = 0;
if (!value) return FALSE;
BOOL result = ReadPciConfigByte(address, reg, value);
if (!result) g_lastError = GetDllStatus();
return result;
}
BOOL WritePciDword(DWORD address, BYTE reg, DWORD value)
{
g_lastError = 0;
BOOL result = WritePciConfigDword(address, reg, value);
if (!result) g_lastError = GetDllStatus();
return result;
}
BOOL WritePciWord(DWORD address, BYTE reg, WORD value)
{
g_lastError = 0;
BOOL result = WritePciConfigWord(address, reg, value);
if (!result) g_lastError = GetDllStatus();
return result;
}
BOOL WritePciByte(DWORD address, BYTE reg, BYTE value)
{
g_lastError = 0;
BOOL result = WritePciConfigByte(address, reg, value);
if (!result) g_lastError = GetDllStatus();
return result;
}
DWORD GetLastPciError()
{
return g_lastError;
}
编译 32 位 DLL 的步骤
Visual Studio 配置
创建项目:新建 → Visual C++ → Windows 桌面 → 动态链接库 (DLL)
设置平台为 x86:
解决方案平台下拉框 → 配置管理器 → 活动解决方案平台 → 新建
选择 x86,确定
添加 WinRing0 文件:
将 OlsDef.h、OlsApi.h 和 WinRing0.lib(32位版本)放入项目目录
项目 → 属性 → VC++ 目录 → 包含目录,添加头文件路径
项目 → 属性 → 链接器 → 输入 → 附加依赖项,添加 WinRing0.lib
定义导出宏:
项目 → 属性 → C/C++ → 预处理器 → 预处理器定义
添加 PCIHELPER_EXPORTS
编译:生成 → 生成解决方案(选择 Release x86)
运行时依赖文件
编译好的 DLL 需要配合以下文件使用 :
文件 说明
PciHelper.dll 你封装的32位DLL
WinRing0.dll WinRing0 32位核心库
WinRing0.sys 32位内核驱动程序
注意:运行时所有文件需放在同一目录,并以管理员权限运行调用程序。
调用示例(C# 调用 32位 DLL)
csharp
using System;
using System.Runtime.InteropServices;
class PciTest
{
[DllImport("PciHelper.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool InitPciAccess();
[DllImport("PciHelper.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void CleanupPciAccess();
[DllImport("PciHelper.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern uint PciBusDevFunc(byte bus, byte dev, byte func);
[DllImport("PciHelper.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool ReadPciDword(uint address, byte reg, out uint value);
static void Main()
{
if (!InitPciAccess())
{
Console.WriteLine("初始化失败,请以管理员权限运行");
return;
}
uint address = PciBusDevFunc(0, 31, 2);
uint value;
if (ReadPciDword(address, 0x00, out value))
{
Console.WriteLine($"Vendor/Device: 0x{value:X8}");
}
CleanupPciAccess();
}
}
注意:调用方也必须编译为 x86 目标平台,才能正确加载32位 DLL |
|