-
Notifications
You must be signed in to change notification settings - Fork 1.8k
WSLC SDK install API update #40949
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
WSLC SDK install API update #40949
Changes from 9 commits
472eba4
b073089
ab47ea7
484712f
6e29da6
0f0d558
a1bd8af
bc87857
42ce029
41d5894
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| /*++ | ||
|
|
||
| Copyright (c) Microsoft. All rights reserved. | ||
|
|
||
| Module Name: | ||
|
|
||
| InstallOptions.cpp | ||
|
|
||
| Abstract: | ||
|
|
||
| This file contains the implementation of the WinRT wrapper for the WSLC SDK InstallOptions class. | ||
|
|
||
| --*/ | ||
|
|
||
| #include "precomp.h" | ||
| #include "InstallOptions.h" | ||
| #include "Microsoft.WSL.Containers.InstallOptions.g.cpp" | ||
|
|
||
| namespace winrt::Microsoft::WSL::Containers::implementation { | ||
|
|
||
| winrt::Windows::Foundation::Collections::IVectorView<winrt::Microsoft::WSL::Containers::Component> InstallOptions::Components() | ||
| { | ||
| return m_components; | ||
| } | ||
|
|
||
| void InstallOptions::Components(winrt::Windows::Foundation::Collections::IVectorView<winrt::Microsoft::WSL::Containers::Component> value) | ||
| { | ||
| m_components = std::move(value); | ||
| } | ||
|
|
||
| bool InstallOptions::Repair() | ||
| { | ||
| return m_repair; | ||
| } | ||
|
|
||
| void InstallOptions::Repair(bool value) | ||
| { | ||
| m_repair = value; | ||
| } | ||
|
|
||
| } // namespace winrt::Microsoft::WSL::Containers::implementation |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| /*++ | ||
|
|
||
| Copyright (c) Microsoft. All rights reserved. | ||
|
|
||
| Module Name: | ||
|
|
||
| InstallOptions.h | ||
|
|
||
| Abstract: | ||
|
|
||
| This file contains the definition of the WinRT wrapper for the WSLC SDK InstallOptions class. | ||
|
|
||
| --*/ | ||
|
|
||
| #pragma once | ||
| #include "Microsoft.WSL.Containers.InstallOptions.g.h" | ||
| #include "Helpers.h" | ||
|
|
||
| namespace winrt::Microsoft::WSL::Containers::implementation { | ||
| struct InstallOptions : InstallOptionsT<InstallOptions> | ||
| { | ||
| InstallOptions() = default; | ||
|
|
||
| winrt::Windows::Foundation::Collections::IVectorView<winrt::Microsoft::WSL::Containers::Component> Components(); | ||
| void Components(winrt::Windows::Foundation::Collections::IVectorView<winrt::Microsoft::WSL::Containers::Component> value); | ||
| bool Repair(); | ||
| void Repair(bool value); | ||
|
|
||
| private: | ||
| winrt::Windows::Foundation::Collections::IVectorView<winrt::Microsoft::WSL::Containers::Component> m_components = nullptr; | ||
| bool m_repair = false; | ||
| }; | ||
| } // namespace winrt::Microsoft::WSL::Containers::implementation | ||
|
|
||
| namespace winrt::Microsoft::WSL::Containers::factory_implementation { | ||
| struct InstallOptions : InstallOptionsT<InstallOptions, implementation::InstallOptions> | ||
| { | ||
| }; | ||
| } // namespace winrt::Microsoft::WSL::Containers::factory_implementation | ||
|
|
||
| DEFINE_TYPE_HELPERS(InstallOptions); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1664,33 +1664,36 @@ try | |
| } | ||
| CATCH_RETURN(); | ||
|
|
||
| STDAPI WslcInstallWithDependencies(_In_opt_ WslcInstallCallback progressCallback, _In_opt_ PVOID context) | ||
| STDAPI WslcInstallWithDependencies( | ||
| _In_ WslcComponentFlags components, _In_ WslcInstallOptions options, _In_opt_ WslcInstallCallback progressCallback, _In_opt_ PVOID context) | ||
| try | ||
| { | ||
| // This API cannot update the SDK that the client is using. | ||
| RETURN_HR_IF(WSLC_E_SDK_UPDATE_NEEDED, WI_IsFlagSet(components, WSLC_COMPONENT_FLAG_SDK_NEEDS_UPDATE)); | ||
|
|
||
| HRESULT result = S_OK; | ||
|
JohnMcPMS marked this conversation as resolved.
|
||
| bool needsVirtualMachine = NeedsVirtualMachineServicesInstalled(); | ||
| auto runtimeResult = CreateSessionManagerRaw().second; | ||
|
|
||
| if (!needsVirtualMachine && SUCCEEDED(runtimeResult)) | ||
| if (components == WSLC_COMPONENT_FLAG_NONE) | ||
| { | ||
| return result; | ||
| } | ||
|
|
||
| THROW_HR_IF(runtimeResult, runtimeResult != REGDB_E_CLASSNOTREG && runtimeResult != WSLC_E_SDK_UPDATE_NEEDED); | ||
|
|
||
| // Installing these components requires elevation. | ||
| // Installing components requires elevation. | ||
| RETURN_HR_IF( | ||
| HRESULT_FROM_WIN32(ERROR_ELEVATION_REQUIRED), | ||
| !wsl::windows::common::security::IsTokenElevated(GetCurrentThreadEffectiveToken()) && | ||
| !wsl::windows::common::security::IsTokenLocalSystem(nullptr)); | ||
|
|
||
| if (needsVirtualMachine) | ||
| bool isRepair = WI_IsFlagSet(options, WSLC_INSTALL_OPTION_REPAIR); | ||
|
|
||
| if (WI_IsFlagSet(components, WSLC_COMPONENT_FLAG_VIRTUAL_MACHINE_PLATFORM)) | ||
| { | ||
| if (progressCallback) | ||
| { | ||
| progressCallback(WSLC_COMPONENT_FLAG_VIRTUAL_MACHINE_PLATFORM, 0, 1, context); | ||
| } | ||
|
|
||
| // No difference between install and repair, just let DISM attempt to enable the feature. | ||
| auto exitCode = WslInstall::InstallOptionalComponent(WslInstall::c_optionalFeatureNameVmp, false); | ||
| if (exitCode == ERROR_SUCCESS_REBOOT_REQUIRED) | ||
| { | ||
|
|
@@ -1707,9 +1710,15 @@ try | |
| { | ||
| progressCallback(WSLC_COMPONENT_FLAG_VIRTUAL_MACHINE_PLATFORM, 1, 1, context); | ||
| } | ||
|
|
||
| // If a reboot is required, we need the reboot to happen before attempting to install the WSL package. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's not necessarily true (the MSI can be installed before reboot). From a UX perspective, I think installing the dependencies and then returning |
||
| if (result == HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED)) | ||
| { | ||
| return result; | ||
| } | ||
| } | ||
|
|
||
| if (!SUCCEEDED(runtimeResult)) | ||
| if (WI_IsFlagSet(components, WSLC_COMPONENT_FLAG_WSL_PACKAGE)) | ||
| { | ||
| std::function<void(uint32_t)> callback; | ||
| if (progressCallback) | ||
|
|
@@ -1719,14 +1728,16 @@ try | |
| }; | ||
| } | ||
|
|
||
| wsl::windows::common::WindowsUpdateContext wuContext; | ||
| wuContext.RunUpdateFlow(true, callback); | ||
| using WindowsUpdateContext = wsl::windows::common::WindowsUpdateContext; | ||
| WindowsUpdateContext wuContext; | ||
| wuContext.RunUpdateFlow( | ||
| isRepair ? WindowsUpdateContext::UpdateOptions::ResetProductRegistration : WindowsUpdateContext::UpdateOptions::EnsureProductRegistration, | ||
| callback); | ||
|
|
||
| // Because we do a forced install here, we expect an update. | ||
| if (wuContext.GetUpdateCount() == 0) | ||
| { | ||
| // During the preview period, the package may not be published yet, so fall back to getting it from GH. | ||
| // When moving to GA, change this to a hard error to indicate a service configuration issue. | ||
| // When moving to GA, change this to an error like WSL_E_NO_UPDATE_AVAILABLE or similar. | ||
| if (callback) | ||
| { | ||
| callback(0); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -126,18 +126,12 @@ namespace anon { | |
| }; | ||
| } // namespace anon | ||
|
|
||
| WindowsUpdateContext::WindowsUpdateContext() : | ||
| WindowsUpdateContext(std::make_unique<anon::DefaultWindowsUpdateClassFactory>(), WslProductIdentifier()) | ||
| WindowsUpdateContext::WindowsUpdateContext() : WindowsUpdateContext(std::make_unique<anon::DefaultWindowsUpdateClassFactory>()) | ||
| { | ||
| } | ||
|
|
||
| WindowsUpdateContext::WindowsUpdateContext(std::wstring product) : | ||
| WindowsUpdateContext(std::make_unique<anon::DefaultWindowsUpdateClassFactory>(), std::move(product)) | ||
| { | ||
| } | ||
|
|
||
| WindowsUpdateContext::WindowsUpdateContext(std::unique_ptr<WindowsUpdateClassFactory> factory, std::wstring product) : | ||
| m_factory(std::move(factory)), m_product(std::move(product)) | ||
| WindowsUpdateContext::WindowsUpdateContext(std::unique_ptr<WindowsUpdateClassFactory> factory) : | ||
| m_factory(std::move(factory)), m_product(WslProductIdentifier()) | ||
| { | ||
| m_session = m_factory->CreateUpdateSession(); | ||
|
|
||
|
|
@@ -158,9 +152,12 @@ std::wstring WindowsUpdateContext::WslProductIdentifier() | |
| return STRING_TO_WIDE_STRING(DCAT_PRODUCT_NAME); | ||
| } | ||
|
|
||
| void WindowsUpdateContext::EnsureProductRegistryEntry() const | ||
| void WindowsUpdateContext::EnsureProductRegistryEntry(bool reset) const | ||
| { | ||
| wsl::windows::common::helpers::RegisterWithDcat(false); | ||
| if (reset || !wsl::windows::common::helpers::VersionRegisteredWithDcat()) | ||
| { | ||
| wsl::windows::common::helpers::RegisterWithDcat(false); | ||
| } | ||
| } | ||
|
|
||
| size_t WindowsUpdateContext::SearchForUpdates() | ||
|
|
@@ -336,14 +333,15 @@ void WindowsUpdateContext::InstallUpdates(const std::function<void(uint32_t)>& p | |
| THROW_IF_FAILED(installationHResult); | ||
| } | ||
|
|
||
| void WindowsUpdateContext::RunUpdateFlow(bool forceInstall, const std::function<void(uint32_t)>& progress) | ||
| void WindowsUpdateContext::RunUpdateFlow(UpdateOptions options, const std::function<void(uint32_t)>& progress) | ||
| { | ||
| TraceLoggingWriteTagged( | ||
| *m_activity, | ||
| "RunUpdateFlow", | ||
| TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), | ||
| TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage), | ||
| TraceLoggingBool(forceInstall, "forceInstall")); | ||
| TraceLoggingBool(options == UpdateOptions::ResetProductRegistration, "forceInstall"), | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we just log the |
||
| TraceLoggingBool(options == UpdateOptions::EnsureProductRegistration, "ensureInstall")); | ||
|
|
||
| static_assert( | ||
| DownloadProgressPercent + InstallProgressPercent == 100, "Download and Install progress values must add up to 100."); | ||
|
|
@@ -353,9 +351,9 @@ void WindowsUpdateContext::RunUpdateFlow(bool forceInstall, const std::function< | |
| progress(0); | ||
| } | ||
|
|
||
| if (forceInstall) | ||
| if (options != UpdateOptions::None) | ||
| { | ||
| EnsureProductRegistryEntry(); | ||
| EnsureProductRegistryEntry(options == UpdateOptions::ResetProductRegistration); | ||
| } | ||
|
|
||
| size_t updateCount = SearchForUpdates(); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.