通过 RegQueryValueEx 和 RegGetValue 获取注册表值时的奇怪行为 [重复]

Posted

技术标签:

【中文标题】通过 RegQueryValueEx 和 RegGetValue 获取注册表值时的奇怪行为 [重复]【英文标题】:Weird behavior when getting registry value via RegQueryValueEx and RegGetValue [duplicate] 【发布时间】:2016-07-21 01:33:02 【问题描述】:

我在使用上述函数的 c++ 中遇到了一些问题。两者的行为方式完全相同。这是我看到的过程:

    运行代码以获取注册表值。仔细检查它是否找到了 10000,它应该有(10000 是每个进程的 GDI 对象的默认窗口限制),并且确实如此。

    使用 regedit 将注册表更改为 10000 以外的值

    再次运行代码,但这次它再次找到 10000,而它本应找到新值。

无论我尝试什么,它总是只会找到原始值而不是 注册表的更新值。

我注意到/尝试过的事情:

    它对我查看过的每个值都执行此操作,而不仅仅是 GDIProcessHandleQuota。 (它并不总是返回 10000,因为它特定于 GDI 值,它总是返回任何给定值的修改前值)

    即使我重新启动计算机并打开 regedit 以验证密钥,它也会这样做 在运行第 3 步之前实际已更改。

    以下代码中的所有结果值(results、results2、results3)均为 0,表示 ERROR_SUCCESS (lol),表示它们没有遇到任何问题。

最后,这是我遇到问题的代码 sn-p:

HKEY hKey;

//open the key for viewing in RegQueryValueEx, store opened handle in hkey
LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
    "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows",
        0,
        KEY_ALL_ACCESS,
        &hKey);


DWORD dwReturn;
DWORD dwBufSize = sizeof(DWORD);

//after this line executes, dwReturn should have the DWORD data of the specified registry key/valuename
LONG result2 = RegQueryValueEx(hKey,
    "GDIProcessHandleQuota",
    0,
    0, 
    reinterpret_cast<LPBYTE>(&dwReturn), 
    &dwBufSize);

DWORD value;
DWORD size = sizeof(DWORD);


//after this executes, value should contain the DWORD data of the specified  registry key/valuename
LONG result3 = RegGetValue(hKey,
    "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows",
    "GDIProcessHandleQuota",
    RRF_RT_ANY,
    NULL,
    &value,
    &size
    );

【问题讨论】:

你是如何编译你的程序的——32位还是64位?如果是 32 位,您的程序实际上是在 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows @The Dark 它正在被编译为 Win32。即使它被告知我明确给出的路径,该位置是否正确? 对不起 - 我在你输入的时候编辑了我的评论 - 检查 Wow6432Node 键 有没有办法强制程序查看其他位置?为什么首先有2个位置?哪个是键的“正确”值? (也就是我应该看哪一个) 这里有一种读取其他位置的方法:***.com/questions/11808462/… - 它是 c#,但想法是一样的。有两个位置可以将 32 位和 64 应用程序分开,所以我想作为 32 位应用程序,您应该不理会它并从 Wow6432Node 键中读取。或者,您可以更改为 64 位应用程序。 【参考方案1】:

在 64 位机器上运行 32 位应用程序时,您的问题很可能是由 WOW64 模拟器引起的。有关详细信息,请参阅 MSDN 文档:

Registry Redirector

Registry Keys Affected by WOW64

32-bit and 64-bit Application Data in the Registry

Accessing an Alternate Registry View

要在 32 位应用程序中打开 64 位密钥,您需要在使用 RegOpenKeyEx() 打开密钥时包含 KEY_WOW64_64KEY 标志,或者在使用 RegGetValue() 打开密钥时包含 RRF_SUBKEY_WOW6464KEY 标志。

您还打开了具有太多权限的密钥(这可能会在 UAC 下启动 Registry Virtualization,但在此示例中您正在访问的特定密钥上禁用了此功能,但您应该注意这一点)。 KEY_ALL_ACCESS 仅适用于管理员用户。大多数用户对 HKLM 没有写访问权限,只有只读访问权限,因此非管理员使用 KEY_ALL_ACCESS 打开密钥将失败。始终请求您实际需要的最低权限。在这种情况下,打开KEY_QUERY_VALUE 访问的密钥。

您还使用错误的参数值调用RegGetValue()

试试类似的方法:

HKEY hKey;

//open the key for viewing in RegQueryValueEx, store opened handle in hkey
LONG result = RegOpenKeyEx(
    HKEY_LOCAL_MACHINE,
    "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows",
    0,
    KEY_QUERY_VALUE | KEY_WOW64_64KEY,
    &hKey);

if (result != ERROR_SUCCESS)

    ...

else

    DWORD value;
    DWORD size = sizeof(DWORD);

    //after this line executes, value should have the DWORD data of the specified registry key/valuename
    result = RegQueryValueEx(
        hKey,
        "GDIProcessHandleQuota",
        0,
        0, 
        reinterpret_cast<LPBYTE>(&value), 
        &size);

    if (result != ERROR_SUCCESS)
    
        ...
    

    size = sizeof(DWORD);

    //after this executes, value should contain the DWORD data of the specified registry key/valuename
    result = RegGetValue(
        hKey,
        NULL,
        "GDIProcessHandleQuota",
        RRF_RT_REG_DWORD,
        NULL,
        &value,
        &size);

    if (result != ERROR_SUCCESS)
    
        ...
    

    RegCloseKey(hKey);

或者:

DWORD value;
DWORD size = sizeof(DWORD);

//after this executes, value should contain the DWORD data of the specified registry key/valuename
LONG result = RegGetValue(
    HKEY_LOCAL_MACHINE,
    "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows",
    "GDIProcessHandleQuota",
    RRF_RT_REG_DWORD | RRF_SUBKEY_WOW6464KEY,
    NULL,
    &value,
    &size);

if (result != ERROR_SUCCESS)

    ...

【讨论】:

以上是关于通过 RegQueryValueEx 和 RegGetValue 获取注册表值时的奇怪行为 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

RegQueryValueEx正确使用方法

从 RegQueryValueEx 获取正确的值

RegQueryValueEx 返回 ERROR_SUCCESS 但它没有给我数据缓冲区。为啥?

使用RegQueryValueEx作为可能为REG_DWORD或REG_SZ的注册表值

RegQueryValueEx 的奇怪行为与另一个寄存器的返回值有关

将 RegQueryValueEx 用于可能是 REG_DWORD 或 REG_SZ 的注册表值