Commit 73faa990 authored by captainwong's avatar captainwong

update for unicode; re-format

parent e91a1a4a
...@@ -60,11 +60,11 @@ class RegKey; ...@@ -60,11 +60,11 @@ class RegKey;
// Wrappers for getting registry values // Wrappers for getting registry values
// //
DWORD RegGetDword (HKEY hKey, const std::wstring& subKey, const std::wstring& value); DWORD RegGetDword(HKEY hKey, const std::wstring& subKey, const std::wstring& value);
ULONGLONG RegGetQword (HKEY hKey, const std::wstring& subKey, const std::wstring& value); ULONGLONG RegGetQword(HKEY hKey, const std::wstring& subKey, const std::wstring& value);
std::wstring RegGetString (HKEY hKey, const std::wstring& subKey, const std::wstring& value); std::wstring RegGetString(HKEY hKey, const std::wstring& subKey, const std::wstring& value);
std::vector<std::wstring> RegGetMultiString (HKEY hKey, const std::wstring& subKey, const std::wstring& value); std::vector<std::wstring> RegGetMultiString(HKEY hKey, const std::wstring& subKey, const std::wstring& value);
std::vector<BYTE> RegGetBinary (HKEY hKey, const std::wstring& subKey, const std::wstring& value); std::vector<BYTE> RegGetBinary(HKEY hKey, const std::wstring& subKey, const std::wstring& value);
// //
...@@ -85,19 +85,19 @@ std::vector<std::wstring> RegEnumSubKeys(HKEY hKey); ...@@ -85,19 +85,19 @@ std::vector<std::wstring> RegEnumSubKeys(HKEY hKey);
// //
RegKey RegCreateKey( RegKey RegCreateKey(
HKEY hKeyParent, HKEY hKeyParent,
const std::wstring& keyName, const std::wstring& keyName,
LPTSTR keyClass = REG_NONE, LPTSTR keyClass = REG_NONE,
DWORD options = REG_OPTION_NON_VOLATILE, DWORD options = REG_OPTION_NON_VOLATILE,
REGSAM access = KEY_READ | KEY_WRITE, REGSAM access = KEY_READ | KEY_WRITE,
SECURITY_ATTRIBUTES* securityAttributes = nullptr, SECURITY_ATTRIBUTES* securityAttributes = nullptr,
DWORD* disposition = nullptr DWORD* disposition = nullptr
); );
RegKey RegOpenKey( RegKey RegOpenKey(
HKEY hKeyParent, HKEY hKeyParent,
const std::wstring& keyName, const std::wstring& keyName,
REGSAM access = KEY_READ | KEY_WRITE REGSAM access = KEY_READ | KEY_WRITE
); );
...@@ -128,201 +128,198 @@ class RegKey ...@@ -128,201 +128,198 @@ class RegKey
{ {
public: public:
// //
// Initialize as an empty key handle // Initialize as an empty key handle
// //
RegKey() noexcept = default; RegKey() noexcept = default;
// //
// Take ownership of the input raw key handle // Take ownership of the input raw key handle
// //
explicit RegKey(HKEY hKey) noexcept explicit RegKey(HKEY hKey) noexcept
: m_hKey{ hKey } : m_hKey{ hKey }
{} {}
// //
// Take ownership of the input key handle. // Take ownership of the input key handle.
// The input key handle wrapper is reset to an empty state // The input key handle wrapper is reset to an empty state
// //
RegKey(RegKey&& other) noexcept RegKey(RegKey&& other) noexcept
: m_hKey{ other.m_hKey } : m_hKey{ other.m_hKey }
{ {
// //
// Other doesn't own the raw handle anymore // Other doesn't own the raw handle anymore
// //
other.m_hKey = nullptr; other.m_hKey = nullptr;
} }
// //
// Move-assign from the input key handle. // Move-assign from the input key handle.
// Properly check against self-move-assign (which is safe and does nothing). // Properly check against self-move-assign (which is safe and does nothing).
// //
RegKey& operator=(RegKey&& other) noexcept RegKey& operator=(RegKey&& other) noexcept
{ {
// //
// Prevent self-move-assign // Prevent self-move-assign
// //
if ((this != &other) && (m_hKey != other.m_hKey)) if ((this != &other) && (m_hKey != other.m_hKey)) {
{ Close();
Close();
//
// // Move from other
// Move from other //
// m_hKey = other.m_hKey;
m_hKey = other.m_hKey; other.m_hKey = nullptr;
other.m_hKey = nullptr; }
} return *this;
return *this; }
}
//
// // Ban copy
// Ban copy //
// RegKey(const RegKey&) = delete;
RegKey(const RegKey&) = delete; RegKey& operator=(const RegKey&) = delete;
RegKey& operator=(const RegKey&) = delete;
//
// // Safely close the wrapped key handle (if any)
// Safely close the wrapped key handle (if any) //
// ~RegKey() noexcept
~RegKey() noexcept {
{ Close();
Close(); }
}
//
// // Give read-only access to the wrapped HKEY handle
// Give read-only access to the wrapped HKEY handle //
// HKEY Get() const noexcept
HKEY Get() const noexcept {
{ return m_hKey;
return m_hKey; }
}
//
// // Close current HKEY handle.
// Close current HKEY handle. // If key wasn't open, does nothing.
// If key wasn't open, does nothing. //
// void Close() noexcept
void Close() noexcept {
{ if (IsValid()) {
if (IsValid()) ::RegCloseKey(m_hKey);
{ m_hKey = nullptr;
::RegCloseKey(m_hKey); }
m_hKey = nullptr; }
}
} //
// Is the wrapped HKEY handle valid?
// //
// Is the wrapped HKEY handle valid? bool IsValid() const noexcept
// {
bool IsValid() const noexcept return m_hKey != nullptr;
{ }
return m_hKey != nullptr;
} //
// Has the same semantic of IsValid, but allows a short "if (regKey)" syntax
// //
// Has the same semantic of IsValid, but allows a short "if (regKey)" syntax explicit operator bool() const noexcept
// {
explicit operator bool() const noexcept return IsValid();
{ }
return IsValid();
} //
// Transfer ownership of current HKEY to the caller.
// // Note that the caller is responsible for closing the key raw handle!
// Transfer ownership of current HKEY to the caller. //
// Note that the caller is responsible for closing the key raw handle! HKEY Detach() noexcept
// {
HKEY Detach() noexcept HKEY hKey = m_hKey;
{
HKEY hKey = m_hKey; //
// We don't own the HKEY handle anymore
// //
// We don't own the HKEY handle anymore m_hKey = nullptr;
//
m_hKey = nullptr; //
// Transfer ownership of the raw handle to the caller
// //
// Transfer ownership of the raw handle to the caller return hKey;
// }
return hKey;
} //
// Take ownership of the HKEY handle.
// // Safely close any previously open handle.
// Take ownership of the HKEY handle. // Input key handle can be nullptr; in this case this wrapper wraps an empty handle.
// Safely close any previously open handle. //
// Input key handle can be nullptr; in this case this wrapper wraps an empty handle. void Attach(HKEY hKey) noexcept
// {
void Attach(HKEY hKey) noexcept //
{ // Prevent self-attach
// //
// Prevent self-attach if (m_hKey != hKey) {
// Close();
if (m_hKey != hKey)
{ //
Close(); // Take ownership of hKey
//
// m_hKey = hKey;
// Take ownership of hKey }
// }
m_hKey = hKey;
} //
} // Non-throwing swap
//
// friend void swap(RegKey& a, RegKey& b) noexcept
// Non-throwing swap {
// //
friend void swap(RegKey& a, RegKey& b) noexcept // Enable ADL (not necessary in this case, but good practice)
{ //
// using std::swap;
// Enable ADL (not necessary in this case, but good practice)
// //
using std::swap; // Swap the raw handle members
//
// swap(a.m_hKey, b.m_hKey);
// Swap the raw handle members }
//
swap(a.m_hKey, b.m_hKey);
} //
// Overload comparison and relational operators
//
//
// Overload comparison and relational operators friend bool operator==(const RegKey& a, const RegKey& b) noexcept
// {
return a.m_hKey == b.m_hKey;
friend bool operator==(const RegKey& a, const RegKey& b) noexcept }
{
return a.m_hKey == b.m_hKey; friend bool operator!=(const RegKey& a, const RegKey& b) noexcept
} {
return a.m_hKey != b.m_hKey;
friend bool operator!=(const RegKey& a, const RegKey& b) noexcept }
{
return a.m_hKey != b.m_hKey; friend bool operator<(const RegKey& a, const RegKey& b) noexcept
} {
return a.m_hKey < b.m_hKey;
friend bool operator<(const RegKey& a, const RegKey& b) noexcept }
{
return a.m_hKey < b.m_hKey; friend bool operator<=(const RegKey& a, const RegKey& b) noexcept
} {
return a.m_hKey <= b.m_hKey;
friend bool operator<=(const RegKey& a, const RegKey& b) noexcept }
{
return a.m_hKey <= b.m_hKey; friend bool operator>(const RegKey& a, const RegKey& b) noexcept
} {
return a.m_hKey > b.m_hKey;
friend bool operator>(const RegKey& a, const RegKey& b) noexcept }
{
return a.m_hKey > b.m_hKey; friend bool operator>=(const RegKey& a, const RegKey& b) noexcept
} {
return a.m_hKey >= b.m_hKey;
friend bool operator>=(const RegKey& a, const RegKey& b) noexcept }
{
return a.m_hKey >= b.m_hKey;
}
private: private:
// //
// The wrapped registry key handle // The wrapped registry key handle
// //
HKEY m_hKey = nullptr; HKEY m_hKey = nullptr;
}; };
...@@ -332,18 +329,18 @@ private: ...@@ -332,18 +329,18 @@ private:
class RegistryError : public std::runtime_error class RegistryError : public std::runtime_error
{ {
public: public:
RegistryError(const char* message, LONG errorCode) RegistryError(const char* message, LONG errorCode)
: std::runtime_error{ message } : std::runtime_error{ message }
, m_errorCode{ errorCode } , m_errorCode{ errorCode }
{} {}
LONG ErrorCode() const noexcept LONG ErrorCode() const noexcept
{ {
return m_errorCode; return m_errorCode;
} }
private: private:
LONG m_errorCode; LONG m_errorCode;
}; };
...@@ -353,464 +350,447 @@ private: ...@@ -353,464 +350,447 @@ private:
inline DWORD RegGetDword(HKEY hKey, const std::wstring& subKey, const std::wstring& value) inline DWORD RegGetDword(HKEY hKey, const std::wstring& subKey, const std::wstring& value)
{ {
// //
// Read a 32-bit DWORD value from the registry // Read a 32-bit DWORD value from the registry
// //
DWORD data{}; DWORD data{};
DWORD dataSize = sizeof(data); DWORD dataSize = sizeof(data);
LONG retCode = ::RegGetValue( LONG retCode = ::RegGetValueW(
hKey, hKey,
subKey.c_str(), subKey.c_str(),
value.c_str(), value.c_str(),
RRF_RT_REG_DWORD, RRF_RT_REG_DWORD,
nullptr, nullptr,
&data, &data,
&dataSize); &dataSize);
if (retCode != ERROR_SUCCESS) if (retCode != ERROR_SUCCESS) {
{ throw RegistryError{ "Cannot read DWORD from registry.", retCode };
throw RegistryError{ "Cannot read DWORD from registry.", retCode }; }
}
return data;
return data;
} }
inline ULONGLONG RegGetQword(HKEY hKey, const std::wstring& subKey, const std::wstring& value) inline ULONGLONG RegGetQword(HKEY hKey, const std::wstring& subKey, const std::wstring& value)
{ {
// //
// Read a 64-bit QWORD value from the registry // Read a 64-bit QWORD value from the registry
// //
ULONGLONG data{}; ULONGLONG data{};
DWORD dataSize = sizeof(data); DWORD dataSize = sizeof(data);
LONG retCode = ::RegGetValue( LONG retCode = ::RegGetValueW(
hKey, hKey,
subKey.c_str(), subKey.c_str(),
value.c_str(), value.c_str(),
RRF_RT_REG_QWORD, RRF_RT_REG_QWORD,
nullptr, nullptr,
&data, &data,
&dataSize); &dataSize);
if (retCode != ERROR_SUCCESS) if (retCode != ERROR_SUCCESS) {
{ throw RegistryError{ "Cannot read QWORD from registry.", retCode };
throw RegistryError{ "Cannot read QWORD from registry.", retCode }; }
}
return data;
return data;
} }
inline std::wstring RegGetString(HKEY hKey, const std::wstring& subKey, const std::wstring& value) inline std::wstring RegGetString(HKEY hKey, const std::wstring& subKey, const std::wstring& value)
{ {
// //
// Request the size of the string, in bytes // Request the size of the string, in bytes
// //
DWORD dataSize{}; DWORD dataSize{};
LONG retCode = ::RegGetValue( LONG retCode = ::RegGetValueW(
hKey, hKey,
subKey.c_str(), subKey.c_str(),
value.c_str(), value.c_str(),
RRF_RT_REG_SZ, RRF_RT_REG_SZ,
nullptr, nullptr,
nullptr, nullptr,
&dataSize); &dataSize);
if (retCode != ERROR_SUCCESS) if (retCode != ERROR_SUCCESS) {
{ throw RegistryError{ "Cannot read string from registry", retCode };
throw RegistryError{ "Cannot read string from registry", retCode }; }
}
//
// // Allocate room for the result string.
// Allocate room for the result string. //
// // Note that dataSize is in bytes, but wstring::resize() expects length in wchar_ts,
// Note that dataSize is in bytes, but wstring::resize() expects length in wchar_ts, // so must convert from bytes to wchar_t count first.
// so must convert from bytes to wchar_t count first. //
// std::wstring data;
std::wstring data; data.resize(dataSize / sizeof(wchar_t));
data.resize(dataSize / sizeof(wchar_t));
//
// // Read the string from the registry into local wstring object
// Read the string from the registry into local wstring object //
// retCode = ::RegGetValueW(
retCode = ::RegGetValue( hKey,
hKey, subKey.c_str(),
subKey.c_str(), value.c_str(),
value.c_str(), RRF_RT_REG_SZ,
RRF_RT_REG_SZ, nullptr,
nullptr, &data[0],
&data[0], &dataSize);
&dataSize); if (retCode != ERROR_SUCCESS) {
if (retCode != ERROR_SUCCESS) throw RegistryError{ "Cannot read string from registry", retCode };
{ }
throw RegistryError{ "Cannot read string from registry", retCode };
} //
// On return, RegGetValue() writes in dataSize the actual size of the string, in bytes.
// // We must resize the wstring object to the proper string size.
// On return, RegGetValue() writes in dataSize the actual size of the string, in bytes. // Note that dataSize is expressed in bytes, and includes the terminating NUL; so we have to
// We must resize the wstring object to the proper string size. // subtract the NUL from the total string length, as wstring objects are already NUL-terminated.
// Note that dataSize is expressed in bytes, and includes the terminating NUL; so we have to //
// subtract the NUL from the total string length, as wstring objects are already NUL-terminated. DWORD stringLengthInWchars = dataSize / sizeof(wchar_t);
// stringLengthInWchars--; // exclude the NUL written by the Win32 API
DWORD stringLengthInWchars = dataSize / sizeof(wchar_t); data.resize(stringLengthInWchars);
stringLengthInWchars--; // exclude the NUL written by the Win32 API
data.resize(stringLengthInWchars); return data;
return data;
} }
inline std::vector<std::wstring> inline std::vector<std::wstring>
RegGetMultiString(HKEY hKey, const std::wstring& subKey, const std::wstring& value) RegGetMultiString(HKEY hKey, const std::wstring& subKey, const std::wstring& value)
{ {
// //
// Request the size of the multi-string, in bytes // Request the size of the multi-string, in bytes
// //
DWORD dataSize{}; DWORD dataSize{};
LONG retCode = ::RegGetValue( LONG retCode = ::RegGetValueW(
hKey, hKey,
subKey.c_str(), subKey.c_str(),
value.c_str(), value.c_str(),
RRF_RT_REG_MULTI_SZ, RRF_RT_REG_MULTI_SZ,
nullptr, nullptr,
nullptr, nullptr,
&dataSize); &dataSize);
if (retCode != ERROR_SUCCESS) if (retCode != ERROR_SUCCESS) {
{ throw RegistryError{ "Cannot read multi-string from registry", retCode };
throw RegistryError{ "Cannot read multi-string from registry", retCode }; }
}
//
// // Allocate room for the result multi-string.
// Allocate room for the result multi-string. //
// // Note that dataSize is in bytes, but our vector<wchar_t> object has size expressed in wchar_ts.
// Note that dataSize is in bytes, but our vector<wchar_t> object has size expressed in wchar_ts. //
// std::vector<wchar_t> data;
std::vector<wchar_t> data; data.resize(dataSize / sizeof(wchar_t));
data.resize(dataSize / sizeof(wchar_t));
//
// // Read the multi-string from the registry into the vector object
// Read the multi-string from the registry into the vector object //
// retCode = ::RegGetValueW(
retCode = ::RegGetValue( hKey,
hKey, subKey.c_str(),
subKey.c_str(), value.c_str(),
value.c_str(), RRF_RT_REG_MULTI_SZ,
RRF_RT_REG_MULTI_SZ, nullptr,
nullptr, &data[0],
&data[0], &dataSize);
&dataSize); if (retCode != ERROR_SUCCESS) {
if (retCode != ERROR_SUCCESS) throw RegistryError{ "Cannot read multi-string from registry", retCode };
{ }
throw RegistryError{ "Cannot read multi-string from registry", retCode };
} //
// Resize vector to the actual size returned by GetRegValue().
// // Note that the vector is a vector of wchar_ts, instead the size returned by GetRegValue()
// Resize vector to the actual size returned by GetRegValue(). // is in bytes, so we have to scale from bytes to wchar_t count.
// Note that the vector is a vector of wchar_ts, instead the size returned by GetRegValue() //
// is in bytes, so we have to scale from bytes to wchar_t count. data.resize(dataSize / sizeof(wchar_t));
//
data.resize( dataSize / sizeof(wchar_t) ); //
// Parse the double-NUL-terminated string into a vector<wstring>
// //
// Parse the double-NUL-terminated string into a vector<wstring> std::vector<std::wstring> result;
// const wchar_t* currStringPtr = &data[0];
std::vector<std::wstring> result; while (*currStringPtr != L'\0') {
const wchar_t* currStringPtr = &data[0]; // Current string is NUL-terminated, so get its length with wcslen()
while (*currStringPtr != L'\0') const size_t currStringLength = wcslen(currStringPtr);
{
// Current string is NUL-terminated, so get its length with wcslen() // Add current string to result vector
const size_t currStringLength = wcslen(currStringPtr); result.push_back(std::wstring{ currStringPtr, currStringLength });
// Add current string to result vector // Move to the next string
result.push_back(std::wstring{ currStringPtr, currStringLength }); currStringPtr += currStringLength + 1;
}
// Move to the next string
currStringPtr += currStringLength + 1; return result;
}
return result;
} }
inline std::vector<BYTE> RegGetBinary(HKEY hKey, const std::wstring& subKey, const std::wstring& value) inline std::vector<BYTE> RegGetBinary(HKEY hKey, const std::wstring& subKey, const std::wstring& value)
{ {
// //
// Request the size of the binary data, in bytes // Request the size of the binary data, in bytes
// //
DWORD dataSize{}; DWORD dataSize{};
LONG retCode = ::RegGetValue( LONG retCode = ::RegGetValueW(
hKey, hKey,
subKey.c_str(), subKey.c_str(),
value.c_str(), value.c_str(),
RRF_RT_REG_BINARY, RRF_RT_REG_BINARY,
nullptr, nullptr,
nullptr, nullptr,
&dataSize); &dataSize);
if (retCode != ERROR_SUCCESS) if (retCode != ERROR_SUCCESS) {
{ throw RegistryError{ "Cannot read binary data from registry", retCode };
throw RegistryError{ "Cannot read binary data from registry", retCode }; }
}
//
// // Allocate room for the result binary data
// Allocate room for the result binary data //
// std::vector<BYTE> data;
std::vector<BYTE> data; data.resize(dataSize);
data.resize(dataSize);
//
// // Read the binary data from the registry into the vector object
// Read the binary data from the registry into the vector object //
// retCode = ::RegGetValueW(
retCode = ::RegGetValue( hKey,
hKey, subKey.c_str(),
subKey.c_str(), value.c_str(),
value.c_str(), RRF_RT_REG_BINARY,
RRF_RT_REG_BINARY, nullptr,
nullptr, &data[0],
&data[0], &dataSize);
&dataSize); if (retCode != ERROR_SUCCESS) {
if (retCode != ERROR_SUCCESS) throw RegistryError{ "Cannot read binary data from registry", retCode };
{ }
throw RegistryError{ "Cannot read binary data from registry", retCode };
} //
// Resize vector to the actual size returned by GetRegValue().
// //
// Resize vector to the actual size returned by GetRegValue(). data.resize(dataSize);
//
data.resize(dataSize);
return data;
return data;
} }
inline std::vector<std::pair<std::wstring, DWORD>> RegEnumValues(HKEY hKey) inline std::vector<std::pair<std::wstring, DWORD>> RegEnumValues(HKEY hKey)
{ {
// //
// Get useful pre-enumeration info, like the total number of values // Get useful pre-enumeration info, like the total number of values
// and the maximum length of the value names // and the maximum length of the value names
// //
DWORD valueCount{}; DWORD valueCount{};
DWORD maxValueNameLen{}; DWORD maxValueNameLen{};
LONG retCode = ::RegQueryInfoKey( LONG retCode = ::RegQueryInfoKey(
hKey, hKey,
nullptr, // no user-defined class nullptr, // no user-defined class
nullptr, // no user-defined class size nullptr, // no user-defined class size
nullptr, // reserved nullptr, // reserved
nullptr, // no subkey count nullptr, // no subkey count
nullptr, // no subkey max length nullptr, // no subkey max length
nullptr, // no subkey class length nullptr, // no subkey class length
&valueCount, &valueCount,
&maxValueNameLen, &maxValueNameLen,
nullptr, // no max value length nullptr, // no max value length
nullptr, // no security descriptor nullptr, // no security descriptor
nullptr // no last write time nullptr // no last write time
); );
if (retCode != ERROR_SUCCESS) if (retCode != ERROR_SUCCESS) {
{ throw RegistryError{ "RegQueryInfoKey failed while preparing for value enumeration.", retCode };
throw RegistryError{ "RegQueryInfoKey failed while preparing for value enumeration.", retCode }; }
}
//
// // NOTE: According to the MSDN documentation, the size returned for value name max length
// NOTE: According to the MSDN documentation, the size returned for value name max length // does *not* include the terminating NUL, so let's add +1 to take it into account
// does *not* include the terminating NUL, so let's add +1 to take it into account // when I allocate the buffer for reading value names.
// when I allocate the buffer for reading value names. //
// maxValueNameLen++;
maxValueNameLen++;
//
// // Preallocate a buffer for the value names
// Preallocate a buffer for the value names //
// auto nameBuffer = std::make_unique<wchar_t[]>(maxValueNameLen);
auto nameBuffer = std::make_unique<wchar_t[]>(maxValueNameLen);
//
// // The value names and types will be stored here
// The value names and types will be stored here //
// std::vector<std::pair<std::wstring, DWORD>> valueInfo;
std::vector<std::pair<std::wstring, DWORD>> valueInfo;
//
// // Enumerate all the values
// Enumerate all the values //
// for (DWORD index = 0; index < valueCount; index++) {
for (DWORD index = 0; index < valueCount; index++) //
{ // Get the name and the type of the current value
// //
// Get the name and the type of the current value DWORD valueNameLen = maxValueNameLen;
// DWORD valueType{};
DWORD valueNameLen = maxValueNameLen; retCode = ::RegEnumValueW(
DWORD valueType{}; hKey,
retCode = ::RegEnumValue( index,
hKey, nameBuffer.get(),
index, &valueNameLen,
nameBuffer.get(), nullptr, // reserved
&valueNameLen, &valueType,
nullptr, // reserved nullptr, // no data
&valueType, nullptr // no data size
nullptr, // no data );
nullptr // no data size if (retCode != ERROR_SUCCESS) {
); throw RegistryError{ "Cannot enumerate values: RegEnumValue failed.", retCode };
if (retCode != ERROR_SUCCESS) }
{
throw RegistryError{ "Cannot enumerate values: RegEnumValue failed.", retCode }; //
} // On success, the RegEnumValue API writes the length of the
// value name in the valueNameLen output parameter
// // (not including the terminating NUL).
// On success, the RegEnumValue API writes the length of the // So we can build a wstring based on that length.
// value name in the valueNameLen output parameter //
// (not including the terminating NUL). // The value info pair is made by the value's name and the value's type.
// So we can build a wstring based on that length. //
// valueInfo.push_back(std::make_pair(
// The value info pair is made by the value's name and the value's type. std::wstring{ nameBuffer.get(), valueNameLen },
// valueType
valueInfo.push_back(std::make_pair( ));
std::wstring{ nameBuffer.get(), valueNameLen }, }
valueType
)); return valueInfo;
}
return valueInfo;
} }
inline std::vector<std::wstring> RegEnumSubKeys(HKEY hKey) inline std::vector<std::wstring> RegEnumSubKeys(HKEY hKey)
{ {
// //
// Get some useful pre-enumeration info, like the total number of subkeys // Get some useful pre-enumeration info, like the total number of subkeys
// and the maximum length of the subkey names // and the maximum length of the subkey names
// //
DWORD subKeyCount{}; DWORD subKeyCount{};
DWORD maxSubKeyNameLen{}; DWORD maxSubKeyNameLen{};
LONG retCode = ::RegQueryInfoKey( LONG retCode = ::RegQueryInfoKey(
hKey, hKey,
nullptr, // no user-defined class nullptr, // no user-defined class
nullptr, // no user-defined class size nullptr, // no user-defined class size
nullptr, // reserved nullptr, // reserved
&subKeyCount, &subKeyCount,
&maxSubKeyNameLen, &maxSubKeyNameLen,
nullptr, // no subkey class length nullptr, // no subkey class length
nullptr, // no value count nullptr, // no value count
nullptr, // no value name max length nullptr, // no value name max length
nullptr, // no max value length nullptr, // no max value length
nullptr, // no security descriptor nullptr, // no security descriptor
nullptr // no last write time nullptr // no last write time
); );
if (retCode != ERROR_SUCCESS) if (retCode != ERROR_SUCCESS) {
{ throw RegistryError{ "RegQueryInfoKey failed while preparing for subkey enumeration.", retCode };
throw RegistryError{ "RegQueryInfoKey failed while preparing for subkey enumeration.", retCode }; }
}
//
// // NOTE: According to the MSDN documentation, the size returned for subkey name max length
// NOTE: According to the MSDN documentation, the size returned for subkey name max length // does *not* include the terminating NUL, so let's add +1 to take it into account
// does *not* include the terminating NUL, so let's add +1 to take it into account // when I allocate the buffer for reading subkey names.
// when I allocate the buffer for reading subkey names. //
// maxSubKeyNameLen++;
maxSubKeyNameLen++;
//
// // Preallocate a buffer for the subkey names
// Preallocate a buffer for the subkey names //
// auto nameBuffer = std::make_unique<wchar_t[]>(maxSubKeyNameLen);
auto nameBuffer = std::make_unique<wchar_t[]>(maxSubKeyNameLen);
//
// // The subkey names will be stored here
// The subkey names will be stored here //
// std::vector<std::wstring> subkeyNames;
std::vector<std::wstring> subkeyNames;
//
// // Enumerate all the subkeys
// Enumerate all the subkeys //
// for (DWORD index = 0; index < subKeyCount; index++) {
for (DWORD index = 0; index < subKeyCount; index++) //
{ // Get the name of the current subkey
// //
// Get the name of the current subkey DWORD subKeyNameLen = maxSubKeyNameLen;
// retCode = ::RegEnumKeyExW(
DWORD subKeyNameLen = maxSubKeyNameLen; hKey,
retCode = ::RegEnumKeyEx( index,
hKey, nameBuffer.get(),
index, &subKeyNameLen,
nameBuffer.get(), nullptr, // reserved
&subKeyNameLen, nullptr, // no class
nullptr, // reserved nullptr, // no class
nullptr, // no class nullptr // no last write time
nullptr, // no class );
nullptr // no last write time if (retCode != ERROR_SUCCESS) {
); throw RegistryError{ "Cannot enumerate subkeys: RegEnumKeyEx failed.", retCode };
if (retCode != ERROR_SUCCESS) }
{
throw RegistryError{ "Cannot enumerate subkeys: RegEnumKeyEx failed.", retCode }; //
} // On success, the ::RegEnumKeyEx API writes the length of the
// subkey name in the subKeyNameLen output parameter
// // (not including the terminating NUL).
// On success, the ::RegEnumKeyEx API writes the length of the // So I can build a wstring based on that length.
// subkey name in the subKeyNameLen output parameter //
// (not including the terminating NUL). subkeyNames.push_back(std::wstring{ nameBuffer.get(), subKeyNameLen });
// So I can build a wstring based on that length. }
//
subkeyNames.push_back(std::wstring{ nameBuffer.get(), subKeyNameLen }); return subkeyNames;
}
return subkeyNames;
} }
inline RegKey RegCreateKey( inline RegKey RegCreateKey(
HKEY hKeyParent, HKEY hKeyParent,
const std::wstring& keyName, const std::wstring& keyName,
LPTSTR keyClass, LPWSTR keyClass,
DWORD options, DWORD options,
REGSAM access, REGSAM access,
SECURITY_ATTRIBUTES* securityAttributes, SECURITY_ATTRIBUTES* securityAttributes,
DWORD* disposition DWORD* disposition
) )
{ {
// //
// Create the key invoking the native RegCreateKeyEx Win32 API // Create the key invoking the native RegCreateKeyEx Win32 API
// //
HKEY hKey = nullptr; HKEY hKey = nullptr;
LONG retCode = ::RegCreateKeyEx( LONG retCode = ::RegCreateKeyExW(
hKeyParent, hKeyParent,
keyName.c_str(), keyName.c_str(),
0, // reserved 0, // reserved
keyClass, keyClass,
options, options,
access, access,
securityAttributes, securityAttributes,
&hKey, &hKey,
disposition disposition
); );
if (retCode != ERROR_SUCCESS) if (retCode != ERROR_SUCCESS) {
{ throw RegistryError{ "Cannot create registry key: RegCreateKeyEx failed.", retCode };
throw RegistryError{ "Cannot create registry key: RegCreateKeyEx failed.", retCode }; }
}
//
// // Return the raw key handle safely wrapped in the C++ key resource manager
// Return the raw key handle safely wrapped in the C++ key resource manager //
// return RegKey{ hKey };
return RegKey{ hKey };
} }
inline RegKey RegOpenKey( inline RegKey RegOpenKey(
HKEY hKeyParent, HKEY hKeyParent,
const std::wstring& keyName, const std::wstring& keyName,
REGSAM access REGSAM access
) )
{ {
// //
// Open the key invoking the native RegOpenKeyEx Win32 API // Open the key invoking the native RegOpenKeyEx Win32 API
// //
HKEY hKey = nullptr; HKEY hKey = nullptr;
LONG retCode = ::RegOpenKeyEx( LONG retCode = ::RegOpenKeyExW(
hKeyParent, hKeyParent,
keyName.c_str(), keyName.c_str(),
0, // default options 0, // default options
access, access,
&hKey &hKey
); );
if (retCode != ERROR_SUCCESS) if (retCode != ERROR_SUCCESS) {
{ throw RegistryError{ "Cannot open registry key: RegOpenKeyEx failed.", retCode };
throw RegistryError{ "Cannot open registry key: RegOpenKeyEx failed.", retCode }; }
}
//
// // Return the raw key handle safely wrapped in the C++ key resource manager
// Return the raw key handle safely wrapped in the C++ key resource manager //
// return RegKey{ hKey };
return RegKey{ hKey };
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment