读取REG_RESOURCE_LIST内存值出错:最后长度值不符求助
问题分析与解决方案
你遇到的物理内存长度读取截断问题,大概率是32位程序在64位系统上访问注册表时的视图重定向导致的,同时代码里还有几处错误处理和API调用的细节需要修正。
核心问题根源
在64位Windows系统中,32位程序默认会访问注册表的32位视图,但Hardware\ResourceMap\System Resources\Physical Memory下的物理内存信息仅存在于64位视图中。如果你的程序是32位编译的,直接用RegOpenKey读取会获取到被截断的64位数值,这就是最后一个长度从0x41f000000变成0x41f0000的原因。
此外,你的代码还存在以下问题:
- 未检查第二次
RegQueryValueEx的返回值,无法确认数据是否正确读取 - 错误提示信息错误(
RegQueryValueEx失败时错误提示RegOpenKey failed) - 没有明确指定注册表访问的权限和视图标志
修正后的代码
#include <iostream> #include <windows.h> #include <iomanip> #include <string> using namespace std; void PrintError(const char* operation) { DWORD error = GetLastError(); cout << operation << " failed, error code: 0x" << hex << error << endl; } int main() { HKEY hKey = NULL; LPCTSTR pszSubKey = L"Hardware\\ResourceMap\\System Resources\\Physical Memory"; LPCTSTR pszValueName = L".Translated"; // 使用RegOpenKeyEx,指定64位视图标志,确保32位程序能访问64位注册表 LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszSubKey, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); if (result != ERROR_SUCCESS) { PrintError("RegOpenKeyEx"); return 1; } DWORD dwType = 0; DWORD dwLength = 0; // 第一次调用获取所需缓冲区大小 result = RegQueryValueEx(hKey, pszValueName, 0, &dwType, NULL, &dwLength); if (result != ERROR_SUCCESS) { PrintError("RegQueryValueEx (get buffer size)"); RegCloseKey(hKey); return 1; } LPBYTE lpData = new BYTE[dwLength]; // 第二次调用读取实际数据,必须检查返回值 result = RegQueryValueEx(hKey, pszValueName, 0, &dwType, lpData, &dwLength); if (result != ERROR_SUCCESS) { PrintError("RegQueryValueEx (read data)"); delete[] lpData; RegCloseKey(hKey); return 1; } // 解析CM_RESOURCE_LIST结构 DWORD dwResourceCount = *(DWORD*)(lpData + 16); auto pmi = lpData + 24; // 设置输出格式,确保64位十六进制数值完整显示 cout << hex << setfill('0'); for (DWORD dwIndex = 0; dwIndex < dwResourceCount; dwIndex++) { uint64_t start = *(uint64_t*)(pmi + 0); uint64_t length = *(uint64_t*)(pmi + 8); uint64_t endaddr = start + length; cout << "-> 0x" << setw(16) << start << " + 0x" << setw(16) << length << " 0x" << setw(16) << endaddr << endl; pmi += 20; // CM_MEMORY_RESOURCE结构大小:8字节起始地址+8字节长度+4字节标志=20字节 } delete[] lpData; RegCloseKey(hKey); return 0; }
关键修改点说明
替换
RegOpenKey为RegOpenKeyEx:
添加KEY_WOW64_64KEY标志,强制32位程序访问64位注册表视图,这是解决数值截断问题的核心。完善错误处理逻辑:
- 所有Win32 API调用都检查返回值
- 添加
PrintError函数输出具体错误码,方便调试 - 错误发生时确保资源正确释放(关闭注册表键、释放内存)
优化输出格式:
使用setw(16)和setfill('0')确保64位十六进制数值完整显示,避免因高位补零被省略导致的误解。修正错误提示信息:
把错误提示改为对应操作的名称,便于快速定位问题。
额外注意事项
- 运行程序时需要管理员权限:
Hardware下的注册表项需要管理员权限才能读取,否则会返回ERROR_ACCESS_DENIED错误。 - 优先编译为64位程序:如果是64位系统,直接编译为64位程序可以避免注册表视图的兼容问题。
内容的提问来源于stack exchange,提问作者Jenny
相关产品推荐
相关产品推荐

