| 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 |