ipc/chromium/src/base/registry.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial