LEFT | RIGHT |
1 #include "Registry.h" | 1 #include "Registry.h" |
2 #include <memory> | 2 #include <memory> |
3 | 3 |
4 using namespace AdblockPlus; | 4 using namespace AdblockPlus; |
5 | 5 |
6 static HKEY predefined_hkeys[5] = | 6 RegistryKey::RegistryKey(HKEY parent, const std::wstring& key_name) |
7 { | 7 { |
8 HKEY_CLASSES_ROOT, | 8 if (key_name.empty()) |
9 HKEY_CURRENT_CONFIG, | |
10 HKEY_CURRENT_USER, | |
11 HKEY_LOCAL_MACHINE, | |
12 HKEY_USERS | |
13 }; | |
14 | |
15 Registry_Key::Registry_Key(Predefined root, std::wstring key_name) | |
16 : is_predefined(key_name.empty()) | |
17 { | |
18 auto predefined_key(predefined_hkeys[(unsigned int) root ]); | |
19 if (is_predefined) | |
20 { | 9 { |
21 key = predefined_key; | 10 throw std::runtime_error("key_name may not be empty"); |
22 return; | |
23 } | 11 } |
24 HRESULT hr = RegOpenKeyExW(predefined_key, key_name.c_str(), 0, KEY_QUERY_VALU
E, &key); | 12 HRESULT hr = RegOpenKeyExW(parent, key_name.c_str(), 0, KEY_QUERY_VALUE, &key)
; |
25 if (hr != ERROR_SUCCESS || !key) | 13 if (hr != ERROR_SUCCESS || !key) |
26 { | 14 { |
27 throw std::runtime_error("Failure in RegOpenKeyExW"); | 15 throw std::runtime_error("Failure in RegOpenKeyExW"); |
28 } | 16 } |
29 } | 17 } |
30 | 18 |
31 Registry_Key::Registry_Key(Predefined root) | 19 RegistryKey::~RegistryKey() |
32 : key(predefined_hkeys[(unsigned int) root ]), is_predefined(true) | |
33 { | 20 { |
| 21 RegCloseKey(key); |
34 } | 22 } |
35 | 23 |
36 Registry_Key::~Registry_Key() | 24 std::wstring RegistryKey::value_wstring(const std::wstring& name) const |
37 { | |
38 if (!is_predefined) | |
39 { | |
40 RegCloseKey(key); | |
41 } | |
42 } | |
43 | |
44 std::wstring Registry_Key::value_wstring(std::wstring name) const | |
45 { | 25 { |
46 /* | 26 /* |
47 * Step one is to determine the presence of the value, along with its type and
byte size. | 27 * Step one is to determine the presence of the value, along with its type and
byte size. |
48 */ | 28 */ |
49 DWORD type; | 29 DWORD type; |
50 DWORD size = 0; | 30 DWORD size = 0; |
51 HRESULT hr = ::RegQueryValueExW(static_cast<HKEY>(key), name.c_str(), 0, &type
, 0, &size); | 31 HRESULT hr = ::RegQueryValueExW(static_cast<HKEY>(key), name.c_str(), 0, &type
, 0, &size); |
52 if (hr != ERROR_SUCCESS) | 32 if (hr != ERROR_SUCCESS) |
53 { | 33 { |
54 throw std::runtime_error("Failure in RegQueryValueEx to query name"); | 34 throw std::runtime_error("Failure in RegQueryValueEx to query name"); |
55 } | 35 } |
56 if (type != REG_SZ) | 36 if (type != REG_SZ) |
57 { | 37 { |
58 throw std::runtime_error("Value is not string type"); | 38 throw std::runtime_error("Value is not string type"); |
59 } | 39 } |
60 | 40 |
61 /* | 41 /* |
62 * Step two is to allocate a buffer for the string and query for its value. | 42 * Step two is to allocate a buffer for the string and query for its value. |
63 * Note that 'size' is the size in bytes, which we need for the system call, | 43 * Note that 'size' is the size in bytes, which we need for the system call, |
64 * but that 'psize' is the size in words, which we need to manipulate the wc
har_t array 'p'. | 44 * but that 'psize' is the size in words, which we need to manipulate the wc
har_t array 'p'. |
65 */ | 45 */ |
| 46 size_t psize = (size + 1)/2; |
66 // Round the byte size up to the nearest multiple of two. | 47 // Round the byte size up to the nearest multiple of two. |
67 size = (size + 1) & ~ DWORD(1); | 48 size = 2 * psize; |
68 size_t psize = size >> 1; | |
69 // 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. | 49 // 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. |
70 std::unique_ptr< wchar_t[] > p(new wchar_t[ psize ]); | 50 std::unique_ptr<wchar_t[]> p(new wchar_t[psize]); |
71 hr = RegQueryValueExW(key, name.c_str(), 0, 0, reinterpret_cast<BYTE*>(p.get()
), &size); | 51 hr = RegQueryValueExW(key, name.c_str(), 0, 0, reinterpret_cast<BYTE*>(p.get()
), &size); |
72 if (hr != ERROR_SUCCESS) | 52 if (hr != ERROR_SUCCESS) |
73 { | 53 { |
74 throw std::runtime_error("Failure in RegQueryValueExW to retrieve value"); | 54 throw std::runtime_error("Failure in RegQueryValueExW to retrieve value"); |
75 } | 55 } |
76 | 56 |
77 /* | 57 /* |
78 * Step three is to construct a return string. | 58 * Step three is to construct a return string. |
79 * | 59 * |
80 * There's the possibility of an extra terminating null character in the retur
n value of the query. | 60 * There's the possibility of an extra terminating null character in the retur
n value of the query. |
81 * If so, we have to decrement the length of the return value to eliminate it. | 61 * If so, we have to decrement the length of the return value to eliminate it. |
82 * If it persists, it will interfere with later string operations such as conc
atenation. | 62 * If it persists, it will interfere with later string operations such as conc
atenation. |
83 */ | 63 */ |
84 if (p[ psize - 1 ] == L'\0') | 64 if (p[psize - 1] == L'\0') |
85 { | 65 { |
86 --psize; | 66 --psize; |
87 } | 67 } |
88 return std::wstring(p.get(), psize); | 68 return std::wstring(p.get(), psize); |
89 } | 69 } |
90 | 70 |
LEFT | RIGHT |