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

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: use composition 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
« no previous file with comments | « base/win/registry.h ('k') | base/win/registry_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 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
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
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
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
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
« no previous file with comments | « base/win/registry.h ('k') | base/win/registry_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698