1/*
2 * libjingle
3 * Copyright 2003-2008, 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// Unittest for registry access API
29
30#include "talk/base/gunit.h"
31#include "talk/base/common.h"
32#include "talk/base/win32regkey.h"
33
34namespace talk_base {
35
36#ifndef EXPECT_SUCCEEDED
37#define EXPECT_SUCCEEDED(x)  EXPECT_TRUE(SUCCEEDED(x))
38#endif
39
40#ifndef EXPECT_FAILED
41#define EXPECT_FAILED(x)  EXPECT_TRUE(FAILED(x))
42#endif
43
44#define kBaseKey           L"Software\\Google\\__TEST"
45#define kSubkeyName        L"subkey_test"
46
47const wchar_t kRkey1[] = kBaseKey;
48const wchar_t kRkey1SubkeyName[] = kSubkeyName;
49const wchar_t kRkey1Subkey[] = kBaseKey L"\\" kSubkeyName;
50const wchar_t kFullRkey1[] = L"HKCU\\" kBaseKey;
51const wchar_t kFullRkey1Subkey[] = L"HKCU\\" kBaseKey L"\\" kSubkeyName;
52
53const wchar_t kValNameInt[] = L"Int32 Value";
54const DWORD kIntVal = 20;
55const DWORD kIntVal2 = 30;
56
57const wchar_t kValNameInt64[] = L"Int64 Value";
58const DWORD64 kIntVal64 = 119600064000000000uI64;
59
60const wchar_t kValNameFloat[] = L"Float Value";
61const float kFloatVal = 12.3456789f;
62
63const wchar_t kValNameDouble[] = L"Double Value";
64const double kDoubleVal = 98.7654321;
65
66const wchar_t kValNameStr[] = L"Str Value";
67const wchar_t kStrVal[] = L"Some string data 1";
68const wchar_t kStrVal2[] = L"Some string data 2";
69
70const wchar_t kValNameBinary[] = L"Binary Value";
71const char kBinaryVal[] = "Some binary data abcdefghi 1";
72const char kBinaryVal2[] = "Some binary data abcdefghi 2";
73
74const wchar_t kValNameMultiStr[] = L"MultiStr Value";
75const wchar_t kMultiSZ[] = L"abc\0def\0P12345\0";
76const wchar_t kEmptyMultiSZ[] = L"";
77const wchar_t kInvalidMultiSZ[] = {L'6', L'7', L'8'};
78
79// friend function of RegKey
80void RegKeyHelperFunctionsTest() {
81  // Try out some dud values
82  std::wstring temp_key = L"";
83  EXPECT_TRUE(RegKey::GetRootKeyInfo(&temp_key) == NULL);
84  EXPECT_STREQ(temp_key.c_str(), L"");
85
86  temp_key = L"a";
87  EXPECT_TRUE(RegKey::GetRootKeyInfo(&temp_key) == NULL);
88  EXPECT_STREQ(temp_key.c_str(), L"");
89
90  // The basics
91  temp_key = L"HKLM\\a";
92  EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_LOCAL_MACHINE);
93  EXPECT_STREQ(temp_key.c_str(), L"a");
94
95  temp_key = L"HKEY_LOCAL_MACHINE\\a";
96  EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_LOCAL_MACHINE);
97  EXPECT_STREQ(temp_key.c_str(), L"a");
98
99  temp_key = L"HKCU\\a";
100  EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CURRENT_USER);
101  EXPECT_STREQ(temp_key.c_str(), L"a");
102
103  temp_key = L"HKEY_CURRENT_USER\\a";
104  EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CURRENT_USER);
105  EXPECT_STREQ(temp_key.c_str(), L"a");
106
107  temp_key = L"HKU\\a";
108  EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_USERS);
109  EXPECT_STREQ(temp_key.c_str(), L"a");
110
111  temp_key = L"HKEY_USERS\\a";
112  EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_USERS);
113  EXPECT_STREQ(temp_key.c_str(), L"a");
114
115  temp_key = L"HKCR\\a";
116  EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CLASSES_ROOT);
117  EXPECT_STREQ(temp_key.c_str(), L"a");
118
119  temp_key = L"HKEY_CLASSES_ROOT\\a";
120  EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CLASSES_ROOT);
121  EXPECT_STREQ(temp_key.c_str(), L"a");
122
123  // Make sure it is case insensitive
124  temp_key = L"hkcr\\a";
125  EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CLASSES_ROOT);
126  EXPECT_STREQ(temp_key.c_str(), L"a");
127
128  temp_key = L"hkey_CLASSES_ROOT\\a";
129  EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CLASSES_ROOT);
130  EXPECT_STREQ(temp_key.c_str(), L"a");
131
132  //
133  // Test RegKey::GetParentKeyInfo
134  //
135
136  // dud cases
137  temp_key = L"";
138  EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), L"");
139  EXPECT_STREQ(temp_key.c_str(), L"");
140
141  temp_key = L"a";
142  EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), L"");
143  EXPECT_STREQ(temp_key.c_str(), L"a");
144
145  temp_key = L"a\\b";
146  EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), L"a");
147  EXPECT_STREQ(temp_key.c_str(), L"b");
148
149  temp_key = L"\\b";
150  EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), L"");
151  EXPECT_STREQ(temp_key.c_str(), L"b");
152
153  // Some regular cases
154  temp_key = L"HKEY_CLASSES_ROOT\\moon";
155  EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(),
156               L"HKEY_CLASSES_ROOT");
157  EXPECT_STREQ(temp_key.c_str(), L"moon");
158
159  temp_key = L"HKEY_CLASSES_ROOT\\moon\\doggy";
160  EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(),
161               L"HKEY_CLASSES_ROOT\\moon");
162  EXPECT_STREQ(temp_key.c_str(), L"doggy");
163
164  //
165  // Test MultiSZBytesToStringArray
166  //
167
168  std::vector<std::wstring> result;
169  EXPECT_SUCCEEDED(RegKey::MultiSZBytesToStringArray(
170      reinterpret_cast<const uint8*>(kMultiSZ), sizeof(kMultiSZ), &result));
171  EXPECT_EQ(result.size(), 3);
172  EXPECT_STREQ(result[0].c_str(), L"abc");
173  EXPECT_STREQ(result[1].c_str(), L"def");
174  EXPECT_STREQ(result[2].c_str(), L"P12345");
175
176  EXPECT_SUCCEEDED(RegKey::MultiSZBytesToStringArray(
177      reinterpret_cast<const uint8*>(kEmptyMultiSZ),
178      sizeof(kEmptyMultiSZ), &result));
179  EXPECT_EQ(result.size(), 0);
180  EXPECT_FALSE(SUCCEEDED(RegKey::MultiSZBytesToStringArray(
181      reinterpret_cast<const uint8*>(kInvalidMultiSZ),
182      sizeof(kInvalidMultiSZ), &result)));
183}
184
185TEST(RegKeyTest, RegKeyHelperFunctionsTest) {
186  RegKeyHelperFunctionsTest();
187}
188
189TEST(RegKeyTest, RegKeyNonStaticFunctionsTest) {
190  DWORD int_val = 0;
191  DWORD64 int64_val = 0;
192  wchar_t* str_val = NULL;
193  uint8* binary_val = NULL;
194  DWORD uint8_count = 0;
195
196  // Just in case...
197  // make sure the no test key residue is left from previous aborted runs
198  RegKey::DeleteKey(kFullRkey1);
199
200  // initial state
201  RegKey r_key;
202  EXPECT_TRUE(r_key.key() == NULL);
203
204  // create a reg key
205  EXPECT_SUCCEEDED(r_key.Create(HKEY_CURRENT_USER, kRkey1));
206
207  // do the create twice - it should return the already created one
208  EXPECT_SUCCEEDED(r_key.Create(HKEY_CURRENT_USER, kRkey1));
209
210  // now do an open - should work just fine
211  EXPECT_SUCCEEDED(r_key.Open(HKEY_CURRENT_USER, kRkey1));
212
213  // get an in-existent value
214  EXPECT_EQ(r_key.GetValue(kValNameInt, &int_val),
215            HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
216
217  // set and get some values
218
219  // set an INT 32
220  EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt, kIntVal));
221
222  // check that the value exists
223  EXPECT_TRUE(r_key.HasValue(kValNameInt));
224
225  // read it back
226  EXPECT_SUCCEEDED(r_key.GetValue(kValNameInt, &int_val));
227  EXPECT_EQ(int_val, kIntVal);
228
229  // set it again!
230  EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt, kIntVal2));
231
232  // read it again
233  EXPECT_SUCCEEDED(r_key.GetValue(kValNameInt, &int_val));
234  EXPECT_EQ(int_val, kIntVal2);
235
236  // delete the value
237  EXPECT_SUCCEEDED(r_key.DeleteValue(kValNameInt));
238
239  // check that the value is gone
240  EXPECT_FALSE(r_key.HasValue(kValNameInt));
241
242  // set an INT 64
243  EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt64, kIntVal64));
244
245  // check that the value exists
246  EXPECT_TRUE(r_key.HasValue(kValNameInt64));
247
248  // read it back
249  EXPECT_SUCCEEDED(r_key.GetValue(kValNameInt64, &int64_val));
250  EXPECT_EQ(int64_val, kIntVal64);
251
252  // delete the value
253  EXPECT_SUCCEEDED(r_key.DeleteValue(kValNameInt64));
254
255  // check that the value is gone
256  EXPECT_FALSE(r_key.HasValue(kValNameInt64));
257
258  // set a string
259  EXPECT_SUCCEEDED(r_key.SetValue(kValNameStr, kStrVal));
260
261  // check that the value exists
262  EXPECT_TRUE(r_key.HasValue(kValNameStr));
263
264  // read it back
265  EXPECT_SUCCEEDED(r_key.GetValue(kValNameStr, &str_val));
266  EXPECT_TRUE(lstrcmp(str_val, kStrVal) == 0);
267  delete[] str_val;
268
269  // set it again
270  EXPECT_SUCCEEDED(r_key.SetValue(kValNameStr, kStrVal2));
271
272  // read it again
273  EXPECT_SUCCEEDED(r_key.GetValue(kValNameStr, &str_val));
274  EXPECT_TRUE(lstrcmp(str_val, kStrVal2) == 0);
275  delete[] str_val;
276
277  // delete the value
278  EXPECT_SUCCEEDED(r_key.DeleteValue(kValNameStr));
279
280  // check that the value is gone
281  EXPECT_FALSE(r_key.HasValue(kValNameInt));
282
283  // set a binary value
284  EXPECT_SUCCEEDED(r_key.SetValue(kValNameBinary,
285      reinterpret_cast<const uint8*>(kBinaryVal), sizeof(kBinaryVal) - 1));
286
287  // check that the value exists
288  EXPECT_TRUE(r_key.HasValue(kValNameBinary));
289
290  // read it back
291  EXPECT_SUCCEEDED(r_key.GetValue(kValNameBinary, &binary_val, &uint8_count));
292  EXPECT_TRUE(memcmp(binary_val, kBinaryVal, sizeof(kBinaryVal) - 1) == 0);
293  delete[] binary_val;
294
295  // set it again
296  EXPECT_SUCCEEDED(r_key.SetValue(kValNameBinary,
297      reinterpret_cast<const uint8*>(kBinaryVal2), sizeof(kBinaryVal) - 1));
298
299  // read it again
300  EXPECT_SUCCEEDED(r_key.GetValue(kValNameBinary, &binary_val, &uint8_count));
301  EXPECT_TRUE(memcmp(binary_val, kBinaryVal2, sizeof(kBinaryVal2) - 1) == 0);
302  delete[] binary_val;
303
304  // delete the value
305  EXPECT_SUCCEEDED(r_key.DeleteValue(kValNameBinary));
306
307  // check that the value is gone
308  EXPECT_FALSE(r_key.HasValue(kValNameBinary));
309
310  // set some values and check the total count
311
312  // set an INT 32
313  EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt, kIntVal));
314
315  // set an INT 64
316  EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt64, kIntVal64));
317
318  // set a string
319  EXPECT_SUCCEEDED(r_key.SetValue(kValNameStr, kStrVal));
320
321  // set a binary value
322  EXPECT_SUCCEEDED(r_key.SetValue(kValNameBinary,
323      reinterpret_cast<const uint8*>(kBinaryVal), sizeof(kBinaryVal) - 1));
324
325  // get the value count
326  uint32 value_count = r_key.GetValueCount();
327  EXPECT_EQ(value_count, 4);
328
329  // check the value names
330  std::wstring value_name;
331  DWORD type = 0;
332
333  EXPECT_SUCCEEDED(r_key.GetValueNameAt(0, &value_name, &type));
334  EXPECT_STREQ(value_name.c_str(), kValNameInt);
335  EXPECT_EQ(type, REG_DWORD);
336
337  EXPECT_SUCCEEDED(r_key.GetValueNameAt(1, &value_name, &type));
338  EXPECT_STREQ(value_name.c_str(), kValNameInt64);
339  EXPECT_EQ(type, REG_QWORD);
340
341  EXPECT_SUCCEEDED(r_key.GetValueNameAt(2, &value_name, &type));
342  EXPECT_STREQ(value_name.c_str(), kValNameStr);
343  EXPECT_EQ(type, REG_SZ);
344
345  EXPECT_SUCCEEDED(r_key.GetValueNameAt(3, &value_name, &type));
346  EXPECT_STREQ(value_name.c_str(), kValNameBinary);
347  EXPECT_EQ(type, REG_BINARY);
348
349  // check that there are no more values
350  EXPECT_FAILED(r_key.GetValueNameAt(4, &value_name, &type));
351
352  uint32 subkey_count = r_key.GetSubkeyCount();
353  EXPECT_EQ(subkey_count, 0);
354
355  // now create a subkey and make sure we can get the name
356  RegKey temp_key;
357  EXPECT_SUCCEEDED(temp_key.Create(HKEY_CURRENT_USER, kRkey1Subkey));
358
359  // check the subkey exists
360  EXPECT_TRUE(r_key.HasSubkey(kRkey1SubkeyName));
361
362  // check the name
363  EXPECT_EQ(r_key.GetSubkeyCount(), 1);
364
365  std::wstring subkey_name;
366  EXPECT_SUCCEEDED(r_key.GetSubkeyNameAt(0, &subkey_name));
367  EXPECT_STREQ(subkey_name.c_str(), kRkey1SubkeyName);
368
369  // delete the key
370  EXPECT_SUCCEEDED(r_key.DeleteSubKey(kRkey1));
371
372  // close this key
373  EXPECT_SUCCEEDED(r_key.Close());
374
375  // whack the whole key
376  EXPECT_SUCCEEDED(RegKey::DeleteKey(kFullRkey1));
377}
378
379TEST(RegKeyTest, RegKeyStaticFunctionsTest) {
380  DWORD int_val = 0;
381  DWORD64 int64_val = 0;
382  float float_val = 0;
383  double double_val = 0;
384  wchar_t* str_val = NULL;
385  std::wstring wstr_val;
386  uint8* binary_val = NULL;
387  DWORD uint8_count = 0;
388
389  // Just in case...
390  // make sure the no test key residue is left from previous aborted runs
391  RegKey::DeleteKey(kFullRkey1);
392
393  // get an in-existent value from an un-existent key
394  EXPECT_EQ(RegKey::GetValue(kFullRkey1, kValNameInt, &int_val),
395            HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
396
397  // set int32
398  EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameInt, kIntVal));
399
400  // check that the value exists
401  EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameInt));
402
403  // get an in-existent value from an existent key
404  EXPECT_EQ(RegKey::GetValue(kFullRkey1, L"bogus", &int_val),
405            HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
406
407  // read it back
408  EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameInt, &int_val));
409  EXPECT_EQ(int_val, kIntVal);
410
411  // delete the value
412  EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameInt));
413
414  // check that the value is gone
415  EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameInt));
416
417  // set int64
418  EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameInt64, kIntVal64));
419
420  // check that the value exists
421  EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameInt64));
422
423  // read it back
424  EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameInt64, &int64_val));
425  EXPECT_EQ(int64_val, kIntVal64);
426
427  // delete the value
428  EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameInt64));
429
430  // check that the value is gone
431  EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameInt64));
432
433  // set float
434  EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameFloat, kFloatVal));
435
436  // check that the value exists
437  EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameFloat));
438
439  // read it back
440  EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameFloat, &float_val));
441  EXPECT_EQ(float_val, kFloatVal);
442
443  // delete the value
444  EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameFloat));
445
446  // check that the value is gone
447  EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameFloat));
448  EXPECT_FAILED(RegKey::GetValue(kFullRkey1, kValNameFloat, &float_val));
449
450  // set double
451  EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameDouble, kDoubleVal));
452
453  // check that the value exists
454  EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameDouble));
455
456  // read it back
457  EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameDouble, &double_val));
458  EXPECT_EQ(double_val, kDoubleVal);
459
460  // delete the value
461  EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameDouble));
462
463  // check that the value is gone
464  EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameDouble));
465  EXPECT_FAILED(RegKey::GetValue(kFullRkey1, kValNameDouble, &double_val));
466
467  // set string
468  EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameStr, kStrVal));
469
470  // check that the value exists
471  EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameStr));
472
473  // read it back
474  EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameStr, &str_val));
475  EXPECT_TRUE(lstrcmp(str_val, kStrVal) == 0);
476  delete[] str_val;
477
478  // read it back in std::wstring
479  EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameStr, &wstr_val));
480  EXPECT_STREQ(wstr_val.c_str(), kStrVal);
481
482  // get an in-existent value from an existent key
483  EXPECT_EQ(RegKey::GetValue(kFullRkey1, L"bogus", &str_val),
484            HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
485
486  // delete the value
487  EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameStr));
488
489  // check that the value is gone
490  EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameStr));
491
492  // set binary
493  EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameBinary,
494      reinterpret_cast<const uint8*>(kBinaryVal), sizeof(kBinaryVal)-1));
495
496  // check that the value exists
497  EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameBinary));
498
499  // read it back
500  EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameBinary,
501      &binary_val, &uint8_count));
502  EXPECT_TRUE(memcmp(binary_val, kBinaryVal, sizeof(kBinaryVal)-1) == 0);
503  delete[] binary_val;
504
505  // delete the value
506  EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameBinary));
507
508  // check that the value is gone
509  EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameBinary));
510
511  // special case - set a binary value with length 0
512  EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameBinary,
513      reinterpret_cast<const uint8*>(kBinaryVal), 0));
514
515  // check that the value exists
516  EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameBinary));
517
518  // read it back
519  EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameBinary,
520      &binary_val, &uint8_count));
521  EXPECT_EQ(uint8_count, 0);
522  EXPECT_TRUE(binary_val == NULL);
523  delete[] binary_val;
524
525  // delete the value
526  EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameBinary));
527
528  // check that the value is gone
529  EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameBinary));
530
531  // special case - set a NULL binary value
532  EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameBinary, NULL, 100));
533
534  // check that the value exists
535  EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameBinary));
536
537  // read it back
538  EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameBinary,
539                                    &binary_val, &uint8_count));
540  EXPECT_EQ(uint8_count, 0);
541  EXPECT_TRUE(binary_val == NULL);
542  delete[] binary_val;
543
544  // delete the value
545  EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameBinary));
546
547  // check that the value is gone
548  EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameBinary));
549
550  // test read/write REG_MULTI_SZ value
551  std::vector<std::wstring> result;
552  EXPECT_SUCCEEDED(RegKey::SetValueMultiSZ(kFullRkey1, kValNameMultiStr,
553      reinterpret_cast<const uint8*>(kMultiSZ), sizeof(kMultiSZ)));
554  EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameMultiStr, &result));
555  EXPECT_EQ(result.size(), 3);
556  EXPECT_STREQ(result[0].c_str(), L"abc");
557  EXPECT_STREQ(result[1].c_str(), L"def");
558  EXPECT_STREQ(result[2].c_str(), L"P12345");
559  EXPECT_SUCCEEDED(RegKey::SetValueMultiSZ(kFullRkey1, kValNameMultiStr,
560      reinterpret_cast<const uint8*>(kEmptyMultiSZ), sizeof(kEmptyMultiSZ)));
561  EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameMultiStr, &result));
562  EXPECT_EQ(result.size(), 0);
563  // writing REG_MULTI_SZ value will automatically add ending null characters
564  EXPECT_SUCCEEDED(RegKey::SetValueMultiSZ(kFullRkey1, kValNameMultiStr,
565      reinterpret_cast<const uint8*>(kInvalidMultiSZ), sizeof(kInvalidMultiSZ)));
566  EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameMultiStr, &result));
567  EXPECT_EQ(result.size(), 1);
568  EXPECT_STREQ(result[0].c_str(), L"678");
569
570  // Run the following test only in dev machine
571  // This is because the build machine might not have admin privilege
572#ifdef IS_PRIVATE_BUILD
573  // get a temp file name
574  wchar_t temp_path[MAX_PATH] = {0};
575  EXPECT_LT(::GetTempPath(ARRAY_SIZE(temp_path), temp_path),
576            static_cast<DWORD>(ARRAY_SIZE(temp_path)));
577  wchar_t temp_file[MAX_PATH] = {0};
578  EXPECT_NE(::GetTempFileName(temp_path, L"rkut_",
579                              ::GetTickCount(), temp_file), 0);
580
581  // test save
582  EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1Subkey, kValNameInt, kIntVal));
583  EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1Subkey, kValNameInt64, kIntVal64));
584  EXPECT_SUCCEEDED(RegKey::Save(kFullRkey1Subkey, temp_file));
585  EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1Subkey, kValNameInt));
586  EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1Subkey, kValNameInt64));
587
588  // test restore
589  EXPECT_SUCCEEDED(RegKey::Restore(kFullRkey1Subkey, temp_file));
590  int_val = 0;
591  EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1Subkey, kValNameInt, &int_val));
592  EXPECT_EQ(int_val, kIntVal);
593  int64_val = 0;
594  EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1Subkey,
595                                    kValNameInt64,
596                                    &int64_val));
597  EXPECT_EQ(int64_val, kIntVal64);
598
599  // delete the temp file
600  EXPECT_EQ(TRUE, ::DeleteFile(temp_file));
601#endif
602
603  // whack the whole key
604  EXPECT_SUCCEEDED(RegKey::DeleteKey(kFullRkey1));
605}
606
607}  // namespace talk_base
608