winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit d010e249786b3d4e95ae5aaef4aa52a7b9fb89b8
parent 83b2db4ed20e4cc7cdae0d053feb14acb8b6df82
Author: JohnMcPMS <johnmcp@microsoft.com>
Date:   Wed, 21 Aug 2024 12:19:15 -0700

External HR error message support (#4746)

Fixes #3982 

## Change
Add support for externally defined HRESULTs to have a custom message.
Use this to provide a message for the errors associated with a Microsoft
Store package being unavailable for the current system.
Diffstat:
Msrc/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw | 3+++
Msrc/AppInstallerSharedLib/Errors.cpp | 63++++++++++++++++++++++++++++++++++++++++++++++-----------------
2 files changed, 49 insertions(+), 17 deletions(-)

diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw @@ -3106,4 +3106,7 @@ Please specify one of them using the --source option to proceed.</value> <data name="ConfigureListUnit" xml:space="preserve"> <value>Unit</value> </data> + <data name="StoreInstall_PackageNotAvailableForCurrentSystem" xml:space="preserve"> + <value>The package is not compatible with the current Windows version or platform.</value> + </data> </root> \ No newline at end of file diff --git a/src/AppInstallerSharedLib/Errors.cpp b/src/AppInstallerSharedLib/Errors.cpp @@ -12,13 +12,13 @@ namespace AppInstaller namespace { // A simple struct to hold the data - struct WinGetHResultData + struct HResultData { HRESULT Value; std::string_view Symbol; std::string_view Description; - bool operator<(const WinGetHResultData& other) const + bool operator<(const HResultData& other) const { return Value < other.Value; } @@ -31,7 +31,7 @@ namespace AppInstaller Errors::HResultInformation(value, symbol), m_unlocalizedDescription(unlocalizedDescription) {} - constexpr WinGetHResultInformation(const WinGetHResultData& data) : + constexpr WinGetHResultInformation(const HResultData& data) : Errors::HResultInformation(data.Value, data.Symbol), m_unlocalizedDescription(data.Description) {} @@ -54,7 +54,7 @@ namespace AppInstaller Errors::HResultInformation(value, symbol), m_unlocalizedDescription(unlocalizedDescription) {} - constexpr WinGetHResultInformationUnlocalized(const WinGetHResultData& data) : + constexpr WinGetHResultInformationUnlocalized(const HResultData& data) : Errors::HResultInformation(data.Value, data.Symbol), m_unlocalizedDescription(data.Description) {} @@ -83,9 +83,9 @@ namespace AppInstaller } }; -#define WINGET_HRESULT_INFO(_name_,_description_) WinGetHResultData{ _name_, #_name_, _description_ } +#define WINGET_HRESULT_INFO(_name_,_description_) HResultData{ _name_, #_name_, _description_ } - constexpr const WinGetHResultData s_wingetHResultData[] = + constexpr const HResultData s_wingetHResultData[] = { // Changes to any of these errors require the corresponding resource string in winget.resw to be updated. WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INTERNAL_ERROR, "Internal Error"), @@ -289,11 +289,21 @@ namespace AppInstaller WINGET_HRESULT_INFO(WINGET_INSTALLED_STATUS_FILE_FOUND_WITHOUT_HASH_CHECK, "The file was found but the hash was not checked."), }; - const WinGetHResultData* FindWinGetHResultData(HRESULT value) + // Map externally defined HRESULTs to error messages we want to use here + constexpr const HResultData s_externalHResultData[] = { - auto itr = std::lower_bound(std::cbegin(s_wingetHResultData), std::cend(s_wingetHResultData), WinGetHResultData{ value }); + // Changes to any of these errors require the corresponding resource string in winget.resw to be updated. + HResultData{ static_cast<HRESULT>(0x803FB103), "StoreInstall_PackageNotAvailableForCurrentSystem", "The package is not compatible with the current Windows version or platform." }, + HResultData{ static_cast<HRESULT>(0x803FB104), "StoreInstall_PackageNotAvailableForCurrentSystem", "The package is not compatible with the current Windows version or platform." }, + HResultData{ static_cast<HRESULT>(0x803FB106), "StoreInstall_PackageNotAvailableForCurrentSystem", "The package is not compatible with the current Windows version or platform." }, + }; - if (itr != std::cend(s_wingetHResultData) && itr->Value == value) + template <size_t ArraySize> + const HResultData* FindHResultData(HRESULT value, const HResultData (&dataArray)[ArraySize]) + { + auto itr = std::lower_bound(std::cbegin(dataArray), std::cend(dataArray), HResultData{ value }); + + if (itr != std::cend(dataArray) && itr->Value == value) { return itr; } @@ -301,9 +311,19 @@ namespace AppInstaller return nullptr; } + const HResultData* FindWinGetHResultData(HRESULT value) + { + return FindHResultData(value, s_wingetHResultData); + } + + const HResultData* FindExternalHResultData(HRESULT value) + { + return FindHResultData(value, s_externalHResultData); + } + Utility::LocIndString GetMessageForAppInstallerHR(HRESULT hr) { - const WinGetHResultData* data = FindWinGetHResultData(hr); + const HResultData* data = FindWinGetHResultData(hr); return data ? WinGetHResultInformation(*data).GetDescription() : UnknownHResultInformation(hr).GetDescription(); @@ -319,7 +339,16 @@ namespace AppInstaller } else { - strstr << std::system_category().message(hr); + const HResultData* data = FindExternalHResultData(hr); + + if (data) + { + strstr << WinGetHResultInformation(*data).GetDescription(); + } + else + { + strstr << std::system_category().message(hr); + } } } } @@ -402,7 +431,7 @@ namespace AppInstaller { if (HRESULT_FACILITY(value) == APPINSTALLER_CLI_ERROR_FACILITY) { - const WinGetHResultData* data = FindWinGetHResultData(value); + const HResultData* data = FindWinGetHResultData(value); if (data) { @@ -425,7 +454,7 @@ namespace AppInstaller auto addToResultIf = [&](auto predicate) { - for (const WinGetHResultData& data : s_wingetHResultData) + for (const HResultData& data : s_wingetHResultData) { if (predicate(data) && std::none_of(result.begin(), result.end(), [&](const std::unique_ptr<HResultInformation>& info) { return info->Value() == data.Value; })) @@ -435,9 +464,9 @@ namespace AppInstaller } }; - addToResultIf([&](const WinGetHResultData& data) { return Utility::CaseInsensitiveEquals(data.Symbol, value); }); - addToResultIf([&](const WinGetHResultData& data) { return Utility::CaseInsensitiveContainsSubstring(data.Symbol, value); }); - addToResultIf([&](const WinGetHResultData& data) { return Utility::CaseInsensitiveContainsSubstring(data.Description, value); }); + addToResultIf([&](const HResultData& data) { return Utility::CaseInsensitiveEquals(data.Symbol, value); }); + addToResultIf([&](const HResultData& data) { return Utility::CaseInsensitiveContainsSubstring(data.Symbol, value); }); + addToResultIf([&](const HResultData& data) { return Utility::CaseInsensitiveContainsSubstring(data.Description, value); }); return result; } @@ -447,7 +476,7 @@ namespace AppInstaller std::vector<std::unique_ptr<HResultInformation>> result; result.reserve(ARRAYSIZE(s_wingetHResultData)); - for (const WinGetHResultData& data : s_wingetHResultData) + for (const HResultData& data : s_wingetHResultData) { result.emplace_back(std::make_unique<WinGetHResultInformationUnlocalized>(data)); }