Home | History | Annotate | Download | only in base
      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
     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 
    169 TEST(RegKeyTest, RegKeyHelperFunctionsTest) {
    170   RegKeyHelperFunctionsTest();
    171 }
    172 
    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 
    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.
    602 TEST(RegKeyTest, RegKeyFunctionsTest) {
    603   RegKeyNonStaticFunctionsTest();
    604   RegKeyStaticFunctionsTest();
    605 }
    606 
    607 }  // namespace rtc
    608