OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/win/registry.h" | 5 #include "base/win/registry.h" |
6 | 6 |
7 #include <shlwapi.h> | 7 #include <shlwapi.h> |
8 #include <algorithm> | 8 #include <algorithm> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 16 matching lines...) Expand all Loading... | |
27 // a size in wchar_t that can store a truncated wchar_t if necessary. | 27 // a size in wchar_t that can store a truncated wchar_t if necessary. |
28 inline DWORD to_wchar_size(DWORD byte_size) { | 28 inline DWORD to_wchar_size(DWORD byte_size) { |
29 return (byte_size + sizeof(wchar_t) - 1) / sizeof(wchar_t); | 29 return (byte_size + sizeof(wchar_t) - 1) / sizeof(wchar_t); |
30 } | 30 } |
31 | 31 |
32 // Mask to pull WOW64 access flags out of REGSAM access. | 32 // Mask to pull WOW64 access flags out of REGSAM access. |
33 const REGSAM kWow64AccessMask = KEY_WOW64_32KEY | KEY_WOW64_64KEY; | 33 const REGSAM kWow64AccessMask = KEY_WOW64_32KEY | KEY_WOW64_64KEY; |
34 | 34 |
35 } // namespace | 35 } // namespace |
36 | 36 |
37 class RegKey::WatcherDelegate : public ObjectWatcher::Delegate { | |
38 public: | |
39 explicit WatcherDelegate(RegKey* owner) : owner_(owner) {} | |
40 | |
41 // Implementation of ObjectWatcher::Delegate. | |
42 void OnObjectSignaled(HANDLE object) override { | |
43 owner_->OnObjectSignaled(object); | |
44 } | |
45 | |
46 private: | |
cpu_(ooo_6.6-7.5)
2014/10/08 23:28:19
now that you have this helper guy seems we want th
rvargas (doing something else)
2014/10/09 00:22:46
done
I wanted a trivial adaptor between a delegat
| |
47 RegKey* owner_; | |
48 }; | |
49 | |
50 | |
37 // RegKey ---------------------------------------------------------------------- | 51 // RegKey ---------------------------------------------------------------------- |
38 | 52 |
39 RegKey::RegKey() | 53 RegKey::RegKey() : key_(NULL), wow64access_(0) { |
40 : key_(NULL), | |
41 watch_event_(0), | |
42 wow64access_(0) { | |
43 } | 54 } |
44 | 55 |
45 RegKey::RegKey(HKEY key) | 56 RegKey::RegKey(HKEY key) : key_(key), wow64access_(0) { |
46 : key_(key), | |
47 watch_event_(0), | |
48 wow64access_(0) { | |
49 } | 57 } |
50 | 58 |
51 RegKey::RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access) | 59 RegKey::RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access) |
52 : key_(NULL), | 60 : key_(NULL), |
53 watch_event_(0), | |
54 wow64access_(0) { | 61 wow64access_(0) { |
55 if (rootkey) { | 62 if (rootkey) { |
56 if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK)) | 63 if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK)) |
57 Create(rootkey, subkey, access); | 64 Create(rootkey, subkey, access); |
58 else | 65 else |
59 Open(rootkey, subkey, access); | 66 Open(rootkey, subkey, access); |
60 } else { | 67 } else { |
61 DCHECK(!subkey); | 68 DCHECK(!subkey); |
62 wow64access_ = access & kWow64AccessMask; | 69 wow64access_ = access & kWow64AccessMask; |
63 } | 70 } |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
143 // one. | 150 // one. |
144 if (result == ERROR_SUCCESS) { | 151 if (result == ERROR_SUCCESS) { |
145 Close(); | 152 Close(); |
146 key_ = subkey; | 153 key_ = subkey; |
147 wow64access_ = access & kWow64AccessMask; | 154 wow64access_ = access & kWow64AccessMask; |
148 } | 155 } |
149 return result; | 156 return result; |
150 } | 157 } |
151 | 158 |
152 void RegKey::Close() { | 159 void RegKey::Close() { |
153 StopWatching(); | |
154 if (key_) { | 160 if (key_) { |
155 ::RegCloseKey(key_); | 161 ::RegCloseKey(key_); |
156 key_ = NULL; | 162 key_ = NULL; |
157 wow64access_ = 0; | 163 wow64access_ = 0; |
158 } | 164 } |
159 } | 165 } |
160 | 166 |
161 // TODO(wfh): Remove this and other unsafe methods. See http://crbug.com/375400 | 167 // TODO(wfh): Remove this and other unsafe methods. See http://crbug.com/375400 |
162 void RegKey::Set(HKEY key) { | 168 void RegKey::Set(HKEY key) { |
163 if (key_ != key) { | 169 if (key_ != key) { |
164 Close(); | 170 Close(); |
165 key_ = key; | 171 key_ = key; |
166 } | 172 } |
167 } | 173 } |
168 | 174 |
169 HKEY RegKey::Take() { | 175 HKEY RegKey::Take() { |
170 DCHECK(wow64access_ == 0); | 176 DCHECK(wow64access_ == 0); |
171 StopWatching(); | |
172 HKEY key = key_; | 177 HKEY key = key_; |
173 key_ = NULL; | 178 key_ = NULL; |
174 return key; | 179 return key; |
175 } | 180 } |
176 | 181 |
177 bool RegKey::HasValue(const wchar_t* name) const { | 182 bool RegKey::HasValue(const wchar_t* name) const { |
178 return RegQueryValueEx(key_, name, 0, NULL, NULL, NULL) == ERROR_SUCCESS; | 183 return RegQueryValueEx(key_, name, 0, NULL, NULL, NULL) == ERROR_SUCCESS; |
179 } | 184 } |
180 | 185 |
181 DWORD RegKey::GetValueCount() const { | 186 DWORD RegKey::GetValueCount() const { |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
360 const void* data, | 365 const void* data, |
361 DWORD dsize, | 366 DWORD dsize, |
362 DWORD dtype) { | 367 DWORD dtype) { |
363 DCHECK(data || !dsize); | 368 DCHECK(data || !dsize); |
364 | 369 |
365 LONG result = RegSetValueEx(key_, name, 0, dtype, | 370 LONG result = RegSetValueEx(key_, name, 0, dtype, |
366 reinterpret_cast<LPBYTE>(const_cast<void*>(data)), dsize); | 371 reinterpret_cast<LPBYTE>(const_cast<void*>(data)), dsize); |
367 return result; | 372 return result; |
368 } | 373 } |
369 | 374 |
370 LONG RegKey::StartWatching() { | 375 bool RegKey::StartWatching(const ChangeCallback& callback) { |
376 DCHECK(callback_.is_null()); | |
377 if (!StartWatchingInternal()) | |
378 return false; | |
379 | |
380 DCHECK(watch_event_.IsValid()); | |
381 if (!watcher_delegate_) | |
382 watcher_delegate_.reset(new WatcherDelegate(this)); | |
383 | |
384 if (!object_watcher_.StartWatching(watch_event_.Get(), | |
385 watcher_delegate_.get())) { | |
386 return false; | |
387 } | |
388 | |
389 callback_ = callback; | |
390 return true; | |
391 } | |
392 | |
393 bool RegKey::StartWatchingInternal() { | |
371 DCHECK(key_); | 394 DCHECK(key_); |
372 if (!watch_event_) | 395 if (GetVersion() < VERSION_VISTA) { |
373 watch_event_ = CreateEvent(NULL, TRUE, FALSE, NULL); | 396 // It is an error to register multiple times before Vista. |
397 if (watch_event_.IsValid()) | |
398 return true; | |
399 } | |
400 | |
401 if (!watch_event_.IsValid()) | |
402 watch_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL)); | |
403 | |
404 if (!watch_event_.IsValid()) | |
405 return false; | |
374 | 406 |
375 DWORD filter = REG_NOTIFY_CHANGE_NAME | | 407 DWORD filter = REG_NOTIFY_CHANGE_NAME | |
376 REG_NOTIFY_CHANGE_ATTRIBUTES | | 408 REG_NOTIFY_CHANGE_ATTRIBUTES | |
377 REG_NOTIFY_CHANGE_LAST_SET | | 409 REG_NOTIFY_CHANGE_LAST_SET | |
378 REG_NOTIFY_CHANGE_SECURITY; | 410 REG_NOTIFY_CHANGE_SECURITY; |
379 | 411 |
380 // Watch the registry key for a change of value. | 412 // Watch the registry key for a change of value. |
381 LONG result = RegNotifyChangeKeyValue(key_, TRUE, filter, watch_event_, TRUE); | 413 LONG result = RegNotifyChangeKeyValue(key_, TRUE, filter, watch_event_.Get(), |
414 TRUE); | |
382 if (result != ERROR_SUCCESS) { | 415 if (result != ERROR_SUCCESS) { |
383 CloseHandle(watch_event_); | 416 watch_event_.Close(); |
384 watch_event_ = 0; | 417 return false; |
385 } | 418 } |
386 | 419 |
387 return result; | 420 return true; |
388 } | |
389 | |
390 bool RegKey::HasChanged() { | |
391 if (watch_event_) { | |
392 if (WaitForSingleObject(watch_event_, 0) == WAIT_OBJECT_0) { | |
393 StartWatching(); | |
394 return true; | |
395 } | |
396 } | |
397 return false; | |
398 } | |
399 | |
400 LONG RegKey::StopWatching() { | |
401 LONG result = ERROR_INVALID_HANDLE; | |
402 if (watch_event_) { | |
403 CloseHandle(watch_event_); | |
404 watch_event_ = 0; | |
405 result = ERROR_SUCCESS; | |
406 } | |
407 return result; | |
408 } | 421 } |
409 | 422 |
410 // static | 423 // static |
411 LONG RegKey::RegDeleteKeyExWrapper(HKEY hKey, | 424 LONG RegKey::RegDeleteKeyExWrapper(HKEY hKey, |
412 const wchar_t* lpSubKey, | 425 const wchar_t* lpSubKey, |
413 REGSAM samDesired, | 426 REGSAM samDesired, |
414 DWORD Reserved) { | 427 DWORD Reserved) { |
415 typedef LSTATUS(WINAPI* RegDeleteKeyExPtr)(HKEY, LPCWSTR, REGSAM, DWORD); | 428 typedef LSTATUS(WINAPI* RegDeleteKeyExPtr)(HKEY, LPCWSTR, REGSAM, DWORD); |
416 | 429 |
417 RegDeleteKeyExPtr reg_delete_key_ex_func = | 430 RegDeleteKeyExPtr reg_delete_key_ex_func = |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
477 } | 490 } |
478 | 491 |
479 RegCloseKey(target_key); | 492 RegCloseKey(target_key); |
480 | 493 |
481 // Try again to delete the key. | 494 // Try again to delete the key. |
482 result = RegDeleteKeyExWrapper(root_key, name.c_str(), access, 0); | 495 result = RegDeleteKeyExWrapper(root_key, name.c_str(), access, 0); |
483 | 496 |
484 return result; | 497 return result; |
485 } | 498 } |
486 | 499 |
500 void RegKey::OnObjectSignaled(HANDLE object) { | |
501 DCHECK(watch_event_.IsValid() && watch_event_.Get() == object); | |
502 ChangeCallback callback = callback_; | |
503 callback_.Reset(); | |
504 callback.Run(); | |
505 } | |
506 | |
487 // RegistryValueIterator ------------------------------------------------------ | 507 // RegistryValueIterator ------------------------------------------------------ |
488 | 508 |
489 RegistryValueIterator::RegistryValueIterator(HKEY root_key, | 509 RegistryValueIterator::RegistryValueIterator(HKEY root_key, |
490 const wchar_t* folder_key) | 510 const wchar_t* folder_key) |
491 : name_(MAX_PATH, L'\0'), | 511 : name_(MAX_PATH, L'\0'), |
492 value_(MAX_PATH, L'\0') { | 512 value_(MAX_PATH, L'\0') { |
493 LONG result = RegOpenKeyEx(root_key, folder_key, 0, KEY_READ, &key_); | 513 LONG result = RegOpenKeyEx(root_key, folder_key, 0, KEY_READ, &key_); |
494 if (result != ERROR_SUCCESS) { | 514 if (result != ERROR_SUCCESS) { |
495 key_ = NULL; | 515 key_ = NULL; |
496 } else { | 516 } else { |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
629 if (ERROR_SUCCESS == r) | 649 if (ERROR_SUCCESS == r) |
630 return true; | 650 return true; |
631 } | 651 } |
632 | 652 |
633 name_[0] = '\0'; | 653 name_[0] = '\0'; |
634 return false; | 654 return false; |
635 } | 655 } |
636 | 656 |
637 } // namespace win | 657 } // namespace win |
638 } // namespace base | 658 } // namespace base |
OLD | NEW |