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