Index: src/shared/Registry.cpp |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/src/shared/Registry.cpp |
@@ -0,0 +1,91 @@ |
+#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 ) |
Oleksandr
2014/07/25 22:23:46
Formatting in this file is too spacious as well
|
+ : 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 ); |
+} |
+ |
+ |