From ea5c29eae74ac02b5ef6baf5dc763974ec6ed560 Mon Sep 17 00:00:00 2001 From: Ben Hillis Date: Fri, 7 Nov 2025 12:53:10 -0800 Subject: [PATCH 01/19] wslsettings: allow OOBE window to close with escape key (#13686) * wslsettings: allow OOBE windows to close with escape key * fix memory leak --------- Co-authored-by: Ben Hillis --- .../wslsettings/Windows/OOBEWindow.xaml.cs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/windows/wslsettings/Windows/OOBEWindow.xaml.cs b/src/windows/wslsettings/Windows/OOBEWindow.xaml.cs index 904cf87..383f4df 100644 --- a/src/windows/wslsettings/Windows/OOBEWindow.xaml.cs +++ b/src/windows/wslsettings/Windows/OOBEWindow.xaml.cs @@ -2,8 +2,10 @@ using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Input; using System.Runtime.InteropServices; using Windows.Graphics; +using Windows.System; using WinUIEx.Messaging; using Windows.UI.ViewManagement; using Windows.UI.WindowManagement; @@ -60,6 +62,8 @@ public sealed partial class OOBEWindow : WindowEx, IDisposable e.Handled = true; } }; + + this.Activated += OnWindowActivated; } // this handles updating the caption button colors correctly when windows system theme is changed @@ -108,6 +112,12 @@ public sealed partial class OOBEWindow : WindowEx, IDisposable { msgMonitor?.Dispose(); settings.ColorValuesChanged -= Settings_ColorValuesChanged; + this.Activated -= OnWindowActivated; + if (this.Content is Microsoft.UI.Xaml.Controls.Page page) + { + page.KeyboardAccelerators.Clear(); + } + disposedValue = true; } } @@ -118,4 +128,25 @@ public sealed partial class OOBEWindow : WindowEx, IDisposable Dispose(disposing: true); GC.SuppressFinalize(this); } + + private void OnWindowActivated(object sender, WindowActivatedEventArgs args) + { + if (args.WindowActivationState != WindowActivationState.Deactivated && this.Content != null) + { + this.Activated -= OnWindowActivated; + + if (this.Content is Microsoft.UI.Xaml.Controls.Page page) + { + var escapeAccelerator = new KeyboardAccelerator() { Key = VirtualKey.Escape }; + escapeAccelerator.Invoked += OnCloseKeyboardAcceleratorInvoked; + page.KeyboardAccelerators.Add(escapeAccelerator); + } + } + } + + private void OnCloseKeyboardAcceleratorInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args) + { + Close(); + args.Handled = true; + } } \ No newline at end of file From b2c28b92fe3153deb98bfc9e59bb09150fcef268 Mon Sep 17 00:00:00 2001 From: Blue Date: Tue, 11 Nov 2025 16:12:16 +0000 Subject: [PATCH 02/19] Localization change from build: 133610492 (#13704) Co-authored-by: WSL localization --- localization/strings/nl-NL/Resources.resw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/localization/strings/nl-NL/Resources.resw b/localization/strings/nl-NL/Resources.resw index f6fc34f..0809226 100644 --- a/localization/strings/nl-NL/Resources.resw +++ b/localization/strings/nl-NL/Resources.resw @@ -606,7 +606,7 @@ Argumenten voor het beheren van distributies in het Windows-subsysteem voor Linu "}{Locked="--quiet,"}{Locked="--verbose,"}{Locked="--online,"}{Locked="--install'"}{Locked="--set-default,"}{Locked="--set-version "}{Locked="--terminate,"}{Locked="--unregister "}Command line arguments, file names and string inserts should not be translated - WSL-versiie: {} + WSL-versie: {} Kernelversie: {} WSLg-versie: {} MSRDC-versie: {} From 9fad2a1b599ec374e60f4dd1e2a675e325c16427 Mon Sep 17 00:00:00 2001 From: Ben Hillis Date: Thu, 13 Nov 2025 13:52:29 -0800 Subject: [PATCH 03/19] wslsettings: fix OOBE text truncation at 200% text scaling (#13693) * wslsettings: fix OOBE text truncation at 200% text scaling Add text scaling factor to window resize calculation and make hero image height responsive to text scaling. Increase minimum window size for better accessibility. Fix MAS 1.4.4 compliance for OOBE dialog. * pr feedback --------- Co-authored-by: Ben Hillis --- .../wslsettings/Controls/OOBEContent.xaml | 2 +- .../wslsettings/Controls/OOBEContent.xaml.cs | 35 +++++++++++++++++-- src/windows/wslsettings/LibWsl.cs | 4 +-- .../wslsettings/Windows/OOBEWindow.xaml | 4 +-- .../wslsettings/Windows/OOBEWindow.xaml.cs | 26 +++++++++++--- 5 files changed, 60 insertions(+), 11 deletions(-) diff --git a/src/windows/wslsettings/Controls/OOBEContent.xaml b/src/windows/wslsettings/Controls/OOBEContent.xaml index 670a4aa..e4c6721 100644 --- a/src/windows/wslsettings/Controls/OOBEContent.xaml +++ b/src/windows/wslsettings/Controls/OOBEContent.xaml @@ -19,7 +19,7 @@ diff --git a/src/windows/wslsettings/Controls/OOBEContent.xaml.cs b/src/windows/wslsettings/Controls/OOBEContent.xaml.cs index a017b0a..90f37dc 100644 --- a/src/windows/wslsettings/Controls/OOBEContent.xaml.cs +++ b/src/windows/wslsettings/Controls/OOBEContent.xaml.cs @@ -1,15 +1,46 @@ -// Copyright (c) Microsoft Corporation +// Copyright (C) Microsoft Corporation. All rights reserved. using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; +using Windows.UI.ViewManagement; namespace WslSettings.Controls { public sealed partial class OOBEContent : UserControl { + // Constants for hero image height calculations + private const double BaseImageHeight = 280.0; + private const double MinimumImageHeight = 200.0; + + private static readonly UISettings Settings = new UISettings(); + public OOBEContent() { this.InitializeComponent(); + + // Set initial hero image height based on current text scaling + UpdateHeroImageHeight(); + + // Subscribe to text scale factor changes for dynamic updates + Settings.TextScaleFactorChanged += OnTextScaleFactorChanged; + + // Ensure event cleanup when control is unloaded + this.Unloaded += (s, e) => Settings.TextScaleFactorChanged -= OnTextScaleFactorChanged; + } + + private void UpdateHeroImageHeight() + { + double textScaleFactor = Settings.TextScaleFactor; + + // Reduce image height when text scaling increases to preserve content space + // Use inverse relationship: as text gets larger, image gets proportionally smaller + HeroImageHeight = Math.Max(BaseImageHeight / textScaleFactor, MinimumImageHeight); + } + + private void OnTextScaleFactorChanged(UISettings sender, object args) + { + // Update hero image height when text scaling changes at runtime + this.DispatcherQueue.TryEnqueue(() => UpdateHeroImageHeight()); } public string Title @@ -46,6 +77,6 @@ namespace WslSettings.Controls public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register("Description", typeof(string), typeof(OOBEContent), new PropertyMetadata(default(string))); public static readonly DependencyProperty HeroImageProperty = DependencyProperty.Register("HeroImage", typeof(string), typeof(OOBEContent), new PropertyMetadata(default(string))); public static readonly DependencyProperty PageContentProperty = DependencyProperty.Register("PageContent", typeof(object), typeof(OOBEContent), new PropertyMetadata(new Grid())); - public static readonly DependencyProperty HeroImageHeightProperty = DependencyProperty.Register("HeroImageHeight", typeof(double), typeof(OOBEContent), new PropertyMetadata(280.0)); + public static readonly DependencyProperty HeroImageHeightProperty = DependencyProperty.Register("HeroImageHeight", typeof(double), typeof(OOBEContent), new PropertyMetadata(BaseImageHeight)); } } \ No newline at end of file diff --git a/src/windows/wslsettings/LibWsl.cs b/src/windows/wslsettings/LibWsl.cs index 4037772..cd151fd 100644 --- a/src/windows/wslsettings/LibWsl.cs +++ b/src/windows/wslsettings/LibWsl.cs @@ -80,7 +80,7 @@ namespace LibWsl internal static bool __TryGetNativeToManagedMapping(IntPtr native, out global::LibWsl.WslConfig managed) { - + return NativeToManagedMap.TryGetValue(native, out managed); } @@ -171,7 +171,7 @@ namespace LibWsl internal static bool __TryGetNativeToManagedMapping(IntPtr native, out global::LibWsl.WslConfigSetting managed) { - + return NativeToManagedMap.TryGetValue(native, out managed); } diff --git a/src/windows/wslsettings/Windows/OOBEWindow.xaml b/src/windows/wslsettings/Windows/OOBEWindow.xaml index 1c3d3cd..6181872 100644 --- a/src/windows/wslsettings/Windows/OOBEWindow.xaml +++ b/src/windows/wslsettings/Windows/OOBEWindow.xaml @@ -5,8 +5,8 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:windowex="using:WinUIEx" - MinWidth="480" - MinHeight="480" + MinWidth="600" + MinHeight="600" Closed="Window_Closed" mc:Ignorable="d"> diff --git a/src/windows/wslsettings/Windows/OOBEWindow.xaml.cs b/src/windows/wslsettings/Windows/OOBEWindow.xaml.cs index 383f4df..f344006 100644 --- a/src/windows/wslsettings/Windows/OOBEWindow.xaml.cs +++ b/src/windows/wslsettings/Windows/OOBEWindow.xaml.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation +// Copyright (C) Microsoft Corporation. All rights reserved. using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; @@ -41,6 +41,7 @@ public sealed partial class OOBEWindow : WindowEx, IDisposable // Theme change code picked from https://github.com/microsoft/WinUI-Gallery/pull/1239 settings.ColorValuesChanged += Settings_ColorValuesChanged; // cannot use FrameworkElement.ActualThemeChanged event + settings.TextScaleFactorChanged += Settings_TextScaleFactorChanged; WindowManager.Get(this).IsMinimizable = false; WindowManager.Get(this).IsMaximizable = false; @@ -77,6 +78,16 @@ public sealed partial class OOBEWindow : WindowEx, IDisposable }); } + // This handles text scaling changes for accessibility + private void Settings_TextScaleFactorChanged(UISettings sender, object args) + { + // This calls comes off-thread, hence we will need to dispatch it to current app's thread + dispatcherQueue.TryEnqueue(() => + { + ResizeWindow(); + }); + } + private void Window_SizeChanged(object sender, WindowSizeChangedEventArgs args) { var dpi = GetDpiForWindow(hWnd); @@ -97,9 +108,15 @@ public sealed partial class OOBEWindow : WindowEx, IDisposable private void ResizeWindow() { - float scalingFactor = (float)currentDPI / DefaultDPI; - int width = (int)(ExpectedWidth * scalingFactor); - int height = (int)(ExpectedHeight * scalingFactor); + float dpiScalingFactor = (float)currentDPI / DefaultDPI; + float textScalingFactor = (float)settings.TextScaleFactor; + + // Combine DPI scaling and text scaling for accessibility + float combinedScalingFactor = dpiScalingFactor * textScalingFactor; + + int width = (int)(ExpectedWidth * combinedScalingFactor); + int height = (int)(ExpectedHeight * combinedScalingFactor); + SizeInt32 size; size.Width = width; size.Height = height; @@ -112,6 +129,7 @@ public sealed partial class OOBEWindow : WindowEx, IDisposable { msgMonitor?.Dispose(); settings.ColorValuesChanged -= Settings_ColorValuesChanged; + settings.TextScaleFactorChanged -= Settings_TextScaleFactorChanged; this.Activated -= OnWindowActivated; if (this.Content is Microsoft.UI.Xaml.Controls.Page page) { From 7c010a1e937ac39dd91cb9315598f6853a8c3645 Mon Sep 17 00:00:00 2001 From: Ben Hillis Date: Thu, 13 Nov 2025 13:53:05 -0800 Subject: [PATCH 04/19] wslsettings: add underlines to links in about page (#13703) Co-authored-by: Ben Hillis --- .../wslsettings/Views/Settings/AboutPage.xaml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/windows/wslsettings/Views/Settings/AboutPage.xaml b/src/windows/wslsettings/Views/Settings/AboutPage.xaml index b490279..70865d7 100644 --- a/src/windows/wslsettings/Views/Settings/AboutPage.xaml +++ b/src/windows/wslsettings/Views/Settings/AboutPage.xaml @@ -7,6 +7,12 @@ xmlns:controls="using:WslSettings.Controls" behaviors:NavigationViewHeaderBehavior.HeaderMode="Never"> + + + + + + @@ -20,10 +26,10 @@ - - - - + + + + From 87c110062013ccfbad878eecc11842c70d111dfa Mon Sep 17 00:00:00 2001 From: Ben Hillis Date: Fri, 14 Nov 2025 16:12:02 -0800 Subject: [PATCH 05/19] .clang-format: add InsertBraces: true and minor fix to FormatSource.ps1 (#13712) Co-authored-by: Ben Hillis --- .clang-format | 1 + src/linux/init/SecCompDispatcher.cpp | 2 + src/linux/init/config.cpp | 4 +- src/linux/init/init.cpp | 4 +- src/linux/init/waitablevalue.h | 8 ++++ src/linux/netlinkutil/IpNeighborManager.cpp | 24 +++++++++++ src/linux/netlinkutil/Packet.h | 8 ++++ src/windows/common/WslClient.cpp | 4 +- src/windows/common/WslCoreConfig.cpp | 8 +++- src/windows/common/socket.cpp | 2 + src/windows/common/svccomm.cpp | 8 +++- src/windows/service/exe/LxssInstance.cpp | 4 +- src/windows/service/exe/LxssUserSession.cpp | 12 ++++-- src/windows/service/exe/WslCoreInstance.cpp | 8 +++- src/windows/service/exe/WslCoreVm.cpp | 48 +++++++++++++++------ tools/FormatSource.ps1.in | 15 ++++--- 16 files changed, 130 insertions(+), 30 deletions(-) diff --git a/.clang-format b/.clang-format index 8409201..040609f 100644 --- a/.clang-format +++ b/.clang-format @@ -58,6 +58,7 @@ IncludeCategories: - Regex: '^"(stdafx.h|pch.h|precomp.h)"$' Priority: -1 IndentCaseLabels: false +InsertBraces: true IndentWidth: 4 IndentWrappedFunctionNames: false KeepEmptyLinesAtTheStartOfBlocks: true diff --git a/src/linux/init/SecCompDispatcher.cpp b/src/linux/init/SecCompDispatcher.cpp index 7dc7be3..98a81c3 100644 --- a/src/linux/init/SecCompDispatcher.cpp +++ b/src/linux/init/SecCompDispatcher.cpp @@ -77,7 +77,9 @@ void SecCompDispatcher::Run() for (;;) { if (!wait_for_fd(m_notifyFd.get(), POLLIN)) + { break; + } // Clear the buffers to make the 5.15 kernel happy. notification_buffer.clear(); diff --git a/src/linux/init/config.cpp b/src/linux/init/config.cpp index f36d319..e6f60cb 100644 --- a/src/linux/init/config.cpp +++ b/src/linux/init/config.cpp @@ -955,6 +955,7 @@ try // if (Config.InitPid.has_value()) + { try { std::string LinkPath = std::format(WSL_INTEROP_SOCKET_FORMAT, WSL_TEMP_FOLDER, 1, WSL_INTEROP_SOCKET); @@ -963,7 +964,8 @@ try LOG_ERROR("symlink({}, {}) failed {}", InteropServer.Path(), LinkPath.c_str(), errno); } } - CATCH_LOG() + CATCH_LOG() + } UtilCreateWorkerThread( "Interop", [InteropChannel = std::move(InteropChannel), InteropServer = std::move(InteropServer), Elevated, &Config]() mutable { diff --git a/src/linux/init/init.cpp b/src/linux/init/init.cpp index 77495eb..229b51b 100644 --- a/src/linux/init/init.cpp +++ b/src/linux/init/init.cpp @@ -221,6 +221,7 @@ int WslEntryPoint(int Argc, char* Argv[]) { // Handle the special case for import result messages, everything else is sent to the binfmt interpreter. if (Pid == 1 && strcmp(BaseName, "init") == 0 && Argc == 3 && strcmp(Argv[1], LX_INIT_IMPORT_MESSAGE_ARG) == 0) + { try { wsl::shared::MessageWriter message; @@ -230,7 +231,8 @@ int WslEntryPoint(int Argc, char* Argv[]) read(STDIN_FILENO, buffer, sizeof(buffer)); exit(0); } - CATCH_RETURN_ERRNO() + CATCH_RETURN_ERRNO() + } ExitCode = CreateNtProcess(Argc - 1, &Argv[1]); } diff --git a/src/linux/init/waitablevalue.h b/src/linux/init/waitablevalue.h index 9b1bd58..4f297e0 100644 --- a/src/linux/init/waitablevalue.h +++ b/src/linux/init/waitablevalue.h @@ -25,7 +25,9 @@ public: { std::unique_lock lck(m_mtx); while (m_value.has_value()) + { m_cv.wait(lck); + } m_value = value; m_cv.notify_all(); } @@ -39,7 +41,9 @@ public: { std::unique_lock lck(m_mtx); while (!m_value.has_value()) + { m_cv.wait(lck); + } auto return_value = m_value.value(); m_value.reset(); m_cv.notify_all(); @@ -57,8 +61,12 @@ public: { std::unique_lock lck(m_mtx); while (!m_value.has_value()) + { if (m_cv.wait_for(lck, timeout) == std::cv_status::timeout) + { return std::nullopt; + } + } auto return_value = m_value.value(); m_value.reset(); m_cv.notify_all(); diff --git a/src/linux/netlinkutil/IpNeighborManager.cpp b/src/linux/netlinkutil/IpNeighborManager.cpp index 4f293e0..4aa2b2e 100644 --- a/src/linux/netlinkutil/IpNeighborManager.cpp +++ b/src/linux/netlinkutil/IpNeighborManager.cpp @@ -65,23 +65,41 @@ bool ParseArpReply(const T& ArpReply, uint16_t ProtocolType, const Neighbor& Sou Target.ipAddress.ConvertToBytes(TargetIp.data()); if (ArpReply.Destination != Source.macAddress) + { return false; + } if (ArpReply.EthernetType != htons(ETH_P_ARP)) + { return false; + } if (ArpReply.HardwareType != htons(ARPHRD_ETHER)) + { return false; + } if (ArpReply.ProtocolType != htons(ProtocolType)) + { return false; + } if (ArpReply.HardwareAddressLength != sizeof(ArpReply.SenderHardwareAddress)) + { return false; + } if (ArpReply.ProtocolAddressLength != sizeof(ArpReply.SenderIpAddress)) + { return false; + } if (ArpReply.Operation != htons(ARPOP_REPLY)) + { return false; + } if (ArpReply.TargetHardwareAddress != Source.macAddress) + { return false; + } if (ArpReply.TargetIpAddress != SourceIp) + { return false; + } Target.macAddress = ArpReply.SenderHardwareAddress; return true; @@ -129,7 +147,9 @@ bool IpNeighborManager::PerformNeighborDiscovery(Neighbor& Local, Neighbor& Neig while (std::chrono::steady_clock::now() < expiry) { if (!wait_for_read(packet_socket.get(), std::chrono::duration_cast(expiry - std::chrono::steady_clock::now()))) + { continue; + } int bytes_read = Syscall(read, packet_socket.get(), &ArpReply, ArpPacketSize); if (bytes_read != ArpPacketSize) { @@ -138,12 +158,16 @@ bool IpNeighborManager::PerformNeighborDiscovery(Neighbor& Local, Neighbor& Neig if (Local.getFamily() == AF_INET) { if (ParseArpReply(ArpReply.IPv4, ETH_P_IP, Local, Neighbor)) + { return true; + } } else { if (ParseArpReply(ArpReply.IPv6, ETH_P_IPV6, Local, Neighbor)) + { return true; + } } } } diff --git a/src/linux/netlinkutil/Packet.h b/src/linux/netlinkutil/Packet.h index 863fe1a..d1724a4 100644 --- a/src/linux/netlinkutil/Packet.h +++ b/src/linux/netlinkutil/Packet.h @@ -31,10 +31,14 @@ public: bool adjust_head(long count) { if ((count + data_offset) < 0) + { return false; + } if ((count + data_offset) > data_end_offset) + { return false; + } data_offset += count; return true; @@ -43,9 +47,13 @@ public: bool adjust_tail(long count) { if ((count + data_end_offset) < data_offset) + { return false; + } if ((count + data_end_offset) > Buffer.size()) + { Buffer.resize(count + data_end_offset); + } data_end_offset += count; return true; diff --git a/src/windows/common/WslClient.cpp b/src/windows/common/WslClient.cpp index 7c34582..7174641 100644 --- a/src/windows/common/WslClient.cpp +++ b/src/windows/common/WslClient.cpp @@ -1896,6 +1896,7 @@ int wsl::windows::common::WslClient::Main(_In_ LPCWSTR commandLine) // Print error messages for failures. if (FAILED(result)) + { try { std::wstring errorString{}; @@ -1949,7 +1950,8 @@ int wsl::windows::common::WslClient::Main(_In_ LPCWSTR commandLine) } } } - CATCH_LOG() + CATCH_LOG() + } if (g_promptBeforeExit) { diff --git a/src/windows/common/WslCoreConfig.cpp b/src/windows/common/WslCoreConfig.cpp index f4e39d2..ee8b780 100644 --- a/src/windows/common/WslCoreConfig.cpp +++ b/src/windows/common/WslCoreConfig.cpp @@ -400,6 +400,7 @@ void wsl::core::Config::Initialize(_In_opt_ HANDLE UserToken) // Load NAT configuration from the registry. if (NetworkingMode == wsl::core::NetworkingMode::Nat) + { try { const auto machineKey = wsl::windows::common::registry::OpenLxssMachineKey(); @@ -410,10 +411,12 @@ void wsl::core::Config::Initialize(_In_opt_ HANDLE UserToken) const auto userKey = wsl::windows::common::registry::OpenLxssUserKey(); NatIpAddress = wsl::windows::common::registry::ReadString(userKey.get(), nullptr, c_natIpAddress, L""); } - CATCH_LOG() + CATCH_LOG() + } // Due to an issue with Global Secure Access Client, do not use DNS tunneling if the service is present. if (EnableDnsTunneling) + { try { // Open a handle to the service control manager and check if the inbox service is registered. @@ -438,7 +441,8 @@ void wsl::core::Config::Initialize(_In_opt_ HANDLE UserToken) } } } - CATCH_LOG() + CATCH_LOG() + } // Ensure that settings are consistent (disable features that require other features that are not present). if (EnableSafeMode) diff --git a/src/windows/common/socket.cpp b/src/windows/common/socket.cpp index 50fe0ae..edc49aa 100644 --- a/src/windows/common/socket.cpp +++ b/src/windows/common/socket.cpp @@ -105,6 +105,7 @@ int wsl::windows::common::socket::ReceiveNoThrow( Overlapped.hEvent = OverlappedEvent.get(); DWORD BytesReturned{}; if (WSARecv(Socket, &VectorBuffer, 1, &BytesReturned, &Flags, &Overlapped, nullptr) != 0) + { try { BytesReturned = SOCKET_ERROR; @@ -117,6 +118,7 @@ int wsl::windows::common::socket::ReceiveNoThrow( // Receive will call GetLastError to look for the error code SetLastError(wil::ResultFromCaughtException()); } + } return BytesReturned; } diff --git a/src/windows/common/svccomm.cpp b/src/windows/common/svccomm.cpp index d2f1c09..0af212e 100644 --- a/src/windows/common/svccomm.cpp +++ b/src/windows/common/svccomm.cpp @@ -751,11 +751,13 @@ wsl::windows::common::SvcComm::LaunchProcess( // if ((WI_IsFlagSet(LaunchFlags, LXSS_LAUNCH_FLAG_ENABLE_INTEROP)) && (ServerPortHandle)) + { try { InitializeInterop(ServerPortHandle.get(), DistributionId); } - CATCH_LOG() + CATCH_LOG() + } ServerPortHandle.reset(); @@ -823,11 +825,13 @@ wsl::windows::common::SvcComm::LaunchProcess( // if (WI_IsFlagSet(LaunchFlags, LXSS_LAUNCH_FLAG_ENABLE_INTEROP)) + { try { SpawnWslHost(InteropSocket.get(), DistributionId, &InstanceId); } - CATCH_LOG() + CATCH_LOG() + } // // Begin reading messages from the utility vm. diff --git a/src/windows/service/exe/LxssInstance.cpp b/src/windows/service/exe/LxssInstance.cpp index 2700366..3f4a300 100644 --- a/src/windows/service/exe/LxssInstance.cpp +++ b/src/windows/service/exe/LxssInstance.cpp @@ -346,6 +346,7 @@ bool LxssInstance::RequestStop(_In_ bool Force) // Send the message to the init daemon to check if the instance can be terminated. bool shutdown = true; if (m_InitMessagePort) + { try { auto lock = m_InitMessagePort->Lock(); @@ -358,7 +359,8 @@ bool LxssInstance::RequestStop(_In_ bool Force) m_InitMessagePort->Receive(&terminateResponse, sizeof(terminateResponse)); shutdown = terminateResponse.Result; } - CATCH_LOG() + CATCH_LOG() + } return shutdown; } diff --git a/src/windows/service/exe/LxssUserSession.cpp b/src/windows/service/exe/LxssUserSession.cpp index d0dcc04..2e5611c 100644 --- a/src/windows/service/exe/LxssUserSession.cpp +++ b/src/windows/service/exe/LxssUserSession.cpp @@ -2952,11 +2952,13 @@ void LxssUserSessionImpl::_DeleteDistributionLockHeld(_In_ const LXSS_DISTRO_CON if (PathFileExistsW(Configuration.VhdFilePath.c_str())) { if (m_utilityVm) + { try { m_utilityVm->EjectVhd(Configuration.VhdFilePath.c_str()); } - CATCH_LOG() + CATCH_LOG() + } if (WI_IsFlagSet(Flags, LXSS_DELETE_DISTRO_FLAGS_VHD)) { @@ -2997,13 +2999,15 @@ void LxssUserSessionImpl::_DeleteDistributionLockHeld(_In_ const LXSS_DISTRO_CON // Remove start menu shortcuts for WSLg applications. if (WI_IsFlagSet(Flags, LXSS_DELETE_DISTRO_FLAGS_WSLG_SHORTCUTS)) + { try { const auto dllPath = wsl::windows::common::wslutil::GetBasePath() / WSLG_TS_PLUGIN_DLL; static LxssDynamicFunction removeAppProvider(dllPath.c_str(), "RemoveAppProvider"); LOG_IF_FAILED(removeAppProvider(Configuration.Name.c_str())); } - CATCH_LOG() + CATCH_LOG() + } // If the basepath is empty, delete it. try @@ -3059,11 +3063,13 @@ std::vector LxssUserSessionImpl::_EnumerateDistributio // Ensure that the default distribution is still valid. if (!orphanedDistributions.empty()) + { try { _GetDefaultDistro(LxssKey); } - CATCH_LOG() + CATCH_LOG() + } return distributions; } diff --git a/src/windows/service/exe/WslCoreInstance.cpp b/src/windows/service/exe/WslCoreInstance.cpp index 213d2cc..74fe316 100644 --- a/src/windows/service/exe/WslCoreInstance.cpp +++ b/src/windows/service/exe/WslCoreInstance.cpp @@ -412,13 +412,15 @@ void WslCoreInstance::Initialize() // Launch the interop server with the user's token. if (response.InteropPort != LX_INIT_UTILITY_VM_INVALID_PORT) + { try { const wil::unique_socket socket{wsl::windows::common::hvsocket::Connect(m_runtimeId, response.InteropPort)}; wil::unique_handle info{wsl::windows::common::helpers::LaunchInteropServer( nullptr, reinterpret_cast(socket.get()), nullptr, nullptr, &m_runtimeId, m_userToken.get())}; } - CATCH_LOG() + CATCH_LOG() + } // Initialization was successful. m_initialized = true; @@ -463,6 +465,7 @@ bool WslCoreInstance::RequestStop(_In_ bool Force) bool shutdown = true; std::lock_guard lock(m_lock); if (m_initChannel) + { try { LX_INIT_TERMINATE_INSTANCE terminateMessage{}; @@ -477,7 +480,8 @@ bool WslCoreInstance::RequestStop(_In_ bool Force) shutdown = message->Result; } } - CATCH_LOG() + CATCH_LOG() + } return shutdown; } diff --git a/src/windows/service/exe/WslCoreVm.cpp b/src/windows/service/exe/WslCoreVm.cpp index adb08bb..d235078 100644 --- a/src/windows/service/exe/WslCoreVm.cpp +++ b/src/windows/service/exe/WslCoreVm.cpp @@ -282,17 +282,20 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken // N.B. wslhost.exe is launched at medium integrity level and its lifetime // is tied to the lifetime of the utility VM. if (m_vmConfig.EnableDebugConsole || !m_vmConfig.DebugConsoleLogFile.empty()) + { try { m_vmConfig.EnableDebugConsole = true; m_comPipe0 = wsl::windows::common::helpers::GetUniquePipeName(); } - CATCH_LOG() + CATCH_LOG() + } // If the system supports virtio console serial ports, use dmesg capture for telemetry and/or debug output. // Legacy serial is much slower, so this is not enabled without virtio console support. m_vmConfig.EnableDebugShell &= IsVirtioSerialConsoleSupported(); if (IsVirtioSerialConsoleSupported()) + { try { bool enableTelemetry = TraceLoggingProviderEnabled(g_hTraceLoggingProvider, WINEVENT_LEVEL_INFO, 0); @@ -309,9 +312,11 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken // Initialize the guest telemetry logger. m_gnsTelemetryLogger = GuestTelemetryLogger::Create(VmId, m_vmExitEvent); } - CATCH_LOG() + CATCH_LOG() + } if (m_vmConfig.EnableDebugConsole) + { try { // If specified, create a file to log the debug console output. @@ -328,7 +333,8 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken wsl::windows::common::helpers::LaunchDebugConsole( m_comPipe0.c_str(), !!m_dmesgCollector, m_restrictedToken.get(), logFile ? logFile.get() : nullptr, !m_vmConfig.EnableTelemetry); } - CATCH_LOG() + CATCH_LOG() + } // Create the utility VM and store the runtime ID. std::wstring json = GenerateConfigJson(); @@ -400,12 +406,14 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken THROW_IF_FAILED(wil::ExpandEnvironmentStringsW(L"%SystemRoot%\\System32\\lxss\\lib", path)); if (wsl::windows::common::filesystem::FileExists(path.c_str())) + { try { addShare(TEXT(LXSS_GPU_INBOX_LIB_SHARE), path.c_str()); m_enableInboxGpuLibs = true; } - CATCH_LOG() + CATCH_LOG() + } #ifdef WSL_GPU_LIB_PATH @@ -482,6 +490,7 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken // the user does not have write access. ULONG swapLun = ULONG_MAX; if ((m_systemDistroDeviceId != ULONG_MAX) && (m_vmConfig.SwapSizeBytes > 0)) + { try { { @@ -524,7 +533,8 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken swapLun = AttachDiskLockHeld(m_vmConfig.SwapFilePath.c_str(), DiskType::VHD, MountFlags::None, {}, false, m_userToken.get()); } - CATCH_LOG() + CATCH_LOG() + } // Validate that the requesting network mode is supported. // @@ -777,11 +787,13 @@ WslCoreVm::~WslCoreVm() noexcept // If the notification did not arrive within the timeout, the VM is // forcefully terminated. if (forcedTerminate) + { try { wsl::windows::common::hcs::TerminateComputeSystem(m_system.get()); } - CATCH_LOG() + CATCH_LOG() + } } m_vmExitEvent.wait(UTILITY_VM_TERMINATE_TIMEOUT); @@ -840,33 +852,40 @@ WslCoreVm::~WslCoreVm() noexcept } if (WI_IsFlagSet(Entry.second.Flags, DiskStateFlags::AccessGranted)) + { try { wsl::windows::common::hcs::RevokeVmAccess(m_machineId.c_str(), Entry.first.Path.c_str()); } - CATCH_LOG() + CATCH_LOG() + } }); // Delete the swap vhd if one was created. if (m_swapFileCreated) + { try { const auto runAsUser = wil::impersonate_token(m_userToken.get()); LOG_IF_WIN32_BOOL_FALSE(DeleteFileW(m_vmConfig.SwapFilePath.c_str())); } - CATCH_LOG() + CATCH_LOG() + } // Delete the temp folder if it was created. if (m_tempDirectoryCreated) + { try { const auto runAsUser = wil::impersonate_token(m_userToken.get()); wil::RemoveDirectoryRecursive(m_tempPath.c_str()); } - CATCH_LOG() + CATCH_LOG() + } // Delete the mstsc.exe local devices key if one was created. if (m_localDevicesKeyCreated) + { try { const auto runAsUser = wil::impersonate_token(m_userToken.get()); @@ -874,7 +893,8 @@ WslCoreVm::~WslCoreVm() noexcept const auto key = wsl::windows::common::registry::CreateKey(userKey.get(), c_localDevicesKey, KEY_SET_VALUE); THROW_IF_WIN32_ERROR(::RegDeleteKeyValueW(key.get(), nullptr, m_machineId.c_str())); } - CATCH_LOG() + CATCH_LOG() + } WSL_LOG("TerminateVmStop"); } @@ -1621,6 +1641,7 @@ std::wstring WslCoreVm::GenerateConfigJson() // N.B. This is done because arm64 and some older amd64 processors do not support nested virtualization. // Nested virtualization not supported on Windows 10. if (m_vmConfig.EnableNestedVirtualization) + { try { std::vector processorFeatures{}; @@ -1638,7 +1659,8 @@ std::wstring WslCoreVm::GenerateConfigJson() EMIT_USER_WARNING(wsl::shared::Localization::MessageNestedVirtualizationNotSupported()); } } - CATCH_LOG() + CATCH_LOG() + } #ifdef _AMD64_ @@ -1881,12 +1903,14 @@ void WslCoreVm::InitializeGuest() if (LXSS_ENABLE_GUI_APPS()) { if (m_vmConfig.EnableVirtio) + { try { MountSharedMemoryDevice(c_virtiofsClassId, L"wslg", L"wslg", WSLG_SHARED_MEMORY_SIZE_MB); m_sharedMemoryRoot = std::format(L"WSL\\{}\\wslg", m_machineId); } - CATCH_LOG() + CATCH_LOG() + } try { diff --git a/tools/FormatSource.ps1.in b/tools/FormatSource.ps1.in index feaef13..b07b726 100644 --- a/tools/FormatSource.ps1.in +++ b/tools/FormatSource.ps1.in @@ -40,7 +40,12 @@ $FilePatterns = "\.(h|cpp|hpp|c|hxx)$" $IgnoreFolders = "(out|.git|.vs|.vscode|bin|CMakeFiles|generated|debug|x64|packages|_deps)$" -$RepoRoot = (Resolve-Path "$PSScriptRoot") +# Handle both execution methods: direct PowerShell and powershell.exe script invocation +if ([string]::IsNullOrEmpty($PSScriptRoot)) { + $RepoRoot = (Get-Location).Path +} else { + $RepoRoot = (Resolve-Path "$PSScriptRoot") +} <# .SYNOPSIS @@ -170,9 +175,9 @@ function Format-Directory { $FilesToFormat = @() if ((Get-Item -Path $Path) -is [System.IO.DirectoryInfo]) { Get-ChildItem -Path $Path -File ` - | Where-Object { $_ -match $FilePatterns } ` + | Where-Object { $_.Name -match $FilePatterns } ` | ForEach-Object { - $FilePath = "$Path\$_" + $FilePath = "$Path\$($_.Name)" if (($null -eq $ModifiedFiles) -or ($ModifiedFiles -contains $FilePath)) { if (!($FilePath -match "Intermediate")) { $FilesToFormat += $FilePath @@ -180,9 +185,9 @@ function Format-Directory { } } Get-ChildItem -Path $Path -Directory ` - | Where-Object { $_ -notmatch $IgnoreFolders } ` + | Where-Object { $_.Name -notmatch $IgnoreFolders } ` | ForEach-Object { - $SubResult = (Format-Directory -Path "$Path\$_" ` + $SubResult = (Format-Directory -Path "$Path\$($_.Name)" ` -ClangFormat $ClangFormat ` -RepoRoot $RepoRoot ` -FilePatterns $FilePatterns ` From b6cc29eefcda6fd52e0093f5e946c887606200ed Mon Sep 17 00:00:00 2001 From: Blue Date: Mon, 17 Nov 2025 19:18:05 +0000 Subject: [PATCH 06/19] Localization change from build: 134015316 (#13731) Co-authored-by: WSL localization --- localization/strings/es-ES/Resources.resw | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/localization/strings/es-ES/Resources.resw b/localization/strings/es-ES/Resources.resw index 8f764d9..6fcebec 100644 --- a/localization/strings/es-ES/Resources.resw +++ b/localization/strings/es-ES/Resources.resw @@ -537,7 +537,7 @@ Argumentos para administrar distribuciones en el Subsistema de Windows para Linu --export <Distro> <FileName> [Options] Exporta la distribución a un archivo tar. - El nombre de archivo puede ser: para stdout. + El nombre de archivo puede ser - para stdout. Opciones: --format <Format> @@ -545,7 +545,7 @@ Argumentos para administrar distribuciones en el Subsistema de Windows para Linu --import <Distro> <InstallLocation> <FileName> [Options] Importa el archivo tar especificado como una nueva distribución. - El nombre de archivo puede ser : para stdin. + El nombre de archivo puede ser - para stdin. Opciones: --version <Version> From 7226b05100b20955692ec83914644c07d035047f Mon Sep 17 00:00:00 2001 From: Ben Hillis Date: Tue, 18 Nov 2025 08:19:50 -0800 Subject: [PATCH 07/19] wslsettings: ensure selected setting is auto-expanded and selected (#13689) * wslsettings: ensure selected setting is auto-selected Implement keyboard focus management for SettingsExpander controls across settings pages. This resolves an accessibility issue reported internally. * add asserts --------- Co-authored-by: Ben Hillis --- .../wslsettings/Helpers/RuntimeHelper.cs | 37 +++++++++++++++++++ .../Views/Settings/DeveloperPage.xaml | 12 +++--- .../Views/Settings/DeveloperPage.xaml.cs | 9 +++++ .../Views/Settings/FileSystemPage.xaml | 4 +- .../Views/Settings/FileSystemPage.xaml.cs | 18 +++++++++ .../Views/Settings/MemAndProcPage.xaml | 16 ++++---- .../Views/Settings/MemAndProcPage.xaml.cs | 10 +++++ .../Views/Settings/NetworkingPage.xaml | 8 ++-- .../Views/Settings/NetworkingPage.xaml.cs | 8 ++++ .../Views/Settings/OptionalFeaturesPage.xaml | 4 +- .../Settings/OptionalFeaturesPage.xaml.cs | 8 ++++ 11 files changed, 112 insertions(+), 22 deletions(-) diff --git a/src/windows/wslsettings/Helpers/RuntimeHelper.cs b/src/windows/wslsettings/Helpers/RuntimeHelper.cs index 5a3592a..58e33de 100644 --- a/src/windows/wslsettings/Helpers/RuntimeHelper.cs +++ b/src/windows/wslsettings/Helpers/RuntimeHelper.cs @@ -1,7 +1,9 @@ // Copyright (C) Microsoft Corporation. All rights reserved. +using CommunityToolkit.WinUI.Controls; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Input; +using System.Diagnostics; using System.Reflection; using System.Runtime.InteropServices; using System.Text; @@ -47,4 +49,39 @@ public class RuntimeHelper FindNextElementOptions fneo = new() { SearchRoot = button.XamlRoot.Content }; FocusManager.TryMoveFocus(FocusNavigationDirection.Previous, fneo); } + + public static void SetupSettingsExpanderFocusManagement(Microsoft.UI.Xaml.FrameworkElement expander, Microsoft.UI.Xaml.Controls.Control firstFocusableElement) + { + if (expander is CommunityToolkit.WinUI.Controls.SettingsExpander settingsExpander) + { + settingsExpander.RegisterPropertyChangedCallback(CommunityToolkit.WinUI.Controls.SettingsExpander.IsExpandedProperty, (sender, dp) => + { + if (sender is CommunityToolkit.WinUI.Controls.SettingsExpander se && se.IsExpanded) + { + System.EventHandler? layoutHandler = null; + layoutHandler = (s, e) => + { + se.LayoutUpdated -= layoutHandler; + firstFocusableElement.Focus(Microsoft.UI.Xaml.FocusState.Keyboard); + }; + + se.LayoutUpdated += layoutHandler; + } + }); + } + } + + public static void SetupExpanderFocusManagementByName(Microsoft.UI.Xaml.FrameworkElement parent, string expanderName, string textBoxName) + { + var expander = parent.FindName(expanderName) as Microsoft.UI.Xaml.FrameworkElement; + var textBox = parent.FindName(textBoxName) as Microsoft.UI.Xaml.Controls.Control; + + Debug.Assert(expander != null, $"Expander '{expanderName}' not found"); + Debug.Assert(textBox != null, $"TextBox '{textBoxName}' not found"); + + if (expander != null && textBox != null) + { + SetupSettingsExpanderFocusManagement(expander, textBox); + } + } } \ No newline at end of file diff --git a/src/windows/wslsettings/Views/Settings/DeveloperPage.xaml b/src/windows/wslsettings/Views/Settings/DeveloperPage.xaml index db83f8a..7c1280c 100644 --- a/src/windows/wslsettings/Views/Settings/DeveloperPage.xaml +++ b/src/windows/wslsettings/Views/Settings/DeveloperPage.xaml @@ -25,12 +25,12 @@ - + -