Read Windows Registry with C++
Quick prototype, but it works
winreg.h
:
#include <string>
#include <vector>
#include <map>
enum class hive
{
classes_root = 0,
local_machine,
current_user,
};
std::vector<std::wstring> enum_subkeys(hive h, std::wstring path);
std::vector<std::wstring> get_value_names(hive h, std::wstring path);
std::wstring get_value(hive h, const std::wstring& path, const std::wstring& value_name = L"");
winreg.cpp
:
# include "winreg.h"
#include <windows.h>
#include <vector>
using namespace std;
#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383
bool get_key_info(HKEY hKey,
unsigned long& subkey_count, unsigned long& value_count,
unsigned long& max_name_length, unsigned long& max_value_length)
{
TCHAR achKey[MAX_KEY_LENGTH];
DWORD cbName = MAX_KEY_LENGTH;
TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name
DWORD cchClassName = MAX_PATH;
DWORD cSubKeys = 0;
DWORD cbMaxSubKey; // longest subkey size
DWORD cchMaxClass; // longest class string
DWORD cValues; // number of values for key
DWORD cchMaxValue; // longest value name
DWORD cbMaxValueData; // longest value data
DWORD cbSecurityDescriptor; // size of security descriptor
FILETIME ftLastWriteTime; // last write time
LSTATUS lResult = ::RegQueryInfoKey(hKey,
achClass,
&cchClassName,
nullptr,
&cSubKeys, // number of sub-keys (tree in regedit)
&cbMaxSubKey,
&cchMaxClass,
&cValues, // number of values (right pane in regedit)
&cchMaxValue,
&cbMaxValueData,
&cbSecurityDescriptor,
&ftLastWriteTime);
if (lResult == ERROR_SUCCESS)
{
subkey_count = cSubKeys;
value_count = cValues;
max_name_length = cchMaxValue;
max_value_length = cbMaxValueData;
return true;
}
return false;
}
vector<wstring> enum_subkeys(hive h, std::wstring path)
{
vector<wstring> result;
HKEY hKey;
LSTATUS lResult = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, path.c_str(), 0, KEY_READ, &hKey);
if (lResult != ERROR_SUCCESS) return result;
TCHAR achKey[MAX_KEY_LENGTH];
for(int i = 0; ;i++)
{
DWORD cbName = MAX_KEY_LENGTH;
lResult = ::RegEnumKeyEx(hKey, i, achKey, &cbName, nullptr, nullptr, nullptr, nullptr);
if (lResult == ERROR_SUCCESS)
{
result.push_back(achKey);
}
else if (lResult == ERROR_NO_MORE_ITEMS)
{
break;
}
else
{
break;
}
}
::RegCloseKey(hKey);
return result;
}
vector<wstring> get_value_names(hive h, wstring path)
{
vector<wstring> result;
HKEY hKey;
LSTATUS lResult = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, path.c_str(), 0, KEY_READ, &hKey);
if (lResult == ERROR_SUCCESS)
{
unsigned long subkey_count, value_count, max_name_length, max_value_length;
DWORD type;
if (get_key_info(hKey, subkey_count, value_count, max_name_length, max_value_length) && value_count)
{
max_name_length += 4;
max_value_length += 4;
vector<TCHAR> achValue(max_name_length);
vector<byte> achData(max_value_length);
for (int i = 0; i < value_count; i++)
{
unsigned long name_length = max_name_length;
lResult = ::RegEnumValue(hKey, i,
&achValue[0], &name_length,
nullptr,
&type, // todo: include type in result
nullptr, nullptr);
if (lResult == ERROR_SUCCESS)
{
wstring name(&achValue[0]);
result.push_back(name);
}
}
}
}
::RegCloseKey(hKey);
return result;
}
std::wstring get_value(hive h, const std::wstring& path, const std::wstring& value_name)
{
HKEY hKey;
LSTATUS lResult = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, path.c_str(), 0, KEY_READ, &hKey);
if (lResult == ERROR_SUCCESS)
{
DWORD dwType;
DWORD cbData;
lResult = ::RegGetValue(hKey,
nullptr,
value_name.c_str(),
RRF_RT_ANY,
&dwType,
nullptr,
&cbData);
if (lResult == ERROR_SUCCESS)
{
// dwType contains data type like REG_SZ
// cbData is buffer length to allocate
if (dwType == REG_SZ || dwType == REG_EXPAND_SZ)
{
vector<byte> buffer(cbData + 1);
cbData = buffer.size();
lResult = ::RegGetValue(hKey, nullptr, value_name.c_str(), RRF_RT_ANY, &dwType,
&buffer[0],
&cbData);
wstring sv(reinterpret_cast<wchar_t*>(&buffer[0]));
return sv;
}
}
}
::RegCloseKey(hKey);
return std::wstring();
}
Sample Usage
#include "winreg.h"
#include <string>
#include <iostream>
using namespace std;
wstring abs_root = L"SOFTWARE\\Clients\\StartMenuInternet";
int main()
{
auto subs = enum_subkeys(hive::local_machine, abs_root);
for (wstring sub : subs)
{
wcout << sub << endl;
wstring root = abs_root + L"\\" + sub;
wstring display_name = get_value(hive::local_machine, root);
wstring open_command = get_value(hive::local_machine, root + L"\\shell\\open\\command");
wstring http_url_assoc = get_value(hive::local_machine, root + L"\\Capabilities\\URLAssociations", L"http");
}
return 0;
}
To contact me, send an email anytime or leave a comment below.