-3

I'm trying to read the Windows "ProductName" value from the registry, I'm using the following code to retrieve the value:

HKEY hKey;
DWORD buffer;
LONG result;
unsigned long type = REG_DWORD, size = 1024;

result = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &hKey);
if (result == ERROR_SUCCESS)
{
    RegQueryValueEx(hKey, "ProductName", NULL, &type, (LPBYTE)&buffer, &size);
    RegCloseKey(hKey);
}

std::stringstream ss;
ss << "version: " << buffer;
std::string s = ss.str();

MessageBox(NULL, s.c_str(), s.c_str(), MB_OK);

The output I'm getting is:

Version: 3435973836

but the "regedit" returns "Windows 10 Enterprise". Any hints on why am I getting this strange value?

0x29a
  • 733
  • 1
  • 7
  • 23
  • 3
    problem in how you try show your data - `ss << "version: " << buffer;` and `3435973836 == 0xcccccccc`, `DWORD buffer` - not string, not 1024 size but 4, you not check are really got data, etc. all code is wrong – RbMm Apr 03 '19 at 09:41
  • 1
    You didn't check for errors when you call `RegQueryValueEx`. If you do so then you will see what went wrong. – David Heffernan Apr 03 '19 at 10:07
  • FYI, on my machine, there is no `ProductName` available under that key in `HKEY_CURRENT_USER`, but there is one available under that key in `HKEY_LOCAL_MACHINE` instead. – Remy Lebeau Apr 03 '19 at 18:15

3 Answers3

3

You aren't storing the result in a string.

DWORD buffer;
...
RegQueryValueEx(hKey, "ProductName", NULL, &type, (LPBYTE)&buffer, &size);

What you should do instead is obviously to use a string:

size_t size = 1024;
char buffer[size];
...

result = RegQueryValueEx(hKey, "ProductName", NULL, &type, buffer, &size);
if(result == ERROR_SUCCESS && type == REG_SZ)
{
  /* do stuff with buffer */
}
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • You really need to check for errors when calling API functions – David Heffernan Apr 03 '19 at 13:51
  • @DavidHeffernan Indeed. So this call should also be checked against `ERROR_SUCCESS` like the previous call in the OP's code. Doesn't really help catching this particular bug though, since the code is doing runaway stack trashing and anything can happen from there. – Lundin Apr 03 '19 at 13:56
  • It's important to hammer home the necessity of error checking – David Heffernan Apr 03 '19 at 14:05
  • @DavidHeffernan Well, I completely agree so I updated the answer. – Lundin Apr 03 '19 at 14:10
  • Note that `RegQueryValueEx()` is a `TCHAR`-based API, so you should be passing it a `TCHAR[]` buffer, not a `char[]` buffer. This code would work only if the project were not configured for Unicode so `RegQueryValueEx()` maps to `RegQueryValueExA()`. Otherwise, you should call `RegQueryValueExA()` explicitly to match your `char[]` buffer and `std::stringstream`. Also, note that `char buffer[size];` is non-standard syntax in C++, use a `std::vector` or `std::string` instead. – Remy Lebeau Apr 03 '19 at 18:14
0

There is nothing in your buffer:

0xCCCCCCCC : Used by Microsoft's C++ debugging runtime 
             library to mark uninitialised stack memory

In Visual Studio C++, what are the memory allocation representations?

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Ozzy
  • 64
  • 4
0

As @Lundin says, you need to send a string but not a pointer of DWORD. What I want to add is, you got the value 3435973836(0xcccccccc in Hexadecimal). That means the call RegQueryValueEx fails or even not run into the condition. If it succeed, then the value of buffer in non-Unicode will be like 1684957527(0x646E6957). Depends on the first 4 characters of "Windows 10 Enterprise", 'W'=0x57;'i'=0x69;'n'=0x6e;'d'=0x64;

The ProductName of "Windows 10 Enterprise" is belong to the Local Machine but not only current user, so you need to retrieve it from HKEY_LOCAL_MACHINE.

Drake Wu
  • 6,927
  • 1
  • 7
  • 30