C RegEnumKeyExA 接收 ERROR_MORE_DATA 的问题

标签 c registry

在 C 领域工作几年后,我试图再次进入 C 领域。抱歉问这个问题,这对你们中的一些人来说可能很容易。

我试图理解为什么下面的代码会为 RegEnumKeyExA 的返回值提供 234 错误代码 (ERROR_MORE_DATA)。

LONG lRValue;
    DWORD dwIndex = 0;
    DWORD dwKeyNameLength;
    DWORD subKeysCount;
    HKEY hOpenKey;
    TCHAR *keyName = TEXT("Software");

    lRValue = RegOpenKeyExA(HKEY_CURRENT_USER, keyName, 0, KEY_ALL_ACCESS, &hOpenKey);

    if (lRValue == ERROR_SUCCESS) {
        printf("<<<< Key opened successfully. >>>>\n");
    } else {
        printf("---- Error detected! ----");
        exit(EXIT_FAILURE);
    }

    lRValue = RegQueryInfoKeyA(hOpenKey, NULL, NULL, NULL, &subKeysCount, &dwKeyNameLength, NULL, NULL, NULL, NULL, NULL, NULL);

    if (lRValue == ERROR_SUCCESS) {
        printf("<<<< Key queried successfully. >>>>\n");
        printf("KeyNameLength: %i\n", dwKeyNameLength);
        printf("SubKeyCount: %i\n", subKeysCount);
    } else {
        printf("---- Error detected! ----");
        exit(EXIT_FAILURE);
    }

    TCHAR lpName[dwKeyNameLength];

    for(int i = 0; i < subKeysCount; i++) {
        int lrValue = RegEnumKeyExA(hOpenKey, dwIndex, lpName, &dwKeyNameLength, NULL, NULL, NULL, NULL);
        if (lrValue != ERROR_SUCCESS) {
            printf("Error in: %i\n", lrValue);
        }
        printf("%s\n", lpName);
        dwIndex++;
    }

    printf("%i\n", dwIndex);
    printf("<<<< Job completed! >>>>");

我担心它与缓冲区大小有关,但我认为我通过执行 RegQueryInfo 正确识别了它。上面的代码肯定性能不是很好,但这不应该是主题。

有人有什么想法吗? :)

谢谢。 :)

最佳答案

问题

问题出在这一行:

int lrValue = RegEnumKeyExA(hOpenKey, dwIndex, lpName, &dwKeyNameLength, NULL, NULL, NULL, NULL);

这里您提供长度的地址作为参数 4 (&dwKeyNameLength)。第一次调用后,它显示为 Adobe然后值为 5。因此,如果下一个 lpName 条目较长(很可能),它将不起作用。

您还必须注意终止 NULL 字符。微软在文档中写道:

A pointer to a variable that specifies the size of the buffer specified by the lpName parameter, in characters. This size should include the terminating null character. If the function succeeds, the variable pointed to by lpcName contains the number of characters stored in the buffer, not including the terminating null character.

请参阅此处:https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regenumkeyexa

因此最大值必须是 dwKeyNameLength + 1。

因此,要解决这两个问题,只需将循环中的值设置为最大值加 1 作为终止 NULL。

其他

  • KEY_ALL_ACCESS不是必需的,KEY_READ用于枚举足够的

  • WINAPI 调用有两种变体:带后缀 A(单字符版本)和后缀 W(宽字符版本)。最好在没有后缀的情况下使用它,并根据项目的 Unicode 设置自动选择正确的版本。

  • 您的代码末尾缺少 RegCloseKey

  • 为了避免有符号/无符号不匹配,应该将变量设置为 i DWORD 类型

完整示例

这里您问题中的代码仅稍作修改。注意:对于 lpName 的动态内存分配,我们需要为终止 NULL 添加 1,如上所述。

另请看一下这一行:

DWORD cchName = dwKeyNameLength + 1;

在循环内,该值始终重置为该缓冲区大小。

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

void enumerate();

void __cdecl _tmain(void) {
    enumerate();
}

void enumerate()
{
    DWORD lRValue;
    DWORD dwKeyNameLength;
    DWORD subKeysCount;
    HKEY hOpenKey;
    TCHAR* keyName = _T("Software");

    lRValue = RegOpenKeyEx(HKEY_CURRENT_USER, keyName, 0, KEY_READ, &hOpenKey);

    if (lRValue == ERROR_SUCCESS) {
        _tprintf(_T("<<<< Key opened successfully. >>>>\n"));
    }
    else {
        _tprintf(_T("---- Error detected! ----"));
        exit(EXIT_FAILURE);
    }

    lRValue = RegQueryInfoKey(hOpenKey, NULL, NULL, NULL, &subKeysCount, &dwKeyNameLength, NULL, NULL, NULL, NULL, NULL, NULL);

    if (lRValue == ERROR_SUCCESS) {
        _tprintf(_T("<<<< Key queried successfully. >>>>\n"));
        _tprintf(_T("KeyNameLength: %i\n"), dwKeyNameLength);
        _tprintf(_T("SubKeyCount: %i\n"), subKeysCount);
    }
    else {
        _tprintf(_T("---- Error detected! ----"));
        exit(EXIT_FAILURE);
    }

    TCHAR *lpName = malloc((dwKeyNameLength + 1) * sizeof(TCHAR));

    for(DWORD i = 0; i < subKeysCount; i++) {
        DWORD cchName = dwKeyNameLength + 1;
        lRValue = RegEnumKeyEx(hOpenKey, i, lpName, &cchName, NULL, NULL, NULL, NULL);
        if (lRValue != ERROR_SUCCESS) {
            _tprintf(_T("Error at index: %d\n"), i);
        } else {
            _tprintf(_T("%s (%d)\n"), lpName, cchName);
        }
    }

    free(lpName);
    RegCloseKey(hOpenKey);

    _tprintf(_T("<<<< Job completed! >>>>"));
}

关于C RegEnumKeyExA 接收 ERROR_MORE_DATA 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57442447/

相关文章:

windows - 使用 PowerShell 从注册表项中检索信息

c++ - 使用 libjpeg 提供自定义文件 IO

c - 第一次 dlopen 后共享库函数可以正常工作

c - gcc 将自动调整结构大小

c - 为什么 memcmp 比 for 循环检查快得多?

docker - 从/插入 Nexus 3 Docker-Registry 时出现 MissingBlobException

registry - NSIS:什么是注册表?

Docker 注册表 : Limit access by account to subset of images

python - Python 中的 Defacto 模板应用程序

c++ - 当注册表中不存在 CLSID 时如何查找 DLL