Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(270)

Side by Side Diff: base/win/registry.cc

Issue 632833002: Remove raw handles from base::win::RegKey (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Split watcher Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 // Watches for modifications to a key.
38 class RegKey::Watcher : public ObjectWatcher::Delegate {
39 public:
40 explicit Watcher(RegKey* owner) : owner_(owner) {}
41 ~Watcher() {}
42
43 bool StartWatching(HKEY key);
44
45 // Implementation of ObjectWatcher::Delegate.
46 void OnObjectSignaled(HANDLE object) override {
47 DCHECK(watch_event_.IsValid() && watch_event_.Get() == object);
48 owner_->OnObjectSignaled(object);
49 }
50
51 private:
52 RegKey* owner_;
53 ScopedHandle watch_event_;
54 ObjectWatcher object_watcher_;
55 DISALLOW_COPY_AND_ASSIGN(Watcher);
56 };
57
58 bool RegKey::Watcher::StartWatching(HKEY key) {
59 DCHECK(key);
60 if (GetVersion() < VERSION_VISTA) {
61 // It is an error to register multiple times before Vista.
62 if (watch_event_.IsValid())
63 return true;
eroman 2014/10/10 21:34:35 This doesn't match my expectation of what StartWat
rvargas (doing something else) 2014/10/10 22:22:05 That failures closes watch_event_ (line 81)
64 }
65
66 if (!watch_event_.IsValid())
67 watch_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL));
68
69 if (!watch_event_.IsValid())
70 return false;
71
72 DWORD filter = REG_NOTIFY_CHANGE_NAME |
73 REG_NOTIFY_CHANGE_ATTRIBUTES |
74 REG_NOTIFY_CHANGE_LAST_SET |
75 REG_NOTIFY_CHANGE_SECURITY;
76
77 // Watch the registry key for a change of value.
78 LONG result = RegNotifyChangeKeyValue(key, TRUE, filter, watch_event_.Get(),
79 TRUE);
80 if (result != ERROR_SUCCESS) {
81 watch_event_.Close();
82 return false;
83 }
84
85 return object_watcher_.StartWatching(watch_event_.Get(), this);
86 }
87
37 // RegKey ---------------------------------------------------------------------- 88 // RegKey ----------------------------------------------------------------------
38 89
39 RegKey::RegKey() 90 RegKey::RegKey() : key_(NULL), wow64access_(0) {
40 : key_(NULL),
41 watch_event_(0),
42 wow64access_(0) {
43 } 91 }
44 92
45 RegKey::RegKey(HKEY key) 93 RegKey::RegKey(HKEY key) : key_(key), wow64access_(0) {
46 : key_(key),
47 watch_event_(0),
48 wow64access_(0) {
49 } 94 }
50 95
51 RegKey::RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access) 96 RegKey::RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access)
52 : key_(NULL), 97 : key_(NULL),
53 watch_event_(0),
54 wow64access_(0) { 98 wow64access_(0) {
55 if (rootkey) { 99 if (rootkey) {
56 if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK)) 100 if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK))
57 Create(rootkey, subkey, access); 101 Create(rootkey, subkey, access);
58 else 102 else
59 Open(rootkey, subkey, access); 103 Open(rootkey, subkey, access);
60 } else { 104 } else {
61 DCHECK(!subkey); 105 DCHECK(!subkey);
62 wow64access_ = access & kWow64AccessMask; 106 wow64access_ = access & kWow64AccessMask;
63 } 107 }
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 // one. 187 // one.
144 if (result == ERROR_SUCCESS) { 188 if (result == ERROR_SUCCESS) {
145 Close(); 189 Close();
146 key_ = subkey; 190 key_ = subkey;
147 wow64access_ = access & kWow64AccessMask; 191 wow64access_ = access & kWow64AccessMask;
148 } 192 }
149 return result; 193 return result;
150 } 194 }
151 195
152 void RegKey::Close() { 196 void RegKey::Close() {
153 StopWatching();
154 if (key_) { 197 if (key_) {
155 ::RegCloseKey(key_); 198 ::RegCloseKey(key_);
156 key_ = NULL; 199 key_ = NULL;
157 wow64access_ = 0; 200 wow64access_ = 0;
158 } 201 }
159 } 202 }
160 203
161 // TODO(wfh): Remove this and other unsafe methods. See http://crbug.com/375400 204 // TODO(wfh): Remove this and other unsafe methods. See http://crbug.com/375400
162 void RegKey::Set(HKEY key) { 205 void RegKey::Set(HKEY key) {
163 if (key_ != key) { 206 if (key_ != key) {
164 Close(); 207 Close();
165 key_ = key; 208 key_ = key;
166 } 209 }
167 } 210 }
168 211
169 HKEY RegKey::Take() { 212 HKEY RegKey::Take() {
170 DCHECK(wow64access_ == 0); 213 DCHECK(wow64access_ == 0);
171 StopWatching();
172 HKEY key = key_; 214 HKEY key = key_;
173 key_ = NULL; 215 key_ = NULL;
174 return key; 216 return key;
175 } 217 }
176 218
177 bool RegKey::HasValue(const wchar_t* name) const { 219 bool RegKey::HasValue(const wchar_t* name) const {
178 return RegQueryValueEx(key_, name, 0, NULL, NULL, NULL) == ERROR_SUCCESS; 220 return RegQueryValueEx(key_, name, 0, NULL, NULL, NULL) == ERROR_SUCCESS;
179 } 221 }
180 222
181 DWORD RegKey::GetValueCount() const { 223 DWORD RegKey::GetValueCount() const {
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 const void* data, 402 const void* data,
361 DWORD dsize, 403 DWORD dsize,
362 DWORD dtype) { 404 DWORD dtype) {
363 DCHECK(data || !dsize); 405 DCHECK(data || !dsize);
364 406
365 LONG result = RegSetValueEx(key_, name, 0, dtype, 407 LONG result = RegSetValueEx(key_, name, 0, dtype,
366 reinterpret_cast<LPBYTE>(const_cast<void*>(data)), dsize); 408 reinterpret_cast<LPBYTE>(const_cast<void*>(data)), dsize);
367 return result; 409 return result;
368 } 410 }
369 411
370 LONG RegKey::StartWatching() { 412 bool RegKey::StartWatching(const ChangeCallback& callback) {
371 DCHECK(key_); 413 DCHECK(callback_.is_null());
372 if (!watch_event_) 414 if (!key_watcher_)
373 watch_event_ = CreateEvent(NULL, TRUE, FALSE, NULL); 415 key_watcher_.reset(new Watcher(this));
374 416
375 DWORD filter = REG_NOTIFY_CHANGE_NAME | 417 if (!key_watcher_.get()->StartWatching(key_))
376 REG_NOTIFY_CHANGE_ATTRIBUTES | 418 return false;
377 REG_NOTIFY_CHANGE_LAST_SET |
378 REG_NOTIFY_CHANGE_SECURITY;
379 419
380 // Watch the registry key for a change of value. 420 callback_ = callback;
381 LONG result = RegNotifyChangeKeyValue(key_, TRUE, filter, watch_event_, TRUE); 421 return true;
382 if (result != ERROR_SUCCESS) {
383 CloseHandle(watch_event_);
384 watch_event_ = 0;
385 }
386
387 return result;
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 } 422 }
409 423
410 // static 424 // static
411 LONG RegKey::RegDeleteKeyExWrapper(HKEY hKey, 425 LONG RegKey::RegDeleteKeyExWrapper(HKEY hKey,
412 const wchar_t* lpSubKey, 426 const wchar_t* lpSubKey,
413 REGSAM samDesired, 427 REGSAM samDesired,
414 DWORD Reserved) { 428 DWORD Reserved) {
415 typedef LSTATUS(WINAPI* RegDeleteKeyExPtr)(HKEY, LPCWSTR, REGSAM, DWORD); 429 typedef LSTATUS(WINAPI* RegDeleteKeyExPtr)(HKEY, LPCWSTR, REGSAM, DWORD);
416 430
417 RegDeleteKeyExPtr reg_delete_key_ex_func = 431 RegDeleteKeyExPtr reg_delete_key_ex_func =
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 } 491 }
478 492
479 RegCloseKey(target_key); 493 RegCloseKey(target_key);
480 494
481 // Try again to delete the key. 495 // Try again to delete the key.
482 result = RegDeleteKeyExWrapper(root_key, name.c_str(), access, 0); 496 result = RegDeleteKeyExWrapper(root_key, name.c_str(), access, 0);
483 497
484 return result; 498 return result;
485 } 499 }
486 500
501 void RegKey::OnObjectSignaled(HANDLE 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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698