I am trying to read the MachineGuid from HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography
in the Registry. I have looked at a couple of postings about doing this and based my code on them.
I have the following code in a button OnClick()
event for testing:
AnsiString S = "MachineGuid: ";
TRegistry* Registry = new TRegistry(KEY_READ);
try {
Registry->RootKey = HKEY_LOCAL_MACHINE;
// False because we do not want to create it if it doesn’t exist
Registry->OpenKey("SOFTWARE\\Microsoft\\Cryptography", false);
// Registry->OpenKeyReadOnly("SOFTWARE\\Microsoft\\Cryptography");
if (!Registry->ValueExists("MachineGuid")) {
S += String("Key not found!");
} else {
S += Registry->ReadString("MachineGuid");
}
} __finally
{
delete Registry;
}
Memo2->Lines->Add(S);
The problem is that Registry->ValueExists("MachineGuid")
always reports false
whether I use OpenKey()
or OpenKeyReadOnly()
. I can't figure out what I am doing wrong.
This is the first time I am using TRegistry
.
Using: C++ Builder 11.3 Community Edition
The problem is that the MachineGuid
value is only available in the 64-bit application data in the registry.
You can solve that by requesting access rights to the 64-bit view over the registry. This will work no matter if your application is compiled for 32 or 64 bit:
TRegistry* Registry = new TRegistry(KEY_READ | KEY_WOW64_64KEY);
Example:
#include <memory>
void __fastcall TForm1::Button1Click(TObject* Sender)
{
System::String S = _D("MachineGuid");
auto Registry = std::make_unique<TRegistry>(KEY_QUERY_VALUE | KEY_WOW64_64KEY);
try {
Registry->RootKey = HKEY_LOCAL_MACHINE;
if (Registry->OpenKeyReadOnly(_D("SOFTWARE\\Microsoft\\Cryptography"))) {
if (!Registry->ValueExists(S)) {
S += _D(": Key not found!");
} else {
S += _D(": ") + Registry->ReadString(S);
}
} else {
S += _D(": OpenKeyReadOnly failed");
}
} catch (...) {
S += _D(": Exception");
}
Memo2->Lines->Add(S);
}
Since I mainly use C++ Builder 4 myself, I was curious about how to solve it in that environment but that version of TRegistry
doesn't seem to support access rights (there was probably no need back in the 90's). Here's a workaround for really old BCB versions:
#ifndef KEY_WOW64_64KEY
#define KEY_WOW64_64KEY 0x0100
#endif
class MyReg {
public:
MyReg(HKEY hKeyParent, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired)
{
LONG rv =
RegOpenKeyExW(hKeyParent, lpSubKey, ulOptions, samDesired, &hKey);
if (rv != ERROR_SUCCESS)
throw Exception(String("RegOpenKeyExW failed ") + GetLastError());
}
~MyReg() { RegCloseKey(hKey); }
String ReadString(LPCWSTR lpValueName)
{
WCHAR buf[MAX_PATH];
DWORD cbData = sizeof buf;
LONG rv = RegQueryValueExW(hKey, lpValueName, 0, NULL,
reinterpret_cast<PBYTE>(buf), &cbData);
if (rv != ERROR_SUCCESS)
throw Exception(String("RegGetValueW failed ") + GetLastError());
buf[cbData / sizeof(WCHAR)] = L'\0';
return String(buf);
}
private:
MyReg(const MyReg&); // no copying
MyReg& operator=(const MyReg&); // no copying
HKEY hKey;
};
void __fastcall TForm1::Button1Click(TObject *Sender) {
MyReg mr(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography", 0,
KEY_QUERY_VALUE | KEY_WOW64_64KEY);
String res = mr.ReadString(L"MachineGuid");
Memo2->Lines->Add(res);
}