commit a5bffb2a86a62597a2d2789bdf9fe79bd5f7fc29 parent 077cf644438980e6eccfe1742abca65595aeb7b6 Author: JohnMcPMS <johnmcp@microsoft.com> Date: Thu, 14 Sep 2023 09:44:31 -0700 Rework the error list and add a command to get error information (#3615) This change reworks the error description switch statement into a sorted array of data. We then use binary search to find the appropriate description when needed. In addition, it now supports these values being localized. This change also adds the `error` command (hidden) to enable a somewhat easier path to getting error information specific to winget. The command takes in a single value. If this is wholly a number, it is treated as the error number itself. If it is not a number, it is treated as a string to search within the symbols and descriptions of the winget errors. Diffstat:
22 files changed, 1382 insertions(+), 458 deletions(-)
diff --git a/src/AppInstallerCLICore/AppInstallerCLICore.vcxproj b/src/AppInstallerCLICore/AppInstallerCLICore.vcxproj @@ -359,6 +359,7 @@ <ClInclude Include="Commands\ConfigureValidateCommand.h" /> <ClInclude Include="Commands\DebugCommand.h" /> <ClInclude Include="Commands\DownloadCommand.h" /> + <ClInclude Include="Commands\ErrorCommand.h" /> <ClInclude Include="Commands\ExperimentalCommand.h" /> <ClInclude Include="Commands\ExportCommand.h" /> <ClInclude Include="Commands\ImportCommand.h" /> @@ -428,6 +429,7 @@ <ClCompile Include="Commands\ConfigureValidateCommand.cpp" /> <ClCompile Include="Commands\DebugCommand.cpp" /> <ClCompile Include="Commands\DownloadCommand.cpp" /> + <ClCompile Include="Commands\ErrorCommand.cpp" /> <ClCompile Include="Commands\ImportCommand.cpp" /> <ClCompile Include="Commands\PinCommand.cpp" /> <ClCompile Include="Commands\TestCommand.cpp" /> diff --git a/src/AppInstallerCLICore/AppInstallerCLICore.vcxproj.filters b/src/AppInstallerCLICore/AppInstallerCLICore.vcxproj.filters @@ -230,6 +230,9 @@ <ClInclude Include="ConfigurationCommon.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="Commands\ErrorCommand.h"> + <Filter>Commands</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="pch.cpp"> @@ -427,6 +430,9 @@ <ClCompile Include="ConfigurationCommon.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="Commands\ErrorCommand.cpp"> + <Filter>Commands</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <None Include="PropertySheet.props" /> diff --git a/src/AppInstallerCLICore/Argument.cpp b/src/AppInstallerCLICore/Argument.cpp @@ -176,6 +176,10 @@ namespace AppInstaller::CLI case Execution::Args::Type::PinInstalled: return { type, "installed"_liv, ArgTypeCategory::None }; + // Error command + case Execution::Args::Type::ErrorInput: + return { type, "input"_liv, ArgTypeCategory::None }; + // Configuration commands case Execution::Args::Type::ConfigurationFile: return { type, "file"_liv, 'f' }; diff --git a/src/AppInstallerCLICore/Commands/DebugCommand.cpp b/src/AppInstallerCLICore/Commands/DebugCommand.cpp @@ -54,6 +54,7 @@ namespace AppInstaller::CLI return InitializeFromMoveOnly<std::vector<std::unique_ptr<Command>>>({ std::make_unique<DumpProxyStubRegistrationsCommand>(FullName()), std::make_unique<DumpInterestingIIDsCommand>(FullName()), + std::make_unique<DumpErrorResourceCommand>(FullName()), }); } @@ -118,6 +119,32 @@ namespace AppInstaller::CLI { OutputIIDMapping<winrt::Microsoft::Management::Configuration::IConfigurationStatics>(context); } + + Resource::LocString DumpErrorResourceCommand::ShortDescription() const + { + return Utility::LocIndString("Dump error resources"sv); + } + + Resource::LocString DumpErrorResourceCommand::LongDescription() const + { + return Utility::LocIndString("Dump the error information as resources."sv); + } + + void DumpErrorResourceCommand::ExecuteInternal(Execution::Context& context) const + { + auto info = context.Reporter.Info(); + + // <data name="InstallFlowReturnCodeInstallInProgress" xml:space="preserve"> + // <value>Another installation is already in progress. Try again later.</value> + // </data> + for (const auto& error : Errors::GetWinGetErrors()) + { + info << + " <data name=\"" << error->Symbol() << "\" xml:space=\"preserve\">\n" + " <value>" << error->GetDescription() << "</value>\n" + " </data>" << std::endl; + } + } } #endif diff --git a/src/AppInstallerCLICore/Commands/DebugCommand.h b/src/AppInstallerCLICore/Commands/DebugCommand.h @@ -45,6 +45,18 @@ namespace AppInstaller::CLI protected: void ExecuteInternal(Execution::Context& context) const override; }; + + // Outputs the errors as resources. + struct DumpErrorResourceCommand final : public Command + { + DumpErrorResourceCommand(std::string_view parent) : Command("dump-error-resource", {}, parent) {} + + Resource::LocString ShortDescription() const override; + Resource::LocString LongDescription() const override; + + protected: + void ExecuteInternal(Execution::Context& context) const override; + }; } #endif diff --git a/src/AppInstallerCLICore/Commands/ErrorCommand.cpp b/src/AppInstallerCLICore/Commands/ErrorCommand.cpp @@ -0,0 +1,87 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "ErrorCommand.h" +#include "AppInstallerStrings.h" +#include "AppInstallerErrors.h" +#include "VTSupport.h" + +namespace AppInstaller::CLI +{ + namespace + { + // 0x12345678 : SYMBOL_VALUE + // Descriptive text + void OutputHResultInformation(Execution::Context& context, const Errors::HResultInformation& error) + { + auto info = context.Reporter.Info(); + info << VirtualTerminal::TextFormat::Foreground::Bright << "0x" << VirtualTerminal::TextFormat::Foreground::Bright << Logging::SetHRFormat << error.Value(); + if (!error.Symbol().empty()) + { + info << " : "_liv << VirtualTerminal::TextFormat::Foreground::BrightCyan << error.Symbol(); + } + info << std::endl; + info << error.GetDescription() << std::endl; + } + } + + std::vector<Argument> ErrorCommand::GetArguments() const + { + return { + Argument{ Execution::Args::Type::ErrorInput, Resource::String::ErrorInputArgumentDescription, ArgumentType::Positional, true }, + }; + } + + Resource::LocString ErrorCommand::ShortDescription() const + { + return { Resource::String::ErrorCommandShortDescription }; + } + + Resource::LocString ErrorCommand::LongDescription() const + { + return { Resource::String::ErrorCommandLongDescription }; + } + + void ErrorCommand::ExecuteInternal(Execution::Context& context) const + { + std::string input{ context.Args.GetArg(Execution::Args::Type::ErrorInput) }; + + const char* begin = input.c_str(); + char* end = nullptr; + errno = 0; + HRESULT errorNumber = strtol(begin, &end, 0); + + if (errno == ERANGE) + { + errno = 0; + unsigned long unsignedError = strtoul(begin, &end, 0); + + if (errno == ERANGE) + { + context.Reporter.Error() << Resource::String::ErrorNumberIsTooLarge << std::endl; + AICLI_TERMINATE_CONTEXT(E_INVALIDARG); + } + + errorNumber = static_cast<HRESULT>(unsignedError); + } + + // If the entire string was consumed as a number, treat it as an HRESULT + if (static_cast<size_t>(end - begin) == input.length()) + { + auto error = Errors::HResultInformation::Find(errorNumber); + if (error) + { + OutputHResultInformation(context, *error); + } + } + // otherwise, treat it as a string and search our error list + else + { + auto errors = Errors::HResultInformation::Find(Utility::Trim(input)); + for (const auto& error : errors) + { + OutputHResultInformation(context, *error); + } + } + } +} diff --git a/src/AppInstallerCLICore/Commands/ErrorCommand.h b/src/AppInstallerCLICore/Commands/ErrorCommand.h @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once +#include "Command.h" + +namespace AppInstaller::CLI +{ + // This command makes it easier to get information on winget errors. + struct ErrorCommand final : public Command + { + ErrorCommand(std::string_view parent) : Command("error", { "err" }, parent, Visibility::Hidden) {} + + std::vector<Argument> GetArguments() const override; + + Resource::LocString ShortDescription() const override; + Resource::LocString LongDescription() const override; + + protected: + void ExecuteInternal(Execution::Context& context) const override; + }; +} diff --git a/src/AppInstallerCLICore/Commands/RootCommand.cpp b/src/AppInstallerCLICore/Commands/RootCommand.cpp @@ -24,6 +24,7 @@ #include "DebugCommand.h" #include "TestCommand.h" #include "DownloadCommand.h" +#include "ErrorCommand.h" #include "Resources.h" #include "TableOutput.h" @@ -180,6 +181,7 @@ namespace AppInstaller::CLI std::make_unique<PinCommand>(FullName()), std::make_unique<ConfigureCommand>(FullName()), std::make_unique<DownloadCommand>(FullName()), + std::make_unique<ErrorCommand>(FullName()), #if _DEBUG std::make_unique<DebugCommand>(FullName()), #endif diff --git a/src/AppInstallerCLICore/ExecutionArgs.h b/src/AppInstallerCLICore/ExecutionArgs.h @@ -106,6 +106,9 @@ namespace AppInstaller::CLI::Execution BlockingPin, PinInstalled, + // Error command + ErrorInput, + // Configuration ConfigurationFile, ConfigurationAcceptWarning, diff --git a/src/AppInstallerCLICore/Resources.h b/src/AppInstallerCLICore/Resources.h @@ -158,6 +158,10 @@ namespace AppInstaller::CLI::Resource WINGET_DEFINE_RESOURCE_STRINGID(Downloading); WINGET_DEFINE_RESOURCE_STRINGID(EnableAdminSettingFailed); WINGET_DEFINE_RESOURCE_STRINGID(EnablingWindowsFeature); + WINGET_DEFINE_RESOURCE_STRINGID(ErrorCommandLongDescription); + WINGET_DEFINE_RESOURCE_STRINGID(ErrorCommandShortDescription); + WINGET_DEFINE_RESOURCE_STRINGID(ErrorInputArgumentDescription); + WINGET_DEFINE_RESOURCE_STRINGID(ErrorNumberIsTooLarge); WINGET_DEFINE_RESOURCE_STRINGID(ExactArgumentDescription); WINGET_DEFINE_RESOURCE_STRINGID(ExperimentalArgumentDescription); WINGET_DEFINE_RESOURCE_STRINGID(ExperimentalCommandLongDescription); diff --git a/src/AppInstallerCLIE2ETests/Constants.cs b/src/AppInstallerCLIE2ETests/Constants.cs @@ -138,6 +138,7 @@ namespace AppInstallerCLIE2ETests public const int S_FALSE = 1; public const int ERROR_FILE_NOT_FOUND = unchecked((int)0x80070002); public const int ERROR_PATH_NOT_FOUND = unchecked((int)0x80070003); + public const int E_INVALIDARG = unchecked((int)0x80070057); public const int ERROR_NO_RANGES_PROCESSED = unchecked((int)0x80070138); public const int OPC_E_ZIP_MISSING_END_OF_CENTRAL_DIRECTORY = unchecked((int)0x8051100F); public const int ERROR_OLD_WIN_VERSION = unchecked((int)0x8007047E); diff --git a/src/AppInstallerCLIE2ETests/ErrorCommand.cs b/src/AppInstallerCLIE2ETests/ErrorCommand.cs @@ -0,0 +1,130 @@ +// ----------------------------------------------------------------------------- +// <copyright file="ErrorCommand.cs" company="Microsoft Corporation"> +// Copyright (c) Microsoft Corporation. Licensed under the MIT License. +// </copyright> +// ----------------------------------------------------------------------------- + +namespace AppInstallerCLIE2ETests +{ + using AppInstallerCLIE2ETests.Helpers; + using NUnit.Framework; + + /// <summary> + /// Test error command. + /// </summary> + public class ErrorCommand + { + /// <summary> + /// Tests 0. + /// </summary> + [Test] + public void Success() + { + var result = TestCommon.RunAICLICommand("error", "0"); + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("0x00000000")); + } + + /// <summary> + /// Tests 0x8a15c001. + /// </summary> + [Test] + public void HexError() + { + var result = TestCommon.RunAICLICommand("error", "0x8a15c001"); + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("0x8a15c001")); + Assert.True(result.StdOut.Contains("WINGET_CONFIG_ERROR_INVALID_CONFIGURATION_FILE")); + } + + /// <summary> + /// Tests a number larger than an HRESULT. + /// </summary> + [Test] + public void HexErrorTooBig() + { + var result = TestCommon.RunAICLICommand("error", "0x8a15c0014"); + Assert.AreEqual(Constants.ErrorCode.E_INVALIDARG, result.ExitCode); + Assert.True(result.StdOut.Contains("The given number is too large to be an HRESULT.")); + } + + /// <summary> + /// Tests 2316681217. + /// </summary> + [Test] + public void DecimalError() + { + var result = TestCommon.RunAICLICommand("error", "2316681217"); + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("0x8a15c001")); + Assert.True(result.StdOut.Contains("WINGET_CONFIG_ERROR_INVALID_CONFIGURATION_FILE")); + } + + /// <summary> + /// Tests -1978335191. + /// </summary> + [Test] + public void NegativeDecimalError() + { + var result = TestCommon.RunAICLICommand("error", "-- -1978335191"); + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("0x8a150029")); + Assert.True(result.StdOut.Contains("APPINSTALLER_CLI_ERROR_MANIFEST_VALIDATION_FAILURE")); + } + + /// <summary> + /// Tests 0x8a15c000. + /// </summary> + [Test] + public void HexErrorNotFound() + { + var result = TestCommon.RunAICLICommand("error", "0x8a15c000"); + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("0x8a15c000")); + Assert.True(result.StdOut.Contains("Unknown error code")); + } + + /// <summary> + /// Tests 0xA150202. + /// </summary> + [Test] + public void NonError() + { + var result = TestCommon.RunAICLICommand("error", "0xA150202"); + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("0x0a150202")); + Assert.True(result.StdOut.Contains("WINGET_INSTALLED_STATUS_INSTALL_LOCATION_NOT_APPLICABLE")); + } + + /// <summary> + /// Tests WINGET_CONFIG_ERROR_INVALID_CONFIGURATION_FILE. + /// </summary> + [Test] + public void Symbol() + { + var result = TestCommon.RunAICLICommand("error", "WINGET_CONFIG_ERROR_INVALID_CONFIGURATION_FILE"); + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("0x8a15c001")); + Assert.True(result.StdOut.Contains("WINGET_CONFIG_ERROR_INVALID_CONFIGURATION_FILE")); + Assert.AreEqual(2, result.StdOut.Split('\n', System.StringSplitOptions.RemoveEmptyEntries).Length); + } + + /// <summary> + /// Tests config. + /// </summary> + [Test] + public void String() + { + var result = TestCommon.RunAICLICommand("error", "config"); + Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode); + Assert.True(result.StdOut.Contains("0x8a15c001")); + Assert.True(result.StdOut.Contains("WINGET_CONFIG_ERROR_INVALID_CONFIGURATION_FILE")); + Assert.True(result.StdOut.Contains("0x8a15c110")); + Assert.True(result.StdOut.Contains("WINGET_CONFIG_ERROR_UNIT_SETTING_CONFIG_ROOT")); + + // This contains config in it's message. + Assert.True(result.StdOut.Contains("0x8a150038")); + Assert.True(result.StdOut.Contains("APPINSTALLER_CLI_ERROR_UNSUPPORTED_RESTSOURCE")); + } + } +}+ \ No newline at end of file diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw @@ -2083,4 +2083,502 @@ Please specify one of them using the --source option to proceed.</value> <data name="PolicyEnableWinGetConfiguration" xml:space="preserve"> <value>Enable Windows Package Manager Configuration</value> </data> + <data name="ErrorCommandLongDescription" xml:space="preserve"> + <value>Retrieve information about errors. Given a number, the output will contain details about the error, including the symbol name if it is a winget specific error. Given a string, the winget specific errors are searched for this value.</value> + </data> + <data name="ErrorCommandShortDescription" xml:space="preserve"> + <value>Get information on errors</value> + </data> + <data name="ErrorInputArgumentDescription" xml:space="preserve"> + <value>A value to search within the error information</value> + </data> + <data name="ErrorNumberIsTooLarge" xml:space="preserve"> + <value>The given number is too large to be an HRESULT.</value> + </data> + <data name="UnknownErrorCode" xml:space="preserve"> + <value>Unknown error code</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INTERNAL_ERROR" xml:space="preserve"> + <value>Internal Error</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS" xml:space="preserve"> + <value>Invalid command line arguments</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_COMMAND_FAILED" xml:space="preserve"> + <value>Executing command failed</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_MANIFEST_FAILED" xml:space="preserve"> + <value>Opening manifest failed</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_CTRL_SIGNAL_RECEIVED" xml:space="preserve"> + <value>Cancellation signal received</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_SHELLEXEC_INSTALL_FAILED" xml:space="preserve"> + <value>Running ShellExecute failed</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_UNSUPPORTED_MANIFESTVERSION" xml:space="preserve"> + <value>Cannot process manifest. The manifest version is higher than supported. Please update the client.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_DOWNLOAD_FAILED" xml:space="preserve"> + <value>Downloading installer failed</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_CANNOT_WRITE_TO_UPLEVEL_INDEX" xml:space="preserve"> + <value>Cannot write to index; it is a higher schema version</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INDEX_INTEGRITY_COMPROMISED" xml:space="preserve"> + <value>The index is corrupt</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_SOURCES_INVALID" xml:space="preserve"> + <value>The configured source information is corrupt</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_SOURCE_NAME_ALREADY_EXISTS" xml:space="preserve"> + <value>The source name is already configured</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INVALID_SOURCE_TYPE" xml:space="preserve"> + <value>The source type is invalid</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_PACKAGE_IS_BUNDLE" xml:space="preserve"> + <value>The MSIX file is a bundle, not a package</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_SOURCE_DATA_MISSING" xml:space="preserve"> + <value>Data required by the source is missing</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_NO_APPLICABLE_INSTALLER" xml:space="preserve"> + <value>None of the installers are applicable for the current system</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALLER_HASH_MISMATCH" xml:space="preserve"> + <value>The installer file's hash does not match the manifest</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST" xml:space="preserve"> + <value>The source name does not exist</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_SOURCE_ARG_ALREADY_EXISTS" xml:space="preserve"> + <value>The source location is already configured under another name</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_NO_APPLICATIONS_FOUND" xml:space="preserve"> + <value>No packages found</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_NO_SOURCES_DEFINED" xml:space="preserve"> + <value>No sources are configured</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_MULTIPLE_APPLICATIONS_FOUND" xml:space="preserve"> + <value>Multiple packages found matching the criteria</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_NO_MANIFEST_FOUND" xml:space="preserve"> + <value>No manifest found matching the criteria</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_EXTENSION_PUBLIC_FAILED" xml:space="preserve"> + <value>Failed to get Public folder from source package</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN" xml:space="preserve"> + <value>Command requires administrator privileges to run</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_SOURCE_NOT_SECURE" xml:space="preserve"> + <value>The source location is not secure</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_MSSTORE_BLOCKED_BY_POLICY" xml:space="preserve"> + <value>The Microsoft Store client is blocked by policy</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_MSSTORE_APP_BLOCKED_BY_POLICY" xml:space="preserve"> + <value>The Microsoft Store app is blocked by policy</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_EXPERIMENTAL_FEATURE_DISABLED" xml:space="preserve"> + <value>The feature is currently under development. It can be enabled using winget settings.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_MSSTORE_INSTALL_FAILED" xml:space="preserve"> + <value>Failed to install the Microsoft Store app</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_COMPLETE_INPUT_BAD" xml:space="preserve"> + <value>Failed to perform auto complete</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_YAML_INIT_FAILED" xml:space="preserve"> + <value>Failed to initialize YAML parser</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_YAML_INVALID_MAPPING_KEY" xml:space="preserve"> + <value>Encountered an invalid YAML key</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_YAML_DUPLICATE_MAPPING_KEY" xml:space="preserve"> + <value>Encountered a duplicate YAML key</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_YAML_INVALID_OPERATION" xml:space="preserve"> + <value>Invalid YAML operation</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_YAML_DOC_BUILD_FAILED" xml:space="preserve"> + <value>Failed to build YAML doc</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_YAML_INVALID_EMITTER_STATE" xml:space="preserve"> + <value>Invalid YAML emitter state</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_YAML_INVALID_DATA" xml:space="preserve"> + <value>Invalid YAML data</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_LIBYAML_ERROR" xml:space="preserve"> + <value>LibYAML error</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_MANIFEST_VALIDATION_WARNING" xml:space="preserve"> + <value>Manifest validation succeeded with warning</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_MANIFEST_VALIDATION_FAILURE" xml:space="preserve"> + <value>Manifest validation failed</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INVALID_MANIFEST" xml:space="preserve"> + <value>Manifest is invalid</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE" xml:space="preserve"> + <value>No applicable update found</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_UPDATE_ALL_HAS_FAILURE" xml:space="preserve"> + <value>winget upgrade --all completed with failures</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALLER_SECURITY_CHECK_FAILED" xml:space="preserve"> + <value>Installer failed security check</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_DOWNLOAD_SIZE_MISMATCH" xml:space="preserve"> + <value>Download size does not match expected content length</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_NO_UNINSTALL_INFO_FOUND" xml:space="preserve"> + <value>Uninstall command not found</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_EXEC_UNINSTALL_COMMAND_FAILED" xml:space="preserve"> + <value>Running uninstall command failed</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_ICU_BREAK_ITERATOR_ERROR" xml:space="preserve"> + <value>ICU break iterator error</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_ICU_CASEMAP_ERROR" xml:space="preserve"> + <value>ICU casemap error</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_ICU_REGEX_ERROR" xml:space="preserve"> + <value>ICU regex error</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_IMPORT_INSTALL_FAILED" xml:space="preserve"> + <value>Failed to install one or more imported packages</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_NOT_ALL_PACKAGES_FOUND" xml:space="preserve"> + <value>Could not find one or more requested packages</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_JSON_INVALID_FILE" xml:space="preserve"> + <value>Json file is invalid</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_SOURCE_NOT_REMOTE" xml:space="preserve"> + <value>The source location is not remote</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_UNSUPPORTED_RESTSOURCE" xml:space="preserve"> + <value>The configured rest source is not supported</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_DATA" xml:space="preserve"> + <value>Invalid data returned by rest source</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY" xml:space="preserve"> + <value>Operation is blocked by Group Policy</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_RESTSOURCE_INTERNAL_ERROR" xml:space="preserve"> + <value>Rest source internal error</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_URL" xml:space="preserve"> + <value>Invalid rest source url</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_RESTSOURCE_UNSUPPORTED_MIME_TYPE" xml:space="preserve"> + <value>Unsupported MIME type returned by rest source</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_VERSION" xml:space="preserve"> + <value>Invalid rest source contract version</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_SOURCE_DATA_INTEGRITY_FAILURE" xml:space="preserve"> + <value>The source data is corrupted or tampered</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_STREAM_READ_FAILURE" xml:space="preserve"> + <value>Error reading from the stream</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_PACKAGE_AGREEMENTS_NOT_ACCEPTED" xml:space="preserve"> + <value>Package agreements were not agreed to</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_PROMPT_INPUT_ERROR" xml:space="preserve"> + <value>Error reading input in prompt</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_UNSUPPORTED_SOURCE_REQUEST" xml:space="preserve"> + <value>The search request is not supported by one or more sources</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_RESTSOURCE_ENDPOINT_NOT_FOUND" xml:space="preserve"> + <value>The rest source endpoint is not found.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED" xml:space="preserve"> + <value>Failed to open the source.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED" xml:space="preserve"> + <value>Source agreements were not agreed to</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_CUSTOMHEADER_EXCEEDS_MAXLENGTH" xml:space="preserve"> + <value>Header size exceeds the allowable limit of 1024 characters. Please reduce the size and try again.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_MISSING_RESOURCE_FILE" xml:space="preserve"> + <value>Missing resource file</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_MSI_INSTALL_FAILED" xml:space="preserve"> + <value>Running MSI install failed</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INVALID_MSIEXEC_ARGUMENT" xml:space="preserve"> + <value>Arguments for msiexec are invalid</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_FAILED_TO_OPEN_ALL_SOURCES" xml:space="preserve"> + <value>Failed to open one or more sources</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_DEPENDENCIES_VALIDATION_FAILED" xml:space="preserve"> + <value>Failed to validate dependencies</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_MISSING_PACKAGE" xml:space="preserve"> + <value>One or more package is missing</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INVALID_TABLE_COLUMN" xml:space="preserve"> + <value>Invalid table column</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_NOT_NEWER" xml:space="preserve"> + <value>The upgrade version is not newer than the installed version</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_UNKNOWN" xml:space="preserve"> + <value>Upgrade version is unknown and override is not specified</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_ICU_CONVERSION_ERROR" xml:space="preserve"> + <value>ICU conversion error</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_PORTABLE_INSTALL_FAILED" xml:space="preserve"> + <value>Failed to install portable package</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_PORTABLE_REPARSE_POINT_NOT_SUPPORTED" xml:space="preserve"> + <value>Volume does not support reparse points</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_PORTABLE_PACKAGE_ALREADY_EXISTS" xml:space="preserve"> + <value>Portable package from a different source already exists.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_PORTABLE_SYMLINK_PATH_IS_DIRECTORY" xml:space="preserve"> + <value>Unable to create symlink, path points to a directory.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALLER_PROHIBITS_ELEVATION" xml:space="preserve"> + <value>The installer cannot be run from an administrator context.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_PORTABLE_UNINSTALL_FAILED" xml:space="preserve"> + <value>Failed to uninstall portable package</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_ARP_VERSION_VALIDATION_FAILED" xml:space="preserve"> + <value>Failed to validate DisplayVersion values against index.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_UNSUPPORTED_ARGUMENT" xml:space="preserve"> + <value>One or more arguments are not supported.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_BIND_WITH_EMBEDDED_NULL" xml:space="preserve"> + <value>Embedded null characters are disallowed for SQLite</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_NESTEDINSTALLER_NOT_FOUND" xml:space="preserve"> + <value>Failed to find the nested installer in the archive.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_EXTRACT_ARCHIVE_FAILED" xml:space="preserve"> + <value>Failed to extract archive.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_NESTEDINSTALLER_INVALID_PATH" xml:space="preserve"> + <value>Invalid relative file path to nested installer provided.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_PINNED_CERTIFICATE_MISMATCH" xml:space="preserve"> + <value>The server certificate did not match any of the expected values.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_LOCATION_REQUIRED" xml:space="preserve"> + <value>Install location must be provided.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_ARCHIVE_SCAN_FAILED" xml:space="preserve"> + <value>Archive malware scan failed.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_PACKAGE_ALREADY_INSTALLED" xml:space="preserve"> + <value>Found at least one version of the package installed.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_PIN_ALREADY_EXISTS" xml:space="preserve"> + <value>A pin already exists for the package.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_PIN_DOES_NOT_EXIST" xml:space="preserve"> + <value>There is no pin for the package.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_CANNOT_OPEN_PINNING_INDEX" xml:space="preserve"> + <value>Unable to open the pin database.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_MULTIPLE_INSTALL_FAILED" xml:space="preserve"> + <value>One or more applications failed to install</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_MULTIPLE_UNINSTALL_FAILED" xml:space="preserve"> + <value>One or more applications failed to uninstall</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_NOT_ALL_QUERIES_FOUND_SINGLE" xml:space="preserve"> + <value>One or more queries did not return exactly one match</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_PACKAGE_IS_PINNED" xml:space="preserve"> + <value>The package has a pin that prevents upgrade.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_PACKAGE_IS_STUB" xml:space="preserve"> + <value>The package currently installed is the stub package</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_APPTERMINATION_RECEIVED" xml:space="preserve"> + <value>Application shutdown signal received</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_DOWNLOAD_DEPENDENCIES" xml:space="preserve"> + <value>Failed to download package dependencies.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_DOWNLOAD_COMMAND_PROHIBITED" xml:space="preserve"> + <value>Failed to download package. Download for offline installation is prohibited.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_PACKAGE_IN_USE" xml:space="preserve"> + <value>Application is currently running. Exit the application then try again.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_INSTALL_IN_PROGRESS" xml:space="preserve"> + <value>Another installation is already in progress. Try again later.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_FILE_IN_USE" xml:space="preserve"> + <value>One or more file is being used. Exit the application then try again.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_MISSING_DEPENDENCY" xml:space="preserve"> + <value>This package has a dependency missing from your system.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_DISK_FULL" xml:space="preserve"> + <value>There's no more space on your PC. Make space, then try again.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_INSUFFICIENT_MEMORY" xml:space="preserve"> + <value>There's not enough memory available to install. Close other applications then try again.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_NO_NETWORK" xml:space="preserve"> + <value>This application requires internet connectivity. Connect to a network then try again.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_CONTACT_SUPPORT" xml:space="preserve"> + <value>This application encountered an error during installation. Contact support.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_REQUIRED_TO_FINISH" xml:space="preserve"> + <value>Restart your PC to finish installation.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_REQUIRED_TO_INSTALL" xml:space="preserve"> + <value>Installation failed. Restart your PC then try again.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_INITIATED" xml:space="preserve"> + <value>Your PC will restart to finish installation.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_CANCELLED_BY_USER" xml:space="preserve"> + <value>You cancelled the installation.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_ALREADY_INSTALLED" xml:space="preserve"> + <value>Another version of this application is already installed.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_DOWNGRADE" xml:space="preserve"> + <value>A higher version of this application is already installed.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_BLOCKED_BY_POLICY" xml:space="preserve"> + <value>Organization policies are preventing installation. Contact your admin.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_DEPENDENCIES" xml:space="preserve"> + <value>Failed to install package dependencies.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_PACKAGE_IN_USE_BY_APPLICATION" xml:space="preserve"> + <value>Application is currently in use by another application.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_INVALID_PARAMETER" xml:space="preserve"> + <value>Invalid parameter.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_SYSTEM_NOT_SUPPORTED" xml:space="preserve"> + <value>Package not supported by the system.</value> + </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_UPGRADE_NOT_SUPPORTED" xml:space="preserve"> + <value>The installer does not support upgrading an existing package.</value> + </data> + <data name="WINGET_INSTALLED_STATUS_ARP_ENTRY_NOT_FOUND" xml:space="preserve"> + <value>The Apps and Features Entry for the package could not be found.</value> + </data> + <data name="WINGET_INSTALLED_STATUS_INSTALL_LOCATION_NOT_APPLICABLE" xml:space="preserve"> + <value>The install location is not applicable.</value> + </data> + <data name="WINGET_INSTALLED_STATUS_INSTALL_LOCATION_NOT_FOUND" xml:space="preserve"> + <value>The install location could not be found.</value> + </data> + <data name="WINGET_INSTALLED_STATUS_FILE_HASH_MISMATCH" xml:space="preserve"> + <value>The hash of the existing file did not match.</value> + </data> + <data name="WINGET_INSTALLED_STATUS_FILE_NOT_FOUND" xml:space="preserve"> + <value>File not found.</value> + </data> + <data name="WINGET_INSTALLED_STATUS_FILE_FOUND_WITHOUT_HASH_CHECK" xml:space="preserve"> + <value>The file was found but the hash was not checked.</value> + </data> + <data name="WINGET_INSTALLED_STATUS_FILE_ACCESS_ERROR" xml:space="preserve"> + <value>The file could not be accessed.</value> + </data> + <data name="WINGET_CONFIG_ERROR_INVALID_CONFIGURATION_FILE" xml:space="preserve"> + <value>The configuration file is invalid.</value> + </data> + <data name="WINGET_CONFIG_ERROR_INVALID_YAML" xml:space="preserve"> + <value>The YAML syntax is invalid.</value> + </data> + <data name="WINGET_CONFIG_ERROR_INVALID_FIELD_TYPE" xml:space="preserve"> + <value>A configuration field has an invalid type.</value> + </data> + <data name="WINGET_CONFIG_ERROR_UNKNOWN_CONFIGURATION_FILE_VERSION" xml:space="preserve"> + <value>The configuration has an unknown version.</value> + </data> + <data name="WINGET_CONFIG_ERROR_SET_APPLY_FAILED" xml:space="preserve"> + <value>An error occurred while applying the configuration.</value> + </data> + <data name="WINGET_CONFIG_ERROR_DUPLICATE_IDENTIFIER" xml:space="preserve"> + <value>The configuration contains a duplicate identifier.</value> + </data> + <data name="WINGET_CONFIG_ERROR_MISSING_DEPENDENCY" xml:space="preserve"> + <value>The configuration is missing a dependency.</value> + </data> + <data name="WINGET_CONFIG_ERROR_DEPENDENCY_UNSATISFIED" xml:space="preserve"> + <value>The configuration has an unsatisfied dependency.</value> + </data> + <data name="WINGET_CONFIG_ERROR_ASSERTION_FAILED" xml:space="preserve"> + <value>An assertion for the configuration unit failed.</value> + </data> + <data name="WINGET_CONFIG_ERROR_MANUALLY_SKIPPED" xml:space="preserve"> + <value>The configuration was manually skipped.</value> + </data> + <data name="WINGET_CONFIG_ERROR_WARNING_NOT_ACCEPTED" xml:space="preserve"> + <value>The user declined to continue execution.</value> + </data> + <data name="WINGET_CONFIG_ERROR_SET_DEPENDENCY_CYCLE" xml:space="preserve"> + <value>The dependency graph contains a cycle which cannot be resolved.</value> + </data> + <data name="WINGET_CONFIG_ERROR_INVALID_FIELD_VALUE" xml:space="preserve"> + <value>The configuration has an invalid field value.</value> + </data> + <data name="WINGET_CONFIG_ERROR_MISSING_FIELD" xml:space="preserve"> + <value>The configuration is missing a field.</value> + </data> + <data name="WINGET_CONFIG_ERROR_TEST_FAILED" xml:space="preserve"> + <value>Some of the configuration units failed while testing their state.</value> + </data> + <data name="WINGET_CONFIG_ERROR_TEST_NOT_RUN" xml:space="preserve"> + <value>Configuration state was not tested.</value> + </data> + <data name="WINGET_CONFIG_ERROR_UNIT_NOT_INSTALLED" xml:space="preserve"> + <value>The configuration unit was not installed.</value> + </data> + <data name="WINGET_CONFIG_ERROR_UNIT_NOT_FOUND_REPOSITORY" xml:space="preserve"> + <value>The configuration unit could not be found.</value> + </data> + <data name="WINGET_CONFIG_ERROR_UNIT_MULTIPLE_MATCHES" xml:space="preserve"> + <value>Multiple matches were found for the configuration unit; specify the module to select the correct one.</value> + </data> + <data name="WINGET_CONFIG_ERROR_UNIT_INVOKE_GET" xml:space="preserve"> + <value>The configuration unit failed while attempting to get the current system state.</value> + </data> + <data name="WINGET_CONFIG_ERROR_UNIT_INVOKE_TEST" xml:space="preserve"> + <value>The configuration unit failed while attempting to test the current system state.</value> + </data> + <data name="WINGET_CONFIG_ERROR_UNIT_INVOKE_SET" xml:space="preserve"> + <value>The configuration unit failed while attempting to apply the desired state.</value> + </data> + <data name="WINGET_CONFIG_ERROR_UNIT_MODULE_CONFLICT" xml:space="preserve"> + <value>The module for the configuration unit is available in multiple locations with the same version.</value> + </data> + <data name="WINGET_CONFIG_ERROR_UNIT_IMPORT_MODULE" xml:space="preserve"> + <value>Loading the module for the configuration unit failed.</value> + </data> + <data name="WINGET_CONFIG_ERROR_UNIT_INVOKE_INVALID_RESULT" xml:space="preserve"> + <value>The configuration unit returned an unexpected result during execution.</value> + </data> + <data name="WINGET_CONFIG_ERROR_UNIT_SETTING_CONFIG_ROOT" xml:space="preserve"> + <value>A unit contains a setting that requires the config root.</value> + </data> </root> \ No newline at end of file diff --git a/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj b/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj @@ -206,6 +206,7 @@ <ClCompile Include="Dependencies.cpp" /> <ClCompile Include="Downloader.cpp" /> <ClCompile Include="DownloadFlow.cpp" /> + <ClCompile Include="Errors.cpp" /> <ClCompile Include="ExperimentalFeature.cpp" /> <ClCompile Include="ExportFlow.cpp" /> <ClCompile Include="Filesystem.cpp" /> diff --git a/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj.filters b/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj.filters @@ -314,6 +314,9 @@ <ClCompile Include="DownloadFlow.cpp"> <Filter>Source Files\CLI</Filter> </ClCompile> + <ClCompile Include="Errors.cpp"> + <Filter>Source Files\Common</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <None Include="PropertySheet.props" /> diff --git a/src/AppInstallerCLITests/Errors.cpp b/src/AppInstallerCLITests/Errors.cpp @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "TestCommon.h" +#include <AppInstallerErrors.h> + +using namespace AppInstaller; +using namespace AppInstaller::Utility; +using namespace std::string_literals; + +TEST_CASE("EnsureSortedErrorList", "[errors]") +{ + auto errors = Errors::GetWinGetErrors(); + for (size_t i = 1; i < errors.size(); ++i) + { + INFO(errors[i - 1]->Symbol() << " then " << errors[i]->Symbol()); + REQUIRE(errors[i]->Value() > errors[i - 1]->Value()); + } +} diff --git a/src/AppInstallerCLITests/Filesystem.cpp b/src/AppInstallerCLITests/Filesystem.cpp @@ -72,9 +72,11 @@ TEST_CASE("VerifyIsSameVolume", "[filesystem]") std::filesystem::path path9 = L"a"; std::filesystem::path path10 = L"b"; - // Verify that a relative path points to the current volume. REQUIRE(IsSameVolume(path1, path2)); - REQUIRE(IsSameVolume(path5, path7)); + if (IsSameVolume(path5, path5)) + { + REQUIRE(IsSameVolume(path5, path7)); + } REQUIRE(IsSameVolume(path3, path4)); REQUIRE(IsSameVolume(path9, path10)); diff --git a/src/AppInstallerCommonCore/Filesystem.cpp b/src/AppInstallerCommonCore/Filesystem.cpp @@ -253,6 +253,6 @@ namespace AppInstaller::Filesystem { return false; } - return Utility::CaseInsensitiveEquals(Utility::ConvertToUTF8(volumeName1), Utility::ConvertToUTF8(volumeName2)); + return Utility::ICUCaseInsensitiveEquals(Utility::ConvertToUTF8(volumeName1), Utility::ConvertToUTF8(volumeName2)); } } \ No newline at end of file diff --git a/src/AppInstallerSharedLib/Errors.cpp b/src/AppInstallerSharedLib/Errors.cpp @@ -4,348 +4,281 @@ #include "Public/AppInstallerErrors.h" #include "Public/AppInstallerLogging.h" #include "Public/AppInstallerStrings.h" +#include "Public/winget/Resources.h" namespace AppInstaller { namespace { - const char* GetMessageForAppInstallerHR(HRESULT hr) + // A simple struct to hold the data + struct WinGetHResultData { - switch (hr) + HRESULT Value; + std::string_view Symbol; + std::string_view Description; + + bool operator<(const WinGetHResultData& other) const { - case APPINSTALLER_CLI_ERROR_INTERNAL_ERROR: - return "Internal Error"; - case APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS: - return "Invalid command line arguments"; - case APPINSTALLER_CLI_ERROR_COMMAND_FAILED: - return "Executing command failed"; - case APPINSTALLER_CLI_ERROR_MANIFEST_FAILED: - return "Opening manifest failed"; - case APPINSTALLER_CLI_ERROR_CTRL_SIGNAL_RECEIVED: - return "Cancellation signal received"; - case APPINSTALLER_CLI_ERROR_SHELLEXEC_INSTALL_FAILED: - return "Running ShellExecute failed"; - case APPINSTALLER_CLI_ERROR_UNSUPPORTED_MANIFESTVERSION: - return "Cannot process manifest. The manifest version is higher than supported. Please update the client."; - case APPINSTALLER_CLI_ERROR_DOWNLOAD_FAILED: - return "Downloading installer failed"; - case APPINSTALLER_CLI_ERROR_CANNOT_WRITE_TO_UPLEVEL_INDEX: - return "Cannot write to index; it is a higher schema version"; - case APPINSTALLER_CLI_ERROR_INDEX_INTEGRITY_COMPROMISED: - return "The index is corrupt"; - case APPINSTALLER_CLI_ERROR_SOURCES_INVALID: - return "The configured source information is corrupt"; - case APPINSTALLER_CLI_ERROR_SOURCE_NAME_ALREADY_EXISTS: - return "The source name is already configured"; - case APPINSTALLER_CLI_ERROR_INVALID_SOURCE_TYPE: - return "The source type is invalid"; - case APPINSTALLER_CLI_ERROR_PACKAGE_IS_BUNDLE: - return "The MSIX file is a bundle, not a package"; - case APPINSTALLER_CLI_ERROR_SOURCE_DATA_MISSING: - return "Data required by the source is missing"; - case APPINSTALLER_CLI_ERROR_NO_APPLICABLE_INSTALLER: - return "None of the installers are applicable for the current system"; - case APPINSTALLER_CLI_ERROR_INSTALLER_HASH_MISMATCH: - return "The installer file's hash does not match the manifest"; - case APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST: - return "The source name does not exist"; - case APPINSTALLER_CLI_ERROR_SOURCE_ARG_ALREADY_EXISTS: - return "The source location is already configured under another name"; - case APPINSTALLER_CLI_ERROR_NO_APPLICATIONS_FOUND: - return "No packages found"; - case APPINSTALLER_CLI_ERROR_NO_SOURCES_DEFINED: - return "No sources are configured"; - case APPINSTALLER_CLI_ERROR_MULTIPLE_APPLICATIONS_FOUND: - return "Multiple packages found matching the criteria"; - case APPINSTALLER_CLI_ERROR_NO_MANIFEST_FOUND: - return "No manifest found matching the criteria"; - case APPINSTALLER_CLI_ERROR_EXTENSION_PUBLIC_FAILED: - return "Failed to get Public folder from source package"; - case APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN: - return "Command requires administrator privileges to run"; - case APPINSTALLER_CLI_ERROR_SOURCE_NOT_SECURE: - return "The source location is not secure"; - case APPINSTALLER_CLI_ERROR_MSSTORE_BLOCKED_BY_POLICY: - return "The Microsoft Store client is blocked by policy"; - case APPINSTALLER_CLI_ERROR_MSSTORE_APP_BLOCKED_BY_POLICY: - return "The Microsoft Store app is blocked by policy"; - case APPINSTALLER_CLI_ERROR_EXPERIMENTAL_FEATURE_DISABLED: - return "The feature is currently under development. It can be enabled using winget settings."; - case APPINSTALLER_CLI_ERROR_MSSTORE_INSTALL_FAILED: - return "Failed to install the Microsoft Store app"; - case APPINSTALLER_CLI_ERROR_COMPLETE_INPUT_BAD: - return "Failed to perform auto complete"; - case APPINSTALLER_CLI_ERROR_YAML_INIT_FAILED: - return "Failed to initialize YAML parser"; - case APPINSTALLER_CLI_ERROR_YAML_INVALID_MAPPING_KEY: - return "Encountered an invalid YAML key"; - case APPINSTALLER_CLI_ERROR_YAML_DUPLICATE_MAPPING_KEY: - return "Encountered a duplicate YAML key"; - case APPINSTALLER_CLI_ERROR_YAML_INVALID_OPERATION: - return "Invalid YAML operation"; - case APPINSTALLER_CLI_ERROR_YAML_DOC_BUILD_FAILED: - return "Failed to build YAML doc"; - case APPINSTALLER_CLI_ERROR_YAML_INVALID_EMITTER_STATE: - return "Invalid YAML emitter state"; - case APPINSTALLER_CLI_ERROR_YAML_INVALID_DATA: - return "Invalid YAML data"; - case APPINSTALLER_CLI_ERROR_LIBYAML_ERROR: - return "LibYAML error"; - case APPINSTALLER_CLI_ERROR_MANIFEST_VALIDATION_WARNING: - return "Manifest validation succeeded with warning"; - case APPINSTALLER_CLI_ERROR_MANIFEST_VALIDATION_FAILURE: - return "Manifest validation failed"; - case APPINSTALLER_CLI_ERROR_INVALID_MANIFEST: - return "Manifest is invalid"; - case APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE: - return "No applicable update found"; - case APPINSTALLER_CLI_ERROR_UPDATE_ALL_HAS_FAILURE: - return "winget upgrade --all completed with failures"; - case APPINSTALLER_CLI_ERROR_INSTALLER_SECURITY_CHECK_FAILED: - return "Installer failed security check"; - case APPINSTALLER_CLI_ERROR_DOWNLOAD_SIZE_MISMATCH: - return "Download size does not match expected content length"; - case APPINSTALLER_CLI_ERROR_NO_UNINSTALL_INFO_FOUND: - return "Uninstall command not found"; - case APPINSTALLER_CLI_ERROR_EXEC_UNINSTALL_COMMAND_FAILED: - return "Running uninstall command failed"; - case APPINSTALLER_CLI_ERROR_ICU_BREAK_ITERATOR_ERROR: - return "ICU break iterator error"; - case APPINSTALLER_CLI_ERROR_ICU_CASEMAP_ERROR: - return "ICU casemap error"; - case APPINSTALLER_CLI_ERROR_ICU_REGEX_ERROR: - return "ICU regex error"; - case APPINSTALLER_CLI_ERROR_IMPORT_INSTALL_FAILED: - return "Failed to install one or more imported packages"; - case APPINSTALLER_CLI_ERROR_NOT_ALL_PACKAGES_FOUND: - return "Could not find one or more requested packages"; - case APPINSTALLER_CLI_ERROR_JSON_INVALID_FILE: - return "Json file is invalid"; - case APPINSTALLER_CLI_ERROR_SOURCE_NOT_REMOTE: - return "The source location is not remote"; - case APPINSTALLER_CLI_ERROR_UNSUPPORTED_RESTSOURCE: - return "The configured rest source is not supported"; - case APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_DATA: - return "Invalid data returned by rest source"; - case APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY: - return "Operation is blocked by Group Policy"; - case APPINSTALLER_CLI_ERROR_RESTSOURCE_INTERNAL_ERROR: - return "Rest source internal error"; - case APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_URL: - return "Invalid rest source url"; - case APPINSTALLER_CLI_ERROR_RESTSOURCE_UNSUPPORTED_MIME_TYPE: - return "Unsupported MIME type returned by rest source"; - case APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_VERSION: - return "Invalid rest source contract version"; - case APPINSTALLER_CLI_ERROR_SOURCE_DATA_INTEGRITY_FAILURE: - return "The source data is corrupted or tampered"; - case APPINSTALLER_CLI_ERROR_STREAM_READ_FAILURE: - return "Error reading from the stream"; - case APPINSTALLER_CLI_ERROR_PACKAGE_AGREEMENTS_NOT_ACCEPTED: - return "Package agreements were not agreed to"; - case APPINSTALLER_CLI_ERROR_PROMPT_INPUT_ERROR: - return "Error reading input in prompt"; - case APPINSTALLER_CLI_ERROR_UNSUPPORTED_SOURCE_REQUEST: - return "The search request is not supported by one or more sources"; - case APPINSTALLER_CLI_ERROR_RESTSOURCE_ENDPOINT_NOT_FOUND: - return "The rest source endpoint is not found."; - case APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED: - return "Failed to open the source."; - case APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED: - return "Source agreements were not agreed to"; - case APPINSTALLER_CLI_ERROR_CUSTOMHEADER_EXCEEDS_MAXLENGTH: - return "Header size exceeds the allowable limit of 1024 characters. Please reduce the size and try again."; - case APPINSTALLER_CLI_ERROR_MISSING_RESOURCE_FILE: - return "Missing resource file"; - case APPINSTALLER_CLI_ERROR_MSI_INSTALL_FAILED: - return "Running MSI install failed"; - case APPINSTALLER_CLI_ERROR_INVALID_MSIEXEC_ARGUMENT: - return "Arguments for msiexec are invalid"; - case APPINSTALLER_CLI_ERROR_FAILED_TO_OPEN_ALL_SOURCES: - return "Failed to open one or more sources"; - case APPINSTALLER_CLI_ERROR_DEPENDENCIES_VALIDATION_FAILED: - return "Failed to validate dependencies"; - case APPINSTALLER_CLI_ERROR_MISSING_PACKAGE: - return "One or more package is missing"; - case APPINSTALLER_CLI_ERROR_INVALID_TABLE_COLUMN: - return "Invalid table column"; - case APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_NOT_NEWER: - return "The upgrade version is not newer than the installed version"; - case APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_UNKNOWN: - return "Upgrade version is unknown and override is not specified"; - case APPINSTALLER_CLI_ERROR_ICU_CONVERSION_ERROR: - return "ICU conversion error"; - case APPINSTALLER_CLI_ERROR_PORTABLE_INSTALL_FAILED: - return "Failed to install portable package"; - case APPINSTALLER_CLI_ERROR_PORTABLE_REPARSE_POINT_NOT_SUPPORTED: - return "Volume does not support reparse points."; - case APPINSTALLER_CLI_ERROR_PORTABLE_PACKAGE_ALREADY_EXISTS: - return "Portable package from a different source already exists."; - case APPINSTALLER_CLI_ERROR_PORTABLE_SYMLINK_PATH_IS_DIRECTORY: - return "Unable to create symlink, path points to a directory."; - case APPINSTALLER_CLI_ERROR_INSTALLER_PROHIBITS_ELEVATION: - return "The installer cannot be run from an administrator context."; - case APPINSTALLER_CLI_ERROR_PORTABLE_UNINSTALL_FAILED: - return "Failed to uninstall portable package"; - case APPINSTALLER_CLI_ERROR_ARP_VERSION_VALIDATION_FAILED: - return "Failed to validate DisplayVersion values against index."; - case APPINSTALLER_CLI_ERROR_UNSUPPORTED_ARGUMENT: - return "One or more arguments are not supported."; - case APPINSTALLER_CLI_ERROR_BIND_WITH_EMBEDDED_NULL: - return "Embedded null characters are disallowed for SQLite"; - case APPINSTALLER_CLI_ERROR_NESTEDINSTALLER_NOT_FOUND: - return "Failed to find the nested installer in the archive."; - case APPINSTALLER_CLI_ERROR_EXTRACT_ARCHIVE_FAILED: - return "Failed to extract archive."; - case APPINSTALLER_CLI_ERROR_NESTEDINSTALLER_INVALID_PATH: - return "Invalid relative file path to nested installer provided."; - case APPINSTALLER_CLI_ERROR_PINNED_CERTIFICATE_MISMATCH: - return "The server certificate did not match any of the expected values."; - case APPINSTALLER_CLI_ERROR_INSTALL_LOCATION_REQUIRED: - return "Install location must be provided."; - case APPINSTALLER_CLI_ERROR_ARCHIVE_SCAN_FAILED: - return "Archive malware scan failed."; - case APPINSTALLER_CLI_ERROR_PACKAGE_ALREADY_INSTALLED: - return "Found at least one version of the package installed."; - case APPINSTALLER_CLI_ERROR_PIN_ALREADY_EXISTS: - return "A pin already exists for the package."; - case APPINSTALLER_CLI_ERROR_PIN_DOES_NOT_EXIST: - return "There is no pin for the package."; - case APPINSTALLER_CLI_ERROR_CANNOT_OPEN_PINNING_INDEX: - return "Unable to open the pin database."; - case APPINSTALLER_CLI_ERROR_MULTIPLE_INSTALL_FAILED: - return "One or more applications failed to install"; - case APPINSTALLER_CLI_ERROR_MULTIPLE_UNINSTALL_FAILED: - return "One or more applications failed to uninstall"; - case APPINSTALLER_CLI_ERROR_NOT_ALL_QUERIES_FOUND_SINGLE: - return "One or more queries did not return exactly one match"; - case APPINSTALLER_CLI_ERROR_PACKAGE_IS_PINNED: - return "The package has a pin that prevents upgrade."; - case APPINSTALLER_CLI_ERROR_PACKAGE_IS_STUB: - return "The package currently installed is the stub package"; - case APPINSTALLER_CLI_ERROR_APPTERMINATION_RECEIVED: - return "Application shutdown signal received"; - case APPINSTALLER_CLI_ERROR_DOWNLOAD_DEPENDENCIES: - return "Failed to download package dependencies."; - case APPINSTALLER_CLI_ERROR_DOWNLOAD_COMMAND_PROHIBITED: - return "Failed to download package. Download for offline installation is prohibited."; - - // Install errors - case APPINSTALLER_CLI_ERROR_INSTALL_PACKAGE_IN_USE: - return "Application is currently running. Exit the application then try again."; - case APPINSTALLER_CLI_ERROR_INSTALL_INSTALL_IN_PROGRESS: - return "Another installation is already in progress. Try again later."; - case APPINSTALLER_CLI_ERROR_INSTALL_FILE_IN_USE: - return "One or more file is being used. Exit the application then try again."; - case APPINSTALLER_CLI_ERROR_INSTALL_MISSING_DEPENDENCY: - return "This package has a dependency missing from your system."; - case APPINSTALLER_CLI_ERROR_INSTALL_DISK_FULL: - return "There's no more space on your PC. Make space, then try again."; - case APPINSTALLER_CLI_ERROR_INSTALL_INSUFFICIENT_MEMORY: - return "There's not enough memory available to install. Close other applications then try again."; - case APPINSTALLER_CLI_ERROR_INSTALL_NO_NETWORK: - return "This application requires internet connectivity. Connect to a network then try again."; - case APPINSTALLER_CLI_ERROR_INSTALL_CONTACT_SUPPORT: - return "This application encountered an error during installation. Contact support."; - case APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_REQUIRED_TO_FINISH: - return "Restart your PC to finish installation."; - case APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_REQUIRED_TO_INSTALL: - return "Installation failed. Restart your PC then try again."; - case APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_INITIATED: - return "Your PC will restart to finish installation."; - case APPINSTALLER_CLI_ERROR_INSTALL_CANCELLED_BY_USER: - return "You cancelled the installation."; - case APPINSTALLER_CLI_ERROR_INSTALL_ALREADY_INSTALLED: - return "Another version of this application is already installed."; - case APPINSTALLER_CLI_ERROR_INSTALL_DOWNGRADE: - return "A higher version of this application is already installed."; - case APPINSTALLER_CLI_ERROR_INSTALL_BLOCKED_BY_POLICY: - return "Organization policies are preventing installation. Contact your admin."; - case APPINSTALLER_CLI_ERROR_INSTALL_DEPENDENCIES: - return "Failed to install package dependencies."; - case APPINSTALLER_CLI_ERROR_INSTALL_PACKAGE_IN_USE_BY_APPLICATION: - return "Application is currently in use by another application."; - case APPINSTALLER_CLI_ERROR_INSTALL_INVALID_PARAMETER: - return "Invalid parameter."; - case APPINSTALLER_CLI_ERROR_INSTALL_SYSTEM_NOT_SUPPORTED: - return "Package not supported by the system."; - case APPINSTALLER_CLI_ERROR_INSTALL_UPGRADE_NOT_SUPPORTED: - return "The installer does not support upgrading an existing package."; - + return Value < other.Value; + } + }; + + // HRESULT information for our errors + struct WinGetHResultInformation : public Errors::HResultInformation + { + constexpr WinGetHResultInformation(HRESULT value, std::string_view symbol, std::string_view unlocalizedDescription) : + Errors::HResultInformation(value, symbol), m_unlocalizedDescription(unlocalizedDescription) + {} + + constexpr WinGetHResultInformation(const WinGetHResultData& data) : + Errors::HResultInformation(data.Value, data.Symbol), m_unlocalizedDescription(data.Description) + {} + + Utility::LocIndString GetDescription() const override + { + auto localizedDescription = StringResource::TryResolveString(Utility::ConvertToUTF16(Symbol())); + return localizedDescription ? + std::move(localizedDescription).value() : + Utility::LocIndString{ m_unlocalizedDescription }; + } + + private: + std::string_view m_unlocalizedDescription; + }; + + // HRESULT information for our errors, with the unlocalized description only. + struct WinGetHResultInformationUnlocalized : public Errors::HResultInformation + { + constexpr WinGetHResultInformationUnlocalized(HRESULT value, std::string_view symbol, std::string_view unlocalizedDescription) : + Errors::HResultInformation(value, symbol), m_unlocalizedDescription(unlocalizedDescription) + {} + + constexpr WinGetHResultInformationUnlocalized(const WinGetHResultData& data) : + Errors::HResultInformation(data.Value, data.Symbol), m_unlocalizedDescription(data.Description) + {} + + Utility::LocIndString GetDescription() const override + { + return Utility::LocIndString{ m_unlocalizedDescription }; + } + + private: + std::string_view m_unlocalizedDescription; + }; + + // The information entry for an HRESULT not in the list (someone probably forgot to add an entry) + struct UnknownHResultInformation : public Errors::HResultInformation + { + constexpr UnknownHResultInformation(HRESULT value) : + Errors::HResultInformation(value) + {} + + Utility::LocIndString GetDescription() const override + { + auto localizedDescription = StringResource::TryResolveString(StringResource::String::UnknownErrorCode); + return localizedDescription ? + std::move(localizedDescription).value() : + Utility::LocIndString{ "Unknown error code"sv }; + } + }; + +#define WINGET_HRESULT_INFO(_name_,_description_) WinGetHResultData{ _name_, #_name_, _description_ } + + constexpr const WinGetHResultData s_wingetHResultData[] = + { + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INTERNAL_ERROR, "Internal Error"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS, "Invalid command line arguments"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_COMMAND_FAILED, "Executing command failed"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_MANIFEST_FAILED, "Opening manifest failed"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_CTRL_SIGNAL_RECEIVED, "Cancellation signal received"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_SHELLEXEC_INSTALL_FAILED, "Running ShellExecute failed"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_UNSUPPORTED_MANIFESTVERSION, "Cannot process manifest. The manifest version is higher than supported. Please update the client."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_DOWNLOAD_FAILED, "Downloading installer failed"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_CANNOT_WRITE_TO_UPLEVEL_INDEX, "Cannot write to index; it is a higher schema version"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INDEX_INTEGRITY_COMPROMISED, "The index is corrupt"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_SOURCES_INVALID, "The configured source information is corrupt"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_SOURCE_NAME_ALREADY_EXISTS, "The source name is already configured"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INVALID_SOURCE_TYPE, "The source type is invalid"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_PACKAGE_IS_BUNDLE, "The MSIX file is a bundle, not a package"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_SOURCE_DATA_MISSING, "Data required by the source is missing"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_NO_APPLICABLE_INSTALLER, "None of the installers are applicable for the current system"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALLER_HASH_MISMATCH, "The installer file's hash does not match the manifest"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST, "The source name does not exist"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_SOURCE_ARG_ALREADY_EXISTS, "The source location is already configured under another name"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_NO_APPLICATIONS_FOUND, "No packages found"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_NO_SOURCES_DEFINED, "No sources are configured"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_MULTIPLE_APPLICATIONS_FOUND, "Multiple packages found matching the criteria"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_NO_MANIFEST_FOUND, "No manifest found matching the criteria"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_EXTENSION_PUBLIC_FAILED, "Failed to get Public folder from source package"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN, "Command requires administrator privileges to run"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_SOURCE_NOT_SECURE, "The source location is not secure"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_MSSTORE_BLOCKED_BY_POLICY, "The Microsoft Store client is blocked by policy"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_MSSTORE_APP_BLOCKED_BY_POLICY, "The Microsoft Store app is blocked by policy"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_EXPERIMENTAL_FEATURE_DISABLED, "The feature is currently under development. It can be enabled using winget settings."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_MSSTORE_INSTALL_FAILED, "Failed to install the Microsoft Store app"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_COMPLETE_INPUT_BAD, "Failed to perform auto complete"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_YAML_INIT_FAILED, "Failed to initialize YAML parser"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_YAML_INVALID_MAPPING_KEY, "Encountered an invalid YAML key"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_YAML_DUPLICATE_MAPPING_KEY, "Encountered a duplicate YAML key"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_YAML_INVALID_OPERATION, "Invalid YAML operation"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_YAML_DOC_BUILD_FAILED, "Failed to build YAML doc"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_YAML_INVALID_EMITTER_STATE, "Invalid YAML emitter state"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_YAML_INVALID_DATA, "Invalid YAML data"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_LIBYAML_ERROR, "LibYAML error"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_MANIFEST_VALIDATION_WARNING, "Manifest validation succeeded with warning"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_MANIFEST_VALIDATION_FAILURE, "Manifest validation failed"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INVALID_MANIFEST, "Manifest is invalid"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE, "No applicable update found"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_UPDATE_ALL_HAS_FAILURE, "winget upgrade --all completed with failures"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALLER_SECURITY_CHECK_FAILED, "Installer failed security check"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_DOWNLOAD_SIZE_MISMATCH, "Download size does not match expected content length"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_NO_UNINSTALL_INFO_FOUND, "Uninstall command not found"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_EXEC_UNINSTALL_COMMAND_FAILED, "Running uninstall command failed"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_ICU_BREAK_ITERATOR_ERROR, "ICU break iterator error"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_ICU_CASEMAP_ERROR, "ICU casemap error"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_ICU_REGEX_ERROR, "ICU regex error"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_IMPORT_INSTALL_FAILED, "Failed to install one or more imported packages"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_NOT_ALL_PACKAGES_FOUND, "Could not find one or more requested packages"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_JSON_INVALID_FILE, "Json file is invalid"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_SOURCE_NOT_REMOTE, "The source location is not remote"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_UNSUPPORTED_RESTSOURCE, "The configured rest source is not supported"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_DATA, "Invalid data returned by rest source"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY, "Operation is blocked by Group Policy"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_RESTSOURCE_INTERNAL_ERROR, "Rest source internal error"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_URL, "Invalid rest source url"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_RESTSOURCE_UNSUPPORTED_MIME_TYPE, "Unsupported MIME type returned by rest source"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_VERSION, "Invalid rest source contract version"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_SOURCE_DATA_INTEGRITY_FAILURE, "The source data is corrupted or tampered"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_STREAM_READ_FAILURE, "Error reading from the stream"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_PACKAGE_AGREEMENTS_NOT_ACCEPTED, "Package agreements were not agreed to"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_PROMPT_INPUT_ERROR, "Error reading input in prompt"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_UNSUPPORTED_SOURCE_REQUEST, "The search request is not supported by one or more sources"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_RESTSOURCE_ENDPOINT_NOT_FOUND, "The rest source endpoint is not found."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED, "Failed to open the source."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED, "Source agreements were not agreed to"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_CUSTOMHEADER_EXCEEDS_MAXLENGTH, "Header size exceeds the allowable limit of 1024 characters. Please reduce the size and try again."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_MISSING_RESOURCE_FILE, "Missing resource file"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_MSI_INSTALL_FAILED, "Running MSI install failed"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INVALID_MSIEXEC_ARGUMENT, "Arguments for msiexec are invalid"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_FAILED_TO_OPEN_ALL_SOURCES, "Failed to open one or more sources"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_DEPENDENCIES_VALIDATION_FAILED, "Failed to validate dependencies"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_MISSING_PACKAGE, "One or more package is missing"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INVALID_TABLE_COLUMN, "Invalid table column"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_NOT_NEWER, "The upgrade version is not newer than the installed version"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_UNKNOWN, "Upgrade version is unknown and override is not specified"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_ICU_CONVERSION_ERROR, "ICU conversion error"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_PORTABLE_INSTALL_FAILED, "Failed to install portable package"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_PORTABLE_REPARSE_POINT_NOT_SUPPORTED, "Volume does not support reparse points"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_PORTABLE_PACKAGE_ALREADY_EXISTS, "Portable package from a different source already exists."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_PORTABLE_SYMLINK_PATH_IS_DIRECTORY, "Unable to create symlink, path points to a directory."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALLER_PROHIBITS_ELEVATION, "The installer cannot be run from an administrator context."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_PORTABLE_UNINSTALL_FAILED, "Failed to uninstall portable package"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_ARP_VERSION_VALIDATION_FAILED, "Failed to validate DisplayVersion values against index."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_UNSUPPORTED_ARGUMENT, "One or more arguments are not supported."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_BIND_WITH_EMBEDDED_NULL, "Embedded null characters are disallowed for SQLite"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_NESTEDINSTALLER_NOT_FOUND, "Failed to find the nested installer in the archive."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_EXTRACT_ARCHIVE_FAILED, "Failed to extract archive."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_NESTEDINSTALLER_INVALID_PATH, "Invalid relative file path to nested installer provided."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_PINNED_CERTIFICATE_MISMATCH, "The server certificate did not match any of the expected values."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_LOCATION_REQUIRED, "Install location must be provided."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_ARCHIVE_SCAN_FAILED, "Archive malware scan failed."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_PACKAGE_ALREADY_INSTALLED, "Found at least one version of the package installed."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_PIN_ALREADY_EXISTS, "A pin already exists for the package."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_PIN_DOES_NOT_EXIST, "There is no pin for the package."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_CANNOT_OPEN_PINNING_INDEX, "Unable to open the pin database."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_MULTIPLE_INSTALL_FAILED, "One or more applications failed to install"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_MULTIPLE_UNINSTALL_FAILED, "One or more applications failed to uninstall"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_NOT_ALL_QUERIES_FOUND_SINGLE, "One or more queries did not return exactly one match"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_PACKAGE_IS_PINNED, "The package has a pin that prevents upgrade."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_PACKAGE_IS_STUB, "The package currently installed is the stub package"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_APPTERMINATION_RECEIVED, "Application shutdown signal received"), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_DOWNLOAD_DEPENDENCIES, "Failed to download package dependencies."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_DOWNLOAD_COMMAND_PROHIBITED, "Failed to download package. Download for offline installation is prohibited."), + + // Install errors. + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_PACKAGE_IN_USE, "Application is currently running. Exit the application then try again."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_INSTALL_IN_PROGRESS, "Another installation is already in progress. Try again later."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_FILE_IN_USE, "One or more file is being used. Exit the application then try again."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_MISSING_DEPENDENCY, "This package has a dependency missing from your system."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_DISK_FULL, "There's no more space on your PC. Make space, then try again."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_INSUFFICIENT_MEMORY, "There's not enough memory available to install. Close other applications then try again."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_NO_NETWORK, "This application requires internet connectivity. Connect to a network then try again."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_CONTACT_SUPPORT, "This application encountered an error during installation. Contact support."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_REQUIRED_TO_FINISH, "Restart your PC to finish installation."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_REQUIRED_TO_INSTALL, "Installation failed. Restart your PC then try again."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_INITIATED, "Your PC will restart to finish installation."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_CANCELLED_BY_USER, "You cancelled the installation."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_ALREADY_INSTALLED, "Another version of this application is already installed."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_DOWNGRADE, "A higher version of this application is already installed."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_BLOCKED_BY_POLICY, "Organization policies are preventing installation. Contact your admin."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_DEPENDENCIES, "Failed to install package dependencies."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_PACKAGE_IN_USE_BY_APPLICATION, "Application is currently in use by another application."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_INVALID_PARAMETER, "Invalid parameter."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_SYSTEM_NOT_SUPPORTED, "Package not supported by the system."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_UPGRADE_NOT_SUPPORTED, "The installer does not support upgrading an existing package."), + // Status values for check package installed status results. - case WINGET_INSTALLED_STATUS_ARP_ENTRY_NOT_FOUND: - return "The Apps and Features Entry for the package could not be found."; - case WINGET_INSTALLED_STATUS_INSTALL_LOCATION_NOT_APPLICABLE: - return "The install location is not applicable."; - case WINGET_INSTALLED_STATUS_INSTALL_LOCATION_NOT_FOUND: - return "The install location could not be found."; - case WINGET_INSTALLED_STATUS_FILE_HASH_MISMATCH: - return "The hash of the existing file did not match."; - case WINGET_INSTALLED_STATUS_FILE_NOT_FOUND: - return "File not found."; - case WINGET_INSTALLED_STATUS_FILE_FOUND_WITHOUT_HASH_CHECK: - return "The file was found but the hash was not checked."; - case WINGET_INSTALLED_STATUS_FILE_ACCESS_ERROR: - return "The file could not be accessed."; + // Partial success has the success bit(first bit) set to 0. + WINGET_HRESULT_INFO(WINGET_INSTALLED_STATUS_ARP_ENTRY_NOT_FOUND, "The Apps and Features Entry for the package could not be found."), + WINGET_HRESULT_INFO(WINGET_INSTALLED_STATUS_INSTALL_LOCATION_NOT_FOUND, "The install location could not be found."), + WINGET_HRESULT_INFO(WINGET_INSTALLED_STATUS_FILE_HASH_MISMATCH, "The hash of the existing file did not match."), + WINGET_HRESULT_INFO(WINGET_INSTALLED_STATUS_FILE_NOT_FOUND, "File not found."), + WINGET_HRESULT_INFO(WINGET_INSTALLED_STATUS_FILE_ACCESS_ERROR, "The file could not be accessed."), // Configuration Errors - case WINGET_CONFIG_ERROR_INVALID_CONFIGURATION_FILE: - return "The configuration file is invalid."; - case WINGET_CONFIG_ERROR_INVALID_YAML: - return "The YAML syntax is invalid."; - case WINGET_CONFIG_ERROR_INVALID_FIELD_TYPE: - return "A configuration field has an invalid type."; - case WINGET_CONFIG_ERROR_UNKNOWN_CONFIGURATION_FILE_VERSION: - return "The configuration has an unknown version."; - case WINGET_CONFIG_ERROR_SET_APPLY_FAILED: - return "An error occurred while applying the configuration."; - case WINGET_CONFIG_ERROR_DUPLICATE_IDENTIFIER: - return "The configuration contains a duplicate identifier."; - case WINGET_CONFIG_ERROR_MISSING_DEPENDENCY: - return "The configuration is missing a dependency."; - case WINGET_CONFIG_ERROR_DEPENDENCY_UNSATISFIED: - return "The configuration has an unsatisfied dependency."; - case WINGET_CONFIG_ERROR_ASSERTION_FAILED: - return "An assertion for the configuration unit failed."; - case WINGET_CONFIG_ERROR_MANUALLY_SKIPPED: - return "The configuration was manually skipped."; - case WINGET_CONFIG_ERROR_WARNING_NOT_ACCEPTED: - return "A warning was thrown and the user declined to continue execution."; - case WINGET_CONFIG_ERROR_SET_DEPENDENCY_CYCLE: - return "The dependency graph contains a cycle which cannot be resolved."; - case WINGET_CONFIG_ERROR_INVALID_FIELD_VALUE: - return "The configuration has an invalid field value."; - case WINGET_CONFIG_ERROR_MISSING_FIELD: - return "The configuration is missing a field."; - case WINGET_CONFIG_ERROR_TEST_FAILED: - return "Some of the configuration units failed while testing their state."; - case WINGET_CONFIG_ERROR_TEST_NOT_RUN: - return "Configuration state was not tested."; + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_INVALID_CONFIGURATION_FILE, "The configuration file is invalid."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_INVALID_YAML, "The YAML syntax is invalid."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_INVALID_FIELD_TYPE, "A configuration field has an invalid type."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_UNKNOWN_CONFIGURATION_FILE_VERSION, "The configuration has an unknown version."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_SET_APPLY_FAILED, "An error occurred while applying the configuration."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_DUPLICATE_IDENTIFIER, "The configuration contains a duplicate identifier."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_MISSING_DEPENDENCY, "The configuration is missing a dependency."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_DEPENDENCY_UNSATISFIED, "The configuration has an unsatisfied dependency."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_ASSERTION_FAILED, "An assertion for the configuration unit failed."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_MANUALLY_SKIPPED, "The configuration was manually skipped."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_WARNING_NOT_ACCEPTED, "The user declined to continue execution."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_SET_DEPENDENCY_CYCLE, "The dependency graph contains a cycle which cannot be resolved."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_INVALID_FIELD_VALUE, "The configuration has an invalid field value."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_MISSING_FIELD, "The configuration is missing a field."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_TEST_FAILED, "Some of the configuration units failed while testing their state."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_TEST_NOT_RUN, "Configuration state was not tested."), // Configuration Processor Errors - case WINGET_CONFIG_ERROR_UNIT_NOT_INSTALLED: - return "The configuration unit was not installed."; - case WINGET_CONFIG_ERROR_UNIT_NOT_FOUND_REPOSITORY: - return "The configuration unit could not be found."; - case WINGET_CONFIG_ERROR_UNIT_MULTIPLE_MATCHES: - return "Multiple matches were found for the configuration unit; specify the module to select the correct one."; - case WINGET_CONFIG_ERROR_UNIT_INVOKE_GET: - return "The configuration unit failed while attempting to get the current system state."; - case WINGET_CONFIG_ERROR_UNIT_INVOKE_TEST: - return "The configuration unit failed while attempting to test the current system state."; - case WINGET_CONFIG_ERROR_UNIT_INVOKE_SET: - return "The configuration unit failed while attempting to apply the desired state."; - case WINGET_CONFIG_ERROR_UNIT_MODULE_CONFLICT: - return "The module for the configuration unit is available in multiple locations with the same version."; - case WINGET_CONFIG_ERROR_UNIT_IMPORT_MODULE: - return "Loading the module for the configuration unit failed."; - case WINGET_CONFIG_ERROR_UNIT_INVOKE_INVALID_RESULT: - return "The configuration unit returned an unexpected result during execution."; - - default: - return "Unknown Error Code"; + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_UNIT_NOT_INSTALLED, "The configuration unit was not installed."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_UNIT_NOT_FOUND_REPOSITORY, "The configuration unit could not be found."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_UNIT_MULTIPLE_MATCHES, "Multiple matches were found for the configuration unit; specify the module to select the correct one."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_UNIT_INVOKE_GET, "The configuration unit failed while attempting to get the current system state."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_UNIT_INVOKE_TEST, "The configuration unit failed while attempting to test the current system state."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_UNIT_INVOKE_SET, "The configuration unit failed while attempting to apply the desired state."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_UNIT_MODULE_CONFLICT, "The module for the configuration unit is available in multiple locations with the same version."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_UNIT_IMPORT_MODULE, "Loading the module for the configuration unit failed."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_UNIT_INVOKE_INVALID_RESULT, "The configuration unit returned an unexpected result during execution."), + WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_UNIT_SETTING_CONFIG_ROOT, "A unit contains a setting that requires the config root."), + + // Errors without the error bit set + WINGET_HRESULT_INFO(WINGET_INSTALLED_STATUS_INSTALL_LOCATION_NOT_APPLICABLE, "The install location is not applicable."), + 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) + { + auto itr = std::lower_bound(std::cbegin(s_wingetHResultData), std::cend(s_wingetHResultData), WinGetHResultData{ value }); + + if (itr != std::cend(s_wingetHResultData) && itr->Value == value) + { + return itr; } + + return nullptr; + } + + Utility::LocIndString GetMessageForAppInstallerHR(HRESULT hr) + { + const WinGetHResultData* data = FindWinGetHResultData(hr); + return data ? + WinGetHResultInformation(*data).GetDescription() : + UnknownHResultInformation(hr).GetDescription(); } void GetUserPresentableMessageForHR(std::ostringstream& strstr, HRESULT hr) @@ -400,4 +333,98 @@ namespace AppInstaller return strstr.str(); } #endif + + namespace Errors + { + constexpr HResultInformation::HResultInformation(HRESULT value) : + m_value(value) {} + + constexpr HResultInformation::HResultInformation(HRESULT value, std::string_view symbol) : + m_value(value), m_symbol(symbol) {} + + HRESULT HResultInformation::Value() const + { + return m_value; + } + + bool HResultInformation::operator<(const HResultInformation& other) const + { + return m_value < other.m_value; + } + + Utility::LocIndView HResultInformation::Symbol() const + { + return Utility::LocIndView{ m_symbol }; + } + + Utility::LocIndString HResultInformation::GetDescription() const + { + if (HRESULT_FACILITY(m_value) == APPINSTALLER_CLI_ERROR_FACILITY) + { + // In case external code attempts to construct HResultInformation directly + return GetMessageForAppInstallerHR(m_value); + } + else + { + return Utility::LocIndString{ std::system_category().message(m_value) }; + } + } + + std::unique_ptr<HResultInformation> HResultInformation::Find(HRESULT value) + { + if (HRESULT_FACILITY(value) == APPINSTALLER_CLI_ERROR_FACILITY) + { + const WinGetHResultData* data = FindWinGetHResultData(value); + + if (data) + { + return std::make_unique<WinGetHResultInformation>(*data); + } + else + { + return std::make_unique<UnknownHResultInformation>(value); + } + } + else + { + return std::make_unique<HResultInformation>(value); + } + } + + std::vector<std::unique_ptr<HResultInformation>> HResultInformation::Find(std::string_view value) + { + std::vector<std::unique_ptr<HResultInformation>> result; + + auto addToResultIf = [&](auto predicate) + { + for (const WinGetHResultData& data : s_wingetHResultData) + { + if (predicate(data) && + std::none_of(result.begin(), result.end(), [&](const std::unique_ptr<HResultInformation>& info) { return info->Value() == data.Value; })) + { + result.emplace_back(std::make_unique<WinGetHResultInformation>(data)); + } + } + }; + + 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); }); + + return result; + } + + std::vector<std::unique_ptr<HResultInformation>> GetWinGetErrors() + { + std::vector<std::unique_ptr<HResultInformation>> result; + result.reserve(ARRAYSIZE(s_wingetHResultData)); + + for (const WinGetHResultData& data : s_wingetHResultData) + { + result.emplace_back(std::make_unique<WinGetHResultInformationUnlocalized>(data)); + } + + return result; + } + } } diff --git a/src/AppInstallerSharedLib/Public/AppInstallerErrors.h b/src/AppInstallerSharedLib/Public/AppInstallerErrors.h @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. #pragma once +#include <winget/LocIndependent.h> #include <wil/result_macros.h> #ifndef WINGET_DISABLE_FOR_FUZZING @@ -8,141 +9,144 @@ #endif #include <exception> +#include <memory> #include <string> +#include <utility> +#include <vector> #define APPINSTALLER_CLI_ERROR_FACILITY 0xA15 -#define APPINSTALLER_CLI_ERROR_INTERNAL_ERROR ((HRESULT)0x8A150001) -#define APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS ((HRESULT)0x8A150002) -#define APPINSTALLER_CLI_ERROR_COMMAND_FAILED ((HRESULT)0x8A150003) -#define APPINSTALLER_CLI_ERROR_MANIFEST_FAILED ((HRESULT)0x8A150004) -#define APPINSTALLER_CLI_ERROR_CTRL_SIGNAL_RECEIVED ((HRESULT)0x8A150005) -#define APPINSTALLER_CLI_ERROR_SHELLEXEC_INSTALL_FAILED ((HRESULT)0x8A150006) -#define APPINSTALLER_CLI_ERROR_UNSUPPORTED_MANIFESTVERSION ((HRESULT)0x8A150007) -#define APPINSTALLER_CLI_ERROR_DOWNLOAD_FAILED ((HRESULT)0x8A150008) -#define APPINSTALLER_CLI_ERROR_CANNOT_WRITE_TO_UPLEVEL_INDEX ((HRESULT)0x8A150009) -#define APPINSTALLER_CLI_ERROR_INDEX_INTEGRITY_COMPROMISED ((HRESULT)0x8A15000A) -#define APPINSTALLER_CLI_ERROR_SOURCES_INVALID ((HRESULT)0x8A15000B) -#define APPINSTALLER_CLI_ERROR_SOURCE_NAME_ALREADY_EXISTS ((HRESULT)0x8A15000C) -#define APPINSTALLER_CLI_ERROR_INVALID_SOURCE_TYPE ((HRESULT)0x8A15000D) -#define APPINSTALLER_CLI_ERROR_PACKAGE_IS_BUNDLE ((HRESULT)0x8A15000E) -#define APPINSTALLER_CLI_ERROR_SOURCE_DATA_MISSING ((HRESULT)0x8A15000F) -#define APPINSTALLER_CLI_ERROR_NO_APPLICABLE_INSTALLER ((HRESULT)0x8A150010) -#define APPINSTALLER_CLI_ERROR_INSTALLER_HASH_MISMATCH ((HRESULT)0x8A150011) -#define APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST ((HRESULT)0x8A150012) -#define APPINSTALLER_CLI_ERROR_SOURCE_ARG_ALREADY_EXISTS ((HRESULT)0x8A150013) -#define APPINSTALLER_CLI_ERROR_NO_APPLICATIONS_FOUND ((HRESULT)0x8A150014) -#define APPINSTALLER_CLI_ERROR_NO_SOURCES_DEFINED ((HRESULT)0x8A150015) -#define APPINSTALLER_CLI_ERROR_MULTIPLE_APPLICATIONS_FOUND ((HRESULT)0x8A150016) -#define APPINSTALLER_CLI_ERROR_NO_MANIFEST_FOUND ((HRESULT)0x8A150017) -#define APPINSTALLER_CLI_ERROR_EXTENSION_PUBLIC_FAILED ((HRESULT)0x8A150018) -#define APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN ((HRESULT)0x8A150019) -#define APPINSTALLER_CLI_ERROR_SOURCE_NOT_SECURE ((HRESULT)0x8A15001A) -#define APPINSTALLER_CLI_ERROR_MSSTORE_BLOCKED_BY_POLICY ((HRESULT)0x8A15001B) -#define APPINSTALLER_CLI_ERROR_MSSTORE_APP_BLOCKED_BY_POLICY ((HRESULT)0x8A15001C) -#define APPINSTALLER_CLI_ERROR_EXPERIMENTAL_FEATURE_DISABLED ((HRESULT)0x8A15001D) -#define APPINSTALLER_CLI_ERROR_MSSTORE_INSTALL_FAILED ((HRESULT)0x8A15001E) -#define APPINSTALLER_CLI_ERROR_COMPLETE_INPUT_BAD ((HRESULT)0x8A15001F) -#define APPINSTALLER_CLI_ERROR_YAML_INIT_FAILED ((HRESULT)0x8A150020) -#define APPINSTALLER_CLI_ERROR_YAML_INVALID_MAPPING_KEY ((HRESULT)0x8A150021) -#define APPINSTALLER_CLI_ERROR_YAML_DUPLICATE_MAPPING_KEY ((HRESULT)0x8A150022) -#define APPINSTALLER_CLI_ERROR_YAML_INVALID_OPERATION ((HRESULT)0x8A150023) -#define APPINSTALLER_CLI_ERROR_YAML_DOC_BUILD_FAILED ((HRESULT)0x8A150024) -#define APPINSTALLER_CLI_ERROR_YAML_INVALID_EMITTER_STATE ((HRESULT)0x8A150025) -#define APPINSTALLER_CLI_ERROR_YAML_INVALID_DATA ((HRESULT)0x8A150026) -#define APPINSTALLER_CLI_ERROR_LIBYAML_ERROR ((HRESULT)0x8A150027) -#define APPINSTALLER_CLI_ERROR_MANIFEST_VALIDATION_WARNING ((HRESULT)0x8A150028) -#define APPINSTALLER_CLI_ERROR_MANIFEST_VALIDATION_FAILURE ((HRESULT)0x8A150029) -#define APPINSTALLER_CLI_ERROR_INVALID_MANIFEST ((HRESULT)0x8A15002A) -#define APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE ((HRESULT)0x8A15002B) -#define APPINSTALLER_CLI_ERROR_UPDATE_ALL_HAS_FAILURE ((HRESULT)0x8A15002C) -#define APPINSTALLER_CLI_ERROR_INSTALLER_SECURITY_CHECK_FAILED ((HRESULT)0x8A15002D) -#define APPINSTALLER_CLI_ERROR_DOWNLOAD_SIZE_MISMATCH ((HRESULT)0x8A15002E) -#define APPINSTALLER_CLI_ERROR_NO_UNINSTALL_INFO_FOUND ((HRESULT)0x8A15002F) -#define APPINSTALLER_CLI_ERROR_EXEC_UNINSTALL_COMMAND_FAILED ((HRESULT)0x8A150030) -#define APPINSTALLER_CLI_ERROR_ICU_BREAK_ITERATOR_ERROR ((HRESULT)0x8A150031) -#define APPINSTALLER_CLI_ERROR_ICU_CASEMAP_ERROR ((HRESULT)0x8A150032) -#define APPINSTALLER_CLI_ERROR_ICU_REGEX_ERROR ((HRESULT)0x8A150033) -#define APPINSTALLER_CLI_ERROR_IMPORT_INSTALL_FAILED ((HRESULT)0x8A150034) -#define APPINSTALLER_CLI_ERROR_NOT_ALL_PACKAGES_FOUND ((HRESULT)0x8A150035) -#define APPINSTALLER_CLI_ERROR_JSON_INVALID_FILE ((HRESULT)0x8A150036) -#define APPINSTALLER_CLI_ERROR_SOURCE_NOT_REMOTE ((HRESULT)0x8A150037) -#define APPINSTALLER_CLI_ERROR_UNSUPPORTED_RESTSOURCE ((HRESULT)0x8A150038) -#define APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_DATA ((HRESULT)0x8A150039) -#define APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY ((HRESULT)0x8A15003A) -#define APPINSTALLER_CLI_ERROR_RESTSOURCE_INTERNAL_ERROR ((HRESULT)0x8A15003B) -#define APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_URL ((HRESULT)0x8A15003C) -#define APPINSTALLER_CLI_ERROR_RESTSOURCE_UNSUPPORTED_MIME_TYPE ((HRESULT)0x8A15003D) -#define APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_VERSION ((HRESULT)0x8A15003E) -#define APPINSTALLER_CLI_ERROR_SOURCE_DATA_INTEGRITY_FAILURE ((HRESULT)0x8A15003F) -#define APPINSTALLER_CLI_ERROR_STREAM_READ_FAILURE ((HRESULT)0x8A150040) -#define APPINSTALLER_CLI_ERROR_PACKAGE_AGREEMENTS_NOT_ACCEPTED ((HRESULT)0x8A150041) -#define APPINSTALLER_CLI_ERROR_PROMPT_INPUT_ERROR ((HRESULT)0x8A150042) -#define APPINSTALLER_CLI_ERROR_UNSUPPORTED_SOURCE_REQUEST ((HRESULT)0x8A150043) -#define APPINSTALLER_CLI_ERROR_RESTSOURCE_ENDPOINT_NOT_FOUND ((HRESULT)0x8A150044) -#define APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED ((HRESULT)0x8A150045) -#define APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED ((HRESULT)0x8A150046) -#define APPINSTALLER_CLI_ERROR_CUSTOMHEADER_EXCEEDS_MAXLENGTH ((HRESULT)0x8A150047) -#define APPINSTALLER_CLI_ERROR_MISSING_RESOURCE_FILE ((HRESULT)0x8A150048) -#define APPINSTALLER_CLI_ERROR_MSI_INSTALL_FAILED ((HRESULT)0x8A150049) -#define APPINSTALLER_CLI_ERROR_INVALID_MSIEXEC_ARGUMENT ((HRESULT)0x8A15004A) -#define APPINSTALLER_CLI_ERROR_FAILED_TO_OPEN_ALL_SOURCES ((HRESULT)0x8A15004B) -#define APPINSTALLER_CLI_ERROR_DEPENDENCIES_VALIDATION_FAILED ((HRESULT)0x8A15004C) -#define APPINSTALLER_CLI_ERROR_MISSING_PACKAGE ((HRESULT)0x8A15004D) -#define APPINSTALLER_CLI_ERROR_INVALID_TABLE_COLUMN ((HRESULT)0x8A15004E) -#define APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_NOT_NEWER ((HRESULT)0x8A15004F) -#define APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_UNKNOWN ((HRESULT)0x8A150050) -#define APPINSTALLER_CLI_ERROR_ICU_CONVERSION_ERROR ((HRESULT)0x8A150051) -#define APPINSTALLER_CLI_ERROR_PORTABLE_INSTALL_FAILED ((HRESULT)0x8A150052) +#define APPINSTALLER_CLI_ERROR_INTERNAL_ERROR ((HRESULT)0x8A150001) +#define APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS ((HRESULT)0x8A150002) +#define APPINSTALLER_CLI_ERROR_COMMAND_FAILED ((HRESULT)0x8A150003) +#define APPINSTALLER_CLI_ERROR_MANIFEST_FAILED ((HRESULT)0x8A150004) +#define APPINSTALLER_CLI_ERROR_CTRL_SIGNAL_RECEIVED ((HRESULT)0x8A150005) +#define APPINSTALLER_CLI_ERROR_SHELLEXEC_INSTALL_FAILED ((HRESULT)0x8A150006) +#define APPINSTALLER_CLI_ERROR_UNSUPPORTED_MANIFESTVERSION ((HRESULT)0x8A150007) +#define APPINSTALLER_CLI_ERROR_DOWNLOAD_FAILED ((HRESULT)0x8A150008) +#define APPINSTALLER_CLI_ERROR_CANNOT_WRITE_TO_UPLEVEL_INDEX ((HRESULT)0x8A150009) +#define APPINSTALLER_CLI_ERROR_INDEX_INTEGRITY_COMPROMISED ((HRESULT)0x8A15000A) +#define APPINSTALLER_CLI_ERROR_SOURCES_INVALID ((HRESULT)0x8A15000B) +#define APPINSTALLER_CLI_ERROR_SOURCE_NAME_ALREADY_EXISTS ((HRESULT)0x8A15000C) +#define APPINSTALLER_CLI_ERROR_INVALID_SOURCE_TYPE ((HRESULT)0x8A15000D) +#define APPINSTALLER_CLI_ERROR_PACKAGE_IS_BUNDLE ((HRESULT)0x8A15000E) +#define APPINSTALLER_CLI_ERROR_SOURCE_DATA_MISSING ((HRESULT)0x8A15000F) +#define APPINSTALLER_CLI_ERROR_NO_APPLICABLE_INSTALLER ((HRESULT)0x8A150010) +#define APPINSTALLER_CLI_ERROR_INSTALLER_HASH_MISMATCH ((HRESULT)0x8A150011) +#define APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST ((HRESULT)0x8A150012) +#define APPINSTALLER_CLI_ERROR_SOURCE_ARG_ALREADY_EXISTS ((HRESULT)0x8A150013) +#define APPINSTALLER_CLI_ERROR_NO_APPLICATIONS_FOUND ((HRESULT)0x8A150014) +#define APPINSTALLER_CLI_ERROR_NO_SOURCES_DEFINED ((HRESULT)0x8A150015) +#define APPINSTALLER_CLI_ERROR_MULTIPLE_APPLICATIONS_FOUND ((HRESULT)0x8A150016) +#define APPINSTALLER_CLI_ERROR_NO_MANIFEST_FOUND ((HRESULT)0x8A150017) +#define APPINSTALLER_CLI_ERROR_EXTENSION_PUBLIC_FAILED ((HRESULT)0x8A150018) +#define APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN ((HRESULT)0x8A150019) +#define APPINSTALLER_CLI_ERROR_SOURCE_NOT_SECURE ((HRESULT)0x8A15001A) +#define APPINSTALLER_CLI_ERROR_MSSTORE_BLOCKED_BY_POLICY ((HRESULT)0x8A15001B) +#define APPINSTALLER_CLI_ERROR_MSSTORE_APP_BLOCKED_BY_POLICY ((HRESULT)0x8A15001C) +#define APPINSTALLER_CLI_ERROR_EXPERIMENTAL_FEATURE_DISABLED ((HRESULT)0x8A15001D) +#define APPINSTALLER_CLI_ERROR_MSSTORE_INSTALL_FAILED ((HRESULT)0x8A15001E) +#define APPINSTALLER_CLI_ERROR_COMPLETE_INPUT_BAD ((HRESULT)0x8A15001F) +#define APPINSTALLER_CLI_ERROR_YAML_INIT_FAILED ((HRESULT)0x8A150020) +#define APPINSTALLER_CLI_ERROR_YAML_INVALID_MAPPING_KEY ((HRESULT)0x8A150021) +#define APPINSTALLER_CLI_ERROR_YAML_DUPLICATE_MAPPING_KEY ((HRESULT)0x8A150022) +#define APPINSTALLER_CLI_ERROR_YAML_INVALID_OPERATION ((HRESULT)0x8A150023) +#define APPINSTALLER_CLI_ERROR_YAML_DOC_BUILD_FAILED ((HRESULT)0x8A150024) +#define APPINSTALLER_CLI_ERROR_YAML_INVALID_EMITTER_STATE ((HRESULT)0x8A150025) +#define APPINSTALLER_CLI_ERROR_YAML_INVALID_DATA ((HRESULT)0x8A150026) +#define APPINSTALLER_CLI_ERROR_LIBYAML_ERROR ((HRESULT)0x8A150027) +#define APPINSTALLER_CLI_ERROR_MANIFEST_VALIDATION_WARNING ((HRESULT)0x8A150028) +#define APPINSTALLER_CLI_ERROR_MANIFEST_VALIDATION_FAILURE ((HRESULT)0x8A150029) +#define APPINSTALLER_CLI_ERROR_INVALID_MANIFEST ((HRESULT)0x8A15002A) +#define APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE ((HRESULT)0x8A15002B) +#define APPINSTALLER_CLI_ERROR_UPDATE_ALL_HAS_FAILURE ((HRESULT)0x8A15002C) +#define APPINSTALLER_CLI_ERROR_INSTALLER_SECURITY_CHECK_FAILED ((HRESULT)0x8A15002D) +#define APPINSTALLER_CLI_ERROR_DOWNLOAD_SIZE_MISMATCH ((HRESULT)0x8A15002E) +#define APPINSTALLER_CLI_ERROR_NO_UNINSTALL_INFO_FOUND ((HRESULT)0x8A15002F) +#define APPINSTALLER_CLI_ERROR_EXEC_UNINSTALL_COMMAND_FAILED ((HRESULT)0x8A150030) +#define APPINSTALLER_CLI_ERROR_ICU_BREAK_ITERATOR_ERROR ((HRESULT)0x8A150031) +#define APPINSTALLER_CLI_ERROR_ICU_CASEMAP_ERROR ((HRESULT)0x8A150032) +#define APPINSTALLER_CLI_ERROR_ICU_REGEX_ERROR ((HRESULT)0x8A150033) +#define APPINSTALLER_CLI_ERROR_IMPORT_INSTALL_FAILED ((HRESULT)0x8A150034) +#define APPINSTALLER_CLI_ERROR_NOT_ALL_PACKAGES_FOUND ((HRESULT)0x8A150035) +#define APPINSTALLER_CLI_ERROR_JSON_INVALID_FILE ((HRESULT)0x8A150036) +#define APPINSTALLER_CLI_ERROR_SOURCE_NOT_REMOTE ((HRESULT)0x8A150037) +#define APPINSTALLER_CLI_ERROR_UNSUPPORTED_RESTSOURCE ((HRESULT)0x8A150038) +#define APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_DATA ((HRESULT)0x8A150039) +#define APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY ((HRESULT)0x8A15003A) +#define APPINSTALLER_CLI_ERROR_RESTSOURCE_INTERNAL_ERROR ((HRESULT)0x8A15003B) +#define APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_URL ((HRESULT)0x8A15003C) +#define APPINSTALLER_CLI_ERROR_RESTSOURCE_UNSUPPORTED_MIME_TYPE ((HRESULT)0x8A15003D) +#define APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_VERSION ((HRESULT)0x8A15003E) +#define APPINSTALLER_CLI_ERROR_SOURCE_DATA_INTEGRITY_FAILURE ((HRESULT)0x8A15003F) +#define APPINSTALLER_CLI_ERROR_STREAM_READ_FAILURE ((HRESULT)0x8A150040) +#define APPINSTALLER_CLI_ERROR_PACKAGE_AGREEMENTS_NOT_ACCEPTED ((HRESULT)0x8A150041) +#define APPINSTALLER_CLI_ERROR_PROMPT_INPUT_ERROR ((HRESULT)0x8A150042) +#define APPINSTALLER_CLI_ERROR_UNSUPPORTED_SOURCE_REQUEST ((HRESULT)0x8A150043) +#define APPINSTALLER_CLI_ERROR_RESTSOURCE_ENDPOINT_NOT_FOUND ((HRESULT)0x8A150044) +#define APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED ((HRESULT)0x8A150045) +#define APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED ((HRESULT)0x8A150046) +#define APPINSTALLER_CLI_ERROR_CUSTOMHEADER_EXCEEDS_MAXLENGTH ((HRESULT)0x8A150047) +#define APPINSTALLER_CLI_ERROR_MISSING_RESOURCE_FILE ((HRESULT)0x8A150048) +#define APPINSTALLER_CLI_ERROR_MSI_INSTALL_FAILED ((HRESULT)0x8A150049) +#define APPINSTALLER_CLI_ERROR_INVALID_MSIEXEC_ARGUMENT ((HRESULT)0x8A15004A) +#define APPINSTALLER_CLI_ERROR_FAILED_TO_OPEN_ALL_SOURCES ((HRESULT)0x8A15004B) +#define APPINSTALLER_CLI_ERROR_DEPENDENCIES_VALIDATION_FAILED ((HRESULT)0x8A15004C) +#define APPINSTALLER_CLI_ERROR_MISSING_PACKAGE ((HRESULT)0x8A15004D) +#define APPINSTALLER_CLI_ERROR_INVALID_TABLE_COLUMN ((HRESULT)0x8A15004E) +#define APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_NOT_NEWER ((HRESULT)0x8A15004F) +#define APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_UNKNOWN ((HRESULT)0x8A150050) +#define APPINSTALLER_CLI_ERROR_ICU_CONVERSION_ERROR ((HRESULT)0x8A150051) +#define APPINSTALLER_CLI_ERROR_PORTABLE_INSTALL_FAILED ((HRESULT)0x8A150052) #define APPINSTALLER_CLI_ERROR_PORTABLE_REPARSE_POINT_NOT_SUPPORTED ((HRESULT)0x8A150053) -#define APPINSTALLER_CLI_ERROR_PORTABLE_PACKAGE_ALREADY_EXISTS ((HRESULT)0x8A150054) -#define APPINSTALLER_CLI_ERROR_PORTABLE_SYMLINK_PATH_IS_DIRECTORY ((HRESULT)0x8A150055) -#define APPINSTALLER_CLI_ERROR_INSTALLER_PROHIBITS_ELEVATION ((HRESULT)0x8A150056) -#define APPINSTALLER_CLI_ERROR_PORTABLE_UNINSTALL_FAILED ((HRESULT)0x8A150057) -#define APPINSTALLER_CLI_ERROR_ARP_VERSION_VALIDATION_FAILED ((HRESULT)0x8A150058) -#define APPINSTALLER_CLI_ERROR_UNSUPPORTED_ARGUMENT ((HRESULT)0x8A150059) -#define APPINSTALLER_CLI_ERROR_BIND_WITH_EMBEDDED_NULL ((HRESULT)0x8A15005A) -#define APPINSTALLER_CLI_ERROR_NESTEDINSTALLER_NOT_FOUND ((HRESULT)0x8A15005B) -#define APPINSTALLER_CLI_ERROR_EXTRACT_ARCHIVE_FAILED ((HRESULT)0x8A15005C) -#define APPINSTALLER_CLI_ERROR_NESTEDINSTALLER_INVALID_PATH ((HRESULT)0x8A15005D) -#define APPINSTALLER_CLI_ERROR_PINNED_CERTIFICATE_MISMATCH ((HRESULT)0x8A15005E) -#define APPINSTALLER_CLI_ERROR_INSTALL_LOCATION_REQUIRED ((HRESULT)0x8A15005F) -#define APPINSTALLER_CLI_ERROR_ARCHIVE_SCAN_FAILED ((HRESULT)0x8A150060) -#define APPINSTALLER_CLI_ERROR_PACKAGE_ALREADY_INSTALLED ((HRESULT)0x8A150061) -#define APPINSTALLER_CLI_ERROR_PIN_ALREADY_EXISTS ((HRESULT)0x8A150062) -#define APPINSTALLER_CLI_ERROR_PIN_DOES_NOT_EXIST ((HRESULT)0x8A150063) -#define APPINSTALLER_CLI_ERROR_CANNOT_OPEN_PINNING_INDEX ((HRESULT)0x8A150064) -#define APPINSTALLER_CLI_ERROR_MULTIPLE_INSTALL_FAILED ((HRESULT)0x8A150065) -#define APPINSTALLER_CLI_ERROR_MULTIPLE_UNINSTALL_FAILED ((HRESULT)0x8A150066) -#define APPINSTALLER_CLI_ERROR_NOT_ALL_QUERIES_FOUND_SINGLE ((HRESULT)0x8A150067) -#define APPINSTALLER_CLI_ERROR_PACKAGE_IS_PINNED ((HRESULT)0x8A150068) -#define APPINSTALLER_CLI_ERROR_PACKAGE_IS_STUB ((HRESULT)0x8A150069) -#define APPINSTALLER_CLI_ERROR_APPTERMINATION_RECEIVED ((HRESULT)0x8A15006A) -#define APPINSTALLER_CLI_ERROR_DOWNLOAD_DEPENDENCIES ((HRESULT)0x8A15006B) -#define APPINSTALLER_CLI_ERROR_DOWNLOAD_COMMAND_PROHIBITED ((HRESULT)0x8A15006C) +#define APPINSTALLER_CLI_ERROR_PORTABLE_PACKAGE_ALREADY_EXISTS ((HRESULT)0x8A150054) +#define APPINSTALLER_CLI_ERROR_PORTABLE_SYMLINK_PATH_IS_DIRECTORY ((HRESULT)0x8A150055) +#define APPINSTALLER_CLI_ERROR_INSTALLER_PROHIBITS_ELEVATION ((HRESULT)0x8A150056) +#define APPINSTALLER_CLI_ERROR_PORTABLE_UNINSTALL_FAILED ((HRESULT)0x8A150057) +#define APPINSTALLER_CLI_ERROR_ARP_VERSION_VALIDATION_FAILED ((HRESULT)0x8A150058) +#define APPINSTALLER_CLI_ERROR_UNSUPPORTED_ARGUMENT ((HRESULT)0x8A150059) +#define APPINSTALLER_CLI_ERROR_BIND_WITH_EMBEDDED_NULL ((HRESULT)0x8A15005A) +#define APPINSTALLER_CLI_ERROR_NESTEDINSTALLER_NOT_FOUND ((HRESULT)0x8A15005B) +#define APPINSTALLER_CLI_ERROR_EXTRACT_ARCHIVE_FAILED ((HRESULT)0x8A15005C) +#define APPINSTALLER_CLI_ERROR_NESTEDINSTALLER_INVALID_PATH ((HRESULT)0x8A15005D) +#define APPINSTALLER_CLI_ERROR_PINNED_CERTIFICATE_MISMATCH ((HRESULT)0x8A15005E) +#define APPINSTALLER_CLI_ERROR_INSTALL_LOCATION_REQUIRED ((HRESULT)0x8A15005F) +#define APPINSTALLER_CLI_ERROR_ARCHIVE_SCAN_FAILED ((HRESULT)0x8A150060) +#define APPINSTALLER_CLI_ERROR_PACKAGE_ALREADY_INSTALLED ((HRESULT)0x8A150061) +#define APPINSTALLER_CLI_ERROR_PIN_ALREADY_EXISTS ((HRESULT)0x8A150062) +#define APPINSTALLER_CLI_ERROR_PIN_DOES_NOT_EXIST ((HRESULT)0x8A150063) +#define APPINSTALLER_CLI_ERROR_CANNOT_OPEN_PINNING_INDEX ((HRESULT)0x8A150064) +#define APPINSTALLER_CLI_ERROR_MULTIPLE_INSTALL_FAILED ((HRESULT)0x8A150065) +#define APPINSTALLER_CLI_ERROR_MULTIPLE_UNINSTALL_FAILED ((HRESULT)0x8A150066) +#define APPINSTALLER_CLI_ERROR_NOT_ALL_QUERIES_FOUND_SINGLE ((HRESULT)0x8A150067) +#define APPINSTALLER_CLI_ERROR_PACKAGE_IS_PINNED ((HRESULT)0x8A150068) +#define APPINSTALLER_CLI_ERROR_PACKAGE_IS_STUB ((HRESULT)0x8A150069) +#define APPINSTALLER_CLI_ERROR_APPTERMINATION_RECEIVED ((HRESULT)0x8A15006A) +#define APPINSTALLER_CLI_ERROR_DOWNLOAD_DEPENDENCIES ((HRESULT)0x8A15006B) +#define APPINSTALLER_CLI_ERROR_DOWNLOAD_COMMAND_PROHIBITED ((HRESULT)0x8A15006C) // Install errors. -#define APPINSTALLER_CLI_ERROR_INSTALL_PACKAGE_IN_USE ((HRESULT)0x8A150101) -#define APPINSTALLER_CLI_ERROR_INSTALL_INSTALL_IN_PROGRESS ((HRESULT)0x8A150102) -#define APPINSTALLER_CLI_ERROR_INSTALL_FILE_IN_USE ((HRESULT)0x8A150103) -#define APPINSTALLER_CLI_ERROR_INSTALL_MISSING_DEPENDENCY ((HRESULT)0x8A150104) -#define APPINSTALLER_CLI_ERROR_INSTALL_DISK_FULL ((HRESULT)0x8A150105) -#define APPINSTALLER_CLI_ERROR_INSTALL_INSUFFICIENT_MEMORY ((HRESULT)0x8A150106) -#define APPINSTALLER_CLI_ERROR_INSTALL_NO_NETWORK ((HRESULT)0x8A150107) -#define APPINSTALLER_CLI_ERROR_INSTALL_CONTACT_SUPPORT ((HRESULT)0x8A150108) -#define APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_REQUIRED_TO_FINISH ((HRESULT)0x8A150109) -#define APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_REQUIRED_TO_INSTALL ((HRESULT)0x8A15010A) -#define APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_INITIATED ((HRESULT)0x8A15010B) -#define APPINSTALLER_CLI_ERROR_INSTALL_CANCELLED_BY_USER ((HRESULT)0x8A15010C) -#define APPINSTALLER_CLI_ERROR_INSTALL_ALREADY_INSTALLED ((HRESULT)0x8A15010D) -#define APPINSTALLER_CLI_ERROR_INSTALL_DOWNGRADE ((HRESULT)0x8A15010E) -#define APPINSTALLER_CLI_ERROR_INSTALL_BLOCKED_BY_POLICY ((HRESULT)0x8A15010F) -#define APPINSTALLER_CLI_ERROR_INSTALL_DEPENDENCIES ((HRESULT)0x8A150110) -#define APPINSTALLER_CLI_ERROR_INSTALL_PACKAGE_IN_USE_BY_APPLICATION ((HRESULT)0x8A150111) -#define APPINSTALLER_CLI_ERROR_INSTALL_INVALID_PARAMETER ((HRESULT)0x8A150112) -#define APPINSTALLER_CLI_ERROR_INSTALL_SYSTEM_NOT_SUPPORTED ((HRESULT)0x8A150113) -#define APPINSTALLER_CLI_ERROR_INSTALL_UPGRADE_NOT_SUPPORTED ((HRESULT)0x8A150114) +#define APPINSTALLER_CLI_ERROR_INSTALL_PACKAGE_IN_USE ((HRESULT)0x8A150101) +#define APPINSTALLER_CLI_ERROR_INSTALL_INSTALL_IN_PROGRESS ((HRESULT)0x8A150102) +#define APPINSTALLER_CLI_ERROR_INSTALL_FILE_IN_USE ((HRESULT)0x8A150103) +#define APPINSTALLER_CLI_ERROR_INSTALL_MISSING_DEPENDENCY ((HRESULT)0x8A150104) +#define APPINSTALLER_CLI_ERROR_INSTALL_DISK_FULL ((HRESULT)0x8A150105) +#define APPINSTALLER_CLI_ERROR_INSTALL_INSUFFICIENT_MEMORY ((HRESULT)0x8A150106) +#define APPINSTALLER_CLI_ERROR_INSTALL_NO_NETWORK ((HRESULT)0x8A150107) +#define APPINSTALLER_CLI_ERROR_INSTALL_CONTACT_SUPPORT ((HRESULT)0x8A150108) +#define APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_REQUIRED_TO_FINISH ((HRESULT)0x8A150109) +#define APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_REQUIRED_TO_INSTALL ((HRESULT)0x8A15010A) +#define APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_INITIATED ((HRESULT)0x8A15010B) +#define APPINSTALLER_CLI_ERROR_INSTALL_CANCELLED_BY_USER ((HRESULT)0x8A15010C) +#define APPINSTALLER_CLI_ERROR_INSTALL_ALREADY_INSTALLED ((HRESULT)0x8A15010D) +#define APPINSTALLER_CLI_ERROR_INSTALL_DOWNGRADE ((HRESULT)0x8A15010E) +#define APPINSTALLER_CLI_ERROR_INSTALL_BLOCKED_BY_POLICY ((HRESULT)0x8A15010F) +#define APPINSTALLER_CLI_ERROR_INSTALL_DEPENDENCIES ((HRESULT)0x8A150110) +#define APPINSTALLER_CLI_ERROR_INSTALL_PACKAGE_IN_USE_BY_APPLICATION ((HRESULT)0x8A150111) +#define APPINSTALLER_CLI_ERROR_INSTALL_INVALID_PARAMETER ((HRESULT)0x8A150112) +#define APPINSTALLER_CLI_ERROR_INSTALL_SYSTEM_NOT_SUPPORTED ((HRESULT)0x8A150113) +#define APPINSTALLER_CLI_ERROR_INSTALL_UPGRADE_NOT_SUPPORTED ((HRESULT)0x8A150114) // Status values for check package installed status results. // Partial success has the success bit(first bit) set to 0. @@ -197,4 +201,40 @@ namespace AppInstaller #ifndef WINGET_DISABLE_FOR_FUZZING std::string GetUserPresentableMessage(const winrt::hresult_error& hre); #endif + + namespace Errors + { + // Details about an HRESULT + struct HResultInformation + { + constexpr HResultInformation(HRESULT value); + constexpr HResultInformation(HRESULT value, std::string_view symbol); + + virtual ~HResultInformation() = default; + + HRESULT Value() const; + + bool operator<(const HResultInformation& other) const; + + // The symbol will be an empty view if not known. + Utility::LocIndView Symbol() const; + + // Looks up the description of the HRESULT + virtual Utility::LocIndString GetDescription() const; + + // Find information by HRESULT; this lookup is optimized. + static std::unique_ptr<HResultInformation> Find(HRESULT value); + + // Find information by substring match with the given value. + // This lookup is not optimized, as it should only be needed for the error command. + static std::vector<std::unique_ptr<HResultInformation>> Find(std::string_view value); + + private: + HRESULT m_value; + std::string_view m_symbol; + }; + + // Gets all of the custom error information for our errors. + std::vector<std::unique_ptr<HResultInformation>> GetWinGetErrors(); + } } diff --git a/src/AppInstallerSharedLib/Public/winget/Resources.h b/src/AppInstallerSharedLib/Public/winget/Resources.h @@ -4,6 +4,7 @@ #include <winrt/Windows.ApplicationModel.Resources.h> #include <string> +#include <optional> #include <vector> #include "AppInstallerStrings.h" @@ -65,6 +66,8 @@ namespace AppInstaller WINGET_DEFINE_RESOURCE_STRINGID(SettingsWarningLoadedBackupSettings); WINGET_DEFINE_RESOURCE_STRINGID(SettingsWarningParseError); WINGET_DEFINE_RESOURCE_STRINGID(SettingsWarningUsingDefault); + + WINGET_DEFINE_RESOURCE_STRINGID(UnknownErrorCode); }; } @@ -96,6 +99,12 @@ namespace AppInstaller }; } + namespace StringResource + { + // Tries to resolve a string, returning a nullopt if it cannot. + std::optional<Resource::LocString> TryResolveString(std::wstring_view resKey); + } + namespace details { // List of approved types for output, others are potentially not localized. diff --git a/src/AppInstallerSharedLib/Resources.cpp b/src/AppInstallerSharedLib/Resources.cpp @@ -86,6 +86,26 @@ namespace AppInstaller return Utility::ConvertToUTF8(resKey); } + // Gets the string resource value or nothing if not present. + std::optional<Resource::LocString> TryResolveString(std::wstring_view resKey) const + { + if (!resKey.empty() && m_wingetLoader) + { + try + { + winrt::hstring result = m_wingetLoader.GetString(resKey); + + if (!result.empty()) + { + return Resource::LocString{ Utility::LocIndString{ Utility::ConvertToUTF8(result) } }; + } + } + CATCH_LOG() + } + + return {}; + } + private: winrt::Windows::ApplicationModel::Resources::ResourceLoader m_wingetLoader; @@ -123,5 +143,10 @@ namespace AppInstaller { return (out << Resource::LocString{ si }); } + + std::optional<Resource::LocString> TryResolveString(std::wstring_view resKey) + { + return Resource::Loader::Instance().TryResolveString(resKey); + } } }