@@ -3104,6 +3104,127 @@ TEST_CASE("BasicRegistryTests::multi-strings", "[registry]")
31043104 }
31053105#endif
31063106#endif
3107+
3108+ #if WIL_USE_STL && defined(WIL_ENABLE_EXCEPTIONS)
3109+ const auto to_ptrs = [](const std::vector<std::wstring>& strings) {
3110+ std::vector<PCWSTR > ptrs;
3111+ ptrs.reserve (strings.size ());
3112+ for (const auto & s : strings)
3113+ {
3114+ ptrs.push_back (s.c_str ());
3115+ }
3116+ return ptrs;
3117+ };
3118+
3119+ SECTION (" set_value_multistring_nothrow/get_value_multistring_nothrow: with open key" )
3120+ {
3121+ wil::unique_hkey hkey;
3122+ REQUIRE_SUCCEEDED (wil::reg::create_unique_key_nothrow (HKEY_CURRENT_USER , testSubkey, hkey, wil::reg::key_access::readwrite));
3123+
3124+ for (const auto & value : multiStringTestVector)
3125+ {
3126+ const auto ptrs = to_ptrs (value);
3127+ REQUIRE_SUCCEEDED (wil::reg::set_value_multistring_nothrow (hkey.get (), stringValueName, ptrs.data (), ptrs.size ()));
3128+ auto result = wil::reg::get_value_multistring (hkey.get (), stringValueName);
3129+ // set_value_multistring_nothrow should produce the same result as set_value_multistring
3130+ wil::reg::set_value_multistring (hkey.get (), multiStringValueName, value);
3131+ auto expected = wil::reg::get_value_multistring (hkey.get (), multiStringValueName);
3132+ REQUIRE (result == expected);
3133+ }
3134+
3135+ // and verify default value name
3136+ const std::vector<std::wstring> testValue{L" hello" , L" world" };
3137+ const auto testPtrs = to_ptrs (testValue);
3138+ REQUIRE_SUCCEEDED (wil::reg::set_value_multistring_nothrow (hkey.get (), nullptr , testPtrs.data (), testPtrs.size ()));
3139+ auto result = wil::reg::get_value_multistring (hkey.get (), nullptr );
3140+ REQUIRE (result == testValue);
3141+ }
3142+
3143+ SECTION (" set_value_multistring_nothrow/get_value_multistring_nothrow: with string key" )
3144+ {
3145+ for (const auto & value : multiStringTestVector)
3146+ {
3147+ const auto ptrs = to_ptrs (value);
3148+ REQUIRE_SUCCEEDED (
3149+ wil::reg::set_value_multistring_nothrow (HKEY_CURRENT_USER , testSubkey, stringValueName, ptrs.data (), ptrs.size ()));
3150+ auto result = wil::reg::get_value_multistring (HKEY_CURRENT_USER , testSubkey, stringValueName);
3151+ // set_value_multistring_nothrow should produce the same result as set_value_multistring
3152+ wil::reg::set_value_multistring (HKEY_CURRENT_USER , testSubkey, multiStringValueName, value);
3153+ auto expected = wil::reg::get_value_multistring (HKEY_CURRENT_USER , testSubkey, multiStringValueName);
3154+ REQUIRE (result == expected);
3155+ }
3156+
3157+ // and verify default value name
3158+ const std::vector<std::wstring> testValue{L" hello" , L" world" };
3159+ const auto testPtrs = to_ptrs (testValue);
3160+ REQUIRE_SUCCEEDED (
3161+ wil::reg::set_value_multistring_nothrow (HKEY_CURRENT_USER , testSubkey, nullptr , testPtrs.data (), testPtrs.size ()));
3162+ auto result = wil::reg::get_value_multistring (HKEY_CURRENT_USER , testSubkey, nullptr );
3163+ REQUIRE (result == testValue);
3164+ }
3165+
3166+ SECTION (" set_value_multistring_nothrow: empty array with open key" )
3167+ {
3168+ wil::unique_hkey hkey;
3169+ REQUIRE_SUCCEEDED (wil::reg::create_unique_key_nothrow (HKEY_CURRENT_USER , testSubkey, hkey, wil::reg::key_access::readwrite));
3170+
3171+ // When passed an empty array, set_value_multistring_nothrow writes 2 null-terminators
3172+ // (i.e. a single empty string), matching the behavior of set_value_multistring
3173+ const std::vector<std::wstring> arrayOfOne{L" " };
3174+ REQUIRE_SUCCEEDED (wil::reg::set_value_multistring_nothrow (hkey.get (), stringValueName, nullptr , 0 ));
3175+ auto result = wil::reg::get_value_multistring (hkey.get (), stringValueName);
3176+ REQUIRE (result == arrayOfOne);
3177+
3178+ // and verify default value name
3179+ REQUIRE_SUCCEEDED (wil::reg::set_value_multistring_nothrow (hkey.get (), nullptr , nullptr , 0 ));
3180+ result = wil::reg::get_value_multistring (hkey.get (), nullptr );
3181+ REQUIRE (result == arrayOfOne);
3182+ }
3183+
3184+ SECTION (" set_value_multistring_nothrow: empty array with string key" )
3185+ {
3186+ const std::vector<std::wstring> arrayOfOne{L" " };
3187+ REQUIRE_SUCCEEDED (wil::reg::set_value_multistring_nothrow (HKEY_CURRENT_USER , testSubkey, stringValueName, nullptr , 0 ));
3188+ auto result = wil::reg::get_value_multistring (HKEY_CURRENT_USER , testSubkey, stringValueName);
3189+ REQUIRE (result == arrayOfOne);
3190+
3191+ // and verify default value name
3192+ REQUIRE_SUCCEEDED (wil::reg::set_value_multistring_nothrow (HKEY_CURRENT_USER , testSubkey, nullptr , nullptr , 0 ));
3193+ result = wil::reg::get_value_multistring (HKEY_CURRENT_USER , testSubkey, nullptr );
3194+ REQUIRE (result == arrayOfOne);
3195+ }
3196+
3197+ SECTION (" set_value_multistring_nothrow: fails with E_ACCESSDENIED on read-only key" )
3198+ {
3199+ wil::unique_hkey hkey;
3200+ REQUIRE_SUCCEEDED (wil::reg::create_unique_key_nothrow (HKEY_CURRENT_USER , testSubkey, hkey, wil::reg::key_access::readwrite));
3201+
3202+ wil::unique_hkey readOnlyKey;
3203+ REQUIRE_SUCCEEDED (wil::reg::open_unique_key_nothrow (HKEY_CURRENT_USER , testSubkey, readOnlyKey, wil::reg::key_access::read));
3204+
3205+ const PCWSTR testValue[]{L" test" };
3206+ auto hr = wil::reg::set_value_multistring_nothrow (readOnlyKey.get (), stringValueName, testValue, ARRAYSIZE (testValue));
3207+ REQUIRE (hr == E_ACCESSDENIED );
3208+ }
3209+
3210+ SECTION (" set_value_multistring_nothrow: round-trip with nothrow get via cotaskmem" )
3211+ {
3212+ wil::unique_hkey hkey;
3213+ REQUIRE_SUCCEEDED (wil::reg::create_unique_key_nothrow (HKEY_CURRENT_USER , testSubkey, hkey, wil::reg::key_access::readwrite));
3214+
3215+ const PCWSTR testValue[]{L" alpha" , L" bravo" , L" charlie" };
3216+ REQUIRE_SUCCEEDED (wil::reg::set_value_multistring_nothrow (hkey.get (), stringValueName, testValue, ARRAYSIZE (testValue)));
3217+
3218+ #if defined(__WIL_OBJBASE_H_)
3219+ wil::unique_cotaskmem_array_ptr<wil::unique_cotaskmem_string> result{};
3220+ REQUIRE_SUCCEEDED (wil::reg::get_value_multistring_nothrow (hkey.get (), stringValueName, result));
3221+ REQUIRE (result.size () == 3 );
3222+ REQUIRE (std::wstring_view (result[0 ]) == L" alpha" );
3223+ REQUIRE (std::wstring_view (result[1 ]) == L" bravo" );
3224+ REQUIRE (std::wstring_view (result[2 ]) == L" charlie" );
3225+ #endif // defined(__WIL_OBJBASE_H_)
3226+ }
3227+ #endif // WIL_USE_STL && defined(WIL_ENABLE_EXCEPTIONS)
31073228}
31083229
31093230#if defined(__WIL_OBJBASE_H_)
0 commit comments