Skip to content

Commit

Permalink
Add upgrade functionality in Com api (#1853)
Browse files Browse the repository at this point in the history
  • Loading branch information
yao-msft authored Jan 21, 2022
1 parent f33afcb commit 808e59b
Show file tree
Hide file tree
Showing 15 changed files with 137 additions and 17 deletions.
3 changes: 1 addition & 2 deletions src/AppInstallerCLICore/Commands/COMInstallCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ namespace AppInstaller::CLI
void COMInstallCommand::ExecuteInternal(Context& context) const
{
context <<
Workflow::GetInstallerHash <<
Workflow::VerifyInstallerHash <<
Workflow::ReverifyInstallerHash <<
Workflow::InstallPackageInstaller;
}
}
4 changes: 3 additions & 1 deletion src/AppInstallerCLICore/Workflows/DownloadFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ namespace AppInstaller::CLI::Workflow
}
}

void GetInstallerHash(Execution::Context& context)
void ReverifyInstallerHash(Execution::Context& context)
{
const auto& installer = context.Get<Execution::Data::Installer>().value();

Expand Down Expand Up @@ -491,6 +491,8 @@ namespace AppInstaller::CLI::Workflow
AICLI_LOG(CLI, Error, << "Installer file not found.");
AICLI_TERMINATE_CONTEXT(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
}

context << VerifyInstallerHash;
}

void RenameDownloadedInstaller(Execution::Context& context)
Expand Down
5 changes: 2 additions & 3 deletions src/AppInstallerCLICore/Workflows/DownloadFlow.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,11 @@ namespace AppInstaller::CLI::Workflow
// Outputs: HashPair
void GetMsixSignatureHash(Execution::Context& context);

// Gets the hash of the downloaded installer.
// Downloading already computes the hash, so this is only needed to re-verify the installer hash.
// Re-verify the installer hash. This is used in Com install commands where download and install are in separate phases.
// Required Args: None
// Inputs: InstallerPath, Installer
// Outputs: HashPair
void GetInstallerHash(Execution::Context& context);
void ReverifyInstallerHash(Execution::Context& context);

// Verifies that the downloaded installer hash matches the hash in the manifest.
// Required Args: None
Expand Down
6 changes: 6 additions & 0 deletions src/AppInstallerCLIE2ETests/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ public class ErrorCode
public const int ERROR_MISSING_RESOURCE_FILE = unchecked((int)0x8A150048);
public const int ERROR_MSI_INSTALL_FAILED = unchecked((int)0x8A150049);
public const int ERROR_INVALID_MSIEXEC_ARGUMENT = unchecked((int)0x8A15004A);
public const int ERROR_FAILED_TO_OPEN_ALL_SOURCES = unchecked((int)0x8A15004B);
public const int ERROR_DEPENDENCIES_VALIDATION_FAILED = unchecked((int)0x8A15004C);
public const int ERROR_MISSING_PACKAGE = unchecked((int)0x8A15004D);
public const int ERROR_INVALID_TABLE_COLUMN = unchecked((int)0x8A15004E);
public const int ERROR_UPGRADE_VERSION_NOT_NEWER = unchecked((int)0x8A15004F);
public const int ERROR_UPGRADE_VERSION_UNKNOWN = unchecked((int)0x8A150050);

public const int ERROR_INSTALL_PACKAGE_IN_USE = unchecked((int)0x8A150101);
public const int ERROR_INSTALL_INSTALL_IN_PROGRESS = unchecked((int)0x8A150102);
Expand Down
16 changes: 14 additions & 2 deletions src/AppInstallerCommonCore/Errors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,6 @@ namespace AppInstaller
return "Package agreements were not agreed to";
case APPINSTALLER_CLI_ERROR_PROMPT_INPUT_ERROR:
return "Error reading input in prompt";
case APPINSTALLER_CLI_ERROR_INVALID_MSIEXEC_ARGUMENT:
return "Arguments for msiexec are invalid";
case APPINSTALLER_CLI_ERROR_UNSUPPORTED_SOURCE_REQUEST:
return "The search request is not supported by one or more sources";
case APPINSTALLER_CLI_ERROR_RESTSOURCE_ENDPOINT_NOT_FOUND:
Expand All @@ -160,6 +158,20 @@ namespace AppInstaller
return "Header size exceeds the allowable limit of 1024 characters. Please reduce the size and try again.";
case APPINSTALLER_CLI_ERROR_MSI_INSTALL_FAILED:
return "Running MSI install failed";
case APPINSTALLER_CLI_ERROR_INVALID_MSIEXEC_ARGUMENT:
return "Arguments for msiexec are invalid";
case APPINSTALLER_CLI_ERROR_FAILED_TO_OPEN_ALL_SOURCES:
return "Failed to open one or more sources";
case APPINSTALLER_CLI_ERROR_DEPENDENCIES_VALIDATION_FAILED:
return "Failed to validate dependencies";
case APPINSTALLER_CLI_ERROR_MISSING_PACKAGE:
return "One or more package is missing";
case APPINSTALLER_CLI_ERROR_INVALID_TABLE_COLUMN:
return "Invalid table column";
case APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_NOT_NEWER:
return "The upgrade version is not newer than the installed version";
case APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_UNKNOWN:
return "Upgrade version is unknown and override is not specified";
case APPINSTALLER_CLI_ERROR_INSTALL_PACKAGE_IN_USE:
return "Application is currently running.Exit the application then try again.";
case APPINSTALLER_CLI_ERROR_INSTALL_INSTALL_IN_PROGRESS:
Expand Down
9 changes: 5 additions & 4 deletions src/AppInstallerCommonCore/Public/AppInstallerErrors.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,13 @@
#define APPINSTALLER_CLI_ERROR_MSI_INSTALL_FAILED ((HRESULT)0x8A150049)
#define APPINSTALLER_CLI_ERROR_INVALID_MSIEXEC_ARGUMENT ((HRESULT)0x8A15004A)
#define APPINSTALLER_CLI_ERROR_FAILED_TO_OPEN_ALL_SOURCES ((HRESULT)0x8A15004B)

// Error associated with dependencies operations.
#define APPINSTALLER_CLI_ERROR_DEPENDENCIES_VALIDATION_FAILED ((HRESULT)0x8A15004C)
#define APPINSTALLER_CLI_ERROR_DEPENDENCIES_VALIDATION_FAILED ((HRESULT)0x8A15004C)
#define APPINSTALLER_CLI_ERROR_MISSING_PACKAGE ((HRESULT)0x8A15004D)
#define APPINSTALLER_CLI_ERROR_INVALID_TABLE_COLUMN ((HRESULT)0x8A15004E)
#define APPINSTALLER_CLI_ERROR_INVALID_TABLE_COLUMN ((HRESULT)0x8A15004E)
#define APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_NOT_NEWER ((HRESULT)0x8A15004F)
#define APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_UNKNOWN ((HRESULT)0x8A150050)

// Install errors.
#define APPINSTALLER_CLI_ERROR_INSTALL_PACKAGE_IN_USE ((HRESULT)0x8A150101)
#define APPINSTALLER_CLI_ERROR_INSTALL_INSTALL_IN_PROGRESS ((HRESULT)0x8A150102)
#define APPINSTALLER_CLI_ERROR_INSTALL_FILE_IN_USE ((HRESULT)0x8A150103)
Expand Down
8 changes: 8 additions & 0 deletions src/Microsoft.Management.Deployment.Client/InstallOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,12 @@ namespace winrt::Microsoft::Management::Deployment::implementation
{
throw hresult_not_implemented();
}
bool InstallOptions::AllowUpgradeToUnknownVersion()
{
throw hresult_not_implemented();
}
void InstallOptions::AllowUpgradeToUnknownVersion(bool)
{
throw hresult_not_implemented();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,8 @@ namespace winrt::Microsoft::Management::Deployment::implementation
{
throw hresult_not_implemented();
}

winrt::Windows::Foundation::IAsyncOperationWithProgress<winrt::Microsoft::Management::Deployment::InstallResult, winrt::Microsoft::Management::Deployment::InstallProgress> PackageManager::UpgradePackageAsync(winrt::Microsoft::Management::Deployment::CatalogPackage package, winrt::Microsoft::Management::Deployment::InstallOptions)
{
throw hresult_not_implemented();
}
}
2 changes: 1 addition & 1 deletion src/Microsoft.Management.Deployment/CatalogPackage.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation
winrt::Microsoft::Management::Deployment::PackageVersionInfo DefaultInstallVersion();
winrt::Microsoft::Management::Deployment::PackageVersionInfo GetPackageVersionInfo(winrt::Microsoft::Management::Deployment::PackageVersionId const& versionKey);
bool IsUpdateAvailable();

#if !defined(INCLUDE_ONLY_INTERFACE_METHODS)
private:
::AppInstaller::Repository::Source m_source;
Expand Down
5 changes: 5 additions & 0 deletions src/Microsoft.Management.Deployment/Converters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,11 @@ namespace winrt::Microsoft::Management::Deployment::implementation
case APPINSTALLER_CLI_ERROR_NO_APPLICABLE_INSTALLER:
resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::NoApplicableInstallers;
break;
case APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE:
case APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_UNKNOWN:
case APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_NOT_NEWER:
resultStatus = winrt::Microsoft::Management::Deployment::InstallResultStatus::NoApplicableUpgrade;
break;
case APPINSTALLER_CLI_ERROR_CANNOT_WRITE_TO_UPLEVEL_INDEX:
case APPINSTALLER_CLI_ERROR_INDEX_INTEGRITY_COMPROMISED:
case APPINSTALLER_CLI_ERROR_YAML_INIT_FAILED:
Expand Down
8 changes: 8 additions & 0 deletions src/Microsoft.Management.Deployment/InstallOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@ namespace winrt::Microsoft::Management::Deployment::implementation
{
return m_allowedArchitectures;
}
bool InstallOptions::AllowUpgradeToUnknownVersion()
{
return m_allowUpgradeToUnknownVersion;
}
void InstallOptions::AllowUpgradeToUnknownVersion(bool value)
{
m_allowUpgradeToUnknownVersion = value;
}

CoCreatableMicrosoftManagementDeploymentClass(InstallOptions);
}
3 changes: 3 additions & 0 deletions src/Microsoft.Management.Deployment/InstallOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ namespace winrt::Microsoft::Management::Deployment::implementation
hstring AdditionalPackageCatalogArguments();
void AdditionalPackageCatalogArguments(hstring const& value);
winrt::Windows::Foundation::Collections::IVector<winrt::Windows::System::ProcessorArchitecture> AllowedArchitectures();
bool AllowUpgradeToUnknownVersion();
void AllowUpgradeToUnknownVersion(bool value);

#if !defined(INCLUDE_ONLY_INTERFACE_METHODS)
private:
Expand All @@ -47,6 +49,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation
std::wstring m_additionalPackageCatalogArguments = L"";
Windows::Foundation::Collections::IVector<Windows::System::ProcessorArchitecture> m_allowedArchitectures{
winrt::single_threaded_vector<winrt::Windows::System::ProcessorArchitecture>() };
bool m_allowUpgradeToUnknownVersion = false;
#endif
};
}
Expand Down
57 changes: 56 additions & 1 deletion src/Microsoft.Management.Deployment/PackageManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,8 @@ namespace winrt::Microsoft::Management::Deployment::implementation
std::shared_ptr<Execution::OrchestratorQueueItem> queueItemParam,
winrt::Microsoft::Management::Deployment::CatalogPackage package = nullptr,
winrt::Microsoft::Management::Deployment::InstallOptions options = nullptr,
std::wstring callerProcessInfoString = {})
std::wstring callerProcessInfoString = {},
bool isUpgrade = false)
{
winrt::hresult terminationHR = S_OK;
hstring correlationData = (options) ? options.CorrelationData() : L"";
Expand All @@ -422,6 +423,34 @@ namespace winrt::Microsoft::Management::Deployment::implementation
{
Microsoft::Management::Deployment::PackageVersionInfo packageVersionInfo = GetPackageVersionInfo(package, options);
std::unique_ptr<COMContext> comContext = CreateContextFromInstallOptions(package, options, callerProcessInfoString);

if (isUpgrade)
{
AppInstaller::Utility::VersionAndChannel installedVersion{ winrt::to_string(package.InstalledVersion().Version()), winrt::to_string(package.InstalledVersion().Channel()) };
AppInstaller::Utility::VersionAndChannel upgradeVersion{ winrt::to_string(packageVersionInfo.Version()), winrt::to_string(packageVersionInfo.Channel()) };

// Perform upgrade version check
if (upgradeVersion.GetVersion().IsUnknown())
{
if (!(options.AllowUpgradeToUnknownVersion() &&
AppInstaller::Utility::ICUCaseInsensitiveEquals(installedVersion.GetChannel().ToString(), upgradeVersion.GetChannel().ToString())))
{
co_return GetInstallResult(executionStage, APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_UNKNOWN, correlationData, false);
}
}
else if (!installedVersion.IsUpdatedBy(upgradeVersion))
{
co_return GetInstallResult(executionStage, APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_NOT_NEWER, correlationData, false);
}

// Set upgrade flag
comContext->SetFlags(AppInstaller::CLI::Execution::ContextFlag::InstallerExecutionUseUpdate);
// Add installed version
winrt::Microsoft::Management::Deployment::implementation::PackageVersionInfo* installedVersionInfoImpl = get_self<winrt::Microsoft::Management::Deployment::implementation::PackageVersionInfo>(package.InstalledVersion());
std::shared_ptr<::AppInstaller::Repository::IPackageVersion> internalInstalledVersion = installedVersionInfoImpl->GetRepositoryPackageVersion();
comContext->Add<AppInstaller::CLI::Execution::Data::InstalledPackageVersion>(internalInstalledVersion);
}

queueItem = Execution::OrchestratorQueueItemFactory::CreateItemForInstall(std::wstring{ package.Id() }, std::wstring{ packageVersionInfo.PackageCatalog().Info().Id() }, std::move(comContext));
Execution::ContextOrchestrator::Instance().EnqueueAndRunItem(queueItem);

Expand Down Expand Up @@ -552,6 +581,32 @@ namespace winrt::Microsoft::Management::Deployment::implementation
return GetInstallOperation(true /*canCancelQueueItem*/, nullptr /*queueItem*/, package, options, std::move(callerProcessInfoString));
}

winrt::Windows::Foundation::IAsyncOperationWithProgress<winrt::Microsoft::Management::Deployment::InstallResult, winrt::Microsoft::Management::Deployment::InstallProgress> PackageManager::UpgradePackageAsync(winrt::Microsoft::Management::Deployment::CatalogPackage package, winrt::Microsoft::Management::Deployment::InstallOptions options)
{
hstring correlationData = (options) ? options.CorrelationData() : L"";

// options and catalog can both be null, package must be set.
WINGET_RETURN_INSTALL_RESULT_HR_IF(APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS, !package);
// the package should have an installed version to be upgraded.
WINGET_RETURN_INSTALL_RESULT_HR_IF(APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS, !package.InstalledVersion());

HRESULT hr = S_OK;
std::wstring callerProcessInfoString;
try
{
// Check for permissions and get caller info for telemetry.
// This must be done before any co_awaits since it requires info from the rpc caller thread.
auto [hrGetCallerId, callerProcessId] = GetCallerProcessId();
WINGET_RETURN_INSTALL_RESULT_HR_IF_FAILED(hrGetCallerId);
WINGET_RETURN_INSTALL_RESULT_HR_IF_FAILED(EnsureProcessHasCapability(Capability::PackageManagement, callerProcessId));
callerProcessInfoString = TryGetCallerProcessInfo(callerProcessId);
}
WINGET_CATCH_STORE(hr, APPINSTALLER_CLI_ERROR_COMMAND_FAILED);
WINGET_RETURN_INSTALL_RESULT_HR_IF_FAILED(hr);

return GetInstallOperation(true /*canCancelQueueItem*/, nullptr /*queueItem*/, package, options, std::move(callerProcessInfoString), true /* isUpgrade */);
}

winrt::Windows::Foundation::IAsyncOperationWithProgress<winrt::Microsoft::Management::Deployment::InstallResult, winrt::Microsoft::Management::Deployment::InstallProgress> PackageManager::GetInstallProgress(winrt::Microsoft::Management::Deployment::CatalogPackage package, winrt::Microsoft::Management::Deployment::PackageCatalogInfo catalogInfo)
{
hstring correlationData;
Expand Down
5 changes: 4 additions & 1 deletion src/Microsoft.Management.Deployment/PackageManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ namespace winrt::Microsoft::Management::Deployment::implementation
winrt::Microsoft::Management::Deployment::PackageCatalogReference CreateCompositePackageCatalog(winrt::Microsoft::Management::Deployment::CreateCompositePackageCatalogOptions const& options);
winrt::Windows::Foundation::IAsyncOperationWithProgress<winrt::Microsoft::Management::Deployment::InstallResult, winrt::Microsoft::Management::Deployment::InstallProgress>
InstallPackageAsync(winrt::Microsoft::Management::Deployment::CatalogPackage package, winrt::Microsoft::Management::Deployment::InstallOptions options);
//Contract 2.0
// Contract 2.0
winrt::Windows::Foundation::IAsyncOperationWithProgress<winrt::Microsoft::Management::Deployment::InstallResult, winrt::Microsoft::Management::Deployment::InstallProgress>
GetInstallProgress(winrt::Microsoft::Management::Deployment::CatalogPackage package, winrt::Microsoft::Management::Deployment::PackageCatalogInfo catalogInfo);
// Contract 4.0
winrt::Windows::Foundation::IAsyncOperationWithProgress<winrt::Microsoft::Management::Deployment::InstallResult, winrt::Microsoft::Management::Deployment::InstallProgress>
UpgradePackageAsync(winrt::Microsoft::Management::Deployment::CatalogPackage package, winrt::Microsoft::Management::Deployment::InstallOptions options);
};
}

Expand Down
18 changes: 17 additions & 1 deletion src/Microsoft.Management.Deployment/PackageManager.idl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Licensed under the MIT License.
namespace Microsoft.Management.Deployment
{
[contractversion(3)]
[contractversion(4)]
apicontract WindowsPackageManagerContract{};

/// State of the install.
Expand Down Expand Up @@ -59,6 +59,10 @@ namespace Microsoft.Management.Deployment
InstallError,
ManifestError,
NoApplicableInstallers,
[contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 4)]
{
NoApplicableUpgrade,
}
};

/// Result of the install
Expand Down Expand Up @@ -525,6 +529,12 @@ namespace Microsoft.Management.Deployment
// architecture after the first will simply be ignored.
Windows.Foundation.Collections.IVector<Windows.System.ProcessorArchitecture> AllowedArchitectures { get; };
}

[contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 4)]
{
/// Allow the upgrade to continue for upgrade packages with manifest versions Unknown.
Boolean AllowUpgradeToUnknownVersion;
}
}

[contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 1)]
Expand Down Expand Up @@ -554,6 +564,12 @@ namespace Microsoft.Management.Deployment
/// Get install progress
Windows.Foundation.IAsyncOperationWithProgress<InstallResult, InstallProgress> GetInstallProgress(CatalogPackage package, PackageCatalogInfo catalogInfo);
}

[contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 4)]
{
/// Upgrade the specified package
Windows.Foundation.IAsyncOperationWithProgress<InstallResult, InstallProgress> UpgradePackageAsync(CatalogPackage package, InstallOptions options);
}
}

/// Force midl3 to generate vector marshalling info.
Expand Down

0 comments on commit 808e59b

Please sign in to comment.