1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_WIN_REGISTRY_H_ 6 #define BASE_WIN_REGISTRY_H_ 7 8 #include <stdint.h> 9 10 #include <memory> 11 #include <string> 12 #include <vector> 13 14 #include "base/base_export.h" 15 #include "base/functional/callback_forward.h" 16 #include "base/gtest_prod_util.h" 17 #include "base/win/windows_types.h" 18 19 class ShellUtil; 20 21 namespace base { 22 namespace win { 23 24 // Utility class to read, write and manipulate the Windows Registry. 25 // Registry vocabulary primer: a "key" is like a folder, in which there 26 // are "values", which are <name, data> pairs, with an associated data type. 27 // 28 // Note: 29 // * ReadValue family of functions guarantee that the out-parameter 30 // is not touched in case of failure. 31 // * Functions returning LONG indicate success as ERROR_SUCCESS or an 32 // error as a (non-zero) win32 error code. 33 // 34 // Most developers should use base::win::RegKey subclass below. 35 namespace internal { 36 37 class Standard; 38 class ExportDerived; 39 template <typename T> 40 class RegTestTraits; 41 42 template <typename Reg> 43 class GenericRegKey { 44 public: 45 // Called from the MessageLoop when the key changes. 46 using ChangeCallback = OnceCallback<void()>; 47 48 GenericRegKey(); 49 explicit GenericRegKey(HKEY key); 50 GenericRegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access); 51 GenericRegKey(GenericRegKey&& other) noexcept; 52 GenericRegKey& operator=(GenericRegKey&& other); 53 54 GenericRegKey(const GenericRegKey&) = delete; 55 GenericRegKey& operator=(const GenericRegKey&) = delete; 56 57 virtual ~GenericRegKey(); 58 59 LONG Create(HKEY rootkey, const wchar_t* subkey, REGSAM access); 60 61 LONG CreateWithDisposition(HKEY rootkey, 62 const wchar_t* subkey, 63 DWORD* disposition, 64 REGSAM access); 65 66 // Creates a subkey or open it if it already exists. 67 LONG CreateKey(const wchar_t* name, REGSAM access); 68 69 // Opens an existing reg key. 70 LONG Open(HKEY rootkey, const wchar_t* subkey, REGSAM access); 71 72 // Opens an existing reg key, given the relative key name. 73 LONG OpenKey(const wchar_t* relative_key_name, REGSAM access); 74 75 // Closes this reg key. 76 void Close(); 77 78 // Replaces the handle of the registry key and takes ownership of the handle. 79 void Set(HKEY key); 80 81 // Transfers ownership away from this object. 82 HKEY Take(); 83 84 // Returns false if this key does not have the specified value, or if an error 85 // occurrs while attempting to access it. 86 bool HasValue(const wchar_t* value_name) const; 87 88 // Returns the number of values for this key, or 0 if the number cannot be 89 // determined. 90 DWORD GetValueCount() const; 91 92 // Returns the last write time or 0 on failure. 93 FILETIME GetLastWriteTime() const; 94 95 // Determines the nth value's name. 96 LONG GetValueNameAt(DWORD index, std::wstring* name) const; 97 98 // True while the key is valid. Valid()99 bool Valid() const { return key_ != nullptr; } 100 101 // Kills a key and everything that lives below it; please be careful when 102 // using it. 103 LONG DeleteKey(const wchar_t* name); 104 105 // Deletes an empty subkey. If the subkey has subkeys or values then this 106 // will fail. 107 LONG DeleteEmptyKey(const wchar_t* name); 108 109 // Deletes a single value within the key. 110 LONG DeleteValue(const wchar_t* name); 111 112 // Getters: 113 114 // Reads a REG_DWORD (uint32_t) into |out_value|. If |name| is null or empty, 115 // reads the key's default value, if any. 116 LONG ReadValueDW(const wchar_t* name, DWORD* out_value) const; 117 118 // Reads a REG_QWORD (int64_t) into |out_value|. If |name| is null or empty, 119 // reads the key's default value, if any. 120 LONG ReadInt64(const wchar_t* name, int64_t* out_value) const; 121 122 // Reads a string into |out_value|. If |name| is null or empty, reads 123 // the key's default value, if any. 124 LONG ReadValue(const wchar_t* name, std::wstring* out_value) const; 125 126 // Reads a REG_MULTI_SZ registry field into a vector of strings. Clears 127 // |values| initially and adds further strings to the list. Returns 128 // ERROR_CANTREAD if type is not REG_MULTI_SZ. 129 LONG ReadValues(const wchar_t* name, std::vector<std::wstring>* values); 130 131 // Reads raw data into |data|. If |name| is null or empty, reads the key's 132 // default value, if any. 133 LONG ReadValue(const wchar_t* name, 134 void* data, 135 DWORD* dsize, 136 DWORD* dtype) const; 137 138 // Setters: 139 140 // Sets an int32_t value. 141 LONG WriteValue(const wchar_t* name, DWORD in_value); 142 143 // Sets a string value. 144 LONG WriteValue(const wchar_t* name, const wchar_t* in_value); 145 146 // Sets raw data, including type. 147 LONG WriteValue(const wchar_t* name, 148 const void* data, 149 DWORD dsize, 150 DWORD dtype); 151 152 // Starts watching the key to see if any of its values have changed. 153 // The key must have been opened with the KEY_NOTIFY access privilege. 154 // Returns true on success. 155 // To stop watching, delete this GenericRegKey object. To continue watching 156 // the object after the callback is invoked, call StartWatching again. 157 bool StartWatching(ChangeCallback callback); 158 Handle()159 HKEY Handle() const { return key_; } 160 161 private: 162 class Watcher; 163 164 // Recursively deletes a key and all of its subkeys. 165 static LONG RegDelRecurse(HKEY root_key, const wchar_t* name, REGSAM access); 166 167 HKEY key_ = nullptr; // The registry key being iterated. 168 REGSAM wow64access_ = 0; 169 std::unique_ptr<Watcher> key_watcher_; 170 }; 171 172 } // namespace internal 173 174 // The Windows registry utility class most developers should use. 175 class BASE_EXPORT RegKey : public internal::GenericRegKey<internal::Standard> { 176 public: 177 RegKey(); 178 explicit RegKey(HKEY key); 179 RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access); 180 RegKey(RegKey&& other) noexcept; 181 RegKey& operator=(RegKey&& other); 182 183 RegKey(const RegKey&) = delete; 184 RegKey& operator=(const RegKey&) = delete; 185 186 ~RegKey() override; 187 }; 188 189 // A Windows registry class that derives its calls directly from advapi32.dll. 190 // Generally, you should use RegKey above. Note that use of this API will pin 191 // advapi32.dll. If you need to use this class, please reach out to the 192 // base/win/OWNERS first. 193 class BASE_EXPORT ExportDerivedRegKey 194 : public internal::GenericRegKey<internal::ExportDerived> { 195 public: 196 ExportDerivedRegKey(ExportDerivedRegKey&& other) noexcept; 197 ExportDerivedRegKey& operator=(ExportDerivedRegKey&& other); 198 199 ExportDerivedRegKey(const ExportDerivedRegKey&) = delete; 200 ExportDerivedRegKey& operator=(const ExportDerivedRegKey&) = delete; 201 202 ~ExportDerivedRegKey() override; 203 204 private: 205 friend class ::ShellUtil; 206 friend class internal::RegTestTraits<ExportDerivedRegKey>; 207 208 ExportDerivedRegKey(); 209 explicit ExportDerivedRegKey(HKEY key); 210 ExportDerivedRegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access); 211 }; 212 213 // Iterates the entries found in a particular folder on the registry. 214 class BASE_EXPORT RegistryValueIterator { 215 public: 216 // Constructs a Registry Value Iterator with default WOW64 access. 217 RegistryValueIterator(HKEY root_key, const wchar_t* folder_key); 218 219 // Constructs a Registry Key Iterator with specific WOW64 access, one of 220 // KEY_WOW64_32KEY or KEY_WOW64_64KEY, or 0. 221 // Note: |wow64access| should be the same access used to open |root_key| 222 // previously, or a predefined key (e.g. HKEY_LOCAL_MACHINE). 223 // See http://msdn.microsoft.com/en-us/library/windows/desktop/aa384129.aspx. 224 RegistryValueIterator(HKEY root_key, 225 const wchar_t* folder_key, 226 REGSAM wow64access); 227 228 RegistryValueIterator(const RegistryValueIterator&) = delete; 229 RegistryValueIterator& operator=(const RegistryValueIterator&) = delete; 230 231 ~RegistryValueIterator(); 232 233 DWORD ValueCount() const; 234 235 // True while the iterator is valid. 236 bool Valid() const; 237 238 // Advances to the next registry entry. 239 void operator++(); 240 Name()241 const wchar_t* Name() const { return name_.c_str(); } Value()242 const wchar_t* Value() const { return value_.data(); } 243 // ValueSize() is in bytes. ValueSize()244 DWORD ValueSize() const { return value_size_; } Type()245 DWORD Type() const { return type_; } 246 Index()247 DWORD Index() const { return index_; } 248 249 private: 250 // Reads in the current values. 251 bool Read(); 252 253 void Initialize(HKEY root_key, const wchar_t* folder_key, REGSAM wow64access); 254 255 // The registry key being iterated. 256 HKEY key_; 257 258 // Current index of the iteration. 259 DWORD index_; 260 261 // Current values. 262 std::wstring name_; 263 std::vector<wchar_t> value_; 264 DWORD value_size_; 265 DWORD type_; 266 }; 267 268 class BASE_EXPORT RegistryKeyIterator { 269 public: 270 // Constructs a Registry Key Iterator with default WOW64 access. 271 RegistryKeyIterator(HKEY root_key, const wchar_t* folder_key); 272 273 // Constructs a Registry Value Iterator with specific WOW64 access, one of 274 // KEY_WOW64_32KEY or KEY_WOW64_64KEY, or 0. 275 // Note: |wow64access| should be the same access used to open |root_key| 276 // previously, or a predefined key (e.g. HKEY_LOCAL_MACHINE). 277 // See http://msdn.microsoft.com/en-us/library/windows/desktop/aa384129.aspx. 278 RegistryKeyIterator(HKEY root_key, 279 const wchar_t* folder_key, 280 REGSAM wow64access); 281 282 RegistryKeyIterator(const RegistryKeyIterator&) = delete; 283 RegistryKeyIterator& operator=(const RegistryKeyIterator&) = delete; 284 285 ~RegistryKeyIterator(); 286 287 DWORD SubkeyCount() const; 288 289 // True while the iterator is valid. 290 bool Valid() const; 291 292 // Advances to the next entry in the folder. 293 void operator++(); 294 Name()295 const wchar_t* Name() const { return name_; } 296 Index()297 DWORD Index() const { return index_; } 298 299 private: 300 // Reads in the current values. 301 bool Read(); 302 303 void Initialize(HKEY root_key, const wchar_t* folder_key, REGSAM wow64access); 304 305 // The registry key being iterated. 306 HKEY key_; 307 308 // Current index of the iteration. 309 DWORD index_; 310 311 wchar_t name_[MAX_PATH]; 312 }; 313 314 } // namespace win 315 } // namespace base 316 317 #endif // BASE_WIN_REGISTRY_H_ 318