| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2003 The WebRTC Project Authors. All rights reserved. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license | |
| 5 * that can be found in the LICENSE file in the root of the source | |
| 6 * tree. An additional intellectual property rights grant can be found | |
| 7 * in the file PATENTS. All contributing project authors may | |
| 8 * be found in the AUTHORS file in the root of the source tree. | |
| 9 */ | |
| 10 | |
| 11 // Registry configuration wrapers class implementation | |
| 12 // | |
| 13 // Change made by S. Ganesh - ganesh@google.com: | |
| 14 // Use SHQueryValueEx instead of RegQueryValueEx throughout. | |
| 15 // A call to the SHLWAPI function is essentially a call to the standard | |
| 16 // function but with post-processing: | |
| 17 // * to fix REG_SZ or REG_EXPAND_SZ data that is not properly null-terminated; | |
| 18 // * to expand REG_EXPAND_SZ data. | |
| 19 | |
| 20 #include "webrtc/base/win32regkey.h" | |
| 21 | |
| 22 #include <shlwapi.h> | |
| 23 | |
| 24 #include <memory> | |
| 25 | |
| 26 #include "webrtc/base/common.h" | |
| 27 #include "webrtc/base/logging.h" | |
| 28 | |
| 29 namespace rtc { | |
| 30 | |
| 31 RegKey::RegKey() { | |
| 32 h_key_ = NULL; | |
| 33 } | |
| 34 | |
| 35 RegKey::~RegKey() { | |
| 36 Close(); | |
| 37 } | |
| 38 | |
| 39 HRESULT RegKey::Create(HKEY parent_key, const wchar_t* key_name) { | |
| 40 return Create(parent_key, | |
| 41 key_name, | |
| 42 REG_NONE, | |
| 43 REG_OPTION_NON_VOLATILE, | |
| 44 KEY_ALL_ACCESS, | |
| 45 NULL, | |
| 46 NULL); | |
| 47 } | |
| 48 | |
| 49 HRESULT RegKey::Open(HKEY parent_key, const wchar_t* key_name) { | |
| 50 return Open(parent_key, key_name, KEY_ALL_ACCESS); | |
| 51 } | |
| 52 | |
| 53 bool RegKey::HasValue(const TCHAR* value_name) const { | |
| 54 return (ERROR_SUCCESS == ::RegQueryValueEx(h_key_, value_name, NULL, | |
| 55 NULL, NULL, NULL)); | |
| 56 } | |
| 57 | |
| 58 HRESULT RegKey::SetValue(const wchar_t* full_key_name, | |
| 59 const wchar_t* value_name, | |
| 60 DWORD value) { | |
| 61 ASSERT(full_key_name != NULL); | |
| 62 | |
| 63 return SetValueStaticHelper(full_key_name, value_name, REG_DWORD, &value); | |
| 64 } | |
| 65 | |
| 66 HRESULT RegKey::SetValue(const wchar_t* full_key_name, | |
| 67 const wchar_t* value_name, | |
| 68 DWORD64 value) { | |
| 69 ASSERT(full_key_name != NULL); | |
| 70 | |
| 71 return SetValueStaticHelper(full_key_name, value_name, REG_QWORD, &value); | |
| 72 } | |
| 73 | |
| 74 HRESULT RegKey::SetValue(const wchar_t* full_key_name, | |
| 75 const wchar_t* value_name, | |
| 76 float value) { | |
| 77 ASSERT(full_key_name != NULL); | |
| 78 | |
| 79 return SetValueStaticHelper(full_key_name, value_name, | |
| 80 REG_BINARY, &value, sizeof(value)); | |
| 81 } | |
| 82 | |
| 83 HRESULT RegKey::SetValue(const wchar_t* full_key_name, | |
| 84 const wchar_t* value_name, | |
| 85 double value) { | |
| 86 ASSERT(full_key_name != NULL); | |
| 87 | |
| 88 return SetValueStaticHelper(full_key_name, value_name, | |
| 89 REG_BINARY, &value, sizeof(value)); | |
| 90 } | |
| 91 | |
| 92 HRESULT RegKey::SetValue(const wchar_t* full_key_name, | |
| 93 const wchar_t* value_name, | |
| 94 const TCHAR* value) { | |
| 95 ASSERT(full_key_name != NULL); | |
| 96 ASSERT(value != NULL); | |
| 97 | |
| 98 return SetValueStaticHelper(full_key_name, value_name, | |
| 99 REG_SZ, const_cast<wchar_t*>(value)); | |
| 100 } | |
| 101 | |
| 102 HRESULT RegKey::SetValue(const wchar_t* full_key_name, | |
| 103 const wchar_t* value_name, | |
| 104 const uint8_t* value, | |
| 105 DWORD byte_count) { | |
| 106 ASSERT(full_key_name != NULL); | |
| 107 | |
| 108 return SetValueStaticHelper(full_key_name, value_name, REG_BINARY, | |
| 109 const_cast<uint8_t*>(value), byte_count); | |
| 110 } | |
| 111 | |
| 112 HRESULT RegKey::SetValueMultiSZ(const wchar_t* full_key_name, | |
| 113 const wchar_t* value_name, | |
| 114 const uint8_t* value, | |
| 115 DWORD byte_count) { | |
| 116 ASSERT(full_key_name != NULL); | |
| 117 | |
| 118 return SetValueStaticHelper(full_key_name, value_name, REG_MULTI_SZ, | |
| 119 const_cast<uint8_t*>(value), byte_count); | |
| 120 } | |
| 121 | |
| 122 HRESULT RegKey::GetValue(const wchar_t* full_key_name, | |
| 123 const wchar_t* value_name, | |
| 124 DWORD* value) { | |
| 125 ASSERT(full_key_name != NULL); | |
| 126 ASSERT(value != NULL); | |
| 127 | |
| 128 return GetValueStaticHelper(full_key_name, value_name, REG_DWORD, value); | |
| 129 } | |
| 130 | |
| 131 HRESULT RegKey::GetValue(const wchar_t* full_key_name, | |
| 132 const wchar_t* value_name, | |
| 133 DWORD64* value) { | |
| 134 ASSERT(full_key_name != NULL); | |
| 135 ASSERT(value != NULL); | |
| 136 | |
| 137 return GetValueStaticHelper(full_key_name, value_name, REG_QWORD, value); | |
| 138 } | |
| 139 | |
| 140 HRESULT RegKey::GetValue(const wchar_t* full_key_name, | |
| 141 const wchar_t* value_name, | |
| 142 float* value) { | |
| 143 ASSERT(value != NULL); | |
| 144 ASSERT(full_key_name != NULL); | |
| 145 | |
| 146 DWORD byte_count = 0; | |
| 147 byte* buffer_raw = nullptr; | |
| 148 HRESULT hr = GetValueStaticHelper(full_key_name, value_name, | |
| 149 REG_BINARY, &buffer_raw, &byte_count); | |
| 150 std::unique_ptr<byte[]> buffer(buffer_raw); | |
| 151 if (SUCCEEDED(hr)) { | |
| 152 ASSERT(byte_count == sizeof(*value)); | |
| 153 if (byte_count == sizeof(*value)) { | |
| 154 *value = *reinterpret_cast<float*>(buffer.get()); | |
| 155 } | |
| 156 } | |
| 157 return hr; | |
| 158 } | |
| 159 | |
| 160 HRESULT RegKey::GetValue(const wchar_t* full_key_name, | |
| 161 const wchar_t* value_name, | |
| 162 double* value) { | |
| 163 ASSERT(value != NULL); | |
| 164 ASSERT(full_key_name != NULL); | |
| 165 | |
| 166 DWORD byte_count = 0; | |
| 167 byte* buffer_raw = nullptr; | |
| 168 HRESULT hr = GetValueStaticHelper(full_key_name, value_name, | |
| 169 REG_BINARY, &buffer_raw, &byte_count); | |
| 170 std::unique_ptr<byte[]> buffer(buffer_raw); | |
| 171 if (SUCCEEDED(hr)) { | |
| 172 ASSERT(byte_count == sizeof(*value)); | |
| 173 if (byte_count == sizeof(*value)) { | |
| 174 *value = *reinterpret_cast<double*>(buffer.get()); | |
| 175 } | |
| 176 } | |
| 177 return hr; | |
| 178 } | |
| 179 | |
| 180 HRESULT RegKey::GetValue(const wchar_t* full_key_name, | |
| 181 const wchar_t* value_name, | |
| 182 wchar_t** value) { | |
| 183 ASSERT(full_key_name != NULL); | |
| 184 ASSERT(value != NULL); | |
| 185 | |
| 186 return GetValueStaticHelper(full_key_name, value_name, REG_SZ, value); | |
| 187 } | |
| 188 | |
| 189 HRESULT RegKey::GetValue(const wchar_t* full_key_name, | |
| 190 const wchar_t* value_name, | |
| 191 std::wstring* value) { | |
| 192 ASSERT(full_key_name != NULL); | |
| 193 ASSERT(value != NULL); | |
| 194 | |
| 195 wchar_t* buffer_raw = nullptr; | |
| 196 HRESULT hr = RegKey::GetValue(full_key_name, value_name, &buffer_raw); | |
| 197 std::unique_ptr<wchar_t[]> buffer(buffer_raw); | |
| 198 if (SUCCEEDED(hr)) { | |
| 199 value->assign(buffer.get()); | |
| 200 } | |
| 201 return hr; | |
| 202 } | |
| 203 | |
| 204 HRESULT RegKey::GetValue(const wchar_t* full_key_name, | |
| 205 const wchar_t* value_name, | |
| 206 std::vector<std::wstring>* value) { | |
| 207 ASSERT(full_key_name != NULL); | |
| 208 ASSERT(value != NULL); | |
| 209 | |
| 210 return GetValueStaticHelper(full_key_name, value_name, REG_MULTI_SZ, value); | |
| 211 } | |
| 212 | |
| 213 HRESULT RegKey::GetValue(const wchar_t* full_key_name, | |
| 214 const wchar_t* value_name, | |
| 215 uint8_t** value, | |
| 216 DWORD* byte_count) { | |
| 217 ASSERT(full_key_name != NULL); | |
| 218 ASSERT(value != NULL); | |
| 219 ASSERT(byte_count != NULL); | |
| 220 | |
| 221 return GetValueStaticHelper(full_key_name, value_name, | |
| 222 REG_BINARY, value, byte_count); | |
| 223 } | |
| 224 | |
| 225 HRESULT RegKey::DeleteSubKey(const wchar_t* key_name) { | |
| 226 ASSERT(key_name != NULL); | |
| 227 ASSERT(h_key_ != NULL); | |
| 228 | |
| 229 LONG res = ::RegDeleteKey(h_key_, key_name); | |
| 230 HRESULT hr = HRESULT_FROM_WIN32(res); | |
| 231 if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) || | |
| 232 hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) { | |
| 233 hr = S_FALSE; | |
| 234 } | |
| 235 return hr; | |
| 236 } | |
| 237 | |
| 238 HRESULT RegKey::DeleteValue(const wchar_t* value_name) { | |
| 239 ASSERT(h_key_ != NULL); | |
| 240 | |
| 241 LONG res = ::RegDeleteValue(h_key_, value_name); | |
| 242 HRESULT hr = HRESULT_FROM_WIN32(res); | |
| 243 if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) || | |
| 244 hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) { | |
| 245 hr = S_FALSE; | |
| 246 } | |
| 247 return hr; | |
| 248 } | |
| 249 | |
| 250 HRESULT RegKey::Close() { | |
| 251 HRESULT hr = S_OK; | |
| 252 if (h_key_ != NULL) { | |
| 253 LONG res = ::RegCloseKey(h_key_); | |
| 254 hr = HRESULT_FROM_WIN32(res); | |
| 255 h_key_ = NULL; | |
| 256 } | |
| 257 return hr; | |
| 258 } | |
| 259 | |
| 260 HRESULT RegKey::Create(HKEY parent_key, | |
| 261 const wchar_t* key_name, | |
| 262 wchar_t* lpszClass, | |
| 263 DWORD options, | |
| 264 REGSAM sam_desired, | |
| 265 LPSECURITY_ATTRIBUTES lpSecAttr, | |
| 266 LPDWORD lpdwDisposition) { | |
| 267 ASSERT(key_name != NULL); | |
| 268 ASSERT(parent_key != NULL); | |
| 269 | |
| 270 DWORD dw = 0; | |
| 271 HKEY h_key = NULL; | |
| 272 LONG res = ::RegCreateKeyEx(parent_key, key_name, 0, lpszClass, options, | |
| 273 sam_desired, lpSecAttr, &h_key, &dw); | |
| 274 HRESULT hr = HRESULT_FROM_WIN32(res); | |
| 275 | |
| 276 if (lpdwDisposition) { | |
| 277 *lpdwDisposition = dw; | |
| 278 } | |
| 279 | |
| 280 // we have to close the currently opened key | |
| 281 // before replacing it with the new one | |
| 282 if (hr == S_OK) { | |
| 283 hr = Close(); | |
| 284 ASSERT(hr == S_OK); | |
| 285 h_key_ = h_key; | |
| 286 } | |
| 287 return hr; | |
| 288 } | |
| 289 | |
| 290 HRESULT RegKey::Open(HKEY parent_key, | |
| 291 const wchar_t* key_name, | |
| 292 REGSAM sam_desired) { | |
| 293 ASSERT(key_name != NULL); | |
| 294 ASSERT(parent_key != NULL); | |
| 295 | |
| 296 HKEY h_key = NULL; | |
| 297 LONG res = ::RegOpenKeyEx(parent_key, key_name, 0, sam_desired, &h_key); | |
| 298 HRESULT hr = HRESULT_FROM_WIN32(res); | |
| 299 | |
| 300 // we have to close the currently opened key | |
| 301 // before replacing it with the new one | |
| 302 if (hr == S_OK) { | |
| 303 // close the currently opened key if any | |
| 304 hr = Close(); | |
| 305 ASSERT(hr == S_OK); | |
| 306 h_key_ = h_key; | |
| 307 } | |
| 308 return hr; | |
| 309 } | |
| 310 | |
| 311 // save the key and all of its subkeys and values to a file | |
| 312 HRESULT RegKey::Save(const wchar_t* full_key_name, const wchar_t* file_name) { | |
| 313 ASSERT(full_key_name != NULL); | |
| 314 ASSERT(file_name != NULL); | |
| 315 | |
| 316 std::wstring key_name(full_key_name); | |
| 317 HKEY h_key = GetRootKeyInfo(&key_name); | |
| 318 if (!h_key) { | |
| 319 return E_FAIL; | |
| 320 } | |
| 321 | |
| 322 RegKey key; | |
| 323 HRESULT hr = key.Open(h_key, key_name.c_str(), KEY_READ); | |
| 324 if (FAILED(hr)) { | |
| 325 return hr; | |
| 326 } | |
| 327 | |
| 328 AdjustCurrentProcessPrivilege(SE_BACKUP_NAME, true); | |
| 329 LONG res = ::RegSaveKey(key.h_key_, file_name, NULL); | |
| 330 AdjustCurrentProcessPrivilege(SE_BACKUP_NAME, false); | |
| 331 | |
| 332 return HRESULT_FROM_WIN32(res); | |
| 333 } | |
| 334 | |
| 335 // restore the key and all of its subkeys and values which are saved into a file | |
| 336 HRESULT RegKey::Restore(const wchar_t* full_key_name, | |
| 337 const wchar_t* file_name) { | |
| 338 ASSERT(full_key_name != NULL); | |
| 339 ASSERT(file_name != NULL); | |
| 340 | |
| 341 std::wstring key_name(full_key_name); | |
| 342 HKEY h_key = GetRootKeyInfo(&key_name); | |
| 343 if (!h_key) { | |
| 344 return E_FAIL; | |
| 345 } | |
| 346 | |
| 347 RegKey key; | |
| 348 HRESULT hr = key.Open(h_key, key_name.c_str(), KEY_WRITE); | |
| 349 if (FAILED(hr)) { | |
| 350 return hr; | |
| 351 } | |
| 352 | |
| 353 AdjustCurrentProcessPrivilege(SE_RESTORE_NAME, true); | |
| 354 LONG res = ::RegRestoreKey(key.h_key_, file_name, REG_FORCE_RESTORE); | |
| 355 AdjustCurrentProcessPrivilege(SE_RESTORE_NAME, false); | |
| 356 | |
| 357 return HRESULT_FROM_WIN32(res); | |
| 358 } | |
| 359 | |
| 360 // check if the current key has the specified subkey | |
| 361 bool RegKey::HasSubkey(const wchar_t* key_name) const { | |
| 362 ASSERT(key_name != NULL); | |
| 363 | |
| 364 RegKey key; | |
| 365 HRESULT hr = key.Open(h_key_, key_name, KEY_READ); | |
| 366 key.Close(); | |
| 367 return hr == S_OK; | |
| 368 } | |
| 369 | |
| 370 // static flush key | |
| 371 HRESULT RegKey::FlushKey(const wchar_t* full_key_name) { | |
| 372 ASSERT(full_key_name != NULL); | |
| 373 | |
| 374 HRESULT hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); | |
| 375 // get the root HKEY | |
| 376 std::wstring key_name(full_key_name); | |
| 377 HKEY h_key = GetRootKeyInfo(&key_name); | |
| 378 | |
| 379 if (h_key != NULL) { | |
| 380 LONG res = ::RegFlushKey(h_key); | |
| 381 hr = HRESULT_FROM_WIN32(res); | |
| 382 } | |
| 383 return hr; | |
| 384 } | |
| 385 | |
| 386 // static SET helper | |
| 387 HRESULT RegKey::SetValueStaticHelper(const wchar_t* full_key_name, | |
| 388 const wchar_t* value_name, | |
| 389 DWORD type, | |
| 390 LPVOID value, | |
| 391 DWORD byte_count) { | |
| 392 ASSERT(full_key_name != NULL); | |
| 393 | |
| 394 HRESULT hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); | |
| 395 // get the root HKEY | |
| 396 std::wstring key_name(full_key_name); | |
| 397 HKEY h_key = GetRootKeyInfo(&key_name); | |
| 398 | |
| 399 if (h_key != NULL) { | |
| 400 RegKey key; | |
| 401 hr = key.Create(h_key, key_name.c_str()); | |
| 402 if (hr == S_OK) { | |
| 403 switch (type) { | |
| 404 case REG_DWORD: | |
| 405 hr = key.SetValue(value_name, *(static_cast<DWORD*>(value))); | |
| 406 break; | |
| 407 case REG_QWORD: | |
| 408 hr = key.SetValue(value_name, *(static_cast<DWORD64*>(value))); | |
| 409 break; | |
| 410 case REG_SZ: | |
| 411 hr = key.SetValue(value_name, static_cast<const wchar_t*>(value)); | |
| 412 break; | |
| 413 case REG_BINARY: | |
| 414 hr = key.SetValue(value_name, static_cast<const uint8_t*>(value), | |
| 415 byte_count); | |
| 416 break; | |
| 417 case REG_MULTI_SZ: | |
| 418 hr = key.SetValue(value_name, static_cast<const uint8_t*>(value), | |
| 419 byte_count, type); | |
| 420 break; | |
| 421 default: | |
| 422 ASSERT(false); | |
| 423 hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH); | |
| 424 break; | |
| 425 } | |
| 426 // close the key after writing | |
| 427 HRESULT temp_hr = key.Close(); | |
| 428 if (hr == S_OK) { | |
| 429 hr = temp_hr; | |
| 430 } | |
| 431 } | |
| 432 } | |
| 433 return hr; | |
| 434 } | |
| 435 | |
| 436 // static GET helper | |
| 437 HRESULT RegKey::GetValueStaticHelper(const wchar_t* full_key_name, | |
| 438 const wchar_t* value_name, | |
| 439 DWORD type, | |
| 440 LPVOID value, | |
| 441 DWORD* byte_count) { | |
| 442 ASSERT(full_key_name != NULL); | |
| 443 | |
| 444 HRESULT hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); | |
| 445 // get the root HKEY | |
| 446 std::wstring key_name(full_key_name); | |
| 447 HKEY h_key = GetRootKeyInfo(&key_name); | |
| 448 | |
| 449 if (h_key != NULL) { | |
| 450 RegKey key; | |
| 451 hr = key.Open(h_key, key_name.c_str(), KEY_READ); | |
| 452 if (hr == S_OK) { | |
| 453 switch (type) { | |
| 454 case REG_DWORD: | |
| 455 hr = key.GetValue(value_name, reinterpret_cast<DWORD*>(value)); | |
| 456 break; | |
| 457 case REG_QWORD: | |
| 458 hr = key.GetValue(value_name, reinterpret_cast<DWORD64*>(value)); | |
| 459 break; | |
| 460 case REG_SZ: | |
| 461 hr = key.GetValue(value_name, reinterpret_cast<wchar_t**>(value)); | |
| 462 break; | |
| 463 case REG_MULTI_SZ: | |
| 464 hr = key.GetValue(value_name, reinterpret_cast< | |
| 465 std::vector<std::wstring>*>(value)); | |
| 466 break; | |
| 467 case REG_BINARY: | |
| 468 hr = key.GetValue(value_name, reinterpret_cast<uint8_t**>(value), | |
| 469 byte_count); | |
| 470 break; | |
| 471 default: | |
| 472 ASSERT(false); | |
| 473 hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH); | |
| 474 break; | |
| 475 } | |
| 476 // close the key after writing | |
| 477 HRESULT temp_hr = key.Close(); | |
| 478 if (hr == S_OK) { | |
| 479 hr = temp_hr; | |
| 480 } | |
| 481 } | |
| 482 } | |
| 483 return hr; | |
| 484 } | |
| 485 | |
| 486 // GET helper | |
| 487 HRESULT RegKey::GetValueHelper(const wchar_t* value_name, | |
| 488 DWORD* type, | |
| 489 uint8_t** value, | |
| 490 DWORD* byte_count) const { | |
| 491 ASSERT(byte_count != NULL); | |
| 492 ASSERT(value != NULL); | |
| 493 ASSERT(type != NULL); | |
| 494 | |
| 495 // init return buffer | |
| 496 *value = NULL; | |
| 497 | |
| 498 // get the size of the return data buffer | |
| 499 LONG res = ::SHQueryValueEx(h_key_, value_name, NULL, type, NULL, byte_count); | |
| 500 HRESULT hr = HRESULT_FROM_WIN32(res); | |
| 501 | |
| 502 if (hr == S_OK) { | |
| 503 // if the value length is 0, nothing to do | |
| 504 if (*byte_count != 0) { | |
| 505 // allocate the buffer | |
| 506 *value = new byte[*byte_count]; | |
| 507 ASSERT(*value != NULL); | |
| 508 | |
| 509 // make the call again to get the data | |
| 510 res = ::SHQueryValueEx(h_key_, value_name, NULL, | |
| 511 type, *value, byte_count); | |
| 512 hr = HRESULT_FROM_WIN32(res); | |
| 513 ASSERT(hr == S_OK); | |
| 514 } | |
| 515 } | |
| 516 return hr; | |
| 517 } | |
| 518 | |
| 519 // Int32 Get | |
| 520 HRESULT RegKey::GetValue(const wchar_t* value_name, DWORD* value) const { | |
| 521 ASSERT(value != NULL); | |
| 522 | |
| 523 DWORD type = 0; | |
| 524 DWORD byte_count = sizeof(DWORD); | |
| 525 LONG res = ::SHQueryValueEx(h_key_, value_name, NULL, &type, | |
| 526 value, &byte_count); | |
| 527 HRESULT hr = HRESULT_FROM_WIN32(res); | |
| 528 ASSERT((hr != S_OK) || (type == REG_DWORD)); | |
| 529 ASSERT((hr != S_OK) || (byte_count == sizeof(DWORD))); | |
| 530 return hr; | |
| 531 } | |
| 532 | |
| 533 // Int64 Get | |
| 534 HRESULT RegKey::GetValue(const wchar_t* value_name, DWORD64* value) const { | |
| 535 ASSERT(value != NULL); | |
| 536 | |
| 537 DWORD type = 0; | |
| 538 DWORD byte_count = sizeof(DWORD64); | |
| 539 LONG res = ::SHQueryValueEx(h_key_, value_name, NULL, &type, | |
| 540 value, &byte_count); | |
| 541 HRESULT hr = HRESULT_FROM_WIN32(res); | |
| 542 ASSERT((hr != S_OK) || (type == REG_QWORD)); | |
| 543 ASSERT((hr != S_OK) || (byte_count == sizeof(DWORD64))); | |
| 544 return hr; | |
| 545 } | |
| 546 | |
| 547 // String Get | |
| 548 HRESULT RegKey::GetValue(const wchar_t* value_name, wchar_t** value) const { | |
| 549 ASSERT(value != NULL); | |
| 550 | |
| 551 DWORD byte_count = 0; | |
| 552 DWORD type = 0; | |
| 553 | |
| 554 // first get the size of the string buffer | |
| 555 LONG res = ::SHQueryValueEx(h_key_, value_name, NULL, | |
| 556 &type, NULL, &byte_count); | |
| 557 HRESULT hr = HRESULT_FROM_WIN32(res); | |
| 558 | |
| 559 if (hr == S_OK) { | |
| 560 // allocate room for the string and a terminating \0 | |
| 561 *value = new wchar_t[(byte_count / sizeof(wchar_t)) + 1]; | |
| 562 | |
| 563 if ((*value) != NULL) { | |
| 564 if (byte_count != 0) { | |
| 565 // make the call again | |
| 566 res = ::SHQueryValueEx(h_key_, value_name, NULL, &type, | |
| 567 *value, &byte_count); | |
| 568 hr = HRESULT_FROM_WIN32(res); | |
| 569 } else { | |
| 570 (*value)[0] = L'\0'; | |
| 571 } | |
| 572 | |
| 573 ASSERT((hr != S_OK) || (type == REG_SZ) || | |
| 574 (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); | |
| 575 } else { | |
| 576 hr = E_OUTOFMEMORY; | |
| 577 } | |
| 578 } | |
| 579 | |
| 580 return hr; | |
| 581 } | |
| 582 | |
| 583 // get a string value | |
| 584 HRESULT RegKey::GetValue(const wchar_t* value_name, std::wstring* value) const { | |
| 585 ASSERT(value != NULL); | |
| 586 | |
| 587 DWORD byte_count = 0; | |
| 588 DWORD type = 0; | |
| 589 | |
| 590 // first get the size of the string buffer | |
| 591 LONG res = ::SHQueryValueEx(h_key_, value_name, NULL, | |
| 592 &type, NULL, &byte_count); | |
| 593 HRESULT hr = HRESULT_FROM_WIN32(res); | |
| 594 | |
| 595 if (hr == S_OK) { | |
| 596 if (byte_count != 0) { | |
| 597 // Allocate some memory and make the call again | |
| 598 value->resize(byte_count / sizeof(wchar_t) + 1); | |
| 599 res = ::SHQueryValueEx(h_key_, value_name, NULL, &type, | |
| 600 &value->at(0), &byte_count); | |
| 601 hr = HRESULT_FROM_WIN32(res); | |
| 602 value->resize(wcslen(value->data())); | |
| 603 } else { | |
| 604 value->clear(); | |
| 605 } | |
| 606 | |
| 607 ASSERT((hr != S_OK) || (type == REG_SZ) || | |
| 608 (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); | |
| 609 } | |
| 610 | |
| 611 return hr; | |
| 612 } | |
| 613 | |
| 614 // convert REG_MULTI_SZ bytes to string array | |
| 615 HRESULT RegKey::MultiSZBytesToStringArray(const uint8_t* buffer, | |
| 616 DWORD byte_count, | |
| 617 std::vector<std::wstring>* value) { | |
| 618 ASSERT(buffer != NULL); | |
| 619 ASSERT(value != NULL); | |
| 620 | |
| 621 const wchar_t* data = reinterpret_cast<const wchar_t*>(buffer); | |
| 622 DWORD data_len = byte_count / sizeof(wchar_t); | |
| 623 value->clear(); | |
| 624 if (data_len > 1) { | |
| 625 // must be terminated by two null characters | |
| 626 if (data[data_len - 1] != 0 || data[data_len - 2] != 0) { | |
| 627 return E_INVALIDARG; | |
| 628 } | |
| 629 | |
| 630 // put null-terminated strings into arrays | |
| 631 while (*data) { | |
| 632 std::wstring str(data); | |
| 633 value->push_back(str); | |
| 634 data += str.length() + 1; | |
| 635 } | |
| 636 } | |
| 637 return S_OK; | |
| 638 } | |
| 639 | |
| 640 // get a std::vector<std::wstring> value from REG_MULTI_SZ type | |
| 641 HRESULT RegKey::GetValue(const wchar_t* value_name, | |
| 642 std::vector<std::wstring>* value) const { | |
| 643 ASSERT(value != NULL); | |
| 644 | |
| 645 DWORD byte_count = 0; | |
| 646 DWORD type = 0; | |
| 647 uint8_t* buffer = 0; | |
| 648 | |
| 649 // first get the size of the buffer | |
| 650 HRESULT hr = GetValueHelper(value_name, &type, &buffer, &byte_count); | |
| 651 ASSERT((hr != S_OK) || (type == REG_MULTI_SZ)); | |
| 652 | |
| 653 if (SUCCEEDED(hr)) { | |
| 654 hr = MultiSZBytesToStringArray(buffer, byte_count, value); | |
| 655 } | |
| 656 | |
| 657 return hr; | |
| 658 } | |
| 659 | |
| 660 // Binary data Get | |
| 661 HRESULT RegKey::GetValue(const wchar_t* value_name, | |
| 662 uint8_t** value, | |
| 663 DWORD* byte_count) const { | |
| 664 ASSERT(byte_count != NULL); | |
| 665 ASSERT(value != NULL); | |
| 666 | |
| 667 DWORD type = 0; | |
| 668 HRESULT hr = GetValueHelper(value_name, &type, value, byte_count); | |
| 669 ASSERT((hr != S_OK) || (type == REG_MULTI_SZ) || (type == REG_BINARY)); | |
| 670 return hr; | |
| 671 } | |
| 672 | |
| 673 // Raw data get | |
| 674 HRESULT RegKey::GetValue(const wchar_t* value_name, | |
| 675 uint8_t** value, | |
| 676 DWORD* byte_count, | |
| 677 DWORD* type) const { | |
| 678 ASSERT(type != NULL); | |
| 679 ASSERT(byte_count != NULL); | |
| 680 ASSERT(value != NULL); | |
| 681 | |
| 682 return GetValueHelper(value_name, type, value, byte_count); | |
| 683 } | |
| 684 | |
| 685 // Int32 set | |
| 686 HRESULT RegKey::SetValue(const wchar_t* value_name, DWORD value) const { | |
| 687 ASSERT(h_key_ != NULL); | |
| 688 | |
| 689 LONG res = | |
| 690 ::RegSetValueEx(h_key_, value_name, NULL, REG_DWORD, | |
| 691 reinterpret_cast<const uint8_t*>(&value), sizeof(DWORD)); | |
| 692 return HRESULT_FROM_WIN32(res); | |
| 693 } | |
| 694 | |
| 695 // Int64 set | |
| 696 HRESULT RegKey::SetValue(const wchar_t* value_name, DWORD64 value) const { | |
| 697 ASSERT(h_key_ != NULL); | |
| 698 | |
| 699 LONG res = ::RegSetValueEx(h_key_, value_name, NULL, REG_QWORD, | |
| 700 reinterpret_cast<const uint8_t*>(&value), | |
| 701 sizeof(DWORD64)); | |
| 702 return HRESULT_FROM_WIN32(res); | |
| 703 } | |
| 704 | |
| 705 // String set | |
| 706 HRESULT RegKey::SetValue(const wchar_t* value_name, | |
| 707 const wchar_t* value) const { | |
| 708 ASSERT(value != NULL); | |
| 709 ASSERT(h_key_ != NULL); | |
| 710 | |
| 711 LONG res = ::RegSetValueEx(h_key_, value_name, NULL, REG_SZ, | |
| 712 reinterpret_cast<const uint8_t*>(value), | |
| 713 (lstrlen(value) + 1) * sizeof(wchar_t)); | |
| 714 return HRESULT_FROM_WIN32(res); | |
| 715 } | |
| 716 | |
| 717 // Binary data set | |
| 718 HRESULT RegKey::SetValue(const wchar_t* value_name, | |
| 719 const uint8_t* value, | |
| 720 DWORD byte_count) const { | |
| 721 ASSERT(h_key_ != NULL); | |
| 722 | |
| 723 // special case - if 'value' is NULL make sure byte_count is zero | |
| 724 if (value == NULL) { | |
| 725 byte_count = 0; | |
| 726 } | |
| 727 | |
| 728 LONG res = ::RegSetValueEx(h_key_, value_name, NULL, | |
| 729 REG_BINARY, value, byte_count); | |
| 730 return HRESULT_FROM_WIN32(res); | |
| 731 } | |
| 732 | |
| 733 // Raw data set | |
| 734 HRESULT RegKey::SetValue(const wchar_t* value_name, | |
| 735 const uint8_t* value, | |
| 736 DWORD byte_count, | |
| 737 DWORD type) const { | |
| 738 ASSERT(value != NULL); | |
| 739 ASSERT(h_key_ != NULL); | |
| 740 | |
| 741 LONG res = ::RegSetValueEx(h_key_, value_name, NULL, type, value, byte_count); | |
| 742 return HRESULT_FROM_WIN32(res); | |
| 743 } | |
| 744 | |
| 745 bool RegKey::HasKey(const wchar_t* full_key_name) { | |
| 746 ASSERT(full_key_name != NULL); | |
| 747 | |
| 748 // get the root HKEY | |
| 749 std::wstring key_name(full_key_name); | |
| 750 HKEY h_key = GetRootKeyInfo(&key_name); | |
| 751 | |
| 752 if (h_key != NULL) { | |
| 753 RegKey key; | |
| 754 HRESULT hr = key.Open(h_key, key_name.c_str(), KEY_READ); | |
| 755 key.Close(); | |
| 756 return S_OK == hr; | |
| 757 } | |
| 758 return false; | |
| 759 } | |
| 760 | |
| 761 // static version of HasValue | |
| 762 bool RegKey::HasValue(const wchar_t* full_key_name, const wchar_t* value_name) { | |
| 763 ASSERT(full_key_name != NULL); | |
| 764 | |
| 765 bool has_value = false; | |
| 766 // get the root HKEY | |
| 767 std::wstring key_name(full_key_name); | |
| 768 HKEY h_key = GetRootKeyInfo(&key_name); | |
| 769 | |
| 770 if (h_key != NULL) { | |
| 771 RegKey key; | |
| 772 if (key.Open(h_key, key_name.c_str(), KEY_READ) == S_OK) { | |
| 773 has_value = key.HasValue(value_name); | |
| 774 key.Close(); | |
| 775 } | |
| 776 } | |
| 777 return has_value; | |
| 778 } | |
| 779 | |
| 780 HRESULT RegKey::GetValueType(const wchar_t* full_key_name, | |
| 781 const wchar_t* value_name, | |
| 782 DWORD* value_type) { | |
| 783 ASSERT(full_key_name != NULL); | |
| 784 ASSERT(value_type != NULL); | |
| 785 | |
| 786 *value_type = REG_NONE; | |
| 787 | |
| 788 std::wstring key_name(full_key_name); | |
| 789 HKEY h_key = GetRootKeyInfo(&key_name); | |
| 790 | |
| 791 RegKey key; | |
| 792 HRESULT hr = key.Open(h_key, key_name.c_str(), KEY_READ); | |
| 793 if (SUCCEEDED(hr)) { | |
| 794 LONG res = ::SHQueryValueEx(key.h_key_, value_name, NULL, value_type, | |
| 795 NULL, NULL); | |
| 796 if (res != ERROR_SUCCESS) { | |
| 797 hr = HRESULT_FROM_WIN32(res); | |
| 798 } | |
| 799 } | |
| 800 | |
| 801 return hr; | |
| 802 } | |
| 803 | |
| 804 HRESULT RegKey::DeleteKey(const wchar_t* full_key_name) { | |
| 805 ASSERT(full_key_name != NULL); | |
| 806 | |
| 807 return DeleteKey(full_key_name, true); | |
| 808 } | |
| 809 | |
| 810 HRESULT RegKey::DeleteKey(const wchar_t* full_key_name, bool recursively) { | |
| 811 ASSERT(full_key_name != NULL); | |
| 812 | |
| 813 // need to open the parent key first | |
| 814 // get the root HKEY | |
| 815 std::wstring key_name(full_key_name); | |
| 816 HKEY h_key = GetRootKeyInfo(&key_name); | |
| 817 | |
| 818 // get the parent key | |
| 819 std::wstring parent_key(GetParentKeyInfo(&key_name)); | |
| 820 | |
| 821 RegKey key; | |
| 822 HRESULT hr = key.Open(h_key, parent_key.c_str()); | |
| 823 | |
| 824 if (hr == S_OK) { | |
| 825 hr = recursively ? key.RecurseDeleteSubKey(key_name.c_str()) | |
| 826 : key.DeleteSubKey(key_name.c_str()); | |
| 827 } else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) || | |
| 828 hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) { | |
| 829 hr = S_FALSE; | |
| 830 } | |
| 831 | |
| 832 key.Close(); | |
| 833 return hr; | |
| 834 } | |
| 835 | |
| 836 HRESULT RegKey::DeleteValue(const wchar_t* full_key_name, | |
| 837 const wchar_t* value_name) { | |
| 838 ASSERT(full_key_name != NULL); | |
| 839 | |
| 840 HRESULT hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); | |
| 841 // get the root HKEY | |
| 842 std::wstring key_name(full_key_name); | |
| 843 HKEY h_key = GetRootKeyInfo(&key_name); | |
| 844 | |
| 845 if (h_key != NULL) { | |
| 846 RegKey key; | |
| 847 hr = key.Open(h_key, key_name.c_str()); | |
| 848 if (hr == S_OK) { | |
| 849 hr = key.DeleteValue(value_name); | |
| 850 key.Close(); | |
| 851 } | |
| 852 } | |
| 853 return hr; | |
| 854 } | |
| 855 | |
| 856 HRESULT RegKey::RecurseDeleteSubKey(const wchar_t* key_name) { | |
| 857 ASSERT(key_name != NULL); | |
| 858 | |
| 859 RegKey key; | |
| 860 HRESULT hr = key.Open(h_key_, key_name); | |
| 861 | |
| 862 if (hr == S_OK) { | |
| 863 // enumerate all subkeys of this key and recursivelly delete them | |
| 864 FILETIME time = {0}; | |
| 865 wchar_t key_name_buf[kMaxKeyNameChars] = {0}; | |
| 866 DWORD key_name_buf_size = kMaxKeyNameChars; | |
| 867 while (hr == S_OK && | |
| 868 ::RegEnumKeyEx(key.h_key_, 0, key_name_buf, &key_name_buf_size, | |
| 869 NULL, NULL, NULL, &time) == ERROR_SUCCESS) { | |
| 870 hr = key.RecurseDeleteSubKey(key_name_buf); | |
| 871 | |
| 872 // restore the buffer size | |
| 873 key_name_buf_size = kMaxKeyNameChars; | |
| 874 } | |
| 875 // close the top key | |
| 876 key.Close(); | |
| 877 } | |
| 878 | |
| 879 if (hr == S_OK) { | |
| 880 // the key has no more children keys | |
| 881 // delete the key and all of its values | |
| 882 hr = DeleteSubKey(key_name); | |
| 883 } | |
| 884 | |
| 885 return hr; | |
| 886 } | |
| 887 | |
| 888 HKEY RegKey::GetRootKeyInfo(std::wstring* full_key_name) { | |
| 889 ASSERT(full_key_name != NULL); | |
| 890 | |
| 891 HKEY h_key = NULL; | |
| 892 // get the root HKEY | |
| 893 size_t index = full_key_name->find(L'\\'); | |
| 894 std::wstring root_key; | |
| 895 | |
| 896 if (index == -1) { | |
| 897 root_key = *full_key_name; | |
| 898 *full_key_name = L""; | |
| 899 } else { | |
| 900 root_key = full_key_name->substr(0, index); | |
| 901 *full_key_name = full_key_name->substr(index + 1, | |
| 902 full_key_name->length() - index - 1); | |
| 903 } | |
| 904 | |
| 905 for (std::wstring::iterator iter = root_key.begin(); | |
| 906 iter != root_key.end(); ++iter) { | |
| 907 *iter = toupper(*iter); | |
| 908 } | |
| 909 | |
| 910 if (!root_key.compare(L"HKLM") || | |
| 911 !root_key.compare(L"HKEY_LOCAL_MACHINE")) { | |
| 912 h_key = HKEY_LOCAL_MACHINE; | |
| 913 } else if (!root_key.compare(L"HKCU") || | |
| 914 !root_key.compare(L"HKEY_CURRENT_USER")) { | |
| 915 h_key = HKEY_CURRENT_USER; | |
| 916 } else if (!root_key.compare(L"HKU") || | |
| 917 !root_key.compare(L"HKEY_USERS")) { | |
| 918 h_key = HKEY_USERS; | |
| 919 } else if (!root_key.compare(L"HKCR") || | |
| 920 !root_key.compare(L"HKEY_CLASSES_ROOT")) { | |
| 921 h_key = HKEY_CLASSES_ROOT; | |
| 922 } | |
| 923 | |
| 924 return h_key; | |
| 925 } | |
| 926 | |
| 927 | |
| 928 // Returns true if this key name is 'safe' for deletion | |
| 929 // (doesn't specify a key root) | |
| 930 bool RegKey::SafeKeyNameForDeletion(const wchar_t* key_name) { | |
| 931 ASSERT(key_name != NULL); | |
| 932 std::wstring key(key_name); | |
| 933 | |
| 934 HKEY root_key = GetRootKeyInfo(&key); | |
| 935 | |
| 936 if (!root_key) { | |
| 937 key = key_name; | |
| 938 } | |
| 939 if (key.empty()) { | |
| 940 return false; | |
| 941 } | |
| 942 bool found_subkey = false, backslash_found = false; | |
| 943 for (size_t i = 0 ; i < key.length() ; ++i) { | |
| 944 if (key[i] == L'\\') { | |
| 945 backslash_found = true; | |
| 946 } else if (backslash_found) { | |
| 947 found_subkey = true; | |
| 948 break; | |
| 949 } | |
| 950 } | |
| 951 return (root_key == HKEY_USERS) ? found_subkey : true; | |
| 952 } | |
| 953 | |
| 954 std::wstring RegKey::GetParentKeyInfo(std::wstring* key_name) { | |
| 955 ASSERT(key_name != NULL); | |
| 956 | |
| 957 // get the parent key | |
| 958 size_t index = key_name->rfind(L'\\'); | |
| 959 std::wstring parent_key; | |
| 960 if (index == -1) { | |
| 961 parent_key = L""; | |
| 962 } else { | |
| 963 parent_key = key_name->substr(0, index); | |
| 964 *key_name = key_name->substr(index + 1, key_name->length() - index - 1); | |
| 965 } | |
| 966 | |
| 967 return parent_key; | |
| 968 } | |
| 969 | |
| 970 // get the number of values for this key | |
| 971 uint32_t RegKey::GetValueCount() { | |
| 972 DWORD num_values = 0; | |
| 973 | |
| 974 if (ERROR_SUCCESS != ::RegQueryInfoKey( | |
| 975 h_key_, // key handle | |
| 976 NULL, // buffer for class name | |
| 977 NULL, // size of class string | |
| 978 NULL, // reserved | |
| 979 NULL, // number of subkeys | |
| 980 NULL, // longest subkey size | |
| 981 NULL, // longest class string | |
| 982 &num_values, // number of values for this key | |
| 983 NULL, // longest value name | |
| 984 NULL, // longest value data | |
| 985 NULL, // security descriptor | |
| 986 NULL)) { // last write time | |
| 987 ASSERT(false); | |
| 988 } | |
| 989 return num_values; | |
| 990 } | |
| 991 | |
| 992 // Enumerators for the value_names for this key | |
| 993 | |
| 994 // Called to get the value name for the given value name index | |
| 995 // Use GetValueCount() to get the total value_name count for this key | |
| 996 // Returns failure if no key at the specified index | |
| 997 HRESULT RegKey::GetValueNameAt(int index, std::wstring* value_name, | |
| 998 DWORD* type) { | |
| 999 ASSERT(value_name != NULL); | |
| 1000 | |
| 1001 LONG res = ERROR_SUCCESS; | |
| 1002 wchar_t value_name_buf[kMaxValueNameChars] = {0}; | |
| 1003 DWORD value_name_buf_size = kMaxValueNameChars; | |
| 1004 res = ::RegEnumValue(h_key_, index, value_name_buf, &value_name_buf_size, | |
| 1005 NULL, type, NULL, NULL); | |
| 1006 | |
| 1007 if (res == ERROR_SUCCESS) { | |
| 1008 value_name->assign(value_name_buf); | |
| 1009 } | |
| 1010 | |
| 1011 return HRESULT_FROM_WIN32(res); | |
| 1012 } | |
| 1013 | |
| 1014 uint32_t RegKey::GetSubkeyCount() { | |
| 1015 // number of values for key | |
| 1016 DWORD num_subkeys = 0; | |
| 1017 | |
| 1018 if (ERROR_SUCCESS != ::RegQueryInfoKey( | |
| 1019 h_key_, // key handle | |
| 1020 NULL, // buffer for class name | |
| 1021 NULL, // size of class string | |
| 1022 NULL, // reserved | |
| 1023 &num_subkeys, // number of subkeys | |
| 1024 NULL, // longest subkey size | |
| 1025 NULL, // longest class string | |
| 1026 NULL, // number of values for this key | |
| 1027 NULL, // longest value name | |
| 1028 NULL, // longest value data | |
| 1029 NULL, // security descriptor | |
| 1030 NULL)) { // last write time | |
| 1031 ASSERT(false); | |
| 1032 } | |
| 1033 return num_subkeys; | |
| 1034 } | |
| 1035 | |
| 1036 HRESULT RegKey::GetSubkeyNameAt(int index, std::wstring* key_name) { | |
| 1037 ASSERT(key_name != NULL); | |
| 1038 | |
| 1039 LONG res = ERROR_SUCCESS; | |
| 1040 wchar_t key_name_buf[kMaxKeyNameChars] = {0}; | |
| 1041 DWORD key_name_buf_size = kMaxKeyNameChars; | |
| 1042 | |
| 1043 res = ::RegEnumKeyEx(h_key_, index, key_name_buf, &key_name_buf_size, | |
| 1044 NULL, NULL, NULL, NULL); | |
| 1045 | |
| 1046 if (res == ERROR_SUCCESS) { | |
| 1047 key_name->assign(key_name_buf); | |
| 1048 } | |
| 1049 | |
| 1050 return HRESULT_FROM_WIN32(res); | |
| 1051 } | |
| 1052 | |
| 1053 // Is the key empty: having no sub-keys and values | |
| 1054 bool RegKey::IsKeyEmpty(const wchar_t* full_key_name) { | |
| 1055 ASSERT(full_key_name != NULL); | |
| 1056 | |
| 1057 bool is_empty = true; | |
| 1058 | |
| 1059 // Get the root HKEY | |
| 1060 std::wstring key_name(full_key_name); | |
| 1061 HKEY h_key = GetRootKeyInfo(&key_name); | |
| 1062 | |
| 1063 // Open the key to check | |
| 1064 if (h_key != NULL) { | |
| 1065 RegKey key; | |
| 1066 HRESULT hr = key.Open(h_key, key_name.c_str(), KEY_READ); | |
| 1067 if (SUCCEEDED(hr)) { | |
| 1068 is_empty = key.GetSubkeyCount() == 0 && key.GetValueCount() == 0; | |
| 1069 key.Close(); | |
| 1070 } | |
| 1071 } | |
| 1072 | |
| 1073 return is_empty; | |
| 1074 } | |
| 1075 | |
| 1076 bool AdjustCurrentProcessPrivilege(const TCHAR* privilege, bool to_enable) { | |
| 1077 ASSERT(privilege != NULL); | |
| 1078 | |
| 1079 bool ret = false; | |
| 1080 HANDLE token; | |
| 1081 if (::OpenProcessToken(::GetCurrentProcess(), | |
| 1082 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) { | |
| 1083 LUID luid; | |
| 1084 memset(&luid, 0, sizeof(luid)); | |
| 1085 if (::LookupPrivilegeValue(NULL, privilege, &luid)) { | |
| 1086 TOKEN_PRIVILEGES privs; | |
| 1087 privs.PrivilegeCount = 1; | |
| 1088 privs.Privileges[0].Luid = luid; | |
| 1089 privs.Privileges[0].Attributes = to_enable ? SE_PRIVILEGE_ENABLED : 0; | |
| 1090 if (::AdjustTokenPrivileges(token, FALSE, &privs, 0, NULL, 0)) { | |
| 1091 ret = true; | |
| 1092 } else { | |
| 1093 LOG_GLE(LS_ERROR) << "AdjustTokenPrivileges failed"; | |
| 1094 } | |
| 1095 } else { | |
| 1096 LOG_GLE(LS_ERROR) << "LookupPrivilegeValue failed"; | |
| 1097 } | |
| 1098 CloseHandle(token); | |
| 1099 } else { | |
| 1100 LOG_GLE(LS_ERROR) << "OpenProcessToken(GetCurrentProcess) failed"; | |
| 1101 } | |
| 1102 | |
| 1103 return ret; | |
| 1104 } | |
| 1105 | |
| 1106 } // namespace rtc | |
| OLD | NEW |