Search code examples
c++registryc++builderregedit

Read a registry value correctly with the type reg_binary c++


My problem is that, I can't retrieve a Registry value correctly in a hex format, converting it to a string so it appears this way in my ListBox (image 1), I know how to do it correctly in C#, but I'm new to C++.

String ks;
DWORD reg2()
{


        char value[255];

        DWORD BufferSize = BUFFER;

        RegGetValue(HKEY_CURRENT_USER, namebuf, "415846243", RRF_RT_ANY, NULL, (PVOID)&value, &BufferSize);

        std::wstringstream box_messages;
        box_messages << value;
        ks = box_messages.str().c_str();

}

void __fastcall TAAP_Test::Button1Click(TObject *Sender)
{
     ListBox1->Items->Add(ks);
}

This image shows the result on my program:

image

This image shows what registry value I'm trying to retrieve:

image


Solution

  • The Registry value you are reading is in a raw binary format (REG_BINARY). What you see in the Registry Editor is not the raw data itself, but a human-readable hex representation of the data. RegGetValueA() will not return that hex representation to you, it will return the raw binary data instead.

    You are reading the raw data fine (minus the lack of error checking), but you are trying to write it as-is to your std::wstringstream, which is why you get the weird result you see in your ListBox. You need to instead loop through the individual bytes of the data, encoding each byte to a hex representation that is then put in to your std::wstringstream, eg:

    #include <iostream>
    #include <iomanip>
    
    void reg2()
    {
        char value[255];
        DWORD BufferSize = sizeof(value);
    
        if (RegGetValueA(HKEY_CURRENT_USER, namebuf, "415846243", RRF_RT_ANY, NULL, value, &BufferSize) == ERROR_SUCCESS)
        {
            std::wstringstream box_messages;
            for(DWORD i = 0; i < BufferSize; ++i) {
                box_messages << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(value[i]) << L" ";
            }
            ks = box_messages.str().c_str();
        }
        else
            ks = _D("error");
    }
    

    Alternatively, the RTL has an IntToHex() function available:

    #include <System.SysUtils.hpp>
    
    void reg2()
    {
        char value[255];
        DWORD BufferSize = sizeof(value);
    
        if (RegGetValueA(HKEY_CURRENT_USER, namebuf, "415846243", RRF_RT_ANY, NULL, value, &BufferSize) == ERROR_SUCCESS)
        {
            std::wstringstream box_messages;
            for(DWORD i = 0; i < BufferSize; ++i) {
                box_messages << IntToHex(static_cast<int>(value[i]), 2).c_str() << _D(" ");
            }
            ks = box_messages.str().c_str();
    
            /* or simpler:
            ks = _D("");
            for(DWORD i = 0; i < BufferSize; ++i) {
                ks += (IntToHex(static_cast<int>(value[i]), 2) + _D(" "));
            }
            */
        }
        else
            ks = _D("error");
    }
    

    Alternatively, UnicodeString has a cat_sprintf() method available:

    void reg2()
    {
        char value[255];
        DWORD BufferSize = sizeof(value);
    
        if (RegGetValueA(HKEY_CURRENT_USER, namebuf, "415846243", RRF_RT_ANY, NULL, value, &BufferSize) == ERROR_SUCCESS)
        {
            ks = _D("");
            for(DWORD i = 0; i < BufferSize; ++i) {
                ks.cat_sprintf(_D("%02X "), static_cast<int>(value[i]));
            }
        }
        else
            ks = _D("error");
    }