| /* | 
 |  *  Copyright 2003 The WebRTC Project Authors. All rights reserved. | 
 |  * | 
 |  *  Use of this source code is governed by a BSD-style license | 
 |  *  that can be found in the LICENSE file in the root of the source | 
 |  *  tree. An additional intellectual property rights grant can be found | 
 |  *  in the file PATENTS.  All contributing project authors may | 
 |  *  be found in the AUTHORS file in the root of the source tree. | 
 |  */ | 
 |  | 
 | // Unittest for registry access API | 
 |  | 
 | #include "webrtc/base/gunit.h" | 
 | #include "webrtc/base/common.h" | 
 | #include "webrtc/base/win32regkey.h" | 
 |  | 
 | namespace rtc { | 
 |  | 
 | #ifndef EXPECT_SUCCEEDED | 
 | #define EXPECT_SUCCEEDED(x)  EXPECT_TRUE(SUCCEEDED(x)) | 
 | #endif | 
 |  | 
 | #ifndef EXPECT_FAILED | 
 | #define EXPECT_FAILED(x)  EXPECT_TRUE(FAILED(x)) | 
 | #endif | 
 |  | 
 | #define kBaseKey           L"Software\\Google\\__TEST" | 
 | #define kSubkeyName        L"subkey_test" | 
 |  | 
 | const wchar_t kRkey1[] = kBaseKey; | 
 | const wchar_t kRkey1SubkeyName[] = kSubkeyName; | 
 | const wchar_t kRkey1Subkey[] = kBaseKey L"\\" kSubkeyName; | 
 | const wchar_t kFullRkey1[] = L"HKCU\\" kBaseKey; | 
 | const wchar_t kFullRkey1Subkey[] = L"HKCU\\" kBaseKey L"\\" kSubkeyName; | 
 |  | 
 | const wchar_t kValNameInt[] = L"Int32 Value"; | 
 | const DWORD kIntVal = 20; | 
 | const DWORD kIntVal2 = 30; | 
 |  | 
 | const wchar_t kValNameInt64[] = L"Int64 Value"; | 
 | const DWORD64 kIntVal64 = 119600064000000000uI64; | 
 |  | 
 | const wchar_t kValNameFloat[] = L"Float Value"; | 
 | const float kFloatVal = 12.3456789f; | 
 |  | 
 | const wchar_t kValNameDouble[] = L"Double Value"; | 
 | const double kDoubleVal = 98.7654321; | 
 |  | 
 | const wchar_t kValNameStr[] = L"Str Value"; | 
 | const wchar_t kStrVal[] = L"Some string data 1"; | 
 | const wchar_t kStrVal2[] = L"Some string data 2"; | 
 |  | 
 | const wchar_t kValNameBinary[] = L"Binary Value"; | 
 | const char kBinaryVal[] = "Some binary data abcdefghi 1"; | 
 | const char kBinaryVal2[] = "Some binary data abcdefghi 2"; | 
 |  | 
 | const wchar_t kValNameMultiStr[] = L"MultiStr Value"; | 
 | const wchar_t kMultiSZ[] = L"abc\0def\0P12345\0"; | 
 | const wchar_t kEmptyMultiSZ[] = L""; | 
 | const wchar_t kInvalidMultiSZ[] = {L'6', L'7', L'8'}; | 
 |  | 
 | // friend function of RegKey | 
 | void RegKeyHelperFunctionsTest() { | 
 |   // Try out some dud values | 
 |   std::wstring temp_key = L""; | 
 |   EXPECT_TRUE(RegKey::GetRootKeyInfo(&temp_key) == NULL); | 
 |   EXPECT_STREQ(temp_key.c_str(), L""); | 
 |  | 
 |   temp_key = L"a"; | 
 |   EXPECT_TRUE(RegKey::GetRootKeyInfo(&temp_key) == NULL); | 
 |   EXPECT_STREQ(temp_key.c_str(), L""); | 
 |  | 
 |   // The basics | 
 |   temp_key = L"HKLM\\a"; | 
 |   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_LOCAL_MACHINE); | 
 |   EXPECT_STREQ(temp_key.c_str(), L"a"); | 
 |  | 
 |   temp_key = L"HKEY_LOCAL_MACHINE\\a"; | 
 |   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_LOCAL_MACHINE); | 
 |   EXPECT_STREQ(temp_key.c_str(), L"a"); | 
 |  | 
 |   temp_key = L"HKCU\\a"; | 
 |   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CURRENT_USER); | 
 |   EXPECT_STREQ(temp_key.c_str(), L"a"); | 
 |  | 
 |   temp_key = L"HKEY_CURRENT_USER\\a"; | 
 |   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CURRENT_USER); | 
 |   EXPECT_STREQ(temp_key.c_str(), L"a"); | 
 |  | 
 |   temp_key = L"HKU\\a"; | 
 |   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_USERS); | 
 |   EXPECT_STREQ(temp_key.c_str(), L"a"); | 
 |  | 
 |   temp_key = L"HKEY_USERS\\a"; | 
 |   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_USERS); | 
 |   EXPECT_STREQ(temp_key.c_str(), L"a"); | 
 |  | 
 |   temp_key = L"HKCR\\a"; | 
 |   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CLASSES_ROOT); | 
 |   EXPECT_STREQ(temp_key.c_str(), L"a"); | 
 |  | 
 |   temp_key = L"HKEY_CLASSES_ROOT\\a"; | 
 |   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CLASSES_ROOT); | 
 |   EXPECT_STREQ(temp_key.c_str(), L"a"); | 
 |  | 
 |   // Make sure it is case insensitive | 
 |   temp_key = L"hkcr\\a"; | 
 |   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CLASSES_ROOT); | 
 |   EXPECT_STREQ(temp_key.c_str(), L"a"); | 
 |  | 
 |   temp_key = L"hkey_CLASSES_ROOT\\a"; | 
 |   EXPECT_EQ(RegKey::GetRootKeyInfo(&temp_key), HKEY_CLASSES_ROOT); | 
 |   EXPECT_STREQ(temp_key.c_str(), L"a"); | 
 |  | 
 |   // | 
 |   // Test RegKey::GetParentKeyInfo | 
 |   // | 
 |  | 
 |   // dud cases | 
 |   temp_key = L""; | 
 |   EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), L""); | 
 |   EXPECT_STREQ(temp_key.c_str(), L""); | 
 |  | 
 |   temp_key = L"a"; | 
 |   EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), L""); | 
 |   EXPECT_STREQ(temp_key.c_str(), L"a"); | 
 |  | 
 |   temp_key = L"a\\b"; | 
 |   EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), L"a"); | 
 |   EXPECT_STREQ(temp_key.c_str(), L"b"); | 
 |  | 
 |   temp_key = L"\\b"; | 
 |   EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), L""); | 
 |   EXPECT_STREQ(temp_key.c_str(), L"b"); | 
 |  | 
 |   // Some regular cases | 
 |   temp_key = L"HKEY_CLASSES_ROOT\\moon"; | 
 |   EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), | 
 |                L"HKEY_CLASSES_ROOT"); | 
 |   EXPECT_STREQ(temp_key.c_str(), L"moon"); | 
 |  | 
 |   temp_key = L"HKEY_CLASSES_ROOT\\moon\\doggy"; | 
 |   EXPECT_STREQ(RegKey::GetParentKeyInfo(&temp_key).c_str(), | 
 |                L"HKEY_CLASSES_ROOT\\moon"); | 
 |   EXPECT_STREQ(temp_key.c_str(), L"doggy"); | 
 |  | 
 |   // | 
 |   // Test MultiSZBytesToStringArray | 
 |   // | 
 |  | 
 |   std::vector<std::wstring> result; | 
 |   EXPECT_SUCCEEDED(RegKey::MultiSZBytesToStringArray( | 
 |       reinterpret_cast<const uint8_t*>(kMultiSZ), sizeof(kMultiSZ), &result)); | 
 |   EXPECT_EQ(result.size(), 3); | 
 |   EXPECT_STREQ(result[0].c_str(), L"abc"); | 
 |   EXPECT_STREQ(result[1].c_str(), L"def"); | 
 |   EXPECT_STREQ(result[2].c_str(), L"P12345"); | 
 |  | 
 |   EXPECT_SUCCEEDED(RegKey::MultiSZBytesToStringArray( | 
 |       reinterpret_cast<const uint8_t*>(kEmptyMultiSZ), sizeof(kEmptyMultiSZ), | 
 |       &result)); | 
 |   EXPECT_EQ(result.size(), 0); | 
 |   EXPECT_FALSE(SUCCEEDED(RegKey::MultiSZBytesToStringArray( | 
 |       reinterpret_cast<const uint8_t*>(kInvalidMultiSZ), | 
 |       sizeof(kInvalidMultiSZ), &result))); | 
 | } | 
 |  | 
 | TEST(RegKeyTest, RegKeyHelperFunctionsTest) { | 
 |   RegKeyHelperFunctionsTest(); | 
 | } | 
 |  | 
 | void RegKeyNonStaticFunctionsTest() { | 
 |   DWORD int_val = 0; | 
 |   DWORD64 int64_val = 0; | 
 |   wchar_t* str_val = NULL; | 
 |   uint8_t* binary_val = NULL; | 
 |   DWORD uint8_count = 0; | 
 |  | 
 |   // Just in case... | 
 |   // make sure the no test key residue is left from previous aborted runs | 
 |   RegKey::DeleteKey(kFullRkey1); | 
 |  | 
 |   // initial state | 
 |   RegKey r_key; | 
 |   EXPECT_TRUE(r_key.key() == NULL); | 
 |  | 
 |   // create a reg key | 
 |   EXPECT_SUCCEEDED(r_key.Create(HKEY_CURRENT_USER, kRkey1)); | 
 |  | 
 |   // do the create twice - it should return the already created one | 
 |   EXPECT_SUCCEEDED(r_key.Create(HKEY_CURRENT_USER, kRkey1)); | 
 |  | 
 |   // now do an open - should work just fine | 
 |   EXPECT_SUCCEEDED(r_key.Open(HKEY_CURRENT_USER, kRkey1)); | 
 |  | 
 |   // get an in-existent value | 
 |   EXPECT_EQ(r_key.GetValue(kValNameInt, &int_val), | 
 |             HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); | 
 |  | 
 |   // set and get some values | 
 |  | 
 |   // set an INT 32 | 
 |   EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt, kIntVal)); | 
 |  | 
 |   // check that the value exists | 
 |   EXPECT_TRUE(r_key.HasValue(kValNameInt)); | 
 |  | 
 |   // read it back | 
 |   EXPECT_SUCCEEDED(r_key.GetValue(kValNameInt, &int_val)); | 
 |   EXPECT_EQ(int_val, kIntVal); | 
 |  | 
 |   // set it again! | 
 |   EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt, kIntVal2)); | 
 |  | 
 |   // read it again | 
 |   EXPECT_SUCCEEDED(r_key.GetValue(kValNameInt, &int_val)); | 
 |   EXPECT_EQ(int_val, kIntVal2); | 
 |  | 
 |   // delete the value | 
 |   EXPECT_SUCCEEDED(r_key.DeleteValue(kValNameInt)); | 
 |  | 
 |   // check that the value is gone | 
 |   EXPECT_FALSE(r_key.HasValue(kValNameInt)); | 
 |  | 
 |   // set an INT 64 | 
 |   EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt64, kIntVal64)); | 
 |  | 
 |   // check that the value exists | 
 |   EXPECT_TRUE(r_key.HasValue(kValNameInt64)); | 
 |  | 
 |   // read it back | 
 |   EXPECT_SUCCEEDED(r_key.GetValue(kValNameInt64, &int64_val)); | 
 |   EXPECT_EQ(int64_val, kIntVal64); | 
 |  | 
 |   // delete the value | 
 |   EXPECT_SUCCEEDED(r_key.DeleteValue(kValNameInt64)); | 
 |  | 
 |   // check that the value is gone | 
 |   EXPECT_FALSE(r_key.HasValue(kValNameInt64)); | 
 |  | 
 |   // set a string | 
 |   EXPECT_SUCCEEDED(r_key.SetValue(kValNameStr, kStrVal)); | 
 |  | 
 |   // check that the value exists | 
 |   EXPECT_TRUE(r_key.HasValue(kValNameStr)); | 
 |  | 
 |   // read it back | 
 |   EXPECT_SUCCEEDED(r_key.GetValue(kValNameStr, &str_val)); | 
 |   EXPECT_TRUE(lstrcmp(str_val, kStrVal) == 0); | 
 |   delete[] str_val; | 
 |  | 
 |   // set it again | 
 |   EXPECT_SUCCEEDED(r_key.SetValue(kValNameStr, kStrVal2)); | 
 |  | 
 |   // read it again | 
 |   EXPECT_SUCCEEDED(r_key.GetValue(kValNameStr, &str_val)); | 
 |   EXPECT_TRUE(lstrcmp(str_val, kStrVal2) == 0); | 
 |   delete[] str_val; | 
 |  | 
 |   // delete the value | 
 |   EXPECT_SUCCEEDED(r_key.DeleteValue(kValNameStr)); | 
 |  | 
 |   // check that the value is gone | 
 |   EXPECT_FALSE(r_key.HasValue(kValNameInt)); | 
 |  | 
 |   // set a binary value | 
 |   EXPECT_SUCCEEDED(r_key.SetValue(kValNameBinary, | 
 |                                   reinterpret_cast<const uint8_t*>(kBinaryVal), | 
 |                                   sizeof(kBinaryVal) - 1)); | 
 |  | 
 |   // check that the value exists | 
 |   EXPECT_TRUE(r_key.HasValue(kValNameBinary)); | 
 |  | 
 |   // read it back | 
 |   EXPECT_SUCCEEDED(r_key.GetValue(kValNameBinary, &binary_val, &uint8_count)); | 
 |   EXPECT_TRUE(memcmp(binary_val, kBinaryVal, sizeof(kBinaryVal) - 1) == 0); | 
 |   delete[] binary_val; | 
 |  | 
 |   // set it again | 
 |   EXPECT_SUCCEEDED(r_key.SetValue(kValNameBinary, | 
 |                                   reinterpret_cast<const uint8_t*>(kBinaryVal2), | 
 |                                   sizeof(kBinaryVal) - 1)); | 
 |  | 
 |   // read it again | 
 |   EXPECT_SUCCEEDED(r_key.GetValue(kValNameBinary, &binary_val, &uint8_count)); | 
 |   EXPECT_TRUE(memcmp(binary_val, kBinaryVal2, sizeof(kBinaryVal2) - 1) == 0); | 
 |   delete[] binary_val; | 
 |  | 
 |   // delete the value | 
 |   EXPECT_SUCCEEDED(r_key.DeleteValue(kValNameBinary)); | 
 |  | 
 |   // check that the value is gone | 
 |   EXPECT_FALSE(r_key.HasValue(kValNameBinary)); | 
 |  | 
 |   // set some values and check the total count | 
 |  | 
 |   // set an INT 32 | 
 |   EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt, kIntVal)); | 
 |  | 
 |   // set an INT 64 | 
 |   EXPECT_SUCCEEDED(r_key.SetValue(kValNameInt64, kIntVal64)); | 
 |  | 
 |   // set a string | 
 |   EXPECT_SUCCEEDED(r_key.SetValue(kValNameStr, kStrVal)); | 
 |  | 
 |   // set a binary value | 
 |   EXPECT_SUCCEEDED(r_key.SetValue(kValNameBinary, | 
 |                                   reinterpret_cast<const uint8_t*>(kBinaryVal), | 
 |                                   sizeof(kBinaryVal) - 1)); | 
 |  | 
 |   // get the value count | 
 |   uint32_t value_count = r_key.GetValueCount(); | 
 |   EXPECT_EQ(value_count, 4); | 
 |  | 
 |   // check the value names | 
 |   std::wstring value_name; | 
 |   DWORD type = 0; | 
 |  | 
 |   EXPECT_SUCCEEDED(r_key.GetValueNameAt(0, &value_name, &type)); | 
 |   EXPECT_STREQ(value_name.c_str(), kValNameInt); | 
 |   EXPECT_EQ(type, REG_DWORD); | 
 |  | 
 |   EXPECT_SUCCEEDED(r_key.GetValueNameAt(1, &value_name, &type)); | 
 |   EXPECT_STREQ(value_name.c_str(), kValNameInt64); | 
 |   EXPECT_EQ(type, REG_QWORD); | 
 |  | 
 |   EXPECT_SUCCEEDED(r_key.GetValueNameAt(2, &value_name, &type)); | 
 |   EXPECT_STREQ(value_name.c_str(), kValNameStr); | 
 |   EXPECT_EQ(type, REG_SZ); | 
 |  | 
 |   EXPECT_SUCCEEDED(r_key.GetValueNameAt(3, &value_name, &type)); | 
 |   EXPECT_STREQ(value_name.c_str(), kValNameBinary); | 
 |   EXPECT_EQ(type, REG_BINARY); | 
 |  | 
 |   // check that there are no more values | 
 |   EXPECT_FAILED(r_key.GetValueNameAt(4, &value_name, &type)); | 
 |  | 
 |   uint32_t subkey_count = r_key.GetSubkeyCount(); | 
 |   EXPECT_EQ(subkey_count, 0); | 
 |  | 
 |   // now create a subkey and make sure we can get the name | 
 |   RegKey temp_key; | 
 |   EXPECT_SUCCEEDED(temp_key.Create(HKEY_CURRENT_USER, kRkey1Subkey)); | 
 |  | 
 |   // check the subkey exists | 
 |   EXPECT_TRUE(r_key.HasSubkey(kRkey1SubkeyName)); | 
 |  | 
 |   // check the name | 
 |   EXPECT_EQ(r_key.GetSubkeyCount(), 1); | 
 |  | 
 |   std::wstring subkey_name; | 
 |   EXPECT_SUCCEEDED(r_key.GetSubkeyNameAt(0, &subkey_name)); | 
 |   EXPECT_STREQ(subkey_name.c_str(), kRkey1SubkeyName); | 
 |  | 
 |   // delete the key | 
 |   EXPECT_SUCCEEDED(r_key.DeleteSubKey(kRkey1)); | 
 |  | 
 |   // close this key | 
 |   EXPECT_SUCCEEDED(r_key.Close()); | 
 |  | 
 |   // whack the whole key | 
 |   EXPECT_SUCCEEDED(RegKey::DeleteKey(kFullRkey1)); | 
 | } | 
 |  | 
 | void RegKeyStaticFunctionsTest() { | 
 |   DWORD int_val = 0; | 
 |   DWORD64 int64_val = 0; | 
 |   float float_val = 0; | 
 |   double double_val = 0; | 
 |   wchar_t* str_val = NULL; | 
 |   std::wstring wstr_val; | 
 |   uint8_t* binary_val = NULL; | 
 |   DWORD uint8_count = 0; | 
 |  | 
 |   // Just in case... | 
 |   // make sure the no test key residue is left from previous aborted runs | 
 |   RegKey::DeleteKey(kFullRkey1); | 
 |  | 
 |   // get an in-existent value from an un-existent key | 
 |   EXPECT_EQ(RegKey::GetValue(kFullRkey1, kValNameInt, &int_val), | 
 |             HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); | 
 |  | 
 |   // set int32_t | 
 |   EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameInt, kIntVal)); | 
 |  | 
 |   // check that the value exists | 
 |   EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameInt)); | 
 |  | 
 |   // get an in-existent value from an existent key | 
 |   EXPECT_EQ(RegKey::GetValue(kFullRkey1, L"bogus", &int_val), | 
 |             HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); | 
 |  | 
 |   // read it back | 
 |   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameInt, &int_val)); | 
 |   EXPECT_EQ(int_val, kIntVal); | 
 |  | 
 |   // delete the value | 
 |   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameInt)); | 
 |  | 
 |   // check that the value is gone | 
 |   EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameInt)); | 
 |  | 
 |   // set int64_t | 
 |   EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameInt64, kIntVal64)); | 
 |  | 
 |   // check that the value exists | 
 |   EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameInt64)); | 
 |  | 
 |   // read it back | 
 |   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameInt64, &int64_val)); | 
 |   EXPECT_EQ(int64_val, kIntVal64); | 
 |  | 
 |   // delete the value | 
 |   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameInt64)); | 
 |  | 
 |   // check that the value is gone | 
 |   EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameInt64)); | 
 |  | 
 |   // set float | 
 |   EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameFloat, kFloatVal)); | 
 |  | 
 |   // check that the value exists | 
 |   EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameFloat)); | 
 |  | 
 |   // read it back | 
 |   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameFloat, &float_val)); | 
 |   EXPECT_EQ(float_val, kFloatVal); | 
 |  | 
 |   // delete the value | 
 |   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameFloat)); | 
 |  | 
 |   // check that the value is gone | 
 |   EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameFloat)); | 
 |   EXPECT_FAILED(RegKey::GetValue(kFullRkey1, kValNameFloat, &float_val)); | 
 |  | 
 |   // set double | 
 |   EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameDouble, kDoubleVal)); | 
 |  | 
 |   // check that the value exists | 
 |   EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameDouble)); | 
 |  | 
 |   // read it back | 
 |   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameDouble, &double_val)); | 
 |   EXPECT_EQ(double_val, kDoubleVal); | 
 |  | 
 |   // delete the value | 
 |   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameDouble)); | 
 |  | 
 |   // check that the value is gone | 
 |   EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameDouble)); | 
 |   EXPECT_FAILED(RegKey::GetValue(kFullRkey1, kValNameDouble, &double_val)); | 
 |  | 
 |   // set string | 
 |   EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameStr, kStrVal)); | 
 |  | 
 |   // check that the value exists | 
 |   EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameStr)); | 
 |  | 
 |   // read it back | 
 |   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameStr, &str_val)); | 
 |   EXPECT_TRUE(lstrcmp(str_val, kStrVal) == 0); | 
 |   delete[] str_val; | 
 |  | 
 |   // read it back in std::wstring | 
 |   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameStr, &wstr_val)); | 
 |   EXPECT_STREQ(wstr_val.c_str(), kStrVal); | 
 |  | 
 |   // get an in-existent value from an existent key | 
 |   EXPECT_EQ(RegKey::GetValue(kFullRkey1, L"bogus", &str_val), | 
 |             HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); | 
 |  | 
 |   // delete the value | 
 |   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameStr)); | 
 |  | 
 |   // check that the value is gone | 
 |   EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameStr)); | 
 |  | 
 |   // set binary | 
 |   EXPECT_SUCCEEDED(RegKey::SetValue( | 
 |       kFullRkey1, kValNameBinary, reinterpret_cast<const uint8_t*>(kBinaryVal), | 
 |       sizeof(kBinaryVal) - 1)); | 
 |  | 
 |   // check that the value exists | 
 |   EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameBinary)); | 
 |  | 
 |   // read it back | 
 |   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameBinary, | 
 |       &binary_val, &uint8_count)); | 
 |   EXPECT_TRUE(memcmp(binary_val, kBinaryVal, sizeof(kBinaryVal)-1) == 0); | 
 |   delete[] binary_val; | 
 |  | 
 |   // delete the value | 
 |   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameBinary)); | 
 |  | 
 |   // check that the value is gone | 
 |   EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameBinary)); | 
 |  | 
 |   // special case - set a binary value with length 0 | 
 |   EXPECT_SUCCEEDED( | 
 |       RegKey::SetValue(kFullRkey1, kValNameBinary, | 
 |                        reinterpret_cast<const uint8_t*>(kBinaryVal), 0)); | 
 |  | 
 |   // check that the value exists | 
 |   EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameBinary)); | 
 |  | 
 |   // read it back | 
 |   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameBinary, | 
 |       &binary_val, &uint8_count)); | 
 |   EXPECT_EQ(uint8_count, 0); | 
 |   EXPECT_TRUE(binary_val == NULL); | 
 |   delete[] binary_val; | 
 |  | 
 |   // delete the value | 
 |   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameBinary)); | 
 |  | 
 |   // check that the value is gone | 
 |   EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameBinary)); | 
 |  | 
 |   // special case - set a NULL binary value | 
 |   EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1, kValNameBinary, NULL, 100)); | 
 |  | 
 |   // check that the value exists | 
 |   EXPECT_TRUE(RegKey::HasValue(kFullRkey1, kValNameBinary)); | 
 |  | 
 |   // read it back | 
 |   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameBinary, | 
 |                                     &binary_val, &uint8_count)); | 
 |   EXPECT_EQ(uint8_count, 0); | 
 |   EXPECT_TRUE(binary_val == NULL); | 
 |   delete[] binary_val; | 
 |  | 
 |   // delete the value | 
 |   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1, kValNameBinary)); | 
 |  | 
 |   // check that the value is gone | 
 |   EXPECT_FALSE(RegKey::HasValue(kFullRkey1, kValNameBinary)); | 
 |  | 
 |   // test read/write REG_MULTI_SZ value | 
 |   std::vector<std::wstring> result; | 
 |   EXPECT_SUCCEEDED(RegKey::SetValueMultiSZ( | 
 |       kFullRkey1, kValNameMultiStr, reinterpret_cast<const uint8_t*>(kMultiSZ), | 
 |       sizeof(kMultiSZ))); | 
 |   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameMultiStr, &result)); | 
 |   EXPECT_EQ(result.size(), 3); | 
 |   EXPECT_STREQ(result[0].c_str(), L"abc"); | 
 |   EXPECT_STREQ(result[1].c_str(), L"def"); | 
 |   EXPECT_STREQ(result[2].c_str(), L"P12345"); | 
 |   EXPECT_SUCCEEDED(RegKey::SetValueMultiSZ( | 
 |       kFullRkey1, kValNameMultiStr, | 
 |       reinterpret_cast<const uint8_t*>(kEmptyMultiSZ), sizeof(kEmptyMultiSZ))); | 
 |   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameMultiStr, &result)); | 
 |   EXPECT_EQ(result.size(), 0); | 
 |   // writing REG_MULTI_SZ value will automatically add ending null characters | 
 |   EXPECT_SUCCEEDED( | 
 |       RegKey::SetValueMultiSZ(kFullRkey1, kValNameMultiStr, | 
 |                               reinterpret_cast<const uint8_t*>(kInvalidMultiSZ), | 
 |                               sizeof(kInvalidMultiSZ))); | 
 |   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1, kValNameMultiStr, &result)); | 
 |   EXPECT_EQ(result.size(), 1); | 
 |   EXPECT_STREQ(result[0].c_str(), L"678"); | 
 |  | 
 |   // Run the following test only in dev machine | 
 |   // This is because the build machine might not have admin privilege | 
 | #ifdef IS_PRIVATE_BUILD | 
 |   // get a temp file name | 
 |   wchar_t temp_path[MAX_PATH] = {0}; | 
 |   EXPECT_LT(::GetTempPath(ARRAY_SIZE(temp_path), temp_path), | 
 |             static_cast<DWORD>(ARRAY_SIZE(temp_path))); | 
 |   wchar_t temp_file[MAX_PATH] = {0}; | 
 |   EXPECT_NE(::GetTempFileName(temp_path, L"rkut_", | 
 |                               ::GetTickCount(), temp_file), 0); | 
 |  | 
 |   // test save | 
 |   EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1Subkey, kValNameInt, kIntVal)); | 
 |   EXPECT_SUCCEEDED(RegKey::SetValue(kFullRkey1Subkey, kValNameInt64, kIntVal64)); | 
 |   EXPECT_SUCCEEDED(RegKey::Save(kFullRkey1Subkey, temp_file)); | 
 |   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1Subkey, kValNameInt)); | 
 |   EXPECT_SUCCEEDED(RegKey::DeleteValue(kFullRkey1Subkey, kValNameInt64)); | 
 |  | 
 |   // test restore | 
 |   EXPECT_SUCCEEDED(RegKey::Restore(kFullRkey1Subkey, temp_file)); | 
 |   int_val = 0; | 
 |   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1Subkey, kValNameInt, &int_val)); | 
 |   EXPECT_EQ(int_val, kIntVal); | 
 |   int64_val = 0; | 
 |   EXPECT_SUCCEEDED(RegKey::GetValue(kFullRkey1Subkey, | 
 |                                     kValNameInt64, | 
 |                                     &int64_val)); | 
 |   EXPECT_EQ(int64_val, kIntVal64); | 
 |  | 
 |   // delete the temp file | 
 |   EXPECT_EQ(TRUE, ::DeleteFile(temp_file)); | 
 | #endif | 
 |  | 
 |   // whack the whole key | 
 |   EXPECT_SUCCEEDED(RegKey::DeleteKey(kFullRkey1)); | 
 | } | 
 |  | 
 | // Run both tests under the same test target. Because they access (read and | 
 | // write) the same registry keys they can't run in parallel with eachother. | 
 | TEST(RegKeyTest, RegKeyFunctionsTest) { | 
 |   RegKeyNonStaticFunctionsTest(); | 
 |   RegKeyStaticFunctionsTest(); | 
 | } | 
 |  | 
 | }  // namespace rtc |