winget-cli

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

commit 1cc58ce1996810b6f2c639b74451f476c7b58244
parent 5c21dec74547d3d70e46c1aabd9df2ef087f9d96
Author: sreadingMSFT <74242768+sreadingMSFT@users.noreply.github.com>
Date:   Fri, 18 Jun 2021 14:15:19 -0700

Add more error handling for com callers and prevent concurrent installs (#1182)

* More error handling; stop concurrent com installs.

* Simplify error catching
Diffstat:
Msrc/AppInstallerCLICore/ExecutionContext.cpp | 10++++++++++
Msrc/AppInstallerCLICore/ExecutionContext.h | 2++
Msrc/Microsoft.Management.Deployment/Converters.cpp | 540++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Microsoft.Management.Deployment/Converters.h | 2+-
Msrc/Microsoft.Management.Deployment/PackageCatalog.cpp | 351++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Microsoft.Management.Deployment/PackageCatalogReference.cpp | 206++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/Microsoft.Management.Deployment/PackageManager.cpp | 672++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/Microsoft.Management.Deployment/PackageMatchFilter.cpp | 109++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Microsoft.Management.Deployment/PackageVersionInfo.cpp | 179++++++++++++++++++++++++++++++++++++++++---------------------------------------
9 files changed, 1069 insertions(+), 1002 deletions(-)

diff --git a/src/AppInstallerCLICore/ExecutionContext.cpp b/src/AppInstallerCLICore/ExecutionContext.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT License. #include "pch.h" #include "ExecutionContext.h" +#include "COMContext.h" #include "winget/UserSettings.h" namespace AppInstaller::CLI::Execution @@ -23,6 +24,15 @@ namespace AppInstaller::CLI::Execution { std::lock_guard<std::mutex> lock{ m_contextsLock }; + // TODO: COMContexts are currently only used specifically for install operations, which Windows does not reliably support concurrently. + // As a temporary fix, this location which already has locking and is tracking the contexts is convenient to prevent those + // installs from happening concurrently. Future work will provide a more robust synchronization mechanism which can queue those requests + // rather than failing. + for (auto& existingContext : m_contexts) + { + THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_INSTALL_ALREADY_RUNNING), (dynamic_cast<COMContext*>(existingContext) != 0)); + } + auto itr = std::find(m_contexts.begin(), m_contexts.end(), context); THROW_HR_IF(E_NOT_VALID_STATE, itr != m_contexts.end()); m_contexts.push_back(context); diff --git a/src/AppInstallerCLICore/ExecutionContext.h b/src/AppInstallerCLICore/ExecutionContext.h @@ -107,6 +107,8 @@ namespace AppInstaller::CLI::Execution virtual void SetExecutionStage(Workflow::ExecutionStage stage, bool); + Workflow::ExecutionStage GetExecutionStage() const { return m_executionStage; } + #ifndef AICLI_DISABLE_TEST_HOOKS // Enable tests to override behavior virtual bool ShouldExecuteWorkflowTask(const Workflow::WorkflowTask&) { return true; } diff --git a/src/Microsoft.Management.Deployment/Converters.cpp b/src/Microsoft.Management.Deployment/Converters.cpp @@ -1,269 +1,273 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -#include "pch.h" -#include <AppInstallerErrors.h> -#include <AppInstallerRepositorySearch.h> -#include <AppInstallerRepositorySource.h> -#include "Microsoft/PredefinedInstalledSourceFactory.h" -#include "Converters.h" - -namespace winrt::Microsoft::Management::Deployment::implementation -{ - Microsoft::Management::Deployment::PackageMatchField GetDeploymentMatchField(::AppInstaller::Repository::PackageMatchField field) - { - Microsoft::Management::Deployment::PackageMatchField matchField = Microsoft::Management::Deployment::PackageMatchField::Id; - switch (field) - { - case ::AppInstaller::Repository::PackageMatchField::Command: - matchField = Microsoft::Management::Deployment::PackageMatchField::Command; - break; - case ::AppInstaller::Repository::PackageMatchField::Id: - matchField = Microsoft::Management::Deployment::PackageMatchField::Id; - break; - case ::AppInstaller::Repository::PackageMatchField::Moniker: - matchField = Microsoft::Management::Deployment::PackageMatchField::Moniker; - break; - case ::AppInstaller::Repository::PackageMatchField::Name: - matchField = Microsoft::Management::Deployment::PackageMatchField::Name; - break; - case ::AppInstaller::Repository::PackageMatchField::Tag: - matchField = Microsoft::Management::Deployment::PackageMatchField::Tag; - break; - default: - matchField = Microsoft::Management::Deployment::PackageMatchField::Id; - break; - } - return matchField; - } - - ::AppInstaller::Repository::PackageMatchField GetRepositoryMatchField(Microsoft::Management::Deployment::PackageMatchField field) - { - ::AppInstaller::Repository::PackageMatchField matchField = ::AppInstaller::Repository::PackageMatchField::Id; - switch (field) - { - case Microsoft::Management::Deployment::PackageMatchField::Command: - matchField = ::AppInstaller::Repository::PackageMatchField::Command; - break; - case Microsoft::Management::Deployment::PackageMatchField::Id: - matchField = ::AppInstaller::Repository::PackageMatchField::Id; - break; - case Microsoft::Management::Deployment::PackageMatchField::Moniker: - matchField = ::AppInstaller::Repository::PackageMatchField::Moniker; - break; - case Microsoft::Management::Deployment::PackageMatchField::Name: - matchField = ::AppInstaller::Repository::PackageMatchField::Name; - break; - case Microsoft::Management::Deployment::PackageMatchField::Tag: - matchField = ::AppInstaller::Repository::PackageMatchField::Tag; - break; - default: - matchField = ::AppInstaller::Repository::PackageMatchField::Id; - break; - } - return matchField; - } - - Microsoft::Management::Deployment::PackageFieldMatchOption GetDeploymentMatchOption(::AppInstaller::Repository::MatchType type) - { - Microsoft::Management::Deployment::PackageFieldMatchOption matchOption = Microsoft::Management::Deployment::PackageFieldMatchOption::Equals; - switch (type) - { - case ::AppInstaller::Repository::MatchType::CaseInsensitive: - matchOption = Microsoft::Management::Deployment::PackageFieldMatchOption::EqualsCaseInsensitive; - break; - case ::AppInstaller::Repository::MatchType::Exact: - matchOption = Microsoft::Management::Deployment::PackageFieldMatchOption::Equals; - break; - case ::AppInstaller::Repository::MatchType::StartsWith: - matchOption = Microsoft::Management::Deployment::PackageFieldMatchOption::StartsWithCaseInsensitive; - break; - case ::AppInstaller::Repository::MatchType::Substring: - matchOption = Microsoft::Management::Deployment::PackageFieldMatchOption::ContainsCaseInsensitive; - break; - default: - matchOption = Microsoft::Management::Deployment::PackageFieldMatchOption::Equals; - break; - } - return matchOption; - } - - ::AppInstaller::Repository::MatchType GetRepositoryMatchType(Microsoft::Management::Deployment::PackageFieldMatchOption option) - { - ::AppInstaller::Repository::MatchType packageFieldMatchOption = ::AppInstaller::Repository::MatchType::Exact; - switch (option) - { - case Microsoft::Management::Deployment::PackageFieldMatchOption::EqualsCaseInsensitive: - packageFieldMatchOption = ::AppInstaller::Repository::MatchType::CaseInsensitive; - break; - case Microsoft::Management::Deployment::PackageFieldMatchOption::Equals: - packageFieldMatchOption = ::AppInstaller::Repository::MatchType::Exact; - break; - case Microsoft::Management::Deployment::PackageFieldMatchOption::StartsWithCaseInsensitive: - packageFieldMatchOption = ::AppInstaller::Repository::MatchType::StartsWith; - break; - case Microsoft::Management::Deployment::PackageFieldMatchOption::ContainsCaseInsensitive: - packageFieldMatchOption = ::AppInstaller::Repository::MatchType::Substring; - break; - default: - packageFieldMatchOption = ::AppInstaller::Repository::MatchType::Exact; - break; - } - return packageFieldMatchOption; - } - - ::AppInstaller::Repository::CompositeSearchBehavior GetRepositoryCompositeSearchBehavior(Microsoft::Management::Deployment::CompositeSearchBehavior searchBehavior) - { - ::AppInstaller::Repository::CompositeSearchBehavior repositorySearchBehavior = ::AppInstaller::Repository::CompositeSearchBehavior::AllPackages; - switch (searchBehavior) - { - case Microsoft::Management::Deployment::CompositeSearchBehavior::LocalCatalogs: - repositorySearchBehavior = ::AppInstaller::Repository::CompositeSearchBehavior::Installed; - break; - case Microsoft::Management::Deployment::CompositeSearchBehavior::RemotePackagesFromRemoteCatalogs: - repositorySearchBehavior = ::AppInstaller::Repository::CompositeSearchBehavior::AvailablePackages; - break; - case Microsoft::Management::Deployment::CompositeSearchBehavior::RemotePackagesFromAllCatalogs: - repositorySearchBehavior = ::AppInstaller::Repository::CompositeSearchBehavior::AvailablePackages; - break; - case Microsoft::Management::Deployment::CompositeSearchBehavior::AllCatalogs: - default: - repositorySearchBehavior = ::AppInstaller::Repository::CompositeSearchBehavior::AllPackages; - break; - } - return repositorySearchBehavior; - } - - ::AppInstaller::Repository::PackageVersionMetadata GetRepositoryPackageVersionMetadata(Microsoft::Management::Deployment::PackageVersionMetadataField packageVersionMetadataField) - { - ::AppInstaller::Repository::PackageVersionMetadata metadataKey = ::AppInstaller::Repository::PackageVersionMetadata::InstalledLocation; - switch (packageVersionMetadataField) - { - case Microsoft::Management::Deployment::PackageVersionMetadataField::InstalledLocation: - metadataKey = ::AppInstaller::Repository::PackageVersionMetadata::InstalledLocation; - break; - case Microsoft::Management::Deployment::PackageVersionMetadataField::InstalledScope: - metadataKey = ::AppInstaller::Repository::PackageVersionMetadata::InstalledScope; - break; - case Microsoft::Management::Deployment::PackageVersionMetadataField::InstallerType: - metadataKey = ::AppInstaller::Repository::PackageVersionMetadata::InstalledType; - break; - case Microsoft::Management::Deployment::PackageVersionMetadataField::PublisherDisplayName: - metadataKey = ::AppInstaller::Repository::PackageVersionMetadata::Publisher; - break; - case Microsoft::Management::Deployment::PackageVersionMetadataField::SilentUninstallCommand: - metadataKey = ::AppInstaller::Repository::PackageVersionMetadata::SilentUninstallCommand; - break; - case Microsoft::Management::Deployment::PackageVersionMetadataField::StandardUninstallCommand: - metadataKey = ::AppInstaller::Repository::PackageVersionMetadata::StandardUninstallCommand; - break; - } - return metadataKey; - } - - winrt::Microsoft::Management::Deployment::InstallResultStatus GetInstallResultStatus(winrt::hresult hresult) - { - winrt::Microsoft::Management::Deployment::InstallResultStatus resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::Ok; - switch (hresult) - { - case(S_OK): - resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::Ok; - break; - case APPINSTALLER_CLI_ERROR_MSSTORE_BLOCKED_BY_POLICY: - case APPINSTALLER_CLI_ERROR_MSSTORE_APP_BLOCKED_BY_POLICY: - case APPINSTALLER_CLI_ERROR_EXPERIMENTAL_FEATURE_DISABLED: - case APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY: - resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::BlockedByPolicy; - break; - case APPINSTALLER_CLI_ERROR_MANIFEST_FAILED: - case APPINSTALLER_CLI_ERROR_UNSUPPORTED_MANIFESTVERSION: - case APPINSTALLER_CLI_ERROR_PACKAGE_IS_BUNDLE: - case APPINSTALLER_CLI_ERROR_SOURCE_DATA_MISSING: - case APPINSTALLER_CLI_ERROR_UNSUPPORTED_RESTSOURCE: - case APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_DATA: - case APPINSTALLER_CLI_ERROR_RESTSOURCE_INTERNAL_ERROR: - case APPINSTALLER_CLI_ERROR_RESTSOURCE_UNSUPPORTED_MIME_TYPE: - case APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_VERSION: - case APPINSTALLER_CLI_ERROR_SOURCE_DATA_INTEGRITY_FAILURE: - case APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST: - case APPINSTALLER_CLI_ERROR_NO_APPLICATIONS_FOUND: - case APPINSTALLER_CLI_ERROR_NO_SOURCES_DEFINED: - case APPINSTALLER_CLI_ERROR_NO_MANIFEST_FOUND: - resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::CatalogError; - break; - case E_INVALIDARG: - case APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS: - resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::InvalidOptions; - break; - case APPINSTALLER_CLI_ERROR_DOWNLOAD_FAILED: - case APPINSTALLER_CLI_ERROR_INSTALLER_HASH_MISMATCH: - case APPINSTALLER_CLI_ERROR_INSTALLER_SECURITY_CHECK_FAILED: - case APPINSTALLER_CLI_ERROR_DOWNLOAD_SIZE_MISMATCH: - resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::DownloadError; - break; - case APPINSTALLER_CLI_ERROR_SHELLEXEC_INSTALL_FAILED: - case APPINSTALLER_CLI_ERROR_MSSTORE_INSTALL_FAILED: - resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::InstallError; - break; - case APPINSTALLER_CLI_ERROR_INVALID_MANIFEST: - resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::ManifestError; - break; - case APPINSTALLER_CLI_ERROR_NO_APPLICABLE_INSTALLER: - resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::NoApplicableInstallers; - break; - case APPINSTALLER_CLI_ERROR_COMMAND_FAILED: - case APPINSTALLER_CLI_ERROR_CANNOT_WRITE_TO_UPLEVEL_INDEX: - case APPINSTALLER_CLI_ERROR_INDEX_INTEGRITY_COMPROMISED: - case APPINSTALLER_CLI_ERROR_YAML_INIT_FAILED: - case APPINSTALLER_CLI_ERROR_YAML_INVALID_MAPPING_KEY: - case APPINSTALLER_CLI_ERROR_YAML_DUPLICATE_MAPPING_KEY: - case APPINSTALLER_CLI_ERROR_YAML_INVALID_OPERATION: - case APPINSTALLER_CLI_ERROR_YAML_DOC_BUILD_FAILED: - case APPINSTALLER_CLI_ERROR_YAML_INVALID_EMITTER_STATE: - case APPINSTALLER_CLI_ERROR_YAML_INVALID_DATA: - case APPINSTALLER_CLI_ERROR_LIBYAML_ERROR: - case APPINSTALLER_CLI_ERROR_INTERNAL_ERROR: - default: - resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::InternalError; - break; - } - return resultStatus; - } - - winrt::Microsoft::Management::Deployment::FindPackagesResultStatus FindPackagesResultStatus(winrt::hresult hresult) - { - winrt::Microsoft::Management::Deployment::FindPackagesResultStatus resultStatus = winrt::Microsoft::Management::Deployment::FindPackagesResultStatus::Ok; - switch (hresult) - { - case(S_OK): - resultStatus = winrt::Microsoft::Management::Deployment::FindPackagesResultStatus::Ok; - break; - case APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY: - resultStatus = winrt::Microsoft::Management::Deployment::FindPackagesResultStatus::BlockedByPolicy; - break; - case APPINSTALLER_CLI_ERROR_UNSUPPORTED_RESTSOURCE: - case APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_DATA: - case APPINSTALLER_CLI_ERROR_RESTSOURCE_INTERNAL_ERROR: - case APPINSTALLER_CLI_ERROR_RESTSOURCE_UNSUPPORTED_MIME_TYPE: - case APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_VERSION: - case APPINSTALLER_CLI_ERROR_SOURCE_DATA_INTEGRITY_FAILURE: - resultStatus = winrt::Microsoft::Management::Deployment::FindPackagesResultStatus::CatalogError; - break; - case E_INVALIDARG: - case APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS: - resultStatus = winrt::Microsoft::Management::Deployment::FindPackagesResultStatus::InvalidOptions; - break; - case APPINSTALLER_CLI_ERROR_COMMAND_FAILED: - case APPINSTALLER_CLI_ERROR_CANNOT_WRITE_TO_UPLEVEL_INDEX: - case APPINSTALLER_CLI_ERROR_INDEX_INTEGRITY_COMPROMISED: - default: - resultStatus = winrt::Microsoft::Management::Deployment::FindPackagesResultStatus::InternalError; - break; - } - return resultStatus; - } - - bool IsLocalPackageCatalog(winrt::Microsoft::Management::Deployment::PackageCatalogInfo info) - { - return (winrt::to_string(info.Type()).compare(::AppInstaller::Repository::Microsoft::PredefinedInstalledSourceFactory::Type()) == 0); - } +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include <AppInstallerErrors.h> +#include <AppInstallerRepositorySearch.h> +#include <AppInstallerRepositorySource.h> +#include "Microsoft/PredefinedInstalledSourceFactory.h" +#include "Workflows/WorkflowBase.h" +#include "Converters.h" + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + Microsoft::Management::Deployment::PackageMatchField GetDeploymentMatchField(::AppInstaller::Repository::PackageMatchField field) + { + Microsoft::Management::Deployment::PackageMatchField matchField = Microsoft::Management::Deployment::PackageMatchField::Id; + switch (field) + { + case ::AppInstaller::Repository::PackageMatchField::Command: + matchField = Microsoft::Management::Deployment::PackageMatchField::Command; + break; + case ::AppInstaller::Repository::PackageMatchField::Id: + matchField = Microsoft::Management::Deployment::PackageMatchField::Id; + break; + case ::AppInstaller::Repository::PackageMatchField::Moniker: + matchField = Microsoft::Management::Deployment::PackageMatchField::Moniker; + break; + case ::AppInstaller::Repository::PackageMatchField::Name: + matchField = Microsoft::Management::Deployment::PackageMatchField::Name; + break; + case ::AppInstaller::Repository::PackageMatchField::Tag: + matchField = Microsoft::Management::Deployment::PackageMatchField::Tag; + break; + default: + matchField = Microsoft::Management::Deployment::PackageMatchField::Id; + break; + } + return matchField; + } + + ::AppInstaller::Repository::PackageMatchField GetRepositoryMatchField(Microsoft::Management::Deployment::PackageMatchField field) + { + ::AppInstaller::Repository::PackageMatchField matchField = ::AppInstaller::Repository::PackageMatchField::Id; + switch (field) + { + case Microsoft::Management::Deployment::PackageMatchField::Command: + matchField = ::AppInstaller::Repository::PackageMatchField::Command; + break; + case Microsoft::Management::Deployment::PackageMatchField::Id: + matchField = ::AppInstaller::Repository::PackageMatchField::Id; + break; + case Microsoft::Management::Deployment::PackageMatchField::Moniker: + matchField = ::AppInstaller::Repository::PackageMatchField::Moniker; + break; + case Microsoft::Management::Deployment::PackageMatchField::Name: + matchField = ::AppInstaller::Repository::PackageMatchField::Name; + break; + case Microsoft::Management::Deployment::PackageMatchField::Tag: + matchField = ::AppInstaller::Repository::PackageMatchField::Tag; + break; + default: + matchField = ::AppInstaller::Repository::PackageMatchField::Id; + break; + } + return matchField; + } + + Microsoft::Management::Deployment::PackageFieldMatchOption GetDeploymentMatchOption(::AppInstaller::Repository::MatchType type) + { + Microsoft::Management::Deployment::PackageFieldMatchOption matchOption = Microsoft::Management::Deployment::PackageFieldMatchOption::Equals; + switch (type) + { + case ::AppInstaller::Repository::MatchType::CaseInsensitive: + matchOption = Microsoft::Management::Deployment::PackageFieldMatchOption::EqualsCaseInsensitive; + break; + case ::AppInstaller::Repository::MatchType::Exact: + matchOption = Microsoft::Management::Deployment::PackageFieldMatchOption::Equals; + break; + case ::AppInstaller::Repository::MatchType::StartsWith: + matchOption = Microsoft::Management::Deployment::PackageFieldMatchOption::StartsWithCaseInsensitive; + break; + case ::AppInstaller::Repository::MatchType::Substring: + matchOption = Microsoft::Management::Deployment::PackageFieldMatchOption::ContainsCaseInsensitive; + break; + default: + matchOption = Microsoft::Management::Deployment::PackageFieldMatchOption::Equals; + break; + } + return matchOption; + } + + ::AppInstaller::Repository::MatchType GetRepositoryMatchType(Microsoft::Management::Deployment::PackageFieldMatchOption option) + { + ::AppInstaller::Repository::MatchType packageFieldMatchOption = ::AppInstaller::Repository::MatchType::Exact; + switch (option) + { + case Microsoft::Management::Deployment::PackageFieldMatchOption::EqualsCaseInsensitive: + packageFieldMatchOption = ::AppInstaller::Repository::MatchType::CaseInsensitive; + break; + case Microsoft::Management::Deployment::PackageFieldMatchOption::Equals: + packageFieldMatchOption = ::AppInstaller::Repository::MatchType::Exact; + break; + case Microsoft::Management::Deployment::PackageFieldMatchOption::StartsWithCaseInsensitive: + packageFieldMatchOption = ::AppInstaller::Repository::MatchType::StartsWith; + break; + case Microsoft::Management::Deployment::PackageFieldMatchOption::ContainsCaseInsensitive: + packageFieldMatchOption = ::AppInstaller::Repository::MatchType::Substring; + break; + default: + packageFieldMatchOption = ::AppInstaller::Repository::MatchType::Exact; + break; + } + return packageFieldMatchOption; + } + + ::AppInstaller::Repository::CompositeSearchBehavior GetRepositoryCompositeSearchBehavior(Microsoft::Management::Deployment::CompositeSearchBehavior searchBehavior) + { + ::AppInstaller::Repository::CompositeSearchBehavior repositorySearchBehavior = ::AppInstaller::Repository::CompositeSearchBehavior::AllPackages; + switch (searchBehavior) + { + case Microsoft::Management::Deployment::CompositeSearchBehavior::LocalCatalogs: + repositorySearchBehavior = ::AppInstaller::Repository::CompositeSearchBehavior::Installed; + break; + case Microsoft::Management::Deployment::CompositeSearchBehavior::RemotePackagesFromRemoteCatalogs: + repositorySearchBehavior = ::AppInstaller::Repository::CompositeSearchBehavior::AvailablePackages; + break; + case Microsoft::Management::Deployment::CompositeSearchBehavior::RemotePackagesFromAllCatalogs: + repositorySearchBehavior = ::AppInstaller::Repository::CompositeSearchBehavior::AvailablePackages; + break; + case Microsoft::Management::Deployment::CompositeSearchBehavior::AllCatalogs: + default: + repositorySearchBehavior = ::AppInstaller::Repository::CompositeSearchBehavior::AllPackages; + break; + } + return repositorySearchBehavior; + } + + ::AppInstaller::Repository::PackageVersionMetadata GetRepositoryPackageVersionMetadata(Microsoft::Management::Deployment::PackageVersionMetadataField packageVersionMetadataField) + { + ::AppInstaller::Repository::PackageVersionMetadata metadataKey = ::AppInstaller::Repository::PackageVersionMetadata::InstalledLocation; + switch (packageVersionMetadataField) + { + case Microsoft::Management::Deployment::PackageVersionMetadataField::InstalledLocation: + metadataKey = ::AppInstaller::Repository::PackageVersionMetadata::InstalledLocation; + break; + case Microsoft::Management::Deployment::PackageVersionMetadataField::InstalledScope: + metadataKey = ::AppInstaller::Repository::PackageVersionMetadata::InstalledScope; + break; + case Microsoft::Management::Deployment::PackageVersionMetadataField::InstallerType: + metadataKey = ::AppInstaller::Repository::PackageVersionMetadata::InstalledType; + break; + case Microsoft::Management::Deployment::PackageVersionMetadataField::PublisherDisplayName: + metadataKey = ::AppInstaller::Repository::PackageVersionMetadata::Publisher; + break; + case Microsoft::Management::Deployment::PackageVersionMetadataField::SilentUninstallCommand: + metadataKey = ::AppInstaller::Repository::PackageVersionMetadata::SilentUninstallCommand; + break; + case Microsoft::Management::Deployment::PackageVersionMetadataField::StandardUninstallCommand: + metadataKey = ::AppInstaller::Repository::PackageVersionMetadata::StandardUninstallCommand; + break; + } + return metadataKey; + } + + winrt::Microsoft::Management::Deployment::InstallResultStatus GetInstallResultStatus(::AppInstaller::CLI::Workflow::ExecutionStage executionStage, winrt::hresult hresult) + { + winrt::Microsoft::Management::Deployment::InstallResultStatus resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::Ok; + + // Map some known hresults to specific statuses, otherwise use the execution stage to determine the status. + switch (hresult) + { + case S_OK: + resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::Ok; + break; + case APPINSTALLER_CLI_ERROR_MSSTORE_BLOCKED_BY_POLICY: + case APPINSTALLER_CLI_ERROR_MSSTORE_APP_BLOCKED_BY_POLICY: + case APPINSTALLER_CLI_ERROR_EXPERIMENTAL_FEATURE_DISABLED: + case APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY: + resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::BlockedByPolicy; + break; + case APPINSTALLER_CLI_ERROR_INVALID_MANIFEST: + resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::ManifestError; + break; + case E_INVALIDARG: + case APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS: + resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::InvalidOptions; + break; + case APPINSTALLER_CLI_ERROR_NO_APPLICABLE_INSTALLER: + resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::NoApplicableInstallers; + break; + case APPINSTALLER_CLI_ERROR_CANNOT_WRITE_TO_UPLEVEL_INDEX: + case APPINSTALLER_CLI_ERROR_INDEX_INTEGRITY_COMPROMISED: + case APPINSTALLER_CLI_ERROR_YAML_INIT_FAILED: + case APPINSTALLER_CLI_ERROR_YAML_INVALID_MAPPING_KEY: + case APPINSTALLER_CLI_ERROR_YAML_DUPLICATE_MAPPING_KEY: + case APPINSTALLER_CLI_ERROR_YAML_INVALID_OPERATION: + case APPINSTALLER_CLI_ERROR_YAML_DOC_BUILD_FAILED: + case APPINSTALLER_CLI_ERROR_YAML_INVALID_EMITTER_STATE: + case APPINSTALLER_CLI_ERROR_YAML_INVALID_DATA: + case APPINSTALLER_CLI_ERROR_LIBYAML_ERROR: + case APPINSTALLER_CLI_ERROR_INTERNAL_ERROR: + resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::InternalError; + break; + default: + switch (executionStage) + { + case ::AppInstaller::CLI::Workflow::ExecutionStage::Initial: + resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::InternalError; + break; + case ::AppInstaller::CLI::Workflow::ExecutionStage::ParseArgs: + resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::InvalidOptions; + break; + case ::AppInstaller::CLI::Workflow::ExecutionStage::Discovery: + resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::CatalogError; + break; + case ::AppInstaller::CLI::Workflow::ExecutionStage::Download: + resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::DownloadError; + break; + case ::AppInstaller::CLI::Workflow::ExecutionStage::PreExecution: + resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::InternalError; + break; + case ::AppInstaller::CLI::Workflow::ExecutionStage::Execution: + resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::InstallError; + break; + case ::AppInstaller::CLI::Workflow::ExecutionStage::PostExecution: + resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::InternalError; + break; + default: + resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::InternalError; + break; + } + } + + return resultStatus; + } + + winrt::Microsoft::Management::Deployment::FindPackagesResultStatus FindPackagesResultStatus(winrt::hresult hresult) + { + winrt::Microsoft::Management::Deployment::FindPackagesResultStatus resultStatus = winrt::Microsoft::Management::Deployment::FindPackagesResultStatus::Ok; + switch (hresult) + { + case(S_OK): + resultStatus = winrt::Microsoft::Management::Deployment::FindPackagesResultStatus::Ok; + break; + case APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY: + resultStatus = winrt::Microsoft::Management::Deployment::FindPackagesResultStatus::BlockedByPolicy; + break; + case APPINSTALLER_CLI_ERROR_UNSUPPORTED_RESTSOURCE: + case APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_DATA: + case APPINSTALLER_CLI_ERROR_RESTSOURCE_INTERNAL_ERROR: + case APPINSTALLER_CLI_ERROR_RESTSOURCE_UNSUPPORTED_MIME_TYPE: + case APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_VERSION: + case APPINSTALLER_CLI_ERROR_SOURCE_DATA_INTEGRITY_FAILURE: + resultStatus = winrt::Microsoft::Management::Deployment::FindPackagesResultStatus::CatalogError; + break; + case E_INVALIDARG: + case APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS: + resultStatus = winrt::Microsoft::Management::Deployment::FindPackagesResultStatus::InvalidOptions; + break; + case APPINSTALLER_CLI_ERROR_COMMAND_FAILED: + case APPINSTALLER_CLI_ERROR_CANNOT_WRITE_TO_UPLEVEL_INDEX: + case APPINSTALLER_CLI_ERROR_INDEX_INTEGRITY_COMPROMISED: + default: + resultStatus = winrt::Microsoft::Management::Deployment::FindPackagesResultStatus::InternalError; + break; + } + return resultStatus; + } + + bool IsLocalPackageCatalog(winrt::Microsoft::Management::Deployment::PackageCatalogInfo info) + { + return (winrt::to_string(info.Type()).compare(::AppInstaller::Repository::Microsoft::PredefinedInstalledSourceFactory::Type()) == 0); + } } \ No newline at end of file diff --git a/src/Microsoft.Management.Deployment/Converters.h b/src/Microsoft.Management.Deployment/Converters.h @@ -11,7 +11,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation ::AppInstaller::Repository::MatchType GetRepositoryMatchType(winrt::Microsoft::Management::Deployment::PackageFieldMatchOption option); ::AppInstaller::Repository::CompositeSearchBehavior GetRepositoryCompositeSearchBehavior(winrt::Microsoft::Management::Deployment::CompositeSearchBehavior searchBehavior); ::AppInstaller::Repository::PackageVersionMetadata GetRepositoryPackageVersionMetadata(winrt::Microsoft::Management::Deployment::PackageVersionMetadataField packageVersionMetadataField); - winrt::Microsoft::Management::Deployment::InstallResultStatus GetInstallResultStatus(winrt::hresult hresult); + winrt::Microsoft::Management::Deployment::InstallResultStatus GetInstallResultStatus(::AppInstaller::CLI::Workflow::ExecutionStage executionStage, winrt::hresult hresult); winrt::Microsoft::Management::Deployment::FindPackagesResultStatus FindPackagesResultStatus(winrt::hresult hresult); bool IsLocalPackageCatalog(winrt::Microsoft::Management::Deployment::PackageCatalogInfo info); } \ No newline at end of file diff --git a/src/Microsoft.Management.Deployment/PackageCatalog.cpp b/src/Microsoft.Management.Deployment/PackageCatalog.cpp @@ -1,175 +1,176 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -#include "pch.h" -#include <mutex> -#include <AppInstallerRepositorySource.h> -#include "Converters.h" -#include "PackageCatalog.h" -#include "PackageCatalog.g.cpp" -#include "PackageCatalogInfo.h" -#include "FindPackagesResult.h" -#include "MatchResult.h" -#include "CatalogPackage.h" -#pragma warning( push ) -#pragma warning ( disable : 4467 6388) -// 6388 Allow CreateInstance. -#include <wil\cppwinrt_wrl.h> -// 4467 Allow use of uuid attribute for com object creation. -#include "PackageMatchFilter.h" -#pragma warning( pop ) -#include "Microsoft/PredefinedInstalledSourceFactory.h" -#include <winget/GroupPolicy.h> -#include <AppInstallerErrors.h> - -namespace winrt::Microsoft::Management::Deployment::implementation -{ - void PackageCatalog::Initialize( - winrt::Microsoft::Management::Deployment::PackageCatalogInfo info, - std::shared_ptr<const ::AppInstaller::Repository::ISource> source, - bool isComposite) - { - m_info = info; - m_source = std::move(source); - m_isComposite = isComposite; - } - bool PackageCatalog::IsComposite() - { - // Can't use m_source->IsComposite for this because all remote sources are turned into composite sources - // behind the scenes when being opened in PackageCatalogReference.cpp so that CatalogPackage.IsInstalled works. - return m_isComposite; - } - winrt::Microsoft::Management::Deployment::PackageCatalogInfo PackageCatalog::Info() - { - return m_info; - } - winrt::Windows::Foundation::IAsyncOperation<winrt::Microsoft::Management::Deployment::FindPackagesResult> PackageCatalog::FindPackagesAsync(winrt::Microsoft::Management::Deployment::FindPackagesOptions options) - { - co_return FindPackages(options); - } - - HRESULT PopulateSearchRequestFromVector( - ::AppInstaller::Repository::SearchRequest* searchRequest, - Windows::Foundation::Collections::IVector<Microsoft::Management::Deployment::PackageMatchFilter> vector, - bool isSelector) - { - // Populates either the Filters vector of a searchRequest (if isSelector is false), - // or the Inclusions and Query (if true) - for (uint32_t i = 0; i < vector.Size(); ++i) - { - Microsoft::Management::Deployment::PackageMatchFilter filter = vector.GetAt(i); - - if (filter.Value().size() == 0) - { - // If the caller did not add a value it can't actually be used to filter or include anything so just ignore it. - continue; - } - ::AppInstaller::Repository::MatchType packageFieldMatchOption = GetRepositoryMatchType(filter.Option()); - ::AppInstaller::Repository::PackageMatchField matchField = GetRepositoryMatchField(filter.Field()); - - if (isSelector) - { - if (filter.Field() == Microsoft::Management::Deployment::PackageMatchField::CatalogDefault) - { - if (searchRequest->Query.has_value()) - { - // CatalogDefault match field can't be used twice. - return E_INVALIDARG; - } - searchRequest->Query = ::AppInstaller::Repository::RequestMatch(packageFieldMatchOption, winrt::to_string(filter.Value())); - } - else - { - auto matchFilter = ::AppInstaller::Repository::PackageMatchFilter(matchField, packageFieldMatchOption, winrt::to_string(filter.Value())); - searchRequest->Inclusions.emplace_back(matchFilter); - } - } - else - { - if (filter.Field() == Microsoft::Management::Deployment::PackageMatchField::CatalogDefault) - { - // CatalogDefault match fields can't be used in the Filters. - return E_INVALIDARG; - } - auto matchFilter = ::AppInstaller::Repository::PackageMatchFilter(matchField, packageFieldMatchOption, winrt::to_string(filter.Value())); - searchRequest->Filters.emplace_back(matchFilter); - } - } - return S_OK; - } - - HRESULT PopulateSearchRequest( - ::AppInstaller::Repository::SearchRequest* searchRequest, - winrt::Microsoft::Management::Deployment::FindPackagesOptions const& options) - { - RETURN_IF_FAILED(PopulateSearchRequestFromVector(searchRequest, options.Filters(), false)); - RETURN_IF_FAILED(PopulateSearchRequestFromVector(searchRequest, options.Selectors(), true)); - return S_OK; - } - - winrt::Microsoft::Management::Deployment::FindPackagesResult PackageCatalog::FindPackages(winrt::Microsoft::Management::Deployment::FindPackagesOptions const& options) - { - winrt::Microsoft::Management::Deployment::FindPackagesResultStatus::Ok; - bool isTruncated = false; - Windows::Foundation::Collections::IVector<Microsoft::Management::Deployment::MatchResult> matches{ winrt::single_threaded_vector<Microsoft::Management::Deployment::MatchResult>() }; - ::AppInstaller::Repository::SearchRequest searchRequest; - - HRESULT hr = PopulateSearchRequest(&searchRequest, options); - if (SUCCEEDED(hr)) - { - searchRequest.MaximumResults = options.ResultLimit(); - try - { - auto searchResult = m_source->Search(searchRequest); - - // Build the result object from the searchResult - for (size_t i = 0; i < searchResult.Matches.size(); ++i) - { - auto match = searchResult.Matches[i]; - auto catalogPackage = winrt::make_self<wil::details::module_count_wrapper< - winrt::Microsoft::Management::Deployment::implementation::CatalogPackage>>(); - catalogPackage->Initialize(m_source, match.Package); - - auto packageMatchFilter = winrt::make_self<wil::details::module_count_wrapper< - winrt::Microsoft::Management::Deployment::implementation::PackageMatchFilter>>(); - packageMatchFilter->Initialize(match.MatchCriteria); - - auto matchResult = winrt::make_self<wil::details::module_count_wrapper< - winrt::Microsoft::Management::Deployment::implementation::MatchResult>>(); - matchResult->Initialize(*catalogPackage, *packageMatchFilter); - - matches.Append(*matchResult); - } - isTruncated = searchResult.Truncated; - } - // Exceptions that may occur in the process of executing an arbitrary command - catch (const wil::ResultException& re) - { - hr = re.GetErrorCode(); - } - catch (const winrt::hresult_error& hre) - { - hr = hre.code(); - } - catch (const ::AppInstaller::Settings::GroupPolicyException&) - { - // Policy could have changed since server started. - hr = APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY; - } - catch (const std::exception&) - { - hr = APPINSTALLER_CLI_ERROR_COMMAND_FAILED; - } - catch (...) - { - hr = APPINSTALLER_CLI_ERROR_COMMAND_FAILED; - } - } - auto findPackagesResult = winrt::make_self<wil::details::module_count_wrapper< - winrt::Microsoft::Management::Deployment::implementation::FindPackagesResult>>(); - // TODO: Add search timeout and error code. - winrt::Microsoft::Management::Deployment::FindPackagesResultStatus status = FindPackagesResultStatus(hr); - findPackagesResult->Initialize(status, isTruncated, matches); - - return *findPackagesResult; - } -} +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include <mutex> +#include <AppInstallerRepositorySource.h> +#include "Workflows/WorkflowBase.h" +#include "Converters.h" +#include "PackageCatalog.h" +#include "PackageCatalog.g.cpp" +#include "PackageCatalogInfo.h" +#include "FindPackagesResult.h" +#include "MatchResult.h" +#include "CatalogPackage.h" +#pragma warning( push ) +#pragma warning ( disable : 4467 6388) +// 6388 Allow CreateInstance. +#include <wil\cppwinrt_wrl.h> +// 4467 Allow use of uuid attribute for com object creation. +#include "PackageMatchFilter.h" +#pragma warning( pop ) +#include "Microsoft/PredefinedInstalledSourceFactory.h" +#include <winget/GroupPolicy.h> +#include <AppInstallerErrors.h> + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + void PackageCatalog::Initialize( + winrt::Microsoft::Management::Deployment::PackageCatalogInfo info, + std::shared_ptr<const ::AppInstaller::Repository::ISource> source, + bool isComposite) + { + m_info = info; + m_source = std::move(source); + m_isComposite = isComposite; + } + bool PackageCatalog::IsComposite() + { + // Can't use m_source->IsComposite for this because all remote sources are turned into composite sources + // behind the scenes when being opened in PackageCatalogReference.cpp so that CatalogPackage.IsInstalled works. + return m_isComposite; + } + winrt::Microsoft::Management::Deployment::PackageCatalogInfo PackageCatalog::Info() + { + return m_info; + } + winrt::Windows::Foundation::IAsyncOperation<winrt::Microsoft::Management::Deployment::FindPackagesResult> PackageCatalog::FindPackagesAsync(winrt::Microsoft::Management::Deployment::FindPackagesOptions options) + { + co_return FindPackages(options); + } + + HRESULT PopulateSearchRequestFromVector( + ::AppInstaller::Repository::SearchRequest* searchRequest, + Windows::Foundation::Collections::IVector<Microsoft::Management::Deployment::PackageMatchFilter> vector, + bool isSelector) + { + // Populates either the Filters vector of a searchRequest (if isSelector is false), + // or the Inclusions and Query (if true) + for (uint32_t i = 0; i < vector.Size(); ++i) + { + Microsoft::Management::Deployment::PackageMatchFilter filter = vector.GetAt(i); + + if (filter.Value().size() == 0) + { + // If the caller did not add a value it can't actually be used to filter or include anything so just ignore it. + continue; + } + ::AppInstaller::Repository::MatchType packageFieldMatchOption = GetRepositoryMatchType(filter.Option()); + ::AppInstaller::Repository::PackageMatchField matchField = GetRepositoryMatchField(filter.Field()); + + if (isSelector) + { + if (filter.Field() == Microsoft::Management::Deployment::PackageMatchField::CatalogDefault) + { + if (searchRequest->Query.has_value()) + { + // CatalogDefault match field can't be used twice. + return E_INVALIDARG; + } + searchRequest->Query = ::AppInstaller::Repository::RequestMatch(packageFieldMatchOption, winrt::to_string(filter.Value())); + } + else + { + auto matchFilter = ::AppInstaller::Repository::PackageMatchFilter(matchField, packageFieldMatchOption, winrt::to_string(filter.Value())); + searchRequest->Inclusions.emplace_back(matchFilter); + } + } + else + { + if (filter.Field() == Microsoft::Management::Deployment::PackageMatchField::CatalogDefault) + { + // CatalogDefault match fields can't be used in the Filters. + return E_INVALIDARG; + } + auto matchFilter = ::AppInstaller::Repository::PackageMatchFilter(matchField, packageFieldMatchOption, winrt::to_string(filter.Value())); + searchRequest->Filters.emplace_back(matchFilter); + } + } + return S_OK; + } + + HRESULT PopulateSearchRequest( + ::AppInstaller::Repository::SearchRequest* searchRequest, + winrt::Microsoft::Management::Deployment::FindPackagesOptions const& options) + { + RETURN_IF_FAILED(PopulateSearchRequestFromVector(searchRequest, options.Filters(), false)); + RETURN_IF_FAILED(PopulateSearchRequestFromVector(searchRequest, options.Selectors(), true)); + return S_OK; + } + + winrt::Microsoft::Management::Deployment::FindPackagesResult PackageCatalog::FindPackages(winrt::Microsoft::Management::Deployment::FindPackagesOptions const& options) + { + winrt::Microsoft::Management::Deployment::FindPackagesResultStatus::Ok; + bool isTruncated = false; + Windows::Foundation::Collections::IVector<Microsoft::Management::Deployment::MatchResult> matches{ winrt::single_threaded_vector<Microsoft::Management::Deployment::MatchResult>() }; + ::AppInstaller::Repository::SearchRequest searchRequest; + + HRESULT hr = PopulateSearchRequest(&searchRequest, options); + if (SUCCEEDED(hr)) + { + searchRequest.MaximumResults = options.ResultLimit(); + try + { + auto searchResult = m_source->Search(searchRequest); + + // Build the result object from the searchResult + for (size_t i = 0; i < searchResult.Matches.size(); ++i) + { + auto match = searchResult.Matches[i]; + auto catalogPackage = winrt::make_self<wil::details::module_count_wrapper< + winrt::Microsoft::Management::Deployment::implementation::CatalogPackage>>(); + catalogPackage->Initialize(m_source, match.Package); + + auto packageMatchFilter = winrt::make_self<wil::details::module_count_wrapper< + winrt::Microsoft::Management::Deployment::implementation::PackageMatchFilter>>(); + packageMatchFilter->Initialize(match.MatchCriteria); + + auto matchResult = winrt::make_self<wil::details::module_count_wrapper< + winrt::Microsoft::Management::Deployment::implementation::MatchResult>>(); + matchResult->Initialize(*catalogPackage, *packageMatchFilter); + + matches.Append(*matchResult); + } + isTruncated = searchResult.Truncated; + } + // Exceptions that may occur in the process of executing an arbitrary command + catch (const wil::ResultException& re) + { + hr = re.GetErrorCode(); + } + catch (const winrt::hresult_error& hre) + { + hr = hre.code(); + } + catch (const ::AppInstaller::Settings::GroupPolicyException&) + { + // Policy could have changed since server started. + hr = APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY; + } + catch (const std::exception&) + { + hr = APPINSTALLER_CLI_ERROR_COMMAND_FAILED; + } + catch (...) + { + hr = APPINSTALLER_CLI_ERROR_COMMAND_FAILED; + } + } + auto findPackagesResult = winrt::make_self<wil::details::module_count_wrapper< + winrt::Microsoft::Management::Deployment::implementation::FindPackagesResult>>(); + // TODO: Add search timeout and error code. + winrt::Microsoft::Management::Deployment::FindPackagesResultStatus status = FindPackagesResultStatus(hr); + findPackagesResult->Initialize(status, isTruncated, matches); + + return *findPackagesResult; + } +} diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp @@ -1,97 +1,109 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -#include "pch.h" -#include <AppInstallerRepositorySource.h> -#include "PackageCatalogReference.h" -#include "PackageCatalogReference.g.cpp" -#include "PackageCatalogInfo.h" -#include "PackageCatalog.h" -#include "ConnectResult.h" -#include "Converters.h" -#include "Microsoft/PredefinedInstalledSourceFactory.h" -#include <wil\cppwinrt_wrl.h> - -namespace winrt::Microsoft::Management::Deployment::implementation -{ - void PackageCatalogReference::Initialize(winrt::Microsoft::Management::Deployment::PackageCatalogInfo packageCatalogInfo) - { - m_info = packageCatalogInfo; - } - void PackageCatalogReference::Initialize(winrt::Microsoft::Management::Deployment::CreateCompositePackageCatalogOptions options) - { - m_compositePackageCatalogOptions = options; - m_isComposite = true; - } - bool PackageCatalogReference::IsComposite() - { - return m_isComposite; - } - winrt::Microsoft::Management::Deployment::PackageCatalogInfo PackageCatalogReference::Info() - { - return m_info; - } - winrt::Windows::Foundation::IAsyncOperation<winrt::Microsoft::Management::Deployment::ConnectResult> PackageCatalogReference::ConnectAsync() - { - co_return Connect(); - } - winrt::Microsoft::Management::Deployment::ConnectResult PackageCatalogReference::Connect() - { - ::AppInstaller::ProgressCallback progress; - std::shared_ptr<::AppInstaller::Repository::ISource> source; - if (m_compositePackageCatalogOptions) - { - std::vector<std::shared_ptr<::AppInstaller::Repository::ISource>> remoteSources; - - for (uint32_t i = 0; i < m_compositePackageCatalogOptions.Catalogs().Size(); ++i) - { - auto catalog = m_compositePackageCatalogOptions.Catalogs().GetAt(i); - winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo* catalogInfoImpl = get_self<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo>(catalog.Info()); - ::AppInstaller::Repository::SourceDetails sourceDetails = catalogInfoImpl->GetSourceDetails(); - std::shared_ptr<::AppInstaller::Repository::ISource> remoteSource = ::AppInstaller::Repository::OpenSourceFromDetails(sourceDetails, progress).Source; - if (!remoteSource) - { - // If source is null, return the error. There's no way to get the hresult that caused the error right now. - auto connectResult = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::ConnectResult>>(); - connectResult->Initialize(winrt::Microsoft::Management::Deployment::ConnectResultStatus::CatalogError, nullptr); - return *connectResult; - } - remoteSources.emplace_back(std::move(remoteSource)); - } - ::AppInstaller::Repository::CompositeSearchBehavior searchBehavior = GetRepositoryCompositeSearchBehavior(m_compositePackageCatalogOptions.CompositeSearchBehavior()); - - std::shared_ptr<::AppInstaller::Repository::ISource> installedSource; - // Check if search behavior indicates that the caller does not want to do local correlation. - if (m_compositePackageCatalogOptions.CompositeSearchBehavior() != Microsoft::Management::Deployment::CompositeSearchBehavior::RemotePackagesFromRemoteCatalogs) - { - installedSource = ::AppInstaller::Repository::OpenPredefinedSource(::AppInstaller::Repository::PredefinedSource::Installed, progress); - } - - // Create the composite source. - source = ::AppInstaller::Repository::CreateCompositeSource(installedSource, remoteSources, searchBehavior); - } - else - { - winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo* catalogInfoImpl = get_self<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo>(m_info); - ::AppInstaller::Repository::SourceDetails sourceDetails = catalogInfoImpl->GetSourceDetails(); - source = ::AppInstaller::Repository::OpenSourceFromDetails(sourceDetails, progress).Source; - } - - if (!source) - { - // If source is null, return the error. There's no way to get the hresult that caused the error right now. - auto connectResult = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::ConnectResult>>(); - connectResult->Initialize(winrt::Microsoft::Management::Deployment::ConnectResultStatus::CatalogError, nullptr); - return *connectResult; - } - - // Have to make another package catalog info because source->GetDetails has more fields than m_info does. - // Specifically, Rest sources do not have the Ids filled in m_info since they only get the id from the rest server after being Opened. - auto packageCatalogInfo = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo>>(); - packageCatalogInfo->Initialize(source->GetDetails()); - auto connectResult = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::ConnectResult>>(); - auto packageCatalog = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalog>>(); - packageCatalog->Initialize(*packageCatalogInfo, source, (m_compositePackageCatalogOptions != nullptr)); - connectResult->Initialize(winrt::Microsoft::Management::Deployment::ConnectResultStatus::Ok, *packageCatalog); - return *connectResult; - } -} +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include <AppInstallerRepositorySource.h> +#include "PackageCatalogReference.h" +#include "PackageCatalogReference.g.cpp" +#include "PackageCatalogInfo.h" +#include "PackageCatalog.h" +#include "ConnectResult.h" +#include "Workflows/WorkflowBase.h" +#include "Converters.h" +#include "Microsoft/PredefinedInstalledSourceFactory.h" +#include <wil\cppwinrt_wrl.h> +#include <winget/GroupPolicy.h> +#include <AppInstallerErrors.h> + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + void PackageCatalogReference::Initialize(winrt::Microsoft::Management::Deployment::PackageCatalogInfo packageCatalogInfo) + { + m_info = packageCatalogInfo; + } + void PackageCatalogReference::Initialize(winrt::Microsoft::Management::Deployment::CreateCompositePackageCatalogOptions options) + { + m_compositePackageCatalogOptions = options; + m_isComposite = true; + } + bool PackageCatalogReference::IsComposite() + { + return m_isComposite; + } + winrt::Microsoft::Management::Deployment::PackageCatalogInfo PackageCatalogReference::Info() + { + return m_info; + } + winrt::Windows::Foundation::IAsyncOperation<winrt::Microsoft::Management::Deployment::ConnectResult> PackageCatalogReference::ConnectAsync() + { + co_return Connect(); + } + winrt::Microsoft::Management::Deployment::ConnectResult PackageCatalogReference::Connect() + { + try + { + ::AppInstaller::ProgressCallback progress; + std::shared_ptr<::AppInstaller::Repository::ISource> source; + if (m_compositePackageCatalogOptions) + { + std::vector<std::shared_ptr<::AppInstaller::Repository::ISource>> remoteSources; + + for (uint32_t i = 0; i < m_compositePackageCatalogOptions.Catalogs().Size(); ++i) + { + auto catalog = m_compositePackageCatalogOptions.Catalogs().GetAt(i); + winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo* catalogInfoImpl = get_self<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo>(catalog.Info()); + ::AppInstaller::Repository::SourceDetails sourceDetails = catalogInfoImpl->GetSourceDetails(); + std::shared_ptr<::AppInstaller::Repository::ISource> remoteSource = ::AppInstaller::Repository::OpenSourceFromDetails(sourceDetails, progress).Source; + if (!remoteSource) + { + // If source is null, return the error. There's no way to get the hresult that caused the error right now. + auto connectResult = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::ConnectResult>>(); + connectResult->Initialize(winrt::Microsoft::Management::Deployment::ConnectResultStatus::CatalogError, nullptr); + return *connectResult; + } + remoteSources.emplace_back(std::move(remoteSource)); + } + ::AppInstaller::Repository::CompositeSearchBehavior searchBehavior = GetRepositoryCompositeSearchBehavior(m_compositePackageCatalogOptions.CompositeSearchBehavior()); + + std::shared_ptr<::AppInstaller::Repository::ISource> installedSource; + // Check if search behavior indicates that the caller does not want to do local correlation. + if (m_compositePackageCatalogOptions.CompositeSearchBehavior() != Microsoft::Management::Deployment::CompositeSearchBehavior::RemotePackagesFromRemoteCatalogs) + { + installedSource = ::AppInstaller::Repository::OpenPredefinedSource(::AppInstaller::Repository::PredefinedSource::Installed, progress); + } + + // Create the composite source. + source = ::AppInstaller::Repository::CreateCompositeSource(installedSource, remoteSources, searchBehavior); + } + else + { + winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo* catalogInfoImpl = get_self<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo>(m_info); + ::AppInstaller::Repository::SourceDetails sourceDetails = catalogInfoImpl->GetSourceDetails(); + source = ::AppInstaller::Repository::OpenSourceFromDetails(sourceDetails, progress).Source; + } + + if (!source) + { + // If source is null, return the error. There's no way to get the hresult that caused the error right now. + auto connectResult = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::ConnectResult>>(); + connectResult->Initialize(winrt::Microsoft::Management::Deployment::ConnectResultStatus::CatalogError, nullptr); + return *connectResult; + } + + // Have to make another package catalog info because source->GetDetails has more fields than m_info does. + // Specifically, Rest sources do not have the Ids filled in m_info since they only get the id from the rest server after being Opened. + auto packageCatalogInfo = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo>>(); + packageCatalogInfo->Initialize(source->GetDetails()); + auto connectResult = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::ConnectResult>>(); + auto packageCatalog = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalog>>(); + packageCatalog->Initialize(*packageCatalogInfo, source, (m_compositePackageCatalogOptions != nullptr)); + connectResult->Initialize(winrt::Microsoft::Management::Deployment::ConnectResultStatus::Ok, *packageCatalog); + return *connectResult; + } + catch (...) + { + } + auto connectResult = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::ConnectResult>>(); + connectResult->Initialize(winrt::Microsoft::Management::Deployment::ConnectResultStatus::CatalogError, nullptr); + return *connectResult; + } +} diff --git a/src/Microsoft.Management.Deployment/PackageManager.cpp b/src/Microsoft.Management.Deployment/PackageManager.cpp @@ -1,318 +1,354 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -#include "pch.h" -#include "Public/AppInstallerCLICore.h" -#include "Microsoft/PredefinedInstalledSourceFactory.h" -#include "Commands/RootCommand.h" -#include "ComContext.h" -#include "ExecutionContext.h" -#include "Workflows/WorkflowBase.h" -#include <winget/UserSettings.h> -#include "Commands/InstallCommand.h" -#include <AppInstallerTelemetry.h> -#include <AppInstallerErrors.h> -#pragma warning( push ) -#pragma warning ( disable : 4467 6388) -// 6388 Allow CreateInstance. -#include <wil\cppwinrt_wrl.h> -// 4467 Allow use of uuid attribute for com object creation. -#include "PackageManager.h" -#pragma warning( pop ) -#include "PackageManager.g.cpp" -#include "InstallResult.h" -#include "PackageCatalogInfo.h" -#include "PackageCatalogReference.h" -#include "PackageVersionInfo.h" -#include "PackageVersionId.h" -#include "Converters.h" -#include "Helpers.h" - -using namespace std::literals::chrono_literals; - -const GUID PackageManagerCLSID1 = { 0xC53A4F16, 0x787E, 0x42A4, { 0xB3, 0x04, 0x29, 0xEF, 0xFB, 0x4B, 0xF5, 0x97 } }; //C53A4F16-787E-42A4-B304-29EFFB4BF597 -const GUID PackageManagerCLSID2 = { 0xE65C7D5A, 0x95AF, 0x4A98, { 0xBE, 0x5F, 0xA7, 0x93, 0x02, 0x9C, 0xEB, 0x56 } }; //E65C7D5A-95AF-4A98-BE5F-A793029CEB56 - -namespace winrt::Microsoft::Management::Deployment::implementation -{ - winrt::Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Management::Deployment::PackageCatalogReference> PackageManager::GetPackageCatalogs() - { - Windows::Foundation::Collections::IVector<Microsoft::Management::Deployment::PackageCatalogReference> catalogs{ winrt::single_threaded_vector<Microsoft::Management::Deployment::PackageCatalogReference>() }; - std::vector<::AppInstaller::Repository::SourceDetails> sources = ::AppInstaller::Repository::GetSources(); - for (uint32_t i = 0; i < sources.size(); i++) - { - auto packageCatalogInfo = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo>>(); - packageCatalogInfo->Initialize(sources.at(i)); - auto packageCatalogRef = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogReference>>(); - packageCatalogRef->Initialize(*packageCatalogInfo); - catalogs.Append(*packageCatalogRef); - } - return catalogs.GetView(); - } - winrt::Microsoft::Management::Deployment::PackageCatalogReference PackageManager::GetPredefinedPackageCatalog(winrt::Microsoft::Management::Deployment::PredefinedPackageCatalog const& predefinedPackageCatalog) - { - ::AppInstaller::Repository::SourceDetails sourceDetails; - switch (predefinedPackageCatalog) - { - case winrt::Microsoft::Management::Deployment::PredefinedPackageCatalog::OpenWindowsCatalog: - { - sourceDetails = GetWellKnownSourceDetails(::AppInstaller::Repository::WellKnownSource::WinGet); - auto packageCatalogInfo = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo>>(); - packageCatalogInfo->Initialize(sourceDetails); - auto packageCatalogRef = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogReference>>(); - packageCatalogRef->Initialize(*packageCatalogInfo); - return *packageCatalogRef; - } - default: - throw hresult_invalid_argument(); - } - } - winrt::Microsoft::Management::Deployment::PackageCatalogReference PackageManager::GetLocalPackageCatalog(winrt::Microsoft::Management::Deployment::LocalPackageCatalog const& localPackageCatalog) - { - // InstalledPackages is the only one supported right now, so return early if it's not that. - if(localPackageCatalog != Microsoft::Management::Deployment::LocalPackageCatalog::InstalledPackages) - { - throw hresult_invalid_argument(); - } - ::AppInstaller::Repository::SourceDetails sourceDetails = GetPredefinedSourceDetails(::AppInstaller::Repository::PredefinedSource::Installed); - auto packageCatalogInfo = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo>>(); - packageCatalogInfo->Initialize(sourceDetails); - auto packageCatalogImpl = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogReference>>(); - packageCatalogImpl->Initialize(*packageCatalogInfo); - return *packageCatalogImpl; - } - winrt::Microsoft::Management::Deployment::PackageCatalogReference PackageManager::GetPackageCatalogByName(hstring const& catalogName) - { - std::optional<::AppInstaller::Repository::SourceDetails> source = ::AppInstaller::Repository::GetSource(winrt::to_string(catalogName)); - // Create the catalog object if the source is found, otherwise return null. Don't throw. - if (source.has_value()) - { - auto packageCatalogInfo = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo>>(); - packageCatalogInfo->Initialize(source.value()); - auto packageCatalogRef = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogReference>>(); - packageCatalogRef->Initialize(*packageCatalogInfo); - return *packageCatalogRef; - } - else - { - return nullptr; - } - } - winrt::Microsoft::Management::Deployment::PackageCatalogReference PackageManager::CreateCompositePackageCatalog(winrt::Microsoft::Management::Deployment::CreateCompositePackageCatalogOptions const& options) - { - for (uint32_t i = 0; i < options.Catalogs().Size(); ++i) - { - auto catalog = options.Catalogs().GetAt(i); - if (catalog.IsComposite()) - { - // Can't make a composite source out of a source that's already a composite. - throw hresult_invalid_argument(); - } - } - auto packageCatalogImpl = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogReference>>(); - packageCatalogImpl->Initialize(options); - return *packageCatalogImpl; - } - - Windows::Foundation::IAsyncAction ExecuteInstallAsync(::AppInstaller::CLI::Execution::Context& context, std::unique_ptr<::AppInstaller::CLI::Command>& command) - { - co_await winrt::resume_background(); - ::AppInstaller::CLI::Execute(context, command); - } - winrt::Windows::Foundation::IAsyncOperationWithProgress<winrt::Microsoft::Management::Deployment::InstallResult, winrt::Microsoft::Management::Deployment::InstallProgress> PackageManager::InstallPackageAsync(winrt::Microsoft::Management::Deployment::CatalogPackage package, winrt::Microsoft::Management::Deployment::InstallOptions options) - { - auto report_progress{ co_await winrt::get_progress_token() }; - auto cancellationToken{ co_await winrt::get_cancellation_token() }; - - InstallProgress queuedProgress{ PackageInstallProgressState::Queued, 0, 0, 0 }; - report_progress(queuedProgress); - - Microsoft::Management::Deployment::PackageVersionId versionId{ nullptr }; - if (options) - { - versionId = options.PackageVersionId(); - } - - // If the version of the package is specified use that, otherwise use the default. - Microsoft::Management::Deployment::PackageVersionInfo packageVersionInfo{ nullptr }; - if (versionId) - { - packageVersionInfo = package.GetPackageVersionInfo(versionId); - } - else - { - packageVersionInfo = package.DefaultInstallVersion(); - } - - if (!packageVersionInfo) - { - // If no package version was found on the catalog then return a failure. This is unexpected, a catalog with no latest version should not be in the catalog. - HRESULT terminationHR = APPINSTALLER_CLI_ERROR_NO_APPLICABLE_INSTALLER; - winrt::Microsoft::Management::Deployment::InstallResultStatus installResultStatus = GetInstallResultStatus(terminationHR); - auto installResult = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::InstallResult>>(); - installResult->Initialize(installResultStatus, terminationHR, options.CorrelationData(), false); - co_return *installResult; - } - - // Handle the progress from the installer - ::AppInstaller::COMContext context; - - // TODO: Exact ComCaller's process name needs to be retrieved from COM Client side in the future - context.SetLoggerContext(options.CorrelationData(), "COMCaller"); - - context.SetProgressCallbackFunction([=]( - ::AppInstaller::ReportType reportType, - uint64_t current, - uint64_t maximum, - ::AppInstaller::ProgressType progressType, - ::AppInstaller::CLI::Workflow::ExecutionStage executionPhase) - { - bool reportProgress = false; - PackageInstallProgressState progressState = PackageInstallProgressState::Queued; - double downloadProgress = 0; - double installProgress = 0; - uint64_t downloadBytesDownloaded = 0; - uint64_t downloadBytesRequired = 0; - switch (executionPhase) - { - case ::AppInstaller::CLI::Workflow::ExecutionStage::Initial: - case ::AppInstaller::CLI::Workflow::ExecutionStage::ParseArgs: - case ::AppInstaller::CLI::Workflow::ExecutionStage::Discovery: - // We already reported queued progress up front. - break; - case ::AppInstaller::CLI::Workflow::ExecutionStage::Download: - progressState = PackageInstallProgressState::Downloading; - if (reportType == ::AppInstaller::ReportType::BeginProgress) - { - reportProgress = true; - } - else if (progressType == ::AppInstaller::ProgressType::Bytes) - { - downloadBytesDownloaded = current; - downloadBytesRequired = maximum; - if (maximum > 0 && maximum >= current) - { - reportProgress = true; - downloadProgress = static_cast<double>(current) / static_cast<double>(maximum); - } - } - break; - case ::AppInstaller::CLI::Workflow::ExecutionStage::PreExecution: - // Wait until installer starts to report Installing. - break; - case ::AppInstaller::CLI::Workflow::ExecutionStage::Execution: - progressState = PackageInstallProgressState::Installing; - downloadProgress = 1; - if (reportType == ::AppInstaller::ReportType::ExecutionPhaseUpdate) - { - // Install is starting. Send progress so callers know the AsyncOperation can't be cancelled. - reportProgress = true; - } - else if (reportType == ::AppInstaller::ReportType::EndProgress) - { - // Install is "finished". May not have succeeded. - reportProgress = true; - installProgress = 1; - } - else if (progressType == ::AppInstaller::ProgressType::Percent) - { - if (maximum > 0 && maximum >= current) - { - // Install is progressing - reportProgress = true; - installProgress = static_cast<double>(current) / static_cast<double>(maximum); - } - } - break; - case ::AppInstaller::CLI::Workflow::ExecutionStage::PostExecution: - if (reportType == ::AppInstaller::ReportType::ExecutionPhaseUpdate) - { - // Send PostInstall progress when it switches to PostExecution phase. - reportProgress = true; - progressState = PackageInstallProgressState::PostInstall; - downloadProgress = 1; - installProgress = 1; - } - break; - } - if (reportProgress) - { - winrt::Microsoft::Management::Deployment::InstallProgress contextProgress{ progressState, downloadBytesDownloaded, downloadBytesRequired, downloadProgress, installProgress }; - report_progress(contextProgress); - } - return; - } - ); - context.EnableCtrlHandler(); - - // Convert the options to arguments for the installer. - context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Id, ::AppInstaller::Utility::ConvertToUTF8(package.Id())); - context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Version, ::AppInstaller::Utility::ConvertToUTF8(packageVersionInfo.Version())); - context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Channel, ::AppInstaller::Utility::ConvertToUTF8(packageVersionInfo.Channel())); - context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Source, ::AppInstaller::Utility::ConvertToUTF8(packageVersionInfo.PackageCatalog().Info().Name())); - context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Exact); - if (options) - { - if (!options.LogOutputPath().empty()) - { - context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Log, ::AppInstaller::Utility::ConvertToUTF8(options.LogOutputPath())); - context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::VerboseLogs); - } - if (options.AllowHashMismatch()) - { - context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::HashOverride); - } - - // If the PackageInstallScope is anything other than ::Any then set it as a requirement. - if (options.PackageInstallScope() == PackageInstallScope::System) - { - context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::InstallScope, ScopeToString(::AppInstaller::Manifest::ScopeEnum::Machine)); - } - else if (options.PackageInstallScope() == PackageInstallScope::User) - { - context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::InstallScope, ScopeToString(::AppInstaller::Manifest::ScopeEnum::User)); - } - - if (options.PackageInstallMode() == PackageInstallMode::Interactive) - { - context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Interactive); - } - else if (options.PackageInstallMode() == PackageInstallMode::Silent) - { - context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Silent); - } - - if (!options.PreferredInstallLocation().empty()) - { - context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::InstallLocation, ::AppInstaller::Utility::ConvertToUTF8(options.PreferredInstallLocation())); - } - - if (!options.ReplacementInstallerArguments().empty()) - { - context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Override, ::AppInstaller::Utility::ConvertToUTF8(options.ReplacementInstallerArguments())); - } - } - - // TODO: AdditionalPackageCatalogArguments is not currently supported by the underlying implementation. - ::AppInstaller::CLI::RootCommand rootCommand; - std::unique_ptr<::AppInstaller::CLI::Command> command = std::make_unique<::AppInstaller::CLI::InstallCommand>(rootCommand.Name()); - Windows::Foundation::IAsyncAction executeOperation = ExecuteInstallAsync(context, command); - - cancellationToken.callback([&context] - { - context.Cancel(false, true); - }); - // Wait for the execute operation to finish. - // The cancellation of the AsyncOperation triggers Terminate which causes the executeOperation to end. - co_await executeOperation; - - HRESULT terminationHR = context.GetTerminationHR(); - winrt::Microsoft::Management::Deployment::InstallResultStatus installResultStatus = GetInstallResultStatus(terminationHR); - - // TODO - RebootRequired not yet populated, msi arguments not returned from Execute. - auto installResult = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::InstallResult>>(); - installResult->Initialize(installResultStatus, terminationHR, options.CorrelationData(), false); - co_return *installResult; - } - CoCreatableCppWinRtClassWithCLSID(PackageManager, 1, &PackageManagerCLSID1); - CoCreatableCppWinRtClassWithCLSID(PackageManager, 2, &PackageManagerCLSID2); -} +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "Public/AppInstallerCLICore.h" +#include "Microsoft/PredefinedInstalledSourceFactory.h" +#include "Commands/RootCommand.h" +#include "ComContext.h" +#include "ExecutionContext.h" +#include "Workflows/WorkflowBase.h" +#include <winget/UserSettings.h> +#include "Commands/InstallCommand.h" +#include <AppInstallerTelemetry.h> +#include <AppInstallerErrors.h> +#pragma warning( push ) +#pragma warning ( disable : 4467 6388) +// 6388 Allow CreateInstance. +#include <wil\cppwinrt_wrl.h> +// 4467 Allow use of uuid attribute for com object creation. +#include "PackageManager.h" +#pragma warning( pop ) +#include "PackageManager.g.cpp" +#include "InstallResult.h" +#include "PackageCatalogInfo.h" +#include "PackageCatalogReference.h" +#include "PackageVersionInfo.h" +#include "PackageVersionId.h" +#include "Workflows/WorkflowBase.h" +#include "Converters.h" +#include "Helpers.h" + +using namespace std::literals::chrono_literals; + +const GUID PackageManagerCLSID1 = { 0xC53A4F16, 0x787E, 0x42A4, { 0xB3, 0x04, 0x29, 0xEF, 0xFB, 0x4B, 0xF5, 0x97 } }; //C53A4F16-787E-42A4-B304-29EFFB4BF597 +const GUID PackageManagerCLSID2 = { 0xE65C7D5A, 0x95AF, 0x4A98, { 0xBE, 0x5F, 0xA7, 0x93, 0x02, 0x9C, 0xEB, 0x56 } }; //E65C7D5A-95AF-4A98-BE5F-A793029CEB56 + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + winrt::Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Management::Deployment::PackageCatalogReference> PackageManager::GetPackageCatalogs() + { + Windows::Foundation::Collections::IVector<Microsoft::Management::Deployment::PackageCatalogReference> catalogs{ winrt::single_threaded_vector<Microsoft::Management::Deployment::PackageCatalogReference>() }; + std::vector<::AppInstaller::Repository::SourceDetails> sources = ::AppInstaller::Repository::GetSources(); + for (uint32_t i = 0; i < sources.size(); i++) + { + auto packageCatalogInfo = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo>>(); + packageCatalogInfo->Initialize(sources.at(i)); + auto packageCatalogRef = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogReference>>(); + packageCatalogRef->Initialize(*packageCatalogInfo); + catalogs.Append(*packageCatalogRef); + } + return catalogs.GetView(); + } + winrt::Microsoft::Management::Deployment::PackageCatalogReference PackageManager::GetPredefinedPackageCatalog(winrt::Microsoft::Management::Deployment::PredefinedPackageCatalog const& predefinedPackageCatalog) + { + ::AppInstaller::Repository::SourceDetails sourceDetails; + switch (predefinedPackageCatalog) + { + case winrt::Microsoft::Management::Deployment::PredefinedPackageCatalog::OpenWindowsCatalog: + { + sourceDetails = GetWellKnownSourceDetails(::AppInstaller::Repository::WellKnownSource::WinGet); + auto packageCatalogInfo = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo>>(); + packageCatalogInfo->Initialize(sourceDetails); + auto packageCatalogRef = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogReference>>(); + packageCatalogRef->Initialize(*packageCatalogInfo); + return *packageCatalogRef; + } + default: + throw hresult_invalid_argument(); + } + } + winrt::Microsoft::Management::Deployment::PackageCatalogReference PackageManager::GetLocalPackageCatalog(winrt::Microsoft::Management::Deployment::LocalPackageCatalog const& localPackageCatalog) + { + // InstalledPackages is the only one supported right now, so return early if it's not that. + if(localPackageCatalog != Microsoft::Management::Deployment::LocalPackageCatalog::InstalledPackages) + { + throw hresult_invalid_argument(); + } + ::AppInstaller::Repository::SourceDetails sourceDetails = GetPredefinedSourceDetails(::AppInstaller::Repository::PredefinedSource::Installed); + auto packageCatalogInfo = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo>>(); + packageCatalogInfo->Initialize(sourceDetails); + auto packageCatalogImpl = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogReference>>(); + packageCatalogImpl->Initialize(*packageCatalogInfo); + return *packageCatalogImpl; + } + winrt::Microsoft::Management::Deployment::PackageCatalogReference PackageManager::GetPackageCatalogByName(hstring const& catalogName) + { + std::optional<::AppInstaller::Repository::SourceDetails> source = ::AppInstaller::Repository::GetSource(winrt::to_string(catalogName)); + // Create the catalog object if the source is found, otherwise return null. Don't throw. + if (source.has_value()) + { + auto packageCatalogInfo = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo>>(); + packageCatalogInfo->Initialize(source.value()); + auto packageCatalogRef = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogReference>>(); + packageCatalogRef->Initialize(*packageCatalogInfo); + return *packageCatalogRef; + } + else + { + return nullptr; + } + } + winrt::Microsoft::Management::Deployment::PackageCatalogReference PackageManager::CreateCompositePackageCatalog(winrt::Microsoft::Management::Deployment::CreateCompositePackageCatalogOptions const& options) + { + for (uint32_t i = 0; i < options.Catalogs().Size(); ++i) + { + auto catalog = options.Catalogs().GetAt(i); + if (catalog.IsComposite()) + { + // Can't make a composite source out of a source that's already a composite. + throw hresult_invalid_argument(); + } + } + auto packageCatalogImpl = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogReference>>(); + packageCatalogImpl->Initialize(options); + return *packageCatalogImpl; + } + + Windows::Foundation::IAsyncOperation<winrt::hresult> ExecuteInstallAsync(::AppInstaller::CLI::Execution::Context& context, std::unique_ptr<::AppInstaller::CLI::Command>& command) + { + co_await winrt::resume_background(); + winrt::hresult result = ::AppInstaller::CLI::Execute(context, command); + return result; + } + winrt::Windows::Foundation::IAsyncOperationWithProgress<winrt::Microsoft::Management::Deployment::InstallResult, winrt::Microsoft::Management::Deployment::InstallProgress> PackageManager::InstallPackageAsync(winrt::Microsoft::Management::Deployment::CatalogPackage package, winrt::Microsoft::Management::Deployment::InstallOptions options) + { + auto report_progress{ co_await winrt::get_progress_token() }; + auto cancellationToken{ co_await winrt::get_cancellation_token() }; + + InstallProgress queuedProgress{ PackageInstallProgressState::Queued, 0, 0, 0 }; + report_progress(queuedProgress); + + winrt::hresult terminationHR = S_OK; + ::AppInstaller::CLI::Workflow::ExecutionStage executionStage = ::AppInstaller::CLI::Workflow::ExecutionStage::Initial; + + try + { + Microsoft::Management::Deployment::PackageVersionId versionId{ nullptr }; + if (options) + { + versionId = options.PackageVersionId(); + } + + // If the version of the package is specified use that, otherwise use the default. + Microsoft::Management::Deployment::PackageVersionInfo packageVersionInfo{ nullptr }; + if (versionId) + { + packageVersionInfo = package.GetPackageVersionInfo(versionId); + } + else + { + packageVersionInfo = package.DefaultInstallVersion(); + } + + if (!packageVersionInfo) + { + // If no package version was found on the catalog then return a failure. This is unexpected, a catalog with no latest version should not be in the catalog. + terminationHR = APPINSTALLER_CLI_ERROR_NO_APPLICABLE_INSTALLER; + winrt::Microsoft::Management::Deployment::InstallResultStatus installResultStatus = GetInstallResultStatus(executionStage, terminationHR); + auto installResult = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::InstallResult>>(); + installResult->Initialize(installResultStatus, terminationHR, options.CorrelationData(), false); + co_return *installResult; + } + + // Handle the progress from the installer + ::AppInstaller::COMContext context; + + // TODO: Exact ComCaller's process name needs to be retrieved from COM Client side in the future + context.SetLoggerContext(options.CorrelationData(), "COMCaller"); + + // Convert the options to arguments for the installer. + context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Id, ::AppInstaller::Utility::ConvertToUTF8(package.Id())); + context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Version, ::AppInstaller::Utility::ConvertToUTF8(packageVersionInfo.Version())); + context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Channel, ::AppInstaller::Utility::ConvertToUTF8(packageVersionInfo.Channel())); + context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Source, ::AppInstaller::Utility::ConvertToUTF8(packageVersionInfo.PackageCatalog().Info().Name())); + context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Exact); + if (options) + { + if (!options.LogOutputPath().empty()) + { + context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Log, ::AppInstaller::Utility::ConvertToUTF8(options.LogOutputPath())); + context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::VerboseLogs); + } + if (options.AllowHashMismatch()) + { + context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::HashOverride); + } + + // If the PackageInstallScope is anything other than ::Any then set it as a requirement. + if (options.PackageInstallScope() == PackageInstallScope::System) + { + context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::InstallScope, ScopeToString(::AppInstaller::Manifest::ScopeEnum::Machine)); + } + else if (options.PackageInstallScope() == PackageInstallScope::User) + { + context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::InstallScope, ScopeToString(::AppInstaller::Manifest::ScopeEnum::User)); + } + + if (options.PackageInstallMode() == PackageInstallMode::Interactive) + { + context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Interactive); + } + else if (options.PackageInstallMode() == PackageInstallMode::Silent) + { + context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Silent); + } + + if (!options.PreferredInstallLocation().empty()) + { + context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::InstallLocation, ::AppInstaller::Utility::ConvertToUTF8(options.PreferredInstallLocation())); + } + + if (!options.ReplacementInstallerArguments().empty()) + { + context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Override, ::AppInstaller::Utility::ConvertToUTF8(options.ReplacementInstallerArguments())); + } + } + + // TODO: AdditionalPackageCatalogArguments is not currently supported by the underlying implementation. + ::AppInstaller::CLI::RootCommand rootCommand; + std::unique_ptr<::AppInstaller::CLI::Command> command = std::make_unique<::AppInstaller::CLI::InstallCommand>(rootCommand.Name()); + rootCommand.ValidateArguments(context.Args); + + context.SetProgressCallbackFunction([=]( + ::AppInstaller::ReportType reportType, + uint64_t current, + uint64_t maximum, + ::AppInstaller::ProgressType progressType, + ::AppInstaller::CLI::Workflow::ExecutionStage executionPhase) + { + bool reportProgress = false; + PackageInstallProgressState progressState = PackageInstallProgressState::Queued; + double downloadProgress = 0; + double installProgress = 0; + uint64_t downloadBytesDownloaded = 0; + uint64_t downloadBytesRequired = 0; + switch (executionPhase) + { + case ::AppInstaller::CLI::Workflow::ExecutionStage::Initial: + case ::AppInstaller::CLI::Workflow::ExecutionStage::ParseArgs: + case ::AppInstaller::CLI::Workflow::ExecutionStage::Discovery: + // We already reported queued progress up front. + break; + case ::AppInstaller::CLI::Workflow::ExecutionStage::Download: + progressState = PackageInstallProgressState::Downloading; + if (reportType == ::AppInstaller::ReportType::BeginProgress) + { + reportProgress = true; + } + else if (progressType == ::AppInstaller::ProgressType::Bytes) + { + downloadBytesDownloaded = current; + downloadBytesRequired = maximum; + if (maximum > 0 && maximum >= current) + { + reportProgress = true; + downloadProgress = static_cast<double>(current) / static_cast<double>(maximum); + } + } + break; + case ::AppInstaller::CLI::Workflow::ExecutionStage::PreExecution: + // Wait until installer starts to report Installing. + break; + case ::AppInstaller::CLI::Workflow::ExecutionStage::Execution: + progressState = PackageInstallProgressState::Installing; + downloadProgress = 1; + if (reportType == ::AppInstaller::ReportType::ExecutionPhaseUpdate) + { + // Install is starting. Send progress so callers know the AsyncOperation can't be cancelled. + reportProgress = true; + } + else if (reportType == ::AppInstaller::ReportType::EndProgress) + { + // Install is "finished". May not have succeeded. + reportProgress = true; + installProgress = 1; + } + else if (progressType == ::AppInstaller::ProgressType::Percent) + { + if (maximum > 0 && maximum >= current) + { + // Install is progressing + reportProgress = true; + installProgress = static_cast<double>(current) / static_cast<double>(maximum); + } + } + break; + case ::AppInstaller::CLI::Workflow::ExecutionStage::PostExecution: + if (reportType == ::AppInstaller::ReportType::ExecutionPhaseUpdate) + { + // Send PostInstall progress when it switches to PostExecution phase. + reportProgress = true; + progressState = PackageInstallProgressState::PostInstall; + downloadProgress = 1; + installProgress = 1; + } + break; + } + if (reportProgress) + { + winrt::Microsoft::Management::Deployment::InstallProgress contextProgress{ progressState, downloadBytesDownloaded, downloadBytesRequired, downloadProgress, installProgress }; + report_progress(contextProgress); + } + return; + } + ); + context.EnableCtrlHandler(); + + Windows::Foundation::IAsyncOperation<winrt::hresult> executeOperation = ExecuteInstallAsync(context, command); + + cancellationToken.callback([&context] + { + context.Cancel(false, true); + }); + // Wait for the execute operation to finish. + // The cancellation of the AsyncOperation triggers Cancel which causes the executeOperation to end. + terminationHR = co_await executeOperation; + executionStage = context.GetExecutionStage(); + + } + // Exceptions that may occur in the process of executing an arbitrary command + catch (const wil::ResultException& re) + { + terminationHR = re.GetErrorCode(); + } + catch (const winrt::hresult_error& hre) + { + terminationHR = hre.code(); + } + catch (const ::AppInstaller::CLI::CommandException&) + { + terminationHR = APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS; + } + catch (const ::AppInstaller::Settings::GroupPolicyException&) + { + // Policy could have changed since server started + // or catalog could have been disabled since being returned. + terminationHR = APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY; + } + catch (const std::exception&) + { + terminationHR = APPINSTALLER_CLI_ERROR_COMMAND_FAILED; + } + catch (...) + { + terminationHR = APPINSTALLER_CLI_ERROR_COMMAND_FAILED; + } + // TODO - RebootRequired not yet populated, msi arguments not returned from Execute. + winrt::Microsoft::Management::Deployment::InstallResultStatus installResultStatus = GetInstallResultStatus(executionStage, terminationHR); + auto installResult = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::InstallResult>>(); + installResult->Initialize(installResultStatus, terminationHR, options.CorrelationData(), false); + co_return *installResult; + } + CoCreatableCppWinRtClassWithCLSID(PackageManager, 1, &PackageManagerCLSID1); + CoCreatableCppWinRtClassWithCLSID(PackageManager, 2, &PackageManagerCLSID2); +} diff --git a/src/Microsoft.Management.Deployment/PackageMatchFilter.cpp b/src/Microsoft.Management.Deployment/PackageMatchFilter.cpp @@ -1,54 +1,55 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -#include "pch.h" -#include <AppInstallerRepositorySource.h> -#include <AppInstallerRepositorySearch.h> -#include "Converters.h" -#pragma warning( push ) -#pragma warning ( disable : 4467 6388) -// 6388 Allow CreateInstance. -#include <wil\cppwinrt_wrl.h> -// 4467 Allow use of uuid attribute for com object creation. -#include "PackageMatchFilter.h" -#pragma warning( pop ) -#include "PackageMatchFilter.g.cpp" -#include "Helpers.h" - -const GUID PackageMatchFilterCLSID1 = { 0xD02C9DAF, 0x99DC, 0x429C, { 0xB5, 0x03, 0x4E, 0x50, 0x4E, 0x4A, 0xB0, 0x00 } }; //D02C9DAF-99DC-429C-B503-4E504E4AB000 -const GUID PackageMatchFilterCLSID2 = { 0xADBF3B4A, 0xDB8A, 0x496C, { 0xA5, 0x79, 0x62, 0xB5, 0x8F, 0x5F, 0xB1, 0x3F } }; //ADBF3B4A-DB8A-496C-A579-62B58F5FB13F - -namespace winrt::Microsoft::Management::Deployment::implementation -{ - void PackageMatchFilter::Initialize(::AppInstaller::Repository::PackageMatchFilter matchFilter) - { - m_value = winrt::to_hstring(matchFilter.Value); - m_matchField = GetDeploymentMatchField(matchFilter.Field); - m_packageFieldMatchOption = GetDeploymentMatchOption(matchFilter.Type); - } - winrt::Microsoft::Management::Deployment::PackageFieldMatchOption PackageMatchFilter::Option() - { - return m_packageFieldMatchOption; - } - void PackageMatchFilter::Option(winrt::Microsoft::Management::Deployment::PackageFieldMatchOption const& value) - { - m_packageFieldMatchOption = value; - } - winrt::Microsoft::Management::Deployment::PackageMatchField PackageMatchFilter::Field() - { - return m_matchField; - } - void PackageMatchFilter::Field(winrt::Microsoft::Management::Deployment::PackageMatchField const& value) - { - m_matchField = value; - } - hstring PackageMatchFilter::Value() - { - return hstring(m_value); - } - void PackageMatchFilter::Value(hstring const& value) - { - m_value = value; - } - CoCreatableCppWinRtClassWithCLSID(PackageMatchFilter, 1, &PackageMatchFilterCLSID1); - CoCreatableCppWinRtClassWithCLSID(PackageMatchFilter, 2, &PackageMatchFilterCLSID2); -} +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include <AppInstallerRepositorySource.h> +#include <AppInstallerRepositorySearch.h> +#include "Workflows/WorkflowBase.h" +#include "Converters.h" +#pragma warning( push ) +#pragma warning ( disable : 4467 6388) +// 6388 Allow CreateInstance. +#include <wil\cppwinrt_wrl.h> +// 4467 Allow use of uuid attribute for com object creation. +#include "PackageMatchFilter.h" +#pragma warning( pop ) +#include "PackageMatchFilter.g.cpp" +#include "Helpers.h" + +const GUID PackageMatchFilterCLSID1 = { 0xD02C9DAF, 0x99DC, 0x429C, { 0xB5, 0x03, 0x4E, 0x50, 0x4E, 0x4A, 0xB0, 0x00 } }; //D02C9DAF-99DC-429C-B503-4E504E4AB000 +const GUID PackageMatchFilterCLSID2 = { 0xADBF3B4A, 0xDB8A, 0x496C, { 0xA5, 0x79, 0x62, 0xB5, 0x8F, 0x5F, 0xB1, 0x3F } }; //ADBF3B4A-DB8A-496C-A579-62B58F5FB13F + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + void PackageMatchFilter::Initialize(::AppInstaller::Repository::PackageMatchFilter matchFilter) + { + m_value = winrt::to_hstring(matchFilter.Value); + m_matchField = GetDeploymentMatchField(matchFilter.Field); + m_packageFieldMatchOption = GetDeploymentMatchOption(matchFilter.Type); + } + winrt::Microsoft::Management::Deployment::PackageFieldMatchOption PackageMatchFilter::Option() + { + return m_packageFieldMatchOption; + } + void PackageMatchFilter::Option(winrt::Microsoft::Management::Deployment::PackageFieldMatchOption const& value) + { + m_packageFieldMatchOption = value; + } + winrt::Microsoft::Management::Deployment::PackageMatchField PackageMatchFilter::Field() + { + return m_matchField; + } + void PackageMatchFilter::Field(winrt::Microsoft::Management::Deployment::PackageMatchField const& value) + { + m_matchField = value; + } + hstring PackageMatchFilter::Value() + { + return hstring(m_value); + } + void PackageMatchFilter::Value(hstring const& value) + { + m_value = value; + } + CoCreatableCppWinRtClassWithCLSID(PackageMatchFilter, 1, &PackageMatchFilterCLSID1); + CoCreatableCppWinRtClassWithCLSID(PackageMatchFilter, 2, &PackageMatchFilterCLSID2); +} diff --git a/src/Microsoft.Management.Deployment/PackageVersionInfo.cpp b/src/Microsoft.Management.Deployment/PackageVersionInfo.cpp @@ -1,89 +1,90 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -#include "pch.h" -#include <mutex> -#include <AppInstallerRepositorySource.h> -#include "PackageVersionInfo.h" -#include "PackageVersionInfo.g.cpp" -#include "PackageCatalogInfo.h" -#include "PackageCatalog.h" -#include "CatalogPackage.h" -#include "Converters.h" -#include <wil\cppwinrt_wrl.h> - -namespace winrt::Microsoft::Management::Deployment::implementation -{ - void PackageVersionInfo::Initialize(std::shared_ptr<::AppInstaller::Repository::IPackageVersion> packageVersion) - { - m_packageVersion = std::move(packageVersion); - } - hstring PackageVersionInfo::GetMetadata(winrt::Microsoft::Management::Deployment::PackageVersionMetadataField const& metadataField) - { - ::AppInstaller::Repository::PackageVersionMetadata metadataKey = GetRepositoryPackageVersionMetadata(metadataField); - ::AppInstaller::Repository::IPackageVersion::Metadata metadata = m_packageVersion->GetMetadata(); - auto result = metadata.find(metadataKey); - hstring resultString = winrt::to_hstring(result->second); - // The api uses "System" rather than "Machine" for install scope. - if (metadataField == PackageVersionMetadataField::InstalledScope && resultString == L"Machine") - { - return winrt::to_hstring(L"System"); - } - return resultString; - } - hstring PackageVersionInfo::Id() - { - return winrt::to_hstring(m_packageVersion->GetProperty(::AppInstaller::Repository::PackageVersionProperty::Id).get()); - } - hstring PackageVersionInfo::DisplayName() - { - return winrt::to_hstring(m_packageVersion->GetProperty(::AppInstaller::Repository::PackageVersionProperty::Name).get()); - } - hstring PackageVersionInfo::Version() - { - return winrt::to_hstring(m_packageVersion->GetProperty(::AppInstaller::Repository::PackageVersionProperty::Version).get()); - } - hstring PackageVersionInfo::Channel() - { - return winrt::to_hstring(m_packageVersion->GetProperty(::AppInstaller::Repository::PackageVersionProperty::Channel).get()); - } - winrt::Windows::Foundation::Collections::IVectorView<hstring> PackageVersionInfo::PackageFamilyNames() - { - if (!m_packageFamilyNames) - { - // Vector hasn't been created yet, create and populate it. - auto packageFamilyNames = winrt::single_threaded_vector<hstring>(); - for (auto&& string : m_packageVersion->GetMultiProperty(::AppInstaller::Repository::PackageVersionMultiProperty::PackageFamilyName)) - { - packageFamilyNames.Append(winrt::to_hstring(string)); - } - m_packageFamilyNames = packageFamilyNames; - } - return m_packageFamilyNames.GetView(); - } - winrt::Windows::Foundation::Collections::IVectorView<hstring> PackageVersionInfo::ProductCodes() - { - if (!m_productCodes) - { - // Vector hasn't been created yet, create and populate it. - auto productCodes = winrt::single_threaded_vector<hstring>(); - for (auto&& string : m_packageVersion->GetMultiProperty(::AppInstaller::Repository::PackageVersionMultiProperty::ProductCode)) - { - productCodes.Append(winrt::to_hstring(string)); - } - m_productCodes = productCodes; - } - return m_productCodes.GetView(); - } - winrt::Microsoft::Management::Deployment::PackageCatalog PackageVersionInfo::PackageCatalog() - { - if (!m_packageCatalog) - { - auto packageCatalogInfo = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo>>(); - packageCatalogInfo->Initialize(m_packageVersion->GetSource()->GetDetails()); - auto packageCatalog = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalog>>(); - packageCatalog->Initialize(*packageCatalogInfo, m_packageVersion->GetSource(), false); - m_packageCatalog = *packageCatalog; - } - return m_packageCatalog; - } -} +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include <mutex> +#include <AppInstallerRepositorySource.h> +#include "PackageVersionInfo.h" +#include "PackageVersionInfo.g.cpp" +#include "PackageCatalogInfo.h" +#include "PackageCatalog.h" +#include "CatalogPackage.h" +#include "Workflows/WorkflowBase.h" +#include "Converters.h" +#include <wil\cppwinrt_wrl.h> + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + void PackageVersionInfo::Initialize(std::shared_ptr<::AppInstaller::Repository::IPackageVersion> packageVersion) + { + m_packageVersion = std::move(packageVersion); + } + hstring PackageVersionInfo::GetMetadata(winrt::Microsoft::Management::Deployment::PackageVersionMetadataField const& metadataField) + { + ::AppInstaller::Repository::PackageVersionMetadata metadataKey = GetRepositoryPackageVersionMetadata(metadataField); + ::AppInstaller::Repository::IPackageVersion::Metadata metadata = m_packageVersion->GetMetadata(); + auto result = metadata.find(metadataKey); + hstring resultString = winrt::to_hstring(result->second); + // The api uses "System" rather than "Machine" for install scope. + if (metadataField == PackageVersionMetadataField::InstalledScope && resultString == L"Machine") + { + return winrt::to_hstring(L"System"); + } + return resultString; + } + hstring PackageVersionInfo::Id() + { + return winrt::to_hstring(m_packageVersion->GetProperty(::AppInstaller::Repository::PackageVersionProperty::Id).get()); + } + hstring PackageVersionInfo::DisplayName() + { + return winrt::to_hstring(m_packageVersion->GetProperty(::AppInstaller::Repository::PackageVersionProperty::Name).get()); + } + hstring PackageVersionInfo::Version() + { + return winrt::to_hstring(m_packageVersion->GetProperty(::AppInstaller::Repository::PackageVersionProperty::Version).get()); + } + hstring PackageVersionInfo::Channel() + { + return winrt::to_hstring(m_packageVersion->GetProperty(::AppInstaller::Repository::PackageVersionProperty::Channel).get()); + } + winrt::Windows::Foundation::Collections::IVectorView<hstring> PackageVersionInfo::PackageFamilyNames() + { + if (!m_packageFamilyNames) + { + // Vector hasn't been created yet, create and populate it. + auto packageFamilyNames = winrt::single_threaded_vector<hstring>(); + for (auto&& string : m_packageVersion->GetMultiProperty(::AppInstaller::Repository::PackageVersionMultiProperty::PackageFamilyName)) + { + packageFamilyNames.Append(winrt::to_hstring(string)); + } + m_packageFamilyNames = packageFamilyNames; + } + return m_packageFamilyNames.GetView(); + } + winrt::Windows::Foundation::Collections::IVectorView<hstring> PackageVersionInfo::ProductCodes() + { + if (!m_productCodes) + { + // Vector hasn't been created yet, create and populate it. + auto productCodes = winrt::single_threaded_vector<hstring>(); + for (auto&& string : m_packageVersion->GetMultiProperty(::AppInstaller::Repository::PackageVersionMultiProperty::ProductCode)) + { + productCodes.Append(winrt::to_hstring(string)); + } + m_productCodes = productCodes; + } + return m_productCodes.GetView(); + } + winrt::Microsoft::Management::Deployment::PackageCatalog PackageVersionInfo::PackageCatalog() + { + if (!m_packageCatalog) + { + auto packageCatalogInfo = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalogInfo>>(); + packageCatalogInfo->Initialize(m_packageVersion->GetSource()->GetDetails()); + auto packageCatalog = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageCatalog>>(); + packageCatalog->Initialize(*packageCatalogInfo, m_packageVersion->GetSource(), false); + m_packageCatalog = *packageCatalog; + } + return m_packageCatalog; + } +}