winget-cli

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

ConfigurationStaticFunctions.cpp (14552B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License
      3 #include <Unknwn.h>
      4 #include <wil\cppwinrt_wrl.h>
      5 #include <winrt/Microsoft.Management.Configuration.h>
      6 #include <winrt/Microsoft.Management.Deployment.h>
      7 #include <ComClsids.h>
      8 #include <AppInstallerErrors.h>
      9 #include <AppInstallerFileLogger.h>
     10 #include <AppInstallerLanguageUtilities.h>
     11 #include <AppInstallerStrings.h>
     12 #include <winget/ConfigurationSetProcessorHandlers.h>
     13 #include <ConfigurationSetProcessorFactoryRemoting.h>
     14 #include <ShutdownMonitoring.h>
     15 #include <winget/ILifetimeWatcher.h>
     16 #include <winget/IConfigurationStaticsInternals.h>
     17 #include <winget/GroupPolicy.h>
     18 #include <winget/Security.h>
     19 #include <winget/ThreadGlobals.h>
     20 #include <winget/SelfManagement.h>
     21 #include <winget/MSStore.h>
     22 #include <winget/ExperimentalFeature.h>
     23 
     24 using namespace AppInstaller::SelfManagement;
     25 using namespace winrt::Microsoft::Management::Deployment;
     26 using namespace winrt::Windows::Foundation::Collections;
     27 
     28 namespace ConfigurationShim
     29 {
     30     namespace
     31     {
     32         static std::atomic_bool s_canBeCreated{ true };
     33 
     34         auto GetInternalStatics()
     35         {
     36             return winrt::Microsoft::Management::Configuration::ConfigurationStaticFunctions().as<AppInstaller::WinRT::IConfigurationStaticsInternals>();
     37         }
     38 
     39         void BlockNewWorkForShutdown(AppInstaller::CancelReason)
     40         {
     41             GetInternalStatics()->BlockNewWorkForShutdown();
     42         }
     43 
     44         void BeginShutdown(AppInstaller::CancelReason)
     45         {
     46             GetInternalStatics()->BeginShutdown();
     47         }
     48 
     49         void WaitForShutdown()
     50         {
     51             GetInternalStatics()->WaitForShutdown();
     52         }
     53 
     54         void RegisterForShutdownSynchronization()
     55         {
     56             static std::once_flag registerComponentOnceFlag;
     57             std::call_once(registerComponentOnceFlag,
     58                 [&]()
     59                 {
     60                     using namespace AppInstaller::ShutdownMonitoring;
     61 
     62                     ServerShutdownSynchronization::ComponentSystem component;
     63                     component.BlockNewWork = BlockNewWorkForShutdown;
     64                     component.BeginShutdown = BeginShutdown;
     65                     component.Wait = WaitForShutdown;
     66 
     67                     ServerShutdownSynchronization::AddComponent(component);
     68                 });
     69         }
     70     }
     71 
     72     CLSID CLSID_ConfigurationObjectLifetimeWatcher = { 0x89a8f1d4,0x1e24,0x46a4,{0x9f,0x6c,0x65,0x78,0xb0,0x47,0xf2,0xf7} };
     73 
     74     struct
     75     DECLSPEC_UUID("89a8f1d4-1e24-46a4-9f6c-6578b047f2f7")
     76     ConfigurationObjectLifetimeWatcher : winrt::implements<ConfigurationObjectLifetimeWatcher, IUnknown>
     77     {
     78     };
     79 
     80     struct
     81     DECLSPEC_UUID(WINGET_OUTOFPROC_COM_CLSID_ConfigurationStaticFunctions)
     82     ConfigurationStaticFunctionsShim : winrt::implements<ConfigurationStaticFunctionsShim,
     83         winrt::Microsoft::Management::Configuration::IConfigurationStatics,
     84         winrt::Microsoft::Management::Configuration::IConfigurationStatics2,
     85         winrt::Microsoft::Management::Configuration::IConfigurationStatics3>
     86     {
     87         ConfigurationStaticFunctionsShim()
     88         {
     89             auto threadGlobalsRestore = m_threadGlobals.SetForCurrentThread();
     90             auto& diagnosticsLogger = m_threadGlobals.GetDiagnosticLogger();
     91             diagnosticsLogger.SetEnabledChannels(AppInstaller::Logging::Channel::All);
     92             diagnosticsLogger.SetLevel(AppInstaller::Logging::Level::Verbose);
     93             diagnosticsLogger.AddLogger(std::make_unique<AppInstaller::Logging::FileLogger>("WinGetCFG"sv));
     94 
     95             if (IsConfigurationAvailable())
     96             {
     97                 m_statics = winrt::Microsoft::Management::Configuration::ConfigurationStaticFunctions().as<winrt::Microsoft::Management::Configuration::IConfigurationStatics3>();
     98                 RegisterForShutdownSynchronization();
     99             }
    100         }
    101 
    102         winrt::Microsoft::Management::Configuration::ConfigurationUnit CreateConfigurationUnit()
    103         {
    104             THROW_HR_IF(CO_E_CLASS_DISABLED, !s_canBeCreated);
    105 
    106             if (!m_statics)
    107             {
    108                 THROW_HR(APPINSTALLER_CLI_ERROR_PACKAGE_IS_STUB);
    109             }
    110 
    111             auto result = m_statics.CreateConfigurationUnit();
    112             result.as<AppInstaller::WinRT::ILifetimeWatcher>()->SetLifetimeWatcher(CreateLifetimeWatcher());
    113             return result;
    114         }
    115 
    116         winrt::Microsoft::Management::Configuration::ConfigurationSet CreateConfigurationSet()
    117         {
    118             THROW_HR_IF(CO_E_CLASS_DISABLED, !s_canBeCreated);
    119 
    120             if (!m_statics)
    121             {
    122                 THROW_HR(APPINSTALLER_CLI_ERROR_PACKAGE_IS_STUB);
    123             }
    124 
    125             auto result = m_statics.CreateConfigurationSet();
    126             result.as<AppInstaller::WinRT::ILifetimeWatcher>()->SetLifetimeWatcher(CreateLifetimeWatcher());
    127             return result;
    128         }
    129 
    130         winrt::Windows::Foundation::IAsyncOperation<winrt::Microsoft::Management::Configuration::IConfigurationSetProcessorFactory> CreateConfigurationSetProcessorFactoryAsync(winrt::hstring const& handler)
    131         {
    132             THROW_HR_IF(CO_E_CLASS_DISABLED, !s_canBeCreated);
    133 
    134             auto strong_this{ get_strong() };
    135             std::wstring lowerHandler = AppInstaller::Utility::ToLower(handler);
    136 
    137             co_await winrt::resume_background();
    138 
    139             auto threadGlobalsRestore = m_threadGlobals.SetForCurrentThread();
    140             winrt::Microsoft::Management::Configuration::IConfigurationSetProcessorFactory result;
    141 
    142             if (lowerHandler == AppInstaller::Configuration::PowerShellHandlerIdentifier)
    143             {
    144                 result = AppInstaller::CLI::ConfigurationRemoting::CreateOutOfProcessFactory(AppInstaller::CLI::ConfigurationRemoting::ProcessorEngine::PowerShell);
    145             }
    146             else if (lowerHandler == AppInstaller::Configuration::DynamicRuntimeHandlerIdentifier)
    147             {
    148                 result = AppInstaller::CLI::ConfigurationRemoting::CreateDynamicRuntimeFactory(AppInstaller::CLI::ConfigurationRemoting::ProcessorEngine::PowerShell);
    149             }
    150             else if (lowerHandler == AppInstaller::Configuration::DSCv3HandlerIdentifier)
    151             {
    152                 result = AppInstaller::CLI::ConfigurationRemoting::CreateOutOfProcessFactory(AppInstaller::CLI::ConfigurationRemoting::ProcessorEngine::DSCv3);
    153             }
    154             else if (lowerHandler == AppInstaller::Configuration::DSCv3DynamicRuntimeHandlerIdentifier)
    155             {
    156                 result = AppInstaller::CLI::ConfigurationRemoting::CreateDynamicRuntimeFactory(AppInstaller::CLI::ConfigurationRemoting::ProcessorEngine::DSCv3);
    157             }
    158 
    159             if (result)
    160             {
    161                 // Objects returned here *must* implement ILifetimeWatcher for now.
    162                 // If we create OOP objects implemented elsewhere in the future, decide then how to exempt those while still ensuring we
    163                 // don't accidentally create a lifetime bug by basing it solely off the QI result.
    164                 result.as<AppInstaller::WinRT::ILifetimeWatcher>()->SetLifetimeWatcher(CreateLifetimeWatcher());
    165                 co_return result;
    166             }
    167 
    168             AICLI_LOG(Config, Error, << "Unknown handler in CreateConfigurationSetProcessorFactory: " << AppInstaller::Utility::ConvertToUTF8(handler));
    169             THROW_HR(E_NOT_SET);
    170         }
    171 
    172         winrt::Microsoft::Management::Configuration::ConfigurationProcessor CreateConfigurationProcessor(winrt::Microsoft::Management::Configuration::IConfigurationSetProcessorFactory const& factory)
    173         {
    174             THROW_HR_IF(CO_E_CLASS_DISABLED, !s_canBeCreated);
    175 
    176             if (!m_statics)
    177             {
    178                 THROW_HR(APPINSTALLER_CLI_ERROR_PACKAGE_IS_STUB);
    179             }
    180 
    181             auto result = m_statics.CreateConfigurationProcessor(factory);
    182             result.as<AppInstaller::WinRT::ILifetimeWatcher>()->SetLifetimeWatcher(CreateLifetimeWatcher());
    183             return result;
    184         }
    185 
    186         bool IsConfigurationAvailable()
    187         {
    188             return !IsStubPackage();
    189         }
    190 
    191         winrt::Windows::Foundation::IAsyncActionWithProgress<uint32_t> EnsureConfigurationAvailableAsync()
    192         {
    193             THROW_HR_IF(CO_E_CLASS_DISABLED, !s_canBeCreated);
    194 
    195             if (IsConfigurationAvailable())
    196             {
    197                 return;
    198             }
    199 
    200             auto strong_this{ get_strong() };
    201             co_await winrt::resume_background();
    202 
    203             SetStubPreferred(false);
    204 
    205             PackageManager packageManager;
    206             PackageCatalogReference catalogRef{ packageManager.GetPredefinedPackageCatalog(PredefinedPackageCatalog::MicrosoftStore) };
    207             THROW_HR_IF(APPINSTALLER_CLI_ERROR_INTERNAL_ERROR, !catalogRef);
    208 
    209             ConnectResult connectResult = catalogRef.Connect();
    210             THROW_HR_IF(APPINSTALLER_CLI_ERROR_SOURCE_OPEN_FAILED, connectResult.Status() != ConnectResultStatus::Ok);
    211 
    212             PackageCatalog catalog = connectResult.PackageCatalog();
    213 
    214             FindPackagesOptions findPackagesOptions;
    215             PackageMatchFilter filter;
    216             filter.Field(PackageMatchField::Id);
    217             filter.Option(PackageFieldMatchOption::Equals);
    218             filter.Value(AppInstaller::MSStore::s_AppInstallerProductId);
    219             findPackagesOptions.Filters().Append(filter);
    220 
    221             FindPackagesResult findPackagesResult{ catalog.FindPackages(findPackagesOptions) };
    222 
    223             auto matches = findPackagesResult.Matches();
    224             THROW_HR_IF(APPINSTALLER_CLI_ERROR_MISSING_PACKAGE, matches.Size() == 0);
    225             auto catalogPackage = matches.GetAt(0).CatalogPackage();
    226 
    227             InstallOptions installOptions;
    228             installOptions.AcceptPackageAgreements(true);
    229             installOptions.AllowUpgradeToUnknownVersion(true);
    230             installOptions.Force(true);
    231 
    232             auto progress = co_await winrt::get_progress_token();
    233 
    234             // Don't use UpgradePackageAsync, we don't support upgrade for packages from the msstore
    235             // it has to be install and internally we know is an update.
    236             auto installTask = packageManager.InstallPackageAsync(catalogPackage, installOptions);
    237             installTask.Progress([progress](auto const&, InstallProgress installProgress)
    238             {
    239                 if (installProgress.State == PackageInstallProgressState::Downloading && installProgress.BytesRequired != 0)
    240                 {
    241                     progress((uint32_t)(installProgress.DownloadProgress * 80));
    242                 }
    243                 else if (installProgress.State == PackageInstallProgressState::Installing)
    244                 {
    245                     progress(((uint32_t)installProgress.InstallationProgress * 20) + 80);
    246                 }
    247             });
    248 
    249             co_await installTask;
    250             s_canBeCreated = false;
    251         }
    252 
    253         winrt::Microsoft::Management::Configuration::ConfigurationParameter CreateConfigurationParameter()
    254         {
    255             THROW_HR_IF(CO_E_CLASS_DISABLED, !s_canBeCreated);
    256 
    257             if (!m_statics)
    258             {
    259                 THROW_HR(APPINSTALLER_CLI_ERROR_PACKAGE_IS_STUB);
    260             }
    261 
    262             auto result = m_statics.CreateConfigurationParameter();
    263             result.as<AppInstaller::WinRT::ILifetimeWatcher>()->SetLifetimeWatcher(CreateLifetimeWatcher());
    264             return result;
    265         }
    266 
    267         winrt::Microsoft::Management::Configuration::FindUnitProcessorsOptions CreateFindUnitProcessorsOptions()
    268         {
    269             THROW_HR_IF(CO_E_CLASS_DISABLED, !s_canBeCreated);
    270 
    271             if (!m_statics)
    272             {
    273                 THROW_HR(APPINSTALLER_CLI_ERROR_PACKAGE_IS_STUB);
    274             }
    275 
    276             auto result = m_statics.CreateFindUnitProcessorsOptions();
    277             result.as<AppInstaller::WinRT::ILifetimeWatcher>()->SetLifetimeWatcher(CreateLifetimeWatcher());
    278             return result;
    279         }
    280 
    281     private:
    282         // Returns a lifetime watcher object that is currently *unowned*.
    283         IUnknown* CreateLifetimeWatcher()
    284         {
    285             ::Microsoft::WRL::ComPtr<IClassFactory> factory;
    286             THROW_IF_FAILED(::Microsoft::WRL::Module<::Microsoft::WRL::ModuleType::OutOfProc>::GetModule().GetClassObject(CLSID_ConfigurationObjectLifetimeWatcher, IID_PPV_ARGS(&factory)));
    287             winrt::com_ptr<IUnknown> out;
    288             THROW_IF_FAILED(factory->CreateInstance(nullptr, __uuidof(IUnknown), out.put_void()));
    289             return out.detach();
    290         }
    291 
    292         winrt::Microsoft::Management::Configuration::IConfigurationStatics3 m_statics = nullptr;
    293         AppInstaller::ThreadLocalStorage::WingetThreadGlobals m_threadGlobals;
    294     };
    295 
    296     // Enable custom code to run before creating any object through the factory.
    297     template <typename TCppWinRTClass>
    298     class ConfigurationFactory : public ::wil::wrl_factory_for_winrt_com_class<TCppWinRTClass>
    299     {
    300     public:
    301         IFACEMETHODIMP CreateInstance(_In_opt_::IUnknown* unknownOuter, REFIID riid, _COM_Outptr_ void** object) noexcept try
    302         {
    303             *object = nullptr;
    304             RETURN_HR_IF(APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY, !::AppInstaller::Settings::GroupPolicies().IsEnabled(::AppInstaller::Settings::TogglePolicy::Policy::WinGet));
    305             RETURN_HR_IF(APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY, !::AppInstaller::Settings::GroupPolicies().IsEnabled(::AppInstaller::Settings::TogglePolicy::Policy::Configuration));
    306             RETURN_HR_IF(E_ACCESSDENIED, !::AppInstaller::Security::IsCOMCallerSameUserAndIntegrityLevel());
    307 
    308             RETURN_HR_IF(CO_E_CLASS_DISABLED, !s_canBeCreated);
    309 
    310             return ::wil::wrl_factory_for_winrt_com_class<TCppWinRTClass>::CreateInstance(unknownOuter, riid, object);
    311         }
    312         CATCH_RETURN()
    313     };
    314 
    315 #define CoCreatableMicrosoftManagementConfigurationClass(className) \
    316     CoCreatableClassWithFactory(className, ::ConfigurationShim::ConfigurationFactory<className>)
    317 
    318     // Disable 6388 as it seems to be falsely warning
    319 #pragma warning(push)
    320 #pragma warning(disable : 6388)
    321     CoCreatableCppWinRtClass(ConfigurationObjectLifetimeWatcher);
    322     CoCreatableMicrosoftManagementConfigurationClass(ConfigurationStaticFunctionsShim);
    323 #pragma warning(pop)
    324 }