Skip to content

Commit

Permalink
Add support for elevation requirement in COM (microsoft#2919)
Browse files Browse the repository at this point in the history
  • Loading branch information
ryfu-msft authored Feb 13, 2023
1 parent 6bfc3d0 commit a9c9cd6
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 10 deletions.
36 changes: 36 additions & 0 deletions src/AppInstallerCLIE2ETests/Interop/InstallInterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -516,5 +516,41 @@ public async Task InstallRequireUserScopeAndUnknown()
// 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);
}
}
}
Original file line number Diff line number Diff line change
@@ -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
17 changes: 17 additions & 0 deletions src/Microsoft.Management.Deployment/Converters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
1 change: 1 addition & 0 deletions src/Microsoft.Management.Deployment/Converters.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>) \
Expand Down
4 changes: 4 additions & 0 deletions src/Microsoft.Management.Deployment/PackageInstallerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
2 changes: 2 additions & 0 deletions src/Microsoft.Management.Deployment/PackageInstallerInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
34 changes: 27 additions & 7 deletions src/Microsoft.Management.Deployment/PackageManager.idl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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.
Expand Down
27 changes: 24 additions & 3 deletions src/Microsoft.Management.Deployment/PackageVersionInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
}
}
2 changes: 2 additions & 0 deletions src/Microsoft.Management.Deployment/PackageVersionInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down

0 comments on commit a9c9cd6

Please sign in to comment.