0

How do you read all the data in a registry key

    void get_reg_value(HKEY handle ,  std::string value_to_read)
    {
        
        char value[2048];
        DWORD BufferSize = 8192;
        
        LONG errorcode = RegGetValueA(handle, NULL, value_to_read.c_str(), RRF_RT_REG_MULTI_SZ, NULL, (PVOID)&value, &BufferSize);
        wprintf(L"Value data: %s\n", (PWSTR)value);


    }

The key to read is HARDWARE\\DESCRIPTION\\System and the subkey is SystemBiosVersion which has the value

ALASKA - 1072009
F6
American Megatrends - 5000C

but I only get

Value data: ALASKA - 1072009
RAT
  • 31
  • 5
  • 1
    MULTI_SZ is a NULL-terminated list of NULL-terminated strings. See [this answer](https://stackoverflow.com/a/6685134/179634). – Luke Feb 09 '22 at 11:46
  • 1
    From [registry value types](https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-value-types): *"`REG_MULTI_SZ`: A sequence of null-terminated strings, terminated by an empty string (\0)."* The documentation for [`RegGetValue`](https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-reggetvaluew) has more information on how this data type is returned. – IInspectable Feb 09 '22 at 11:47

1 Answers1

0

First off, you are passing in the wrong BufferSize value to RegGetValueA(). You are claiming that you have allocated 8KB of memory, but you have actually allocated only 2KB. If the Registry data exceeds 2KB, you will overflow your buffer and corrupt memory. NEVER lie about your buffer sizes.

Also, you are trying to print out a narrow ANSI string as-if it were a wide Unicode string, which it is not, so that is also wrong.

That being said, a REG_MULTI_SZ value is a null-terminated list of multiple null-terminated strings. You are printing out only the 1st string in the list. You need to loop through the whole list until you encounter the final null terminator, eg:

void get_reg_value(HKEY handle, std::string value_to_read)
{
    char Buffer[2048];
    DWORD BufferSize = sizeof(Buffer);
        
    LONG errorcode = RegGetValueA(handle, NULL, value_to_read.c_str(), RRF_RT_REG_MULTI_SZ, NULL, Buffer, &BufferSize);
    if (errorcode == ERROR_SUCCESS) {
        char *value = Buffer;
        while (*value != '\0') {
            printf("Value data: %s\n", value);
            value += (strlen(value) + 1);
        }
    }
    else {
        printf("Error: %ld\n", errorcode);
    }
}

Alternatively, if needed, consider using a dynamically allocated buffer, so can handle data values greater than 2KB:

void get_reg_value(HKEY handle, std::string value_to_read)
{
    std::vector<char> Buffer(2048);
    DWORD BufferSize = Buffer.size();
        
    LONG errorcode;
    do {
        errorcode = RegGetValueA(handle, NULL, value_to_read.c_str(), RRF_RT_REG_MULTI_SZ, NULL, Buffer, &BufferSize);
        if (errorcode != ERROR_MORE_DATA) break;
        Buffer.resize(BufferSize);
    }
    while (true);

    if (errorcode == ERROR_SUCCESS) {
        char *value = Buffer.data();
        while (*value != '\0') {
            printf("Value data: %s\n", value);
            value += (strlen(value) + 1);
        }
    }
    else {
        printf("Error: %ld\n", errorcode);
    }
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770