From 5ec924d96cb591fd29bc5ed417c7fb02ab33c76f Mon Sep 17 00:00:00 2001 From: GiovanniDicanio Date: Tue, 29 Mar 2022 20:16:33 +0200 Subject: [PATCH] Added Error-Returning TrySetXxxValue Methods Added methods named like TrySetXxxValue (e.g. TrySetDwordValue) that, on failure, return an error instead of throwing exceptions. --- README.md | 2 +- WinReg/WinReg.hpp | 164 +++++++++++++++++++++++++++++++++++++++++- WinReg/WinRegTest.cpp | 50 +++++++++++-- 3 files changed, 208 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index ce98ec1..81fdd54 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# WinReg v5.0.1 +# WinReg v5.1.0 ## High-level C++ Wrapper Around the Low-level Windows Registry C-interface API by Giovanni Dicanio diff --git a/WinReg/WinReg.hpp b/WinReg/WinReg.hpp index 3a80e73..53cd1aa 100644 --- a/WinReg/WinReg.hpp +++ b/WinReg/WinReg.hpp @@ -9,7 +9,7 @@ // Copyright (C) by Giovanni Dicanio // // First version: 2017, January 22nd -// Last update: 2022, March 21th +// Last update: 2022, March 29th // // E-mail: . AT REMOVE_THIS gmail.com // @@ -278,6 +278,36 @@ class RegKey void SetBinaryValue(const std::wstring& valueName, const void* data, DWORD dataSize); + // + // Registry Value Setters Returning RegResult + // (instead of throwing RegException on error) + // + + [[nodiscard]] RegResult TrySetDwordValue(const std::wstring& valueName, DWORD data) noexcept; + + [[nodiscard]] RegResult TrySetQwordValue(const std::wstring& valueName, + const ULONGLONG& data) noexcept; + + [[nodiscard]] RegResult TrySetStringValue(const std::wstring& valueName, + const std::wstring& data) noexcept; + + [[nodiscard]] RegResult TrySetExpandStringValue(const std::wstring& valueName, + const std::wstring& data) noexcept; + + [[nodiscard]] RegResult TrySetMultiStringValue(const std::wstring& valueName, + const std::vector& data); + // Note: The TrySetMultiStringValue method CANNOT be marked noexcept, + // because internally the method *dynamically allocates memory* for creating the multi-string + // that will be stored in the Registry. + + [[nodiscard]] RegResult TrySetBinaryValue(const std::wstring& valueName, + const std::vector& data) noexcept; + + [[nodiscard]] RegResult TrySetBinaryValue(const std::wstring& valueName, + const void* data, + DWORD dataSize) noexcept; + + // // Registry Value Getters // @@ -1251,6 +1281,138 @@ inline void RegKey::SetBinaryValue( } +inline RegResult RegKey::TrySetDwordValue(const std::wstring& valueName, const DWORD data) noexcept +{ + _ASSERTE(IsValid()); + + return RegResult{ ::RegSetValueExW( + m_hKey, + valueName.c_str(), + 0, // reserved + REG_DWORD, + reinterpret_cast(&data), + sizeof(data) + ) }; +} + + +inline RegResult RegKey::TrySetQwordValue(const std::wstring& valueName, + const ULONGLONG& data) noexcept +{ + _ASSERTE(IsValid()); + + return RegResult{ ::RegSetValueExW( + m_hKey, + valueName.c_str(), + 0, // reserved + REG_QWORD, + reinterpret_cast(&data), + sizeof(data) + ) }; +} + + +inline RegResult RegKey::TrySetStringValue(const std::wstring& valueName, + const std::wstring& data) noexcept +{ + _ASSERTE(IsValid()); + + // String size including the terminating NUL, in bytes + const DWORD dataSize = static_cast((data.length() + 1) * sizeof(wchar_t)); + + return RegResult{ ::RegSetValueExW( + m_hKey, + valueName.c_str(), + 0, // reserved + REG_SZ, + reinterpret_cast(data.c_str()), + dataSize + ) }; +} + + +inline RegResult RegKey::TrySetExpandStringValue(const std::wstring& valueName, + const std::wstring& data) noexcept +{ + _ASSERTE(IsValid()); + + // String size including the terminating NUL, in bytes + const DWORD dataSize = static_cast((data.length() + 1) * sizeof(wchar_t)); + + return RegResult{ ::RegSetValueExW( + m_hKey, + valueName.c_str(), + 0, // reserved + REG_EXPAND_SZ, + reinterpret_cast(data.c_str()), + dataSize + ) }; +} + + +inline RegResult RegKey::TrySetMultiStringValue(const std::wstring& valueName, + const std::vector& data) +{ + _ASSERTE(IsValid()); + + // First, we have to build a double-NUL-terminated multi-string from the input data. + // + // NOTE: This is the reason why I *cannot* mark this method noexcept, + // since a *dynamic allocation* happens for creating the std::vector in BuildMultiString. + // And, if dynamic memory allocations fail, an exception is thrown. + // + const std::vector multiString = detail::BuildMultiString(data); + + // Total size, in bytes, of the whole multi-string structure + const DWORD dataSize = static_cast(multiString.size() * sizeof(wchar_t)); + + return RegResult{ ::RegSetValueExW( + m_hKey, + valueName.c_str(), + 0, // reserved + REG_MULTI_SZ, + reinterpret_cast(&multiString[0]), + dataSize + ) }; +} + + +inline RegResult RegKey::TrySetBinaryValue(const std::wstring& valueName, + const std::vector& data) noexcept +{ + _ASSERTE(IsValid()); + + // Total data size, in bytes + const DWORD dataSize = static_cast(data.size()); + + return RegResult{ ::RegSetValueExW( + m_hKey, + valueName.c_str(), + 0, // reserved + REG_BINARY, + &data[0], + dataSize + ) }; +} + + +inline RegResult RegKey::TrySetBinaryValue(const std::wstring& valueName, + const void* const data, + const DWORD dataSize) noexcept +{ + _ASSERTE(IsValid()); + + return RegResult{ ::RegSetValueExW( + m_hKey, + valueName.c_str(), + 0, // reserved + REG_BINARY, + static_cast(data), + dataSize + ) }; +} + + inline DWORD RegKey::GetDwordValue(const std::wstring& valueName) const { _ASSERTE(IsValid()); diff --git a/WinReg/WinRegTest.cpp b/WinReg/WinRegTest.cpp index 648f706..a59b003 100644 --- a/WinReg/WinRegTest.cpp +++ b/WinReg/WinRegTest.cpp @@ -82,13 +82,44 @@ void Test() key.SetMultiStringValue(L"TestValueMultiString", testMultiSz); key.SetBinaryValue(L"TestValueBinary", testBinary); + if (key.TrySetDwordValue(L"TestTryValueDword", testDw).Failed()) + { + wcout << L"RegKey::TrySetDwordValue failed.\n"; + } + + if (key.TrySetQwordValue(L"TestTryValueQword", testQw).Failed()) + { + wcout << L"RegKey::TrySetQwordValue failed.\n"; + } + + if (key.TrySetStringValue(L"TestTryValueString", testSz).Failed()) + { + wcout << L"RegKey::TrySetStringValue failed.\n"; + } + + if (key.TrySetExpandStringValue(L"TestTryValueExpandString", testExpandSz).Failed()) + { + wcout << L"RegKey::TrySetExpandStringValue failed.\n"; + } + + if (key.TrySetMultiStringValue(L"TestTryValueMultiString", testMultiSz).Failed()) + { + wcout << L"RegKey::TrySetMultiStringValue failed.\n"; + } + + if (key.TrySetBinaryValue(L"TestTryValueBinary", testBinary).Failed()) + { + wcout << L"RegKey::TrySetBinaryValue failed.\n"; + } + + DWORD testDw1 = key.GetDwordValue(L"TestValueDword"); if (testDw1 != testDw) { wcout << L"RegKey::GetDwordValue failed.\n"; } - if (auto testDw2 = key.TryGetDwordValue(L"TestValueDword")) + if (auto testDw2 = key.TryGetDwordValue(L"TestTryValueDword")) { if (testDw2 != testDw) { @@ -112,7 +143,7 @@ void Test() wcout << L"RegKey::GetQwordValue failed.\n"; } - if (auto testQw2 = key.TryGetQwordValue(L"TestValueQword")) + if (auto testQw2 = key.TryGetQwordValue(L"TestTryValueQword")) { if (testQw2 != testQw) { @@ -136,7 +167,7 @@ void Test() wcout << L"RegKey::GetStringValue failed.\n"; } - if (auto testSz2 = key.TryGetStringValue(L"TestValueString")) + if (auto testSz2 = key.TryGetStringValue(L"TestTryValueString")) { if (testSz2 != testSz) { @@ -160,7 +191,7 @@ void Test() wcout << L"RegKey::GetExpandStringValue failed.\n"; } - if (auto testExpandSz2 = key.TryGetExpandStringValue(L"TestValueExpandString")) + if (auto testExpandSz2 = key.TryGetExpandStringValue(L"TestTryValueExpandString")) { if (testExpandSz2 != testExpandSz) { @@ -184,7 +215,7 @@ void Test() wcout << L"RegKey::GetMultiStringValue failed.\n"; } - if (auto testMultiSz2 = key.TryGetMultiStringValue(L"TestValueMultiString")) + if (auto testMultiSz2 = key.TryGetMultiStringValue(L"TestTryValueMultiString")) { if (testMultiSz2 != testMultiSz) { @@ -208,7 +239,7 @@ void Test() wcout << L"RegKey::GetBinaryValue failed.\n"; } - if (auto testBinary2 = key.TryGetBinaryValue(L"TestValueBinary")) + if (auto testBinary2 = key.TryGetBinaryValue(L"TestTryValueBinary")) { if (testBinary2 != testBinary) { @@ -237,6 +268,13 @@ void Test() key.DeleteValue(L"TestValueExpandString"); key.DeleteValue(L"TestValueMultiString"); key.DeleteValue(L"TestValueBinary"); + + key.DeleteValue(L"TestTryValueDword"); + key.DeleteValue(L"TestTryValueQword"); + key.DeleteValue(L"TestTryValueString"); + key.DeleteValue(L"TestTryValueExpandString"); + key.DeleteValue(L"TestTryValueMultiString"); + key.DeleteValue(L"TestTryValueBinary"); }