Search code examples
winapiregistry

Difficulty using the Win32 API for reading and writing a registry profile value


I have a simple Win32 (no MFC) app, and on startup (in WinMain) it calls:

int location = (char)GetProfileInt(L"Foo", L"location", 0);
// location is an enumeration and 0 is the harmless default

and on close:

case WM_CLOSE:
{
   wchar_t buffer[50];
   buffer[0] = 0x00;
   _itow_s(location, buffer, 50, 10);
   BOOL result = WriteProfileString(L"Foo", L"location", buffer);
   if(!result)
   {
      DWORD foo = ::GetLastError();
      foo++; // do something with foo to keep the compiler from complaining
   }
}
break;

The WriteProfileString() call returns FALSE and GetLastError() returns ERROR_ACCESS_DENIED (5).

When I open the Registry Editor, it finds the value, but the Data field is empty...

I don't make any other registry-related calls besides GetProfileInt() and WriteProfileString().

What mistake am I making? I didn't have trouble like this when I worked on an MFC project. Probably because MFC was doing some special steps that I am missing.

MSDN did not give me much help. There was no comment like "If you get ERROR_ACCESS_DENIED then you probably didn't open or init [thing] first".


Solution

  • The (Read|Write)Profile...() functions do not operate on the Registry by default. Unless there is an explicit INI-to-Registry mapping defined in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\IniFileMapping Registry key, the functions will instead operate on the win.ini file in the Windows install directory, which you likely don't have write access to, hence the error on writing but not on reading.

    To operate with Registry values, you should be using the Registry API instead, such as via the Reg(Open|Create)KeyEx() and Reg(Query|Set)ValueEx() functions, eg:

    int location = 0;
    HKEY hKey = NULL;
    LSTATUS result = RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Software\\Foo"), 0, KEY_QUERY_VALUE, &hKey);
    if (result == ERROR_SUCCESS) {
        DWORD dwSize = sizeof(location);
        result = RegQueryValueEx(hKey, TEXT("location"), NULL, NULL, (LPBYTE)&location, &dwSize);
        RegCloseKey(hKey);
    }
    
    case WM_CLOSE:
    {
        HKEY hKey = NULL;
        LSTATUS result = RegCreateKeyEx(HKEY_CURRENT_USER, TEXT("Software\\Foo"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL);
        if (result == ERROR_SUCCESS) {
            result = RegSetValueEx(hKey, TEXT("location"), 0, REG_DWORD, (LPBYTE)&location, sizeof(location));
            RegCloseKey(hKey);
        }
    
        /* alternatively:
        LSTATUS result = RegSetKeyValue(HKEY_CURRENT_USER, TEXT("Software\\Foo"), TEXT("location"), REG_DWORD, &location, sizeof(location));
        */
    }
    break;