| Index: src/shared/Registry.cpp |
| =================================================================== |
| new file mode 100644 |
| --- /dev/null |
| +++ b/src/shared/Registry.cpp |
| @@ -0,0 +1,90 @@ |
| +#include "Registry.h" |
| +#include <memory> |
| + |
| +using namespace AdblockPlus; |
| + |
| +static HKEY predefined_hkeys[5] = |
| +{ |
| + HKEY_CLASSES_ROOT, |
| + HKEY_CURRENT_CONFIG, |
| + HKEY_CURRENT_USER, |
| + HKEY_LOCAL_MACHINE, |
| + HKEY_USERS |
| +}; |
| + |
| +Registry_Key::Registry_Key(Predefined root, std::wstring key_name) |
| + : is_predefined(key_name.empty()) |
| +{ |
| + auto predefined_key(predefined_hkeys[(unsigned int) root ]); |
| + if (is_predefined) |
| + { |
| + key = predefined_key; |
| + return; |
| + } |
| + HRESULT hr = RegOpenKeyExW(predefined_key, key_name.c_str(), 0, KEY_QUERY_VALUE, &key); |
| + if (hr != ERROR_SUCCESS || !key) |
| + { |
| + throw std::runtime_error("Failure in RegOpenKeyExW"); |
| + } |
| +} |
| + |
| +Registry_Key::Registry_Key(Predefined root) |
| + : key(predefined_hkeys[(unsigned int) root ]), is_predefined(true) |
| +{ |
| +} |
| + |
| +Registry_Key::~Registry_Key() |
| +{ |
| + if (!is_predefined) |
| + { |
| + RegCloseKey(key); |
| + } |
| +} |
| + |
| +std::wstring Registry_Key::value_wstring(std::wstring name) const |
| +{ |
| + /* |
| + * Step one is to determine the presence of the value, along with its type and byte size. |
| + */ |
| + DWORD type; |
| + DWORD size = 0; |
| + HRESULT hr = ::RegQueryValueExW(static_cast<HKEY>(key), name.c_str(), 0, &type, 0, &size); |
| + if (hr != ERROR_SUCCESS) |
| + { |
| + throw std::runtime_error("Failure in RegQueryValueEx to query name"); |
| + } |
| + if (type != REG_SZ) |
| + { |
| + throw std::runtime_error("Value is not string type"); |
| + } |
| + |
| + /* |
| + * Step two is to allocate a buffer for the string and query for its value. |
| + * Note that 'size' is the size in bytes, which we need for the system call, |
| + * but that 'psize' is the size in words, which we need to manipulate the wchar_t array 'p'. |
| + */ |
| + // Round the byte size up to the nearest multiple of two. |
| + size = (size + 1) & ~ DWORD(1); |
| + size_t psize = size >> 1; |
| + // We need to allocate a temporary buffer to receive the value, because there's no interface to write directly into the buffer of std::basic_string. |
| + std::unique_ptr< wchar_t[] > p(new wchar_t[ psize ]); |
| + hr = RegQueryValueExW(key, name.c_str(), 0, 0, reinterpret_cast<BYTE*>(p.get()), &size); |
| + if (hr != ERROR_SUCCESS) |
| + { |
| + throw std::runtime_error("Failure in RegQueryValueExW to retrieve value"); |
| + } |
| + |
| + /* |
| + * Step three is to construct a return string. |
| + * |
| + * There's the possibility of an extra terminating null character in the return value of the query. |
| + * If so, we have to decrement the length of the return value to eliminate it. |
| + * If it persists, it will interfere with later string operations such as concatenation. |
| + */ |
| + if (p[ psize - 1 ] == L'\0') |
| + { |
| + --psize; |
| + } |
| + return std::wstring(p.get(), psize); |
| +} |
| + |