BobBobby
BobBobby

Reputation: 1

Windows registry returning incorrect value C++

The below code can correctly read Registry values from various different keys, however whenever I try to read a value from a key under Winlogon it will either come up as "not found" or it will return a completely wrong value. The code is ran as admin, and compiled with Visual Studio 2017.

HKEY registryHandle = NULL;
int registryResult = NULL;

DWORD dataType;
TCHAR dataBuffer[1024] = {};
DWORD bufferSize = sizeof(dataBuffer);

registryResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", 0, KEY_QUERY_VALUE, &registryHandle);
if (registryResult != ERROR_SUCCESS) {
    std::cout << "Error: " << registryResult << std::endl;
    return false;
}

registryResult = RegQueryValueEx(registryHandle, L"LastUsedUsername", NULL, NULL, (LPBYTE)dataBuffer, &bufferSize);
if (registryResult != ERROR_SUCCESS) {
    std::cout << "Error2: " << registryResult << std::endl;
    return false;
}

std::cout << "Data Size: " << bufferSize << std::endl;
for (int i = 0; i < 256; i++) {
    if (dataBuffer[i] == NULL) { break; }
    std::cout << (char)dataBuffer[i];
}
std::cin.get();
RegCloseKey(registryHandle);    

Registry value that I'm trying to read:

image

image

Below refers to Remy's suggested solution.

RegQueryValueEx Returns a buffer size of 4 with an output of 18754 17236 0 52428

Upvotes: 0

Views: 329

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 595837

You are clearly calling the Unicode version of the Registry functions, so you should be using WCHAR instead of TCHAR for your data buffer.

And you should not be truncating the characters to char at all. Use std::wcout instead of std::cout for printing out Unicode strings. And use the returned bufferSize to know how many WCHARs were actually output. Your printing loop is ignoring the bufferSize completely, so it is possible that you are actually printing out random garbage that RegQueryValueEx() did not actually intend for you to use (hence why lpcbData parameter is an in/out parameter, so you know how many bytes are actually valid).

You are also leaking the opened HKEY handle if RegQueryValueEx() fails.

Try something more like this instead:

HKEY registryHandle;
int registryResult;

registryResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", 0, KEY_QUERY_VALUE, &registryHandle);

if (registryResult != ERROR_SUCCESS) {
    std::cout << "Error: " << registryResult << std::endl;
    return false;
}

WCHAR dataBuffer[1024];
DWORD bufferSize = sizeof(dataBuffer);

// TODO: consider using RegGetValueW() instead, which is safer
// when it comes to reading string values from the Registry...
registryResult = RegQueryValueExW(registryHandle, L"LastUsedUsername", NULL, NULL, (LPBYTE)dataBuffer, &bufferSize);
RegCloseKey(registryHandle);    

if (registryResult != ERROR_SUCCESS) {
    std::cout << "Error2: " << registryResult << std::endl;
    return false;
}

DWORD len = bufferSize / sizeof(WCHAR);
if ((len > 0) && (dataBuffer[len-1] == L'\0')) {
    --len;
}

std::cout << "Data Byte Size: " << bufferSize << std::endl;
std::cout << "Data Character Length: " << len << std::endl;
std::wcout.write(dataBuffer, len);

std::cin.get();
return true;

That being said, on my machine, there is no LastUsedUsername value in the Winlogon key you are accessing, so getting a "not found" error is a very likely possibility. But you definately need to handle

Upvotes: 2

Related Questions