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:
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));
}