1/*
2 * libjingle
3 * Copyright 2003-2007, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 *  1. Redistributions of source code must retain the above copyright notice,
9 *     this list of conditions and the following disclaimer.
10 *  2. Redistributions in binary form must reproduce the above copyright notice,
11 *     this list of conditions and the following disclaimer in the documentation
12 *     and/or other materials provided with the distribution.
13 *  3. The name of the author may not be used to endorse or promote products
14 *     derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28// Registry configuration wrappers class
29//
30// Offers static functions for convenient
31// fast access for individual values
32//
33// Also provides a wrapper class for efficient
34// batch operations on values of a given registry key.
35//
36
37#ifndef TALK_BASE_WIN32REGKEY_H_
38#define TALK_BASE_WIN32REGKEY_H_
39
40#include <string>
41#include <vector>
42
43#include "talk/base/basictypes.h"
44#include "talk/base/win32.h"
45
46namespace talk_base {
47
48// maximum sizes registry key and value names
49const int kMaxKeyNameChars = 255 + 1;
50const int kMaxValueNameChars = 16383 + 1;
51
52class RegKey {
53 public:
54  // constructor
55  RegKey();
56
57  // destructor
58  ~RegKey();
59
60  // create a reg key
61  HRESULT Create(HKEY parent_key, const wchar_t* key_name);
62
63  HRESULT Create(HKEY parent_key,
64                 const wchar_t* key_name,
65                 wchar_t* reg_class,
66                 DWORD options,
67                 REGSAM sam_desired,
68                 LPSECURITY_ATTRIBUTES lp_sec_attr,
69                 LPDWORD lp_disposition);
70
71  // open an existing reg key
72  HRESULT Open(HKEY parent_key, const wchar_t* key_name);
73
74  HRESULT Open(HKEY parent_key, const wchar_t* key_name, REGSAM sam_desired);
75
76  // close this reg key
77  HRESULT Close();
78
79  // check if the key has a specified value
80  bool HasValue(const wchar_t* value_name) const;
81
82  // get the number of values for this key
83  uint32 GetValueCount();
84
85  // Called to get the value name for the given value name index
86  // Use GetValueCount() to get the total value_name count for this key
87  // Returns failure if no key at the specified index
88  // If you modify the key while enumerating, the indexes will be out of order.
89  // Since the index order is not guaranteed, you need to reset your counting
90  // loop.
91  // 'type' refers to REG_DWORD, REG_QWORD, etc..
92  // 'type' can be NULL if not interested in the value type
93  HRESULT GetValueNameAt(int index, std::wstring* value_name, DWORD* type);
94
95  // check if the current key has the specified subkey
96  bool HasSubkey(const wchar_t* key_name) const;
97
98  // get the number of subkeys for this key
99  uint32 GetSubkeyCount();
100
101  // Called to get the key name for the given key index
102  // Use GetSubkeyCount() to get the total count for this key
103  // Returns failure if no key at the specified index
104  // If you modify the key while enumerating, the indexes will be out of order.
105  // Since the index order is not guaranteed, you need to reset your counting
106  // loop.
107  HRESULT GetSubkeyNameAt(int index, std::wstring* key_name);
108
109  // SETTERS
110
111  // set an int32 value - use when reading multiple values from a key
112  HRESULT SetValue(const wchar_t* value_name, DWORD value) const;
113
114  // set an int64 value
115  HRESULT SetValue(const wchar_t* value_name, DWORD64 value) const;
116
117  // set a string value
118  HRESULT SetValue(const wchar_t* value_name, const wchar_t* value) const;
119
120  // set binary data
121  HRESULT SetValue(const wchar_t* value_name,
122                   const uint8* value,
123                   DWORD byte_count) const;
124
125  // set raw data, including type
126  HRESULT SetValue(const wchar_t* value_name,
127                   const uint8* value,
128                   DWORD byte_count,
129                   DWORD type) const;
130
131  // GETTERS
132
133  // get an int32 value
134  HRESULT GetValue(const wchar_t* value_name, DWORD* value) const;
135
136  // get an int64 value
137  HRESULT GetValue(const wchar_t* value_name, DWORD64* value) const;
138
139  // get a string value - the caller must free the return buffer
140  HRESULT GetValue(const wchar_t* value_name, wchar_t** value) const;
141
142  // get a string value
143  HRESULT GetValue(const wchar_t* value_name, std::wstring* value) const;
144
145  // get a std::vector<std::wstring> value from REG_MULTI_SZ type
146  HRESULT GetValue(const wchar_t* value_name,
147                   std::vector<std::wstring>* value) const;
148
149  // get binary data - the caller must free the return buffer
150  HRESULT GetValue(const wchar_t* value_name,
151                   uint8** value,
152                   DWORD* byte_count) const;
153
154  // get raw data, including type - the caller must free the return buffer
155  HRESULT GetValue(const wchar_t* value_name,
156                   uint8** value,
157                   DWORD* byte_count,
158                   DWORD* type) const;
159
160  // STATIC VERSIONS
161
162  // flush
163  static HRESULT FlushKey(const wchar_t* full_key_name);
164
165  // check if a key exists
166  static bool HasKey(const wchar_t* full_key_name);
167
168  // check if the key has a specified value
169  static bool HasValue(const wchar_t* full_key_name, const wchar_t* value_name);
170
171  // SETTERS
172
173  // STATIC int32 set
174  static HRESULT SetValue(const wchar_t* full_key_name,
175                          const wchar_t* value_name,
176                          DWORD value);
177
178  // STATIC int64 set
179  static HRESULT SetValue(const wchar_t* full_key_name,
180                          const wchar_t* value_name,
181                          DWORD64 value);
182
183  // STATIC float set
184  static HRESULT SetValue(const wchar_t* full_key_name,
185                          const wchar_t* value_name,
186                          float value);
187
188  // STATIC double set
189  static HRESULT SetValue(const wchar_t* full_key_name,
190                          const wchar_t* value_name,
191                          double value);
192
193  // STATIC string set
194  static HRESULT SetValue(const wchar_t* full_key_name,
195                          const wchar_t* value_name,
196                          const wchar_t* value);
197
198  // STATIC binary data set
199  static HRESULT SetValue(const wchar_t* full_key_name,
200                          const wchar_t* value_name,
201                          const uint8* value,
202                          DWORD byte_count);
203
204  // STATIC multi-string set
205  static HRESULT SetValueMultiSZ(const wchar_t* full_key_name,
206                                 const TCHAR* value_name,
207                                 const uint8* value,
208                                 DWORD byte_count);
209
210  // GETTERS
211
212  // STATIC int32 get
213  static HRESULT GetValue(const wchar_t* full_key_name,
214                          const wchar_t* value_name,
215                          DWORD* value);
216
217  // STATIC int64 get
218  //
219  // Note: if you are using time64 you should
220  // likely use GetLimitedTimeValue (util.h) instead of this method.
221  static HRESULT GetValue(const wchar_t* full_key_name,
222                          const wchar_t* value_name,
223                          DWORD64* value);
224
225  // STATIC float get
226  static HRESULT GetValue(const wchar_t* full_key_name,
227                          const wchar_t* value_name,
228                          float* value);
229
230  // STATIC double get
231  static HRESULT GetValue(const wchar_t* full_key_name,
232                          const wchar_t* value_name,
233                          double* value);
234
235  // STATIC string get
236  // Note: the caller must free the return buffer for wchar_t* version
237  static HRESULT GetValue(const wchar_t* full_key_name,
238                          const wchar_t* value_name,
239                          wchar_t** value);
240  static HRESULT GetValue(const wchar_t* full_key_name,
241                          const wchar_t* value_name,
242                          std::wstring* value);
243
244  // STATIC REG_MULTI_SZ get
245  static HRESULT GetValue(const wchar_t* full_key_name,
246                          const wchar_t* value_name,
247                          std::vector<std::wstring>* value);
248
249  // STATIC get binary data - the caller must free the return buffer
250  static HRESULT GetValue(const wchar_t* full_key_name,
251                          const wchar_t* value_name,
252                          uint8** value,
253                          DWORD* byte_count);
254
255  // Get type of a registry value
256  static HRESULT GetValueType(const wchar_t* full_key_name,
257                              const wchar_t* value_name,
258                              DWORD* value_type);
259
260  // delete a subkey of the current key (with no subkeys)
261  HRESULT DeleteSubKey(const wchar_t* key_name);
262
263  // recursively delete a sub key of the current key (and all its subkeys)
264  HRESULT RecurseDeleteSubKey(const wchar_t* key_name);
265
266  // STATIC version of delete key - handles nested keys also
267  // delete a key and all its sub-keys recursively
268  // Returns S_FALSE if key didn't exist, S_OK if deletion was successful,
269  // and failure otherwise.
270  static HRESULT DeleteKey(const wchar_t* full_key_name);
271
272  // STATIC version of delete key
273  // delete a key recursively or non-recursively
274  // Returns S_FALSE if key didn't exist, S_OK if deletion was successful,
275  // and failure otherwise.
276  static HRESULT DeleteKey(const wchar_t* full_key_name, bool recursive);
277
278  // delete the specified value
279  HRESULT DeleteValue(const wchar_t* value_name);
280
281  // STATIC version of delete value
282  // Returns S_FALSE if key didn't exist, S_OK if deletion was successful,
283  // and failure otherwise.
284  static HRESULT DeleteValue(const wchar_t* full_key_name,
285                             const wchar_t* value_name);
286
287  // Peek inside (use a RegKey as a smart wrapper around a registry handle)
288  HKEY key() { return h_key_; }
289
290  // helper function to get the HKEY and the root key from a string
291  // modifies the argument in place and returns the key name
292  // e.g. HKLM\\Software\\Google\... returns HKLM, "Software\\Google\..."
293  // Necessary for the static versions that use the full name of the reg key
294  static HKEY GetRootKeyInfo(std::wstring* full_key_name);
295
296  // Returns true if this key name is 'safe' for deletion (doesn't specify a key
297  // root)
298  static bool SafeKeyNameForDeletion(const wchar_t* key_name);
299
300  // save the key and all of its subkeys and values to a file
301  static HRESULT Save(const wchar_t* full_key_name, const wchar_t* file_name);
302
303  // restore the key and all of its subkeys and values which are saved into a
304  // file
305  static HRESULT Restore(const wchar_t* full_key_name,
306                         const wchar_t* file_name);
307
308  // Is the key empty: having no sub-keys and values
309  static bool IsKeyEmpty(const wchar_t* full_key_name);
310
311 private:
312
313  // helper function to get any value from the registry
314  // used when the size of the data is unknown
315  HRESULT GetValueHelper(const wchar_t* value_name,
316                         DWORD* type, uint8** value,
317                         DWORD* byte_count) const;
318
319  // helper function to get the parent key name and the subkey from a string
320  // modifies the argument in place and returns the key name
321  // Necessary for the static versions that use the full name of the reg key
322  static std::wstring GetParentKeyInfo(std::wstring* key_name);
323
324  // common SET Helper for the static case
325  static HRESULT SetValueStaticHelper(const wchar_t* full_key_name,
326                                      const wchar_t* value_name,
327                                      DWORD type,
328                                      LPVOID value,
329                                      DWORD byte_count = 0);
330
331  // common GET Helper for the static case
332  static HRESULT GetValueStaticHelper(const wchar_t* full_key_name,
333                                      const wchar_t* value_name,
334                                      DWORD type,
335                                      LPVOID value,
336                                      DWORD* byte_count = NULL);
337
338  // convert REG_MULTI_SZ bytes to string array
339  static HRESULT MultiSZBytesToStringArray(const uint8* buffer,
340                                           DWORD byte_count,
341                                           std::vector<std::wstring>* value);
342
343  // the HKEY for the current key
344  HKEY h_key_;
345
346  // for unittest
347  friend void RegKeyHelperFunctionsTest();
348
349  DISALLOW_EVIL_CONSTRUCTORS(RegKey);
350};
351
352}  // namespace talk_base
353
354#endif  // TALK_BASE_WIN32REGKEY_H_
355