You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

读取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;
}

关键修改点说明

  1. 替换RegOpenKey为RegOpenKeyEx:
    添加KEY_WOW64_64KEY标志,强制32位程序访问64位注册表视图,这是解决数值截断问题的核心。

  2. 完善错误处理逻辑:

    • 所有Win32 API调用都检查返回值
    • 添加PrintError函数输出具体错误码,方便调试
    • 错误发生时确保资源正确释放(关闭注册表键、释放内存)
  3. 优化输出格式:
    使用setw(16)和setfill('0')确保64位十六进制数值完整显示,避免因高位补零被省略导致的误解。

  4. 修正错误提示信息:
    把错误提示改为对应操作的名称,便于快速定位问题。

额外注意事项

  • 运行程序时需要管理员权限:Hardware下的注册表项需要管理员权限才能读取,否则会返回ERROR_ACCESS_DENIED错误。
  • 优先编译为64位程序:如果是64位系统,直接编译为64位程序可以避免注册表视图的兼容问题。

内容的提问来源于stack exchange,提问作者Jenny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:56:11