Index: src/shared/Registry.cpp |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/src/shared/Registry.cpp |
@@ -0,0 +1,70 @@ |
+#include "Registry.h" |
+#include <memory> |
+ |
+using namespace AdblockPlus; |
+ |
+Registry_Key::Registry_Key(HKEY parent, std::wstring key_name) |
+{ |
+ if (key_name.empty()) |
+ { |
+ throw std::runtime_error("key_name may not be empty"); |
+ } |
+ HRESULT hr = RegOpenKeyExW(parent, 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() |
+{ |
+ 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"); |
sergei
2014/07/28 11:46:27
It's not descriptive. Is it possible to find a roo
Eric
2014/07/29 12:42:25
No, it's not, and it doesn't really matter at the
sergei
2014/07/29 14:45:56
It does always matter.
- There is no real reason t
Eric
2014/07/29 15:17:22
Yes, and when we get unified and regular error han
sergei
2014/07/30 10:42:04
I'm pretty sure that std::system_error can be used
Eric
2014/07/30 13:02:04
It's not the exception that's the main problem, it
|
+ } |
+ if (type != REG_SZ) |
+ { |
+ throw std::runtime_error("Value is not string type"); |
sergei
2014/07/28 11:46:27
The same as above, it's completely not descriptive
|
+ } |
+ |
+ /* |
+ * 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 ]); |
sergei
2014/07/28 11:46:27
not sure about it, One one hand it's correct, but
Eric
2014/07/29 12:42:25
We need an allocated buffer, because writing into
sergei
2014/07/29 14:45:56
But we have already decided, that `&x[0]` is OK fo
Eric
2014/07/29 15:17:22
I am not convinced that we have already decided th
|
+ 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') |
Oleksandr
2014/07/27 22:13:30
Nit: No spaces before and after array index:
if (
|
+ { |
+ --psize; |
+ } |
+ return std::wstring(p.get(), psize); |
+} |
+ |