From 50412ff73a7d9d4f9ca267630f4c210a874fb122 Mon Sep 17 00:00:00 2001 From: Yao Sun Date: Mon, 4 Apr 2022 15:29:18 -0700 Subject: [PATCH 1/9] build --- .../Public/AppInstallerRuntime.h | 2 + .../Public/winget/UserSettings.h | 7 +- src/AppInstallerCommonCore/Runtime.cpp | 34 +++++++ src/AppInstallerCommonCore/UserSettings.cpp | 99 ++++++++++++------- .../Client.PackageManagerSettings.h | 13 +++ ...osoft.Management.Deployment.Client.vcxproj | 2 + .../PackageManagerSettings.cpp | 25 +++++ .../ComClsids.cpp | 5 + .../Microsoft.Management.Deployment.vcxproj | 2 + ...soft.Management.Deployment.vcxproj.filters | 2 + .../PackageManager.cpp | 19 +++- .../PackageManager.h | 4 + .../PackageManager.idl | 26 +++++ .../PackageManagerSettings.cpp | 56 +++++++++++ .../PackageManagerSettings.h | 28 ++++++ .../Public/ComClsids.h | 6 +- src/Microsoft.Management.Deployment/pch.h | 2 + src/WindowsPackageManager/main.cpp | 1 + 18 files changed, 296 insertions(+), 37 deletions(-) create mode 100644 src/Microsoft.Management.Deployment.Client/Client.PackageManagerSettings.h create mode 100644 src/Microsoft.Management.Deployment.Client/PackageManagerSettings.cpp create mode 100644 src/Microsoft.Management.Deployment/PackageManagerSettings.cpp create mode 100644 src/Microsoft.Management.Deployment/PackageManagerSettings.h diff --git a/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h b/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h index b399c6b9aa..43ed51d04a 100644 --- a/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h +++ b/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h @@ -55,6 +55,8 @@ namespace AppInstaller::Runtime PortableAppMachineRootX86, }; + void SetRuntimePathStateName(std::string name); + // Gets the path to the requested location. std::filesystem::path GetPathTo(PathName path); diff --git a/src/AppInstallerCommonCore/Public/winget/UserSettings.h b/src/AppInstallerCommonCore/Public/winget/UserSettings.h index 5c6898e0ec..7272cad579 100644 --- a/src/AppInstallerCommonCore/Public/winget/UserSettings.h +++ b/src/AppInstallerCommonCore/Public/winget/UserSettings.h @@ -30,6 +30,8 @@ namespace AppInstaller::Settings Standard, // Loaded settings.json.backup Backup, + // Loaded from custom settings content + Custom, }; // The visual style of the progress bar. @@ -172,7 +174,7 @@ namespace AppInstaller::Settings bool IsFieldWarning = true; }; - static UserSettings const& Instance(); + static UserSettings const& Instance(const std::optional& content = std::nullopt); static std::filesystem::path SettingsFilePath(); @@ -205,10 +207,11 @@ namespace AppInstaller::Settings std::vector m_warnings; std::map m_settings; - UserSettings(); + UserSettings(const std::optional& content = std::nullopt); ~UserSettings() = default; }; const UserSettings* TryGetUser(); UserSettings const& User(); + bool TryInitializeCustomUserSettings(std::string content); } diff --git a/src/AppInstallerCommonCore/Runtime.cpp b/src/AppInstallerCommonCore/Runtime.cpp index 8adf34826f..e80eca028d 100644 --- a/src/AppInstallerCommonCore/Runtime.cpp +++ b/src/AppInstallerCommonCore/Runtime.cpp @@ -31,6 +31,10 @@ namespace AppInstaller::Runtime constexpr std::string_view s_SecureSettings_Relative_Packaged = "pkg"sv; #endif constexpr std::string_view s_PreviewBuildSuffix = "-preview"sv; + constexpr std::string_view s_RuntimePath_Unpackaged_DefaultState = "defaultState"sv; + + static std::optional s_runtimePathStateName; + static wil::srwlock s_runtimePathStateNameLock; // Gets a boolean indicating whether the current process has identity. bool DoesCurrentProcessHaveIdentity() @@ -139,6 +143,24 @@ namespace AppInstaller::Runtime THROW_IF_WIN32_BOOL_FALSE(ConvertSidToStringSidW(userToken->User.Sid, &sidString)); return { sidString.get() }; } + + std::string GetRuntimePathStateName() + { + std::string result; + auto lock = s_runtimePathStateNameLock.lock_shared(); + + if (s_runtimePathStateName.has_value()) + { + result = s_runtimePathStateName.value(); + } + + if (Utility::IsEmptyOrWhitespace(result)) + { + result = s_RuntimePath_Unpackaged_DefaultState; + } + + return result; + } } bool IsRunningInPackagedContext() @@ -239,6 +261,13 @@ namespace AppInstaller::Runtime } #endif + void SetRuntimePathStateName(std::string name) + { + auto suitablePathPart = MakeSuitablePathPart(name); + auto lock = s_runtimePathStateNameLock.lock_exclusive(); + s_runtimePathStateName.emplace(std::move(suitablePathPart)); + } + std::filesystem::path GetPathTo(PathName path) { std::filesystem::path result; @@ -358,19 +387,23 @@ namespace AppInstaller::Runtime { result = GetPathToUserTemp(); result /= s_DefaultTempDirectory; + result /= GetRuntimePathStateName(); } break; case PathName::DefaultLogLocationForDisplay: result.assign("%TEMP%"); result /= s_DefaultTempDirectory; + result /= GetRuntimePathStateName(); create = false; break; case PathName::LocalState: result = GetPathToAppDataDir(s_AppDataDir_State); + result /= GetRuntimePathStateName(); break; case PathName::StandardSettings: case PathName::UserFileSettings: result = GetPathToAppDataDir(s_AppDataDir_Settings); + result /= GetRuntimePathStateName(); break; case PathName::SecureSettings: result = GetKnownFolderPath(FOLDERID_ProgramData); @@ -378,6 +411,7 @@ namespace AppInstaller::Runtime result /= GetUserSID(); result /= s_SecureSettings_UserRelative; result /= s_SecureSettings_Relative_Unpackaged; + result /= GetRuntimePathStateName(); create = false; break; case PathName::UserProfile: diff --git a/src/AppInstallerCommonCore/UserSettings.cpp b/src/AppInstallerCommonCore/UserSettings.cpp index 36f40aabe3..c8b50d3838 100644 --- a/src/AppInstallerCommonCore/UserSettings.cpp +++ b/src/AppInstallerCommonCore/UserSettings.cpp @@ -72,25 +72,31 @@ namespace AppInstaller::Settings return convertedValue; } + std::optional ParseSettingsContent(const std::string& content, std::string_view settingName, std::vector& warnings) + { + Json::Value root; + Json::CharReaderBuilder builder; + const std::unique_ptr reader(builder.newCharReader()); + std::string error; + + if (reader->parse(content.c_str(), content.c_str() + content.size(), &root, &error)) + { + return root; + } + + AICLI_LOG(Core, Error, << "Error parsing " << settingName << ": " << error); + warnings.emplace_back(StringResource::String::SettingsWarningParseError, settingName, error, false); + + return {}; + } + std::optional ParseFile(const StreamDefinition& setting, std::vector& warnings) { auto stream = Stream{ setting }.Get(); if (stream) { - Json::Value root; - Json::CharReaderBuilder builder; - const std::unique_ptr reader(builder.newCharReader()); - std::string settingsContentStr = Utility::ReadEntireStream(*stream); - std::string error; - - if (reader->parse(settingsContentStr.c_str(), settingsContentStr.c_str() + settingsContentStr.size(), &root, &error)) - { - return root; - } - - AICLI_LOG(Core, Error, << "Error parsing " << setting.Name << ": " << error); - warnings.emplace_back(StringResource::String::SettingsWarningParseError, setting.Name, error, false); + return ParseSettingsContent(settingsContentStr, setting.Name, warnings); } return {}; @@ -382,7 +388,7 @@ namespace AppInstaller::Settings static std::atomic_bool s_userSettingsInitialized{ false }; static std::atomic_bool s_userSettingsInInitialization{ false }; - UserSettings const& UserSettings::Instance() + UserSettings const& UserSettings::Instance(const std::optional& content) { #ifndef AICLI_DISABLE_TEST_HOOKS if (s_UserSettings_Override) @@ -395,7 +401,7 @@ namespace AppInstaller::Settings s_userSettingsInInitialization = true; } - static UserSettings userSettings; + static UserSettings userSettings(content); s_userSettingsInitialized = true; s_userSettingsInInitialization = false; @@ -423,15 +429,29 @@ namespace AppInstaller::Settings return UserSettings::Instance(); } - UserSettings::UserSettings() : m_type(UserSettingsType::Default) + bool TryInitializeCustomUserSettings(std::string content) + { + if (s_userSettingsInitialized || s_userSettingsInInitialization) + { + return false; + } + + return UserSettings::Instance(std::move(content)).GetType() == UserSettingsType::Custom; + } + + UserSettings::UserSettings(const std::optional& content) : m_type(UserSettingsType::Default) { Json::Value settingsRoot = Json::Value::nullSingleton(); // Settings can be loaded from settings.json or settings.json.backup files. // 0 - Use default (empty) settings if disabled by group policy. - // 1 - Use settings.json if exists and passes parsing. - // 2 - Use settings.backup.json if settings.json fails to parse. - // 3 - Use default (empty) if both settings files fail to load. + // if + // 1 - Use passed in settings content if available. + // else + // 2 - Use settings.json if exists and passes parsing. + // 3 - Use settings.backup.json if settings.json fails to parse. + // finally + // 4 - Use default (empty) if both settings files fail to load. if (!GroupPolicies().IsEnabled(TogglePolicy::Policy::Settings)) { @@ -439,24 +459,37 @@ namespace AppInstaller::Settings return; } - auto settingsJson = ParseFile(Stream::PrimaryUserSettings, m_warnings); - if (settingsJson.has_value()) + if (content.has_value()) { - AICLI_LOG(Core, Info, << "Settings loaded from " << Stream::PrimaryUserSettings.Name); - m_type = UserSettingsType::Standard; - settingsRoot = settingsJson.value(); + auto settingsJson = ParseSettingsContent(content.value(), "CustomSettings", m_warnings); + if (settingsJson.has_value()) + { + AICLI_LOG(Core, Info, << "Settings loaded from custom settings"); + m_type = UserSettingsType::Custom; + settingsRoot = settingsJson.value(); + } } - - // Settings didn't parse or doesn't exist, try with backup. - if (settingsRoot.isNull()) + else { - auto settingsBackupJson = ParseFile(Stream::BackupUserSettings, m_warnings); - if (settingsBackupJson.has_value()) + auto settingsJson = ParseFile(Stream::PrimaryUserSettings, m_warnings); + if (settingsJson.has_value()) { - AICLI_LOG(Core, Info, << "Settings loaded from " << Stream::BackupUserSettings.Name); - m_warnings.emplace_back(StringResource::String::SettingsWarningLoadedBackupSettings); - m_type = UserSettingsType::Backup; - settingsRoot = settingsBackupJson.value(); + AICLI_LOG(Core, Info, << "Settings loaded from " << Stream::PrimaryUserSettings.Name); + m_type = UserSettingsType::Standard; + settingsRoot = settingsJson.value(); + } + + // Settings didn't parse or doesn't exist, try with backup. + if (settingsRoot.isNull()) + { + auto settingsBackupJson = ParseFile(Stream::BackupUserSettings, m_warnings); + if (settingsBackupJson.has_value()) + { + AICLI_LOG(Core, Info, << "Settings loaded from " << Stream::BackupUserSettings.Name); + m_warnings.emplace_back(StringResource::String::SettingsWarningLoadedBackupSettings); + m_type = UserSettingsType::Backup; + settingsRoot = settingsBackupJson.value(); + } } } diff --git a/src/Microsoft.Management.Deployment.Client/Client.PackageManagerSettings.h b/src/Microsoft.Management.Deployment.Client/Client.PackageManagerSettings.h new file mode 100644 index 0000000000..498dc89a12 --- /dev/null +++ b/src/Microsoft.Management.Deployment.Client/Client.PackageManagerSettings.h @@ -0,0 +1,13 @@ +#pragma once +#include "PackageManagerSettings.g.h" + +namespace winrt::Microsoft::Management::Deployment::factory_implementation +{ + struct PackageManagerSettings : PackageManagerSettingsT + { + auto ActivateInstance() const + { + return winrt::create_instance(__uuidof(implementation::PackageManagerSettings), CLSCTX_ALL); + } + }; +} diff --git a/src/Microsoft.Management.Deployment.Client/Microsoft.Management.Deployment.Client.vcxproj b/src/Microsoft.Management.Deployment.Client/Microsoft.Management.Deployment.Client.vcxproj index 1994278418..52db0ac661 100644 --- a/src/Microsoft.Management.Deployment.Client/Microsoft.Management.Deployment.Client.vcxproj +++ b/src/Microsoft.Management.Deployment.Client/Microsoft.Management.Deployment.Client.vcxproj @@ -129,6 +129,7 @@ + @@ -141,6 +142,7 @@ + Create diff --git a/src/Microsoft.Management.Deployment.Client/PackageManagerSettings.cpp b/src/Microsoft.Management.Deployment.Client/PackageManagerSettings.cpp new file mode 100644 index 0000000000..bb6d993c5e --- /dev/null +++ b/src/Microsoft.Management.Deployment.Client/PackageManagerSettings.cpp @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#pragma warning( push ) +#pragma warning ( disable : 4467 6388) +#include +#include +#pragma warning( pop ) +#include "PackageManagerSettings.g.cpp" + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + bool PackageManagerSettings::SetCallerIdentifier(hstring const&) + { + throw hresult_not_implemented(); + } + bool PackageManagerSettings::SetStateIdentifier(hstring const&) + { + throw hresult_not_implemented(); + } + bool PackageManagerSettings::SetUserSettings(hstring const&) + { + throw hresult_not_implemented(); + } +} diff --git a/src/Microsoft.Management.Deployment/ComClsids.cpp b/src/Microsoft.Management.Deployment/ComClsids.cpp index b02dd3d2ae..35e774070f 100644 --- a/src/Microsoft.Management.Deployment/ComClsids.cpp +++ b/src/Microsoft.Management.Deployment/ComClsids.cpp @@ -11,6 +11,7 @@ #include "InstallOptions.h" #include "UninstallOptions.h" #include "PackageMatchFilter.h" +#include "PackageManagerSettings.h" #pragma warning( pop ) namespace winrt::Microsoft::Management::Deployment @@ -41,6 +42,10 @@ namespace winrt::Microsoft::Management::Deployment { return __uuidof(winrt::Microsoft::Management::Deployment::implementation::PackageMatchFilter); } + else if (IsEqualCLSID(clsid, WINGET_INPROC_COM_CLSID_PackageManagerSettings)) + { + return __uuidof(winrt::Microsoft::Management::Deployment::implementation::PackageManagerSettings); + } else { return CLSID_NULL; diff --git a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj index 4613289587..3d9be32869 100644 --- a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj +++ b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj @@ -150,6 +150,7 @@ + @@ -174,6 +175,7 @@ + diff --git a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters index 18aa3e0a7b..bb03d687bf 100644 --- a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters +++ b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters @@ -23,6 +23,7 @@ + @@ -48,6 +49,7 @@ Public + diff --git a/src/Microsoft.Management.Deployment/PackageManager.cpp b/src/Microsoft.Management.Deployment/PackageManager.cpp index a4ec730dea..f9702387ba 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.cpp +++ b/src/Microsoft.Management.Deployment/PackageManager.cpp @@ -38,6 +38,18 @@ using namespace ::AppInstaller::CLI::Execution; namespace winrt::Microsoft::Management::Deployment::implementation { + namespace + { + static std::optional s_callerName; + static wil::srwlock s_callerNameLock; + } + + void SetComCallerName(std::string name) + { + auto lock = s_callerNameLock.lock_exclusive(); + s_callerName.emplace(std::move(name)); + } + winrt::Windows::Foundation::Collections::IVectorView PackageManager::GetPackageCatalogs() { Windows::Foundation::Collections::IVector catalogs{ winrt::single_threaded_vector() }; @@ -415,7 +427,12 @@ namespace winrt::Microsoft::Management::Deployment::implementation { std::unique_ptr context = std::make_unique(); hstring correlationData = (options) ? options.CorrelationData() : L""; - context->SetContextLoggers(correlationData, ::AppInstaller::Utility::ConvertToUTF8(callerProcessInfoString)); + std::string callerName; + { + auto lock = s_callerNameLock.lock_shared(); + callerName = s_callerName.has_value() ? s_callerName.value() : AppInstaller::Utility::ConvertToUTF8(callerProcessInfoString); + } + context->SetContextLoggers(correlationData, callerName); // Convert the options to arguments for the installer. if constexpr (std::is_same_v) diff --git a/src/Microsoft.Management.Deployment/PackageManager.h b/src/Microsoft.Management.Deployment/PackageManager.h index bc40538b59..4e896da3ad 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.h +++ b/src/Microsoft.Management.Deployment/PackageManager.h @@ -29,6 +29,10 @@ namespace winrt::Microsoft::Management::Deployment::implementation winrt::Windows::Foundation::IAsyncOperationWithProgress GetUninstallProgress(winrt::Microsoft::Management::Deployment::CatalogPackage package, winrt::Microsoft::Management::Deployment::PackageCatalogInfo catalogInfo); }; + +#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) + void SetComCallerName(std::string name); +#endif } #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl index f39b28accd..21176415f9 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.idl +++ b/src/Microsoft.Management.Deployment/PackageManager.idl @@ -684,6 +684,32 @@ namespace Microsoft.Management.Deployment } } + /// Global settings for PackageManager operations. + /// This settings should be invoked prior to invocation of PackageManager class. + /// This settings is only exposed in in-proc Com invocation. + [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 4)] + runtimeclass PackageManagerSettings + { + PackageManagerSettings(); + + /// Sets caller name to be used in telemetry logging. Default value is the calling process name. + /// Call this before any PackageManager operations. + /// Returns true if successful, false if caller name is already set. + /// This is a one time setup, multiple calls will not override existing caller name. + Boolean SetCallerIdentifier(String callerIdentifier); + + /// Sets state name for state separation. If not set, state will be written in a default location and states may be affected by other callers. + /// Call this before any PackageManager operations. + /// Returns true if successful, false if state name is already set. + /// This is a one time setup, multiple calls will not override existing state name. + Boolean SetStateIdentifier(String stateIdentifier); + + /// Sets custom UserSettings. + /// Returns true if successful, false if settingsContent cannot be parsed or UserSettings is already created. + /// This is a one time setup, multiple calls will not override existing UserSettings. + Boolean SetUserSettings(String settingsContent); + } + /// Force midl3 to generate vector marshalling info. declare { diff --git a/src/Microsoft.Management.Deployment/PackageManagerSettings.cpp b/src/Microsoft.Management.Deployment/PackageManagerSettings.cpp new file mode 100644 index 0000000000..9b76a9d8e8 --- /dev/null +++ b/src/Microsoft.Management.Deployment/PackageManagerSettings.cpp @@ -0,0 +1,56 @@ +// 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 "PackageManager.h" +#include "PackageManagerSettings.h" +#pragma warning( pop ) +#include "PackageManagerSettings.g.cpp" +#include "Helpers.h" +#include +#include + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + bool PackageManagerSettings::SetCallerIdentifier(hstring const& callerIdentifier) + { + bool success = false; + static std::once_flag setCallerOnceFlag; + std::call_once(setCallerOnceFlag, + [&]() + { + SetComCallerName(AppInstaller::Utility::ConvertToUTF8(callerIdentifier)); + success = true; + }); + return success; + } + bool PackageManagerSettings::SetStateIdentifier(hstring const& stateIdentifier) + { + bool success = false; + static std::once_flag setStateOnceFlag; + std::call_once(setStateOnceFlag, + [&]() + { + AppInstaller::Runtime::SetRuntimePathStateName(AppInstaller::Utility::ConvertToUTF8(stateIdentifier)); + success = true; + }); + return success; + } + bool PackageManagerSettings::SetUserSettings(hstring const& settingsContent) + { + bool success = false; + static std::once_flag setSettingsOnceFlag; + std::call_once(setSettingsOnceFlag, + [&]() + { + success = AppInstaller::Settings::TryInitializeCustomUserSettings(AppInstaller::Utility::ConvertToUTF8(settingsContent)); + }); + return success; + } + + CoCreatableMicrosoftManagementDeploymentClass(PackageManagerSettings); +} diff --git a/src/Microsoft.Management.Deployment/PackageManagerSettings.h b/src/Microsoft.Management.Deployment/PackageManagerSettings.h new file mode 100644 index 0000000000..9504efdaf9 --- /dev/null +++ b/src/Microsoft.Management.Deployment/PackageManagerSettings.h @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once +#include "PackageManagerSettings.g.h" +#include "Public/ComClsids.h" + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + [uuid(WINGET_INPROC_ONLY_COM_CLSID_PackageManagerSettings)] + struct PackageManagerSettings : PackageManagerSettingsT + { + PackageManagerSettings() = default; + + // Contract 4.0 + bool SetCallerIdentifier(hstring const& callerIdentifier); + bool SetStateIdentifier(hstring const& stateIdentifier); + bool SetUserSettings(hstring const& settingsContent); + }; +} + +#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) +namespace winrt::Microsoft::Management::Deployment::factory_implementation +{ + struct PackageManagerSettings : PackageManagerSettingsT + { + }; +} +#endif diff --git a/src/Microsoft.Management.Deployment/Public/ComClsids.h b/src/Microsoft.Management.Deployment/Public/ComClsids.h index aa04828bc6..144ddb351e 100644 --- a/src/Microsoft.Management.Deployment/Public/ComClsids.h +++ b/src/Microsoft.Management.Deployment/Public/ComClsids.h @@ -3,7 +3,7 @@ #pragma once #include -// clsids for out-of-proc com invocation +// Clsids for out-of-proc com invocation #if USE_PROD_CLSIDS #define WINGET_OUTOFPROC_COM_CLSID_PackageManager "C53A4F16-787E-42A4-B304-29EFFB4BF597" #define WINGET_OUTOFPROC_COM_CLSID_FindPackagesOptions "572DED96-9C60-4526-8F92-EE7D91D38C1A" @@ -20,6 +20,9 @@ #define WINGET_OUTOFPROC_COM_CLSID_PackageMatchFilter "3F85B9F4-487A-4C48-9035-2903F8A6D9E8" #endif +// Clsids only used in in-proc invocation +#define WINGET_INPROC_ONLY_COM_CLSID_PackageManagerSettings "80CF9D63-5505-4342-B9B4-BB87895CA8BB" + namespace winrt::Microsoft::Management::Deployment { // clsid constants for in-proc com invocation @@ -29,6 +32,7 @@ namespace winrt::Microsoft::Management::Deployment const CLSID WINGET_INPROC_COM_CLSID_InstallOptions = { 0xE2AF3BA8, 0x8A88, 0x4766, 0x9D, 0xDA, 0xAE, 0x40, 0x13, 0xAD, 0xE2, 0x86 }; // E2AF3BA8-8A88-4766-9DDA-AE4013ADE286 const CLSID WINGET_INPROC_COM_CLSID_UninstallOptions = { 0x869CB959, 0xEB54, 0x425C, 0xA1, 0xE4, 0x1A, 0x1C, 0x29, 0x1C, 0x64, 0xE9 }; // 869CB959-EB54-425C-A1E4-1A1C291C64E9 const CLSID WINGET_INPROC_COM_CLSID_PackageMatchFilter = { 0x57DC8962, 0x7343, 0x42CD, 0xB9, 0x1C, 0x04, 0xF6, 0xA2, 0x5D, 0xB1, 0xD0 }; // 57DC8962-7343-42CD-B91C-04F6A25DB1D0 + const CLSID WINGET_INPROC_COM_CLSID_PackageManagerSettings = { 0x80CF9D63, 0x5505, 0x4342, 0xB9, 0xB4, 0xBB, 0x87, 0x89, 0x5C, 0xA8, 0xBB }; // 80CF9D63-5505-4342-B9B4-BB87895CA8BB CLSID GetRedirectedClsidFromInProcClsid(REFCLSID clsid); } \ No newline at end of file diff --git a/src/Microsoft.Management.Deployment/pch.h b/src/Microsoft.Management.Deployment/pch.h index c25df203ef..a12993ff40 100644 --- a/src/Microsoft.Management.Deployment/pch.h +++ b/src/Microsoft.Management.Deployment/pch.h @@ -4,3 +4,5 @@ #include #include #include + +#include \ No newline at end of file diff --git a/src/WindowsPackageManager/main.cpp b/src/WindowsPackageManager/main.cpp index 9dc5cb4485..edad9eee60 100644 --- a/src/WindowsPackageManager/main.cpp +++ b/src/WindowsPackageManager/main.cpp @@ -21,6 +21,7 @@ CoCreatableClassWrlCreatorMapInclude(CreateCompositePackageCatalogOptions); CoCreatableClassWrlCreatorMapInclude(InstallOptions); CoCreatableClassWrlCreatorMapInclude(UninstallOptions); CoCreatableClassWrlCreatorMapInclude(PackageMatchFilter); +CoCreatableClassWrlCreatorMapInclude(PackageManagerSettings); extern "C" { From ac09b039f70f1a5177783c98edae26ee8c62ebeb Mon Sep 17 00:00:00 2001 From: Yao Sun Date: Mon, 4 Apr 2022 17:03:29 -0700 Subject: [PATCH 2/9] fix invoc --- .../Microsoft.Management.Deployment.InProc.dll.manifest | 4 ++++ src/WindowsPackageManager/main.cpp | 2 +- 2 files changed, 5 insertions(+), 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 341f7a73ad..0ed258d962 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 @@ -31,6 +31,10 @@ clsid="{57DC8962-7343-42CD-B91C-04F6A25DB1D0}" threadingModel="Both" description="PackageMatchFilter"/> + diff --git a/src/WindowsPackageManager/main.cpp b/src/WindowsPackageManager/main.cpp index edad9eee60..f0c69cd613 100644 --- a/src/WindowsPackageManager/main.cpp +++ b/src/WindowsPackageManager/main.cpp @@ -14,7 +14,7 @@ using namespace winrt::Microsoft::Management::Deployment; -// CreatorMap for out-of-proc com registration +// CreatorMap for out-of-proc com registration and direct in-proc com class construction CoCreatableClassWrlCreatorMapInclude(PackageManager); CoCreatableClassWrlCreatorMapInclude(FindPackagesOptions); CoCreatableClassWrlCreatorMapInclude(CreateCompositePackageCatalogOptions); From d46da9a4a33ae77f42fd1c3771bd351eb20e577d Mon Sep 17 00:00:00 2001 From: Yao Sun Date: Mon, 4 Apr 2022 18:11:35 -0700 Subject: [PATCH 3/9] Run tests under system --- azure-pipelines.yml | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 65e4bdb602..c432dbf7ba 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -143,13 +143,19 @@ jobs: inputs: packageFeedSelector: 'nugetOrg' - # - task: CmdLine@2 - # displayName: Run Unit Tests Unpackaged - # inputs: - # script: | - # AppInstallerCLITests.exe -logto $(artifactsDir)\AICLI-Unpackaged.log -s -r junit -o $(artifactsDir)\TEST-AppInstallerCLI-Unpackaged.xml - # workingDirectory: '$(buildOutDir)\AppInstallerCLITests' - # continueOnError: true + - task: DownloadSecureFile@1 + name: PsExec + displayName: 'Download PsExec.exe' + inputs: + secureFile: 'PsExec.exe' + + - task: CmdLine@2 + displayName: Run Unit Tests Unpackaged Under System Context + inputs: + script: | + $(PsExec.secureFilePath) -s -i AppInstallerCLITests.exe -logto $(artifactsDir)\AICLI-Unpackaged-System.log -s -r junit -o $(artifactsDir)\TEST-AppInstallerCLI-Unpackaged-System.xml + workingDirectory: '$(buildOutDir)\AppInstallerCLITests' + continueOnError: true - task: PowerShell@2 displayName: Run Unit Tests Packaged From c2fd1bdc03bf37361149c6a4082abe9e1206b01d Mon Sep 17 00:00:00 2001 From: Yao Sun Date: Mon, 4 Apr 2022 18:51:45 -0700 Subject: [PATCH 4/9] accept eula --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c432dbf7ba..a3b24598ae 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -153,7 +153,7 @@ jobs: displayName: Run Unit Tests Unpackaged Under System Context inputs: script: | - $(PsExec.secureFilePath) -s -i AppInstallerCLITests.exe -logto $(artifactsDir)\AICLI-Unpackaged-System.log -s -r junit -o $(artifactsDir)\TEST-AppInstallerCLI-Unpackaged-System.xml + $(PsExec.secureFilePath) -accepteula -s -i AppInstallerCLITests.exe -logto $(artifactsDir)\AICLI-Unpackaged-System.log -s -r junit -o $(artifactsDir)\TEST-AppInstallerCLI-Unpackaged-System.xml workingDirectory: '$(buildOutDir)\AppInstallerCLITests' continueOnError: true From 91750de450d52c819d4a307e2093e100ad4998a9 Mon Sep 17 00:00:00 2001 From: Yao Sun Date: Mon, 4 Apr 2022 19:32:27 -0700 Subject: [PATCH 5/9] spelling and fix --- .github/actions/spelling/expect.txt | 1 + azure-pipelines.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index 9a8ca91dc7..2ba11ce311 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -1,4 +1,5 @@ abcd +accepteula adjacents activatable adml diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a3b24598ae..6803198c81 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -153,7 +153,7 @@ jobs: displayName: Run Unit Tests Unpackaged Under System Context inputs: script: | - $(PsExec.secureFilePath) -accepteula -s -i AppInstallerCLITests.exe -logto $(artifactsDir)\AICLI-Unpackaged-System.log -s -r junit -o $(artifactsDir)\TEST-AppInstallerCLI-Unpackaged-System.xml + $(PsExec.secureFilePath) -accepteula -s -i $(buildOutDir)\AppInstallerCLITests\AppInstallerCLITests.exe -logto $(artifactsDir)\AICLI-Unpackaged-System.log -s -r junit -o $(artifactsDir)\TEST-AppInstallerCLI-Unpackaged-System.xml workingDirectory: '$(buildOutDir)\AppInstallerCLITests' continueOnError: true From 6c71354b542d437ed13f0c546fc0b881efa38132 Mon Sep 17 00:00:00 2001 From: Yao Sun Date: Tue, 5 Apr 2022 13:56:44 -0700 Subject: [PATCH 6/9] try 2022 --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 6803198c81..f5dcf6d3b8 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -13,7 +13,7 @@ pr: - src/* pool: - vmImage: 'windows-2019' + vmImage: 'windows-latest' variables: solution: 'src\AppInstallerCLI.sln' From aaf8d9abbda7edbd41a95131488729705e73690e Mon Sep 17 00:00:00 2001 From: Yao Sun Date: Tue, 5 Apr 2022 15:48:03 -0700 Subject: [PATCH 7/9] try fix build --- src/WinGetServer/WinMain.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/WinGetServer/WinMain.cpp b/src/WinGetServer/WinMain.cpp index 2b341a3098..2d5077827d 100644 --- a/src/WinGetServer/WinMain.cpp +++ b/src/WinGetServer/WinMain.cpp @@ -1,6 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#pragma warning( push ) +#pragma warning ( disable : 6553) #include +#pragma warning( pop ) #include #include #include From ac60c80f7768441d28148be0cf245efdc7dcf359 Mon Sep 17 00:00:00 2001 From: Yao Sun Date: Tue, 5 Apr 2022 16:52:50 -0700 Subject: [PATCH 8/9] Update nuget pipeline too --- azure-pipelines.nuget.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.nuget.yml b/azure-pipelines.nuget.yml index 48744699ed..fe6b77e01f 100644 --- a/azure-pipelines.nuget.yml +++ b/azure-pipelines.nuget.yml @@ -6,7 +6,7 @@ parameters: type: string pool: - vmImage: "windows-2019" + vmImage: "windows-latest" variables: solution: "src/AppInstallerCLI.sln" From 4d82734184ddbb4ea5609ff6719a764dd51a0daf Mon Sep 17 00:00:00 2001 From: Yao Sun Date: Thu, 7 Apr 2022 17:16:57 -0700 Subject: [PATCH 9/9] Take InstallOptions for applicability check --- src/Microsoft.Management.Deployment/PackageManager.h | 9 +++++++++ src/Microsoft.Management.Deployment/PackageManager.idl | 2 +- .../PackageVersionInfo.cpp | 8 +++++++- src/Microsoft.Management.Deployment/PackageVersionInfo.h | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.Management.Deployment/PackageManager.h b/src/Microsoft.Management.Deployment/PackageManager.h index 4e896da3ad..d73c69277f 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.h +++ b/src/Microsoft.Management.Deployment/PackageManager.h @@ -4,6 +4,14 @@ #include "PackageManager.g.h" #include "Public/ComClsids.h" +#if !defined(INCLUDE_ONLY_INTERFACE_METHODS) +// Forward declaration +namespace AppInstaller::CLI::Execution +{ + struct Context; +} +#endif + namespace winrt::Microsoft::Management::Deployment::implementation { [uuid(WINGET_OUTOFPROC_COM_CLSID_PackageManager)] @@ -32,6 +40,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) void SetComCallerName(std::string name); + void PopulateContextFromInstallOptions(AppInstaller::CLI::Execution::Context* context, winrt::Microsoft::Management::Deployment::InstallOptions options); #endif } diff --git a/src/Microsoft.Management.Deployment/PackageManager.idl b/src/Microsoft.Management.Deployment/PackageManager.idl index 21176415f9..82785fac17 100644 --- a/src/Microsoft.Management.Deployment/PackageManager.idl +++ b/src/Microsoft.Management.Deployment/PackageManager.idl @@ -269,7 +269,7 @@ namespace Microsoft.Management.Deployment [contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 4)] { /// Checks if this package version has at least one applicable installer. - Boolean HasApplicableInstaller { get; }; + Boolean HasApplicableInstaller(InstallOptions options); } /// DESIGN NOTE: diff --git a/src/Microsoft.Management.Deployment/PackageVersionInfo.cpp b/src/Microsoft.Management.Deployment/PackageVersionInfo.cpp index a2e4812cc2..9b1d79cc1d 100644 --- a/src/Microsoft.Management.Deployment/PackageVersionInfo.cpp +++ b/src/Microsoft.Management.Deployment/PackageVersionInfo.cpp @@ -14,6 +14,11 @@ #include "winget/RepositorySearch.h" #include "AppInstallerVersions.h" #include "Converters.h" +#pragma warning( push ) +#pragma warning ( disable : 4467 ) +// 4467 Allow use of uuid attribute for com object creation. +#include "PackageManager.h" +#pragma warning( pop ) #include namespace winrt::Microsoft::Management::Deployment::implementation @@ -115,9 +120,10 @@ namespace winrt::Microsoft::Management::Deployment::implementation return CompareResult::Equal; } } - bool PackageVersionInfo::HasApplicableInstaller() + bool PackageVersionInfo::HasApplicableInstaller(InstallOptions options) { AppInstaller::CLI::Execution::COMContext context; + PopulateContextFromInstallOptions(&context, options); AppInstaller::Repository::IPackageVersion::Metadata installationMetadata; AppInstaller::CLI::Workflow::ManifestComparator manifestComparator{ context, installationMetadata }; AppInstaller::Manifest::Manifest manifest = m_packageVersion->GetManifest(); diff --git a/src/Microsoft.Management.Deployment/PackageVersionInfo.h b/src/Microsoft.Management.Deployment/PackageVersionInfo.h index 8d7c5e189f..c74c70db6d 100644 --- a/src/Microsoft.Management.Deployment/PackageVersionInfo.h +++ b/src/Microsoft.Management.Deployment/PackageVersionInfo.h @@ -24,7 +24,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation winrt::Microsoft::Management::Deployment::PackageCatalog PackageCatalog(); winrt::Microsoft::Management::Deployment::CompareResult CompareToVersion(hstring versionString); // Contract version 4 - bool HasApplicableInstaller(); + bool HasApplicableInstaller(InstallOptions options); #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) private: