【问题标题】:RegEnumKeyExW not return all name sub-keysRegEnumKeyExW 不返回所有名称子键
【发布时间】:2018-11-23 07:35:47
【问题描述】:

我想枚举键名。但。这里有什么问题吗。它不会返回所有名称。我检查子键它返回 12 个总键。在 RegEnumKeyExW 中循环时,它只返回 3 个名称而不是 12 个名称。它只返回 1,2 和 5 名称键

HKEY_CURRENT_USER 键中。有 12 键。

  1. 应用事件

  2. 控制台

  3. 控制面板

  4. 环境

  5. EUDC

  6. 身份

  7. 键盘布局

  8. 网络

  9. 打印机

  10. 软件

  11. 系统

  12. 易变环境

这是代码

HKEY hKey;
    if (RegOpenKeyExW(HKEY_CURRENT_USER, NULL, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
    {
        DWORD subKeys;
        FILETIME ftLastWriteTime;
        if (RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &subKeys, NULL, NULL, NULL, NULL, NULL, NULL, &ftLastWriteTime) == ERROR_SUCCESS)
        {
            wchar_t keyName[MAX_KEY_LENGTH];
            DWORD cbName;
            for (DWORD i = 0; i < subKeys; i++)
            {
                if (RegEnumKeyExW(hKey, i, keyName, &cbName, NULL, NULL, NULL, &ftLastWriteTime) == ERROR_SUCCESS)
                {
                        std::wcout << keyName << std::endl;
                }
                else
                {
                    std::cout << GetLastError() << std::endl;
                }
            }
        }
        else
        {
            std::cout << GetLastError() << std::endl;
        }
    }
    else
    {
        std::cout << GetLastError() << std::endl;
    }

【问题讨论】:

  • 尝试以较少的权限打开密钥,RegEnumKeyExW 只需要KEY_ENUMERATE_SUB_KEYS。您无需先调用RegQueryInfoKeyW,只需循环直到RegEnumKeyExW 失败。
  • 起初 Reg api 未设置 GetLastError() 但返回错误代码。第二 - 您在调用 RegEnumKeyExW 时未初始化 cbName 的错误。这是in-out 参数,在调用之前必须指定lpName 参数指定的缓冲区大小,以字符为单位。所以在你的代码中必须是&amp;(cbName = RTL_NUMBER_OF(keyName))
  • 当 API 函数的行为不符合预期时,您必须重新阅读文档。您将看到的其中一件事是如何为此函数执行错误处理,实际上是所有注册表 api 函数。
  • 修复:DWORD cbName = MAX_KEY_LENGTH;现在它对于第一个子键是偶然的,并且只有在名称较短时才能再次起作用。所以确实是 1、2 和 5。

标签: c++ windows visual-studio winapi


【解决方案1】:

正如@Hans Passant 所说,您应该重置cbName 的长度,但实际上不是MAX_KEY_LENGTH。如果 buff 长度不足以容纳键名,RegEnumKeyExW 将失败。在上面RegQueryInfoKeyW中添加参数,获取子键名的最大长度:

DWORD cbMaxSubKeyLen;
if (RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &subKeys, &cbMaxSubKeyLen, NULL, NULL, NULL, NULL, NULL, &ftLastWriteTime) == ERROR_SUCCESS)

然后在for循环中,重置cbName = cbMaxSubKeyLen;

【讨论】:

  • 可以查询大小。但是,重新分配 keyName 以使其足够大也非常非常重要。缓冲区溢出是一个非常讨厌的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-15
  • 2012-08-14
  • 2019-06-03
  • 1970-01-01
  • 2013-07-13
  • 2021-09-03
  • 1970-01-01
相关资源
最近更新 更多