Search code examples
c#c++registry

Reading a string value from from registry gives some junk character


I am using the following code to read a value from registry. The value is written to registry by a C++ application. The problem I am facing is that, value read from C# application has some termination junk character. If I write the string manually to registry, the value read in C# is correct.

string strPath = "SOFTWARE\\SUKHAS\\TEST\\";
string strName = "ActiveLayoutName";

try
{
    using (RegistryKey regKeyExt = Registry.CurrentUser.OpenSubKey(strPath))
    {
        if (regKeyExt != null)
        {
            string strLayoutName = "";
            object obj = regKeyExt.GetValue(strName, strLayoutName);

            LayoutName = obj as string;
         }
    }
}
catch (Exception ex)
{
}

The main C++ code which writes the value to registry.

DWORD len = (DWORD)( (_tcslen(lNewValue) * sizeof(TCHAR)) + 1 );
//Does this cause problem? +1? if I remove the +1, I am not getting the junk character in C# application.

result = RegSetValueEx(hResultKey, lpRegSzName, 0, REG_SZ, (LPBYTE)lNewValue, len);

RegCloseKey(hResultKey);

Any clue? Is this because of this +1 in the length which is causing the problem?

As per documentation of RegSetValueEx,

The size of the information pointed to by the lpData parameter, in bytes. If the data is of type REG_SZ, REG_EXPAND_SZ, or REG_MULTI_SZ, cbData must include the size of the terminating null character or characters.

I am not sure what is causing the problem.


Solution

  • _tcslen returns the number of characters in the string, so if TCHAR is defined as wchar_t (i.e. being used with UNICODE), then the length calculation needs one whole wchar_t (for the NUL) to get the length correct (counting in the terminating null).

    DWORD len = static_cast<DWORD>( (_tcslen(lNewValue)+1) * sizeof(TCHAR) );
    //                                                 ^^ add 1 for the wchar_t NUL