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