| 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 ); | 
| +} | 
| + | 
| + |