winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 4c4413102dcb0a68462d369c3645223fd4ff2128
parent c63f1d81cf3be8bc08466189dd59b0262c1daed5
Author: yao-msft <50888816+yao-msft@users.noreply.github.com>
Date:   Fri,  8 Apr 2022 15:08:26 -0700

Add support for in-proc Com state separation (#2068)


Diffstat:
M.github/actions/spelling/expect.txt | 1+
Mazure-pipelines.nuget.yml | 2+-
Mazure-pipelines.yml | 22++++++++++++++--------
Msrc/AppInstallerCommonCore/Public/AppInstallerRuntime.h | 2++
Msrc/AppInstallerCommonCore/Public/winget/UserSettings.h | 7+++++--
Msrc/AppInstallerCommonCore/Runtime.cpp | 34++++++++++++++++++++++++++++++++++
Msrc/AppInstallerCommonCore/UserSettings.cpp | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Asrc/Microsoft.Management.Deployment.Client/Client.PackageManagerSettings.h | 13+++++++++++++
Msrc/Microsoft.Management.Deployment.Client/Microsoft.Management.Deployment.Client.vcxproj | 2++
Asrc/Microsoft.Management.Deployment.Client/PackageManagerSettings.cpp | 25+++++++++++++++++++++++++
Msrc/Microsoft.Management.Deployment.InProc/Microsoft.Management.Deployment.InProc.dll.manifest | 4++++
Msrc/Microsoft.Management.Deployment/ComClsids.cpp | 5+++++
Msrc/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj | 2++
Msrc/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters | 2++
Msrc/Microsoft.Management.Deployment/PackageManager.cpp | 19++++++++++++++++++-
Msrc/Microsoft.Management.Deployment/PackageManager.h | 13+++++++++++++
Msrc/Microsoft.Management.Deployment/PackageManager.idl | 28+++++++++++++++++++++++++++-
Asrc/Microsoft.Management.Deployment/PackageManagerSettings.cpp | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Microsoft.Management.Deployment/PackageManagerSettings.h | 28++++++++++++++++++++++++++++
Msrc/Microsoft.Management.Deployment/PackageVersionInfo.cpp | 8+++++++-
Msrc/Microsoft.Management.Deployment/PackageVersionInfo.h | 2+-
Msrc/Microsoft.Management.Deployment/Public/ComClsids.h | 6+++++-
Msrc/Microsoft.Management.Deployment/pch.h | 3+++
Msrc/WinGetServer/WinMain.cpp | 3+++
Msrc/WindowsPackageManager/main.cpp | 3++-
25 files changed, 339 insertions(+), 50 deletions(-)

diff --git 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.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" diff --git 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' @@ -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) -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 - task: PowerShell@2 displayName: Run Unit Tests Packaged diff --git 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 @@ -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<std::string>& content = std::nullopt); static std::filesystem::path SettingsFilePath(); @@ -205,10 +207,11 @@ namespace AppInstaller::Settings std::vector<Warning> m_warnings; std::map<Setting, details::SettingVariant> m_settings; - UserSettings(); + UserSettings(const std::optional<std::string>& 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 @@ -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<std::string> 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 @@ -72,25 +72,31 @@ namespace AppInstaller::Settings return convertedValue; } + std::optional<Json::Value> ParseSettingsContent(const std::string& content, std::string_view settingName, std::vector<UserSettings::Warning>& warnings) + { + Json::Value root; + Json::CharReaderBuilder builder; + const std::unique_ptr<Json::CharReader> 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<Json::Value> ParseFile(const StreamDefinition& setting, std::vector<UserSettings::Warning>& warnings) { auto stream = Stream{ setting }.Get(); if (stream) { - Json::Value root; - Json::CharReaderBuilder builder; - const std::unique_ptr<Json::CharReader> 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<std::string>& 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<std::string>& 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 @@ -0,0 +1,13 @@ +#pragma once +#include "PackageManagerSettings.g.h" + +namespace winrt::Microsoft::Management::Deployment::factory_implementation +{ + struct PackageManagerSettings : PackageManagerSettingsT<PackageManagerSettings, implementation::PackageManagerSettings> + { + auto ActivateInstance() const + { + return winrt::create_instance<winrt::Microsoft::Management::Deployment::PackageManagerSettings>(__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 @@ -129,6 +129,7 @@ </Link> </ItemDefinitionGroup> <ItemGroup> + <ClInclude Include="Client.PackageManagerSettings.h" /> <ClInclude Include="Client.UninstallOptions.h" /> <ClInclude Include="pch.h" /> <ClInclude Include="Client.CreateCompositePackageCatalogOptions.h" /> @@ -141,6 +142,7 @@ <ClCompile Include="CreateCompositePackageCatalogOptions.cpp" /> <ClCompile Include="FindPackagesOptions.cpp" /> <ClCompile Include="InstallOptions.cpp" /> + <ClCompile Include="PackageManagerSettings.cpp" /> <ClCompile Include="PackageMatchFilter.cpp" /> <ClCompile Include="pch.cpp"> <PrecompiledHeader>Create</PrecompiledHeader> diff --git a/src/Microsoft.Management.Deployment.Client/PackageManagerSettings.cpp 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 <PackageManagerSettings.h> +#include <Client.PackageManagerSettings.h> +#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.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"/> + <comClass + clsid="{80CF9D63-5505-4342-B9B4-BB87895CA8BB}" + threadingModel="Both" + description="PackageManagerSettings"/> </file> </assembly> diff --git 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 @@ -150,6 +150,7 @@ <ClInclude Include="PackageCatalogInfo.h" /> <ClInclude Include="PackageCatalogReference.h" /> <ClInclude Include="PackageManager.h" /> + <ClInclude Include="PackageManagerSettings.h" /> <ClInclude Include="PackageMatchFilter.h" /> <ClInclude Include="PackageVersionId.h" /> <ClInclude Include="PackageVersionInfo.h" /> @@ -174,6 +175,7 @@ <ClCompile Include="PackageCatalogInfo.cpp" /> <ClCompile Include="PackageCatalogReference.cpp" /> <ClCompile Include="PackageManager.cpp" /> + <ClCompile Include="PackageManagerSettings.cpp" /> <ClCompile Include="PackageMatchFilter.cpp" /> <ClCompile Include="PackageVersionId.cpp" /> <ClCompile Include="PackageVersionInfo.cpp" /> diff --git a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj.filters @@ -23,6 +23,7 @@ <ClCompile Include="UninstallOptions.cpp" /> <ClCompile Include="UninstallResult.cpp" /> <ClCompile Include="ComClsids.cpp" /> + <ClCompile Include="PackageManagerSettings.cpp" /> </ItemGroup> <ItemGroup> <ClInclude Include="CatalogPackage.h" /> @@ -48,6 +49,7 @@ <ClInclude Include="Public\ComClsids.h"> <Filter>Public</Filter> </ClInclude> + <ClInclude Include="PackageManagerSettings.h" /> </ItemGroup> <ItemGroup> <Midl Include="PackageManager.idl" /> diff --git 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<std::string> 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<winrt::Microsoft::Management::Deployment::PackageCatalogReference> PackageManager::GetPackageCatalogs() { Windows::Foundation::Collections::IVector<Microsoft::Management::Deployment::PackageCatalogReference> catalogs{ winrt::single_threaded_vector<Microsoft::Management::Deployment::PackageCatalogReference>() }; @@ -415,7 +427,12 @@ namespace winrt::Microsoft::Management::Deployment::implementation { std::unique_ptr<COMContext> context = std::make_unique<COMContext>(); 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<TOptions, winrt::Microsoft::Management::Deployment::InstallOptions>) diff --git 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)] @@ -29,6 +37,11 @@ namespace winrt::Microsoft::Management::Deployment::implementation winrt::Windows::Foundation::IAsyncOperationWithProgress<winrt::Microsoft::Management::Deployment::UninstallResult, winrt::Microsoft::Management::Deployment::UninstallProgress> GetUninstallProgress(winrt::Microsoft::Management::Deployment::CatalogPackage package, winrt::Microsoft::Management::Deployment::PackageCatalogInfo catalogInfo); }; + +#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 } #if !defined(INCLUDE_ONLY_INTERFACE_METHODS) diff --git 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: @@ -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 @@ -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 <wil\cppwinrt_wrl.h> +// 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 <winget/UserSettings.h> +#include <AppInstallerRuntime.h> + +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 @@ -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> + { + 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<PackageManagerSettings, implementation::PackageManagerSettings> + { + }; +} +#endif diff --git 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 <wil\cppwinrt_wrl.h> 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 @@ -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: diff --git a/src/Microsoft.Management.Deployment/Public/ComClsids.h b/src/Microsoft.Management.Deployment/Public/ComClsids.h @@ -3,7 +3,7 @@ #pragma once #include <guiddef.h> -// 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 @@ -4,3 +4,5 @@ #include <unknwn.h> #include <winrt/Windows.Foundation.h> #include <winrt/Windows.Foundation.Collections.h> + +#include <mutex>+ \ No newline at end of file diff --git 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 <wil/resource.h> +#pragma warning( pop ) #include <winrt/base.h> #include <objidl.h> #include <WindowsPackageManager.h> diff --git a/src/WindowsPackageManager/main.cpp b/src/WindowsPackageManager/main.cpp @@ -14,13 +14,14 @@ 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); CoCreatableClassWrlCreatorMapInclude(InstallOptions); CoCreatableClassWrlCreatorMapInclude(UninstallOptions); CoCreatableClassWrlCreatorMapInclude(PackageMatchFilter); +CoCreatableClassWrlCreatorMapInclude(PackageManagerSettings); extern "C" {