Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 // All Rights Reserved.
6 #include "base/registry.h"
8 #include <assert.h>
9 #include <shlwapi.h>
10 #include <windows.h>
12 #pragma comment(lib, "shlwapi.lib") // for SHDeleteKey
14 // local types (see the same declarations in the header file)
15 #define tchar TCHAR
16 #define CTP const tchar*
17 #define tstr std::basic_string<tchar>
19 //
20 // RegistryValueIterator
21 //
23 RegistryValueIterator::RegistryValueIterator(HKEY root_key,
24 LPCTSTR folder_key) {
25 LONG result = RegOpenKeyEx(root_key, folder_key, 0, KEY_READ, &key_);
26 if (result != ERROR_SUCCESS) {
27 key_ = NULL;
28 } else {
29 DWORD count = 0;
30 result = ::RegQueryInfoKey(key_, NULL, 0, NULL, NULL, NULL, NULL, &count,
31 NULL, NULL, NULL, NULL);
33 if (result != ERROR_SUCCESS) {
34 ::RegCloseKey(key_);
35 key_ = NULL;
36 } else {
37 index_ = count - 1;
38 }
39 }
41 Read();
42 }
44 RegistryValueIterator::~RegistryValueIterator() {
45 if (key_)
46 ::RegCloseKey(key_);
47 }
49 bool RegistryValueIterator::Valid() const {
50 // true while the iterator is valid
51 return key_ != NULL && index_ >= 0;
52 }
54 void RegistryValueIterator::operator ++ () {
55 // advance to the next entry in the folder
56 --index_;
57 Read();
58 }
60 bool RegistryValueIterator::Read() {
61 if (Valid()) {
62 DWORD ncount = sizeof(name_)/sizeof(*name_);
63 value_size_ = sizeof(value_);
64 LRESULT r = ::RegEnumValue(key_, index_, name_, &ncount, NULL, &type_,
65 reinterpret_cast<BYTE*>(value_), &value_size_);
66 if (ERROR_SUCCESS == r)
67 return true;
68 }
70 name_[0] = '\0';
71 value_[0] = '\0';
72 value_size_ = 0;
73 return false;
74 }
76 DWORD RegistryValueIterator::ValueCount() const {
78 DWORD count = 0;
79 HRESULT result = ::RegQueryInfoKey(key_, NULL, 0, NULL, NULL, NULL, NULL,
80 &count, NULL, NULL, NULL, NULL);
82 if (result != ERROR_SUCCESS)
83 return 0;
85 return count;
86 }
88 //
89 // RegistryKeyIterator
90 //
92 RegistryKeyIterator::RegistryKeyIterator(HKEY root_key,
93 LPCTSTR folder_key) {
94 LONG result = RegOpenKeyEx(root_key, folder_key, 0, KEY_READ, &key_);
95 if (result != ERROR_SUCCESS) {
96 key_ = NULL;
97 } else {
98 DWORD count = 0;
99 HRESULT result = ::RegQueryInfoKey(key_, NULL, 0, NULL, &count, NULL, NULL,
100 NULL, NULL, NULL, NULL, NULL);
102 if (result != ERROR_SUCCESS) {
103 ::RegCloseKey(key_);
104 key_ = NULL;
105 } else {
106 index_ = count - 1;
107 }
108 }
110 Read();
111 }
113 RegistryKeyIterator::~RegistryKeyIterator() {
114 if (key_)
115 ::RegCloseKey(key_);
116 }
118 bool RegistryKeyIterator::Valid() const {
119 // true while the iterator is valid
120 return key_ != NULL && index_ >= 0;
121 }
123 void RegistryKeyIterator::operator ++ () {
124 // advance to the next entry in the folder
125 --index_;
126 Read();
127 }
129 bool RegistryKeyIterator::Read() {
130 if (Valid()) {
131 DWORD ncount = sizeof(name_)/sizeof(*name_);
132 FILETIME written;
133 LRESULT r = ::RegEnumKeyEx(key_, index_, name_, &ncount, NULL, NULL,
134 NULL, &written);
135 if (ERROR_SUCCESS == r)
136 return true;
137 }
139 name_[0] = '\0';
140 return false;
141 }
143 DWORD RegistryKeyIterator::SubkeyCount() const {
145 DWORD count = 0;
146 HRESULT result = ::RegQueryInfoKey(key_, NULL, 0, NULL, &count, NULL, NULL,
147 NULL, NULL, NULL, NULL, NULL);
149 if (result != ERROR_SUCCESS)
150 return 0;
152 return count;
153 }
155 //
156 // RegKey
157 //
159 RegKey::RegKey(HKEY rootkey, const tchar* subkey, REGSAM access)
160 : key_(NULL), watch_event_(0) {
161 if (rootkey) {
162 if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK))
163 this->Create(rootkey, subkey, access);
164 else
165 this->Open(rootkey, subkey, access);
166 }
167 else assert(!subkey);
168 }
170 void RegKey::Close() {
171 StopWatching();
172 if (key_) {
173 ::RegCloseKey(key_);
174 key_ = NULL;
175 }
176 }
178 bool RegKey::Create(HKEY rootkey, const tchar* subkey, REGSAM access) {
179 DWORD disposition_value;
180 return CreateWithDisposition(rootkey, subkey, &disposition_value, access);
181 }
183 bool RegKey::CreateWithDisposition(HKEY rootkey, const tchar* subkey,
184 DWORD* disposition, REGSAM access) {
185 assert(rootkey && subkey && access && disposition);
186 this->Close();
188 LONG const result = RegCreateKeyEx(rootkey,
189 subkey,
190 0,
191 NULL,
192 REG_OPTION_NON_VOLATILE,
193 access,
194 NULL,
195 &key_,
196 disposition );
197 if (result != ERROR_SUCCESS) {
198 key_ = NULL;
199 return false;
200 }
201 else return true;
202 }
204 bool RegKey::Open(HKEY rootkey, const tchar* subkey, REGSAM access) {
205 assert(rootkey && subkey && access);
206 this->Close();
208 LONG const result = RegOpenKeyEx(rootkey, subkey, 0,
209 access, &key_ );
210 if (result != ERROR_SUCCESS) {
211 key_ = NULL;
212 return false;
213 }
214 else return true;
215 }
217 bool RegKey::CreateKey(const tchar* name, REGSAM access) {
218 assert(name && access);
220 HKEY subkey = NULL;
221 LONG const result = RegCreateKeyEx(key_, name, 0, NULL,
222 REG_OPTION_NON_VOLATILE,
223 access, NULL, &subkey, NULL);
224 this->Close();
226 key_ = subkey;
227 return (result == ERROR_SUCCESS);
228 }
230 bool RegKey::OpenKey(const tchar* name, REGSAM access) {
231 assert(name && access);
233 HKEY subkey = NULL;
234 LONG const result = RegOpenKeyEx(key_, name, 0, access, &subkey);
236 this->Close();
238 key_ = subkey;
239 return (result == ERROR_SUCCESS);
240 }
242 DWORD RegKey::ValueCount() {
243 DWORD count = 0;
244 HRESULT const result = ::RegQueryInfoKey(key_, NULL, 0, NULL, NULL, NULL,
245 NULL, &count, NULL, NULL, NULL, NULL);
246 return (result != ERROR_SUCCESS) ? 0 : count;
247 }
249 bool RegKey::ReadName(int index, tstr* name) {
250 tchar buf[256];
251 DWORD bufsize = sizeof(buf)/sizeof(*buf);
252 LRESULT r = ::RegEnumValue(key_, index, buf, &bufsize, NULL, NULL,
253 NULL, NULL);
254 if (r != ERROR_SUCCESS)
255 return false;
256 if (name)
257 *name = buf;
258 return true;
259 }
261 bool RegKey::ValueExists(const tchar* name) {
262 if (!key_) return false;
263 const HRESULT result = RegQueryValueEx(key_, name, 0, NULL, NULL, NULL);
264 return (result == ERROR_SUCCESS);
265 }
267 bool RegKey::ReadValue(const tchar* name, void* data,
268 DWORD* dsize, DWORD* dtype) {
269 if (!key_) return false;
270 HRESULT const result = RegQueryValueEx(key_, name, 0, dtype,
271 reinterpret_cast<LPBYTE>(data),
272 dsize);
273 return (result == ERROR_SUCCESS);
274 }
276 bool RegKey::ReadValue(const tchar* name, tstr * value) {
277 assert(value);
278 static const size_t kMaxStringLength = 1024; // This is after expansion.
279 // Use the one of the other forms of ReadValue if 1024 is too small for you.
280 TCHAR raw_value[kMaxStringLength];
281 DWORD type = REG_SZ, size = sizeof(raw_value);
282 if (this->ReadValue(name, raw_value, &size, &type)) {
283 if (type == REG_SZ) {
284 *value = raw_value;
285 } else if (type == REG_EXPAND_SZ) {
286 TCHAR expanded[kMaxStringLength];
287 size = ExpandEnvironmentStrings(raw_value, expanded, kMaxStringLength);
288 // Success: returns the number of TCHARs copied
289 // Fail: buffer too small, returns the size required
290 // Fail: other, returns 0
291 if (size == 0 || size > kMaxStringLength)
292 return false;
293 *value = expanded;
294 } else {
295 // Not a string. Oops.
296 return false;
297 }
298 return true;
299 }
300 else return false;
301 }
303 bool RegKey::ReadValueDW(const tchar* name, DWORD * value) {
304 assert(value);
305 DWORD type = REG_DWORD, size = sizeof(DWORD), result = 0;
306 if (this->ReadValue(name, &result, &size, &type)
307 && (type == REG_DWORD || type == REG_BINARY)
308 && size == sizeof(DWORD)) {
309 *value = result;
310 return true;
311 }
312 else return false;
313 }
315 bool RegKey::WriteValue(const tchar* name,
316 const void * data,
317 DWORD dsize,
318 DWORD dtype) {
319 assert(data);
320 if (!key_) return false;
321 HRESULT const result = RegSetValueEx(
322 key_,
323 name,
324 0,
325 dtype,
326 reinterpret_cast<LPBYTE>(const_cast<void*>(data)),
327 dsize);
328 return (result == ERROR_SUCCESS);
329 }
331 bool RegKey::WriteValue(const tchar * name, const tchar * value) {
332 return this->WriteValue(name, value,
333 static_cast<DWORD>(sizeof(*value) * (_tcslen(value) + 1)), REG_SZ);
334 }
336 bool RegKey::WriteValue(const tchar * name, DWORD value) {
337 return this->WriteValue(name, &value,
338 static_cast<DWORD>(sizeof(value)), REG_DWORD);
339 }
341 bool RegKey::DeleteKey(const tchar * name) {
342 if (!key_) return false;
343 return (ERROR_SUCCESS == SHDeleteKey(key_, name));
344 }
347 bool RegKey::DeleteValue(const tchar * value_name) {
348 assert(value_name);
349 HRESULT const result = RegDeleteValue(key_, value_name);
350 return (result == ERROR_SUCCESS);
351 }
353 bool RegKey::StartWatching() {
354 if (!watch_event_)
355 watch_event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
357 DWORD filter = REG_NOTIFY_CHANGE_NAME |
358 REG_NOTIFY_CHANGE_ATTRIBUTES |
359 REG_NOTIFY_CHANGE_LAST_SET |
360 REG_NOTIFY_CHANGE_SECURITY;
362 // Watch the registry key for a change of value.
363 HRESULT result = RegNotifyChangeKeyValue(key_, TRUE, filter,
364 watch_event_, TRUE);
365 if (SUCCEEDED(result)) {
366 return true;
367 } else {
368 CloseHandle(watch_event_);
369 watch_event_ = 0;
370 return false;
371 }
372 }
374 bool RegKey::StopWatching() {
375 if (watch_event_) {
376 CloseHandle(watch_event_);
377 watch_event_ = 0;
378 return true;
379 }
380 return false;
381 }
383 bool RegKey::HasChanged() {
384 if (watch_event_) {
385 if (WaitForSingleObject(watch_event_, 0) == WAIT_OBJECT_0) {
386 StartWatching();
387 return true;
388 }
389 }
390 return false;
391 }
393 // Register a COM object with the most usual properties.
394 bool RegisterCOMServer(const tchar* guid,
395 const tchar* name,
396 const tchar* path) {
397 RegKey key(HKEY_CLASSES_ROOT, _T("CLSID"), KEY_WRITE);
398 key.CreateKey(guid, KEY_WRITE);
399 key.WriteValue(NULL, name);
400 key.CreateKey(_T("InprocServer32"), KEY_WRITE);
401 key.WriteValue(NULL, path);
402 key.WriteValue(_T("ThreadingModel"), _T("Apartment"));
403 return true;
404 }
406 bool RegisterCOMServer(const tchar* guid, const tchar* name, HINSTANCE module) {
407 tchar module_path[MAX_PATH];
408 ::GetModuleFileName(module, module_path, MAX_PATH);
409 _tcslwr_s(module_path, MAX_PATH);
410 return RegisterCOMServer(guid, name, module_path);
411 }
413 bool UnregisterCOMServer(const tchar* guid) {
414 RegKey key(HKEY_CLASSES_ROOT, _T("CLSID"), KEY_WRITE);
415 key.DeleteKey(guid);
416 return true;
417 }