OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/threading/thread_restrictions.h" | 10 #include "base/threading/thread_restrictions.h" |
11 | 11 |
12 #pragma comment(lib, "shlwapi.lib") // for SHDeleteKey | 12 #pragma comment(lib, "shlwapi.lib") // for SHDeleteKey |
13 | 13 |
14 namespace base { | 14 namespace base { |
15 namespace win { | 15 namespace win { |
16 | 16 |
17 RegistryValueIterator::RegistryValueIterator(HKEY root_key, | 17 // RegKey ---------------------------------------------------------------------- |
18 const wchar_t* folder_key) { | |
19 base::ThreadRestrictions::AssertIOAllowed(); | |
20 | |
21 LONG result = RegOpenKeyEx(root_key, folder_key, 0, KEY_READ, &key_); | |
22 if (result != ERROR_SUCCESS) { | |
23 key_ = NULL; | |
24 } else { | |
25 DWORD count = 0; | |
26 result = ::RegQueryInfoKey(key_, NULL, 0, NULL, NULL, NULL, NULL, &count, | |
27 NULL, NULL, NULL, NULL); | |
28 | |
29 if (result != ERROR_SUCCESS) { | |
30 ::RegCloseKey(key_); | |
31 key_ = NULL; | |
32 } else { | |
33 index_ = count - 1; | |
34 } | |
35 } | |
36 | |
37 Read(); | |
38 } | |
39 | |
40 RegistryValueIterator::~RegistryValueIterator() { | |
41 base::ThreadRestrictions::AssertIOAllowed(); | |
42 if (key_) | |
43 ::RegCloseKey(key_); | |
44 } | |
45 | |
46 bool RegistryValueIterator::Valid() const { | |
47 return key_ != NULL && index_ >= 0; | |
48 } | |
49 | |
50 void RegistryValueIterator::operator++() { | |
51 --index_; | |
52 Read(); | |
53 } | |
54 | |
55 bool RegistryValueIterator::Read() { | |
56 base::ThreadRestrictions::AssertIOAllowed(); | |
57 if (Valid()) { | |
58 DWORD ncount = arraysize(name_); | |
59 value_size_ = sizeof(value_); | |
60 LRESULT r = ::RegEnumValue(key_, index_, name_, &ncount, NULL, &type_, | |
61 reinterpret_cast<BYTE*>(value_), &value_size_); | |
62 if (ERROR_SUCCESS == r) | |
63 return true; | |
64 } | |
65 | |
66 name_[0] = '\0'; | |
67 value_[0] = '\0'; | |
68 value_size_ = 0; | |
69 return false; | |
70 } | |
71 | |
72 DWORD RegistryValueIterator::ValueCount() const { | |
73 base::ThreadRestrictions::AssertIOAllowed(); | |
74 DWORD count = 0; | |
75 HRESULT result = ::RegQueryInfoKey(key_, NULL, 0, NULL, NULL, NULL, NULL, | |
76 &count, NULL, NULL, NULL, NULL); | |
77 | |
78 if (result != ERROR_SUCCESS) | |
79 return 0; | |
80 | |
81 return count; | |
82 } | |
83 | |
84 RegistryKeyIterator::RegistryKeyIterator(HKEY root_key, | |
85 const wchar_t* folder_key) { | |
86 base::ThreadRestrictions::AssertIOAllowed(); | |
87 LONG result = RegOpenKeyEx(root_key, folder_key, 0, KEY_READ, &key_); | |
88 if (result != ERROR_SUCCESS) { | |
89 key_ = NULL; | |
90 } else { | |
91 DWORD count = 0; | |
92 HRESULT result = ::RegQueryInfoKey(key_, NULL, 0, NULL, &count, NULL, NULL, | |
93 NULL, NULL, NULL, NULL, NULL); | |
94 | |
95 if (result != ERROR_SUCCESS) { | |
96 ::RegCloseKey(key_); | |
97 key_ = NULL; | |
98 } else { | |
99 index_ = count - 1; | |
100 } | |
101 } | |
102 | |
103 Read(); | |
104 } | |
105 | |
106 RegistryKeyIterator::~RegistryKeyIterator() { | |
107 base::ThreadRestrictions::AssertIOAllowed(); | |
108 if (key_) | |
109 ::RegCloseKey(key_); | |
110 } | |
111 | |
112 bool RegistryKeyIterator::Valid() const { | |
113 return key_ != NULL && index_ >= 0; | |
114 } | |
115 | |
116 void RegistryKeyIterator::operator++() { | |
117 --index_; | |
118 Read(); | |
119 } | |
120 | |
121 bool RegistryKeyIterator::Read() { | |
122 base::ThreadRestrictions::AssertIOAllowed(); | |
123 if (Valid()) { | |
124 DWORD ncount = arraysize(name_); | |
125 FILETIME written; | |
126 LRESULT r = ::RegEnumKeyEx(key_, index_, name_, &ncount, NULL, NULL, | |
127 NULL, &written); | |
128 if (ERROR_SUCCESS == r) | |
129 return true; | |
130 } | |
131 | |
132 name_[0] = '\0'; | |
133 return false; | |
134 } | |
135 | |
136 DWORD RegistryKeyIterator::SubkeyCount() const { | |
137 base::ThreadRestrictions::AssertIOAllowed(); | |
138 DWORD count = 0; | |
139 HRESULT result = ::RegQueryInfoKey(key_, NULL, 0, NULL, &count, NULL, NULL, | |
140 NULL, NULL, NULL, NULL, NULL); | |
141 | |
142 if (result != ERROR_SUCCESS) | |
143 return 0; | |
144 | |
145 return count; | |
146 } | |
147 | 18 |
148 RegKey::RegKey() | 19 RegKey::RegKey() |
149 : key_(NULL), | 20 : key_(NULL), |
150 watch_event_(0) { | 21 watch_event_(0) { |
151 } | 22 } |
152 | 23 |
153 RegKey::RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access) | 24 RegKey::RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access) |
154 : key_(NULL), | 25 : key_(NULL), |
155 watch_event_(0) { | 26 watch_event_(0) { |
156 base::ThreadRestrictions::AssertIOAllowed(); | 27 base::ThreadRestrictions::AssertIOAllowed(); |
157 if (rootkey) { | 28 if (rootkey) { |
158 if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK)) | 29 if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK)) |
159 Create(rootkey, subkey, access); | 30 Create(rootkey, subkey, access); |
160 else | 31 else |
161 Open(rootkey, subkey, access); | 32 Open(rootkey, subkey, access); |
162 } else { | 33 } else { |
163 DCHECK(!subkey); | 34 DCHECK(!subkey); |
164 } | 35 } |
165 } | 36 } |
166 | 37 |
167 RegKey::~RegKey() { | 38 RegKey::~RegKey() { |
168 Close(); | 39 Close(); |
169 } | 40 } |
170 | 41 |
171 void RegKey::Close() { | |
172 base::ThreadRestrictions::AssertIOAllowed(); | |
173 StopWatching(); | |
174 if (key_) { | |
175 ::RegCloseKey(key_); | |
176 key_ = NULL; | |
177 } | |
178 } | |
179 | |
180 bool RegKey::Create(HKEY rootkey, const wchar_t* subkey, REGSAM access) { | 42 bool RegKey::Create(HKEY rootkey, const wchar_t* subkey, REGSAM access) { |
181 DWORD disposition_value; | 43 DWORD disposition_value; |
182 return CreateWithDisposition(rootkey, subkey, &disposition_value, access); | 44 return CreateWithDisposition(rootkey, subkey, &disposition_value, access); |
183 } | 45 } |
184 | 46 |
185 bool RegKey::CreateWithDisposition(HKEY rootkey, const wchar_t* subkey, | 47 bool RegKey::CreateWithDisposition(HKEY rootkey, const wchar_t* subkey, |
186 DWORD* disposition, REGSAM access) { | 48 DWORD* disposition, REGSAM access) { |
187 base::ThreadRestrictions::AssertIOAllowed(); | 49 base::ThreadRestrictions::AssertIOAllowed(); |
188 DCHECK(rootkey && subkey && access && disposition); | 50 DCHECK(rootkey && subkey && access && disposition); |
189 Close(); | 51 Close(); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 | 99 |
238 HKEY subkey = NULL; | 100 HKEY subkey = NULL; |
239 LONG result = RegOpenKeyEx(key_, name, 0, access, &subkey); | 101 LONG result = RegOpenKeyEx(key_, name, 0, access, &subkey); |
240 | 102 |
241 Close(); | 103 Close(); |
242 | 104 |
243 key_ = subkey; | 105 key_ = subkey; |
244 return (result == ERROR_SUCCESS); | 106 return (result == ERROR_SUCCESS); |
245 } | 107 } |
246 | 108 |
| 109 void RegKey::Close() { |
| 110 base::ThreadRestrictions::AssertIOAllowed(); |
| 111 StopWatching(); |
| 112 if (key_) { |
| 113 ::RegCloseKey(key_); |
| 114 key_ = NULL; |
| 115 } |
| 116 } |
| 117 |
247 DWORD RegKey::ValueCount() const { | 118 DWORD RegKey::ValueCount() const { |
248 base::ThreadRestrictions::AssertIOAllowed(); | 119 base::ThreadRestrictions::AssertIOAllowed(); |
249 DWORD count = 0; | 120 DWORD count = 0; |
250 HRESULT result = RegQueryInfoKey(key_, NULL, 0, NULL, NULL, NULL, | 121 HRESULT result = RegQueryInfoKey(key_, NULL, 0, NULL, NULL, NULL, |
251 NULL, &count, NULL, NULL, NULL, NULL); | 122 NULL, &count, NULL, NULL, NULL, NULL); |
252 return (result != ERROR_SUCCESS) ? 0 : count; | 123 return (result != ERROR_SUCCESS) ? 0 : count; |
253 } | 124 } |
254 | 125 |
255 bool RegKey::ReadName(int index, std::wstring* name) const { | 126 bool RegKey::ReadName(int index, std::wstring* name) const { |
256 base::ThreadRestrictions::AssertIOAllowed(); | 127 base::ThreadRestrictions::AssertIOAllowed(); |
257 wchar_t buf[256]; | 128 wchar_t buf[256]; |
258 DWORD bufsize = arraysize(buf); | 129 DWORD bufsize = arraysize(buf); |
259 LRESULT r = ::RegEnumValue(key_, index, buf, &bufsize, NULL, NULL, | 130 LRESULT r = ::RegEnumValue(key_, index, buf, &bufsize, NULL, NULL, |
260 NULL, NULL); | 131 NULL, NULL); |
261 if (r != ERROR_SUCCESS) | 132 if (r != ERROR_SUCCESS) |
262 return false; | 133 return false; |
263 if (name) | 134 if (name) |
264 *name = buf; | 135 *name = buf; |
265 return true; | 136 return true; |
266 } | 137 } |
267 | 138 |
| 139 bool RegKey::DeleteKey(const wchar_t* name) { |
| 140 base::ThreadRestrictions::AssertIOAllowed(); |
| 141 if (!key_) |
| 142 return false; |
| 143 LSTATUS ret = SHDeleteKey(key_, name); |
| 144 if (ERROR_SUCCESS != ret) |
| 145 SetLastError(ret); |
| 146 return ERROR_SUCCESS == ret; |
| 147 } |
| 148 |
| 149 bool RegKey::DeleteValue(const wchar_t* value_name) { |
| 150 base::ThreadRestrictions::AssertIOAllowed(); |
| 151 DCHECK(value_name); |
| 152 HRESULT result = RegDeleteValue(key_, value_name); |
| 153 return (result == ERROR_SUCCESS); |
| 154 } |
| 155 |
268 bool RegKey::ValueExists(const wchar_t* name) { | 156 bool RegKey::ValueExists(const wchar_t* name) { |
269 base::ThreadRestrictions::AssertIOAllowed(); | 157 base::ThreadRestrictions::AssertIOAllowed(); |
270 if (!key_) | 158 if (!key_) |
271 return false; | 159 return false; |
272 HRESULT result = RegQueryValueEx(key_, name, 0, NULL, NULL, NULL); | 160 HRESULT result = RegQueryValueEx(key_, name, 0, NULL, NULL, NULL); |
273 return (result == ERROR_SUCCESS); | 161 return (result == ERROR_SUCCESS); |
274 } | 162 } |
275 | 163 |
276 bool RegKey::ReadValue(const wchar_t* name, void* data, | 164 bool RegKey::ReadValue(const wchar_t* name, void* data, |
277 DWORD* dsize, DWORD* dtype) const { | 165 DWORD* dsize, DWORD* dtype) const { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 bool RegKey::WriteValue(const wchar_t * name, const wchar_t* value) { | 236 bool RegKey::WriteValue(const wchar_t * name, const wchar_t* value) { |
349 return WriteValue(name, value, | 237 return WriteValue(name, value, |
350 static_cast<DWORD>(sizeof(*value) * (wcslen(value) + 1)), REG_SZ); | 238 static_cast<DWORD>(sizeof(*value) * (wcslen(value) + 1)), REG_SZ); |
351 } | 239 } |
352 | 240 |
353 bool RegKey::WriteValue(const wchar_t* name, DWORD value) { | 241 bool RegKey::WriteValue(const wchar_t* name, DWORD value) { |
354 return WriteValue(name, &value, | 242 return WriteValue(name, &value, |
355 static_cast<DWORD>(sizeof(value)), REG_DWORD); | 243 static_cast<DWORD>(sizeof(value)), REG_DWORD); |
356 } | 244 } |
357 | 245 |
358 bool RegKey::DeleteKey(const wchar_t* name) { | |
359 base::ThreadRestrictions::AssertIOAllowed(); | |
360 if (!key_) | |
361 return false; | |
362 LSTATUS ret = SHDeleteKey(key_, name); | |
363 if (ERROR_SUCCESS != ret) | |
364 SetLastError(ret); | |
365 return ERROR_SUCCESS == ret; | |
366 } | |
367 | |
368 bool RegKey::DeleteValue(const wchar_t* value_name) { | |
369 base::ThreadRestrictions::AssertIOAllowed(); | |
370 DCHECK(value_name); | |
371 HRESULT result = RegDeleteValue(key_, value_name); | |
372 return (result == ERROR_SUCCESS); | |
373 } | |
374 | |
375 bool RegKey::StartWatching() { | 246 bool RegKey::StartWatching() { |
376 if (!watch_event_) | 247 if (!watch_event_) |
377 watch_event_ = CreateEvent(NULL, TRUE, FALSE, NULL); | 248 watch_event_ = CreateEvent(NULL, TRUE, FALSE, NULL); |
378 | 249 |
379 DWORD filter = REG_NOTIFY_CHANGE_NAME | | 250 DWORD filter = REG_NOTIFY_CHANGE_NAME | |
380 REG_NOTIFY_CHANGE_ATTRIBUTES | | 251 REG_NOTIFY_CHANGE_ATTRIBUTES | |
381 REG_NOTIFY_CHANGE_LAST_SET | | 252 REG_NOTIFY_CHANGE_LAST_SET | |
382 REG_NOTIFY_CHANGE_SECURITY; | 253 REG_NOTIFY_CHANGE_SECURITY; |
383 | 254 |
384 // Watch the registry key for a change of value. | 255 // Watch the registry key for a change of value. |
385 HRESULT result = RegNotifyChangeKeyValue(key_, TRUE, filter, | 256 HRESULT result = RegNotifyChangeKeyValue(key_, TRUE, filter, |
386 watch_event_, TRUE); | 257 watch_event_, TRUE); |
387 if (SUCCEEDED(result)) { | 258 if (SUCCEEDED(result)) { |
388 return true; | 259 return true; |
389 } else { | 260 } else { |
390 CloseHandle(watch_event_); | 261 CloseHandle(watch_event_); |
391 watch_event_ = 0; | 262 watch_event_ = 0; |
392 return false; | 263 return false; |
393 } | 264 } |
394 } | 265 } |
395 | 266 |
| 267 bool RegKey::HasChanged() { |
| 268 if (watch_event_) { |
| 269 if (WaitForSingleObject(watch_event_, 0) == WAIT_OBJECT_0) { |
| 270 StartWatching(); |
| 271 return true; |
| 272 } |
| 273 } |
| 274 return false; |
| 275 } |
| 276 |
396 bool RegKey::StopWatching() { | 277 bool RegKey::StopWatching() { |
397 if (watch_event_) { | 278 if (watch_event_) { |
398 CloseHandle(watch_event_); | 279 CloseHandle(watch_event_); |
399 watch_event_ = 0; | 280 watch_event_ = 0; |
400 return true; | 281 return true; |
401 } | 282 } |
402 return false; | 283 return false; |
403 } | 284 } |
404 | 285 |
405 bool RegKey::HasChanged() { | 286 // RegistryValueIterator ------------------------------------------------------ |
406 if (watch_event_) { | 287 |
407 if (WaitForSingleObject(watch_event_, 0) == WAIT_OBJECT_0) { | 288 RegistryValueIterator::RegistryValueIterator(HKEY root_key, |
408 StartWatching(); | 289 const wchar_t* folder_key) { |
409 return true; | 290 base::ThreadRestrictions::AssertIOAllowed(); |
| 291 |
| 292 LONG result = RegOpenKeyEx(root_key, folder_key, 0, KEY_READ, &key_); |
| 293 if (result != ERROR_SUCCESS) { |
| 294 key_ = NULL; |
| 295 } else { |
| 296 DWORD count = 0; |
| 297 result = ::RegQueryInfoKey(key_, NULL, 0, NULL, NULL, NULL, NULL, &count, |
| 298 NULL, NULL, NULL, NULL); |
| 299 |
| 300 if (result != ERROR_SUCCESS) { |
| 301 ::RegCloseKey(key_); |
| 302 key_ = NULL; |
| 303 } else { |
| 304 index_ = count - 1; |
410 } | 305 } |
411 } | 306 } |
| 307 |
| 308 Read(); |
| 309 } |
| 310 |
| 311 RegistryValueIterator::~RegistryValueIterator() { |
| 312 base::ThreadRestrictions::AssertIOAllowed(); |
| 313 if (key_) |
| 314 ::RegCloseKey(key_); |
| 315 } |
| 316 |
| 317 DWORD RegistryValueIterator::ValueCount() const { |
| 318 base::ThreadRestrictions::AssertIOAllowed(); |
| 319 DWORD count = 0; |
| 320 HRESULT result = ::RegQueryInfoKey(key_, NULL, 0, NULL, NULL, NULL, NULL, |
| 321 &count, NULL, NULL, NULL, NULL); |
| 322 |
| 323 if (result != ERROR_SUCCESS) |
| 324 return 0; |
| 325 |
| 326 return count; |
| 327 } |
| 328 |
| 329 bool RegistryValueIterator::Valid() const { |
| 330 return key_ != NULL && index_ >= 0; |
| 331 } |
| 332 |
| 333 void RegistryValueIterator::operator++() { |
| 334 --index_; |
| 335 Read(); |
| 336 } |
| 337 |
| 338 bool RegistryValueIterator::Read() { |
| 339 base::ThreadRestrictions::AssertIOAllowed(); |
| 340 if (Valid()) { |
| 341 DWORD ncount = arraysize(name_); |
| 342 value_size_ = sizeof(value_); |
| 343 LRESULT r = ::RegEnumValue(key_, index_, name_, &ncount, NULL, &type_, |
| 344 reinterpret_cast<BYTE*>(value_), &value_size_); |
| 345 if (ERROR_SUCCESS == r) |
| 346 return true; |
| 347 } |
| 348 |
| 349 name_[0] = '\0'; |
| 350 value_[0] = '\0'; |
| 351 value_size_ = 0; |
412 return false; | 352 return false; |
413 } | 353 } |
414 | 354 |
| 355 // RegistryKeyIterator -------------------------------------------------------- |
| 356 |
| 357 RegistryKeyIterator::RegistryKeyIterator(HKEY root_key, |
| 358 const wchar_t* folder_key) { |
| 359 base::ThreadRestrictions::AssertIOAllowed(); |
| 360 LONG result = RegOpenKeyEx(root_key, folder_key, 0, KEY_READ, &key_); |
| 361 if (result != ERROR_SUCCESS) { |
| 362 key_ = NULL; |
| 363 } else { |
| 364 DWORD count = 0; |
| 365 HRESULT result = ::RegQueryInfoKey(key_, NULL, 0, NULL, &count, NULL, NULL, |
| 366 NULL, NULL, NULL, NULL, NULL); |
| 367 |
| 368 if (result != ERROR_SUCCESS) { |
| 369 ::RegCloseKey(key_); |
| 370 key_ = NULL; |
| 371 } else { |
| 372 index_ = count - 1; |
| 373 } |
| 374 } |
| 375 |
| 376 Read(); |
| 377 } |
| 378 |
| 379 RegistryKeyIterator::~RegistryKeyIterator() { |
| 380 base::ThreadRestrictions::AssertIOAllowed(); |
| 381 if (key_) |
| 382 ::RegCloseKey(key_); |
| 383 } |
| 384 |
| 385 DWORD RegistryKeyIterator::SubkeyCount() const { |
| 386 base::ThreadRestrictions::AssertIOAllowed(); |
| 387 DWORD count = 0; |
| 388 HRESULT result = ::RegQueryInfoKey(key_, NULL, 0, NULL, &count, NULL, NULL, |
| 389 NULL, NULL, NULL, NULL, NULL); |
| 390 |
| 391 if (result != ERROR_SUCCESS) |
| 392 return 0; |
| 393 |
| 394 return count; |
| 395 } |
| 396 |
| 397 bool RegistryKeyIterator::Valid() const { |
| 398 return key_ != NULL && index_ >= 0; |
| 399 } |
| 400 |
| 401 void RegistryKeyIterator::operator++() { |
| 402 --index_; |
| 403 Read(); |
| 404 } |
| 405 |
| 406 bool RegistryKeyIterator::Read() { |
| 407 base::ThreadRestrictions::AssertIOAllowed(); |
| 408 if (Valid()) { |
| 409 DWORD ncount = arraysize(name_); |
| 410 FILETIME written; |
| 411 LRESULT r = ::RegEnumKeyEx(key_, index_, name_, &ncount, NULL, NULL, |
| 412 NULL, &written); |
| 413 if (ERROR_SUCCESS == r) |
| 414 return true; |
| 415 } |
| 416 |
| 417 name_[0] = '\0'; |
| 418 return false; |
| 419 } |
| 420 |
415 } // namespace win | 421 } // namespace win |
416 } // namespace base | 422 } // namespace base |
OLD | NEW |