jord
jord

Reputation: 71

Query registry values

I'm trying to use C++ to query registry values like the following

$ reg query HKLM\SOFTWARE\GitForWindows

HKEY_LOCAL_MACHINE\SOFTWARE\GitForWindows
    CurrentVersion    REG_SZ    2.31.1
    InstallPath    REG_SZ    C:\Program Files\Git
    LibexecPath    REG_SZ    C:\Program Files\Git\mingw64\libexec\git-core

I've found many solutions but I can't seem to get it to work, I think the issue is that i'm using the code incorrectly.

Example 1 from Microsoft documentation

    // get the size of the string
    DWORD dataSize{};
    LONG retCode = ::RegGetValue(
        HKEY_LOCAL_MACHINE,
        L"SOFTWARE", // subKey.c_str(),
        L"GitForWindows", //value.c_str(),
        RRF_RT_REG_SZ,
        nullptr,
        nullptr,
        &dataSize
    );

    if (retCode != ERROR_SUCCESS)
    {
        printf("Error1\n");
        return;
    }

    std::wstring data;
    data.resize(dataSize / sizeof(wchar_t));

    // store the string in data
    retCode = ::RegGetValue(
        HKEY_LOCAL_MACHINE,
        L"SOFTWARE", // subKey.c_str(),
        L"GitForWindows", //value.c_str(),
        RRF_RT_REG_SZ,
        nullptr,
        &data[0],
        &dataSize
    );

    if (retCode != ERROR_SUCCESS)
    {
        printf("Error2\n");
        return;
    }

    printf("%s\n", data[0]);

This gets stuck at Error1

Example 2 from code online

    int BUFFER = 1024;
    char value[255];
    DWORD BufferSize = BUFFER;
    RegGetValue(HKEY_LOCAL_MACHINE, L"SOFTWARE", L"GitForWindows", RRF_RT_ANY, NULL, (PVOID)&value, &BufferSize);
    std::cout << value << std::endl;
    return;

This prints

╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠

The function for RegGetValue is

LONG WINAPI RegGetValue(
  _In_        HKEY    hkey,
  _In_opt_    LPCTSTR lpSubKey,
  _In_opt_    LPCTSTR lpValue,
  _In_opt_    DWORD   dwFlags,
  _Out_opt_   LPDWORD pdwType,
  _Out_opt_   PVOID   pvData,
  _Inout_opt_ LPDWORD pcbData
);

I think the hkey is HKEY_LOCAL_MACHINE, lpSubKey is this SOFTWARE and if lpValue is GitForWindows, if this is correct then how do I access the values inside, e.g. CurrentVersion?

Upvotes: 0

Views: 577

Answers (2)

YangXiaoPo-MSFT
YangXiaoPo-MSFT

Reputation: 2130

According to MSDN:Enumerating Registry Subkeys and RegGetValue, RegGetValue retrieves the type and data for the specified registry value.
Code:

int main()
{
    long ret;
    unsigned long reg_index = 0;

    DWORD dwValSize = MAX_VALUE_NAME;
    DWORD dwDataSize = MAX_VALUE_NAME;
    LPTSTR lpValname = new TCHAR[MAX_VALUE_NAME]{};
    LPTSTR lpDataname = new TCHAR[MAX_VALUE_NAME]{};

    HKEY hkey;
    int result = RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft"), 0, KEY_READ, &hkey);
    if (result == ERROR_SUCCESS) {
        while ((ret = RegEnumValue(hkey, reg_index++, lpValname, &dwValSize, NULL, NULL, NULL, NULL)) != ERROR_NO_MORE_ITEMS)
        {
            if ((ret == ERROR_SUCCESS) || (ret == ERROR_MORE_DATA)) {
                _tprintf(TEXT("(%d) %s"), reg_index, lpValname);
                DWORD type = 0;
                if (RegGetValue(hkey, 0,lpValname, RRF_RT_ANY, &type, lpDataname, &dwDataSize) == ERROR_SUCCESS)
                {
                    _tprintf(TEXT("(Value data %s)\n"), lpDataname);
                }
            }
            dwValSize = MAX_VALUE_NAME;
            dwDataSize = MAX_VALUE_NAME;
            ZeroMemory(lpDataname,sizeof(TCHAR)* dwDataSize);
            ZeroMemory(lpValname,sizeof(TCHAR)* dwValSize);
        }
        //ErrorExit(TEXT("RegEnumValue"));
        RegCloseKey(hkey);
    }
    return TRUE;
}

Upvotes: 1

jord
jord

Reputation: 71

I've figured out how to query the registry now, although i'm still not printing values succesfully. There were many different issues with the original code.

To query the registry i first had to use RegOpenKeyEx and then query the values individually with RegEnumValue, finally close the key handle with RegCloseKey.

There was another issue with the RRF_RT_ANY type values, explained more RegOpenKeyEx returning error code 2

I'm not printing the values correctly yet but when running the while loop for RegEnumValue it iterates n times for registry values with n keys so i'm fairly confident that should be working correctly.

int main()
{
    long ret;
    unsigned long reg_index = 0;
    unsigned long len_key;
    unsigned long len_val;
    unsigned long type;
    LPWSTR* reg_key;
    LPBYTE* reg_val;

    DWORD dwValSize = 50;
    LONG regret;
    LPTSTR lpValname = new TCHAR[50];

    HKEY hkey;
    int result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\GitForWindows", 0, KEY_READ | KEY_WOW64_64KEY, &hkey);
    if (result == ERROR_SUCCESS) {
        std::cout << "opened key\n";
        while (ret = RegEnumValue(hkey, reg_index++, lpValname, &dwValSize, NULL, NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS)
        {
            std::cout << "Read item\n";
            if ((ret == ERROR_SUCCESS) || (ret == ERROR_MORE_DATA)) {
                std::cout << lpValname[0];
            }
        }
        RegCloseKey(hkey);
    }
}

Some resources i found helpful

Upvotes: 0

Related Questions