Search code examples
c++cwindowswinapiregistry

HKEY handle is NULL, during debug it writes unused <unable to read memory>


I have defined HKEY in anonymous namespace to use it in more cpp. I create register key and it normally returns HKEY, then I want to use that handle in another cpp, and it is NULL. When I debug, it writes unused .

this is one .h file (structAndHandle.h)

namespace
{
StCommand command;
HANDLE dataInEvent;
HANDLE dataOutEvent;
HANDLE threadHandle;
HANDLE mutexHandle;
HKEY hKey;
TCHAR repositoryPath[MAX_PATH];
}

here I create it... (repositoryStore.cpp)

if (RegCreateKeyEx(HKEY_CURRENT_USER, STR_KEY_NAME, 0L, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL)
    != ERROR_SUCCESS)
{
    _tprintf_s(_T("Could not create or open register key: %s\n"), STR_KEY_NAME);
}

TCHAR pathValueName[MAX_PATH] = _T("repositoryPath");
TCHAR indexValueName[MAX_PATH] = _T("repositoryIndex");

TCHAR repPath[MAX_PATH] = _T("C:\\repository\0");
if (RegSetValueEx(hKey, pathValueName, 0L, REG_SZ, (LPBYTE)repPath, _tcslen(repPath) * sizeof(TCHAR))
    != ERROR_SUCCESS)
{
    _tprintf_s(_T("Could not create or set register value: %s\n"), repPath);
}

DWORD repositoryIndex = 0;
if (RegSetValueEx(hKey, indexValueName, 0L, REG_DWORD, (LPBYTE)&repositoryIndex, sizeof(DWORD))
    != ERROR_SUCCESS)
{
    _tprintf_s(_T("Could not create or set register value: repositoryIndex\n"));
}

and when I want to use it here, in another cpp, it is NULL (settings.cpp)

DWORD GetDwordSetting(TCHAR* valueName, DWORD defaultValueData)
{
DWORD receivedData;
DWORD type = REG_DWORD;
DWORD size = sizeof(DWORD);
if (RegQueryValueEx(hKey, valueName, 0L, &type, (LPBYTE)&receivedData, &size)
    != ERROR_SUCCESS)
{
    _tprintf_s(_T("Could not get register value: repositoryIndex\n"));
    return defaultValueData;
}
return receivedData;
}

DWORD SetDwordSetting(TCHAR* valueName, DWORD valueData)
{
if (RegSetValueEx(hKey, valueName, 0L, REG_DWORD, (LPBYTE)&valueData, sizeof(DWORD))
    != ERROR_SUCCESS)
{
    _tprintf_s(_T("Could not set register value: repositoryIndex\n"));
    return GetLastError();
}
return 0;
}

DWORD GetSzSetting(TCHAR* valueName, TCHAR* defaultValueData)
{
DWORD type = REG_SZ;
DWORD size = sizeof(TCHAR) * sizeof(MAX_PATH);
if (RegQueryValueEx(hKey, valueName, 0L, &type, (LPBYTE)&repositoryPath, &size)
    != ERROR_SUCCESS)
{
    _tcscpy_s(repositoryPath, defaultValueData);
    _tprintf_s(_T("Could not get register value: repositoryPath\n"));
    return GetLastError();
}
return 0;
}

Solution

  • Instead of placing your handles in an unnamed namespace put them in a singleton class, that multiple .cpp files can access the same instance:

    class AllMyHandles {
    public:
        static AllMyHandles& instance() {
             static AllMyHandles theInstance;
             return theInstance;
        }
    
        // provide getter setter methods for these handles
    
    private:
        StCommand command;
        HANDLE dataInEvent;
        HANDLE dataOutEvent;
        HANDLE threadHandle;
        HANDLE mutexHandle;
        HKEY hKey;
        TCHAR repositoryPath[MAX_PATH];
    
        AllMyHandles() {}    
    };
    

    Another way, is to have a simple class/struct (without the instance() function), and to pass instances of these around as reference parameters.