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

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

Issue 2963783002: Remove unsafe registry APIs from base::win::RegKey
Patch Set: half-fix remoting Created 3 years, 5 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 <stddef.h> 8 #include <stddef.h>
9 #include <algorithm> 9 #include <algorithm>
10 10
(...skipping 16 matching lines...) Expand all
27 // Registry values are read as BYTE* but can have wchar_t* data whose last 27 // Registry values are read as BYTE* but can have wchar_t* data whose last
28 // wchar_t is truncated. This function converts the reported |byte_size| to 28 // wchar_t is truncated. This function converts the reported |byte_size| to
29 // a size in wchar_t that can store a truncated wchar_t if necessary. 29 // a size in wchar_t that can store a truncated wchar_t if necessary.
30 inline DWORD to_wchar_size(DWORD byte_size) { 30 inline DWORD to_wchar_size(DWORD byte_size) {
31 return (byte_size + sizeof(wchar_t) - 1) / sizeof(wchar_t); 31 return (byte_size + sizeof(wchar_t) - 1) / sizeof(wchar_t);
32 } 32 }
33 33
34 // Mask to pull WOW64 access flags out of REGSAM access. 34 // Mask to pull WOW64 access flags out of REGSAM access.
35 const REGSAM kWow64AccessMask = KEY_WOW64_32KEY | KEY_WOW64_64KEY; 35 const REGSAM kWow64AccessMask = KEY_WOW64_32KEY | KEY_WOW64_64KEY;
36 36
37 #if DCHECK_IS_ON()
38 inline bool isValidRootKey(HKEY key) {
39 return key == HKEY_CLASSES_ROOT || key == HKEY_CURRENT_USER ||
40 key == HKEY_LOCAL_MACHINE || key == HKEY_USERS ||
41 key == HKEY_PERFORMANCE_DATA || key == HKEY_PERFORMANCE_TEXT ||
42 key == HKEY_PERFORMANCE_NLSTEXT || key == HKEY_CURRENT_CONFIG ||
43 key == HKEY_DYN_DATA || key == HKEY_CURRENT_USER_LOCAL_SETTINGS;
44 }
45 #endif // DCHECK_IS_ON()
46
37 } // namespace 47 } // namespace
38 48
39 // Watches for modifications to a key. 49 // Watches for modifications to a key.
40 class RegKey::Watcher : public ObjectWatcher::Delegate { 50 class RegKey::Watcher : public ObjectWatcher::Delegate {
41 public: 51 public:
42 Watcher() {} 52 Watcher() {}
43 ~Watcher() override {} 53 ~Watcher() override {}
44 54
55 Watcher(Watcher&&) = default;
56 Watcher& operator=(Watcher&&) = default;
57
45 bool StartWatching(HKEY key, const ChangeCallback& callback); 58 bool StartWatching(HKEY key, const ChangeCallback& callback);
46 59
47 // Implementation of ObjectWatcher::Delegate. 60 // Implementation of ObjectWatcher::Delegate.
48 void OnObjectSignaled(HANDLE object) override { 61 void OnObjectSignaled(HANDLE object) override {
49 DCHECK(watch_event_.IsValid() && watch_event_.Get() == object); 62 DCHECK(watch_event_.IsValid() && watch_event_.Get() == object);
50 ChangeCallback callback = callback_; 63 ChangeCallback callback = callback_;
51 callback_.Reset(); 64 callback_.Reset();
52 callback.Run(); 65 callback.Run();
53 } 66 }
54 67
(...skipping 29 matching lines...) Expand all
84 97
85 callback_ = callback; 98 callback_ = callback;
86 return object_watcher_.StartWatchingOnce(watch_event_.Get(), this); 99 return object_watcher_.StartWatchingOnce(watch_event_.Get(), this);
87 } 100 }
88 101
89 // RegKey ---------------------------------------------------------------------- 102 // RegKey ----------------------------------------------------------------------
90 103
91 RegKey::RegKey() : key_(NULL), wow64access_(0) { 104 RegKey::RegKey() : key_(NULL), wow64access_(0) {
92 } 105 }
93 106
94 RegKey::RegKey(HKEY key) : key_(key), wow64access_(0) { 107 RegKey::RegKey(HKEY rootkey) : key_(rootkey), wow64access_(0) {
108 DCHECK(isValidRootKey(rootkey));
95 } 109 }
96 110
97 RegKey::RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access) 111 RegKey::RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access)
98 : key_(NULL), 112 : key_(NULL),
99 wow64access_(0) { 113 wow64access_(0) {
100 if (rootkey) { 114 if (rootkey) {
101 if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK)) 115 if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK))
102 Create(rootkey, subkey, access); 116 Create(rootkey, subkey, access);
103 else 117 else
104 Open(rootkey, subkey, access); 118 Open(rootkey, subkey, access);
105 } else { 119 } else {
106 DCHECK(!subkey); 120 DCHECK(!subkey);
107 wow64access_ = access & kWow64AccessMask; 121 wow64access_ = access & kWow64AccessMask;
108 } 122 }
109 } 123 }
110 124
111 RegKey::~RegKey() { 125 RegKey::~RegKey() {
112 Close(); 126 Close();
113 } 127 }
114 128
129 RegKey::RegKey(RegKey&&) = default;
130
131 RegKey& RegKey::operator=(RegKey&&) = default;
132
115 LONG RegKey::Create(HKEY rootkey, const wchar_t* subkey, REGSAM access) { 133 LONG RegKey::Create(HKEY rootkey, const wchar_t* subkey, REGSAM access) {
134 DCHECK(isValidRootKey(rootkey));
116 DWORD disposition_value; 135 DWORD disposition_value;
117 return CreateWithDisposition(rootkey, subkey, &disposition_value, access); 136 return CreateWithDisposition(rootkey, subkey, &disposition_value, access);
118 } 137 }
119 138
120 LONG RegKey::CreateWithDisposition(HKEY rootkey, const wchar_t* subkey, 139 LONG RegKey::CreateWithDisposition(HKEY rootkey, const wchar_t* subkey,
121 DWORD* disposition, REGSAM access) { 140 DWORD* disposition, REGSAM access) {
122 DCHECK(rootkey && subkey && access && disposition); 141 DCHECK(rootkey && subkey && access && disposition);
142 DCHECK(isValidRootKey(rootkey));
123 HKEY subhkey = NULL; 143 HKEY subhkey = NULL;
124 LONG result = RegCreateKeyEx(rootkey, subkey, 0, NULL, 144 LONG result = RegCreateKeyEx(rootkey, subkey, 0, NULL,
125 REG_OPTION_NON_VOLATILE, access, NULL, &subhkey, 145 REG_OPTION_NON_VOLATILE, access, NULL, &subhkey,
126 disposition); 146 disposition);
127 if (result == ERROR_SUCCESS) { 147 if (result == ERROR_SUCCESS) {
128 Close(); 148 Close();
129 key_ = subhkey; 149 key_ = subhkey;
130 wow64access_ = access & kWow64AccessMask; 150 wow64access_ = access & kWow64AccessMask;
131 } 151 }
132 152
133 return result; 153 return result;
134 } 154 }
135 155
136 LONG RegKey::CreateKey(const wchar_t* name, REGSAM access) { 156 LONG RegKey::CreateKey(const wchar_t* name, REGSAM access) {
137 DCHECK(name && access); 157 DCHECK(name && access);
158 DCHECK(key_);
grt (UTC plus 2) 2017/06/29 08:49:47 i'm not sure about this. when you don't care about
138 // After the application has accessed an alternate registry view using one of 159 // After the application has accessed an alternate registry view using one of
139 // the [KEY_WOW64_32KEY / KEY_WOW64_64KEY] flags, all subsequent operations 160 // the [KEY_WOW64_32KEY / KEY_WOW64_64KEY] flags, all subsequent operations
140 // (create, delete, or open) on child registry keys must explicitly use the 161 // (create, delete, or open) on child registry keys must explicitly use the
141 // same flag. Otherwise, there can be unexpected behavior. 162 // same flag. Otherwise, there can be unexpected behavior.
142 // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384129.aspx. 163 // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384129.aspx.
143 if ((access & kWow64AccessMask) != wow64access_) { 164 if ((access & kWow64AccessMask) != wow64access_) {
144 NOTREACHED(); 165 NOTREACHED();
145 return ERROR_INVALID_PARAMETER; 166 return ERROR_INVALID_PARAMETER;
146 } 167 }
147 HKEY subkey = NULL; 168 HKEY subkey = NULL;
148 LONG result = RegCreateKeyEx(key_, name, 0, NULL, REG_OPTION_NON_VOLATILE, 169 LONG result = RegCreateKeyEx(key_, name, 0, NULL, REG_OPTION_NON_VOLATILE,
149 access, NULL, &subkey, NULL); 170 access, NULL, &subkey, NULL);
150 if (result == ERROR_SUCCESS) { 171 if (result == ERROR_SUCCESS) {
151 Close(); 172 Close();
152 key_ = subkey; 173 key_ = subkey;
153 wow64access_ = access & kWow64AccessMask; 174 wow64access_ = access & kWow64AccessMask;
154 } 175 }
155 176
156 return result; 177 return result;
157 } 178 }
158 179
159 LONG RegKey::Open(HKEY rootkey, const wchar_t* subkey, REGSAM access) { 180 LONG RegKey::Open(HKEY rootkey, const wchar_t* subkey, REGSAM access) {
160 DCHECK(rootkey && subkey && access); 181 DCHECK(rootkey && subkey && access);
182 DCHECK(isValidRootKey(rootkey));
161 HKEY subhkey = NULL; 183 HKEY subhkey = NULL;
162 184
163 LONG result = RegOpenKeyEx(rootkey, subkey, 0, access, &subhkey); 185 LONG result = RegOpenKeyEx(rootkey, subkey, 0, access, &subhkey);
164 if (result == ERROR_SUCCESS) { 186 if (result == ERROR_SUCCESS) {
165 Close(); 187 Close();
166 key_ = subhkey; 188 key_ = subhkey;
167 wow64access_ = access & kWow64AccessMask; 189 wow64access_ = access & kWow64AccessMask;
168 } 190 }
169 191
170 return result; 192 return result;
171 } 193 }
172 194
173 LONG RegKey::OpenKey(const wchar_t* relative_key_name, REGSAM access) { 195 LONG RegKey::OpenKey(const wchar_t* relative_key_name, REGSAM access) {
174 DCHECK(relative_key_name && access); 196 DCHECK(relative_key_name && access);
197 DCHECK(key_);
175 // After the application has accessed an alternate registry view using one of 198 // After the application has accessed an alternate registry view using one of
176 // the [KEY_WOW64_32KEY / KEY_WOW64_64KEY] flags, all subsequent operations 199 // the [KEY_WOW64_32KEY / KEY_WOW64_64KEY] flags, all subsequent operations
177 // (create, delete, or open) on child registry keys must explicitly use the 200 // (create, delete, or open) on child registry keys must explicitly use the
178 // same flag. Otherwise, there can be unexpected behavior. 201 // same flag. Otherwise, there can be unexpected behavior.
179 // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384129.aspx. 202 // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384129.aspx.
180 if ((access & kWow64AccessMask) != wow64access_) { 203 if ((access & kWow64AccessMask) != wow64access_) {
181 NOTREACHED(); 204 NOTREACHED();
182 return ERROR_INVALID_PARAMETER; 205 return ERROR_INVALID_PARAMETER;
183 } 206 }
184 HKEY subkey = NULL; 207 HKEY subkey = NULL;
(...skipping 10 matching lines...) Expand all
195 } 218 }
196 219
197 void RegKey::Close() { 220 void RegKey::Close() {
198 if (key_) { 221 if (key_) {
199 ::RegCloseKey(key_); 222 ::RegCloseKey(key_);
200 key_ = NULL; 223 key_ = NULL;
201 wow64access_ = 0; 224 wow64access_ = 0;
202 } 225 }
203 } 226 }
204 227
205 // TODO(wfh): Remove this and other unsafe methods. See http://crbug.com/375400
206 void RegKey::Set(HKEY key) {
207 if (key_ != key) {
208 Close();
209 key_ = key;
210 }
211 }
212
213 HKEY RegKey::Take() {
214 DCHECK_EQ(wow64access_, 0u);
215 HKEY key = key_;
216 key_ = NULL;
217 return key;
218 }
219
220 bool RegKey::HasValue(const wchar_t* name) const { 228 bool RegKey::HasValue(const wchar_t* name) const {
229 DCHECK(key_);
221 return RegQueryValueEx(key_, name, 0, NULL, NULL, NULL) == ERROR_SUCCESS; 230 return RegQueryValueEx(key_, name, 0, NULL, NULL, NULL) == ERROR_SUCCESS;
222 } 231 }
223 232
224 DWORD RegKey::GetValueCount() const { 233 DWORD RegKey::GetValueCount() const {
234 DCHECK(key_);
225 DWORD count = 0; 235 DWORD count = 0;
226 LONG result = RegQueryInfoKey(key_, NULL, 0, NULL, NULL, NULL, NULL, &count, 236 LONG result = RegQueryInfoKey(key_, NULL, 0, NULL, NULL, NULL, NULL, &count,
227 NULL, NULL, NULL, NULL); 237 NULL, NULL, NULL, NULL);
228 return (result == ERROR_SUCCESS) ? count : 0; 238 return (result == ERROR_SUCCESS) ? count : 0;
229 } 239 }
230 240
231 LONG RegKey::GetValueNameAt(int index, std::wstring* name) const { 241 LONG RegKey::GetValueNameAt(int index, std::wstring* name) const {
242 DCHECK(key_);
232 wchar_t buf[256]; 243 wchar_t buf[256];
233 DWORD bufsize = arraysize(buf); 244 DWORD bufsize = arraysize(buf);
234 LONG r = ::RegEnumValue(key_, index, buf, &bufsize, NULL, NULL, NULL, NULL); 245 LONG r = ::RegEnumValue(key_, index, buf, &bufsize, NULL, NULL, NULL, NULL);
235 if (r == ERROR_SUCCESS) 246 if (r == ERROR_SUCCESS)
236 *name = buf; 247 *name = buf;
237 248
238 return r; 249 return r;
239 } 250 }
240 251
241 LONG RegKey::DeleteKey(const wchar_t* name) { 252 LONG RegKey::DeleteKey(const wchar_t* name) {
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 } 357 }
347 } 358 }
348 359
349 return result; 360 return result;
350 } 361 }
351 362
352 LONG RegKey::ReadValue(const wchar_t* name, 363 LONG RegKey::ReadValue(const wchar_t* name,
353 void* data, 364 void* data,
354 DWORD* dsize, 365 DWORD* dsize,
355 DWORD* dtype) const { 366 DWORD* dtype) const {
367 DCHECK(key_);
356 LONG result = RegQueryValueEx(key_, name, 0, dtype, 368 LONG result = RegQueryValueEx(key_, name, 0, dtype,
357 reinterpret_cast<LPBYTE>(data), dsize); 369 reinterpret_cast<LPBYTE>(data), dsize);
358 return result; 370 return result;
359 } 371 }
360 372
361 LONG RegKey::ReadValues(const wchar_t* name, 373 LONG RegKey::ReadValues(const wchar_t* name,
362 std::vector<std::wstring>* values) { 374 std::vector<std::wstring>* values) {
363 values->clear(); 375 values->clear();
364 376
365 DWORD type = REG_MULTI_SZ; 377 DWORD type = REG_MULTI_SZ;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 LONG RegKey::WriteValue(const wchar_t * name, const wchar_t* in_value) { 409 LONG RegKey::WriteValue(const wchar_t * name, const wchar_t* in_value) {
398 return WriteValue(name, in_value, 410 return WriteValue(name, in_value,
399 static_cast<DWORD>(sizeof(*in_value) * (wcslen(in_value) + 1)), REG_SZ); 411 static_cast<DWORD>(sizeof(*in_value) * (wcslen(in_value) + 1)), REG_SZ);
400 } 412 }
401 413
402 LONG RegKey::WriteValue(const wchar_t* name, 414 LONG RegKey::WriteValue(const wchar_t* name,
403 const void* data, 415 const void* data,
404 DWORD dsize, 416 DWORD dsize,
405 DWORD dtype) { 417 DWORD dtype) {
406 DCHECK(data || !dsize); 418 DCHECK(data || !dsize);
419 DCHECK(key_);
407 420
408 LONG result = RegSetValueEx(key_, name, 0, dtype, 421 LONG result = RegSetValueEx(key_, name, 0, dtype,
409 reinterpret_cast<LPBYTE>(const_cast<void*>(data)), dsize); 422 reinterpret_cast<LPBYTE>(const_cast<void*>(data)), dsize);
410 return result; 423 return result;
411 } 424 }
412 425
413 bool RegKey::StartWatching(const ChangeCallback& callback) { 426 bool RegKey::StartWatching(const ChangeCallback& callback) {
414 if (!key_watcher_) 427 if (!key_watcher_)
415 key_watcher_.reset(new Watcher()); 428 key_watcher_.reset(new Watcher());
416 429
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 REGSAM wow64access) { 627 REGSAM wow64access) {
615 Initialize(root_key, folder_key, wow64access); 628 Initialize(root_key, folder_key, wow64access);
616 } 629 }
617 630
618 RegistryKeyIterator::~RegistryKeyIterator() { 631 RegistryKeyIterator::~RegistryKeyIterator() {
619 if (key_) 632 if (key_)
620 ::RegCloseKey(key_); 633 ::RegCloseKey(key_);
621 } 634 }
622 635
623 DWORD RegistryKeyIterator::SubkeyCount() const { 636 DWORD RegistryKeyIterator::SubkeyCount() const {
637 DCHECK(key_);
624 DWORD count = 0; 638 DWORD count = 0;
625 LONG result = ::RegQueryInfoKey(key_, NULL, 0, NULL, &count, NULL, NULL, 639 LONG result = ::RegQueryInfoKey(key_, NULL, 0, NULL, &count, NULL, NULL,
626 NULL, NULL, NULL, NULL, NULL); 640 NULL, NULL, NULL, NULL, NULL);
627 if (result != ERROR_SUCCESS) 641 if (result != ERROR_SUCCESS)
628 return 0; 642 return 0;
629 643
630 return count; 644 return count;
631 } 645 }
632 646
633 bool RegistryKeyIterator::Valid() const { 647 bool RegistryKeyIterator::Valid() const {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
672 } else { 686 } else {
673 index_ = count - 1; 687 index_ = count - 1;
674 } 688 }
675 } 689 }
676 690
677 Read(); 691 Read();
678 } 692 }
679 693
680 } // namespace win 694 } // namespace win
681 } // namespace base 695 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698