diff --git a/src/AppInstallerCLIE2ETests/Interop/GroupPolicyForInterop.cs b/src/AppInstallerCLIE2ETests/Interop/GroupPolicyForInterop.cs index 45f34a91d3..e86e27beca 100644 --- a/src/AppInstallerCLIE2ETests/Interop/GroupPolicyForInterop.cs +++ b/src/AppInstallerCLIE2ETests/Interop/GroupPolicyForInterop.cs @@ -9,6 +9,7 @@ namespace AppInstallerCLIE2ETests.Interop using System; using System.IO; using System.Text; + using System.Threading; using System.Threading.Tasks; using AppInstallerCLIE2ETests.Helpers; using Microsoft.Management.Deployment; @@ -51,6 +52,16 @@ public void CleanUp() GroupPolicyHelper.DeleteExistingPolicies(); } + /// + /// Test class Tear down. + /// + [OneTimeTearDown] + public void TestClassTearDown() + { + // Restore the tests source if it was removed as the affects subsequent tests. + TestCommon.SetupTestSource(); + } + /// /// Validates disabling WinGetPolicy should block COM/WinRT Objects creation (InProcess and OutOfProcess). /// @@ -91,6 +102,14 @@ public void DisableWinGetPolicy() Assert.AreEqual(Constants.BlockByWinGetPolicyErrorMessage, groupPolicyException.Message); Assert.AreEqual(Constants.ErrorCode.ERROR_BLOCKED_BY_POLICY, groupPolicyException.HResult); + groupPolicyException = Assert.Catch(() => { AddPackageCatalogOptions packageManagerSettings = this.TestFactory.CreateAddPackageCatalogOptions(); }); + Assert.AreEqual(Constants.BlockByWinGetPolicyErrorMessage, groupPolicyException.Message); + Assert.AreEqual(Constants.ErrorCode.ERROR_BLOCKED_BY_POLICY, groupPolicyException.HResult); + + groupPolicyException = Assert.Catch(() => { RemovePackageCatalogOptions packageManagerSettings = this.TestFactory.CreateRemovePackageCatalogOptions(); }); + Assert.AreEqual(Constants.BlockByWinGetPolicyErrorMessage, groupPolicyException.Message); + Assert.AreEqual(Constants.ErrorCode.ERROR_BLOCKED_BY_POLICY, groupPolicyException.HResult); + // PackageManagerSettings is not implemented in context OutOfProcDev if (this.TestFactory.Context == ClsidContext.InProc) { @@ -159,6 +178,65 @@ public async Task DisableWinGetCommandLineInterfacesPolicy() var packageVersion = "2.0.0.0"; string downloadDir = Path.Combine(TestCommon.GetDefaultDownloadDirectory(), $"{Constants.ModifyRepairInstaller}_{packageVersion}"); TestCommon.AssertInstallerDownload(downloadDir, "TestModifyRepair", packageVersion, ProcessorArchitecture.X86, TestCommon.Scope.Unknown, PackageInstallerType.Burn, "en-US"); + + // Add, update and remove package catalog + await this.AddUpdateRemovePackageCatalog(); + } + + private async Task AddUpdateRemovePackageCatalog() + { + // Remove the tests source if it exists. + await this.RemovePackageCatalog(); + + PackageManager packageManager = this.TestFactory.CreatePackageManager(); + + // Add package catalog + AddPackageCatalogOptions options = this.TestFactory.CreateAddPackageCatalogOptions(); + options.SourceUri = Constants.TestSourceUrl; + options.Name = Constants.TestSourceName; + options.TrustLevel = PackageCatalogTrustLevel.Trusted; + + var addCatalogResult = await packageManager.AddPackageCatalogAsync(options); + Assert.IsNotNull(addCatalogResult); + Assert.AreEqual(AddPackageCatalogStatus.Ok, addCatalogResult.Status); + + // Get package catalog + var packageCatalog = packageManager.GetPackageCatalogByName(options.Name); + + Assert.IsNotNull(packageCatalog); + Assert.AreEqual(options.Name, packageCatalog.Info.Name); + Assert.AreEqual(options.SourceUri, packageCatalog.Info.Argument); + var lastUpdatedTime = packageCatalog.Info.LastUpdateTime; + + // Update package catalog + // Sleep for 30 seconds to make sure the last updated time is different after the refresh. + Thread.Sleep(TimeSpan.FromSeconds(30)); + + var updateResult = await packageCatalog.RefreshPackageCatalogAsync(); + Assert.IsNotNull(updateResult); + Assert.AreEqual(RefreshPackageCatalogStatus.Ok, updateResult.Status); + + packageCatalog = packageManager.GetPackageCatalogByName(options.Name); + Assert.IsTrue(packageCatalog.Info.LastUpdateTime > lastUpdatedTime); + + // Remove package catalog + await this.RemovePackageCatalog(); + } + + private async Task RemovePackageCatalog() + { + PackageManager packageManager = this.TestFactory.CreatePackageManager(); + + // Remove the tests source if it exists. + RemovePackageCatalogOptions removePackageCatalogOptions = this.TestFactory.CreateRemovePackageCatalogOptions(); + removePackageCatalogOptions.Name = Constants.TestSourceName; + + var removeCatalogResult = await packageManager.RemovePackageCatalogAsync(removePackageCatalogOptions); + Assert.IsNotNull(removeCatalogResult); + Assert.AreEqual(RemovePackageCatalogStatus.Ok, removeCatalogResult.Status); + + var packageCatalog = packageManager.GetPackageCatalogByName(removePackageCatalogOptions.Name); + Assert.IsNull(packageCatalog); } } } diff --git a/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs b/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs new file mode 100644 index 0000000000..23e133fb00 --- /dev/null +++ b/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs @@ -0,0 +1,328 @@ +// ----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT License. +// +// ----------------------------------------------------------------------------- +namespace AppInstallerCLIE2ETests.Interop +{ + using System; + using System.IO; + using System.Threading; + using System.Threading.Tasks; + using AppInstallerCLIE2ETests.Helpers; + using Microsoft.CodeAnalysis; + using Microsoft.Management.Deployment; + using Microsoft.Management.Deployment.Projection; + using NUnit.Framework; + using Windows.System; + + /// + /// Package catalog interop class. + /// + [TestFixtureSource(typeof(InstanceInitializersSource), nameof(InstanceInitializersSource.InProcess), Category = nameof(InstanceInitializersSource.InProcess))] + [TestFixtureSource(typeof(InstanceInitializersSource), nameof(InstanceInitializersSource.OutOfProcess), Category = nameof(InstanceInitializersSource.OutOfProcess))] + public class PackageCatalogInterop : BaseInterop + { + private PackageManager packageManager; + + /// + /// Initializes a new instance of the class. + /// + /// initializer. + public PackageCatalogInterop(IInstanceInitializer initializer) + : base(initializer) + { + } + + /// + /// Set up. + /// + [SetUp] + public void Setup() + { + // Remove the tests source if it exists. + TestCommon.RunAICLICommand("source remove", Constants.TestSourceName); + + this.packageManager = this.TestFactory.CreatePackageManager(); + } + + /// + /// Add and remove package catalog. + /// + /// representing the asynchronous unit test. + [Test] + public async Task AddRemovePackageCatalog() + { + AddPackageCatalogOptions options = this.TestFactory.CreateAddPackageCatalogOptions(); + options.SourceUri = Constants.TestSourceUrl; + options.Name = Constants.TestSourceName; + options.TrustLevel = PackageCatalogTrustLevel.Trusted; + + await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.Ok); + + RemovePackageCatalogOptions removePackageCatalogOptions = this.TestFactory.CreateRemovePackageCatalogOptions(); + removePackageCatalogOptions.Name = Constants.TestSourceName; + var removeCatalogResult = await this.packageManager.RemovePackageCatalogAsync(removePackageCatalogOptions); + Assert.IsNotNull(removeCatalogResult); + Assert.AreEqual(RemovePackageCatalogStatus.Ok, removeCatalogResult.Status); + + var testSource = this.packageManager.GetPackageCatalogByName(Constants.TestSourceName); + Assert.IsNull(testSource); + } + + /// + /// Add package catalog with invalid options. + /// + [Test] + public void AddPackageCatalogWithInvalidOptions() + { + // Add package catalog with null options. + Assert.ThrowsAsync(async () => await this.packageManager.AddPackageCatalogAsync(null)); + + // Add package catalog with empty options. + Assert.ThrowsAsync(async () => await this.packageManager.AddPackageCatalogAsync(this.TestFactory.CreateAddPackageCatalogOptions())); + } + + /// + /// Add package catalog with a duplicate name and verify it returns SourceNameExists. + /// + /// representing the asynchronous unit test. + [Test] + public async Task AddPackageCatalog_DuplicateName_ReturnsSourceNameExists() + { + AddPackageCatalogOptions options = this.TestFactory.CreateAddPackageCatalogOptions(); + options.SourceUri = Constants.TestSourceUrl; + options.Name = Constants.TestSourceName; + options.TrustLevel = PackageCatalogTrustLevel.Trusted; + + await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.Ok); + + // Add the same package catalog again. + await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.InvalidOptions, Constants.ErrorCode.ERROR_SOURCE_NAME_ALREADY_EXISTS); + + // Remove the tests source if it exists. + RemovePackageCatalogOptions removePackageCatalogOptions = this.TestFactory.CreateRemovePackageCatalogOptions(); + removePackageCatalogOptions.Name = Constants.TestSourceName; + await this.RemoveAndValidatePackageCatalogAsync(removePackageCatalogOptions, RemovePackageCatalogStatus.Ok); + } + + /// + /// Add package catalog with a duplicate source uri and verify it returns SourceArg AlreadyExists. + /// + /// representing the asynchronous unit test. + [Test] + public async Task AddPackageCatalog_DuplicateSourceUri_ReturnSourceArgAlreadyExists() + { + AddPackageCatalogOptions options = this.TestFactory.CreateAddPackageCatalogOptions(); + options.SourceUri = Constants.TestSourceUrl; + options.Name = Constants.TestSourceName; + options.TrustLevel = PackageCatalogTrustLevel.Trusted; + + await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.Ok); + + // Add the same package catalog again. + options.Name = "TestSource2"; + await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.InvalidOptions, Constants.ErrorCode.ERROR_SOURCE_ARG_ALREADY_EXISTS); + + // Remove the tests source if it exists. + RemovePackageCatalogOptions removePackageCatalogOptions = this.TestFactory.CreateRemovePackageCatalogOptions(); + removePackageCatalogOptions.Name = Constants.TestSourceName; + await this.RemoveAndValidatePackageCatalogAsync(removePackageCatalogOptions, RemovePackageCatalogStatus.Ok); + } + + /// + /// Add package catalog with invalid source uri. + /// + /// representing the asynchronous unit test. + [Test] + public async Task AddPackageCatalogWithInvalidSourceUri() + { + AddPackageCatalogOptions options = this.TestFactory.CreateAddPackageCatalogOptions(); + options.SourceUri = "InvalidUri"; + options.Name = Constants.TestSourceName; + options.TrustLevel = PackageCatalogTrustLevel.Trusted; + + await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.InternalError); + } + + /// + /// Add package catalog with insecure source uri. + /// + /// representing the asynchronous unit test. + [Test] + public async Task AddPackageCatalogWithHttpSourceUri() + { + AddPackageCatalogOptions options = this.TestFactory.CreateAddPackageCatalogOptions(); + options.SourceUri = "http://microsoft.com"; + options.Name = "Insecure"; + options.TrustLevel = PackageCatalogTrustLevel.Trusted; + + await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.InvalidOptions, Constants.ErrorCode.ERROR_SOURCE_NOT_SECURE); + } + + /// + /// Add package catalog with invalid type. + /// + /// representing the asynchronous unit test. + [Test] + public async Task AddPackageCatalogWithInvalidType() + { + AddPackageCatalogOptions options = this.TestFactory.CreateAddPackageCatalogOptions(); + options.SourceUri = Constants.TestSourceUrl; + options.Name = Constants.TestSourceName; + options.Type = "InvalidType"; + + await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.InvalidOptions, Constants.ErrorCode.ERROR_INVALID_SOURCE_TYPE); + } + + /// + /// Add, update and remove package catalog. + /// + /// representing the asynchronous unit test. + [Test] + public async Task AddUpdateRemovePackageCatalog() + { + AddPackageCatalogOptions options = this.TestFactory.CreateAddPackageCatalogOptions(); + options.SourceUri = Constants.TestSourceUrl; + options.Name = Constants.TestSourceName; + options.TrustLevel = PackageCatalogTrustLevel.Trusted; + + await this.AddCatalogAndVerifyStatusAsync(options, AddPackageCatalogStatus.Ok); + + var packageCatalog = this.GetAndValidatePackageCatalog(options); + var lastUpdatedTime = packageCatalog.Info.LastUpdateTime; + + // Sleep for 30 seconds to make sure the last updated time is different after the refresh. + Thread.Sleep(TimeSpan.FromSeconds(30)); + + var updateResult = await packageCatalog.RefreshPackageCatalogAsync(); + Assert.IsNotNull(updateResult); + Assert.AreEqual(RefreshPackageCatalogStatus.Ok, updateResult.Status); + + packageCatalog = this.GetAndValidatePackageCatalog(options); + Assert.IsTrue(packageCatalog.Info.LastUpdateTime > lastUpdatedTime); + + RemovePackageCatalogOptions removePackageCatalogOptions = this.TestFactory.CreateRemovePackageCatalogOptions(); + removePackageCatalogOptions.Name = Constants.TestSourceName; + await this.RemoveAndValidatePackageCatalogAsync(removePackageCatalogOptions, RemovePackageCatalogStatus.Ok); + } + + /// + /// Add, remove package catalog with PreserveData filed set.. + /// + /// representing the asynchronous unit test. + [Test] + public async Task AddRemovePackageCatalogWithPreserveDataFiledSet() + { + AddPackageCatalogOptions options = this.TestFactory.CreateAddPackageCatalogOptions(); + options.SourceUri = Constants.TestSourceUrl; + options.Name = Constants.TestSourceName; + options.TrustLevel = PackageCatalogTrustLevel.Trusted; + + await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.Ok); + + RemovePackageCatalogOptions removePackageCatalogOptions = this.TestFactory.CreateRemovePackageCatalogOptions(); + removePackageCatalogOptions.Name = Constants.TestSourceName; + removePackageCatalogOptions.PreserveData = true; + + await this.RemoveAndValidatePackageCatalogAsync(removePackageCatalogOptions, RemovePackageCatalogStatus.Ok); + } + + /// + /// Remove package catalog with invalid options. + /// + [Test] + public void RemovePackageCatalogWithInvalidOptions() + { + // Remove package catalog with null options. + Assert.ThrowsAsync(async () => await this.packageManager.RemovePackageCatalogAsync(null)); + + // Remove package catalog with empty options. + Assert.ThrowsAsync(async () => await this.packageManager.RemovePackageCatalogAsync(this.TestFactory.CreateRemovePackageCatalogOptions())); + } + + /// + /// Remove a package catalog that is not present. + /// + /// representing the asynchronous unit test. + [Test] + public async Task RemoveNonExistingPackageCatalog() + { + RemovePackageCatalogOptions removePackageCatalogOptions = this.TestFactory.CreateRemovePackageCatalogOptions(); + removePackageCatalogOptions.Name = Constants.TestSourceName; + + await this.RemoveAndValidatePackageCatalogAsync(removePackageCatalogOptions, RemovePackageCatalogStatus.InvalidOptions, Constants.ErrorCode.ERROR_SOURCE_NAME_DOES_NOT_EXIST); + } + + /// + /// Test class Tear down. + /// + [OneTimeTearDown] + public void TestClassTearDown() + { + // Restore the tests source if it was removed as the affects subsequent tests. + TestCommon.SetupTestSource(); + } + + private async Task AddCatalogAndVerifyStatusAsync(AddPackageCatalogOptions addPackageCatalogOptions, AddPackageCatalogStatus expectedStatus, int expectedErrorCode = 0) + { + var addCatalogResult = await this.packageManager.AddPackageCatalogAsync(addPackageCatalogOptions); + Assert.IsNotNull(addCatalogResult); + Assert.AreEqual(expectedStatus, addCatalogResult.Status); + + if (expectedStatus != AddPackageCatalogStatus.Ok && expectedErrorCode != 0) + { + Assert.AreEqual(expectedErrorCode, addCatalogResult.ExtendedErrorCode.HResult); + } + } + + private PackageCatalogReference GetAndValidatePackageCatalog(AddPackageCatalogOptions addPackageCatalogOptions) + { + var packageCatalog = this.packageManager.GetPackageCatalogByName(addPackageCatalogOptions.Name); + + Assert.IsNotNull(packageCatalog); + Assert.AreEqual(addPackageCatalogOptions.Name, packageCatalog.Info.Name); + Assert.AreEqual(addPackageCatalogOptions.SourceUri, packageCatalog.Info.Argument); + + return packageCatalog; + } + + private async Task AddAndValidatePackageCatalogAsync(AddPackageCatalogOptions addPackageCatalogOptions, AddPackageCatalogStatus expectedStatus, int expectedErrorCode = 0) + { + // Add the package catalog and verify the status + var addCatalogResult = await this.packageManager.AddPackageCatalogAsync(addPackageCatalogOptions); + Assert.IsNotNull(addCatalogResult); + Assert.AreEqual(expectedStatus, addCatalogResult.Status); + + if (expectedStatus != AddPackageCatalogStatus.Ok) + { + // Only validate the error code if the status is not Ok and the expected error code is not 0 + if (expectedErrorCode != 0) + { + Assert.AreEqual(expectedErrorCode, addCatalogResult.ExtendedErrorCode.HResult); + } + + return; + } + + // Validate the added package catalog if the status is Ok + this.GetAndValidatePackageCatalog(addPackageCatalogOptions); + } + + private async Task RemoveAndValidatePackageCatalogAsync(RemovePackageCatalogOptions removePackageCatalogOptions, RemovePackageCatalogStatus expectedStatus, int expectedErrorCode = 0) + { + var removeCatalogResult = await this.packageManager.RemovePackageCatalogAsync(removePackageCatalogOptions); + Assert.IsNotNull(removeCatalogResult); + Assert.AreEqual(expectedStatus, removeCatalogResult.Status); + + if (expectedStatus != RemovePackageCatalogStatus.Ok && expectedErrorCode != 0) + { + Assert.AreEqual(expectedErrorCode, removeCatalogResult.ExtendedErrorCode.HResult); + return; + } + + var packageCatalog = this.packageManager.GetPackageCatalogByName(removePackageCatalogOptions.Name); + Assert.IsNull(packageCatalog); + } + } +} diff --git a/src/AppInstallerCLIPackage/Package.appxmanifest b/src/AppInstallerCLIPackage/Package.appxmanifest index 6ed816f412..6ef3f5aa9d 100644 --- a/src/AppInstallerCLIPackage/Package.appxmanifest +++ b/src/AppInstallerCLIPackage/Package.appxmanifest @@ -80,6 +80,10 @@ + + + + diff --git a/src/AppInstallerCommonCore/Progress.cpp b/src/AppInstallerCommonCore/Progress.cpp index 4288256507..df7fd7b545 100644 --- a/src/AppInstallerCommonCore/Progress.cpp +++ b/src/AppInstallerCommonCore/Progress.cpp @@ -134,4 +134,43 @@ namespace AppInstaller m_rangeMin = rangeMin; m_rangeMax = rangeMax; } + + void CallbackDispatcherSink::BeginProgress() + { + FireCallbacks(0, 0, ProgressType::None); + } + + void CallbackDispatcherSink::OnProgress(uint64_t current, uint64_t maximum, ProgressType type) + { + FireCallbacks(current, maximum, type); + } + + void CallbackDispatcherSink::SetProgressMessage(std::string_view message) + { + UNREFERENCED_PARAMETER(message); + // No-op + } + + void CallbackDispatcherSink::EndProgress(bool hideProgressWhenDone) + { + UNREFERENCED_PARAMETER(hideProgressWhenDone); + FireCallbacks(0, 0, ProgressType::None); + } + + void CallbackDispatcherSink::AddCallback(ProgressCallBack&& callback) + { + std::lock_guard lock{ m_progressCallbackMutex }; + m_progressCallbacks.push_back(std::move(callback)); + } + + void CallbackDispatcherSink::FireCallbacks(uint64_t current, uint64_t maximum, ProgressType type) + { + // Lock around iterating through the list. Callbacks should not do long running tasks. + std::lock_guard lock{ m_progressCallbackMutex }; + + for (auto& callback : m_progressCallbacks) + { + callback(current, maximum, type); + } + } } diff --git a/src/AppInstallerCommonCore/Public/AppInstallerProgress.h b/src/AppInstallerCommonCore/Public/AppInstallerProgress.h index 9ba643dc34..5449355773 100644 --- a/src/AppInstallerCommonCore/Public/AppInstallerProgress.h +++ b/src/AppInstallerCommonCore/Public/AppInstallerProgress.h @@ -5,6 +5,7 @@ #include #include #include +#include namespace AppInstaller { @@ -19,7 +20,7 @@ namespace AppInstaller } // The semantic meaning of the progress values. - enum class ProgressType: uint32_t + enum class ProgressType : uint32_t { // Progress will not be sent. None, @@ -126,6 +127,32 @@ namespace AppInstaller uint64_t m_globalMax = 0; }; + using ProgressCallBack = std::function; + + // A sink that dispatches progress to a set of callbacks. + struct CallbackDispatcherSink : public IProgressSink + { + CallbackDispatcherSink() = default; + + ~CallbackDispatcherSink() = default; + + void OnProgress(uint64_t current, uint64_t maximum, ProgressType type) override; + + void SetProgressMessage(std::string_view message) override; + + void BeginProgress() override; + + void EndProgress(bool hideProgressWhenDone) override; + + void AddCallback(ProgressCallBack&& callback); + + private: + void FireCallbacks(uint64_t current, uint64_t maximum, ProgressType type); + + std::vector m_progressCallbacks; + std::mutex m_progressCallbackMutex; + }; + namespace details { inline void RemoveCancellationFunction(IProgressCallback* callback) diff --git a/src/AppInstallerSharedLib/Public/winget/Runtime.h b/src/AppInstallerSharedLib/Public/winget/Runtime.h index 61fbe0d19e..6c09b98cf4 100644 --- a/src/AppInstallerSharedLib/Public/winget/Runtime.h +++ b/src/AppInstallerSharedLib/Public/winget/Runtime.h @@ -40,6 +40,9 @@ namespace AppInstaller::Runtime // Determines whether the process is running with local system context. bool IsRunningAsSystem(); + // Determines whether the process is running with administrator or system privileges. + bool IsRunningAsAdminOrSystem(); + // Returns true if this is a release build; false if not. inline constexpr bool IsReleaseBuild() { diff --git a/src/AppInstallerSharedLib/Runtime.cpp b/src/AppInstallerSharedLib/Runtime.cpp index 89a0b297a5..2c35ea3135 100644 --- a/src/AppInstallerSharedLib/Runtime.cpp +++ b/src/AppInstallerSharedLib/Runtime.cpp @@ -208,4 +208,9 @@ namespace AppInstaller::Runtime { return wil::test_token_membership(nullptr, SECURITY_NT_AUTHORITY, SECURITY_LOCAL_SYSTEM_RID); } + + bool IsRunningAsAdminOrSystem() + { + return IsRunningAsAdmin() || IsRunningAsSystem(); + } } diff --git a/src/Microsoft.Management.Deployment.InProc/Microsoft.Management.Deployment.InProc.dll.manifest b/src/Microsoft.Management.Deployment.InProc/Microsoft.Management.Deployment.InProc.dll.manifest index f9e41531c7..4e9725d652 100644 --- a/src/Microsoft.Management.Deployment.InProc/Microsoft.Management.Deployment.InProc.dll.manifest +++ b/src/Microsoft.Management.Deployment.InProc/Microsoft.Management.Deployment.InProc.dll.manifest @@ -47,5 +47,13 @@ clsid="{30C024C4-852C-4DD4-9810-1348C51EF9BB}" threadingModel="Both" description="RepairOptions"/> + + diff --git a/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp b/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp index ad7c0d66ca..89bd2f4048 100644 --- a/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp +++ b/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp @@ -22,6 +22,8 @@ namespace Microsoft::Management::Deployment::OutOfProc constexpr CLSID CLSID_DownloadOptions = { 0x4CBABE76, 0x7322, 0x4BE4, { 0x9C, 0xEA, 0x25, 0x89, 0xA8, 0x06, 0x82, 0xDC } }; //4CBABE76-7322-4BE4-9CEA-2589A80682DC constexpr CLSID CLSID_AuthenticationArguments = { 0xBA580786, 0xBDE3, 0x4F6C, { 0xB8, 0xF3, 0x44, 0x69, 0x8A, 0xC8, 0x71, 0x1A } }; //BA580786-BDE3-4F6C-B8F3-44698AC8711A constexpr CLSID CLSID_RepairOptions = { 0x0498F441, 0x3097, 0x455F, { 0x9C, 0xAF, 0x14, 0x8F, 0x28, 0x29, 0x38, 0x65 } }; //0498F441-3097-455F-9CAF-148F28293865 + constexpr CLSID CLSID_AddPackageCatalogOptions = { 0xDB9D012D, 0x00D7, 0x47EE, { 0x8F, 0xB1, 0x60, 0x6E, 0x10, 0xAC, 0x4F, 0x51 } }; //DB9D012D-00D7-47EE-8FB1-606E10AC4F51 + constexpr CLSID CLSID_RemovePackageCatalogOptions = { 0x032B1C58, 0xB975, 0x469B, { 0xA0, 0x13, 0xE6, 0x32, 0xB6, 0xEC, 0xE8, 0xD8 } }; //032B1C58-B975-469B-A013-E632B6ECE8D8 #else constexpr CLSID CLSID_PackageManager = { 0x74CB3139, 0xB7C5, 0x4B9E, { 0x93, 0x88, 0xE6, 0x61, 0x6D, 0xEA, 0x28, 0x8C } }; //74CB3139-B7C5-4B9E-9388-E6616DEA288C constexpr CLSID CLSID_InstallOptions = { 0x44FE0580, 0x62F7, 0x44D4, { 0x9E, 0x91, 0xAA, 0x96, 0x14, 0xAB, 0x3E, 0x86 } }; //44FE0580-62F7-44D4-9E91-AA9614AB3E86 @@ -32,6 +34,9 @@ namespace Microsoft::Management::Deployment::OutOfProc constexpr CLSID CLSID_DownloadOptions = { 0x8EF324ED, 0x367C, 0x4880, { 0x83, 0xE5, 0xBB, 0x2A, 0xBD, 0x0B, 0x72, 0xF6 } }; //8EF324ED-367C-4880-83E5-BB2ABD0B72F6 constexpr CLSID CLSID_AuthenticationArguments = { 0x6484A61D, 0x50FA, 0x41F0, { 0xB7, 0x1E, 0xF4, 0x37, 0x0C, 0x6E, 0xB3, 0x7C } }; //6484A61D-50FA-41F0-B71E-F4370C6EB37C constexpr CLSID CLSID_RepairOptions = { 0xE62BB1E7, 0xC7B2, 0x4AEC, { 0x9E, 0x28, 0xFB, 0x64, 0x9B, 0x30, 0xFF, 0x03 } }; //E62BB1E7-C7B2-4AEC-9E28-FB649B30FF03 + constexpr CLSID CLSID_AddPackageCatalogOptions = { 0xD58C7E4C, 0x70E6, 0x476C, { 0xA5, 0xD4, 0x80, 0x34, 0x1E, 0xD8, 0x02, 0x52 } }; //D58C7E4C-70E6-476C-A5D4-80341ED80252 + constexpr CLSID CLSID_RemovePackageCatalogOptions = { 0x87A96609, 0x1A39, 0x4955, { 0xBE, 0x72, 0x71, 0x74, 0xE1, 0x47, 0xB7, 0xDC } }; //87A96609-1A39-4955-BE72-7174E147B7DC + #endif struct NameCLSIDPair @@ -40,7 +45,7 @@ namespace Microsoft::Management::Deployment::OutOfProc GUID CLSID; }; - constexpr std::array s_nameCLSIDPairs + constexpr std::array s_nameCLSIDPairs { NameCLSIDPair{ L"Microsoft.Management.Deployment.PackageManager"sv, CLSID_PackageManager }, NameCLSIDPair{ L"Microsoft.Management.Deployment.InstallOptions"sv, CLSID_InstallOptions }, @@ -50,7 +55,9 @@ namespace Microsoft::Management::Deployment::OutOfProc NameCLSIDPair{ L"Microsoft.Management.Deployment.CreateCompositePackageCatalogOptions"sv, CLSID_CreateCompositePackageCatalogOptions }, NameCLSIDPair{ L"Microsoft.Management.Deployment.DownloadOptions"sv, CLSID_DownloadOptions }, NameCLSIDPair{ L"Microsoft.Management.Deployment.AuthenticationArguments"sv, CLSID_AuthenticationArguments }, - NameCLSIDPair{ L"Microsoft.Management.Deployment.RepairOptions"sv, CLSID_RepairOptions } + NameCLSIDPair{ L"Microsoft.Management.Deployment.RepairOptions"sv, CLSID_RepairOptions }, + NameCLSIDPair{ L"Microsoft.Management.Deployment.AddPackageCatalogOptions"sv, CLSID_AddPackageCatalogOptions }, + NameCLSIDPair{ L"Microsoft.Management.Deployment.RemovePackageCatalogOptions"sv, CLSID_RemovePackageCatalogOptions }, }; bool IsCLSIDPresent(const GUID& clsid) diff --git a/src/Microsoft.Management.Deployment.Projection/ClassesDefinition.cs b/src/Microsoft.Management.Deployment.Projection/ClassesDefinition.cs index bf39299cc8..ed6adfb500 100644 --- a/src/Microsoft.Management.Deployment.Projection/ClassesDefinition.cs +++ b/src/Microsoft.Management.Deployment.Projection/ClassesDefinition.cs @@ -126,6 +126,30 @@ internal static class ClassesDefinition [ClsidContext.OutOfProc] = new Guid("0498F441-3097-455F-9CAF-148F28293865"), [ClsidContext.OutOfProcDev] = new Guid("E62BB1E7-C7B2-4AEC-9E28-FB649B30FF03"), } + }, + + [typeof(AddPackageCatalogOptions)] = new() + { + ProjectedClassType = typeof(AddPackageCatalogOptions), + InterfaceType = typeof(IAddPackageCatalogOptions), + Clsids = new Dictionary() + { + [ClsidContext.InProc] = new Guid("24E6F1FA-E4C3-4ACD-965D-DF213FD58F15"), + [ClsidContext.OutOfProc] = new Guid("DB9D012D-00D7-47EE-8FB1-606E10AC4F51"), + [ClsidContext.OutOfProcDev] = new Guid("D58C7E4C-70E6-476C-A5D4-80341ED80252"), + } + }, + + [typeof(RemovePackageCatalogOptions)] = new() + { + ProjectedClassType = typeof(RemovePackageCatalogOptions), + InterfaceType = typeof(IRemovePackageCatalogOptions), + Clsids = new Dictionary() + { + [ClsidContext.InProc] = new Guid("1125D3A6-E2CE-479A-91D5-71A3F6F8B00B"), + [ClsidContext.OutOfProc] = new Guid("032B1C58-B975-469B-A013-E632B6ECE8D8"), + [ClsidContext.OutOfProcDev] = new Guid("87A96609-1A39-4955-BE72-7174E147B7DC"), + } } }; diff --git a/src/Microsoft.Management.Deployment.Projection/WinGetProjectionFactory.cs b/src/Microsoft.Management.Deployment.Projection/WinGetProjectionFactory.cs index 73b75d5c70..5201492b2f 100644 --- a/src/Microsoft.Management.Deployment.Projection/WinGetProjectionFactory.cs +++ b/src/Microsoft.Management.Deployment.Projection/WinGetProjectionFactory.cs @@ -33,8 +33,12 @@ public WinGetProjectionFactory(IInstanceInitializer instanceInitializer) public AuthenticationArguments CreateAuthenticationArguments() => InstanceInitializer.CreateInstance(); - public PackageManagerSettings CreatePackageManagerSettings() => InstanceInitializer.CreateInstance(); + public PackageManagerSettings CreatePackageManagerSettings() => InstanceInitializer.CreateInstance(); public RepairOptions CreateRepairOptions() => InstanceInitializer.CreateInstance(); + + public AddPackageCatalogOptions CreateAddPackageCatalogOptions() => InstanceInitializer.CreateInstance(); + + public RemovePackageCatalogOptions CreateRemovePackageCatalogOptions() => InstanceInitializer.CreateInstance(); } } diff --git a/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.cpp b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.cpp new file mode 100644 index 0000000000..b31d0962f5 --- /dev/null +++ b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.cpp @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#pragma warning( push ) +#pragma warning ( disable : 4467 6388) +// 6388 Allow CreateInstance. +#include +// 4467 Allow use of uuid attribute for com object creation. +#include "AddPackageCatalogOptions.h" +#pragma warning( pop ) +#include "AddPackageCatalogOptions.g.cpp" +#include "Converters.h" +#include "Helpers.h" + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + hstring AddPackageCatalogOptions::Name() + { + return hstring(m_name); + } + void AddPackageCatalogOptions::Name(hstring const& value) + { + m_name = value; + } + hstring AddPackageCatalogOptions::SourceUri() + { + return hstring(m_sourceUri); + } + void AddPackageCatalogOptions::SourceUri(hstring const& value) + { + m_sourceUri = value; + } + hstring AddPackageCatalogOptions::Type() + { + return hstring(m_type); + } + void AddPackageCatalogOptions::Type(hstring const& value) + { + m_type = value; + } + winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel AddPackageCatalogOptions::TrustLevel() + { + return m_trustLevel; + } + void AddPackageCatalogOptions::TrustLevel(winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel const& value) + { + m_trustLevel = value; + } + hstring AddPackageCatalogOptions::CustomHeader() + { + return hstring(m_customHeader); + } + void AddPackageCatalogOptions::CustomHeader(hstring const& value) + { + m_customHeader = value; + } + bool AddPackageCatalogOptions::Explicit() + { + return m_explicit; + } + void AddPackageCatalogOptions::Explicit(bool const& value) + { + m_explicit = value; + } + CoCreatableMicrosoftManagementDeploymentClass(AddPackageCatalogOptions); +} diff --git a/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h new file mode 100644 index 0000000000..91ec268cad --- /dev/null +++ b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once +#include "AddPackageCatalogOptions.g.h" +#include "public/ComClsids.h" + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + [uuid(WINGET_OUTOFPROC_COM_CLSID_AddPackageCatalogOptions)] + struct AddPackageCatalogOptions : AddPackageCatalogOptionsT + { + AddPackageCatalogOptions() = default; + + hstring Name(); + void Name(hstring const& value); + + hstring SourceUri(); + void SourceUri(hstring const& value); + + hstring Type(); + void Type(hstring const& value); + + winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel TrustLevel(); + void TrustLevel(winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel const& value); + + hstring CustomHeader(); + void CustomHeader(hstring const& value); + + bool Explicit(); + void Explicit(bool const& value); + +#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) + private: + std::wstring m_name = L""; + std::wstring m_sourceUri = L""; + std::wstring m_type = L""; + winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel m_trustLevel = winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel::None; + std::wstring m_customHeader = L""; + bool m_explicit = false; +#endif + }; +} + +#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) +namespace winrt::Microsoft::Management::Deployment::factory_implementation +{ + struct AddPackageCatalogOptions : AddPackageCatalogOptionsT + { + }; +} +#endif diff --git a/src/Microsoft.Management.Deployment/AddPackageCatalogResult.cpp b/src/Microsoft.Management.Deployment/AddPackageCatalogResult.cpp new file mode 100644 index 0000000000..f337c873e0 --- /dev/null +++ b/src/Microsoft.Management.Deployment/AddPackageCatalogResult.cpp @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "AddPackageCatalogResult.h" +#include "AddPackageCatalogResult.g.cpp" +#include + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + void AddPackageCatalogResult::Initialize( + winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus status, + winrt::hresult extendedErrorCode) + { + m_status = status; + m_extendedErrorCode = extendedErrorCode; + } + winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus AddPackageCatalogResult::Status() + { + return m_status; + } + winrt::hresult AddPackageCatalogResult::ExtendedErrorCode() + { + return m_extendedErrorCode; + } +} diff --git a/src/Microsoft.Management.Deployment/AddPackageCatalogResult.h b/src/Microsoft.Management.Deployment/AddPackageCatalogResult.h new file mode 100644 index 0000000000..a12def883b --- /dev/null +++ b/src/Microsoft.Management.Deployment/AddPackageCatalogResult.h @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once +#include "AddPackageCatalogResult.g.h" + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + struct AddPackageCatalogResult : AddPackageCatalogResultT + { + AddPackageCatalogResult() = default; + +#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) + void Initialize( + winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus status, + winrt::hresult extendedErrorCode); +#endif + + winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus Status(); + winrt::hresult ExtendedErrorCode(); + +#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) + private: + winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus m_status = winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus::Ok; + winrt::hresult m_extendedErrorCode = S_OK; +#endif + }; +} +#pragma once diff --git a/src/Microsoft.Management.Deployment/ComClsids.cpp b/src/Microsoft.Management.Deployment/ComClsids.cpp index d76c1daf10..1cf315ba5c 100644 --- a/src/Microsoft.Management.Deployment/ComClsids.cpp +++ b/src/Microsoft.Management.Deployment/ComClsids.cpp @@ -14,7 +14,9 @@ #include "PackageManagerSettings.h" #include "DownloadOptions.h" #include "AuthenticationArguments.h" -#include "RepairOptions.h" +#include "RepairOptions.h" +#include "AddPackageCatalogOptions.h" +#include "RemovePackageCatalogOptions.h" #pragma warning( pop ) namespace winrt::Microsoft::Management::Deployment @@ -60,6 +62,14 @@ namespace winrt::Microsoft::Management::Deployment else if (IsEqualCLSID(clsid, WINGET_INPROC_COM_CLSID_RepairOptions)) { return __uuidof(winrt::Microsoft::Management::Deployment::implementation::RepairOptions); + } + else if (IsEqualCLSID(clsid, WINGET_INPROC_COM_CLSID_AddPackageCatalogOptions)) + { + return __uuidof(winrt::Microsoft::Management::Deployment::implementation::AddPackageCatalogOptions); + } + else if (IsEqualCLSID(clsid, WINGET_INPROC_COM_CLSID_RemovePackageCatalogOptions)) + { + return __uuidof(winrt::Microsoft::Management::Deployment::implementation::RemovePackageCatalogOptions); } else { diff --git a/src/Microsoft.Management.Deployment/Converters.cpp b/src/Microsoft.Management.Deployment/Converters.cpp index e016a95dd4..5412dea8f9 100644 --- a/src/Microsoft.Management.Deployment/Converters.cpp +++ b/src/Microsoft.Management.Deployment/Converters.cpp @@ -497,4 +497,37 @@ namespace winrt::Microsoft::Management::Deployment::implementation return result; } + + AddPackageCatalogStatus GetAddPackageCatalogOperationStatus(winrt::hresult hresult) + { + switch (hresult) + { + case APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED: + return AddPackageCatalogStatus::AuthenticationError; + case APPINSTALLER_CLI_ERROR_SOURCE_NOT_SECURE: + case APPINSTALLER_CLI_ERROR_INVALID_SOURCE_TYPE: + case APPINSTALLER_CLI_ERROR_SOURCE_NOT_REMOTE: + case APPINSTALLER_CLI_ERROR_SOURCE_NAME_ALREADY_EXISTS: + case APPINSTALLER_CLI_ERROR_SOURCE_ARG_ALREADY_EXISTS: + return AddPackageCatalogStatus::InvalidOptions; + case APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED: + return AddPackageCatalogStatus::CatalogError; + default: + return HandleCommonCatalogOperationStatus(hresult); + } + } + + RemovePackageCatalogStatus GetRemovePackageCatalogOperationStatus(winrt::hresult hresult) + { + switch (hresult) + { + case APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST: + return RemovePackageCatalogStatus::InvalidOptions; + case APPINSTALLER_CLI_ERROR_INVALID_SOURCE_TYPE: + return RemovePackageCatalogStatus::CatalogError; + default: + return HandleCommonCatalogOperationStatus(hresult); + } + } + } diff --git a/src/Microsoft.Management.Deployment/Converters.h b/src/Microsoft.Management.Deployment/Converters.h index fa0993e3ae..a861302341 100644 --- a/src/Microsoft.Management.Deployment/Converters.h +++ b/src/Microsoft.Management.Deployment/Converters.h @@ -31,6 +31,8 @@ namespace winrt::Microsoft::Management::Deployment::implementation ::AppInstaller::Authentication::AuthenticationMode GetAuthenticationMode(winrt::Microsoft::Management::Deployment::AuthenticationMode authMode); ::AppInstaller::Authentication::AuthenticationArguments GetAuthenticationArguments(winrt::Microsoft::Management::Deployment::AuthenticationArguments authArgs); ::AppInstaller::Manifest::ScopeEnum GetManifestRepairScope(winrt::Microsoft::Management::Deployment::PackageRepairScope scope); + winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus GetAddPackageCatalogOperationStatus(winrt::hresult hresult); + winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus GetRemovePackageCatalogOperationStatus(winrt::hresult hresult); #define WINGET_GET_OPERATION_RESULT_STATUS(_installResultStatus_, _uninstallResultStatus_, _downloadResultStatus_, _repairResultStatus_) \ if constexpr (std::is_same_v) \ @@ -141,4 +143,59 @@ namespace winrt::Microsoft::Management::Deployment::implementation return resultStatus; } + + template + TStatus HandleCommonCatalogOperationStatus(winrt::hresult hresult) + { + // Common status handling for AddPackageCatalogStatus and RemovePackageCatalogStatus. + if constexpr (std::is_same_v || std::is_same_v) + { + switch (hresult) + { + case APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN: + case E_ACCESSDENIED: + return TStatus::AccessDenied; + case APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS: + case E_INVALIDARG: + return TStatus::InvalidOptions; + default: + break; + } + } + + // Common status handling for AddPackageCatalogStatus, RemovePackageCatalogStatus, and RefreshPackageCatalogStatus. + switch (hresult) + { + case S_OK: + return TStatus::Ok; + case APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY: + return TStatus::GroupPolicyError; + case APPINSTALLER_CLI_ERROR_SOURCE_DATA_INTEGRITY_FAILURE: + return TStatus::CatalogError; + case APPINSTALLER_CLI_ERROR_INTERNAL_ERROR: + default: + return TStatus::InternalError; + } + } + + template + TStatus GetPackageCatalogOperationStatus(winrt::hresult hresult) + { + if constexpr (std::is_same_v) + { + return GetAddPackageCatalogOperationStatus(hresult); + } + else if constexpr (std::is_same_v) + { + return GetRemovePackageCatalogOperationStatus(hresult); + } + else if constexpr (std::is_same_v) + { + return HandleCommonCatalogOperationStatus(hresult); + } + else + { + throw winrt::hresult_error(E_UNEXPECTED); + } + } } diff --git a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj index a1c3e41274..78cb7dc534 100644 --- a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj +++ b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj @@ -183,6 +183,8 @@ + + @@ -217,13 +219,18 @@ + + + + + @@ -259,12 +266,15 @@ Create + + + diff --git a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters index 128b48aeff..22d8f3398c 100644 --- a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters +++ b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters @@ -40,6 +40,11 @@ + + + + + @@ -85,6 +90,11 @@ + + + + + diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp index 4d9f0cc197..c6bf9e126d 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp @@ -18,9 +18,22 @@ #include #include #include +#include +#include namespace winrt::Microsoft::Management::Deployment::implementation { + namespace + { + winrt::Microsoft::Management::Deployment::RefreshPackageCatalogResult GetRefreshPackageCatalogResult(winrt::hresult terminationStatus) + { + winrt::Microsoft::Management::Deployment::RefreshPackageCatalogStatus status = GetPackageCatalogOperationStatus(terminationStatus); + auto updateResult = winrt::make_self>(); + updateResult->Initialize(status, terminationStatus); + return *updateResult; + } + } + void PackageCatalogReference::Initialize(winrt::Microsoft::Management::Deployment::PackageCatalogInfo packageCatalogInfo, ::AppInstaller::Repository::Source sourceReference) { m_info = packageCatalogInfo; @@ -289,4 +302,35 @@ namespace winrt::Microsoft::Management::Deployment::implementation }); return m_authenticationInfo; } + + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageCatalogReference::RefreshPackageCatalogAsync() + { + HRESULT terminationHR = S_OK; + try { + // Check for permissions and get caller info for telemetry + THROW_IF_FAILED(EnsureComCallerHasCapability(Capability::PackageQuery)); + + auto report_progress{ co_await winrt::get_progress_token() }; + co_await winrt::resume_background(); + + AppInstaller::CallbackDispatcherSink progressCallback; + + progressCallback.AddCallback([&report_progress](uint64_t current, uint64_t maximum, AppInstaller::ProgressType type) + { + UNREFERENCED_PARAMETER(type); + UNREFERENCED_PARAMETER(maximum); + report_progress(static_cast(current)); + }); + + ::AppInstaller::ProgressCallback progress(&progressCallback); + + this->m_sourceReference.Update(progress); + } + catch (...) + { + terminationHR = AppInstaller::CLI::Workflow::HandleException(nullptr, std::current_exception()); + } + + co_return GetRefreshPackageCatalogResult(terminationHR); + } } diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.h b/src/Microsoft.Management.Deployment/PackageCatalogReference.h index fbfc68fe24..75539d926a 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.h +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.h @@ -32,7 +32,9 @@ namespace winrt::Microsoft::Management::Deployment::implementation void InstalledPackageInformationOnly(bool value); winrt::Microsoft::Management::Deployment::AuthenticationArguments AuthenticationArguments(); void AuthenticationArguments(winrt::Microsoft::Management::Deployment::AuthenticationArguments const& value); - winrt::Microsoft::Management::Deployment::AuthenticationInfo AuthenticationInfo(); + winrt::Microsoft::Management::Deployment::AuthenticationInfo AuthenticationInfo(); + // Contract 12.0 + winrt::Windows::Foundation::IAsyncOperationWithProgress RefreshPackageCatalogAsync(); #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) private: diff --git a/src/Microsoft.Management.Deployment/PackageManager.cpp b/src/Microsoft.Management.Deployment/PackageManager.cpp index 6e21cab2e1..47ad79bafa 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.cpp +++ b/src/Microsoft.Management.Deployment/PackageManager.cpp @@ -30,9 +30,13 @@ #include "PackageCatalogReference.h" #include "PackageVersionInfo.h" #include "PackageVersionId.h" +#include "AddPackageCatalogResult.h" +#include "RemovePackageCatalogResult.h" #include "Converters.h" #include "Helpers.h" #include "ContextOrchestrator.h" +#include "AppInstallerRuntime.h" +#include using namespace std::literals::chrono_literals; using namespace ::AppInstaller::CLI; @@ -52,6 +56,113 @@ namespace winrt::Microsoft::Management::Deployment::implementation ::AppInstaller::Logging::Telemetry().LogStartup(true); }); } + + winrt::Microsoft::Management::Deployment::AddPackageCatalogResult GetAddPackageCatalogResult(winrt::hresult terminationStatus) + { + winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus status = GetPackageCatalogOperationStatus(terminationStatus); + auto addPackageCatalogResult = winrt::make_self>(); + addPackageCatalogResult->Initialize(status, terminationStatus); + return *addPackageCatalogResult; + } + + void CheckForDuplicateSource(const std::string& name, const std::string& type, const std::string& sourceUri) + { + auto sourceList = ::AppInstaller::Repository::Source::GetCurrentSources(); + + std::string sourceType = type; + + // [NOTE:] If the source type is not specified, the default source type will be used for validation.In cases where the source type is empty, + // it remains unassigned until the add operation, at which point it is assigned.Without this default assignment, an empty string could be + // compared to the default type, potentially allowing different source names with the same URI to be seen as unique. + // To avoid this, assign the default source type prior to comparison. + if (sourceType.empty()) + { + // This method of obtaining the default source type is slightly expensive as it requires creating a SourceFactory object + // and fetching the type name.Nonetheless, it future-proofs the code against any changes in the SourceFactory's default type. + sourceType = ::AppInstaller::Repository::Source::GetDefaultSourceType(); + } + + for (const auto& source : sourceList) + { + THROW_HR_IF(APPINSTALLER_CLI_ERROR_SOURCE_NAME_ALREADY_EXISTS, ::AppInstaller::Utility::ICUCaseInsensitiveEquals(source.Name, name)); + + bool sourceUriAlreadyExists = !source.Arg.empty() && source.Arg == sourceUri && source.Type == sourceType; + THROW_HR_IF(APPINSTALLER_CLI_ERROR_SOURCE_ARG_ALREADY_EXISTS, sourceUriAlreadyExists); + } + } + + ::AppInstaller::Repository::Source CreateSourceFromOptions(const winrt::Microsoft::Management::Deployment::AddPackageCatalogOptions& options) + { + std::string name = winrt::to_string(options.Name()); + std::string type = winrt::to_string(options.Type()); + std::string sourceUri = winrt::to_string(options.SourceUri()); + + AppInstaller::Repository::SourceTrustLevel trustLevel = AppInstaller::Repository::SourceTrustLevel::None; + if (options.TrustLevel() == winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel::Trusted) + { + trustLevel = AppInstaller::Repository::SourceTrustLevel::Trusted; + } + + CheckForDuplicateSource(name, type, sourceUri); + + ::AppInstaller::Repository::Source source = ::AppInstaller::Repository::Source{ name, sourceUri, type, trustLevel, options.Explicit() }; + + std::string customHeader = winrt::to_string(options.CustomHeader()); + if (!customHeader.empty()) + { + source.SetCustomHeader(customHeader); + } + + try + { + auto sourceInfo = source.GetInformation(); + + if (sourceInfo.Authentication.Type == ::AppInstaller::Authentication::AuthenticationType::Unknown) + { + throw winrt::hresult_error(APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED); + } + } + catch (const winrt::hresult_error& hre) + { + if (hre.code() == APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED) + { + THROW_HR(APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED); + } + else + { + THROW_HR(APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED); + } + } + catch (...) // Catch all exceptions + { + THROW_HR(APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED); + } + + return source; + } + + winrt::Microsoft::Management::Deployment::RemovePackageCatalogResult GetRemovePackageCatalogResult(winrt::hresult terminationStatus) + { + winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus status = GetPackageCatalogOperationStatus(terminationStatus); + auto removeResult = winrt::make_self>(); + removeResult->Initialize(status, terminationStatus); + return *removeResult; + } + + std::optional<::AppInstaller::Repository::SourceDetails> GetMatchingSource(const std::string& name) + { + auto sourceList = ::AppInstaller::Repository::Source::GetCurrentSources(); + + for (const auto& source : sourceList) + { + if (::AppInstaller::Utility::ICUCaseInsensitiveEquals(source.Name, name)) + { + return source; // Return the first matching source + } + } + + return std::nullopt; // Return std::nullopt if no matching source is found + } } winrt::Windows::Foundation::Collections::IVectorView PackageManager::GetPackageCatalogs() @@ -843,7 +954,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation } else if constexpr (std::is_same_v) { - TProgress queuedProgress{ TProgressState::Queued, 0}; + TProgress queuedProgress{ TProgressState::Queued, 0 }; report_progress(queuedProgress); } else if constexpr (std::is_same_v) @@ -1197,5 +1308,102 @@ namespace winrt::Microsoft::Management::Deployment::implementation true /*canCancelQueueItem*/, nullptr /*queueItem*/, package, options, std::move(callerProcessInfoString)); } + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::AddPackageCatalogAsync(winrt::Microsoft::Management::Deployment::AddPackageCatalogOptions options) + { + LogStartupIfApplicable(); + + // options must be set. + THROW_HR_IF_NULL(E_INVALIDARG, options); + THROW_HR_IF(E_INVALIDARG, options.Name().empty()); + THROW_HR_IF(E_INVALIDARG, options.SourceUri().empty()); + + HRESULT terminationHR = S_OK; + try { + + // Check if running as admin/system. + // [NOTE:] For OutOfProc calls, the Windows Package Manager Service executes in the context initiated by the caller process, + // so the same admin/system validation check is applicable for both InProc and OutOfProc calls. + THROW_HR_IF(APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN, !AppInstaller::Runtime::IsRunningAsAdminOrSystem()); + + ::AppInstaller::Repository::Source sourceToAdd = CreateSourceFromOptions(options); + + auto report_progress{ co_await winrt::get_progress_token() }; + co_await winrt::resume_background(); + + AppInstaller::CallbackDispatcherSink progressCallback; + + progressCallback.AddCallback([&report_progress](uint64_t current, uint64_t maximum, AppInstaller::ProgressType type) + { + UNREFERENCED_PARAMETER(type); + UNREFERENCED_PARAMETER(maximum); + report_progress(static_cast(current)); + }); + + ::AppInstaller::ProgressCallback progress(&progressCallback); + + sourceToAdd.Add(progress); + } + catch (...) + { + terminationHR = AppInstaller::CLI::Workflow::HandleException(nullptr, std::current_exception()); + } + + co_return GetAddPackageCatalogResult(terminationHR); + } + + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::RemovePackageCatalogAsync(winrt::Microsoft::Management::Deployment::RemovePackageCatalogOptions options) + { + LogStartupIfApplicable(); + + // options must be set. + THROW_HR_IF_NULL(E_INVALIDARG, options); + THROW_HR_IF(E_INVALIDARG, options.Name().empty()); + + HRESULT terminationHR = S_OK; + try { + + // Check if running as admin/system. + // [NOTE:] For OutOfProc calls, the Windows Package Manager Service executes in the context initiated by the caller process, + // so the same admin/system validation check is applicable for both InProc and OutOfProc calls. + THROW_HR_IF(APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN, !AppInstaller::Runtime::IsRunningAsAdminOrSystem()); + + auto matchingSource = GetMatchingSource(winrt::to_string(options.Name())); + THROW_HR_IF(APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST, !matchingSource.has_value()); + + auto report_progress{ co_await winrt::get_progress_token() }; + co_await winrt::resume_background(); + + AppInstaller::CallbackDispatcherSink progressCallback; + ::AppInstaller::Repository::Source sourceToRemove = ::AppInstaller::Repository::Source{ matchingSource.value().Name }; + + progressCallback.AddCallback([&report_progress](uint64_t current, uint64_t maximum, AppInstaller::ProgressType type) + { + UNREFERENCED_PARAMETER(type); + UNREFERENCED_PARAMETER(maximum); + report_progress(static_cast(current)); + }); + + ::AppInstaller::ProgressCallback progress(&progressCallback); + + // If the PreserveData option is set, this is equivalent to the WinGet CLI Reset command on a single source; otherwise, it removes the source. + if (options.PreserveData()) + { + progressCallback.BeginProgress(); + THROW_HR_IF(APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST, !sourceToRemove.DropSource(matchingSource.value().Name)); + progressCallback.OnProgress(100, 100, AppInstaller::ProgressType::Percent); + } + else + { + sourceToRemove.Remove(progress); + } + } + catch (...) + { + terminationHR = AppInstaller::CLI::Workflow::HandleException(nullptr, std::current_exception()); + } + + co_return GetRemovePackageCatalogResult(terminationHR); + } + CoCreatableMicrosoftManagementDeploymentClass(PackageManager); } diff --git a/src/Microsoft.Management.Deployment/PackageManager.h b/src/Microsoft.Management.Deployment/PackageManager.h index 0ce0b32560..1758962bd9 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.h +++ b/src/Microsoft.Management.Deployment/PackageManager.h @@ -44,6 +44,11 @@ namespace winrt::Microsoft::Management::Deployment::implementation // Contract 11.0 winrt::Windows::Foundation::IAsyncOperationWithProgress RepairPackageAsync(winrt::Microsoft::Management::Deployment::CatalogPackage package, winrt::Microsoft::Management::Deployment::RepairOptions options); + // Contract 12.0 + winrt::Windows::Foundation::IAsyncOperationWithProgress + AddPackageCatalogAsync(winrt::Microsoft::Management::Deployment::AddPackageCatalogOptions options); + winrt::Windows::Foundation::IAsyncOperationWithProgress + RemovePackageCatalogAsync(winrt::Microsoft::Management::Deployment::RemovePackageCatalogOptions options); }; #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl index 8c5c166698..302e66fda5 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.idl +++ b/src/Microsoft.Management.Deployment/PackageManager.idl @@ -2,7 +2,7 @@ // Licensed under the MIT License. namespace Microsoft.Management.Deployment { - [contractversion(11)] // For version 1.9 + [contractversion(12)] // For version 1.10 apicontract WindowsPackageManagerContract{}; /// State of the install @@ -863,6 +863,25 @@ namespace Microsoft.Management.Deployment } } + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] + enum RefreshPackageCatalogStatus + { + Ok, + GroupPolicyError, + CatalogError, + InternalError, + }; + + /// IMPLEMENTATION NOTE: RefreshPackageCatalogResult + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] + runtimeclass RefreshPackageCatalogResult + { + RefreshPackageCatalogStatus Status { get; }; + + /// Error codes + HRESULT ExtendedErrorCode { get; }; + }; + /// A reference to a catalog that callers can try to Connect. [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 1)] runtimeclass PackageCatalogReference @@ -917,6 +936,12 @@ namespace Microsoft.Management.Deployment /// This is defined by individual package catalog. AuthenticationInfo AuthenticationInfo { get; }; } + + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] + { + /// Updates the package catalog. + Windows.Foundation.IAsyncOperationWithProgress RefreshPackageCatalogAsync(); + } } /// Catalogs with PackageCatalogOrigin Predefined @@ -1351,6 +1376,103 @@ namespace Microsoft.Management.Deployment String InstallationNotes { get; }; } + /// IMPLEMENTATION NOTE: AddPackageCatalogOptions + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] + runtimeclass AddPackageCatalogOptions + { + AddPackageCatalogOptions(); + + /// The name of the package catalog. + /// SAMPLE VALUES: For OpenWindowsCatalog "winget". + /// For contoso sample on msdn "contoso" + String Name; + + /// The SourceUri used when adding the package catalog. + /// SAMPLE VALUES: For OpenWindowsCatalog "https://winget.azureedge.net/cache" + /// For contoso sample on msdn "https://pkgmgr-int.azureedge.net/cache" + String SourceUri; + + /// ALLOWED VALUES: "Microsoft.Rest", "Microsoft.PreIndexed.Package" + /// SAMPLE VALUES: For OpenWindowsCatalog "Microsoft.PreIndexed.Package". + /// For contoso sample on msdn "Microsoft.PreIndexed.Package" + String Type; + + /// The trust level of the catalog to add. + PackageCatalogTrustLevel TrustLevel; + + /// Custom header to pass to the catalog. + String CustomHeader; + + /// Excludes a source from discovery unless specified. + Boolean Explicit; + }; + + /// IMPLEMENTATION NOTE: AddPackageCatalogStatus + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] + enum AddPackageCatalogStatus + { + Ok, + GroupPolicyError, + CatalogError, + InternalError, + InvalidOptions, + AccessDenied, + AuthenticationError, + }; + + /// IMPLEMENTATION NOTE: AddPackageCatalogResult + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] + runtimeclass AddPackageCatalogResult + { + AddPackageCatalogStatus Status { get; }; + + /// Error codes + HRESULT ExtendedErrorCode { get; }; + }; + + /// IMPLEMENTATION NOTE: RemovePackageCatalogOptions + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] + runtimeclass RemovePackageCatalogOptions + { + RemovePackageCatalogOptions(); + + /// The name of the package catalog. + /// SAMPLE VALUES: For OpenWindowsCatalog "winget". + /// For contoso sample on msdn "contoso" + String Name; + + /// By default, the value is 'false', resulting in the removal of the package catalog registration + /// from the winget Package catalogs list and the deletion of all associated system artifacts. This + /// mirrors the WinGet Source remove operation on a specific Package Catalog. + /// If set to 'true', it removes the package catalog registration from the Windows Package Catalogs + /// list without any cleanup, similar to the WinGet source reset operation on a specific Package + /// Catalog. + Boolean PreserveData; + }; + + /// IMPLEMENTATION NOTE: RemovePackageCatalogStatus + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] + enum RemovePackageCatalogStatus + { + Ok, + GroupPolicyError, + CatalogError, + InternalError, + AccessDenied, + InvalidOptions, + }; + + /// IMPLEMENTATION NOTE: RemovePackageCatalogResult + /// Result of removing a package catalog. + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] + runtimeclass RemovePackageCatalogResult + { + RemovePackageCatalogStatus Status { get; }; + + /// Error codes + HRESULT ExtendedErrorCode { get; }; + }; + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 1)] runtimeclass PackageManager { @@ -1370,6 +1492,15 @@ namespace Microsoft.Management.Deployment /// (Installing, Installed) together at the same time. PackageCatalogReference CreateCompositePackageCatalog(CreateCompositePackageCatalogOptions options); + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] + { + /// Add a catalog to the Windows Package Catalogs. + Windows.Foundation.IAsyncOperationWithProgress AddPackageCatalogAsync(AddPackageCatalogOptions options); + + /// Unregisters a Package Catalog from the Windows Package Catalogs and eliminates the system artifacts based on the provided options. + Windows.Foundation.IAsyncOperationWithProgress RemovePackageCatalogAsync(RemovePackageCatalogOptions options); + } + /// Install the specified package Windows.Foundation.IAsyncOperationWithProgress InstallPackageAsync(CatalogPackage package, InstallOptions options); diff --git a/src/Microsoft.Management.Deployment/Public/ComClsids.h b/src/Microsoft.Management.Deployment/Public/ComClsids.h index 8d787d635f..75f14afbd6 100644 --- a/src/Microsoft.Management.Deployment/Public/ComClsids.h +++ b/src/Microsoft.Management.Deployment/Public/ComClsids.h @@ -15,6 +15,8 @@ #define WINGET_OUTOFPROC_COM_CLSID_DownloadOptions "4CBABE76-7322-4BE4-9CEA-2589A80682DC" #define WINGET_OUTOFPROC_COM_CLSID_AuthenticationArguments "BA580786-BDE3-4F6C-B8F3-44698AC8711A" #define WINGET_OUTOFPROC_COM_CLSID_RepairOptions "0498F441-3097-455F-9CAF-148F28293865" +#define WINGET_OUTOFPROC_COM_CLSID_AddPackageCatalogOptions "DB9D012D-00D7-47EE-8FB1-606E10AC4F51" +#define WINGET_OUTOFPROC_COM_CLSID_RemovePackageCatalogOptions "032B1C58-B975-469B-A013-E632B6ECE8D8" #else #define WINGET_OUTOFPROC_COM_CLSID_PackageManager "74CB3139-B7C5-4B9E-9388-E6616DEA288C" #define WINGET_OUTOFPROC_COM_CLSID_FindPackagesOptions "1BD8FF3A-EC50-4F69-AEEE-DF4C9D3BAA96" @@ -26,6 +28,8 @@ #define WINGET_OUTOFPROC_COM_CLSID_DownloadOptions "8EF324ED-367C-4880-83E5-BB2ABD0B72F6" #define WINGET_OUTOFPROC_COM_CLSID_AuthenticationArguments "6484A61D-50FA-41F0-B71E-F4370C6EB37C" #define WINGET_OUTOFPROC_COM_CLSID_RepairOptions "E62BB1E7-C7B2-4AEC-9E28-FB649B30FF03" +#define WINGET_OUTOFPROC_COM_CLSID_AddPackageCatalogOptions "D58C7E4C-70E6-476C-A5D4-80341ED80252" +#define WINGET_OUTOFPROC_COM_CLSID_RemovePackageCatalogOptions "87A96609-1A39-4955-BE72-7174E147B7DC" #endif // Clsids only used in in-proc invocation @@ -44,6 +48,8 @@ namespace winrt::Microsoft::Management::Deployment const CLSID WINGET_INPROC_COM_CLSID_DownloadOptions = { 0x4288DF96, 0xFDC9, 0x4B68, 0xB4, 0x03, 0x19, 0x3D, 0xBB, 0xF5, 0x6A, 0x24 }; // 4288DF96-FDC9-4B68-B403-193DBBF56A24 const CLSID WINGET_INPROC_COM_CLSID_AuthenticationArguments = { 0x8D593114, 0x1CF1, 0x43B9, 0x87, 0x22, 0x4D, 0xBB, 0x30, 0x10, 0x32, 0x96 }; // 8D593114-1CF1-43B9-8722-4DBB30103296 const CLSID WINGET_INPROC_COM_CLSID_RepairOptions = { 0x30c024c4, 0x852c, 0x4dd4, 0x98, 0x10, 0x13, 0x48, 0xc5, 0x1e, 0xf9, 0xbb }; // {30C024C4-852C-4DD4-9810-1348C51EF9BB} + const CLSID WINGET_INPROC_COM_CLSID_AddPackageCatalogOptions = { 0x24e6f1fa, 0xe4c3, 0x4acd, 0x96, 0x5d, 0xdf, 0x21, 0x3f, 0xd5, 0x8f, 0x15 }; // {24E6F1FA-E4C3-4ACD-965D-DF213FD58F15} + const CLSID WINGET_INPROC_COM_CLSID_RemovePackageCatalogOptions = { 0x1125d3a6, 0xe2ce, 0x479a, 0x91, 0xd5, 0x71, 0xa3, 0xf6, 0xf8, 0xb0, 0xb }; // {1125D3A6-E2CE-479A-91D5-71A3F6F8B00B} CLSID GetRedirectedClsidFromInProcClsid(REFCLSID clsid); } diff --git a/src/Microsoft.Management.Deployment/RefreshPackageCatalogResult.cpp b/src/Microsoft.Management.Deployment/RefreshPackageCatalogResult.cpp new file mode 100644 index 0000000000..7a0fe2c586 --- /dev/null +++ b/src/Microsoft.Management.Deployment/RefreshPackageCatalogResult.cpp @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "RefreshPackageCatalogResult.h" +#include "RefreshPackageCatalogResult.g.cpp" +#include + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + void RefreshPackageCatalogResult::Initialize( + winrt::Microsoft::Management::Deployment::RefreshPackageCatalogStatus status, + winrt::hresult extendedErrorCode) + { + m_status = status; + m_extendedErrorCode = extendedErrorCode; + } + + winrt::Microsoft::Management::Deployment::RefreshPackageCatalogStatus RefreshPackageCatalogResult::Status() + { + return m_status; + } + + winrt::hresult RefreshPackageCatalogResult::ExtendedErrorCode() + { + return m_extendedErrorCode; + } +} diff --git a/src/Microsoft.Management.Deployment/RefreshPackageCatalogResult.h b/src/Microsoft.Management.Deployment/RefreshPackageCatalogResult.h new file mode 100644 index 0000000000..08fd3cb448 --- /dev/null +++ b/src/Microsoft.Management.Deployment/RefreshPackageCatalogResult.h @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once +#include "RefreshPackageCatalogResult.g.h" + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + struct RefreshPackageCatalogResult : RefreshPackageCatalogResultT + { + RefreshPackageCatalogResult() = default; + +#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) + void Initialize( + winrt::Microsoft::Management::Deployment::RefreshPackageCatalogStatus status, + winrt::hresult extendedErrorCode); +#endif + + winrt::Microsoft::Management::Deployment::RefreshPackageCatalogStatus Status(); + winrt::hresult ExtendedErrorCode(); + +#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) + private: + winrt::Microsoft::Management::Deployment::RefreshPackageCatalogStatus m_status = winrt::Microsoft::Management::Deployment::RefreshPackageCatalogStatus::Ok; + winrt::hresult m_extendedErrorCode = S_OK; +#endif + }; +} diff --git a/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.cpp b/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.cpp new file mode 100644 index 0000000000..e66d3dcb0f --- /dev/null +++ b/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.cpp @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#pragma warning( push ) +#pragma warning ( disable : 4467 6388) +// 6388 Allow CreateInstance. +#include +// 4467 Allow use of uuid attribute for com object creation. +#include "RemovePackageCatalogOptions.h" +#pragma warning( pop ) +#include "RemovePackageCatalogOptions.g.cpp" +#include "Converters.h" +#include "Helpers.h" + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + hstring RemovePackageCatalogOptions::Name() + { + return hstring(m_name); + } + void RemovePackageCatalogOptions::Name(hstring const& value) + { + m_name = value; + } + bool RemovePackageCatalogOptions::PreserveData() + { + return m_preserveData; + } + void RemovePackageCatalogOptions::PreserveData(bool const& value) + { + m_preserveData = value; + } + + CoCreatableMicrosoftManagementDeploymentClass(RemovePackageCatalogOptions); +} diff --git a/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.h b/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.h new file mode 100644 index 0000000000..ba312a70fa --- /dev/null +++ b/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.h @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once +#include "RemovePackageCatalogOptions.g.h" +#include "public/ComClsids.h" + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + [uuid(WINGET_OUTOFPROC_COM_CLSID_RemovePackageCatalogOptions)] + struct RemovePackageCatalogOptions : RemovePackageCatalogOptionsT + { + RemovePackageCatalogOptions() = default; + + hstring Name(); + void Name(hstring const& value); + + bool PreserveData(); + void PreserveData(bool const& value); + +#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) + private: + std::wstring m_name = L""; + bool m_preserveData = false; +#endif + }; +} + +#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) +namespace winrt::Microsoft::Management::Deployment::factory_implementation +{ + struct RemovePackageCatalogOptions : RemovePackageCatalogOptionsT + { + }; +} +#endif diff --git a/src/Microsoft.Management.Deployment/RemovePackageCatalogResult.cpp b/src/Microsoft.Management.Deployment/RemovePackageCatalogResult.cpp new file mode 100644 index 0000000000..b74be4bf79 --- /dev/null +++ b/src/Microsoft.Management.Deployment/RemovePackageCatalogResult.cpp @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "RemovePackageCatalogResult.h" +#include "RemovePackageCatalogResult.g.cpp" +#include + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + void RemovePackageCatalogResult::Initialize( + winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus status, + winrt::hresult extendedErrorCode) + { + m_status = status; + m_extendedErrorCode = extendedErrorCode; + } + winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus RemovePackageCatalogResult::Status() + { + return m_status; + } + winrt::hresult RemovePackageCatalogResult::ExtendedErrorCode() + { + return m_extendedErrorCode; + } +} diff --git a/src/Microsoft.Management.Deployment/RemovePackageCatalogResult.h b/src/Microsoft.Management.Deployment/RemovePackageCatalogResult.h new file mode 100644 index 0000000000..1f00690e1e --- /dev/null +++ b/src/Microsoft.Management.Deployment/RemovePackageCatalogResult.h @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once +#include "RemovePackageCatalogResult.g.h" + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + struct RemovePackageCatalogResult : RemovePackageCatalogResultT + { + RemovePackageCatalogResult() = default; + +#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) + void Initialize( + winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus status, + winrt::hresult extendedErrorCode); +#endif + + winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus Status(); + winrt::hresult ExtendedErrorCode(); + +#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) + private: + winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus m_status = winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus::Ok; + winrt::hresult m_extendedErrorCode = S_OK; +#endif + }; +} diff --git a/src/Microsoft.Management.Deployment/RepairOptions.h b/src/Microsoft.Management.Deployment/RepairOptions.h index 2794d1f231..2b083bef6a 100644 --- a/src/Microsoft.Management.Deployment/RepairOptions.h +++ b/src/Microsoft.Management.Deployment/RepairOptions.h @@ -7,7 +7,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation { [uuid(WINGET_OUTOFPROC_COM_CLSID_RepairOptions)] - struct RepairOptions : RepairOptionsT + struct RepairOptions : RepairOptionsT { RepairOptions(); diff --git a/src/WindowsPackageManager/main.cpp b/src/WindowsPackageManager/main.cpp index 21016db93d..751d75caa2 100644 --- a/src/WindowsPackageManager/main.cpp +++ b/src/WindowsPackageManager/main.cpp @@ -30,6 +30,8 @@ CoCreatableClassWrlCreatorMapInclude(PackageMatchFilter); CoCreatableClassWrlCreatorMapInclude(AuthenticationArguments); CoCreatableClassWrlCreatorMapInclude(PackageManagerSettings); CoCreatableClassWrlCreatorMapInclude(RepairOptions); +CoCreatableClassWrlCreatorMapInclude(AddPackageCatalogOptions); +CoCreatableClassWrlCreatorMapInclude(RemovePackageCatalogOptions); // Shim for configuration static functions CoCreatableClassWrlCreatorMapInclude(ConfigurationStaticFunctionsShim);