c++mbcs

Read registry value 32 bit?


I have the following code that compiles for MBCS.

CString GetRegistry(LPCTSTR pszValueName)
{
    // Try open registry key
    HKEY hKey = NULL;
    LPCTSTR pszSubkey = _T("SOFTWARE\\Wow6432Node\\PAX");
    if ( RegOpenKey(HKEY_LOCAL_MACHINE, pszSubkey, &hKey) != ERROR_SUCCESS )
    {
        // Error:
        // throw an exception or something...
        //
        // (In production code a custom C++ exception 
        // derived from std::runtime_error could be used)
        AtlThrowLastWin32();
    }

    // Buffer to store string read from registry
    TCHAR szValue[1024];
    DWORD cbValueLength = sizeof(szValue);

    // Query string value
    if ( RegQueryValueEx(
            hKey,
            pszValueName, 
            NULL, 
            NULL, 
            reinterpret_cast<LPBYTE>(&szValue), 
            &cbValueLength) 
         != ERROR_SUCCESS )
    {
        // Error
        // throw an exception or something...
        AtlThrowLastWin32();
    }

    // Create a CString from the value buffer
    return CString(szValue);
}

Solution

  • You need to use RegOpenKeyEx() with the KEY_WOW64_32KEY flag and let it handle the Wow6432 node for you, eg:

    CString GetRegistry(LPCTSTR pszValueName)
    {
        // WOW64 access
        REGSAM Wow64Flag;
        #ifdef _WIN64
        Wow64Flag = KEY_WOW64_32KEY;
        #else
        Wow64Flag = 0;
        #endif
    
        // Try open registry key
        HKEY hKey = NULL;
    
        LONG lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\PAX"), 0, KEY_QUERY_VALUE | Wow64Flag, &hKey);
        if ( lResult != ERROR_SUCCESS )
        {
            // Error:
            // throw an exception or something...
            //
            // (In production code a custom C++ exception 
            // derived from std::runtime_error could be used)
            SetLastError(lResult);
            AtlThrowLastWin32();
        }
    
        DWORD cbValueLength;
    
        // Query string value size
        lResult = RegQueryValueEx(
                hKey,
                pszValueName, 
                NULL, 
                NULL, 
                NULL, 
                &cbValueLength) 
             != ERROR_SUCCESS )
        {
            // Error
            RegCloseKey(hKey);
            // throw an exception or something...
            SetLastError(lResult);
            AtlThrowLastWin32();
        }
    
        // Buffer to return string read from registry
        CString sValue;
    
        if ( cbValueLength > 0 )
        {
            // Buffer to store string read from registry
            std::vector<TCHAR> szValue((cbValueLength / sizeof(TCHAR))+1);
    
            lResult = RegQueryValueEx(
                    hKey,
                    pszValueName, 
                    NULL, 
                    NULL, 
                    reinterpret_cast<LPBYTE>(&szValue[0]), 
                    &cbValueLength) 
                 != ERROR_SUCCESS )
            {
                // Error
                RegCloseKey(hKey);
                // throw an exception or something...
                SetLastError(lResult);
                AtlThrowLastWin32();
            }
    
            szValue[cbValueLength / sizeof(TCHAR)] = 0;
            sValue = &szValue[0];
        }
    
        RegCloseKey(hKey);
    
        return sValue;
    }
    

    When a 64bit process specifies KEY_WOW64_32KEY, or a 32bit process does not specify any WOW64 flag, it will be accessing the 32bit Registry, and thus SOFTWARE\PAX will resolve to SOFTWARE\Wow6432Node\PAX on a 64bit system.