From 874c5237df3e77806a6ba66c605ae1e595dbdff1 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Sun, 15 Sep 2024 22:05:26 -0700 Subject: [PATCH 01/38] Implement skeleton for package catalog management - Update IDL for new runtime classes and methods. - Add files and classes for package catalog operations (add, remove, reset, update). - Update `PackageManager` with async methods for catalog operations. [Compiles successfully] --- .../AddPackageCatalogOptions.cpp | 67 ++++++ .../AddPackageCatalogOptions.h | 51 +++++ .../AddPackageCatalogResult.cpp | 25 ++ .../AddPackageCatalogResult.h | 28 +++ .../Microsoft.Management.Deployment.vcxproj | 10 + .../PackageManager.cpp | 28 +++ .../PackageManager.h | 7 + .../PackageManager.idl | 214 ++++++++++++++++++ .../Public/ComClsids.h | 5 +- .../RemovePackageCatalogResult.cpp | 25 ++ .../RemovePackageCatalogResult.h | 27 +++ .../ResetPackageCatalogResult.cpp | 25 ++ .../ResetPackageCatalogResult.h | 27 +++ .../UpdatePackageCatalogResult.cpp | 27 +++ .../UpdatePackageCatalogResult.h | 27 +++ 15 files changed, 592 insertions(+), 1 deletion(-) create mode 100644 src/Microsoft.Management.Deployment/AddPackageCatalogOptions.cpp create mode 100644 src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h create mode 100644 src/Microsoft.Management.Deployment/AddPackageCatalogResult.cpp create mode 100644 src/Microsoft.Management.Deployment/AddPackageCatalogResult.h create mode 100644 src/Microsoft.Management.Deployment/RemovePackageCatalogResult.cpp create mode 100644 src/Microsoft.Management.Deployment/RemovePackageCatalogResult.h create mode 100644 src/Microsoft.Management.Deployment/ResetPackageCatalogResult.cpp create mode 100644 src/Microsoft.Management.Deployment/ResetPackageCatalogResult.h create mode 100644 src/Microsoft.Management.Deployment/UpdatePackageCatalogResult.cpp create mode 100644 src/Microsoft.Management.Deployment/UpdatePackageCatalogResult.h diff --git a/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.cpp b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.cpp new file mode 100644 index 0000000000..a05e2292e3 --- /dev/null +++ b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.cpp @@ -0,0 +1,67 @@ +// 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::CatalogName() + { + return hstring(m_catalogName); + } + void AddPackageCatalogOptions::CatalogName(hstring const& value) + { + m_catalogName = 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; + } + hstring AddPackageCatalogOptions::Arguments() + { + return hstring(m_arguments); + } + void AddPackageCatalogOptions::Arguments(hstring const& value) + { + m_arguments = 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; + } + + CoCreatableMicrosoftManagementDeploymentClass(AddPackageCatalogOptions); +} diff --git a/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h new file mode 100644 index 0000000000..cdab8a64fd --- /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 CatalogName(); + void CatalogName(hstring const& value); + + hstring SourceUri(); + void SourceUri(hstring const& value); + + hstring Type(); + void Type(hstring const& value); + + hstring Arguments(); + void Arguments(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); + +#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) + private: + std::wstring m_catalogName = L""; + std::wstring m_sourceUri = L""; + std::wstring m_type = L""; + std::wstring m_arguments = L""; + winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel m_trustLevel = winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel::None; + std::wstring m_customHeader = L""; +#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/Microsoft.Management.Deployment.vcxproj b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj index 8047c96419..481a412568 100644 --- a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj +++ b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj @@ -183,6 +183,8 @@ + + @@ -217,11 +219,16 @@ + + + + + @@ -257,10 +264,13 @@ Create + + + diff --git a/src/Microsoft.Management.Deployment/PackageManager.cpp b/src/Microsoft.Management.Deployment/PackageManager.cpp index 20c5dfb18f..42afbee647 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.cpp +++ b/src/Microsoft.Management.Deployment/PackageManager.cpp @@ -1066,5 +1066,33 @@ namespace winrt::Microsoft::Management::Deployment::implementation return GetPackageOperation(true, std::move(queueItem)); } + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::AddPackageCatalogAsync(winrt::Microsoft::Management::Deployment::AddPackageCatalogOptions options) + { + // TODO: Implement AddPackageCatalogAsync + return winrt::Windows::Foundation::IAsyncOperationWithProgress(); + } + + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::RemovePackageCatalogAsync(hstring const& catalogName) + { + UNREFERENCED_PARAMETER(catalogName); + + // TODO: Implement RemovePackageCatalogAsync + return winrt::Windows::Foundation::IAsyncOperationWithProgress(); + } + + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::ResetPackageCatalogAsync() + { + // TODO: Implement ResetPackageCatalogAsync + return winrt::Windows::Foundation::IAsyncOperationWithProgress(); + } + + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::UpdatePackageCatalogAsync(hstring const& catalogName) + { + UNREFERENCED_PARAMETER(catalogName); + + // TODO: Implement UpdatePackageCatalogAsync + return winrt::Windows::Foundation::IAsyncOperationWithProgress(); + } + CoCreatableMicrosoftManagementDeploymentClass(PackageManager); } diff --git a/src/Microsoft.Management.Deployment/PackageManager.h b/src/Microsoft.Management.Deployment/PackageManager.h index 3b07342be3..0202718c96 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.h +++ b/src/Microsoft.Management.Deployment/PackageManager.h @@ -41,6 +41,13 @@ namespace winrt::Microsoft::Management::Deployment::implementation DownloadPackageAsync(winrt::Microsoft::Management::Deployment::CatalogPackage package, winrt::Microsoft::Management::Deployment::DownloadOptions options); winrt::Windows::Foundation::IAsyncOperationWithProgress GetDownloadProgress(winrt::Microsoft::Management::Deployment::CatalogPackage package, winrt::Microsoft::Management::Deployment::PackageCatalogInfo catalogInfo); + // Contract 11.0 + winrt::Windows::Foundation::IAsyncOperationWithProgress + AddPackageCatalogAsync(winrt::Microsoft::Management::Deployment::AddPackageCatalogOptions options); + winrt::Windows::Foundation::IAsyncOperationWithProgress + RemovePackageCatalogAsync(hstring const& catalogName); + winrt::Windows::Foundation::IAsyncOperationWithProgress ResetPackageCatalogAsync(); + winrt::Windows::Foundation::IAsyncOperationWithProgress UpdatePackageCatalogAsync(hstring const& catalogName); }; #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl index 43ade7aa71..565c11be15 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.idl +++ b/src/Microsoft.Management.Deployment/PackageManager.idl @@ -1214,6 +1214,206 @@ namespace Microsoft.Management.Deployment String InstallationNotes { get; }; } + /// IMPLEMENTATION NOTE: AddPackageCatalogOptions + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + runtimeclass AddPackageCatalogOptions + { + AddPackageCatalogOptions(); + + /// The name of the catalog to add. + String CatalogName; + /// The source URI of the catalog to add. + String SourceUri; + /// Type of the catalog to add. + String Type; + /// Additional arguments to pass to the catalog. + String Arguments; + /// The trust level of the catalog to add. + PackageCatalogTrustLevel TrustLevel; + /// Custom header to pass to the catalog. + String CustomHeader; + }; + + /// IMPLEMENTATION NOTE: AddPackageCatalogStatus + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + enum AddPackageCatalogStatus + { + Ok, + GroupPolicyError, + CatalogError, + InternalError, + }; + + /// IMPLEMENTATION NOTE: AddPackageCatalogResult + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + runtimeclass AddPackageCatalogResult + { + AddPackageCatalogStatus Status { get; }; + + /// Error codes + HRESULT ExtendedErrorCode { get; }; + }; + + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + enum AddPackageCatalogProgressState + { + /// The AddCatalog is queued but not yet active. Cancellation of the IAsyncOperationWithProgress in this + /// state will prevent the Catalog addition. + Queued, + + /// The AddPackageCatalog is in progress. Cancellation of the IAsyncOperationWithProgress in this state will not + /// stop AddPackageCatalog operation. + AddingCatalog, + + /// The operation is complete. + Finished, + }; + + /// IMPLEMENTATION NOTE: AddPackageCatalogProgress + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + struct AddPackageCatalogProgress + { + AddPackageCatalogProgressState State; + + /// The progress percentage of the operation. + Double ProgressPercentage; + }; + + /// IMPLEMENTATION NOTE: RemovePackageCatalogStatus + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + enum RemovePackageCatalogStatus + { + Ok, + GroupPolicyError, + CatalogError, + InternalError, + }; + + /// IMPLEMENTATION NOTE: RemovePackageCatalogResult + /// Result of removing a package catalog. + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + runtimeclass RemovePackageCatalogResult + { + RemovePackageCatalogStatus Status { get; }; + + /// Error codes + HRESULT ExtendedErrorCode { get; }; + }; + + /// IMPLEMENTATION NOTE: RemovePackageCatalogProgressState + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + enum RemovePackageCatalogProgressState + { + /// The RemovePackageCatalog is queued but not yet active. Cancellation of the IAsyncOperationWithProgress in this + /// state will prevent the PackageCatalog removal. + Queued, + + /// The RemovePackageCatalog is in progress. Cancellation of the IAsyncOperationWithProgress in this state will not + /// stop RemovePackageCatalog operation. + RemovingCatalog, + + /// The operation is complete. + Finished, + }; + + /// IMPLEMENTATION NOTE: RemovePackageCatalogProgress + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + struct RemovePackageCatalogProgress + { + RemovePackageCatalogProgressState State; + + /// The progress percentage of the operation. + Double ProgressPercentage; + }; + + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + enum ResetPackageCatalogStatus + { + Ok, + GroupPolicyError, + CatalogError, + InternalError, + }; + + /// IMPLEMENTATION NOTE: ResetPackageCatalogResult + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + runtimeclass ResetPackageCatalogResult + { + ResetPackageCatalogStatus Status { get; }; + + /// Error codes + HRESULT ExtendedErrorCode { get; }; + }; + + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + enum ResetPackageCatalogProgressState + { + /// The ResetPackageCatalog is queued but not yet active. Cancellation of the IAsyncOperationWithProgress in this + /// state will prevent the PackageCatalog reset. + Queued, + + /// The ResetPackageCatalog is in progress. Cancellation of the IAsyncOperationWithProgress in this state will not + /// stop ResetPackageCatalog operation. + ResettingCatalog, + + /// The operation is complete. + Finished, + }; + + /// IMPLEMENTATION NOTE: ResetPackageCatalogProgress + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + struct ResetPackageCatalogProgress + { + ResetPackageCatalogProgressState State; + + /// The progress percentage of the operation. + Double ProgressPercentage; + }; + + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + enum UpdatePackageCatalogStatus + { + Ok, + GroupPolicyError, + CatalogError, + InternalError, + }; + + /// IMPLEMENTATION NOTE: UpdatePackageCatalogResult + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + runtimeclass UpdatePackageCatalogResult + { + UpdatePackageCatalogStatus Status { get; }; + + /// Error codes + HRESULT ExtendedErrorCode { get; }; + }; + + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + enum UpdatePackageCatalogProgressState + { + /// The UpdatePackageCatalog is queued but not yet active. Cancellation of the IAsyncOperationWithProgress in this + /// state will prevent the UpdatePackageCatalog reset. + Queued, + + // The UpdatePackageCatalog is in progress. Cancellation of the IAsyncOperationWithProgress in this state will not + /// stop UpdatePackageCatalog operation. + UpdatingCatalog, + + /// The operation is complete. + Finished, + }; + + /// IMPLEMENTATION NOTE: UpdatePackageCatalogProgress + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + struct UpdatePackageCatalogProgress + { + UpdatePackageCatalogProgressState State; + + /// The progress percentage of the operation. + Double ProgressPercentage; + }; + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 1)] runtimeclass PackageManager { @@ -1233,6 +1433,20 @@ namespace Microsoft.Management.Deployment /// (Installing, Installed) together at the same time. PackageCatalogReference CreateCompositePackageCatalog(CreateCompositePackageCatalogOptions options); + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + { + Windows.Foundation.IAsyncOperationWithProgress AddPackageCatalogAsync(AddPackageCatalogOptions options); + + /// Removes a source from the Windows Package Manager source list. + Windows.Foundation.IAsyncOperationWithProgress RemovePackageCatalogAsync(String catalogName); + + /// Resets the package catalog to the default state. + Windows.Foundation.IAsyncOperationWithProgress ResetPackageCatalogAsync(); + + /// Updates the package catalog. + Windows.Foundation.IAsyncOperationWithProgress UpdatePackageCatalogAsync(String catalogName); + } + /// 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 d42097f871..ef42266e72 100644 --- a/src/Microsoft.Management.Deployment/Public/ComClsids.h +++ b/src/Microsoft.Management.Deployment/Public/ComClsids.h @@ -14,6 +14,7 @@ #define WINGET_OUTOFPROC_COM_CLSID_ConfigurationStaticFunctions "73D763B7-2937-432F-A97A-D98A4A596126" #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_AddPackageCatalogOptions "DB9D012D-00D7-47EE-8FB1-606E10AC4F51" #else #define WINGET_OUTOFPROC_COM_CLSID_PackageManager "74CB3139-B7C5-4B9E-9388-E6616DEA288C" #define WINGET_OUTOFPROC_COM_CLSID_FindPackagesOptions "1BD8FF3A-EC50-4F69-AEEE-DF4C9D3BAA96" @@ -24,6 +25,7 @@ #define WINGET_OUTOFPROC_COM_CLSID_ConfigurationStaticFunctions "C9ED7917-66AB-4E31-A92A-F65F18EF7933" #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_AddPackageCatalogOptions "D58C7E4C-70E6-476C-A5D4-80341ED80252" #endif // Clsids only used in in-proc invocation @@ -41,6 +43,7 @@ namespace winrt::Microsoft::Management::Deployment const CLSID WINGET_INPROC_COM_CLSID_PackageManagerSettings = { 0x80CF9D63, 0x5505, 0x4342, 0xB9, 0xB4, 0xBB, 0x87, 0x89, 0x5C, 0xA8, 0xBB }; // 80CF9D63-5505-4342-B9B4-BB87895CA8BB 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_AddPackageCatalogOptions = { 0x24e6f1fa, 0xe4c3, 0x4acd, 0x96, 0x5d, 0xdf, 0x21, 0x3f, 0xd5, 0x8f, 0x15 }; // {24E6F1FA-E4C3-4ACD-965D-DF213FD58F15} CLSID GetRedirectedClsidFromInProcClsid(REFCLSID clsid); -} \ No newline at end of file +} 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/ResetPackageCatalogResult.cpp b/src/Microsoft.Management.Deployment/ResetPackageCatalogResult.cpp new file mode 100644 index 0000000000..d5b4bc99cd --- /dev/null +++ b/src/Microsoft.Management.Deployment/ResetPackageCatalogResult.cpp @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "ResetPackageCatalogResult.h" +#include "ResetPackageCatalogResult.g.cpp" +#include + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + void ResetPackageCatalogResult::Initialize( + winrt::Microsoft::Management::Deployment::ResetPackageCatalogStatus status, + winrt::hresult extendedErrorCode) + { + m_status = status; + m_extendedErrorCode = extendedErrorCode; + } + winrt::Microsoft::Management::Deployment::ResetPackageCatalogStatus ResetPackageCatalogResult::Status() + { + return m_status; + } + winrt::hresult ResetPackageCatalogResult::ExtendedErrorCode() + { + return m_extendedErrorCode; + } +} diff --git a/src/Microsoft.Management.Deployment/ResetPackageCatalogResult.h b/src/Microsoft.Management.Deployment/ResetPackageCatalogResult.h new file mode 100644 index 0000000000..07f11c2542 --- /dev/null +++ b/src/Microsoft.Management.Deployment/ResetPackageCatalogResult.h @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once +#include "ResetPackageCatalogResult.g.h" + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + struct ResetPackageCatalogResult : ResetPackageCatalogResultT + { + ResetPackageCatalogResult() = default; + +#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) + void Initialize( + winrt::Microsoft::Management::Deployment::ResetPackageCatalogStatus status, + winrt::hresult extendedErrorCode); +#endif + + winrt::Microsoft::Management::Deployment::ResetPackageCatalogStatus Status(); + winrt::hresult ExtendedErrorCode(); + +#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) + private: + winrt::Microsoft::Management::Deployment::ResetPackageCatalogStatus m_status = winrt::Microsoft::Management::Deployment::ResetPackageCatalogStatus::Ok; + winrt::hresult m_extendedErrorCode = S_OK; +#endif + }; +} diff --git a/src/Microsoft.Management.Deployment/UpdatePackageCatalogResult.cpp b/src/Microsoft.Management.Deployment/UpdatePackageCatalogResult.cpp new file mode 100644 index 0000000000..dbeb45d7af --- /dev/null +++ b/src/Microsoft.Management.Deployment/UpdatePackageCatalogResult.cpp @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "UpdatePackageCatalogResult.h" +#include "UpdatePackageCatalogResult.g.cpp" +#include + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + void UpdatePackageCatalogResult::Initialize( + winrt::Microsoft::Management::Deployment::UpdatePackageCatalogStatus status, + winrt::hresult extendedErrorCode) + { + m_status = status; + m_extendedErrorCode = extendedErrorCode; + } + + winrt::Microsoft::Management::Deployment::UpdatePackageCatalogStatus UpdatePackageCatalogResult::Status() + { + return m_status; + } + + winrt::hresult UpdatePackageCatalogResult::ExtendedErrorCode() + { + return m_extendedErrorCode; + } +} diff --git a/src/Microsoft.Management.Deployment/UpdatePackageCatalogResult.h b/src/Microsoft.Management.Deployment/UpdatePackageCatalogResult.h new file mode 100644 index 0000000000..956e0725dd --- /dev/null +++ b/src/Microsoft.Management.Deployment/UpdatePackageCatalogResult.h @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once +#include "UpdatePackageCatalogResult.g.h" + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + struct UpdatePackageCatalogResult : UpdatePackageCatalogResultT + { + UpdatePackageCatalogResult() = default; + +#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) + void Initialize( + winrt::Microsoft::Management::Deployment::UpdatePackageCatalogStatus status, + winrt::hresult extendedErrorCode); +#endif + + winrt::Microsoft::Management::Deployment::UpdatePackageCatalogStatus Status(); + winrt::hresult ExtendedErrorCode(); + +#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) + private: + winrt::Microsoft::Management::Deployment::UpdatePackageCatalogStatus m_status = winrt::Microsoft::Management::Deployment::UpdatePackageCatalogStatus::Ok; + winrt::hresult m_extendedErrorCode = S_OK; +#endif + }; +} From 2ba2e77867cbfb9ca9ed1e8e6753f66b467571b9 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Sun, 15 Sep 2024 22:38:52 -0700 Subject: [PATCH 02/38] Add new vector interfaces for package catalog operations Introduced new interfaces in the `Microsoft.Management.Deployment` namespace within the `PackageManager.idl` file. Added interfaces for handling collections of `AddPackageCatalogOptions`, `AddPackageCatalogResult`, `RemovePackageCatalogResult`, `ResetPackageCatalogResult`, and `UpdatePackageCatalogResult`. --- src/Microsoft.Management.Deployment/PackageManager.idl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl index 565c11be15..6230949bc5 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.idl +++ b/src/Microsoft.Management.Deployment/PackageManager.idl @@ -1565,5 +1565,15 @@ namespace Microsoft.Management.Deployment interface Windows.Foundation.Collections.IVectorView; interface Windows.Foundation.Collections.IVector; interface Windows.Foundation.Collections.IVectorView; + interface Windows.Foundation.Collections.IVector; + interface Windows.Foundation.Collections.IVectorView; + interface Windows.Foundation.Collections.IVector; + interface Windows.Foundation.Collections.IVectorView; + interface Windows.Foundation.Collections.IVector; + interface Windows.Foundation.Collections.IVectorView; + interface Windows.Foundation.Collections.IVector; + interface Windows.Foundation.Collections.IVectorView; + interface Windows.Foundation.Collections.IVector; + interface Windows.Foundation.Collections.IVectorView; } } From 084e9a7128aa9cb6233a8741cc13fd5d7716a270 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Sun, 15 Sep 2024 22:45:05 -0700 Subject: [PATCH 03/38] Add registration for AddPackageCatalogOptions COM class - Update `Package.appxmanifest` with a new entry. - Add a new entry in `Microsoft.Management.Deployment.InProc.dll.manifest`. - Define new `constexpr CLSID` values for `AddPackageCatalogOptions` in `Factory.cpp`. - Update `s_nameCLSIDPairs` array to include `AddPackageCatalogOptions`. --- src/AppInstallerCLIPackage/Package.appxmanifest | 2 ++ .../Microsoft.Management.Deployment.InProc.dll.manifest | 4 ++++ src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp | 5 ++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/AppInstallerCLIPackage/Package.appxmanifest b/src/AppInstallerCLIPackage/Package.appxmanifest index 18d9ca333e..53b3974ce2 100644 --- a/src/AppInstallerCLIPackage/Package.appxmanifest +++ b/src/AppInstallerCLIPackage/Package.appxmanifest @@ -78,6 +78,8 @@ + + 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 55778515a8..c7e22987a8 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 @@ -43,6 +43,10 @@ clsid="{80CF9D63-5505-4342-B9B4-BB87895CA8BB}" threadingModel="Both" description="PackageManagerSettings"/> + diff --git a/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp b/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp index a7d8c15c07..23ffeea773 100644 --- a/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp +++ b/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp @@ -21,6 +21,7 @@ namespace Microsoft::Management::Deployment::OutOfProc constexpr CLSID CLSID_CreateCompositePackageCatalogOptions = { 0x526534B8, 0x7E46, 0x47C8, { 0x84, 0x16, 0xB1, 0x68, 0x5C, 0x32, 0x7D, 0x37 } }; //526534B8-7E46-47C8-8416-B1685C327D37 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_AddPackageCatalogOptions = { 0xDB9D012D, 0x00D7, 0x47EE, { 0x8F, 0xB1, 0x60, 0x6E, 0x10, 0xAC, 0x4F, 0x51 } }; //DB9D012D-00D7-47EE-8FB1-606E10AC4F51 #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 @@ -30,6 +31,7 @@ namespace Microsoft::Management::Deployment::OutOfProc constexpr CLSID CLSID_CreateCompositePackageCatalogOptions = { 0xEE160901, 0xB317, 0x4EA7, { 0x9C, 0xC6, 0x53, 0x55, 0xC6, 0xD7, 0xD8, 0xA7 } }; //EE160901-B317-4EA7-9CC6-5355C6D7D8A7 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_AddPackageCatalogOptions = { 0xD58C7E4C, 0x70E6, 0x476C, { 0xA5, 0xD4, 0x80, 0x34, 0x1E, 0xD8, 0x02, 0x52 } }; //D58C7E4C-70E6-476C-A5D4-80341ED80252 #endif struct NameCLSIDPair @@ -38,7 +40,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 }, @@ -48,6 +50,7 @@ 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.AddPackageCatalogOptions"sv, CLSID_AddPackageCatalogOptions } }; bool IsCLSIDPresent(const GUID& clsid) From 8dbdbb8f7f1909d5057fd4261f5550edb5a70d19 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Sun, 15 Sep 2024 22:59:15 -0700 Subject: [PATCH 04/38] Add C# WinRT Projection for AddPackageCatalogOptions class - Add entry to type dictionary in ClassesDefinition.cs. - Introduce CreateAddPackageCatalogOptions method in WinGetProjectionFactory.cs. --- .../ClassesDefinition.cs | 16 ++++++++++++++-- .../WinGetProjectionFactory.cs | 6 ++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.Management.Deployment.Projection/ClassesDefinition.cs b/src/Microsoft.Management.Deployment.Projection/ClassesDefinition.cs index 49012a2e1e..d9d08c2540 100644 --- a/src/Microsoft.Management.Deployment.Projection/ClassesDefinition.cs +++ b/src/Microsoft.Management.Deployment.Projection/ClassesDefinition.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. namespace Microsoft.Management.Deployment.Projection @@ -114,7 +114,19 @@ internal static class ClassesDefinition { [ClsidContext.InProc] = new Guid("80CF9D63-5505-4342-B9B4-BB87895CA8BB"), } - } + }, + + [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"), + } + }, }; /// diff --git a/src/Microsoft.Management.Deployment.Projection/WinGetProjectionFactory.cs b/src/Microsoft.Management.Deployment.Projection/WinGetProjectionFactory.cs index 4e457fed2e..692f934508 100644 --- a/src/Microsoft.Management.Deployment.Projection/WinGetProjectionFactory.cs +++ b/src/Microsoft.Management.Deployment.Projection/WinGetProjectionFactory.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. namespace Microsoft.Management.Deployment.Projection @@ -33,6 +33,8 @@ public WinGetProjectionFactory(IInstanceInitializer instanceInitializer) public AuthenticationArguments CreateAuthenticationArguments() => InstanceInitializer.CreateInstance(); - public PackageManagerSettings CreatePackageManagerSettings() => InstanceInitializer.CreateInstance(); + public PackageManagerSettings CreatePackageManagerSettings() => InstanceInitializer.CreateInstance(); + + public AddPackageCatalogOptions CreateAddPackageCatalogOptions() => InstanceInitializer.CreateInstance(); } } From fb402a1474d2bd4e4ad20dfe9c8515660cd1a68a Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Mon, 16 Sep 2024 22:55:25 -0700 Subject: [PATCH 05/38] [PR Feedback:] Refactor AddPackageCatalogOptions and update PackageManager.idl - Renamed `CatalogName` to `Name` and `m_catalogName` to `m_name` in `AddPackageCatalogOptions`. - Removed `Arguments` property and its methods. - Added new boolean property `Explicit` with getter and setter. Updated `PackageManager.idl` to reflect these changes: - Renamed `CatalogName` to `Name` with updated comments. - Removed `Arguments` property. - Added `Explicit` property with explanatory comments. - Updated `RemovePackageCatalogAsync` description to use "catalog". - Removed several `IVector` and `IVectorView` interfaces related to package catalog options and results. --- .../AddPackageCatalogOptions.cpp | 24 ++++++------- .../AddPackageCatalogOptions.h | 16 ++++----- .../PackageManager.idl | 35 ++++++++++--------- 3 files changed, 38 insertions(+), 37 deletions(-) diff --git a/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.cpp b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.cpp index a05e2292e3..c8551105d1 100644 --- a/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.cpp +++ b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.cpp @@ -14,13 +14,13 @@ namespace winrt::Microsoft::Management::Deployment::implementation { - hstring AddPackageCatalogOptions::CatalogName() + hstring AddPackageCatalogOptions::Name() { - return hstring(m_catalogName); + return hstring(m_name); } - void AddPackageCatalogOptions::CatalogName(hstring const& value) + void AddPackageCatalogOptions::Name(hstring const& value) { - m_catalogName = value; + m_name = value; } hstring AddPackageCatalogOptions::SourceUri() { @@ -38,14 +38,6 @@ namespace winrt::Microsoft::Management::Deployment::implementation { m_type = value; } - hstring AddPackageCatalogOptions::Arguments() - { - return hstring(m_arguments); - } - void AddPackageCatalogOptions::Arguments(hstring const& value) - { - m_arguments = value; - } winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel AddPackageCatalogOptions::TrustLevel() { return m_trustLevel; @@ -62,6 +54,14 @@ namespace winrt::Microsoft::Management::Deployment::implementation { 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 index cdab8a64fd..91ec268cad 100644 --- a/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h +++ b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h @@ -7,12 +7,12 @@ namespace winrt::Microsoft::Management::Deployment::implementation { [uuid(WINGET_OUTOFPROC_COM_CLSID_AddPackageCatalogOptions)] - struct AddPackageCatalogOptions : AddPackageCatalogOptionsT + struct AddPackageCatalogOptions : AddPackageCatalogOptionsT { AddPackageCatalogOptions() = default; - hstring CatalogName(); - void CatalogName(hstring const& value); + hstring Name(); + void Name(hstring const& value); hstring SourceUri(); void SourceUri(hstring const& value); @@ -20,23 +20,23 @@ namespace winrt::Microsoft::Management::Deployment::implementation hstring Type(); void Type(hstring const& value); - hstring Arguments(); - void Arguments(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_catalogName = L""; + std::wstring m_name = L""; std::wstring m_sourceUri = L""; std::wstring m_type = L""; - std::wstring m_arguments = L""; winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel m_trustLevel = winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel::None; std::wstring m_customHeader = L""; + bool m_explicit = false; #endif }; } diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl index 6230949bc5..7aa32456cd 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.idl +++ b/src/Microsoft.Management.Deployment/PackageManager.idl @@ -1220,18 +1220,29 @@ namespace Microsoft.Management.Deployment { AddPackageCatalogOptions(); - /// The name of the catalog to add. - String CatalogName; - /// The source URI of the catalog to add. + /// 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; - /// Type of the catalog to add. + + /// ALLOWED VALUES: "Microsoft.Rest", "Microsoft.PreIndexed.Package" + /// SAMPLE VALUES: For OpenWindowsCatalog "Microsoft.PreIndexed.Package". + /// For contoso sample on msdn "Microsoft.PreIndexed.Package" String Type; - /// Additional arguments to pass to the catalog. - String Arguments; + /// 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 @@ -1437,7 +1448,7 @@ namespace Microsoft.Management.Deployment { Windows.Foundation.IAsyncOperationWithProgress AddPackageCatalogAsync(AddPackageCatalogOptions options); - /// Removes a source from the Windows Package Manager source list. + /// Removes a catalog from the Windows Package Catalogs. Windows.Foundation.IAsyncOperationWithProgress RemovePackageCatalogAsync(String catalogName); /// Resets the package catalog to the default state. @@ -1565,15 +1576,5 @@ namespace Microsoft.Management.Deployment interface Windows.Foundation.Collections.IVectorView; interface Windows.Foundation.Collections.IVector; interface Windows.Foundation.Collections.IVectorView; - interface Windows.Foundation.Collections.IVector; - interface Windows.Foundation.Collections.IVectorView; - interface Windows.Foundation.Collections.IVector; - interface Windows.Foundation.Collections.IVectorView; - interface Windows.Foundation.Collections.IVector; - interface Windows.Foundation.Collections.IVectorView; - interface Windows.Foundation.Collections.IVector; - interface Windows.Foundation.Collections.IVectorView; - interface Windows.Foundation.Collections.IVector; - interface Windows.Foundation.Collections.IVectorView; } } From bb0923b9d06ba72b040d90b1a0b7761f0db63abc Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Mon, 16 Sep 2024 23:10:33 -0700 Subject: [PATCH 06/38] [PR Feedback:] Refactor progress reporting for CatalogPackageAsync methods - Simplified progress reporting for *CatalogPackageAsync operations in PackageManager by using a double type. - Updated method signatures and removed related enums and structures in PackageManager.cpp, PackageManager.h, and PackageManager.idl. --- .../PackageManager.cpp | 16 +-- .../PackageManager.h | 8 +- .../PackageManager.idl | 109 +----------------- 3 files changed, 16 insertions(+), 117 deletions(-) diff --git a/src/Microsoft.Management.Deployment/PackageManager.cpp b/src/Microsoft.Management.Deployment/PackageManager.cpp index 42afbee647..5b83520ea3 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.cpp +++ b/src/Microsoft.Management.Deployment/PackageManager.cpp @@ -1066,32 +1066,32 @@ namespace winrt::Microsoft::Management::Deployment::implementation return GetPackageOperation(true, std::move(queueItem)); } - winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::AddPackageCatalogAsync(winrt::Microsoft::Management::Deployment::AddPackageCatalogOptions options) + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::AddPackageCatalogAsync(winrt::Microsoft::Management::Deployment::AddPackageCatalogOptions options) { // TODO: Implement AddPackageCatalogAsync - return winrt::Windows::Foundation::IAsyncOperationWithProgress(); + return winrt::Windows::Foundation::IAsyncOperationWithProgress(); } - winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::RemovePackageCatalogAsync(hstring const& catalogName) + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::RemovePackageCatalogAsync(hstring const& catalogName) { UNREFERENCED_PARAMETER(catalogName); // TODO: Implement RemovePackageCatalogAsync - return winrt::Windows::Foundation::IAsyncOperationWithProgress(); + return winrt::Windows::Foundation::IAsyncOperationWithProgress(); } - winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::ResetPackageCatalogAsync() + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::ResetPackageCatalogAsync() { // TODO: Implement ResetPackageCatalogAsync - return winrt::Windows::Foundation::IAsyncOperationWithProgress(); + return winrt::Windows::Foundation::IAsyncOperationWithProgress(); } - winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::UpdatePackageCatalogAsync(hstring const& catalogName) + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::UpdatePackageCatalogAsync(hstring const& catalogName) { UNREFERENCED_PARAMETER(catalogName); // TODO: Implement UpdatePackageCatalogAsync - return winrt::Windows::Foundation::IAsyncOperationWithProgress(); + return winrt::Windows::Foundation::IAsyncOperationWithProgress(); } CoCreatableMicrosoftManagementDeploymentClass(PackageManager); diff --git a/src/Microsoft.Management.Deployment/PackageManager.h b/src/Microsoft.Management.Deployment/PackageManager.h index 0202718c96..db03213ca9 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.h +++ b/src/Microsoft.Management.Deployment/PackageManager.h @@ -42,12 +42,12 @@ namespace winrt::Microsoft::Management::Deployment::implementation winrt::Windows::Foundation::IAsyncOperationWithProgress GetDownloadProgress(winrt::Microsoft::Management::Deployment::CatalogPackage package, winrt::Microsoft::Management::Deployment::PackageCatalogInfo catalogInfo); // Contract 11.0 - winrt::Windows::Foundation::IAsyncOperationWithProgress + winrt::Windows::Foundation::IAsyncOperationWithProgress AddPackageCatalogAsync(winrt::Microsoft::Management::Deployment::AddPackageCatalogOptions options); - winrt::Windows::Foundation::IAsyncOperationWithProgress + winrt::Windows::Foundation::IAsyncOperationWithProgress RemovePackageCatalogAsync(hstring const& catalogName); - winrt::Windows::Foundation::IAsyncOperationWithProgress ResetPackageCatalogAsync(); - winrt::Windows::Foundation::IAsyncOperationWithProgress UpdatePackageCatalogAsync(hstring const& catalogName); + winrt::Windows::Foundation::IAsyncOperationWithProgress ResetPackageCatalogAsync(); + winrt::Windows::Foundation::IAsyncOperationWithProgress UpdatePackageCatalogAsync(hstring const& catalogName); }; #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl index 7aa32456cd..92a76a7bab 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.idl +++ b/src/Microsoft.Management.Deployment/PackageManager.idl @@ -1265,31 +1265,6 @@ namespace Microsoft.Management.Deployment HRESULT ExtendedErrorCode { get; }; }; - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - enum AddPackageCatalogProgressState - { - /// The AddCatalog is queued but not yet active. Cancellation of the IAsyncOperationWithProgress in this - /// state will prevent the Catalog addition. - Queued, - - /// The AddPackageCatalog is in progress. Cancellation of the IAsyncOperationWithProgress in this state will not - /// stop AddPackageCatalog operation. - AddingCatalog, - - /// The operation is complete. - Finished, - }; - - /// IMPLEMENTATION NOTE: AddPackageCatalogProgress - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - struct AddPackageCatalogProgress - { - AddPackageCatalogProgressState State; - - /// The progress percentage of the operation. - Double ProgressPercentage; - }; - /// IMPLEMENTATION NOTE: RemovePackageCatalogStatus [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] enum RemovePackageCatalogStatus @@ -1311,32 +1286,6 @@ namespace Microsoft.Management.Deployment HRESULT ExtendedErrorCode { get; }; }; - /// IMPLEMENTATION NOTE: RemovePackageCatalogProgressState - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - enum RemovePackageCatalogProgressState - { - /// The RemovePackageCatalog is queued but not yet active. Cancellation of the IAsyncOperationWithProgress in this - /// state will prevent the PackageCatalog removal. - Queued, - - /// The RemovePackageCatalog is in progress. Cancellation of the IAsyncOperationWithProgress in this state will not - /// stop RemovePackageCatalog operation. - RemovingCatalog, - - /// The operation is complete. - Finished, - }; - - /// IMPLEMENTATION NOTE: RemovePackageCatalogProgress - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - struct RemovePackageCatalogProgress - { - RemovePackageCatalogProgressState State; - - /// The progress percentage of the operation. - Double ProgressPercentage; - }; - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] enum ResetPackageCatalogStatus { @@ -1356,31 +1305,6 @@ namespace Microsoft.Management.Deployment HRESULT ExtendedErrorCode { get; }; }; - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - enum ResetPackageCatalogProgressState - { - /// The ResetPackageCatalog is queued but not yet active. Cancellation of the IAsyncOperationWithProgress in this - /// state will prevent the PackageCatalog reset. - Queued, - - /// The ResetPackageCatalog is in progress. Cancellation of the IAsyncOperationWithProgress in this state will not - /// stop ResetPackageCatalog operation. - ResettingCatalog, - - /// The operation is complete. - Finished, - }; - - /// IMPLEMENTATION NOTE: ResetPackageCatalogProgress - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - struct ResetPackageCatalogProgress - { - ResetPackageCatalogProgressState State; - - /// The progress percentage of the operation. - Double ProgressPercentage; - }; - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] enum UpdatePackageCatalogStatus { @@ -1400,31 +1324,6 @@ namespace Microsoft.Management.Deployment HRESULT ExtendedErrorCode { get; }; }; - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - enum UpdatePackageCatalogProgressState - { - /// The UpdatePackageCatalog is queued but not yet active. Cancellation of the IAsyncOperationWithProgress in this - /// state will prevent the UpdatePackageCatalog reset. - Queued, - - // The UpdatePackageCatalog is in progress. Cancellation of the IAsyncOperationWithProgress in this state will not - /// stop UpdatePackageCatalog operation. - UpdatingCatalog, - - /// The operation is complete. - Finished, - }; - - /// IMPLEMENTATION NOTE: UpdatePackageCatalogProgress - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - struct UpdatePackageCatalogProgress - { - UpdatePackageCatalogProgressState State; - - /// The progress percentage of the operation. - Double ProgressPercentage; - }; - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 1)] runtimeclass PackageManager { @@ -1446,16 +1345,16 @@ namespace Microsoft.Management.Deployment [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] { - Windows.Foundation.IAsyncOperationWithProgress AddPackageCatalogAsync(AddPackageCatalogOptions options); + Windows.Foundation.IAsyncOperationWithProgress AddPackageCatalogAsync(AddPackageCatalogOptions options); /// Removes a catalog from the Windows Package Catalogs. - Windows.Foundation.IAsyncOperationWithProgress RemovePackageCatalogAsync(String catalogName); + Windows.Foundation.IAsyncOperationWithProgress RemovePackageCatalogAsync(String catalogName); /// Resets the package catalog to the default state. - Windows.Foundation.IAsyncOperationWithProgress ResetPackageCatalogAsync(); + Windows.Foundation.IAsyncOperationWithProgress ResetPackageCatalogAsync(); /// Updates the package catalog. - Windows.Foundation.IAsyncOperationWithProgress UpdatePackageCatalogAsync(String catalogName); + Windows.Foundation.IAsyncOperationWithProgress UpdatePackageCatalogAsync(String catalogName); } /// Install the specified package From a8e28b727ce1aebe6ed831862b8402479bd5ca74 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Mon, 16 Sep 2024 23:59:11 -0700 Subject: [PATCH 07/38] [PR Feedback:] Refactor package catalog operations to async methods - Introduce new async methods in `PackageCatalogReference` for removing, resetting, and updating package catalogs. - These methods are defined in `PackageCatalogReference.h` and implemented as placeholders in `PackageCatalogReference.cpp`. - Remove corresponding methods from `PackageManager`, shifting responsibility to `PackageCatalogReference`. Update `PackageManager.idl` to reflect these changes: - Add enums and result classes for new operations. - Include new async methods in `PackageCatalogReference`. - Remove outdated methods from `PackageManager`. --- .../PackageCatalogReference.cpp | 22 +++ .../PackageCatalogReference.h | 7 +- .../PackageManager.cpp | 22 --- .../PackageManager.h | 5 +- .../PackageManager.idl | 138 +++++++++--------- 5 files changed, 99 insertions(+), 95 deletions(-) diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp index e3aa23ca16..88c0df3f54 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp @@ -289,4 +289,26 @@ namespace winrt::Microsoft::Management::Deployment::implementation }); return m_authenticationInfo; } + + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageCatalogReference::RemovePackageCatalogAsync(hstring const& catalogName) + { + UNREFERENCED_PARAMETER(catalogName); + + // TODO: Implement RemovePackageCatalogAsync + return winrt::Windows::Foundation::IAsyncOperationWithProgress(); + } + + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageCatalogReference::ResetPackageCatalogAsync() + { + // TODO: Implement ResetPackageCatalogAsync + return winrt::Windows::Foundation::IAsyncOperationWithProgress(); + } + + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageCatalogReference::UpdatePackageCatalogAsync(hstring const& catalogName) + { + UNREFERENCED_PARAMETER(catalogName); + + // TODO: Implement UpdatePackageCatalogAsync + return winrt::Windows::Foundation::IAsyncOperationWithProgress(); + } } diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.h b/src/Microsoft.Management.Deployment/PackageCatalogReference.h index fbfc68fe24..801feac0d1 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.h +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.h @@ -32,7 +32,12 @@ 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 11.0 + winrt::Windows::Foundation::IAsyncOperationWithProgress + RemovePackageCatalogAsync(hstring const& catalogName); + winrt::Windows::Foundation::IAsyncOperationWithProgress ResetPackageCatalogAsync(); + winrt::Windows::Foundation::IAsyncOperationWithProgress UpdatePackageCatalogAsync(hstring const& catalogName); #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) private: diff --git a/src/Microsoft.Management.Deployment/PackageManager.cpp b/src/Microsoft.Management.Deployment/PackageManager.cpp index 5b83520ea3..6acc13fe2b 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.cpp +++ b/src/Microsoft.Management.Deployment/PackageManager.cpp @@ -1072,27 +1072,5 @@ namespace winrt::Microsoft::Management::Deployment::implementation return winrt::Windows::Foundation::IAsyncOperationWithProgress(); } - winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::RemovePackageCatalogAsync(hstring const& catalogName) - { - UNREFERENCED_PARAMETER(catalogName); - - // TODO: Implement RemovePackageCatalogAsync - return winrt::Windows::Foundation::IAsyncOperationWithProgress(); - } - - winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::ResetPackageCatalogAsync() - { - // TODO: Implement ResetPackageCatalogAsync - return winrt::Windows::Foundation::IAsyncOperationWithProgress(); - } - - winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::UpdatePackageCatalogAsync(hstring const& catalogName) - { - UNREFERENCED_PARAMETER(catalogName); - - // TODO: Implement UpdatePackageCatalogAsync - return winrt::Windows::Foundation::IAsyncOperationWithProgress(); - } - CoCreatableMicrosoftManagementDeploymentClass(PackageManager); } diff --git a/src/Microsoft.Management.Deployment/PackageManager.h b/src/Microsoft.Management.Deployment/PackageManager.h index db03213ca9..bbe2c9f138 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.h +++ b/src/Microsoft.Management.Deployment/PackageManager.h @@ -44,10 +44,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation // Contract 11.0 winrt::Windows::Foundation::IAsyncOperationWithProgress AddPackageCatalogAsync(winrt::Microsoft::Management::Deployment::AddPackageCatalogOptions options); - winrt::Windows::Foundation::IAsyncOperationWithProgress - RemovePackageCatalogAsync(hstring const& catalogName); - winrt::Windows::Foundation::IAsyncOperationWithProgress ResetPackageCatalogAsync(); - winrt::Windows::Foundation::IAsyncOperationWithProgress UpdatePackageCatalogAsync(hstring const& catalogName); + }; #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl index 92a76a7bab..32a86ce4dd 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.idl +++ b/src/Microsoft.Management.Deployment/PackageManager.idl @@ -784,6 +784,64 @@ namespace Microsoft.Management.Deployment PackageCatalog PackageCatalog { get; }; } + /// IMPLEMENTATION NOTE: RemovePackageCatalogStatus + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + enum RemovePackageCatalogStatus + { + Ok, + GroupPolicyError, + CatalogError, + InternalError, + }; + + /// IMPLEMENTATION NOTE: RemovePackageCatalogResult + /// Result of removing a package catalog. + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + runtimeclass RemovePackageCatalogResult + { + RemovePackageCatalogStatus Status { get; }; + + /// Error codes + HRESULT ExtendedErrorCode { get; }; + }; + + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + enum ResetPackageCatalogStatus + { + Ok, + GroupPolicyError, + CatalogError, + InternalError, + }; + + /// IMPLEMENTATION NOTE: ResetPackageCatalogResult + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + runtimeclass ResetPackageCatalogResult + { + ResetPackageCatalogStatus Status { get; }; + + /// Error codes + HRESULT ExtendedErrorCode { get; }; + }; + + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + enum UpdatePackageCatalogStatus + { + Ok, + GroupPolicyError, + CatalogError, + InternalError, + }; + + /// IMPLEMENTATION NOTE: UpdatePackageCatalogResult + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + runtimeclass UpdatePackageCatalogResult + { + UpdatePackageCatalogStatus 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 @@ -838,6 +896,18 @@ namespace Microsoft.Management.Deployment /// This is defined by individual package catalog. AuthenticationInfo AuthenticationInfo { get; }; } + + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + { + /// Removes a catalog from the Windows Package Catalogs. + Windows.Foundation.IAsyncOperationWithProgress RemovePackageCatalogAsync(String catalogName); + + /// Resets the package catalog to the default state. + Windows.Foundation.IAsyncOperationWithProgress ResetPackageCatalogAsync(); + + /// Updates the package catalog. + Windows.Foundation.IAsyncOperationWithProgress UpdatePackageCatalogAsync(String catalogName); + } } /// Catalogs with PackageCatalogOrigin Predefined @@ -1265,65 +1335,6 @@ namespace Microsoft.Management.Deployment HRESULT ExtendedErrorCode { get; }; }; - /// IMPLEMENTATION NOTE: RemovePackageCatalogStatus - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - enum RemovePackageCatalogStatus - { - Ok, - GroupPolicyError, - CatalogError, - InternalError, - }; - - /// IMPLEMENTATION NOTE: RemovePackageCatalogResult - /// Result of removing a package catalog. - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - runtimeclass RemovePackageCatalogResult - { - RemovePackageCatalogStatus Status { get; }; - - /// Error codes - HRESULT ExtendedErrorCode { get; }; - }; - - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - enum ResetPackageCatalogStatus - { - Ok, - GroupPolicyError, - CatalogError, - InternalError, - }; - - /// IMPLEMENTATION NOTE: ResetPackageCatalogResult - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - runtimeclass ResetPackageCatalogResult - { - ResetPackageCatalogStatus Status { get; }; - - /// Error codes - HRESULT ExtendedErrorCode { get; }; - }; - - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - enum UpdatePackageCatalogStatus - { - Ok, - GroupPolicyError, - CatalogError, - InternalError, - }; - - /// IMPLEMENTATION NOTE: UpdatePackageCatalogResult - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - runtimeclass UpdatePackageCatalogResult - { - UpdatePackageCatalogStatus Status { get; }; - - /// Error codes - HRESULT ExtendedErrorCode { get; }; - }; - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 1)] runtimeclass PackageManager { @@ -1346,15 +1357,6 @@ namespace Microsoft.Management.Deployment [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] { Windows.Foundation.IAsyncOperationWithProgress AddPackageCatalogAsync(AddPackageCatalogOptions options); - - /// Removes a catalog from the Windows Package Catalogs. - Windows.Foundation.IAsyncOperationWithProgress RemovePackageCatalogAsync(String catalogName); - - /// Resets the package catalog to the default state. - Windows.Foundation.IAsyncOperationWithProgress ResetPackageCatalogAsync(); - - /// Updates the package catalog. - Windows.Foundation.IAsyncOperationWithProgress UpdatePackageCatalogAsync(String catalogName); } /// Install the specified package From c5ccec23d9de567e1caf0672c4a94e1141050f50 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Mon, 23 Sep 2024 17:28:55 -0700 Subject: [PATCH 08/38] Refactor PackageCatalogReference methods to remove params - Refactored RemovePackageCatalogAsync and UpdatePackageCatalogAsync to exclude the catalogName parameter in PackageCatalogReference.cpp, PackageCatalogReference.h, and PackageManager.idl. - This modification eliminates the necessity of passing a catalog name, as the required context is now inherently loaded from PackageCatalogInfor within PackageCatalogReference. Note: These operations are not designed to support actions on multiple PackageCatalog/Source, such as ResetAll, UpdateAll, or RemoveAll. These mass operations are intended only for human interactions. For such operations, consumers are expected to recreate 'all' with a simple set of calls. --- .../PackageCatalogReference.cpp | 8 ++------ .../PackageCatalogReference.h | 5 ++--- src/Microsoft.Management.Deployment/PackageManager.idl | 4 ++-- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp index 88c0df3f54..39fd1e6595 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp @@ -290,10 +290,8 @@ namespace winrt::Microsoft::Management::Deployment::implementation return m_authenticationInfo; } - winrt::Windows::Foundation::IAsyncOperationWithProgress PackageCatalogReference::RemovePackageCatalogAsync(hstring const& catalogName) + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageCatalogReference::RemovePackageCatalogAsync() { - UNREFERENCED_PARAMETER(catalogName); - // TODO: Implement RemovePackageCatalogAsync return winrt::Windows::Foundation::IAsyncOperationWithProgress(); } @@ -304,10 +302,8 @@ namespace winrt::Microsoft::Management::Deployment::implementation return winrt::Windows::Foundation::IAsyncOperationWithProgress(); } - winrt::Windows::Foundation::IAsyncOperationWithProgress PackageCatalogReference::UpdatePackageCatalogAsync(hstring const& catalogName) + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageCatalogReference::UpdatePackageCatalogAsync() { - UNREFERENCED_PARAMETER(catalogName); - // TODO: Implement UpdatePackageCatalogAsync return winrt::Windows::Foundation::IAsyncOperationWithProgress(); } diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.h b/src/Microsoft.Management.Deployment/PackageCatalogReference.h index 801feac0d1..153e048e30 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.h +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.h @@ -34,10 +34,9 @@ namespace winrt::Microsoft::Management::Deployment::implementation void AuthenticationArguments(winrt::Microsoft::Management::Deployment::AuthenticationArguments const& value); winrt::Microsoft::Management::Deployment::AuthenticationInfo AuthenticationInfo(); // Contract 11.0 - winrt::Windows::Foundation::IAsyncOperationWithProgress - RemovePackageCatalogAsync(hstring const& catalogName); + winrt::Windows::Foundation::IAsyncOperationWithProgress RemovePackageCatalogAsync(); winrt::Windows::Foundation::IAsyncOperationWithProgress ResetPackageCatalogAsync(); - winrt::Windows::Foundation::IAsyncOperationWithProgress UpdatePackageCatalogAsync(hstring const& catalogName); + winrt::Windows::Foundation::IAsyncOperationWithProgress UpdatePackageCatalogAsync(); #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) private: diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl index 32a86ce4dd..8b9804c1b6 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.idl +++ b/src/Microsoft.Management.Deployment/PackageManager.idl @@ -900,13 +900,13 @@ namespace Microsoft.Management.Deployment [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] { /// Removes a catalog from the Windows Package Catalogs. - Windows.Foundation.IAsyncOperationWithProgress RemovePackageCatalogAsync(String catalogName); + Windows.Foundation.IAsyncOperationWithProgress RemovePackageCatalogAsync(); /// Resets the package catalog to the default state. Windows.Foundation.IAsyncOperationWithProgress ResetPackageCatalogAsync(); /// Updates the package catalog. - Windows.Foundation.IAsyncOperationWithProgress UpdatePackageCatalogAsync(String catalogName); + Windows.Foundation.IAsyncOperationWithProgress UpdatePackageCatalogAsync(); } } From 16d41d011b182f32632b6f5a9149de3cc61f0bc5 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Mon, 23 Sep 2024 22:05:17 -0700 Subject: [PATCH 09/38] Remove progress reporting from ResetPackageCatalogAsync - Remove progress reporting from ResetPackageCatalogAsync. The underlying implementation for ResetPackageCatalog does not support progress in Repository::DropSource(..). Therefore, the reset API is now an async operation without progress. - The return type of the `ResetPackageCatalogAsync` method in the `PackageCatalogReference` class has been changed from `winrt::Windows::Foundation::IAsyncOperationWithProgress` to `winrt::Windows::Foundation::IAsyncOperation`. This change removes the progress reporting capability from the asynchronous operation. - Corresponding changes have been made in `PackageCatalogReference.h` and `PackageManager.idl` to reflect the new return type. - This simplifies the method's signature and potentially its implementation. --- .../PackageCatalogReference.cpp | 4 ++-- src/Microsoft.Management.Deployment/PackageCatalogReference.h | 2 +- src/Microsoft.Management.Deployment/PackageManager.idl | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp index 39fd1e6595..e973cd3671 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp @@ -296,10 +296,10 @@ namespace winrt::Microsoft::Management::Deployment::implementation return winrt::Windows::Foundation::IAsyncOperationWithProgress(); } - winrt::Windows::Foundation::IAsyncOperationWithProgress PackageCatalogReference::ResetPackageCatalogAsync() + winrt::Windows::Foundation::IAsyncOperation PackageCatalogReference::ResetPackageCatalogAsync() { // TODO: Implement ResetPackageCatalogAsync - return winrt::Windows::Foundation::IAsyncOperationWithProgress(); + return winrt::Windows::Foundation::IAsyncOperation(); } winrt::Windows::Foundation::IAsyncOperationWithProgress PackageCatalogReference::UpdatePackageCatalogAsync() diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.h b/src/Microsoft.Management.Deployment/PackageCatalogReference.h index 153e048e30..df4e86f8da 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.h +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.h @@ -35,7 +35,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation winrt::Microsoft::Management::Deployment::AuthenticationInfo AuthenticationInfo(); // Contract 11.0 winrt::Windows::Foundation::IAsyncOperationWithProgress RemovePackageCatalogAsync(); - winrt::Windows::Foundation::IAsyncOperationWithProgress ResetPackageCatalogAsync(); + winrt::Windows::Foundation::IAsyncOperation ResetPackageCatalogAsync(); winrt::Windows::Foundation::IAsyncOperationWithProgress UpdatePackageCatalogAsync(); #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl index 8b9804c1b6..b2cc8be9eb 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.idl +++ b/src/Microsoft.Management.Deployment/PackageManager.idl @@ -903,7 +903,7 @@ namespace Microsoft.Management.Deployment Windows.Foundation.IAsyncOperationWithProgress RemovePackageCatalogAsync(); /// Resets the package catalog to the default state. - Windows.Foundation.IAsyncOperationWithProgress ResetPackageCatalogAsync(); + Windows.Foundation.IAsyncOperation ResetPackageCatalogAsync(); /// Updates the package catalog. Windows.Foundation.IAsyncOperationWithProgress UpdatePackageCatalogAsync(); From c2d3a0f72e9499567ffd4d9a2e3d425c791e4916 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Fri, 27 Sep 2024 12:41:37 -0700 Subject: [PATCH 10/38] Eliminate ResetPackageCatalogAsync in favor of options for RemovePackageCatalogAsync. - The reset operation is a subset of the remove operation but does not include cleanup. - The remove operation ensures that everything the PackageCatalog writes to the system is cleaned up, in addition to removing the package catalog entry from the winget package catalog list. Conversely, the reset operation only removes the entry without performing any cleanup. --- .../Microsoft.Management.Deployment.vcxproj | 2 -- ...soft.Management.Deployment.vcxproj.filters | 8 +++++ .../PackageCatalogReference.cpp | 32 +++++++++++++---- .../PackageCatalogReference.h | 3 +- .../PackageManager.idl | 35 +++++++------------ 5 files changed, 46 insertions(+), 34 deletions(-) diff --git a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj index 481a412568..64bc71c080 100644 --- a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj +++ b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj @@ -220,7 +220,6 @@ - @@ -265,7 +264,6 @@ Create - diff --git a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters index fac175dc11..d7f083220d 100644 --- a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters +++ b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters @@ -38,6 +38,10 @@ + + + + @@ -81,6 +85,10 @@ + + + + diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp index e973cd3671..2a6fe38125 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp @@ -290,20 +290,38 @@ namespace winrt::Microsoft::Management::Deployment::implementation return m_authenticationInfo; } - winrt::Windows::Foundation::IAsyncOperationWithProgress PackageCatalogReference::RemovePackageCatalogAsync() + winrt::Windows::Foundation::IAsyncOperationWithProgressPackageCatalogReference::RemovePackageCatalogAsync(RemovePackageCatalogOptions options) { + // TODO: Add PackageQuery capability check + + // TODO: Add Admin check + + if (options == RemovePackageCatalogOptions::Drop) + { + this->m_sourceReference.DropSource(""); + } + else + { + ::AppInstaller::ProgressCallback progress; + this->m_sourceReference.Remove(progress); + } + + // TODO: Associate above progress with the async operation winrt progress + // TODO: Implement RemovePackageCatalogAsync return winrt::Windows::Foundation::IAsyncOperationWithProgress(); } - winrt::Windows::Foundation::IAsyncOperation PackageCatalogReference::ResetPackageCatalogAsync() - { - // TODO: Implement ResetPackageCatalogAsync - return winrt::Windows::Foundation::IAsyncOperation(); - } - winrt::Windows::Foundation::IAsyncOperationWithProgress PackageCatalogReference::UpdatePackageCatalogAsync() { + // TODO: Add PackageQuery capability check + + // TODO: Add Admin check + ::AppInstaller::ProgressCallback progress; + this->m_sourceReference.Update(progress); + + // TODO: Associate above progress with the async operation winrt progress + // TODO: Implement UpdatePackageCatalogAsync return winrt::Windows::Foundation::IAsyncOperationWithProgress(); } diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.h b/src/Microsoft.Management.Deployment/PackageCatalogReference.h index df4e86f8da..ede06f3d82 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.h +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.h @@ -34,8 +34,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation void AuthenticationArguments(winrt::Microsoft::Management::Deployment::AuthenticationArguments const& value); winrt::Microsoft::Management::Deployment::AuthenticationInfo AuthenticationInfo(); // Contract 11.0 - winrt::Windows::Foundation::IAsyncOperationWithProgress RemovePackageCatalogAsync(); - winrt::Windows::Foundation::IAsyncOperation ResetPackageCatalogAsync(); + winrt::Windows::Foundation::IAsyncOperationWithProgress RemovePackageCatalogAsync(RemovePackageCatalogOptions options); winrt::Windows::Foundation::IAsyncOperationWithProgress UpdatePackageCatalogAsync(); #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl index b2cc8be9eb..4a11dfae80 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.idl +++ b/src/Microsoft.Management.Deployment/PackageManager.idl @@ -784,6 +784,16 @@ namespace Microsoft.Management.Deployment PackageCatalog PackageCatalog { get; }; } + /// IMPLEMENTATION NOTE: RemovePackageCatalogOptions + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + enum RemovePackageCatalogOptions + { + /// Removes the package catalog from the Windows Package Catalogs list without performing any cleanup. This is similar to the WinGet source reset operation on a specific Package Catalog. + Drop = 0x1, + /// Removes the package catalog from the Windows Package Catalogs list and clears any data written to the system by the package catalog. + Remove = 0x2, + }; + /// IMPLEMENTATION NOTE: RemovePackageCatalogStatus [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] enum RemovePackageCatalogStatus @@ -805,25 +815,6 @@ namespace Microsoft.Management.Deployment HRESULT ExtendedErrorCode { get; }; }; - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - enum ResetPackageCatalogStatus - { - Ok, - GroupPolicyError, - CatalogError, - InternalError, - }; - - /// IMPLEMENTATION NOTE: ResetPackageCatalogResult - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - runtimeclass ResetPackageCatalogResult - { - ResetPackageCatalogStatus Status { get; }; - - /// Error codes - HRESULT ExtendedErrorCode { get; }; - }; - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] enum UpdatePackageCatalogStatus { @@ -842,6 +833,7 @@ namespace Microsoft.Management.Deployment /// Error codes HRESULT ExtendedErrorCode { get; }; }; + /// A reference to a catalog that callers can try to Connect. [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 1)] runtimeclass PackageCatalogReference @@ -900,10 +892,7 @@ namespace Microsoft.Management.Deployment [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] { /// Removes a catalog from the Windows Package Catalogs. - Windows.Foundation.IAsyncOperationWithProgress RemovePackageCatalogAsync(); - - /// Resets the package catalog to the default state. - Windows.Foundation.IAsyncOperation ResetPackageCatalogAsync(); + Windows.Foundation.IAsyncOperationWithProgress RemovePackageCatalogAsync(RemovePackageCatalogOptions options); /// Updates the package catalog. Windows.Foundation.IAsyncOperationWithProgress UpdatePackageCatalogAsync(); From e2021d7ab39ddc4c25009242713d16b62ce9eaf6 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Wed, 9 Oct 2024 11:02:55 -0700 Subject: [PATCH 11/38] [MergeConflictFix:] Add new NameCLSIDPair for AddPackageCatalogOptions - Increased the size of the s_nameCLSIDPairs array from 9 to 10 elements in Factory.cpp within the Microsoft::Management::Deployment::OutOfProc namespace. - Added a new NameCLSIDPair entry for Microsoft.Management.Deployment.AddPackageCatalogOptions. Updated the last entry for Microsoft.Management.Deployment.RepairOptions to include a trailing comma. --- src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp b/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp index fd92daff50..1a3bd324bf 100644 --- a/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp +++ b/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp @@ -42,7 +42,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 }, @@ -52,7 +52,7 @@ 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 } }; From 6410b49b0c733a6bde99e551b9497921ecb80f74 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Wed, 9 Oct 2024 11:04:58 -0700 Subject: [PATCH 12/38] Remove package catalog handling logic for the changes expected in the upcoming commit - Removed the implementation details for handling the removal and update of package catalogs in the `PackageCatalogReference` class. - Added TODO comments indicating future implementation plans. --- .../PackageCatalogReference.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp index bc2edb6ba4..8f62b34e6c 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp @@ -296,17 +296,6 @@ namespace winrt::Microsoft::Management::Deployment::implementation // TODO: Add Admin check - if (options == RemovePackageCatalogOptions::Drop) - { - this->m_sourceReference.DropSource(""); - } - else - { - ::AppInstaller::ProgressCallback progress; - this->m_sourceReference.Remove(progress); - } - - // TODO: Associate above progress with the async operation winrt progress // TODO: Implement RemovePackageCatalogAsync return winrt::Windows::Foundation::IAsyncOperationWithProgress(); @@ -317,10 +306,6 @@ namespace winrt::Microsoft::Management::Deployment::implementation // TODO: Add PackageQuery capability check // TODO: Add Admin check - ::AppInstaller::ProgressCallback progress; - this->m_sourceReference.Update(progress); - - // TODO: Associate above progress with the async operation winrt progress // TODO: Implement UpdatePackageCatalogAsync return winrt::Windows::Foundation::IAsyncOperationWithProgress(); From c41bb16ec4457e5c9fa3c2ad39a35d5cef50831f Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Mon, 14 Oct 2024 12:05:44 -0700 Subject: [PATCH 13/38] Apply API review feedback - Introduced a new COM class `RemovePackageCatalogOptions` with corresponding CLSIDs and properties. - Updated project files and headers to include the new class. - Added RemovePackageCatalogAsync method to handle the new functionality in `PackageManager`. - Renamed `UpdatePackageCatalog` to `RefreshPackageCatalog` and - Removed the old `UpdatePackageCatalogResult` class and introduced `RefreshPackageCatalogResult`. - Added new properties to `AddPackageCatalogOptions`. --- .../Package.appxmanifest | 2 + .../Factory.cpp | 8 +- .../ClassesDefinition.cs | 14 ++- .../WinGetProjectionFactory.cs | 4 +- .../AddPackageCatalogOptions.cpp | 8 ++ .../AddPackageCatalogOptions.h | 4 + .../ComClsids.cpp | 12 ++- .../Microsoft.Management.Deployment.vcxproj | 6 +- ...soft.Management.Deployment.vcxproj.filters | 9 +- .../PackageCatalogReference.cpp | 19 +--- .../PackageCatalogReference.h | 3 +- .../PackageManager.cpp | 10 ++ .../PackageManager.h | 2 +- .../PackageManager.idl | 95 +++++++++++-------- .../Public/ComClsids.h | 3 + .../RefreshPackageCatalogResult.cpp | 27 ++++++ .../RefreshPackageCatalogResult.h | 27 ++++++ .../RemovePackageCatalogOptions.cpp | 33 +++++++ .../RemovePackageCatalogOptions.h | 36 +++++++ .../UpdatePackageCatalogResult.cpp | 27 ------ .../UpdatePackageCatalogResult.h | 27 ------ src/WindowsPackageManager/main.cpp | 2 + 22 files changed, 257 insertions(+), 121 deletions(-) create mode 100644 src/Microsoft.Management.Deployment/RefreshPackageCatalogResult.cpp create mode 100644 src/Microsoft.Management.Deployment/RefreshPackageCatalogResult.h create mode 100644 src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.cpp create mode 100644 src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.h delete mode 100644 src/Microsoft.Management.Deployment/UpdatePackageCatalogResult.cpp delete mode 100644 src/Microsoft.Management.Deployment/UpdatePackageCatalogResult.h diff --git a/src/AppInstallerCLIPackage/Package.appxmanifest b/src/AppInstallerCLIPackage/Package.appxmanifest index a6a8de9f7e..6ef3f5aa9d 100644 --- a/src/AppInstallerCLIPackage/Package.appxmanifest +++ b/src/AppInstallerCLIPackage/Package.appxmanifest @@ -82,6 +82,8 @@ + + diff --git a/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp b/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp index 1a3bd324bf..58ab03a56c 100644 --- a/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp +++ b/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp @@ -23,6 +23,7 @@ namespace Microsoft::Management::Deployment::OutOfProc 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 @@ -34,6 +35,8 @@ namespace Microsoft::Management::Deployment::OutOfProc 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 @@ -42,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 }, @@ -53,7 +56,8 @@ namespace Microsoft::Management::Deployment::OutOfProc 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.AddPackageCatalogOptions"sv, CLSID_AddPackageCatalogOptions } + 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 b4495ba70e..ed6adfb500 100644 --- a/src/Microsoft.Management.Deployment.Projection/ClassesDefinition.cs +++ b/src/Microsoft.Management.Deployment.Projection/ClassesDefinition.cs @@ -138,7 +138,19 @@ internal static class ClassesDefinition [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 80d016a0f9..5201492b2f 100644 --- a/src/Microsoft.Management.Deployment.Projection/WinGetProjectionFactory.cs +++ b/src/Microsoft.Management.Deployment.Projection/WinGetProjectionFactory.cs @@ -37,6 +37,8 @@ public WinGetProjectionFactory(IInstanceInitializer instanceInitializer) public RepairOptions CreateRepairOptions() => InstanceInitializer.CreateInstance(); - public AddPackageCatalogOptions CreateAddPackageCatalogOptions() => 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 index c8551105d1..f0c981d187 100644 --- a/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.cpp +++ b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.cpp @@ -62,6 +62,14 @@ namespace winrt::Microsoft::Management::Deployment::implementation { m_explicit = value; } + bool AddPackageCatalogOptions::AcceptSourceAgreements() + { + return m_acceptSourceAgreements; + } + void AddPackageCatalogOptions::AcceptSourceAgreements(bool const& value) + { + m_acceptSourceAgreements = value; + } CoCreatableMicrosoftManagementDeploymentClass(AddPackageCatalogOptions); } diff --git a/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h index 91ec268cad..3650eab1a4 100644 --- a/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h +++ b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h @@ -29,6 +29,9 @@ namespace winrt::Microsoft::Management::Deployment::implementation bool Explicit(); void Explicit(bool const& value); + bool AcceptSourceAgreements(); + void AcceptSourceAgreements(bool const& value); + #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) private: std::wstring m_name = L""; @@ -37,6 +40,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel m_trustLevel = winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel::None; std::wstring m_customHeader = L""; bool m_explicit = false; + bool m_acceptSourceAgreements = false; #endif }; } 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/Microsoft.Management.Deployment.vcxproj b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj index d13b5af982..78cb7dc534 100644 --- a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj +++ b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj @@ -219,13 +219,14 @@ + - + @@ -265,6 +266,7 @@ Create + @@ -272,7 +274,7 @@ - + diff --git a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters index 839374b6d8..5443970406 100644 --- a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters +++ b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters @@ -43,7 +43,8 @@ - + + @@ -92,7 +93,8 @@ - + + @@ -107,4 +109,7 @@ {9c3907ed-84d9-4485-9b15-04c50717f0ab} + + + \ No newline at end of file diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp index 8f62b34e6c..465638e94a 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp @@ -290,24 +290,11 @@ namespace winrt::Microsoft::Management::Deployment::implementation return m_authenticationInfo; } - winrt::Windows::Foundation::IAsyncOperationWithProgressPackageCatalogReference::RemovePackageCatalogAsync(RemovePackageCatalogOptions options) + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageCatalogReference::RefreshPackageCatalogAsync() { // TODO: Add PackageQuery capability check - // TODO: Add Admin check - - - // TODO: Implement RemovePackageCatalogAsync - return winrt::Windows::Foundation::IAsyncOperationWithProgress(); - } - - winrt::Windows::Foundation::IAsyncOperationWithProgress PackageCatalogReference::UpdatePackageCatalogAsync() - { - // TODO: Add PackageQuery capability check - - // TODO: Add Admin check - - // TODO: Implement UpdatePackageCatalogAsync - return winrt::Windows::Foundation::IAsyncOperationWithProgress(); + // TODO: Implement RefreshPackageCatalogAsync + return winrt::Windows::Foundation::IAsyncOperationWithProgress(); } } diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.h b/src/Microsoft.Management.Deployment/PackageCatalogReference.h index ede06f3d82..a217720d24 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.h +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.h @@ -34,8 +34,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation void AuthenticationArguments(winrt::Microsoft::Management::Deployment::AuthenticationArguments const& value); winrt::Microsoft::Management::Deployment::AuthenticationInfo AuthenticationInfo(); // Contract 11.0 - winrt::Windows::Foundation::IAsyncOperationWithProgress RemovePackageCatalogAsync(RemovePackageCatalogOptions options); - winrt::Windows::Foundation::IAsyncOperationWithProgress UpdatePackageCatalogAsync(); + 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 acca3f124c..c63b88ddcd 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.cpp +++ b/src/Microsoft.Management.Deployment/PackageManager.cpp @@ -1199,9 +1199,19 @@ namespace winrt::Microsoft::Management::Deployment::implementation winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::AddPackageCatalogAsync(winrt::Microsoft::Management::Deployment::AddPackageCatalogOptions options) { + UNREFERENCED_PARAMETER(options); + // TODO: Implement AddPackageCatalogAsync return winrt::Windows::Foundation::IAsyncOperationWithProgress(); } + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::RemovePackageCatalogAsync(winrt::Microsoft::Management::Deployment::RemovePackageCatalogOptions options) + { + UNREFERENCED_PARAMETER(options); + + // TODO: Implement RemovePackageCatalogAsync + return winrt::Windows::Foundation::IAsyncOperationWithProgress(); + } + CoCreatableMicrosoftManagementDeploymentClass(PackageManager); } diff --git a/src/Microsoft.Management.Deployment/PackageManager.h b/src/Microsoft.Management.Deployment/PackageManager.h index 9802fdca44..20d861610a 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.h +++ b/src/Microsoft.Management.Deployment/PackageManager.h @@ -47,7 +47,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation // Contract 11.0 winrt::Windows::Foundation::IAsyncOperationWithProgress AddPackageCatalogAsync(winrt::Microsoft::Management::Deployment::AddPackageCatalogOptions options); - + winrt::Windows::Foundation::IAsyncOperationWithProgress RemovePackageCatalogAsync(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 fa0dd87e45..3d8895bbd0 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.idl +++ b/src/Microsoft.Management.Deployment/PackageManager.idl @@ -863,39 +863,8 @@ namespace Microsoft.Management.Deployment } } - /// IMPLEMENTATION NOTE: RemovePackageCatalogOptions - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - enum RemovePackageCatalogOptions - { - /// Removes the package catalog from the Windows Package Catalogs list without performing any cleanup. This is similar to the WinGet source reset operation on a specific Package Catalog. - Drop = 0x1, - /// Removes the package catalog from the Windows Package Catalogs list and clears any data written to the system by the package catalog. - Remove = 0x2, - }; - - /// IMPLEMENTATION NOTE: RemovePackageCatalogStatus - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - enum RemovePackageCatalogStatus - { - Ok, - GroupPolicyError, - CatalogError, - InternalError, - }; - - /// IMPLEMENTATION NOTE: RemovePackageCatalogResult - /// Result of removing a package catalog. [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - runtimeclass RemovePackageCatalogResult - { - RemovePackageCatalogStatus Status { get; }; - - /// Error codes - HRESULT ExtendedErrorCode { get; }; - }; - - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - enum UpdatePackageCatalogStatus + enum RefreshPackageCatalogStatus { Ok, GroupPolicyError, @@ -903,11 +872,11 @@ namespace Microsoft.Management.Deployment InternalError, }; - /// IMPLEMENTATION NOTE: UpdatePackageCatalogResult + /// IMPLEMENTATION NOTE: RefreshPackageCatalogResult [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] - runtimeclass UpdatePackageCatalogResult + runtimeclass RefreshPackageCatalogResult { - UpdatePackageCatalogStatus Status { get; }; + RefreshPackageCatalogStatus Status { get; }; /// Error codes HRESULT ExtendedErrorCode { get; }; @@ -970,11 +939,8 @@ namespace Microsoft.Management.Deployment [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] { - /// Removes a catalog from the Windows Package Catalogs. - Windows.Foundation.IAsyncOperationWithProgress RemovePackageCatalogAsync(RemovePackageCatalogOptions options); - /// Updates the package catalog. - Windows.Foundation.IAsyncOperationWithProgress UpdatePackageCatalogAsync(); + Windows.Foundation.IAsyncOperationWithProgress RefreshPackageCatalogAsync(); } } @@ -1439,6 +1405,9 @@ namespace Microsoft.Management.Deployment /// Excludes a source from discovery unless specified. Boolean Explicit; + + /// PacakageCatalog Source agreement. + Boolean AcceptSourceAgreements; }; /// IMPLEMENTATION NOTE: AddPackageCatalogStatus @@ -1449,6 +1418,8 @@ namespace Microsoft.Management.Deployment GroupPolicyError, CatalogError, InternalError, + InvalidOptions, + AccessDenied, }; /// IMPLEMENTATION NOTE: AddPackageCatalogResult @@ -1461,6 +1432,48 @@ namespace Microsoft.Management.Deployment HRESULT ExtendedErrorCode { get; }; }; + /// IMPLEMENTATION NOTE: RemovePackageCatalogOptions + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + 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, 11)] + enum RemovePackageCatalogStatus + { + Ok, + GroupPolicyError, + CatalogError, + InternalError, + AccessDenied, + }; + + /// IMPLEMENTATION NOTE: RemovePackageCatalogResult +/// Result of removing a package catalog. + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + runtimeclass RemovePackageCatalogResult + { + RemovePackageCatalogStatus Status { get; }; + + /// Error codes + HRESULT ExtendedErrorCode { get; }; + }; + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 1)] runtimeclass PackageManager { @@ -1482,7 +1495,11 @@ namespace Microsoft.Management.Deployment [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] { + /// Add a catalog to the Windows Package Catalogs. Windows.Foundation.IAsyncOperationWithProgress AddPackageCatalogAsync(AddPackageCatalogOptions options); + + /// Removes a catalog from the Windows Package Catalogs. + Windows.Foundation.IAsyncOperationWithProgress RemovePackageCatalogAsync(RemovePackageCatalogOptions options); } /// Install the specified package diff --git a/src/Microsoft.Management.Deployment/Public/ComClsids.h b/src/Microsoft.Management.Deployment/Public/ComClsids.h index e3a5fe4ba4..75f14afbd6 100644 --- a/src/Microsoft.Management.Deployment/Public/ComClsids.h +++ b/src/Microsoft.Management.Deployment/Public/ComClsids.h @@ -16,6 +16,7 @@ #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" @@ -28,6 +29,7 @@ #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 @@ -47,6 +49,7 @@ namespace winrt::Microsoft::Management::Deployment 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..cb9c45bf0d --- /dev/null +++ b/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.cpp @@ -0,0 +1,33 @@ +// 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" + +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..08793f0644 --- /dev/null +++ b/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.h @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once +#include "public/ComClsids.h" +#include "RemovePackageCatalogOptions.g.h" +#include "Public/CoCreatableMicrosoftManagementDeploymentClass.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/UpdatePackageCatalogResult.cpp b/src/Microsoft.Management.Deployment/UpdatePackageCatalogResult.cpp deleted file mode 100644 index dbeb45d7af..0000000000 --- a/src/Microsoft.Management.Deployment/UpdatePackageCatalogResult.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -#include "pch.h" -#include "UpdatePackageCatalogResult.h" -#include "UpdatePackageCatalogResult.g.cpp" -#include - -namespace winrt::Microsoft::Management::Deployment::implementation -{ - void UpdatePackageCatalogResult::Initialize( - winrt::Microsoft::Management::Deployment::UpdatePackageCatalogStatus status, - winrt::hresult extendedErrorCode) - { - m_status = status; - m_extendedErrorCode = extendedErrorCode; - } - - winrt::Microsoft::Management::Deployment::UpdatePackageCatalogStatus UpdatePackageCatalogResult::Status() - { - return m_status; - } - - winrt::hresult UpdatePackageCatalogResult::ExtendedErrorCode() - { - return m_extendedErrorCode; - } -} diff --git a/src/Microsoft.Management.Deployment/UpdatePackageCatalogResult.h b/src/Microsoft.Management.Deployment/UpdatePackageCatalogResult.h deleted file mode 100644 index 956e0725dd..0000000000 --- a/src/Microsoft.Management.Deployment/UpdatePackageCatalogResult.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -#pragma once -#include "UpdatePackageCatalogResult.g.h" - -namespace winrt::Microsoft::Management::Deployment::implementation -{ - struct UpdatePackageCatalogResult : UpdatePackageCatalogResultT - { - UpdatePackageCatalogResult() = default; - -#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) - void Initialize( - winrt::Microsoft::Management::Deployment::UpdatePackageCatalogStatus status, - winrt::hresult extendedErrorCode); -#endif - - winrt::Microsoft::Management::Deployment::UpdatePackageCatalogStatus Status(); - winrt::hresult ExtendedErrorCode(); - -#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) - private: - winrt::Microsoft::Management::Deployment::UpdatePackageCatalogStatus m_status = winrt::Microsoft::Management::Deployment::UpdatePackageCatalogStatus::Ok; - winrt::hresult m_extendedErrorCode = S_OK; -#endif - }; -} 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); From ac4ae580b62179206cb41a9fe1518ac3f6c6ae1e Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Mon, 14 Oct 2024 12:12:04 -0700 Subject: [PATCH 14/38] Fix typo in comment for AcceptSourceAgreements Corrected a typo in the comment for `AcceptSourceAgreements` from "PacakageCatalog" to "PackageCatalog". This change improves the readability and accuracy of the code documentation. --- src/Microsoft.Management.Deployment/PackageManager.idl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl index 3d8895bbd0..49bcdbf559 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.idl +++ b/src/Microsoft.Management.Deployment/PackageManager.idl @@ -1406,7 +1406,7 @@ namespace Microsoft.Management.Deployment /// Excludes a source from discovery unless specified. Boolean Explicit; - /// PacakageCatalog Source agreement. + /// PackageCatalog Source agreement. Boolean AcceptSourceAgreements; }; From 0bf0ad465f125ee19a822eea8775161ae414dc02 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Mon, 14 Oct 2024 13:01:42 -0700 Subject: [PATCH 15/38] Reformat RemovePackageCatalogAsync method declaration Reformatted the RemovePackageCatalogAsync method declaration in PackageManager.h for improved readability. --- src/Microsoft.Management.Deployment/PackageManager.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Management.Deployment/PackageManager.h b/src/Microsoft.Management.Deployment/PackageManager.h index 20d861610a..89c69b883b 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.h +++ b/src/Microsoft.Management.Deployment/PackageManager.h @@ -47,7 +47,8 @@ namespace winrt::Microsoft::Management::Deployment::implementation // Contract 11.0 winrt::Windows::Foundation::IAsyncOperationWithProgress AddPackageCatalogAsync(winrt::Microsoft::Management::Deployment::AddPackageCatalogOptions options); - winrt::Windows::Foundation::IAsyncOperationWithProgress RemovePackageCatalogAsync(RemovePackageCatalogOptions options); + winrt::Windows::Foundation::IAsyncOperationWithProgress + RemovePackageCatalogAsync(winrt::Microsoft::Management::Deployment::RemovePackageCatalogOptions options); }; #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) From f1a064a0ca35cabda7b1d80a4bbbfa3aea3abbd7 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Thu, 17 Oct 2024 17:34:22 -0700 Subject: [PATCH 16/38] Add new error codes and update method documentation - Two new error codes, `SourceAgreementsNotAccepted` and `AuthenticationError`, were added to the `AddPackageCatalogResult` - enumeration in the `Microsoft.Management.Deployment` namespace. - The `InvalidOptions` error code was added to the `RemovePackageCatalogResult` enumeration in the same namespace. - The comment for the `RemovePackageCatalogAsync` method was updated to clarify that it unregisters a package catalog and eliminates system artifacts based on the provided options. --- src/Microsoft.Management.Deployment/PackageManager.idl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl index 49bcdbf559..38513ceecf 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.idl +++ b/src/Microsoft.Management.Deployment/PackageManager.idl @@ -1420,6 +1420,8 @@ namespace Microsoft.Management.Deployment InternalError, InvalidOptions, AccessDenied, + SourceAgreementsNotAccepted, + AuthenticationError, }; /// IMPLEMENTATION NOTE: AddPackageCatalogResult @@ -1461,6 +1463,7 @@ namespace Microsoft.Management.Deployment CatalogError, InternalError, AccessDenied, + InvalidOptions, }; /// IMPLEMENTATION NOTE: RemovePackageCatalogResult @@ -1498,7 +1501,7 @@ namespace Microsoft.Management.Deployment /// Add a catalog to the Windows Package Catalogs. Windows.Foundation.IAsyncOperationWithProgress AddPackageCatalogAsync(AddPackageCatalogOptions options); - /// Removes a catalog from the Windows Package Catalogs. + /// Unregisters a Packagecatalog from the Windows Package Catalogs and eliminates the system artifacts based on the provided options. Windows.Foundation.IAsyncOperationWithProgress RemovePackageCatalogAsync(RemovePackageCatalogOptions options); } From e988965903dbfa4fe6580171f158ef215efee714 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Thu, 17 Oct 2024 17:36:18 -0700 Subject: [PATCH 17/38] Add CallbackDispatcherSink class for progress updates - Introduce CallbackDispatcherSink in AppInstaller namespace to manage and dispatch progress updates to registered callbacks. - Implement methods for initializing, updating, and ending progress, as well as adding and firing callbacks. - Ensure thread-safe access with a mutex. - Minor formatting changes included. --- src/AppInstallerCommonCore/Progress.cpp | 39 +++++++++++++++++++ .../Public/AppInstallerProgress.h | 29 +++++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) 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) From 8bff63ec1a609831d10ef492d12210ef91ad1c7c Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Thu, 17 Oct 2024 17:40:10 -0700 Subject: [PATCH 18/38] Add, Remove and Refresh package catalog operations with error handling Introduced new functionalities for handling package catalog operations, including adding, refreshing, and removing package catalogs. These operations now feature detailed exception handling, progress reporting, and validation checks. Key changes include: - Added `WINGET_CATALOG_CATCH_STORE` macro in ExecutionContext.h. - Implemented `RefreshPackageCatalogAsync` in PackageCatalogReference.cpp. - Implemented `AddPackageCatalogAsync` and `RemovePackageCatalogAsync` in PackageManager.cpp. - Added various helper functions for status mapping and result creation. - Adjusted includes and formatting for consistency in RemovePackageCatalogOptions.h. --- src/AppInstallerCLICore/ExecutionContext.h | 7 + .../PackageCatalogReference.cpp | 63 ++++- .../PackageManager.cpp | 254 +++++++++++++++++- .../RemovePackageCatalogOptions.cpp | 2 + .../RemovePackageCatalogOptions.h | 5 +- 5 files changed, 318 insertions(+), 13 deletions(-) diff --git a/src/AppInstallerCLICore/ExecutionContext.h b/src/AppInstallerCLICore/ExecutionContext.h index a5fa557570..f3e9c23100 100644 --- a/src/AppInstallerCLICore/ExecutionContext.h +++ b/src/AppInstallerCLICore/ExecutionContext.h @@ -25,6 +25,13 @@ WINGET_CATCH_STD_EXCEPTION_STORE(exceptionHR, genericHR) \ WINGET_CATCH_ALL_EXCEPTION_STORE(exceptionHR, genericHR) +#define WINGET_CATALOG_CATCH_STORE(exceptionHR, genericHR) \ + WINGET_CATCH_RESULT_EXCEPTION_STORE(exceptionHR) \ + WINGET_CATCH_HRESULT_EXCEPTION_STORE(exceptionHR) \ + WINGET_CATCH_POLICY_EXCEPTION_STORE(exceptionHR) \ + WINGET_CATCH_STD_EXCEPTION_STORE(exceptionHR, genericHR) \ + WINGET_CATCH_ALL_EXCEPTION_STORE(exceptionHR, genericHR) + // Terminates the Context with some logging to indicate the location. // Also returns from the current function. #define AICLI_TERMINATE_CONTEXT_ARGS(_context_,_hr_,_ret_) \ diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp index 465638e94a..33461fca63 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include namespace winrt::Microsoft::Management::Deployment::implementation { @@ -290,11 +292,66 @@ namespace winrt::Microsoft::Management::Deployment::implementation return m_authenticationInfo; } + RefreshPackageCatalogStatus GetCatalogStatus(winrt::hresult terminationStatus) + { + switch (terminationStatus) + { + case S_OK: + return RefreshPackageCatalogStatus::Ok; + case APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY: + return RefreshPackageCatalogStatus::GroupPolicyError; + case APPINSTALLER_CLI_ERROR_SOURCES_INVALID: + case APPINSTALLER_CLI_ERROR_SOURCE_DATA_MISSING: + case APPINSTALLER_CLI_ERROR_SOURCE_NAME_ALREADY_EXISTS: + case APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST: + case APPINSTALLER_CLI_ERROR_SOURCE_ARG_ALREADY_EXISTS: + case APPINSTALLER_CLI_ERROR_SOURCE_NOT_SECURE: + case APPINSTALLER_CLI_ERROR_SOURCE_NOT_REMOTE: + case APPINSTALLER_CLI_ERROR_SOURCE_DATA_INTEGRITY_FAILURE: + case APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED: + return RefreshPackageCatalogStatus::CatalogError; + case APPINSTALLER_CLI_ERROR_INTERNAL_ERROR: + default: + return RefreshPackageCatalogStatus::InternalError; + } + } + + winrt::Microsoft::Management::Deployment::RefreshPackageCatalogResult GetRefreshPackageCatalogResult(winrt::hresult terminationStatus) + { + winrt::Microsoft::Management::Deployment::RefreshPackageCatalogStatus status = GetCatalogStatus(terminationStatus); + auto updateResult = winrt::make_self>(); + updateResult->Initialize(status, terminationStatus); + return *updateResult; + } + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageCatalogReference::RefreshPackageCatalogAsync() { - // TODO: Add PackageQuery capability check + ::AppInstaller::Logging::Telemetry().SetCaller(GetCallerName()); + ::AppInstaller::Logging::Telemetry().LogStartup(true); + + 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); + report_progress(static_cast(current) / static_cast(maximum)); + }); + + ::AppInstaller::ProgressCallback progress(&progressCallback); + + this->m_sourceReference.Update(progress); + } + WINGET_CATALOG_CATCH_STORE(terminationHR, APPINSTALLER_CLI_ERROR_INTERNAL_ERROR); - // TODO: Implement RefreshPackageCatalogAsync - return winrt::Windows::Foundation::IAsyncOperationWithProgress(); + co_return GetRefreshPackageCatalogResult(terminationHR); } } diff --git a/src/Microsoft.Management.Deployment/PackageManager.cpp b/src/Microsoft.Management.Deployment/PackageManager.cpp index c63b88ddcd..0fbf818b49 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.cpp +++ b/src/Microsoft.Management.Deployment/PackageManager.cpp @@ -30,9 +30,12 @@ #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" using namespace std::literals::chrono_literals; using namespace ::AppInstaller::CLI; @@ -843,7 +846,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,20 +1200,257 @@ namespace winrt::Microsoft::Management::Deployment::implementation true /*canCancelQueueItem*/, nullptr /*queueItem*/, package, options, std::move(callerProcessInfoString)); } + winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus GetAddPackageCatalogStatus(winrt::hresult terminationStatus) + { + switch (terminationStatus) + { + case S_OK: + return winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus::Ok; + case APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS: + return winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus::InvalidOptions; + case APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY: + return winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus::GroupPolicyError; + case APPINSTALLER_CLI_ERROR_SOURCES_INVALID: + case APPINSTALLER_CLI_ERROR_SOURCE_DATA_MISSING: + case APPINSTALLER_CLI_ERROR_SOURCE_NAME_ALREADY_EXISTS: + case APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST: + case APPINSTALLER_CLI_ERROR_SOURCE_ARG_ALREADY_EXISTS: + case APPINSTALLER_CLI_ERROR_SOURCE_NOT_SECURE: + case APPINSTALLER_CLI_ERROR_SOURCE_NOT_REMOTE: + case APPINSTALLER_CLI_ERROR_SOURCE_DATA_INTEGRITY_FAILURE: + case APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED: + return winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus::CatalogError; + case APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN: + case E_ACCESSDENIED: + return winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus::AccessDenied; + case APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED: + return winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus::SourceAgreementsNotAccepted; + case APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED: + return winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus::AuthenticationError; + case APPINSTALLER_CLI_ERROR_INTERNAL_ERROR: + default: + return winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus::InternalError; + } + } + + winrt::Microsoft::Management::Deployment::AddPackageCatalogResult GetAddPackageCatalogResult(winrt::hresult terminationStatus) + { + winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus status = GetAddPackageCatalogStatus(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::ISourceFactory::GetForType("")->TypeName(); + } + + 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() }; + + // This will throw if the source details are not initialized properly, acting as a validation check for the source object. + source.GetDetails(); + + std::string customHeader = winrt::to_string(options.CustomHeader()); + if (!customHeader.empty()) + { + source.SetCustomHeader(customHeader); + } + + return source; + } + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::AddPackageCatalogAsync(winrt::Microsoft::Management::Deployment::AddPackageCatalogOptions options) { - UNREFERENCED_PARAMETER(options); + LogStartupIfApplicable(); - // TODO: Implement AddPackageCatalogAsync - return winrt::Windows::Foundation::IAsyncOperationWithProgress(); + // options must be set. + if (!options) + { + co_return GetAddPackageCatalogResult(APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS); + } + + if (options.Name().empty() || options.SourceUri().empty()) + { + co_return GetAddPackageCatalogResult(APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS); + } + + HRESULT terminationHR = S_OK; + try { + + // Check if running as admin + THROW_HR_IF(APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN, !AppInstaller::Runtime::IsRunningAsAdmin()); + + ::AppInstaller::Repository::Source sourceToAdd = CreateSourceFromOptions(options); + + THROW_HR_IF(APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED, sourceToAdd.GetInformation().Authentication.Type == ::AppInstaller::Authentication::AuthenticationType::Unknown); + + if (!sourceToAdd.CheckSourceAgreements()) + { + THROW_HR_IF(APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED, !options.AcceptSourceAgreements()); + sourceToAdd.SaveAcceptedSourceAgreements(); + } + + 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); + report_progress(static_cast(current) / static_cast(maximum)); + }); + + ::AppInstaller::ProgressCallback progress(&progressCallback); + + sourceToAdd.Add(progress); + } + WINGET_CATALOG_CATCH_STORE(terminationHR, APPINSTALLER_CLI_ERROR_INTERNAL_ERROR); + + co_return GetAddPackageCatalogResult(terminationHR); } + winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus GetRemoveCatalogStatus(winrt::hresult terminationStatus) + { + switch (terminationStatus) + { + case S_OK: + return winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus::Ok; + case APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS: + return winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus::InvalidOptions; + case APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY: + return winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus::GroupPolicyError; + case APPINSTALLER_CLI_ERROR_SOURCES_INVALID: + case APPINSTALLER_CLI_ERROR_SOURCE_DATA_MISSING: + case APPINSTALLER_CLI_ERROR_SOURCE_NAME_ALREADY_EXISTS: + case APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST: + case APPINSTALLER_CLI_ERROR_SOURCE_ARG_ALREADY_EXISTS: + case APPINSTALLER_CLI_ERROR_SOURCE_NOT_SECURE: + case APPINSTALLER_CLI_ERROR_SOURCE_NOT_REMOTE: + case APPINSTALLER_CLI_ERROR_SOURCE_DATA_INTEGRITY_FAILURE: + case APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED: + return winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus::CatalogError; + case APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN: + case E_ACCESSDENIED: + return winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus::AccessDenied; + case APPINSTALLER_CLI_ERROR_INTERNAL_ERROR: + default: + return winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus::InternalError; + } + } + + winrt::Microsoft::Management::Deployment::RemovePackageCatalogResult GetRemovePackageCatalogResult(winrt::hresult terminationStatus) + { + winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus status = GetRemoveCatalogStatus(terminationStatus); + auto removeResult = winrt::make_self>(); + removeResult->Initialize(status, terminationStatus); + return *removeResult; + } + + #include + 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::IAsyncOperationWithProgress PackageManager::RemovePackageCatalogAsync(winrt::Microsoft::Management::Deployment::RemovePackageCatalogOptions options) { - UNREFERENCED_PARAMETER(options); + LogStartupIfApplicable(); + + // options must be set. + if (!options) + { + co_return GetRemovePackageCatalogResult(APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS); + } + + if (options.Name().empty()) + { + co_return GetRemovePackageCatalogResult(APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS); + } + + HRESULT terminationHR = S_OK; + try { + // Check if running as admin + THROW_HR_IF(APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN, !AppInstaller::Runtime::IsRunningAsAdmin()); + + 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); + report_progress(static_cast(current) / static_cast(maximum)); + }); + + ::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); + } + } + WINGET_CATALOG_CATCH_STORE(terminationHR, APPINSTALLER_CLI_ERROR_INTERNAL_ERROR); - // TODO: Implement RemovePackageCatalogAsync - return winrt::Windows::Foundation::IAsyncOperationWithProgress(); + co_return GetRemovePackageCatalogResult(terminationHR); } CoCreatableMicrosoftManagementDeploymentClass(PackageManager); diff --git a/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.cpp b/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.cpp index cb9c45bf0d..e66d3dcb0f 100644 --- a/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.cpp +++ b/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.cpp @@ -9,6 +9,8 @@ #include "RemovePackageCatalogOptions.h" #pragma warning( pop ) #include "RemovePackageCatalogOptions.g.cpp" +#include "Converters.h" +#include "Helpers.h" namespace winrt::Microsoft::Management::Deployment::implementation { diff --git a/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.h b/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.h index 08793f0644..ba312a70fa 100644 --- a/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.h +++ b/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.h @@ -1,14 +1,13 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. #pragma once -#include "public/ComClsids.h" #include "RemovePackageCatalogOptions.g.h" -#include "Public/CoCreatableMicrosoftManagementDeploymentClass.h" +#include "public/ComClsids.h" namespace winrt::Microsoft::Management::Deployment::implementation { [uuid(WINGET_OUTOFPROC_COM_CLSID_RemovePackageCatalogOptions)] - struct RemovePackageCatalogOptions : RemovePackageCatalogOptionsT + struct RemovePackageCatalogOptions : RemovePackageCatalogOptionsT { RemovePackageCatalogOptions() = default; From 9f3fad305e7ce960437d46d00c167ebc348d5469 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Thu, 17 Oct 2024 17:43:29 -0700 Subject: [PATCH 19/38] Add PackageCatalogInterop class for E2E PackageCatalog test operations - The PackageCatalogInterop class handles package catalog operations for end-to-end tests, including adding, removing, and validating package catalogs. - It addresses edge cases like invalid options, duplicate names, and unaccepted source agreements. --- .../Interop/PackageCatalogInterop.cs | 322 ++++++++++++++++++ 1 file changed, 322 insertions(+) create mode 100644 src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs diff --git a/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs b/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs new file mode 100644 index 0000000000..7a6121208f --- /dev/null +++ b/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs @@ -0,0 +1,322 @@ +// ----------------------------------------------------------------------------- +// +// 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; + options.AcceptSourceAgreements = true; + + 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. + /// + /// representing the asynchronous unit test. + [Test] + public async Task AddPackageCatalogWithInvalidOptions() + { + // Add package catalog with null options. + await this.AddAndValidatePackageCatalogAsync(null, AddPackageCatalogStatus.InvalidOptions, Constants.ErrorCode.ERROR_INVALID_CL_ARGUMENTS); + + // Add package catalog with empty options. + await this.AddAndValidatePackageCatalogAsync(this.TestFactory.CreateAddPackageCatalogOptions(), AddPackageCatalogStatus.InvalidOptions, Constants.ErrorCode.ERROR_INVALID_CL_ARGUMENTS); + } + + /// + /// 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; + options.AcceptSourceAgreements = true; + + await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.Ok); + + // Add the same package catalog again. + await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.CatalogError, 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; + options.AcceptSourceAgreements = true; + + await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.Ok); + + // Add the same package catalog again. + options.Name = "TestSource2"; + await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.CatalogError, 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; + options.AcceptSourceAgreements = true; + + await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.InternalError); + } + + /// + /// Add package catalog with source agreement not accepted. + /// + /// representing the asynchronous unit test. + [Test] + public async Task AddPackageCatalogWithSourceAgreementNotAccepted() + { + AddPackageCatalogOptions options = this.TestFactory.CreateAddPackageCatalogOptions(); + options.SourceUri = Constants.DefaultMSStoreSourceUrl; + options.Name = Constants.DefaultMSStoreSourceName; + options.Type = Constants.DefaultMSStoreSourceType; + options.TrustLevel = PackageCatalogTrustLevel.Trusted; + + await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.SourceAgreementsNotAccepted, Constants.ErrorCode.ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED); + } + + /// + /// 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; + options.AcceptSourceAgreements = true; + + 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; + options.AcceptSourceAgreements = true; + + 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. + /// + /// representing the asynchronous unit test. + [Test] + public async Task RemovePackageCatalogWithInvalidOptions() + { + // Remove package catalog with null options. + await this.RemoveAndValidatePackageCatalogAsync(null, RemovePackageCatalogStatus.InvalidOptions, Constants.ErrorCode.ERROR_INVALID_CL_ARGUMENTS); + + // Remove package catalog with empty options. + await this.RemoveAndValidatePackageCatalogAsync(this.TestFactory.CreateRemovePackageCatalogOptions(), RemovePackageCatalogStatus.InvalidOptions, Constants.ErrorCode.ERROR_INVALID_CL_ARGUMENTS); + } + + /// + /// Remove non existing package catalog. + /// + /// representing the asynchronous unit test. + [Test] + public async Task RemoveNonExistingPackageCatalog() + { + RemovePackageCatalogOptions removePackageCatalogOptions = this.TestFactory.CreateRemovePackageCatalogOptions(); + removePackageCatalogOptions.Name = Constants.TestSourceName; + + await this.RemoveAndValidatePackageCatalogAsync(removePackageCatalogOptions, RemovePackageCatalogStatus.CatalogError, 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); + } + } +} From 7714865edf4eac30a5839e927bb1d7f85ac606d1 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Thu, 17 Oct 2024 22:17:41 -0700 Subject: [PATCH 20/38] Refactor status handling for Add, Remove and Refresh with a Template method - Refactored status handling by introducing a template function `GetPackageCatalogOperationStatus` in `Converters.h`, replacing individual status conversion functions in `PackageCatalogReference.cpp` and `PackageManager.cpp`. - Simplified progress reporting by modifying callbacks to report only the current progress value. - Moved new functions `CheckForDuplicateSource`, `CreateSourceFromOptions`, and `GetMatchingSource` in `PackageManager.cpp` close all the private methods. - Included `` header to support `std::optional`. - Cleaned up redundant code and improved comments for better clarity. --- .../Converters.h | 57 +++++ .../PackageCatalogReference.cpp | 29 +-- .../PackageManager.cpp | 240 +++++++----------- 3 files changed, 150 insertions(+), 176 deletions(-) diff --git a/src/Microsoft.Management.Deployment/Converters.h b/src/Microsoft.Management.Deployment/Converters.h index fa0993e3ae..6f8afef906 100644 --- a/src/Microsoft.Management.Deployment/Converters.h +++ b/src/Microsoft.Management.Deployment/Converters.h @@ -141,4 +141,61 @@ namespace winrt::Microsoft::Management::Deployment::implementation return resultStatus; } + + template + TStatus GetPackageCatalogOperationStatus(winrt::hresult hresult) + { + // Applicable only for AddPackageCatalogStatus + if constexpr (std::is_same_v) + { + switch (hresult) + { + case APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED: + return TStatus::SourceAgreementsNotAccepted; + case APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED: + return TStatus::AuthenticationError; + default: + break; + } + } + + // Applicable only for AddPackageCatalogStatus and RemovePackageCatalogStatus + if constexpr (std::is_same_v + || std::is_same_v) + { + switch (hresult) + { + case APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS: + case E_INVALIDARG: + return TStatus::InvalidOptions; + case APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN: + case E_ACCESSDENIED: + return TStatus::AccessDenied; + default: + break; + } + } + + // Handle the common status codes across add, remove and refresh operations. + switch (hresult) + { + case S_OK: + return TStatus::Ok; + case APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY: + return TStatus::GroupPolicyError; + case APPINSTALLER_CLI_ERROR_SOURCES_INVALID: + case APPINSTALLER_CLI_ERROR_SOURCE_DATA_MISSING: + case APPINSTALLER_CLI_ERROR_SOURCE_NAME_ALREADY_EXISTS: + case APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST: + case APPINSTALLER_CLI_ERROR_SOURCE_ARG_ALREADY_EXISTS: + case APPINSTALLER_CLI_ERROR_SOURCE_NOT_SECURE: + case APPINSTALLER_CLI_ERROR_SOURCE_NOT_REMOTE: + case APPINSTALLER_CLI_ERROR_SOURCE_DATA_INTEGRITY_FAILURE: + case APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED: + return TStatus::CatalogError; + case APPINSTALLER_CLI_ERROR_INTERNAL_ERROR: + default: + return TStatus::InternalError; + } + } } diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp index 33461fca63..200d5c171d 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp @@ -292,33 +292,9 @@ namespace winrt::Microsoft::Management::Deployment::implementation return m_authenticationInfo; } - RefreshPackageCatalogStatus GetCatalogStatus(winrt::hresult terminationStatus) - { - switch (terminationStatus) - { - case S_OK: - return RefreshPackageCatalogStatus::Ok; - case APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY: - return RefreshPackageCatalogStatus::GroupPolicyError; - case APPINSTALLER_CLI_ERROR_SOURCES_INVALID: - case APPINSTALLER_CLI_ERROR_SOURCE_DATA_MISSING: - case APPINSTALLER_CLI_ERROR_SOURCE_NAME_ALREADY_EXISTS: - case APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST: - case APPINSTALLER_CLI_ERROR_SOURCE_ARG_ALREADY_EXISTS: - case APPINSTALLER_CLI_ERROR_SOURCE_NOT_SECURE: - case APPINSTALLER_CLI_ERROR_SOURCE_NOT_REMOTE: - case APPINSTALLER_CLI_ERROR_SOURCE_DATA_INTEGRITY_FAILURE: - case APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED: - return RefreshPackageCatalogStatus::CatalogError; - case APPINSTALLER_CLI_ERROR_INTERNAL_ERROR: - default: - return RefreshPackageCatalogStatus::InternalError; - } - } - winrt::Microsoft::Management::Deployment::RefreshPackageCatalogResult GetRefreshPackageCatalogResult(winrt::hresult terminationStatus) { - winrt::Microsoft::Management::Deployment::RefreshPackageCatalogStatus status = GetCatalogStatus(terminationStatus); + winrt::Microsoft::Management::Deployment::RefreshPackageCatalogStatus status = GetPackageCatalogOperationStatus(terminationStatus); auto updateResult = winrt::make_self>(); updateResult->Initialize(status, terminationStatus); return *updateResult; @@ -343,7 +319,8 @@ namespace winrt::Microsoft::Management::Deployment::implementation progressCallback.AddCallback([&report_progress](uint64_t current, uint64_t maximum, AppInstaller::ProgressType type) { UNREFERENCED_PARAMETER(type); - report_progress(static_cast(current) / static_cast(maximum)); + UNREFERENCED_PARAMETER(maximum); + report_progress(static_cast(current)); }); ::AppInstaller::ProgressCallback progress(&progressCallback); diff --git a/src/Microsoft.Management.Deployment/PackageManager.cpp b/src/Microsoft.Management.Deployment/PackageManager.cpp index 0fbf818b49..a21d96cef7 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.cpp +++ b/src/Microsoft.Management.Deployment/PackageManager.cpp @@ -36,6 +36,7 @@ #include "Helpers.h" #include "ContextOrchestrator.h" #include "AppInstallerRuntime.h" +#include using namespace std::literals::chrono_literals; using namespace ::AppInstaller::CLI; @@ -962,6 +963,91 @@ namespace winrt::Microsoft::Management::Deployment::implementation co_return GetOperationResult(::Workflow::ExecutionStage::Initial, hr, 0, correlationData, false); } + 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::ISourceFactory::GetForType("")->TypeName(); + } + + 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() }; + + // This will throw if the source details are not initialized properly, acting as a validation check for the source object. + source.GetDetails(); + + std::string customHeader = winrt::to_string(options.CustomHeader()); + if (!customHeader.empty()) + { + source.SetCustomHeader(customHeader); + } + + 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 + } + #define WINGET_RETURN_INSTALL_RESULT_HR_IF(hr, boolVal) { if(boolVal) { return GetEmptyAsynchronousResultForOperation(hr, correlationData); }} #define WINGET_RETURN_INSTALL_RESULT_HR_IF_FAILED(hr) { WINGET_RETURN_INSTALL_RESULT_HR_IF(hr, FAILED(hr)) } @@ -1200,101 +1286,6 @@ namespace winrt::Microsoft::Management::Deployment::implementation true /*canCancelQueueItem*/, nullptr /*queueItem*/, package, options, std::move(callerProcessInfoString)); } - winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus GetAddPackageCatalogStatus(winrt::hresult terminationStatus) - { - switch (terminationStatus) - { - case S_OK: - return winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus::Ok; - case APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS: - return winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus::InvalidOptions; - case APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY: - return winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus::GroupPolicyError; - case APPINSTALLER_CLI_ERROR_SOURCES_INVALID: - case APPINSTALLER_CLI_ERROR_SOURCE_DATA_MISSING: - case APPINSTALLER_CLI_ERROR_SOURCE_NAME_ALREADY_EXISTS: - case APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST: - case APPINSTALLER_CLI_ERROR_SOURCE_ARG_ALREADY_EXISTS: - case APPINSTALLER_CLI_ERROR_SOURCE_NOT_SECURE: - case APPINSTALLER_CLI_ERROR_SOURCE_NOT_REMOTE: - case APPINSTALLER_CLI_ERROR_SOURCE_DATA_INTEGRITY_FAILURE: - case APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED: - return winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus::CatalogError; - case APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN: - case E_ACCESSDENIED: - return winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus::AccessDenied; - case APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED: - return winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus::SourceAgreementsNotAccepted; - case APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED: - return winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus::AuthenticationError; - case APPINSTALLER_CLI_ERROR_INTERNAL_ERROR: - default: - return winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus::InternalError; - } - } - - winrt::Microsoft::Management::Deployment::AddPackageCatalogResult GetAddPackageCatalogResult(winrt::hresult terminationStatus) - { - winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus status = GetAddPackageCatalogStatus(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::ISourceFactory::GetForType("")->TypeName(); - } - - 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() }; - - // This will throw if the source details are not initialized properly, acting as a validation check for the source object. - source.GetDetails(); - - std::string customHeader = winrt::to_string(options.CustomHeader()); - if (!customHeader.empty()) - { - source.SetCustomHeader(customHeader); - } - - return source; - } - winrt::Windows::Foundation::IAsyncOperationWithProgress PackageManager::AddPackageCatalogAsync(winrt::Microsoft::Management::Deployment::AddPackageCatalogOptions options) { LogStartupIfApplicable(); @@ -1334,7 +1325,8 @@ namespace winrt::Microsoft::Management::Deployment::implementation progressCallback.AddCallback([&report_progress](uint64_t current, uint64_t maximum, AppInstaller::ProgressType type) { UNREFERENCED_PARAMETER(type); - report_progress(static_cast(current) / static_cast(maximum)); + UNREFERENCED_PARAMETER(maximum); + report_progress(static_cast(current)); }); ::AppInstaller::ProgressCallback progress(&progressCallback); @@ -1346,59 +1338,6 @@ namespace winrt::Microsoft::Management::Deployment::implementation co_return GetAddPackageCatalogResult(terminationHR); } - winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus GetRemoveCatalogStatus(winrt::hresult terminationStatus) - { - switch (terminationStatus) - { - case S_OK: - return winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus::Ok; - case APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS: - return winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus::InvalidOptions; - case APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY: - return winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus::GroupPolicyError; - case APPINSTALLER_CLI_ERROR_SOURCES_INVALID: - case APPINSTALLER_CLI_ERROR_SOURCE_DATA_MISSING: - case APPINSTALLER_CLI_ERROR_SOURCE_NAME_ALREADY_EXISTS: - case APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST: - case APPINSTALLER_CLI_ERROR_SOURCE_ARG_ALREADY_EXISTS: - case APPINSTALLER_CLI_ERROR_SOURCE_NOT_SECURE: - case APPINSTALLER_CLI_ERROR_SOURCE_NOT_REMOTE: - case APPINSTALLER_CLI_ERROR_SOURCE_DATA_INTEGRITY_FAILURE: - case APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED: - return winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus::CatalogError; - case APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN: - case E_ACCESSDENIED: - return winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus::AccessDenied; - case APPINSTALLER_CLI_ERROR_INTERNAL_ERROR: - default: - return winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus::InternalError; - } - } - - winrt::Microsoft::Management::Deployment::RemovePackageCatalogResult GetRemovePackageCatalogResult(winrt::hresult terminationStatus) - { - winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus status = GetRemoveCatalogStatus(terminationStatus); - auto removeResult = winrt::make_self>(); - removeResult->Initialize(status, terminationStatus); - return *removeResult; - } - - #include - 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::IAsyncOperationWithProgress PackageManager::RemovePackageCatalogAsync(winrt::Microsoft::Management::Deployment::RemovePackageCatalogOptions options) { LogStartupIfApplicable(); @@ -1431,7 +1370,8 @@ namespace winrt::Microsoft::Management::Deployment::implementation progressCallback.AddCallback([&report_progress](uint64_t current, uint64_t maximum, AppInstaller::ProgressType type) { UNREFERENCED_PARAMETER(type); - report_progress(static_cast(current) / static_cast(maximum)); + UNREFERENCED_PARAMETER(maximum); + report_progress(static_cast(current)); }); ::AppInstaller::ProgressCallback progress(&progressCallback); From a0a91baee8fd23047c761a59a755e42262be2675 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Thu, 17 Oct 2024 22:18:11 -0700 Subject: [PATCH 21/38] Align RepairOptions struct with its UUID attribute The indentation of the `struct RepairOptions` declaration has been adjusted. Specifically, the indentation level has been decreased by one level, aligning it with the `[uuid(WINGET_OUTOFPROC_COM_CLSID_RepairOptions)]` attribute. This change improves code readability and consistency. --- src/Microsoft.Management.Deployment/RepairOptions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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(); From 75c68a2a2f91a0006e1499844d1de17697a9e9e8 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Thu, 17 Oct 2024 22:25:28 -0700 Subject: [PATCH 22/38] Update contract version to 12 in deployment namespaces for WinGet PackageCatalog COM APIs (as it is targetted for 1.10 release) Updated contract version from 11 to 12 in `winrt::Microsoft::Management::Deployment::implementation` and `Microsoft.Management.Deployment` namespaces. Changes include: - Updated comments and attributes in `PackageCatalogReference.h`, `PackageManager.h`, and `PackageManager.idl`. - Modified `contractversion` attribute in `PackageManager.idl` to 12. - Adjusted contract attributes for enums, runtime classes, and methods to version 12. These updates ensure the codebase aligns with the new contract version, incorporating any new features, improvements, or fixes. --- .../PackageCatalogReference.h | 2 +- .../PackageManager.h | 2 +- .../PackageManager.idl | 24 +++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.h b/src/Microsoft.Management.Deployment/PackageCatalogReference.h index a217720d24..75539d926a 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.h +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.h @@ -33,7 +33,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation winrt::Microsoft::Management::Deployment::AuthenticationArguments AuthenticationArguments(); void AuthenticationArguments(winrt::Microsoft::Management::Deployment::AuthenticationArguments const& value); winrt::Microsoft::Management::Deployment::AuthenticationInfo AuthenticationInfo(); - // Contract 11.0 + // Contract 12.0 winrt::Windows::Foundation::IAsyncOperationWithProgress RefreshPackageCatalogAsync(); #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) diff --git a/src/Microsoft.Management.Deployment/PackageManager.h b/src/Microsoft.Management.Deployment/PackageManager.h index 89c69b883b..1758962bd9 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.h +++ b/src/Microsoft.Management.Deployment/PackageManager.h @@ -44,7 +44,7 @@ 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 11.0 + // Contract 12.0 winrt::Windows::Foundation::IAsyncOperationWithProgress AddPackageCatalogAsync(winrt::Microsoft::Management::Deployment::AddPackageCatalogOptions options); winrt::Windows::Foundation::IAsyncOperationWithProgress diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl index 38513ceecf..c8b28428bc 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,7 +863,7 @@ namespace Microsoft.Management.Deployment } } - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] enum RefreshPackageCatalogStatus { Ok, @@ -873,7 +873,7 @@ namespace Microsoft.Management.Deployment }; /// IMPLEMENTATION NOTE: RefreshPackageCatalogResult - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] runtimeclass RefreshPackageCatalogResult { RefreshPackageCatalogStatus Status { get; }; @@ -937,7 +937,7 @@ namespace Microsoft.Management.Deployment AuthenticationInfo AuthenticationInfo { get; }; } - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] { /// Updates the package catalog. Windows.Foundation.IAsyncOperationWithProgress RefreshPackageCatalogAsync(); @@ -1377,7 +1377,7 @@ namespace Microsoft.Management.Deployment } /// IMPLEMENTATION NOTE: AddPackageCatalogOptions - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] runtimeclass AddPackageCatalogOptions { AddPackageCatalogOptions(); @@ -1411,7 +1411,7 @@ namespace Microsoft.Management.Deployment }; /// IMPLEMENTATION NOTE: AddPackageCatalogStatus - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] enum AddPackageCatalogStatus { Ok, @@ -1425,7 +1425,7 @@ namespace Microsoft.Management.Deployment }; /// IMPLEMENTATION NOTE: AddPackageCatalogResult - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] runtimeclass AddPackageCatalogResult { AddPackageCatalogStatus Status { get; }; @@ -1435,7 +1435,7 @@ namespace Microsoft.Management.Deployment }; /// IMPLEMENTATION NOTE: RemovePackageCatalogOptions - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] runtimeclass RemovePackageCatalogOptions { RemovePackageCatalogOptions(); @@ -1455,7 +1455,7 @@ namespace Microsoft.Management.Deployment }; /// IMPLEMENTATION NOTE: RemovePackageCatalogStatus - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] enum RemovePackageCatalogStatus { Ok, @@ -1467,8 +1467,8 @@ namespace Microsoft.Management.Deployment }; /// IMPLEMENTATION NOTE: RemovePackageCatalogResult -/// Result of removing a package catalog. - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + /// Result of removing a package catalog. + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] runtimeclass RemovePackageCatalogResult { RemovePackageCatalogStatus Status { get; }; @@ -1496,7 +1496,7 @@ namespace Microsoft.Management.Deployment /// (Installing, Installed) together at the same time. PackageCatalogReference CreateCompositePackageCatalog(CreateCompositePackageCatalogOptions options); - [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)] + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] { /// Add a catalog to the Windows Package Catalogs. Windows.Foundation.IAsyncOperationWithProgress AddPackageCatalogAsync(AddPackageCatalogOptions options); From fead163b8f5f350ffc2e180dbc55ac16b580974b Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Thu, 17 Oct 2024 22:30:45 -0700 Subject: [PATCH 23/38] [SpellCheck_Error] Fix typo in RemovePackageCatalogAsync method comment Corrected the term "Packagecatalog" to "Package Catalog" in the comment for the RemovePackageCatalogAsync method in the Microsoft.Management.Deployment namespace. --- src/Microsoft.Management.Deployment/PackageManager.idl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl index c8b28428bc..2cecb1e7a5 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.idl +++ b/src/Microsoft.Management.Deployment/PackageManager.idl @@ -1501,7 +1501,7 @@ namespace Microsoft.Management.Deployment /// Add a catalog to the Windows Package Catalogs. Windows.Foundation.IAsyncOperationWithProgress AddPackageCatalogAsync(AddPackageCatalogOptions options); - /// Unregisters a Packagecatalog from the Windows Package Catalogs and eliminates the system artifacts based on the provided 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); } From 9fef0f8bede45abd3b589a41051b9875916ca0b1 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Thu, 17 Oct 2024 23:40:23 -0700 Subject: [PATCH 24/38] Improve clarity of RemoveNonExistingPackageCatalog comment Updated the comment for the RemoveNonExistingPackageCatalog method to enhance readability and grammatical correctness. Changed "Remove non existing package catalog." to "Remove a non-existent package catalog." to make the purpose of the method clearer. --- src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs b/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs index 7a6121208f..259aa8a699 100644 --- a/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs +++ b/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs @@ -236,7 +236,7 @@ public async Task RemovePackageCatalogWithInvalidOptions() } /// - /// Remove non existing package catalog. + /// Remove a non-existent package catalog. /// /// representing the asynchronous unit test. [Test] From 69462af557b9d9c3c8efdd29a07f65edf1e5a12c Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Thu, 17 Oct 2024 23:48:16 -0700 Subject: [PATCH 25/38] Fix for forbidden-pattern error by spellchecking bot. Updated the comment for the RemoveNonExistingPackageCatalog method to improve clarity. The new comment "Remove a package catalog that is not present" is more straightforward and easier to understand. --- src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs b/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs index 259aa8a699..33cac389bf 100644 --- a/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs +++ b/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs @@ -236,7 +236,7 @@ public async Task RemovePackageCatalogWithInvalidOptions() } /// - /// Remove a non-existent package catalog. + /// Remove a package catalog that is not present. /// /// representing the asynchronous unit test. [Test] From 016c61885f3eb426ad501341138f1f7772365f52 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Thu, 17 Oct 2024 23:50:52 -0700 Subject: [PATCH 26/38] Remove element from vcxproj.filters Deleted the containing the element from the Microsoft.Management.Deployment.vcxproj.filters file. This change removes the inclusion of the wil.natvis file, which provided custom visualizations for native types in Visual Studio. --- .../Microsoft.Management.Deployment.vcxproj.filters | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters index 5443970406..22d8f3398c 100644 --- a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters +++ b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters @@ -109,7 +109,4 @@ {9c3907ed-84d9-4485-9b15-04c50717f0ab} - - - \ No newline at end of file From b4db8df101d5f1561172a414278b99bc4f5f444b Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Sun, 20 Oct 2024 22:16:54 -0700 Subject: [PATCH 27/38] Refactor error handling that includes logging and update test cases - Removed WINGET_CATALOG_CATCH_STORE macro from ExecutionContext.h. - Refactored GetPackageCatalogOperationStatus in Converters.h. - Updated PackageCatalogReference.cpp to use HandleException. - Refactored PackageManager.cpp for detailed exception handling. - Added new test cases for insecure URI and invalid type scenarios. - Updated PackageCatalogInterop.cs tests to use InvalidOptions status. - Added comments for admin validation checks in InProc/OutOfProc calls. --- src/AppInstallerCLICore/ExecutionContext.h | 7 -- .../Interop/PackageCatalogInterop.cs | 37 ++++++- .../Converters.h | 96 +++++++++++++------ .../PackageCatalogReference.cpp | 11 +-- .../PackageManager.cpp | 64 ++++++++++--- 5 files changed, 155 insertions(+), 60 deletions(-) diff --git a/src/AppInstallerCLICore/ExecutionContext.h b/src/AppInstallerCLICore/ExecutionContext.h index f3e9c23100..a5fa557570 100644 --- a/src/AppInstallerCLICore/ExecutionContext.h +++ b/src/AppInstallerCLICore/ExecutionContext.h @@ -25,13 +25,6 @@ WINGET_CATCH_STD_EXCEPTION_STORE(exceptionHR, genericHR) \ WINGET_CATCH_ALL_EXCEPTION_STORE(exceptionHR, genericHR) -#define WINGET_CATALOG_CATCH_STORE(exceptionHR, genericHR) \ - WINGET_CATCH_RESULT_EXCEPTION_STORE(exceptionHR) \ - WINGET_CATCH_HRESULT_EXCEPTION_STORE(exceptionHR) \ - WINGET_CATCH_POLICY_EXCEPTION_STORE(exceptionHR) \ - WINGET_CATCH_STD_EXCEPTION_STORE(exceptionHR, genericHR) \ - WINGET_CATCH_ALL_EXCEPTION_STORE(exceptionHR, genericHR) - // Terminates the Context with some logging to indicate the location. // Also returns from the current function. #define AICLI_TERMINATE_CONTEXT_ARGS(_context_,_hr_,_ret_) \ diff --git a/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs b/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs index 33cac389bf..d6d46dcae6 100644 --- a/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs +++ b/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs @@ -101,7 +101,7 @@ public async Task AddPackageCatalog_DuplicateName_ReturnsSourceNameExists() await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.Ok); // Add the same package catalog again. - await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.CatalogError, Constants.ErrorCode.ERROR_SOURCE_NAME_ALREADY_EXISTS); + 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(); @@ -126,7 +126,7 @@ public async Task AddPackageCatalog_DuplicateSourceUri_ReturnSourceArgAlreadyExi // Add the same package catalog again. options.Name = "TestSource2"; - await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.CatalogError, Constants.ErrorCode.ERROR_SOURCE_ARG_ALREADY_EXISTS); + 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(); @@ -150,6 +150,37 @@ public async Task AddPackageCatalogWithInvalidSourceUri() 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; + options.AcceptSourceAgreements = true; + + 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 package catalog with source agreement not accepted. /// @@ -245,7 +276,7 @@ public async Task RemoveNonExistingPackageCatalog() RemovePackageCatalogOptions removePackageCatalogOptions = this.TestFactory.CreateRemovePackageCatalogOptions(); removePackageCatalogOptions.Name = Constants.TestSourceName; - await this.RemoveAndValidatePackageCatalogAsync(removePackageCatalogOptions, RemovePackageCatalogStatus.CatalogError, Constants.ErrorCode.ERROR_SOURCE_NAME_DOES_NOT_EXIST); + await this.RemoveAndValidatePackageCatalogAsync(removePackageCatalogOptions, RemovePackageCatalogStatus.InvalidOptions, Constants.ErrorCode.ERROR_SOURCE_NAME_DOES_NOT_EXIST); } /// diff --git a/src/Microsoft.Management.Deployment/Converters.h b/src/Microsoft.Management.Deployment/Converters.h index 6f8afef906..f85ba8acc2 100644 --- a/src/Microsoft.Management.Deployment/Converters.h +++ b/src/Microsoft.Management.Deployment/Converters.h @@ -143,59 +143,93 @@ namespace winrt::Microsoft::Management::Deployment::implementation } template - TStatus GetPackageCatalogOperationStatus(winrt::hresult hresult) + TStatus HandleCommonCatalogOperationStatus(winrt::hresult hresult) { - // Applicable only for AddPackageCatalogStatus - if constexpr (std::is_same_v) + // Common status handling for AddPackageCatalogStatus and RemovePackageCatalogStatus. + if constexpr (std::is_same_v || std::is_same_v) { switch (hresult) { - case APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED: - return TStatus::SourceAgreementsNotAccepted; - case APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED: - return TStatus::AuthenticationError; - default: - break; - } - } - - // Applicable only for AddPackageCatalogStatus and RemovePackageCatalogStatus - if constexpr (std::is_same_v - || std::is_same_v) - { - switch (hresult) - { - case APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS: - case E_INVALIDARG: - return TStatus::InvalidOptions; case APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN: case E_ACCESSDENIED: return TStatus::AccessDenied; - default: + case APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS: + case E_INVALIDARG: + return TStatus::InvalidOptions; + default: break; } } - // Handle the common status codes across add, remove and refresh operations. + // 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_SOURCES_INVALID: - case APPINSTALLER_CLI_ERROR_SOURCE_DATA_MISSING: - case APPINSTALLER_CLI_ERROR_SOURCE_NAME_ALREADY_EXISTS: - case APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST: - case APPINSTALLER_CLI_ERROR_SOURCE_ARG_ALREADY_EXISTS: - case APPINSTALLER_CLI_ERROR_SOURCE_NOT_SECURE: - case APPINSTALLER_CLI_ERROR_SOURCE_NOT_REMOTE: case APPINSTALLER_CLI_ERROR_SOURCE_DATA_INTEGRITY_FAILURE: - case APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED: return TStatus::CatalogError; case APPINSTALLER_CLI_ERROR_INTERNAL_ERROR: default: return TStatus::InternalError; } } + + template + TStatus GetAddPackageCatalogOperationStatus(winrt::hresult hresult) + { + switch (hresult) + { + case APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED: + return TStatus::SourceAgreementsNotAccepted; + case APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED: + return TStatus::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 TStatus::InvalidOptions; + case APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED: + return TStatus::CatalogError; + default: + return HandleCommonCatalogOperationStatus(hresult); + } + } + + template + TStatus GetRemovePackageCatalogOperationStatus(winrt::hresult hresult) + { + switch (hresult) + { + case APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST: + return TStatus::InvalidOptions; + case APPINSTALLER_CLI_ERROR_INVALID_SOURCE_TYPE: + return TStatus::CatalogError; + default: + return HandleCommonCatalogOperationStatus(hresult); + } + } + + 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/PackageCatalogReference.cpp b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp index 200d5c171d..49a19f861c 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp @@ -302,12 +302,8 @@ namespace winrt::Microsoft::Management::Deployment::implementation winrt::Windows::Foundation::IAsyncOperationWithProgress PackageCatalogReference::RefreshPackageCatalogAsync() { - ::AppInstaller::Logging::Telemetry().SetCaller(GetCallerName()); - ::AppInstaller::Logging::Telemetry().LogStartup(true); - HRESULT terminationHR = S_OK; - try - { + try { // Check for permissions and get caller info for telemetry THROW_IF_FAILED(EnsureComCallerHasCapability(Capability::PackageQuery)); @@ -327,7 +323,10 @@ namespace winrt::Microsoft::Management::Deployment::implementation this->m_sourceReference.Update(progress); } - WINGET_CATALOG_CATCH_STORE(terminationHR, APPINSTALLER_CLI_ERROR_INTERNAL_ERROR); + catch (...) + { + terminationHR = AppInstaller::CLI::Workflow::HandleException(nullptr, std::current_exception()); + } co_return GetRefreshPackageCatalogResult(terminationHR); } diff --git a/src/Microsoft.Management.Deployment/PackageManager.cpp b/src/Microsoft.Management.Deployment/PackageManager.cpp index a21d96cef7..d6a6b6e444 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.cpp +++ b/src/Microsoft.Management.Deployment/PackageManager.cpp @@ -1013,15 +1013,51 @@ namespace winrt::Microsoft::Management::Deployment::implementation ::AppInstaller::Repository::Source source = ::AppInstaller::Repository::Source{ name, sourceUri, type, trustLevel, options.Explicit() }; - // This will throw if the source details are not initialized properly, acting as a validation check for the source object. - source.GetDetails(); - 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); + } + + if (!source.CheckSourceAgreements()) + { + if(!options.AcceptSourceAgreements()) + { + throw winrt::hresult_error(APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED); + } + + source.SaveAcceptedSourceAgreements(); + } + } + 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 if (hre.code() == APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED) + { + THROW_HR(APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED); + } + else + { + THROW_HR(APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED); + } + } + catch (...) // Catch all exceptions + { + THROW_HR(APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED); + } + return source; } @@ -1305,18 +1341,12 @@ namespace winrt::Microsoft::Management::Deployment::implementation try { // Check if running as admin + // [NOTE:] For OutOfProc calls, the Windows Package Manager Service executes in the context initiated by the caller process, + //so the same admin validation check is applicable for both InProc and OutOfProc calls. THROW_HR_IF(APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN, !AppInstaller::Runtime::IsRunningAsAdmin()); ::AppInstaller::Repository::Source sourceToAdd = CreateSourceFromOptions(options); - THROW_HR_IF(APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED, sourceToAdd.GetInformation().Authentication.Type == ::AppInstaller::Authentication::AuthenticationType::Unknown); - - if (!sourceToAdd.CheckSourceAgreements()) - { - THROW_HR_IF(APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED, !options.AcceptSourceAgreements()); - sourceToAdd.SaveAcceptedSourceAgreements(); - } - auto report_progress{ co_await winrt::get_progress_token() }; co_await winrt::resume_background(); @@ -1333,7 +1363,10 @@ namespace winrt::Microsoft::Management::Deployment::implementation sourceToAdd.Add(progress); } - WINGET_CATALOG_CATCH_STORE(terminationHR, APPINSTALLER_CLI_ERROR_INTERNAL_ERROR); + catch (...) + { + terminationHR = AppInstaller::CLI::Workflow::HandleException(nullptr, std::current_exception()); + } co_return GetAddPackageCatalogResult(terminationHR); } @@ -1356,6 +1389,8 @@ namespace winrt::Microsoft::Management::Deployment::implementation HRESULT terminationHR = S_OK; try { // Check if running as admin + // [NOTE:] For OutOfProc calls, the Windows Package Manager Service executes in the context initiated by the caller process, + //so the same admin validation check is applicable for both InProc and OutOfProc calls. THROW_HR_IF(APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN, !AppInstaller::Runtime::IsRunningAsAdmin()); auto matchingSource = GetMatchingSource(winrt::to_string(options.Name())); @@ -1388,7 +1423,10 @@ namespace winrt::Microsoft::Management::Deployment::implementation sourceToRemove.Remove(progress); } } - WINGET_CATALOG_CATCH_STORE(terminationHR, APPINSTALLER_CLI_ERROR_INTERNAL_ERROR); + catch (...) + { + terminationHR = AppInstaller::CLI::Workflow::HandleException(nullptr, std::current_exception()); + } co_return GetRemovePackageCatalogResult(terminationHR); } From 28b0a1227fb45bd85a142f51ea7fcfb7a5136a94 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Sun, 20 Oct 2024 23:10:40 -0700 Subject: [PATCH 28/38] Extend group policy tests to include package catalog management operation - Introduced `TestClassTearDown` method with `[OneTimeTearDown]` attribute. - Added `AddUpdateRemovePackageCatalog` method for catalog management. - Added `RemovePackageCatalog` method for catalog removal. - Integrated `AddUpdateRemovePackageCatalog` into existing tests. --- .../Interop/GroupPolicyForInterop.cs | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/src/AppInstallerCLIE2ETests/Interop/GroupPolicyForInterop.cs b/src/AppInstallerCLIE2ETests/Interop/GroupPolicyForInterop.cs index 45f34a91d3..cf645cf210 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,66 @@ 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; + options.AcceptSourceAgreements = true; + + 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); } } } From 127b4c7947e3c6138a57baab82f5d9e14fa9b496 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Mon, 21 Oct 2024 15:51:13 -0700 Subject: [PATCH 29/38] Simplify default source type retrieval in PackageManager - Integrate the fix from "Fix for Source Argument Validation in SourceWorkflow for Default Source Type" (#4891). This commit incorporates part of the included fix for consistency. - Updated the method of obtaining the default source type in the winrt::Microsoft::Management::Deployment::implementation namespace within PackageManager.cpp. Replaced the use of ::AppInstaller::Repository::ISourceFactory::GetForType("")->TypeName() with ::AppInstaller::Repository::Source::GetDefaultSourceType(). This change simplifies the process and ensures future-proofing against any changes in the SourceFactory's default type. --- src/Microsoft.Management.Deployment/PackageManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Management.Deployment/PackageManager.cpp b/src/Microsoft.Management.Deployment/PackageManager.cpp index d6a6b6e444..8b4f41b75b 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.cpp +++ b/src/Microsoft.Management.Deployment/PackageManager.cpp @@ -984,8 +984,8 @@ namespace winrt::Microsoft::Management::Deployment::implementation 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::ISourceFactory::GetForType("")->TypeName(); + // 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) From ea785f3fc18243ded111f71533fecd93c0776146 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Tue, 22 Oct 2024 20:54:53 -0700 Subject: [PATCH 30/38] Remove AcceptSourceAgreements property and related logic The implementation of PackageCatalogReference already includes the necessary logic to handle AcceptSourceAgreements. The `AcceptSourceAgreements` property has been removed from the `AddPackageCatalogOptions` class and its related files. This includes: - Removal of the property from `AddPackageCatalogOptions.h` and `AddPackageCatalogOptions.cpp`. - Removal of source agreement handling logic in `PackageManager.cpp`. - Removal of `SourceAgreementsNotAccepted` status from `AddPackageCatalogStatus` enum in `PackageManager.idl`. - Removal of the `AddPackageCatalogWithSourceAgreementNotAccepted` test case from `PackageCatalogInterop.cs`. - Removal of handling for `APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED` error in `Converters.h` and `PackageManager.cpp`. - Updates to test cases in `GroupPolicyForInterop.cs` and `PackageCatalogInterop.cs` to remove the setting of `AcceptSourceAgreements` to `true`. --- .../Interop/GroupPolicyForInterop.cs | 1 - .../Interop/PackageCatalogInterop.cs | 23 ------------------- .../AddPackageCatalogOptions.cpp | 9 -------- .../AddPackageCatalogOptions.h | 4 ---- .../Converters.h | 2 -- .../PackageManager.cpp | 14 ----------- .../PackageManager.idl | 4 ---- 7 files changed, 57 deletions(-) diff --git a/src/AppInstallerCLIE2ETests/Interop/GroupPolicyForInterop.cs b/src/AppInstallerCLIE2ETests/Interop/GroupPolicyForInterop.cs index cf645cf210..e86e27beca 100644 --- a/src/AppInstallerCLIE2ETests/Interop/GroupPolicyForInterop.cs +++ b/src/AppInstallerCLIE2ETests/Interop/GroupPolicyForInterop.cs @@ -195,7 +195,6 @@ private async Task AddUpdateRemovePackageCatalog() options.SourceUri = Constants.TestSourceUrl; options.Name = Constants.TestSourceName; options.TrustLevel = PackageCatalogTrustLevel.Trusted; - options.AcceptSourceAgreements = true; var addCatalogResult = await packageManager.AddPackageCatalogAsync(options); Assert.IsNotNull(addCatalogResult); diff --git a/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs b/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs index d6d46dcae6..e01683803b 100644 --- a/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs +++ b/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs @@ -57,7 +57,6 @@ public async Task AddRemovePackageCatalog() options.SourceUri = Constants.TestSourceUrl; options.Name = Constants.TestSourceName; options.TrustLevel = PackageCatalogTrustLevel.Trusted; - options.AcceptSourceAgreements = true; await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.Ok); @@ -96,7 +95,6 @@ public async Task AddPackageCatalog_DuplicateName_ReturnsSourceNameExists() options.SourceUri = Constants.TestSourceUrl; options.Name = Constants.TestSourceName; options.TrustLevel = PackageCatalogTrustLevel.Trusted; - options.AcceptSourceAgreements = true; await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.Ok); @@ -120,7 +118,6 @@ public async Task AddPackageCatalog_DuplicateSourceUri_ReturnSourceArgAlreadyExi options.SourceUri = Constants.TestSourceUrl; options.Name = Constants.TestSourceName; options.TrustLevel = PackageCatalogTrustLevel.Trusted; - options.AcceptSourceAgreements = true; await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.Ok); @@ -145,7 +142,6 @@ public async Task AddPackageCatalogWithInvalidSourceUri() options.SourceUri = "InvalidUri"; options.Name = Constants.TestSourceName; options.TrustLevel = PackageCatalogTrustLevel.Trusted; - options.AcceptSourceAgreements = true; await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.InternalError); } @@ -161,7 +157,6 @@ public async Task AddPackageCatalogWithHttpSourceUri() options.SourceUri = "http://microsoft.com"; options.Name = "Insecure"; options.TrustLevel = PackageCatalogTrustLevel.Trusted; - options.AcceptSourceAgreements = true; await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.InvalidOptions, Constants.ErrorCode.ERROR_SOURCE_NOT_SECURE); } @@ -181,22 +176,6 @@ public async Task AddPackageCatalogWithInvalidType() await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.InvalidOptions, Constants.ErrorCode.ERROR_INVALID_SOURCE_TYPE); } - /// - /// Add package catalog with source agreement not accepted. - /// - /// representing the asynchronous unit test. - [Test] - public async Task AddPackageCatalogWithSourceAgreementNotAccepted() - { - AddPackageCatalogOptions options = this.TestFactory.CreateAddPackageCatalogOptions(); - options.SourceUri = Constants.DefaultMSStoreSourceUrl; - options.Name = Constants.DefaultMSStoreSourceName; - options.Type = Constants.DefaultMSStoreSourceType; - options.TrustLevel = PackageCatalogTrustLevel.Trusted; - - await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.SourceAgreementsNotAccepted, Constants.ErrorCode.ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED); - } - /// /// Add, update and remove package catalog. /// @@ -208,7 +187,6 @@ public async Task AddUpdateRemovePackageCatalog() options.SourceUri = Constants.TestSourceUrl; options.Name = Constants.TestSourceName; options.TrustLevel = PackageCatalogTrustLevel.Trusted; - options.AcceptSourceAgreements = true; await this.AddCatalogAndVerifyStatusAsync(options, AddPackageCatalogStatus.Ok); @@ -241,7 +219,6 @@ public async Task AddRemovePackageCatalogWithPreserveDataFiledSet() options.SourceUri = Constants.TestSourceUrl; options.Name = Constants.TestSourceName; options.TrustLevel = PackageCatalogTrustLevel.Trusted; - options.AcceptSourceAgreements = true; await this.AddAndValidatePackageCatalogAsync(options, AddPackageCatalogStatus.Ok); diff --git a/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.cpp b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.cpp index f0c981d187..b31d0962f5 100644 --- a/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.cpp +++ b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.cpp @@ -62,14 +62,5 @@ namespace winrt::Microsoft::Management::Deployment::implementation { m_explicit = value; } - bool AddPackageCatalogOptions::AcceptSourceAgreements() - { - return m_acceptSourceAgreements; - } - void AddPackageCatalogOptions::AcceptSourceAgreements(bool const& value) - { - m_acceptSourceAgreements = value; - } - CoCreatableMicrosoftManagementDeploymentClass(AddPackageCatalogOptions); } diff --git a/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h index 3650eab1a4..91ec268cad 100644 --- a/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h +++ b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h @@ -29,9 +29,6 @@ namespace winrt::Microsoft::Management::Deployment::implementation bool Explicit(); void Explicit(bool const& value); - bool AcceptSourceAgreements(); - void AcceptSourceAgreements(bool const& value); - #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) private: std::wstring m_name = L""; @@ -40,7 +37,6 @@ namespace winrt::Microsoft::Management::Deployment::implementation winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel m_trustLevel = winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel::None; std::wstring m_customHeader = L""; bool m_explicit = false; - bool m_acceptSourceAgreements = false; #endif }; } diff --git a/src/Microsoft.Management.Deployment/Converters.h b/src/Microsoft.Management.Deployment/Converters.h index f85ba8acc2..764440b6b1 100644 --- a/src/Microsoft.Management.Deployment/Converters.h +++ b/src/Microsoft.Management.Deployment/Converters.h @@ -181,8 +181,6 @@ namespace winrt::Microsoft::Management::Deployment::implementation { switch (hresult) { - case APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED: - return TStatus::SourceAgreementsNotAccepted; case APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED: return TStatus::AuthenticationError; case APPINSTALLER_CLI_ERROR_SOURCE_NOT_SECURE: diff --git a/src/Microsoft.Management.Deployment/PackageManager.cpp b/src/Microsoft.Management.Deployment/PackageManager.cpp index 8b4f41b75b..ac7ee1ed1d 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.cpp +++ b/src/Microsoft.Management.Deployment/PackageManager.cpp @@ -1027,16 +1027,6 @@ namespace winrt::Microsoft::Management::Deployment::implementation { throw winrt::hresult_error(APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED); } - - if (!source.CheckSourceAgreements()) - { - if(!options.AcceptSourceAgreements()) - { - throw winrt::hresult_error(APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED); - } - - source.SaveAcceptedSourceAgreements(); - } } catch (const winrt::hresult_error& hre) { @@ -1044,10 +1034,6 @@ namespace winrt::Microsoft::Management::Deployment::implementation { THROW_HR(APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED); } - else if (hre.code() == APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED) - { - THROW_HR(APPINSTALLER_CLI_ERROR_SOURCE_AGREEMENTS_NOT_ACCEPTED); - } else { THROW_HR(APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED); diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl index 2cecb1e7a5..302e66fda5 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.idl +++ b/src/Microsoft.Management.Deployment/PackageManager.idl @@ -1405,9 +1405,6 @@ namespace Microsoft.Management.Deployment /// Excludes a source from discovery unless specified. Boolean Explicit; - - /// PackageCatalog Source agreement. - Boolean AcceptSourceAgreements; }; /// IMPLEMENTATION NOTE: AddPackageCatalogStatus @@ -1420,7 +1417,6 @@ namespace Microsoft.Management.Deployment InternalError, InvalidOptions, AccessDenied, - SourceAgreementsNotAccepted, AuthenticationError, }; From 4dcdc2a5a2128a8d1e9e68c5a1bc32217d712804 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Wed, 23 Oct 2024 00:00:41 -0700 Subject: [PATCH 31/38] [PR Feedback]:Refactor error handling and add admin/system check functions - Added IsRunningAsAdminOrSystem() in Runtime.h and Runtime.cpp. - Added COM class entry for RemovePackageCatalogOptions in Microsoft.Management.Deployment.InProc.dll.manifest. - Corrected NameCLSIDPair syntax in Factory.cpp. - Added and declared new status mapping functions in Converters.cpp and Converters.h. - Encapsulated GetRefreshPackageCatalogResult in PackageCatalogReference.cpp. - Encapsulated package catalog operation functions in PackageManager.cpp. - Removed ResetPackageCatalogResult class and its implementation. - Updated error codes in PackageCatalogInterop.cs. --- .../Interop/PackageCatalogInterop.cs | 8 +- .../Public/winget/Runtime.h | 3 + src/AppInstallerSharedLib/Runtime.cpp | 5 + ....Management.Deployment.InProc.dll.manifest | 4 + .../Factory.cpp | 2 +- .../Converters.cpp | 33 +++ .../Converters.h | 40 +-- .../PackageCatalogReference.cpp | 19 +- .../PackageManager.cpp | 258 +++++++++--------- .../ResetPackageCatalogResult.cpp | 25 -- .../ResetPackageCatalogResult.h | 27 -- 11 files changed, 188 insertions(+), 236 deletions(-) delete mode 100644 src/Microsoft.Management.Deployment/ResetPackageCatalogResult.cpp delete mode 100644 src/Microsoft.Management.Deployment/ResetPackageCatalogResult.h diff --git a/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs b/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs index e01683803b..1a24433ecc 100644 --- a/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs +++ b/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs @@ -78,10 +78,10 @@ public async Task AddRemovePackageCatalog() public async Task AddPackageCatalogWithInvalidOptions() { // Add package catalog with null options. - await this.AddAndValidatePackageCatalogAsync(null, AddPackageCatalogStatus.InvalidOptions, Constants.ErrorCode.ERROR_INVALID_CL_ARGUMENTS); + await this.AddAndValidatePackageCatalogAsync(null, AddPackageCatalogStatus.InvalidOptions, Constants.ErrorCode.E_INVALIDARG); // Add package catalog with empty options. - await this.AddAndValidatePackageCatalogAsync(this.TestFactory.CreateAddPackageCatalogOptions(), AddPackageCatalogStatus.InvalidOptions, Constants.ErrorCode.ERROR_INVALID_CL_ARGUMENTS); + await this.AddAndValidatePackageCatalogAsync(this.TestFactory.CreateAddPackageCatalogOptions(), AddPackageCatalogStatus.InvalidOptions, Constants.ErrorCode.E_INVALIDARG); } /// @@ -237,10 +237,10 @@ public async Task AddRemovePackageCatalogWithPreserveDataFiledSet() public async Task RemovePackageCatalogWithInvalidOptions() { // Remove package catalog with null options. - await this.RemoveAndValidatePackageCatalogAsync(null, RemovePackageCatalogStatus.InvalidOptions, Constants.ErrorCode.ERROR_INVALID_CL_ARGUMENTS); + await this.RemoveAndValidatePackageCatalogAsync(null, RemovePackageCatalogStatus.InvalidOptions, Constants.ErrorCode.E_INVALIDARG); // Remove package catalog with empty options. - await this.RemoveAndValidatePackageCatalogAsync(this.TestFactory.CreateRemovePackageCatalogOptions(), RemovePackageCatalogStatus.InvalidOptions, Constants.ErrorCode.ERROR_INVALID_CL_ARGUMENTS); + await this.RemoveAndValidatePackageCatalogAsync(this.TestFactory.CreateRemovePackageCatalogOptions(), RemovePackageCatalogStatus.InvalidOptions, Constants.ErrorCode.E_INVALIDARG); } /// 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 cc2f0f0353..bc3374be82 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 @@ -51,5 +51,9 @@ clsid="{24E6F1FA-E4C3-4ACD-965D-DF213FD58F15}" threadingModel="Both" description="AddPackageCatalogOptions"/> + diff --git a/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp b/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp index 58ab03a56c..89bd2f4048 100644 --- a/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp +++ b/src/Microsoft.Management.Deployment.OutOfProc/Factory.cpp @@ -57,7 +57,7 @@ namespace Microsoft::Management::Deployment::OutOfProc NameCLSIDPair{ L"Microsoft.Management.Deployment.AuthenticationArguments"sv, CLSID_AuthenticationArguments }, 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 } + NameCLSIDPair{ L"Microsoft.Management.Deployment.RemovePackageCatalogOptions"sv, CLSID_RemovePackageCatalogOptions }, }; bool IsCLSIDPresent(const GUID& clsid) 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 764440b6b1..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) \ @@ -176,50 +178,16 @@ namespace winrt::Microsoft::Management::Deployment::implementation } } - template - TStatus GetAddPackageCatalogOperationStatus(winrt::hresult hresult) - { - switch (hresult) - { - case APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED: - return TStatus::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 TStatus::InvalidOptions; - case APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED: - return TStatus::CatalogError; - default: - return HandleCommonCatalogOperationStatus(hresult); - } - } - - template - TStatus GetRemovePackageCatalogOperationStatus(winrt::hresult hresult) - { - switch (hresult) - { - case APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST: - return TStatus::InvalidOptions; - case APPINSTALLER_CLI_ERROR_INVALID_SOURCE_TYPE: - return TStatus::CatalogError; - default: - return HandleCommonCatalogOperationStatus(hresult); - } - } - template TStatus GetPackageCatalogOperationStatus(winrt::hresult hresult) { if constexpr (std::is_same_v) { - return GetAddPackageCatalogOperationStatus(hresult); + return GetAddPackageCatalogOperationStatus(hresult); } else if constexpr (std::is_same_v) { - return GetRemovePackageCatalogOperationStatus(hresult); + return GetRemovePackageCatalogOperationStatus(hresult); } else if constexpr (std::is_same_v) { diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp index 49a19f861c..c6bf9e126d 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp @@ -23,6 +23,17 @@ 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; @@ -292,14 +303,6 @@ namespace winrt::Microsoft::Management::Deployment::implementation return m_authenticationInfo; } - 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; - } - winrt::Windows::Foundation::IAsyncOperationWithProgress PackageCatalogReference::RefreshPackageCatalogAsync() { HRESULT terminationHR = S_OK; diff --git a/src/Microsoft.Management.Deployment/PackageManager.cpp b/src/Microsoft.Management.Deployment/PackageManager.cpp index ac7ee1ed1d..c8d6c36536 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.cpp +++ b/src/Microsoft.Management.Deployment/PackageManager.cpp @@ -56,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() @@ -963,113 +1070,6 @@ namespace winrt::Microsoft::Management::Deployment::implementation co_return GetOperationResult(::Workflow::ExecutionStage::Initial, hr, 0, correlationData, false); } - 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 - } - #define WINGET_RETURN_INSTALL_RESULT_HR_IF(hr, boolVal) { if(boolVal) { return GetEmptyAsynchronousResultForOperation(hr, correlationData); }} #define WINGET_RETURN_INSTALL_RESULT_HR_IF_FAILED(hr) { WINGET_RETURN_INSTALL_RESULT_HR_IF(hr, FAILED(hr)) } @@ -1312,24 +1312,18 @@ namespace winrt::Microsoft::Management::Deployment::implementation { LogStartupIfApplicable(); - // options must be set. - if (!options) - { - co_return GetAddPackageCatalogResult(APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS); - } - - if (options.Name().empty() || options.SourceUri().empty()) - { - co_return GetAddPackageCatalogResult(APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS); - } - HRESULT terminationHR = S_OK; try { - // Check if running as admin + // 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()); + + // 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 validation check is applicable for both InProc and OutOfProc calls. - THROW_HR_IF(APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN, !AppInstaller::Runtime::IsRunningAsAdmin()); + // 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); @@ -1361,23 +1355,17 @@ namespace winrt::Microsoft::Management::Deployment::implementation { LogStartupIfApplicable(); - // options must be set. - if (!options) - { - co_return GetRemovePackageCatalogResult(APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS); - } - - if (options.Name().empty()) - { - co_return GetRemovePackageCatalogResult(APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS); - } - HRESULT terminationHR = S_OK; try { - // Check if running as admin + + // options must be set. + THROW_HR_IF_NULL(E_INVALIDARG, options); + THROW_HR_IF(E_INVALIDARG, options.Name().empty()); + + // 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 validation check is applicable for both InProc and OutOfProc calls. - THROW_HR_IF(APPINSTALLER_CLI_ERROR_COMMAND_REQUIRES_ADMIN, !AppInstaller::Runtime::IsRunningAsAdmin()); + // 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()); diff --git a/src/Microsoft.Management.Deployment/ResetPackageCatalogResult.cpp b/src/Microsoft.Management.Deployment/ResetPackageCatalogResult.cpp deleted file mode 100644 index d5b4bc99cd..0000000000 --- a/src/Microsoft.Management.Deployment/ResetPackageCatalogResult.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -#include "pch.h" -#include "ResetPackageCatalogResult.h" -#include "ResetPackageCatalogResult.g.cpp" -#include - -namespace winrt::Microsoft::Management::Deployment::implementation -{ - void ResetPackageCatalogResult::Initialize( - winrt::Microsoft::Management::Deployment::ResetPackageCatalogStatus status, - winrt::hresult extendedErrorCode) - { - m_status = status; - m_extendedErrorCode = extendedErrorCode; - } - winrt::Microsoft::Management::Deployment::ResetPackageCatalogStatus ResetPackageCatalogResult::Status() - { - return m_status; - } - winrt::hresult ResetPackageCatalogResult::ExtendedErrorCode() - { - return m_extendedErrorCode; - } -} diff --git a/src/Microsoft.Management.Deployment/ResetPackageCatalogResult.h b/src/Microsoft.Management.Deployment/ResetPackageCatalogResult.h deleted file mode 100644 index 07f11c2542..0000000000 --- a/src/Microsoft.Management.Deployment/ResetPackageCatalogResult.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -#pragma once -#include "ResetPackageCatalogResult.g.h" - -namespace winrt::Microsoft::Management::Deployment::implementation -{ - struct ResetPackageCatalogResult : ResetPackageCatalogResultT - { - ResetPackageCatalogResult() = default; - -#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) - void Initialize( - winrt::Microsoft::Management::Deployment::ResetPackageCatalogStatus status, - winrt::hresult extendedErrorCode); -#endif - - winrt::Microsoft::Management::Deployment::ResetPackageCatalogStatus Status(); - winrt::hresult ExtendedErrorCode(); - -#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) - private: - winrt::Microsoft::Management::Deployment::ResetPackageCatalogStatus m_status = winrt::Microsoft::Management::Deployment::ResetPackageCatalogStatus::Ok; - winrt::hresult m_extendedErrorCode = S_OK; -#endif - }; -} From f92b9473e1851a768f3c9b3f3bf3f5262ff194f9 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Wed, 23 Oct 2024 11:21:04 -0700 Subject: [PATCH 32/38] Fix indentation in RemovePackageCatalogOptions clsid Corrected the indentation of the `clsid` attribute for the `RemovePackageCatalogOptions` comClass element in the `Microsoft.Management.Deployment.InProc.dll.manifest` file. The `clsid` value itself remains unchanged. --- .../Microsoft.Management.Deployment.InProc.dll.manifest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 bc3374be82..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 @@ -52,7 +52,7 @@ threadingModel="Both" description="AddPackageCatalogOptions"/> From 10f92be2c4d145aa9da82734d551ec36a4cb8f72 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Wed, 23 Oct 2024 13:07:52 -0700 Subject: [PATCH 33/38] Refactor argument validation in AddPackageCatalogAsync & RemovePackageCatalogAsync to throw errors on invalid arguments, following API design guidelines. - Updated `AddPackageCatalogAsync` and `RemovePackageCatalogAsync` in `PackageManager.cpp` to perform argument validation at the beginning of the methods, ensuring early error detection and potential performance improvements. At this stage, we avoid constructing a result object for error codes and simply use a THROW statement to generate an exception for the caller. - Refactored `AddPackageCatalogWithInvalidOptions` and `RemovePackageCatalogWithInvalidOptions` in `PackageCatalogInterop.cs` to be synchronous and directly test for exceptions using `Assert.ThrowsAsync`. --- .../Interop/PackageCatalogInterop.cs | 14 ++++++-------- .../PackageManager.cpp | 18 +++++++++--------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs b/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs index 1a24433ecc..23e133fb00 100644 --- a/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs +++ b/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs @@ -73,15 +73,14 @@ public async Task AddRemovePackageCatalog() /// /// Add package catalog with invalid options. /// - /// representing the asynchronous unit test. [Test] - public async Task AddPackageCatalogWithInvalidOptions() + public void AddPackageCatalogWithInvalidOptions() { // Add package catalog with null options. - await this.AddAndValidatePackageCatalogAsync(null, AddPackageCatalogStatus.InvalidOptions, Constants.ErrorCode.E_INVALIDARG); + Assert.ThrowsAsync(async () => await this.packageManager.AddPackageCatalogAsync(null)); // Add package catalog with empty options. - await this.AddAndValidatePackageCatalogAsync(this.TestFactory.CreateAddPackageCatalogOptions(), AddPackageCatalogStatus.InvalidOptions, Constants.ErrorCode.E_INVALIDARG); + Assert.ThrowsAsync(async () => await this.packageManager.AddPackageCatalogAsync(this.TestFactory.CreateAddPackageCatalogOptions())); } /// @@ -232,15 +231,14 @@ public async Task AddRemovePackageCatalogWithPreserveDataFiledSet() /// /// Remove package catalog with invalid options. /// - /// representing the asynchronous unit test. [Test] - public async Task RemovePackageCatalogWithInvalidOptions() + public void RemovePackageCatalogWithInvalidOptions() { // Remove package catalog with null options. - await this.RemoveAndValidatePackageCatalogAsync(null, RemovePackageCatalogStatus.InvalidOptions, Constants.ErrorCode.E_INVALIDARG); + Assert.ThrowsAsync(async () => await this.packageManager.RemovePackageCatalogAsync(null)); // Remove package catalog with empty options. - await this.RemoveAndValidatePackageCatalogAsync(this.TestFactory.CreateRemovePackageCatalogOptions(), RemovePackageCatalogStatus.InvalidOptions, Constants.ErrorCode.E_INVALIDARG); + Assert.ThrowsAsync(async () => await this.packageManager.RemovePackageCatalogAsync(this.TestFactory.CreateRemovePackageCatalogOptions())); } /// diff --git a/src/Microsoft.Management.Deployment/PackageManager.cpp b/src/Microsoft.Management.Deployment/PackageManager.cpp index c8d6c36536..47ad79bafa 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.cpp +++ b/src/Microsoft.Management.Deployment/PackageManager.cpp @@ -1312,14 +1312,14 @@ namespace winrt::Microsoft::Management::Deployment::implementation { 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 { - // 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()); - // 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. @@ -1355,13 +1355,13 @@ namespace winrt::Microsoft::Management::Deployment::implementation { 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 { - // options must be set. - THROW_HR_IF_NULL(E_INVALIDARG, options); - THROW_HR_IF(E_INVALIDARG, options.Name().empty()); - // 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. From 1244dd67ca4ea4897d69061a318c30f74ef9e47e Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Thu, 24 Oct 2024 10:35:03 -0700 Subject: [PATCH 34/38] [PR Feedback:] Refactor progress reporting mechanism - Removed `CallbackDispatcherSink` and - introduced new progress sink classes: - `CompletionOnlyProgressSink` and - 'PreIndexedPackageCatalogProgressSink`. - Updated project files and existing code to use the new progress sinks, simplifying and improving progress reporting for package catalog operations. --- src/AppInstallerCommonCore/Progress.cpp | 39 ----- .../Public/AppInstallerProgress.h | 26 ---- .../Microsoft.Management.Deployment.vcxproj | 2 + ...soft.Management.Deployment.vcxproj.filters | 2 + .../PackageCatalogProgress.cpp | 137 ++++++++++++++++++ .../PackageCatalogProgress.h | 73 ++++++++++ .../PackageCatalogReference.cpp | 15 +- .../PackageManager.cpp | 34 ++--- 8 files changed, 231 insertions(+), 97 deletions(-) create mode 100644 src/Microsoft.Management.Deployment/PackageCatalogProgress.cpp create mode 100644 src/Microsoft.Management.Deployment/PackageCatalogProgress.h diff --git a/src/AppInstallerCommonCore/Progress.cpp b/src/AppInstallerCommonCore/Progress.cpp index df7fd7b545..4288256507 100644 --- a/src/AppInstallerCommonCore/Progress.cpp +++ b/src/AppInstallerCommonCore/Progress.cpp @@ -134,43 +134,4 @@ 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 5449355773..5f9a08dcc2 100644 --- a/src/AppInstallerCommonCore/Public/AppInstallerProgress.h +++ b/src/AppInstallerCommonCore/Public/AppInstallerProgress.h @@ -127,32 +127,6 @@ 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/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj index 78cb7dc534..57f0161936 100644 --- a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj +++ b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj @@ -207,6 +207,7 @@ + @@ -254,6 +255,7 @@ + diff --git a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters index 22d8f3398c..78c593d394 100644 --- a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters +++ b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters @@ -45,6 +45,7 @@ + @@ -95,6 +96,7 @@ + diff --git a/src/Microsoft.Management.Deployment/PackageCatalogProgress.cpp b/src/Microsoft.Management.Deployment/PackageCatalogProgress.cpp new file mode 100644 index 0000000000..83941b9f9d --- /dev/null +++ b/src/Microsoft.Management.Deployment/PackageCatalogProgress.cpp @@ -0,0 +1,137 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "PackageCatalogProgress.h" +#include "AppInstallerStrings.h" +#include "Microsoft/PredefinedInstalledSourceFactory.h" + +using namespace AppInstaller; +using namespace AppInstaller::Repository; + +namespace winrt::Microsoft::Management::Deployment +{ + namespace ProgressSinkFactory + { + std::shared_ptr CreatePackageCatalogProgressSink(std::string sourceType, std::function progressReporter, bool removeOperation) + { + if (sourceType.empty() + || Utility::CaseInsensitiveEquals( Repository::Microsoft::PredefinedInstalledSourceFactory::Type(), sourceType)) + { + std::unordered_map progressWeights; + + // There is no download operation for remove operation, so remove the download progress. + if (removeOperation) + { + // it is percentage based progress. + progressWeights.insert_or_assign(AppInstaller::ProgressType::Bytes, 0); + } + else + { + // Add/Update operation has two progress types: + // 1. Bytes for downloading index and + // 2. Percent for index installation. + progressWeights.insert_or_assign(AppInstaller::ProgressType::Bytes, 0.7); + progressWeights.insert_or_assign(AppInstaller::ProgressType::Percent, 0.3); + } + + return std::make_shared(progressWeights, progressReporter); + } + else + { + return std::make_shared(progressReporter); + } + } + } + + CompletionOnlyProgressSink::CompletionOnlyProgressSink(std::function progressReporter) : + m_progressReporter(progressReporter) + { + } + + void CompletionOnlyProgressSink::OnProgress(uint64_t current, uint64_t maximum, AppInstaller::ProgressType type) + { + UNREFERENCED_PARAMETER(current); + UNREFERENCED_PARAMETER(maximum); + UNREFERENCED_PARAMETER(type); + } + + void CompletionOnlyProgressSink::SetProgressMessage(std::string_view message) + { + UNREFERENCED_PARAMETER(message); + } + + void CompletionOnlyProgressSink::BeginProgress() + { + m_progressReporter(0); + } + + void CompletionOnlyProgressSink::EndProgress(bool hideProgressWhenDone) + { + UNREFERENCED_PARAMETER(hideProgressWhenDone); + m_progressReporter(100); + } + + PreIndexedPackageCatalogProgressSink::PreIndexedPackageCatalogProgressSink(std::unordered_map progressWeights, std::function progressReporter) : + m_progressWeights(progressWeights), m_progressReporter(progressReporter) + { + // If no weights are provided, default to percent. + if (m_progressWeights.empty()) + { + m_progressWeights[AppInstaller::ProgressType::Percent] = 1; + } + + // Calculate the total weight. + double totalWeight = 0; + for (const auto& weight : m_progressWeights) + { + if (weight.first != AppInstaller::ProgressType::None) + { + totalWeight += weight.second; + } + } + + // If the total weight is greater than 1, throw an exception. + if (totalWeight != 1.0) + { + THROW_HR(E_INVALIDARG); + } + } + + void PreIndexedPackageCatalogProgressSink::OnProgress(uint64_t current, uint64_t maximum, AppInstaller::ProgressType type) + { + if (maximum == 0 || type == AppInstaller::ProgressType::None) + { + return; + } + + double progress = static_cast(current) / maximum; + m_progressValues[type] = progress; + + double totalProgress = 0.0; + + // Calculate the total progress. + for (const auto& [progressType, weight] : m_progressWeights) + { + // Adjust the total progress value based on the weight. + totalProgress += m_progressValues[progressType] * weight; + } + + m_progressReporter(totalProgress * 100); + } + + void PreIndexedPackageCatalogProgressSink::SetProgressMessage(std::string_view message) + { + UNREFERENCED_PARAMETER(message); + } + + void PreIndexedPackageCatalogProgressSink::BeginProgress() + { + OnProgress(0, 1, AppInstaller::ProgressType::None); + } + + void PreIndexedPackageCatalogProgressSink::EndProgress(bool hideProgressWhenDone) + { + UNREFERENCED_PARAMETER(hideProgressWhenDone); + OnProgress(1, 1, AppInstaller::ProgressType::None); + } +} diff --git a/src/Microsoft.Management.Deployment/PackageCatalogProgress.h b/src/Microsoft.Management.Deployment/PackageCatalogProgress.h new file mode 100644 index 0000000000..4ec8716fb7 --- /dev/null +++ b/src/Microsoft.Management.Deployment/PackageCatalogProgress.h @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once +#include "AppInstallerProgress.h" +#include +#include + +namespace winrt::Microsoft::Management::Deployment +{ + namespace ProgressSinkFactory + { + /// + /// Creates a progress sink for package catalog operations based on sourceType. + /// + /// sourceType. + /// callback function that reports progress to caller. + /// Default value is false. Identifies if the operation is a PackageCatalog removal and requests the ProgressSink. + /// IProgressSink. + std::shared_ptr CreatePackageCatalogProgressSink(std::string sourceType, std::function progressReporter, bool removeOperation = false); + } + + /// + /// Progress sink that only reports start and completion to caller. + /// + struct CompletionOnlyProgressSink : AppInstaller::IProgressSink + { + /// + /// Constructor. + /// + /// callback that reports progress to caller. + CompletionOnlyProgressSink(std::function progressReporter); + + void OnProgress(uint64_t current, uint64_t maximum, AppInstaller::ProgressType type) override; + void SetProgressMessage(std::string_view message) override; + void BeginProgress() override; + void EndProgress(bool hideProgressWhenDone) override; + + private: + std::function m_progressReporter; + }; + + /// + /// Progress sink for pre-indexed package catalog operations. + /// capable of reporting progress for download and installation of index. + /// Add/update operation has two progress types: Bytes for downloading index and Percent for index installation. + /// Remove operation has only percentage based progress. + /// + struct PreIndexedPackageCatalogProgressSink : AppInstaller::IProgressSink + { + /// + /// Constructor. + /// + /// ProgressType weight map. + /// Callback function that reports progress to caller. + PreIndexedPackageCatalogProgressSink(std::unordered_map progressWeights, std::function progressReporter); + + /// + /// Reports combined progress to caller when configured for multiple progress types. + /// + /// The current progress value. + /// The maximum progres value. + /// ProgressType for which progress is applicable. + void OnProgress(uint64_t current, uint64_t maximum, AppInstaller::ProgressType type) override; + void SetProgressMessage(std::string_view message) override; + void BeginProgress() override; + void EndProgress(bool hideProgressWhenDone) override; + + private: + std::unordered_map m_progressWeights; + std::function m_progressReporter; + std::unordered_map m_progressValues; + }; +} diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp index c6bf9e126d..c2787e8924 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp +++ b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace winrt::Microsoft::Management::Deployment::implementation { @@ -313,18 +314,12 @@ namespace winrt::Microsoft::Management::Deployment::implementation 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); + auto packageCatalogProgressSink = winrt::Microsoft::Management::Deployment::ProgressSinkFactory::CreatePackageCatalogProgressSink(this->m_sourceReference.GetDetails().Type, report_progress); + packageCatalogProgressSink->BeginProgress(); + ::AppInstaller::ProgressCallback progress(packageCatalogProgressSink.get()); this->m_sourceReference.Update(progress); + packageCatalogProgressSink->EndProgress(false); } catch (...) { diff --git a/src/Microsoft.Management.Deployment/PackageManager.cpp b/src/Microsoft.Management.Deployment/PackageManager.cpp index 47ad79bafa..ac6fa06a17 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.cpp +++ b/src/Microsoft.Management.Deployment/PackageManager.cpp @@ -37,6 +37,7 @@ #include "ContextOrchestrator.h" #include "AppInstallerRuntime.h" #include +#include using namespace std::literals::chrono_literals; using namespace ::AppInstaller::CLI; @@ -1330,18 +1331,13 @@ namespace winrt::Microsoft::Management::Deployment::implementation 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); + std::string type = winrt::to_string(options.Type()); + auto packageCatalogProgressSink = winrt::Microsoft::Management::Deployment::ProgressSinkFactory::CreatePackageCatalogProgressSink(type, report_progress ); + packageCatalogProgressSink->BeginProgress(); + ::AppInstaller::ProgressCallback progress(packageCatalogProgressSink.get()); sourceToAdd.Add(progress); + packageCatalogProgressSink->EndProgress(false); } catch (...) { @@ -1373,29 +1369,23 @@ namespace winrt::Microsoft::Management::Deployment::implementation 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 }; + auto packageCatalogProgressSink = winrt::Microsoft::Management::Deployment::ProgressSinkFactory::CreatePackageCatalogProgressSink(matchingSource.value().Type, report_progress, true); - 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); + packageCatalogProgressSink->BeginProgress(); + ::AppInstaller::Repository::Source sourceToRemove = ::AppInstaller::Repository::Source{ matchingSource.value().Name }; + ::AppInstaller::ProgressCallback progress(packageCatalogProgressSink.get()); // 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); + packageCatalogProgressSink->OnProgress(100, 100, AppInstaller::ProgressType::Percent); } else { sourceToRemove.Remove(progress); } + packageCatalogProgressSink->EndProgress(false); } catch (...) { From 2066dbfb1533705079d01798f77a3f3e6b59dd98 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Thu, 24 Oct 2024 10:43:19 -0700 Subject: [PATCH 35/38] [SpellCheck] Fix typo in `OnProgress` method parameter description Corrected a typo in the comment for the `maximum` parameter of the `OnProgress` method in `PackageCatalogProgress.h`. The word "progres" was corrected to "progress". --- src/Microsoft.Management.Deployment/PackageCatalogProgress.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Management.Deployment/PackageCatalogProgress.h b/src/Microsoft.Management.Deployment/PackageCatalogProgress.h index 4ec8716fb7..f6dfb5c396 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogProgress.h +++ b/src/Microsoft.Management.Deployment/PackageCatalogProgress.h @@ -58,7 +58,7 @@ namespace winrt::Microsoft::Management::Deployment /// Reports combined progress to caller when configured for multiple progress types. /// /// The current progress value. - /// The maximum progres value. + /// The maximum progress value. /// ProgressType for which progress is applicable. void OnProgress(uint64_t current, uint64_t maximum, AppInstaller::ProgressType type) override; void SetProgressMessage(std::string_view message) override; From 16ecf85ae9b237580b08fa1ca635d9654f5061df Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Thu, 24 Oct 2024 12:20:18 -0700 Subject: [PATCH 36/38] Add validation for progressReporter and improve map insertion - Added validation to ensure that the `progressReporter` function is not null in the constructors of `CompletionOnlyProgressSink` and `PreIndexedPackageCatalogProgressSink`. - If `progressReporter` is null, an `E_INVALIDARG` exception is thrown. - Modified the insertion of the default weight for `AppInstaller::ProgressType::Percent` in `PreIndexedPackageCatalogProgressSink` to use `insert_or_assign` instead of direct assignment for better robustness. --- .../PackageCatalogProgress.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Management.Deployment/PackageCatalogProgress.cpp b/src/Microsoft.Management.Deployment/PackageCatalogProgress.cpp index 83941b9f9d..7539a7593f 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogProgress.cpp +++ b/src/Microsoft.Management.Deployment/PackageCatalogProgress.cpp @@ -46,6 +46,10 @@ namespace winrt::Microsoft::Management::Deployment CompletionOnlyProgressSink::CompletionOnlyProgressSink(std::function progressReporter) : m_progressReporter(progressReporter) { + if (!m_progressReporter) + { + THROW_HR(E_INVALIDARG); + } } void CompletionOnlyProgressSink::OnProgress(uint64_t current, uint64_t maximum, AppInstaller::ProgressType type) @@ -74,10 +78,15 @@ namespace winrt::Microsoft::Management::Deployment PreIndexedPackageCatalogProgressSink::PreIndexedPackageCatalogProgressSink(std::unordered_map progressWeights, std::function progressReporter) : m_progressWeights(progressWeights), m_progressReporter(progressReporter) { + if (!m_progressReporter) + { + THROW_HR(E_INVALIDARG); + } + // If no weights are provided, default to percent. if (m_progressWeights.empty()) { - m_progressWeights[AppInstaller::ProgressType::Percent] = 1; + m_progressWeights.insert_or_assign(AppInstaller::ProgressType::Percent, 1.0); } // Calculate the total weight. From b5eae14b7fdda52a920f75091660a6fcca62d523 Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Thu, 24 Oct 2024 18:12:33 -0700 Subject: [PATCH 37/38] [PR Feedback] Refactor error handling and optimize data structures - Updated data structures for `progressWeights` to account for edge case. - Refined progress reporting logic to handle edge cases and ensure accurate tracking. - Replaced `std::wstring` with `hstring` in Add/Removal headers get a perf. benefits. - Updated exception types in tests to reflect actual exceptions thrown. - Removed unnecessary headers. --- .../Interop/PackageCatalogInterop.cs | 4 +- .../Public/AppInstallerProgress.h | 1 - .../AddPackageCatalogOptions.h | 8 +-- .../Converters.cpp | 2 - .../PackageCatalogProgress.cpp | 55 +++++++++++-------- .../PackageCatalogProgress.h | 4 +- .../PackageManager.cpp | 29 ++-------- .../PackageManager.idl | 14 +++++ .../RemovePackageCatalogOptions.h | 2 +- 9 files changed, 61 insertions(+), 58 deletions(-) diff --git a/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs b/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs index 23e133fb00..c38cb36f6b 100644 --- a/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs +++ b/src/AppInstallerCLIE2ETests/Interop/PackageCatalogInterop.cs @@ -77,7 +77,7 @@ public async Task AddRemovePackageCatalog() public void AddPackageCatalogWithInvalidOptions() { // Add package catalog with null options. - Assert.ThrowsAsync(async () => await this.packageManager.AddPackageCatalogAsync(null)); + Assert.ThrowsAsync(async () => await this.packageManager.AddPackageCatalogAsync(null)); // Add package catalog with empty options. Assert.ThrowsAsync(async () => await this.packageManager.AddPackageCatalogAsync(this.TestFactory.CreateAddPackageCatalogOptions())); @@ -235,7 +235,7 @@ public async Task AddRemovePackageCatalogWithPreserveDataFiledSet() public void RemovePackageCatalogWithInvalidOptions() { // Remove package catalog with null options. - Assert.ThrowsAsync(async () => await this.packageManager.RemovePackageCatalogAsync(null)); + Assert.ThrowsAsync(async () => await this.packageManager.RemovePackageCatalogAsync(null)); // Remove package catalog with empty options. Assert.ThrowsAsync(async () => await this.packageManager.RemovePackageCatalogAsync(this.TestFactory.CreateRemovePackageCatalogOptions())); diff --git a/src/AppInstallerCommonCore/Public/AppInstallerProgress.h b/src/AppInstallerCommonCore/Public/AppInstallerProgress.h index 5f9a08dcc2..7d7460b137 100644 --- a/src/AppInstallerCommonCore/Public/AppInstallerProgress.h +++ b/src/AppInstallerCommonCore/Public/AppInstallerProgress.h @@ -5,7 +5,6 @@ #include #include #include -#include namespace AppInstaller { diff --git a/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h index 91ec268cad..d7a32b774e 100644 --- a/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h +++ b/src/Microsoft.Management.Deployment/AddPackageCatalogOptions.h @@ -31,11 +31,11 @@ namespace winrt::Microsoft::Management::Deployment::implementation #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) private: - std::wstring m_name = L""; - std::wstring m_sourceUri = L""; - std::wstring m_type = L""; + hstring m_name = L""; + hstring m_sourceUri = L""; + hstring m_type = L""; winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel m_trustLevel = winrt::Microsoft::Management::Deployment::PackageCatalogTrustLevel::None; - std::wstring m_customHeader = L""; + hstring m_customHeader = L""; bool m_explicit = false; #endif }; diff --git a/src/Microsoft.Management.Deployment/Converters.cpp b/src/Microsoft.Management.Deployment/Converters.cpp index 5412dea8f9..08338dd306 100644 --- a/src/Microsoft.Management.Deployment/Converters.cpp +++ b/src/Microsoft.Management.Deployment/Converters.cpp @@ -510,8 +510,6 @@ namespace winrt::Microsoft::Management::Deployment::implementation 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); } diff --git a/src/Microsoft.Management.Deployment/PackageCatalogProgress.cpp b/src/Microsoft.Management.Deployment/PackageCatalogProgress.cpp index 7539a7593f..e82f1d7fdb 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogProgress.cpp +++ b/src/Microsoft.Management.Deployment/PackageCatalogProgress.cpp @@ -17,21 +17,21 @@ namespace winrt::Microsoft::Management::Deployment if (sourceType.empty() || Utility::CaseInsensitiveEquals( Repository::Microsoft::PredefinedInstalledSourceFactory::Type(), sourceType)) { - std::unordered_map progressWeights; + std::vector> progressWeights; - // There is no download operation for remove operation, so remove the download progress. + // There is no download operation for remove operation, so use only percentage based progress to account for uninstall. if (removeOperation) { // it is percentage based progress. - progressWeights.insert_or_assign(AppInstaller::ProgressType::Bytes, 0); + progressWeights.push_back(std::make_pair(AppInstaller::ProgressType::Percent, 1.0)); } else { // Add/Update operation has two progress types: // 1. Bytes for downloading index and // 2. Percent for index installation. - progressWeights.insert_or_assign(AppInstaller::ProgressType::Bytes, 0.7); - progressWeights.insert_or_assign(AppInstaller::ProgressType::Percent, 0.3); + progressWeights.push_back(std::make_pair(AppInstaller::ProgressType::Bytes, 0.7)); + progressWeights.push_back(std::make_pair(AppInstaller::ProgressType::Percent, 0.3)); } return std::make_shared(progressWeights, progressReporter); @@ -52,16 +52,12 @@ namespace winrt::Microsoft::Management::Deployment } } - void CompletionOnlyProgressSink::OnProgress(uint64_t current, uint64_t maximum, AppInstaller::ProgressType type) + void CompletionOnlyProgressSink::OnProgress(uint64_t /*current*/, uint64_t /*maximum*/, AppInstaller::ProgressType /*type*/) { - UNREFERENCED_PARAMETER(current); - UNREFERENCED_PARAMETER(maximum); - UNREFERENCED_PARAMETER(type); } - void CompletionOnlyProgressSink::SetProgressMessage(std::string_view message) + void CompletionOnlyProgressSink::SetProgressMessage(std::string_view /*message*/) { - UNREFERENCED_PARAMETER(message); } void CompletionOnlyProgressSink::BeginProgress() @@ -69,13 +65,12 @@ namespace winrt::Microsoft::Management::Deployment m_progressReporter(0); } - void CompletionOnlyProgressSink::EndProgress(bool hideProgressWhenDone) + void CompletionOnlyProgressSink::EndProgress(bool /*hideProgressWhenDone*/) { - UNREFERENCED_PARAMETER(hideProgressWhenDone); m_progressReporter(100); } - PreIndexedPackageCatalogProgressSink::PreIndexedPackageCatalogProgressSink(std::unordered_map progressWeights, std::function progressReporter) : + PreIndexedPackageCatalogProgressSink::PreIndexedPackageCatalogProgressSink(std::vector> progressWeights, std::function progressReporter) : m_progressWeights(progressWeights), m_progressReporter(progressReporter) { if (!m_progressReporter) @@ -86,7 +81,7 @@ namespace winrt::Microsoft::Management::Deployment // If no weights are provided, default to percent. if (m_progressWeights.empty()) { - m_progressWeights.insert_or_assign(AppInstaller::ProgressType::Percent, 1.0); + m_progressWeights.push_back(std::make_pair(AppInstaller::ProgressType::Percent, 1.0)); } // Calculate the total weight. @@ -117,30 +112,46 @@ namespace winrt::Microsoft::Management::Deployment m_progressValues[type] = progress; double totalProgress = 0.0; + double totalWeight = 0.0; // Calculate the total progress. for (const auto& [progressType, weight] : m_progressWeights) { + double progressValue = m_progressValues[progressType]; + + // [NOTE:] Sequential execution assumption & Handling incomplete progress reports : + // This progress calculation assumes that each operation is executed sequentially, meaning the download must be complete before + // the installation begins.If the download fails, the installation will not proceed.However, there may be cases where the previous + // operation completes successfully, but its onprogress callback does not report 100% completion(e.g., the last progress report for + // the download was at 90%, but the download is complete, and the installation has started).This can result in the total progress not + // reaching 100% after the last operation completes due to the gap in the previous operation's progress report.To handle this, consider + // the progress for the last operation as complete by assigning its full weight while computing progress for the following operation. + // For example, while computing progress for the installation, consider the download operation complete even if it did not report progress + // exactly at 100%. + if (progressValue != 0) + { + totalProgress = totalWeight; + } + // Adjust the total progress value based on the weight. - totalProgress += m_progressValues[progressType] * weight; + totalWeight += weight; + totalProgress += progressValue * weight; } m_progressReporter(totalProgress * 100); } - void PreIndexedPackageCatalogProgressSink::SetProgressMessage(std::string_view message) + void PreIndexedPackageCatalogProgressSink::SetProgressMessage(std::string_view /*message*/) { - UNREFERENCED_PARAMETER(message); } void PreIndexedPackageCatalogProgressSink::BeginProgress() { - OnProgress(0, 1, AppInstaller::ProgressType::None); + m_progressReporter(0); } - void PreIndexedPackageCatalogProgressSink::EndProgress(bool hideProgressWhenDone) + void PreIndexedPackageCatalogProgressSink::EndProgress(bool /*hideProgressWhenDone*/) { - UNREFERENCED_PARAMETER(hideProgressWhenDone); - OnProgress(1, 1, AppInstaller::ProgressType::None); + m_progressReporter(100); } } diff --git a/src/Microsoft.Management.Deployment/PackageCatalogProgress.h b/src/Microsoft.Management.Deployment/PackageCatalogProgress.h index f6dfb5c396..4f175d054e 100644 --- a/src/Microsoft.Management.Deployment/PackageCatalogProgress.h +++ b/src/Microsoft.Management.Deployment/PackageCatalogProgress.h @@ -52,7 +52,7 @@ namespace winrt::Microsoft::Management::Deployment /// /// ProgressType weight map. /// Callback function that reports progress to caller. - PreIndexedPackageCatalogProgressSink(std::unordered_map progressWeights, std::function progressReporter); + PreIndexedPackageCatalogProgressSink(std::vector> progressWeights, std::function progressReporter); /// /// Reports combined progress to caller when configured for multiple progress types. @@ -66,7 +66,7 @@ namespace winrt::Microsoft::Management::Deployment void EndProgress(bool hideProgressWhenDone) override; private: - std::unordered_map m_progressWeights; + std::vector> m_progressWeights; std::function m_progressReporter; std::unordered_map m_progressValues; }; diff --git a/src/Microsoft.Management.Deployment/PackageManager.cpp b/src/Microsoft.Management.Deployment/PackageManager.cpp index ac6fa06a17..e0b3c7c87d 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.cpp +++ b/src/Microsoft.Management.Deployment/PackageManager.cpp @@ -114,29 +114,11 @@ namespace winrt::Microsoft::Management::Deployment::implementation source.SetCustomHeader(customHeader); } - try - { - auto sourceInfo = source.GetInformation(); + 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 + if (sourceInfo.Authentication.Type == ::AppInstaller::Authentication::AuthenticationType::Unknown) { - THROW_HR(APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED); + THROW_HR(APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED); } return source; @@ -1314,7 +1296,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation LogStartupIfApplicable(); // options must be set. - THROW_HR_IF_NULL(E_INVALIDARG, options); + THROW_HR_IF_NULL(E_POINTER, options); THROW_HR_IF(E_INVALIDARG, options.Name().empty()); THROW_HR_IF(E_INVALIDARG, options.SourceUri().empty()); @@ -1352,7 +1334,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation LogStartupIfApplicable(); // options must be set. - THROW_HR_IF_NULL(E_INVALIDARG, options); + THROW_HR_IF_NULL(E_POINTER, options); THROW_HR_IF(E_INVALIDARG, options.Name().empty()); HRESULT terminationHR = S_OK; @@ -1379,7 +1361,6 @@ namespace winrt::Microsoft::Management::Deployment::implementation if (options.PreserveData()) { THROW_HR_IF(APPINSTALLER_CLI_ERROR_SOURCE_NAME_DOES_NOT_EXIST, !sourceToRemove.DropSource(matchingSource.value().Name)); - packageCatalogProgressSink->OnProgress(100, 100, AppInstaller::ProgressType::Percent); } else { diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl index 302e66fda5..268fde4327 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.idl +++ b/src/Microsoft.Management.Deployment/PackageManager.idl @@ -940,6 +940,11 @@ namespace Microsoft.Management.Deployment [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] { /// Updates the package catalog. + /// The progress value, represented as a double, indicates the percentage of operation completion. + /// For "Microsoft.PreIndexed.Package" Package Catalogs, it reflects the progress of downloading and + /// installing the index. When there is no meaningful progress to report for other Package Catalogs, + /// the progress will be set to 0% at the start and will be updated to 100% upon the operation's completion. + /// The progress range is from 0 to 100. Windows.Foundation.IAsyncOperationWithProgress RefreshPackageCatalogAsync(); } } @@ -1495,9 +1500,18 @@ namespace Microsoft.Management.Deployment [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] { /// Add a catalog to the Windows Package Catalogs. + /// The progress value, represented as a double, indicates the percentage of operation completion. + /// For "Microsoft.PreIndexed.Package" Package Catalogs, it reflects the progress of downloading and + /// installing the index. When there is no meaningful progress to report for other Package Catalogs, + /// the progress will be set to 0% at the start and will be updated to 100% upon the operation's completion. + /// The progress range is from 0 to 100. 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. + /// The progress value, represented as a double, indicates the percentage of operation completion.For "Microsoft.PreIndexed.Package" + /// Package Catalogs, it reflects the progress of uninstalling the index. When there is no meaningful progress to report for + /// other Package Catalogs, the progress will be set to 0% at the start and will be updated to 100% upon the operation's completion. + /// The progress range is from 0 to 100. Windows.Foundation.IAsyncOperationWithProgress RemovePackageCatalogAsync(RemovePackageCatalogOptions options); } diff --git a/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.h b/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.h index ba312a70fa..583043d6f1 100644 --- a/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.h +++ b/src/Microsoft.Management.Deployment/RemovePackageCatalogOptions.h @@ -19,7 +19,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) private: - std::wstring m_name = L""; + hstring m_name = L""; bool m_preserveData = false; #endif }; From 340200a933666687d54f4666d30a5eb1a144ddae Mon Sep 17 00:00:00 2001 From: Madhusudhan Gumbalapura Sudarshan Date: Fri, 25 Oct 2024 12:57:03 -0700 Subject: [PATCH 38/38] Update PackageManager.idl comments for async operations - Simplified documentation comments for RefreshPackageCatalogAsync, AddPackageCatalogAsync, and RemovePackageCatalogAsync to specify progress as a percentage (0-100). - Removed detailed explanation about progress reporting for "Microsoft.PreIndexed.Package" Package Catalogs (implementation details). --- .../PackageManager.idl | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl index 268fde4327..943177fc45 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.idl +++ b/src/Microsoft.Management.Deployment/PackageManager.idl @@ -940,10 +940,7 @@ namespace Microsoft.Management.Deployment [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] { /// Updates the package catalog. - /// The progress value, represented as a double, indicates the percentage of operation completion. - /// For "Microsoft.PreIndexed.Package" Package Catalogs, it reflects the progress of downloading and - /// installing the index. When there is no meaningful progress to report for other Package Catalogs, - /// the progress will be set to 0% at the start and will be updated to 100% upon the operation's completion. + /// The progress value, represented as a double, indicates the percentage of update package catalog operation completion. /// The progress range is from 0 to 100. Windows.Foundation.IAsyncOperationWithProgress RefreshPackageCatalogAsync(); } @@ -1500,17 +1497,12 @@ namespace Microsoft.Management.Deployment [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 12)] { /// Add a catalog to the Windows Package Catalogs. - /// The progress value, represented as a double, indicates the percentage of operation completion. - /// For "Microsoft.PreIndexed.Package" Package Catalogs, it reflects the progress of downloading and - /// installing the index. When there is no meaningful progress to report for other Package Catalogs, - /// the progress will be set to 0% at the start and will be updated to 100% upon the operation's completion. + /// The progress value, represented as a double, indicates the percentage of add package catalog operation completion. /// The progress range is from 0 to 100. 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. - /// The progress value, represented as a double, indicates the percentage of operation completion.For "Microsoft.PreIndexed.Package" - /// Package Catalogs, it reflects the progress of uninstalling the index. When there is no meaningful progress to report for - /// other Package Catalogs, the progress will be set to 0% at the start and will be updated to 100% upon the operation's completion. + /// The progress value, represented as a double, indicates the percentage of remove package catalog operation completion. /// The progress range is from 0 to 100. Windows.Foundation.IAsyncOperationWithProgress RemovePackageCatalogAsync(RemovePackageCatalogOptions options); }