OLD | NEW |
| (Empty) |
1 // Copyright 2003-2009 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 // | |
16 // reg_key.h | |
17 // | |
18 // Registry configuration wrappers class | |
19 // | |
20 // Offers static functions for convenient | |
21 // fast access for individual values | |
22 // | |
23 // Also provides a wrapper class for efficient | |
24 // batch operations on values of a given registry key. | |
25 | |
26 #ifndef OMAHA_BASE_REG_KEY_H_ | |
27 #define OMAHA_BASE_REG_KEY_H_ | |
28 | |
29 #include <windows.h> | |
30 #include <vector> | |
31 #include "base/basictypes.h" | |
32 #include "base/scoped_ptr.h" | |
33 #include "omaha/base/debug.h" | |
34 #include "omaha/base/logging.h" | |
35 #include "omaha/base/scoped_any.h" | |
36 #include "omaha/base/static_assert.h" | |
37 #include "omaha/base/store_watcher.h" | |
38 | |
39 namespace omaha { | |
40 | |
41 // maximum sizes registry key and value names | |
42 #define kMaxKeyNameChars (255 + 1) | |
43 #define kMaxValueNameChars (16383 + 1) | |
44 | |
45 class RegKey { | |
46 public: | |
47 RegKey(); | |
48 virtual ~RegKey(); | |
49 | |
50 // create a reg key | |
51 HRESULT Create(HKEY hKeyParent, const TCHAR * key_name, | |
52 TCHAR * reg_class = REG_NONE, DWORD options = REG_OPTION_NON_VOLATILE, | |
53 REGSAM sam_desired = KEY_ALL_ACCESS, | |
54 LPSECURITY_ATTRIBUTES lp_sec_attr = NULL, | |
55 LPDWORD lp_disposition = NULL); | |
56 | |
57 // create a reg key, given the full key name, including the HKEY root | |
58 // (say for example, "HKLM\\Software") | |
59 HRESULT Create(const TCHAR * full_key_name, | |
60 TCHAR * reg_class = REG_NONE, DWORD options = REG_OPTION_NON_VOLATILE, | |
61 REGSAM sam_desired = KEY_ALL_ACCESS, | |
62 LPSECURITY_ATTRIBUTES lp_sec_attr = NULL, | |
63 LPDWORD lp_disposition = NULL); | |
64 | |
65 // static helper function that create a set of reg keys, | |
66 // given an array of full key names including the HKEY root | |
67 // (say for example, "HKLM\\Software") | |
68 static HRESULT CreateKeys(const TCHAR* keys_to_create[], | |
69 DWORD number_of_keys, | |
70 TCHAR* reg_class = REG_NONE, | |
71 DWORD options = REG_OPTION_NON_VOLATILE, | |
72 LPSECURITY_ATTRIBUTES lp_sec_attr = NULL); | |
73 | |
74 // Static method to create a single key. | |
75 static HRESULT CreateKey(const TCHAR * full_key_name, | |
76 TCHAR * reg_class = REG_NONE, | |
77 DWORD options = REG_OPTION_NON_VOLATILE, | |
78 LPSECURITY_ATTRIBUTES lp_sec_attr = NULL); | |
79 | |
80 // open an existing reg key | |
81 HRESULT Open(HKEY hKeyParent, | |
82 const TCHAR * key_name, | |
83 REGSAM sam_desired = KEY_ALL_ACCESS); | |
84 | |
85 // open an existing reg key, given the full key name, including the HKEY root | |
86 // (say for example, "HKLM\\Software") | |
87 HRESULT Open(const TCHAR * full_key_name, | |
88 REGSAM sam_desired = KEY_ALL_ACCESS); | |
89 | |
90 // close this reg key | |
91 virtual HRESULT Close(); | |
92 | |
93 // check if the key has a specified value | |
94 bool HasValue(const TCHAR * value_name); | |
95 | |
96 // get the number of values for this key | |
97 uint32 GetValueCount(); | |
98 | |
99 // Called to get the value name for the given value name index | |
100 // Use GetValueCount() to get the total value_name count for this key | |
101 // Returns failure if no key at the specified index | |
102 // If you modify the key while enumerating, the indexes will be out of order. | |
103 // Since the index order is not guaranteed, you need to reset your counting | |
104 // loop. | |
105 // type refers to REG_DWORD, REG_QWORD, etc.. | |
106 // 'type' can be NULL if not interested in the value type | |
107 HRESULT GetValueNameAt(int index, CString * value_name, DWORD *type); | |
108 | |
109 // check if the current key has the specified subkey | |
110 bool HasSubkey(const TCHAR * key_name) const; | |
111 | |
112 // get the number of subkeys for this key | |
113 uint32 GetSubkeyCount(); | |
114 | |
115 // Called to get the key name for the given key index | |
116 // Use GetSubkeyCount() to get the total count for this key | |
117 // Returns failure if no key at the specified index | |
118 // If you modify the key while enumerating, the indexes will be out of order. | |
119 // Since the index order is not guaranteed, you need to reset your counting | |
120 // loop. | |
121 HRESULT GetSubkeyNameAt(int index, CString * key_name); | |
122 | |
123 // SETTERS | |
124 | |
125 // set an int32 value - use when reading multiple values from a key | |
126 HRESULT SetValue(const TCHAR * value_name, DWORD value) const; | |
127 | |
128 // set an int64 value | |
129 HRESULT SetValue(const TCHAR * value_name, DWORD64 value) const; | |
130 | |
131 // set a string value | |
132 HRESULT SetValue(const TCHAR * value_name, const TCHAR * value) const; | |
133 | |
134 // set binary data | |
135 HRESULT SetValue(const TCHAR * value_name, | |
136 const byte * value, | |
137 DWORD byte_count) const; | |
138 | |
139 // set raw data, including type | |
140 HRESULT SetValue(const TCHAR * value_name, | |
141 const byte * value, | |
142 DWORD byte_count, | |
143 DWORD type) const; | |
144 | |
145 // GETTERS | |
146 | |
147 // get type of a registry value | |
148 HRESULT GetValueType(const TCHAR* value_name, DWORD* value_type) const; | |
149 | |
150 // get an int32 value | |
151 HRESULT GetValue(const TCHAR * value_name, DWORD * value) const; | |
152 | |
153 // get an int64 value | |
154 // | |
155 // Note: if you are using time64 you should | |
156 // likely use GetLimitedTimeValue (util.h) instead of this method. | |
157 HRESULT GetValue(const TCHAR * value_name, DWORD64 * value) const; | |
158 | |
159 // get a string value - the caller must free the return buffer | |
160 HRESULT GetValue(const TCHAR * value_name, TCHAR * * value) const; | |
161 | |
162 // get a CString value | |
163 HRESULT GetValue(const TCHAR* value_name, OUT CString* value) const; | |
164 | |
165 // get a vector<CString> value from REG_MULTI_SZ type | |
166 HRESULT GetValue(const TCHAR * value_name, | |
167 std::vector<CString> * value) const; | |
168 | |
169 // get binary data - the caller must free the return buffer | |
170 HRESULT GetValue(const TCHAR * value_name, | |
171 byte * * value, | |
172 DWORD * byte_count) const; | |
173 | |
174 // get raw data, including type - the caller must free the return buffer | |
175 HRESULT GetValue(const TCHAR * value_name, | |
176 byte * * value, | |
177 DWORD * byte_count, | |
178 DWORD *type) const; | |
179 | |
180 // RENAMERS | |
181 | |
182 // Rename a named value. | |
183 HRESULT RenameValue(const TCHAR * old_value_name, | |
184 const TCHAR * new_value_name) const; | |
185 | |
186 // STATIC VERSIONS | |
187 | |
188 // flush | |
189 static HRESULT FlushKey(const TCHAR * full_key_name); | |
190 | |
191 // Check if a key exists. | |
192 static bool HasKey(const TCHAR * full_key_name); | |
193 | |
194 // Check if a key exists in the native (i.e. non-redirected) registry. | |
195 static bool HasNativeKey(const TCHAR * full_key_name); | |
196 | |
197 // check if the key has a specified value | |
198 static bool HasValue(const TCHAR * full_key_name, const TCHAR * value_name); | |
199 | |
200 // SETTERS | |
201 | |
202 // STATIC int32 set | |
203 static HRESULT SetValue(const TCHAR * full_key_name, | |
204 const TCHAR * value_name, | |
205 DWORD value); | |
206 | |
207 // STATIC int64 set | |
208 static HRESULT SetValue(const TCHAR * full_key_name, | |
209 const TCHAR * value_name, | |
210 DWORD64 value); | |
211 | |
212 // STATIC float set | |
213 static HRESULT SetValue(const TCHAR * full_key_name, | |
214 const TCHAR * value_name, | |
215 float value); | |
216 | |
217 // STATIC double set | |
218 static HRESULT SetValue(const TCHAR * full_key_name, | |
219 const TCHAR * value_name, | |
220 double value); | |
221 | |
222 // STATIC string set | |
223 static HRESULT SetValue(const TCHAR * full_key_name, | |
224 const TCHAR * value_name, | |
225 const TCHAR * value); | |
226 | |
227 // STATIC binary data set | |
228 static HRESULT SetValue(const TCHAR * full_key_name, | |
229 const TCHAR * value_name, | |
230 const byte * value, | |
231 DWORD byte_count); | |
232 | |
233 // STATIC array of strings set | |
234 static HRESULT SetValueMultiSZ(const TCHAR * full_key_name, | |
235 const TCHAR * value_name, | |
236 const byte * value, | |
237 DWORD byte_count); | |
238 | |
239 // STATIC expandable string set | |
240 static HRESULT SetValueExpandSZ(const TCHAR * full_key_name, | |
241 const TCHAR * value_name, | |
242 const TCHAR * value); | |
243 | |
244 // GETTERS | |
245 | |
246 // STATIC int32 get | |
247 static HRESULT GetValue(const TCHAR * full_key_name, | |
248 const TCHAR * value_name, | |
249 DWORD * value); | |
250 | |
251 // STATIC int64 get | |
252 // | |
253 // Note: if you are using time64 you should | |
254 // likely use GetLimitedTimeValue (util.h) instead of this method. | |
255 static HRESULT GetValue(const TCHAR * full_key_name, | |
256 const TCHAR * value_name, | |
257 DWORD64 * value); | |
258 | |
259 // STATIC float get | |
260 static HRESULT GetValue(const TCHAR * full_key_name, | |
261 const TCHAR * value_name, | |
262 float * value); | |
263 | |
264 // STATIC double get | |
265 static HRESULT GetValue(const TCHAR * full_key_name, | |
266 const TCHAR * value_name, | |
267 double * value); | |
268 | |
269 // STATIC string get (STR and CString versions) - the caller must free | |
270 // the return buffer | |
271 static HRESULT GetValue(const TCHAR * full_key_name, | |
272 const TCHAR * value_name, | |
273 TCHAR * * value); | |
274 | |
275 static HRESULT GetValue(const TCHAR * full_key_name, | |
276 const TCHAR * value_name, | |
277 CString * value); | |
278 | |
279 // STATIC REG_MULTI_SZ get | |
280 static HRESULT GetValue(const TCHAR * full_key_name, | |
281 const TCHAR * value_name, | |
282 std::vector<CString> * value); | |
283 | |
284 // STATIC get binary data - the caller must free the return buffer | |
285 static HRESULT GetValue(const TCHAR * full_key_name, | |
286 const TCHAR * value_name, | |
287 byte * * value, | |
288 DWORD * byte_count); | |
289 | |
290 // Try reg keys successively if there is a failure in getting a value. | |
291 // | |
292 // Typically used when there is a user value and a default value if the | |
293 // user has none. | |
294 template<typename T> | |
295 static HRESULT GetValue(const TCHAR * full_key_names[], | |
296 int key_names_length, | |
297 const TCHAR * value_name, | |
298 T* value); | |
299 | |
300 // RENAMERS | |
301 | |
302 // Rename a named value. | |
303 static HRESULT RenameValue(const TCHAR * full_key_name, | |
304 const TCHAR * old_value_name, | |
305 const TCHAR * new_value_name); | |
306 | |
307 // COPIERS | |
308 | |
309 // The full_to_key must exist for CopyValue to succeed. | |
310 static HRESULT CopyValue(const TCHAR * full_from_key_name, | |
311 const TCHAR * from_value_name, | |
312 const TCHAR * full_to_key_name, | |
313 const TCHAR * to_value_name); | |
314 | |
315 static HRESULT CopyValue(const TCHAR * full_from_key_name, | |
316 const TCHAR * full_to_key_name, | |
317 const TCHAR * value_name); | |
318 | |
319 // Get type of a registry value | |
320 static HRESULT GetValueType(const TCHAR* full_key_name, | |
321 const TCHAR* value_name, | |
322 DWORD* value_type); | |
323 | |
324 // delete a subkey of the current key (with no subkeys) | |
325 HRESULT DeleteSubKey(const TCHAR * key_name); | |
326 | |
327 // recursively delete a sub key of the current key (and all its subkeys) | |
328 HRESULT RecurseDeleteSubKey(const TCHAR * key_name); | |
329 | |
330 // STATIC version of delete key - handles nested keys also | |
331 // delete a key and all its sub-keys recursively | |
332 // Returns S_FALSE if key didn't exist, S_OK if deletion was successful, | |
333 // and failure otherwise. | |
334 static HRESULT DeleteKey(const TCHAR* full_key_name); | |
335 | |
336 // STATIC version of delete key | |
337 // delete a key recursively or non-recursively | |
338 // Returns S_FALSE if key didn't exist, S_OK if deletion was successful, | |
339 // and failure otherwise. | |
340 static HRESULT DeleteKey(const TCHAR* full_key_name, bool recursive); | |
341 | |
342 // delete the specified value | |
343 HRESULT DeleteValue(const TCHAR * value_name) const; | |
344 | |
345 // STATIC version of delete value | |
346 // Returns S_FALSE if key didn't exist, S_OK if deletion was successful, | |
347 // and failure otherwise. | |
348 static HRESULT DeleteValue(const TCHAR * full_key_name, | |
349 const TCHAR * value_name); | |
350 | |
351 // Peek inside (use a RegKey as a smart wrapper around a registry handle) | |
352 HKEY Key() { return h_key_; } | |
353 | |
354 // Used to help test the private functionality | |
355 friend class RegKeyTestClass; | |
356 | |
357 // helper function to get the HKEY and the root key from a string | |
358 // representation modifies the argument in place and returns the key name | |
359 // e.g. HKLM\\Software\\Google\... returns HKLM, "Software\\Google\..." | |
360 // Necessary for the static versions that use the full name of the reg key | |
361 static HKEY GetRootKeyInfo(CString * full_key_name); | |
362 | |
363 // Returns true if this key name is 'safe' for deletion (doesn't specify | |
364 // a key root) | |
365 static bool SafeKeyNameForDeletion(const wchar_t *key_name); | |
366 | |
367 // save the key and all of its subkeys and values to a file | |
368 static HRESULT Save(const TCHAR* full_key_name, const TCHAR* file_name); | |
369 | |
370 // restore the key and all of its subkeys and values which are saved into | |
371 // a file | |
372 static HRESULT Restore(const TCHAR* full_key_name, const TCHAR* file_name); | |
373 | |
374 // Is the key empty: having no sub-keys and values | |
375 static bool IsKeyEmpty(const TCHAR* full_key_name); | |
376 | |
377 private: | |
378 | |
379 // Helper function to check if a key exists, using the sam flags specified. | |
380 // Note: KEY_READ must be included in sam_flags. | |
381 static bool HasKeyHelper(const TCHAR * full_key_name, DWORD sam_flags); | |
382 | |
383 // helper function to get the parent key name and the subkey from a string | |
384 // representation modifies the argument in place and returns the key name | |
385 // e.g. Software\\Google\\Foo_Bar returns "Software\\Google", "Foo_Bar" | |
386 // Necessary for the static versions that use the full name of the reg key | |
387 static CString GetParentKeyInfo(CString * key_name); | |
388 | |
389 // helper function to get any value from the registry | |
390 // used when the size of the data is unknown | |
391 HRESULT GetValueHelper(const TCHAR * value_name, | |
392 DWORD * type, | |
393 byte * * value, | |
394 DWORD * byte_count) const; | |
395 | |
396 // common SET Helper for the static case | |
397 static HRESULT SetValueStaticHelper(const TCHAR * full_key_name, | |
398 const TCHAR * value_name, | |
399 DWORD type, | |
400 LPVOID value, | |
401 DWORD byte_count = 0); | |
402 | |
403 // common GET Helper for the static case | |
404 static HRESULT GetValueStaticHelper(const TCHAR * full_key_name, | |
405 const TCHAR * value_name, | |
406 DWORD type, | |
407 LPVOID value, | |
408 DWORD * byte_count = NULL); | |
409 | |
410 // convert REG_MULTI_SZ bytes to string array | |
411 static HRESULT MultiSZBytesToStringArray(const byte * buffer, | |
412 DWORD byte_count, | |
413 std::vector<CString> * value); | |
414 | |
415 // set a string or expandable string value | |
416 HRESULT SetStringValue(const TCHAR * value_name, | |
417 const TCHAR * value, | |
418 DWORD type) const; | |
419 | |
420 // the HKEY for the current key | |
421 HKEY h_key_; | |
422 | |
423 DISALLOW_EVIL_CONSTRUCTORS(RegKey); | |
424 }; | |
425 | |
426 // Provides all the functionality of RegKey plus | |
427 // an event to watch for changes to the registry key. | |
428 class RegKeyWithChangeEvent : public RegKey { | |
429 public: | |
430 RegKeyWithChangeEvent() {} | |
431 // close this reg key and the event | |
432 virtual HRESULT Close(); | |
433 | |
434 // Called to create/reset the event that gets signaled | |
435 // any time the registry key changes. Access the created | |
436 // event using change_event(). | |
437 // | |
438 // See the documentation for RegNotifyChangeKeyValue | |
439 // for values for notify_filter. | |
440 HRESULT SetupEvent(bool watch_subtree, DWORD notify_filter); | |
441 | |
442 // Indicates if any changes (that are being monitored) have occured | |
443 bool HasChangeOccurred() const; | |
444 | |
445 // Get the event that is signaled on registry changes. | |
446 // Note: | |
447 // * This event will remain constant until Close() is called. | |
448 // * One should call SetupEvent to set-up the event. | |
449 // * The event is only signaled on the next change and remains signaled. | |
450 // Do not call ::ResetEvent(). Call SetupEvent() to reset | |
451 // the event and wait for more changes. | |
452 HANDLE change_event() const { | |
453 return get(change_event_); | |
454 } | |
455 | |
456 private: | |
457 scoped_handle change_event_; | |
458 DISALLOW_EVIL_CONSTRUCTORS(RegKeyWithChangeEvent); | |
459 }; | |
460 | |
461 // Does the common things necessary for watching | |
462 // registry key changes. If there are file change or other watchers, | |
463 // there could be a common interface for the three methods to decouple | |
464 // the code that is doing the watching from the code that owns the store. | |
465 class RegKeyWatcher : public StoreWatcher { | |
466 public: | |
467 // reg_key: the full string for the reg key | |
468 // watch_subtree: watch all subkey changes or | |
469 // only immediate child values | |
470 // notify_filter: See the documentation for RegNotifyChangeKeyValue | |
471 // allow_creation: Should the key be created if it doesn't exist? | |
472 RegKeyWatcher(const TCHAR* reg_key, bool watch_subtree, | |
473 DWORD notify_filter, bool allow_creation); | |
474 virtual ~RegKeyWatcher() {} | |
475 | |
476 // Called to create/reset the event that gets signaled | |
477 // any time the registry key changes. Access the created | |
478 // event using change_event(). | |
479 virtual HRESULT EnsureEventSetup(); | |
480 | |
481 // Get the event that is signaled on registry changes. | |
482 virtual HANDLE change_event() const; | |
483 | |
484 private: | |
485 // Used to do the SetupEvent method | |
486 scoped_ptr<RegKeyWithChangeEvent> reg_key_with_change_event_; | |
487 | |
488 CString reg_key_string_; | |
489 bool watch_subtree_; | |
490 bool allow_creation_; | |
491 DWORD notify_filter_; | |
492 DISALLOW_EVIL_CONSTRUCTORS(RegKeyWatcher); | |
493 }; | |
494 | |
495 | |
496 inline RegKey::RegKey() { h_key_ = NULL; } | |
497 | |
498 inline RegKey::~RegKey() { Close(); } | |
499 | |
500 inline bool RegKey::HasValue(const TCHAR* value_name) { | |
501 return (ERROR_SUCCESS == ::RegQueryValueEx(h_key_, | |
502 value_name, | |
503 NULL, NULL, | |
504 NULL, | |
505 NULL)); | |
506 } | |
507 | |
508 // SETTERS static versions | |
509 inline HRESULT RegKey::SetValue(const TCHAR* full_key_name, | |
510 const TCHAR* value_name, | |
511 DWORD value) { | |
512 ASSERT1(full_key_name); | |
513 | |
514 return SetValueStaticHelper(full_key_name, value_name, REG_DWORD, &value); | |
515 } | |
516 | |
517 inline HRESULT RegKey::SetValue(const TCHAR* full_key_name, | |
518 const TCHAR* value_name, | |
519 DWORD64 value) { | |
520 ASSERT1(full_key_name); | |
521 | |
522 return SetValueStaticHelper(full_key_name, value_name, REG_QWORD, &value); | |
523 } | |
524 | |
525 inline HRESULT RegKey::SetValue(const TCHAR* full_key_name, | |
526 const TCHAR* value_name, | |
527 float value) { | |
528 ASSERT1(full_key_name); | |
529 | |
530 return SetValueStaticHelper(full_key_name, | |
531 value_name, | |
532 REG_BINARY, | |
533 &value, | |
534 sizeof(value)); | |
535 } | |
536 | |
537 inline HRESULT RegKey::SetValue(const TCHAR* full_key_name, | |
538 const TCHAR* value_name, | |
539 double value) { | |
540 ASSERT1(full_key_name); | |
541 | |
542 return SetValueStaticHelper(full_key_name, | |
543 value_name, | |
544 REG_BINARY, | |
545 &value, | |
546 sizeof(value)); | |
547 } | |
548 | |
549 inline HRESULT RegKey::SetValue(const TCHAR* full_key_name, | |
550 const TCHAR* value_name, | |
551 const TCHAR* value) { | |
552 ASSERT1(full_key_name); | |
553 ASSERT1(value); | |
554 | |
555 return SetValueStaticHelper(full_key_name, | |
556 value_name, | |
557 REG_SZ, | |
558 const_cast<TCHAR*>(value)); | |
559 } | |
560 | |
561 inline HRESULT RegKey::SetValue(const TCHAR* full_key_name, | |
562 const TCHAR* value_name, | |
563 const byte* value, | |
564 DWORD byte_count) { | |
565 ASSERT1(full_key_name); | |
566 | |
567 return SetValueStaticHelper(full_key_name, value_name, REG_BINARY, | |
568 const_cast<byte*>(value), byte_count); | |
569 } | |
570 | |
571 inline HRESULT RegKey::SetValueMultiSZ(const TCHAR* full_key_name, | |
572 const TCHAR* value_name, | |
573 const byte* value, | |
574 DWORD byte_count) { | |
575 ASSERT1(full_key_name); | |
576 | |
577 return SetValueStaticHelper(full_key_name, value_name, REG_MULTI_SZ, | |
578 const_cast<byte*>(value), byte_count); | |
579 } | |
580 | |
581 inline HRESULT RegKey::SetValueExpandSZ(const TCHAR* full_key_name, | |
582 const TCHAR* value_name, | |
583 const TCHAR* value) { | |
584 ASSERT1(full_key_name); | |
585 ASSERT1(value); | |
586 | |
587 return SetValueStaticHelper(full_key_name, | |
588 value_name, | |
589 REG_EXPAND_SZ, | |
590 const_cast<TCHAR*>(value)); | |
591 } | |
592 | |
593 // GETTERS static versions | |
594 inline HRESULT RegKey::GetValue(const TCHAR* full_key_name, | |
595 const TCHAR* value_name, | |
596 DWORD* value) { | |
597 ASSERT1(full_key_name); | |
598 ASSERT1(value); | |
599 | |
600 return GetValueStaticHelper(full_key_name, value_name, REG_DWORD, value); | |
601 } | |
602 | |
603 inline HRESULT RegKey::GetValue(const TCHAR* full_key_name, | |
604 const TCHAR* value_name, | |
605 DWORD64* value) { | |
606 ASSERT1(full_key_name); | |
607 ASSERT1(value); | |
608 | |
609 return GetValueStaticHelper(full_key_name, value_name, REG_QWORD, value); | |
610 } | |
611 | |
612 inline HRESULT RegKey::GetValue(const TCHAR* full_key_name, | |
613 const TCHAR* value_name, | |
614 float* value) { | |
615 ASSERT1(value); | |
616 ASSERT1(value_name); | |
617 ASSERT1(full_key_name); | |
618 | |
619 DWORD byte_count = 0; | |
620 byte* buffer = NULL; | |
621 HRESULT hr = GetValueStaticHelper(full_key_name, | |
622 value_name, | |
623 REG_BINARY, | |
624 &buffer, | |
625 &byte_count); | |
626 scoped_array<byte> free_buffer(buffer); | |
627 | |
628 if (SUCCEEDED(hr)) { | |
629 if (byte_count == sizeof(*value)) { | |
630 ::CopyMemory(value, buffer, sizeof(*value)); | |
631 } else { | |
632 UTIL_LOG(LEVEL_ERROR, (_T("[RegKey::GetValue]") | |
633 _T("[size mismatches for float value][%s\\%s]"), | |
634 full_key_name, value_name)); | |
635 return HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH); | |
636 } | |
637 } | |
638 | |
639 return hr; | |
640 } | |
641 | |
642 inline HRESULT RegKey::GetValue(const TCHAR* full_key_name, | |
643 const TCHAR* value_name, | |
644 double* value) { | |
645 ASSERT1(value); | |
646 ASSERT1(value_name); | |
647 ASSERT1(full_key_name); | |
648 | |
649 DWORD byte_count = 0; | |
650 byte* buffer = NULL; | |
651 HRESULT hr = GetValueStaticHelper(full_key_name, | |
652 value_name, | |
653 REG_BINARY, | |
654 &buffer, | |
655 &byte_count); | |
656 scoped_array<byte> free_buffer(buffer); | |
657 | |
658 if (SUCCEEDED(hr)) { | |
659 if (byte_count == sizeof(*value)) { | |
660 ::CopyMemory(value, buffer, sizeof(*value)); | |
661 } else { | |
662 UTIL_LOG(LEVEL_ERROR, (_T("[RegKey::GetValue]") | |
663 _T("[size mismatches for double value][%s\\%s]"), | |
664 full_key_name, value_name)); | |
665 return HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH); | |
666 } | |
667 } | |
668 | |
669 return hr; | |
670 } | |
671 | |
672 inline HRESULT RegKey::GetValue(const TCHAR* full_key_name, | |
673 const TCHAR* value_name, | |
674 TCHAR** value) { | |
675 ASSERT1(full_key_name); | |
676 ASSERT1(value); | |
677 | |
678 return GetValueStaticHelper(full_key_name, value_name, REG_SZ, value); | |
679 } | |
680 | |
681 inline HRESULT RegKey::GetValue(const TCHAR* full_key_name, | |
682 const TCHAR* value_name, | |
683 CString* value) { | |
684 ASSERT1(full_key_name); | |
685 ASSERT1(value); | |
686 | |
687 TCHAR* buffer = NULL; | |
688 HRESULT hr = RegKey::GetValue(full_key_name, value_name, &buffer); | |
689 value->SetString(buffer); | |
690 delete [] buffer; | |
691 return hr; | |
692 } | |
693 | |
694 inline HRESULT RegKey::GetValue(const TCHAR* full_key_name, | |
695 const TCHAR* value_name, | |
696 std::vector<CString>* value) { | |
697 ASSERT1(full_key_name); | |
698 ASSERT1(value); | |
699 | |
700 return GetValueStaticHelper(full_key_name, value_name, REG_MULTI_SZ, value); | |
701 } | |
702 | |
703 inline HRESULT RegKey::GetValue(const TCHAR* full_key_name, | |
704 const TCHAR* value_name, | |
705 byte** value, | |
706 DWORD* byte_count) { | |
707 ASSERT1(full_key_name); | |
708 ASSERT1(value); | |
709 ASSERT1(byte_count); | |
710 | |
711 return GetValueStaticHelper(full_key_name, | |
712 value_name, | |
713 REG_BINARY, | |
714 value, | |
715 byte_count); | |
716 } | |
717 | |
718 template<typename T> | |
719 HRESULT RegKey::GetValue(const TCHAR* full_key_names[], | |
720 int key_names_length, | |
721 const TCHAR* value_name, | |
722 T* value) { | |
723 HRESULT hr = S_OK; | |
724 for (int i = 0; i < key_names_length; ++i) { | |
725 hr = GetValue(full_key_names[i], value_name, value); | |
726 if (SUCCEEDED(hr)) { | |
727 return hr; | |
728 } | |
729 } | |
730 return hr; | |
731 } | |
732 | |
733 // Rename a named value. | |
734 inline HRESULT RegKey::RenameValue(const TCHAR * full_key_name, | |
735 const TCHAR * old_value_name, | |
736 const TCHAR * new_value_name) { | |
737 ASSERT1(full_key_name); | |
738 | |
739 RegKey reg_key; | |
740 HRESULT hr = reg_key.Open(full_key_name); | |
741 if (FAILED(hr)) { | |
742 return hr; | |
743 } | |
744 | |
745 return reg_key.RenameValue(old_value_name, new_value_name); | |
746 } | |
747 | |
748 inline HRESULT RegKey::CopyValue(const TCHAR * full_from_key_name, | |
749 const TCHAR * full_to_key_name, | |
750 const TCHAR * value_name) { | |
751 return CopyValue(full_from_key_name, | |
752 value_name, | |
753 full_to_key_name, | |
754 value_name); | |
755 } | |
756 | |
757 // DELETE | |
758 inline HRESULT RegKey::DeleteSubKey(const TCHAR* key_name) { | |
759 ASSERT1(key_name); | |
760 ASSERT1(h_key_); | |
761 | |
762 LONG res = ::RegDeleteKey(h_key_, key_name); | |
763 HRESULT hr = HRESULT_FROM_WIN32(res); | |
764 if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) || | |
765 hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) { | |
766 hr = S_FALSE; | |
767 } | |
768 return hr; | |
769 } | |
770 | |
771 inline HRESULT RegKey::DeleteValue(const TCHAR* value_name) const { | |
772 ASSERT1(value_name); | |
773 ASSERT1(h_key_); | |
774 | |
775 LONG res = ::RegDeleteValue(h_key_, value_name); | |
776 HRESULT hr = HRESULT_FROM_WIN32(res); | |
777 if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) || | |
778 hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) { | |
779 hr = S_FALSE; | |
780 } | |
781 return hr; | |
782 } | |
783 | |
784 } // namespace omaha | |
785 | |
786 #endif // OMAHA_BASE_REG_KEY_H_ | |
787 | |
OLD | NEW |