commit a9c9cd678c8643bcd106af27c41c11a00487597c
parent 6bfc3d04c4a7f917815486fddcf1042c8ba1fb10
Author: Ryan Fu <69221034+ryfu-msft@users.noreply.github.com>
Date: Mon, 13 Feb 2023 10:05:28 -0800
Add support for elevation requirement in COM (#2919)
Diffstat:
9 files changed, 135 insertions(+), 10 deletions(-)
diff --git a/src/AppInstallerCLIE2ETests/Interop/InstallInterop.cs b/src/AppInstallerCLIE2ETests/Interop/InstallInterop.cs
@@ -516,5 +516,41 @@ namespace AppInstallerCLIE2ETests.Interop
// Assert
Assert.AreEqual(InstallResultStatus.Ok, installResult.Status);
}
+
+ /// <summary>
+ /// Test to verify the GetApplicableInstaller() COM call returns the correct manifest installer metadata.
+ /// </summary>
+ [Test]
+ public void GetApplicableInstaller()
+ {
+ // Find package
+ var searchResult = this.FindAllPackages(this.testSource, PackageMatchField.Id, PackageFieldMatchOption.Equals, "AppInstallerTest.PackageInstallerInfo");
+ Assert.AreEqual(1, searchResult.Count);
+
+ // Configure installation
+ var catalogPackage = searchResult[0].CatalogPackage;
+ var packageVersionId = catalogPackage.AvailableVersions[0];
+ var packageVersionInfo = catalogPackage.GetPackageVersionInfo(packageVersionId);
+
+ // Use install options with no applicable match.
+ var badInstallOptions = this.TestFactory.CreateInstallOptions();
+ badInstallOptions.PackageInstallScope = PackageInstallScope.System;
+
+ Assert.IsNull(packageVersionInfo.GetApplicableInstaller(badInstallOptions));
+
+ // Use install options with valid applicable match.
+ var installOptions = this.TestFactory.CreateInstallOptions();
+ installOptions.PackageInstallScope = PackageInstallScope.User;
+ var packageInstallerInfo = packageVersionInfo.GetApplicableInstaller(installOptions);
+
+ // Assert
+ Assert.IsNotNull(packageInstallerInfo);
+ Assert.AreEqual(ElevationRequirement.ElevationRequired, packageInstallerInfo.ElevationRequirement);
+ Assert.AreEqual(Windows.System.ProcessorArchitecture.X64, packageInstallerInfo.Architecture);
+ Assert.AreEqual(PackageInstallerType.Zip, packageInstallerInfo.InstallerType);
+ Assert.AreEqual(PackageInstallerType.Exe, packageInstallerInfo.NestedInstallerType);
+ Assert.AreEqual(PackageInstallerScope.User, packageInstallerInfo.Scope);
+ Assert.AreEqual("en-US", packageInstallerInfo.Locale);
+ }
}
}
\ No newline at end of file
diff --git a/src/AppInstallerCLIE2ETests/TestData/Manifests/TestZipInstaller_PackageInstallerInfo.yaml b/src/AppInstallerCLIE2ETests/TestData/Manifests/TestZipInstaller_PackageInstallerInfo.yaml
@@ -0,0 +1,21 @@
+# Test manifest for verifying the behavior of retrieving a PackageInstallerInfo COM object.
+PackageIdentifier: AppInstallerTest.PackageInstallerInfo
+PackageVersion: 1.0.0.0
+PackageName: TestPackageInstallerInfo
+PackageLocale: en-US
+Publisher: AppInstallerTest
+License: Test
+ShortDescription: E2E test for PackageInstallerInfo COM object.
+Installers:
+ - Architecture: x64
+ Scope: User
+ InstallerUrl: https://localhost:5001/TestKit/AppInstallerTestZipInstaller/AppInstallerTestZipInstaller.zip
+ InstallerType: zip
+ InstallerSha256: <EXEHASH>
+ NestedInstallerType: exe
+ NestedInstallerFiles:
+ - RelativeFilePath: AppInstallerTestExeInstaller.exe
+ ElevationRequirement: elevationRequired
+ InstallerLocale: en-US
+ManifestType: singleton
+ManifestVersion: 1.4.0+
\ No newline at end of file
diff --git a/src/Microsoft.Management.Deployment/Converters.cpp b/src/Microsoft.Management.Deployment/Converters.cpp
@@ -322,4 +322,21 @@ namespace winrt::Microsoft::Management::Deployment::implementation
return ::AppInstaller::Manifest::ScopeEnum::Unknown;
}
+
+ winrt::Microsoft::Management::Deployment::ElevationRequirement GetDeploymentElevationRequirement(::AppInstaller::Manifest::ElevationRequirementEnum elevationRequirement)
+ {
+ switch (elevationRequirement)
+ {
+ case ::AppInstaller::Manifest::ElevationRequirementEnum::ElevationRequired:
+ return Microsoft::Management::Deployment::ElevationRequirement::ElevationRequired;
+ case ::AppInstaller::Manifest::ElevationRequirementEnum::ElevationProhibited:
+ return Microsoft::Management::Deployment::ElevationRequirement::ElevationProhibited;
+ case ::AppInstaller::Manifest::ElevationRequirementEnum::ElevatesSelf:
+ return Microsoft::Management::Deployment::ElevationRequirement::ElevatesSelf;
+ case ::AppInstaller::Manifest::ElevationRequirementEnum::Unknown:
+ return Microsoft::Management::Deployment::ElevationRequirement::Unknown;
+ }
+
+ return Microsoft::Management::Deployment::ElevationRequirement::Unknown;
+ }
}
diff --git a/src/Microsoft.Management.Deployment/Converters.h b/src/Microsoft.Management.Deployment/Converters.h
@@ -21,6 +21,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation
winrt::Microsoft::Management::Deployment::PackageInstallerType GetDeploymentInstallerType(::AppInstaller::Manifest::InstallerTypeEnum installerType);
winrt::Microsoft::Management::Deployment::PackageInstallerScope GetDeploymentInstallerScope(::AppInstaller::Manifest::ScopeEnum installerScope);
::AppInstaller::Manifest::ScopeEnum GetManifestUninstallScope(winrt::Microsoft::Management::Deployment::PackageUninstallScope scope);
+ winrt::Microsoft::Management::Deployment::ElevationRequirement GetDeploymentElevationRequirement(::AppInstaller::Manifest::ElevationRequirementEnum elevationRequirement);
#define WINGET_GET_OPERATION_RESULT_STATUS(_installResultStatus_, _uninstallResultStatus_) \
if constexpr (std::is_same_v<TStatus, winrt::Microsoft::Management::Deployment::InstallResultStatus>) \
diff --git a/src/Microsoft.Management.Deployment/PackageInstallerInfo.cpp b/src/Microsoft.Management.Deployment/PackageInstallerInfo.cpp
@@ -33,4 +33,8 @@ namespace winrt::Microsoft::Management::Deployment::implementation
{
return winrt::to_hstring(m_manifestInstaller.Locale);
}
+ winrt::Microsoft::Management::Deployment::ElevationRequirement PackageInstallerInfo::ElevationRequirement()
+ {
+ return GetDeploymentElevationRequirement(m_manifestInstaller.ElevationRequirement);
+ }
}
diff --git a/src/Microsoft.Management.Deployment/PackageInstallerInfo.h b/src/Microsoft.Management.Deployment/PackageInstallerInfo.h
@@ -19,6 +19,8 @@ namespace winrt::Microsoft::Management::Deployment::implementation
winrt::Windows::System::ProcessorArchitecture Architecture();
winrt::Microsoft::Management::Deployment::PackageInstallerScope Scope();
hstring Locale();
+ // Contract 6.0
+ winrt::Microsoft::Management::Deployment::ElevationRequirement ElevationRequirement();
#if !defined(INCLUDE_ONLY_INTERFACE_METHODS)
private:
diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl
@@ -274,12 +274,12 @@ namespace Microsoft.Management.Deployment
/// Gets the publisher string for this package version, if one is available.
String Publisher { get; };
}
-
- /// DESIGN NOTE:
- /// GetManifest from IPackageVersion in winget/RepositorySearch is not implemented in V1. That class has
- /// a lot of fields and no one requesting it.
- /// Gets the manifest of this package version.
- /// virtual Manifest::Manifest GetManifest() = 0;
+
+ [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 6)]
+ {
+ /// Gets the applicable installer for this package version.
+ PackageInstallerInfo GetApplicableInstaller(InstallOptions options);
+ }
}
/// IMPLEMENTATION NOTE: PackageVersionKey from winget/RepositorySearch.h
@@ -335,6 +335,20 @@ namespace Microsoft.Management.Deployment
System,
};
+ /// The package installer elevation requirement.
+ [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 6)]
+ enum ElevationRequirement
+ {
+ /// Elevation requirement not declared.
+ Unknown,
+ /// Package installer requires elevation.
+ ElevationRequired,
+ /// Package installer prohibits elevation.
+ ElevationProhibited,
+ /// Package installer elevates self.
+ ElevatesSelf,
+ };
+
/// Interface for retrieving information about a package installer.
[contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 5)]
runtimeclass PackageInstallerInfo
@@ -348,7 +362,13 @@ namespace Microsoft.Management.Deployment
/// The package installer scope.
PackageInstallerScope Scope { get; };
/// The package installer locale.
- String Locale{ get; };
+ String Locale { get; };
+
+ [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 6)]
+ {
+ /// The package installer elevation requirement.
+ ElevationRequirement ElevationRequirement { get; };
+ }
};
/// The installed status type. The values need to match InstalledStatusType from winget/RepositorySearch.h.
diff --git a/src/Microsoft.Management.Deployment/PackageVersionInfo.cpp b/src/Microsoft.Management.Deployment/PackageVersionInfo.cpp
@@ -7,6 +7,7 @@
#include "PackageVersionInfo.g.cpp"
#include "PackageCatalogInfo.h"
#include "PackageCatalog.h"
+#include "PackageInstallerInfo.h"
#include "CatalogPackage.h"
#include "ComContext.h"
#include "Workflows/WorkflowBase.h"
@@ -27,6 +28,10 @@ namespace winrt::Microsoft::Management::Deployment::implementation
{
m_packageVersion = std::move(packageVersion);
}
+ std::shared_ptr<::AppInstaller::Repository::IPackageVersion> PackageVersionInfo::GetRepositoryPackageVersion()
+ {
+ return m_packageVersion;
+ }
hstring PackageVersionInfo::GetMetadata(winrt::Microsoft::Management::Deployment::PackageVersionMetadataField const& metadataField)
{
::AppInstaller::Repository::PackageVersionMetadata metadataKey = GetRepositoryPackageVersionMetadata(metadataField);
@@ -134,8 +139,24 @@ namespace winrt::Microsoft::Management::Deployment::implementation
auto result = manifestComparator.GetPreferredInstaller(manifest);
return result.installer.has_value();
}
- std::shared_ptr<::AppInstaller::Repository::IPackageVersion> PackageVersionInfo::GetRepositoryPackageVersion()
- {
- return m_packageVersion;
+ winrt::Microsoft::Management::Deployment::PackageInstallerInfo PackageVersionInfo::GetApplicableInstaller(InstallOptions options)
+ {
+ AppInstaller::CLI::Execution::COMContext context;
+ PopulateContextFromInstallOptions(&context, options);
+ AppInstaller::Repository::IPackageVersion::Metadata installationMetadata;
+ AppInstaller::CLI::Workflow::ManifestComparator manifestComparator{ context, installationMetadata };
+ AppInstaller::Manifest::Manifest manifest = m_packageVersion->GetManifest();
+ auto result = manifestComparator.GetPreferredInstaller(manifest);
+
+ if (result.installer.has_value())
+ {
+ auto packageInstallerInfo = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::PackageInstallerInfo>>();
+ packageInstallerInfo->Initialize(result.installer.value());
+ return *packageInstallerInfo;
+ }
+ else
+ {
+ return nullptr;
+ }
}
}
diff --git a/src/Microsoft.Management.Deployment/PackageVersionInfo.h b/src/Microsoft.Management.Deployment/PackageVersionInfo.h
@@ -26,6 +26,8 @@ namespace winrt::Microsoft::Management::Deployment::implementation
winrt::Microsoft::Management::Deployment::CompareResult CompareToVersion(hstring versionString);
// Contract version 4
bool HasApplicableInstaller(InstallOptions options);
+ // Contract version 6
+ winrt::Microsoft::Management::Deployment::PackageInstallerInfo GetApplicableInstaller(InstallOptions options);
#if !defined(INCLUDE_ONLY_INTERFACE_METHODS)
private: