Files
WSL/localization
Ben Hillis df33fb3307 Surface MSI reboot-required failures instead of silently dropping VHDs
When the embedded MSI in the Microsoft Store MSIX cannot replace a locked
file (most commonly system.vhd, which is mounted whenever a WSL2 instance
is running), Windows Installer renames the existing file to
C:\Windows\Installer\Config.Msi\<hex>.rbf, schedules the new file via
MoveFileEx(MOVEFILE_DELAY_UNTIL_REBOOT), and returns
ERROR_SUCCESS_REBOOT_REQUIRED (3010).

InstallMsipackageImpl in wslinstaller silently converted 3010 to
ERROR_SUCCESS and returned success to its caller. The user was told
nothing; their next wsl invocation hit a now-empty C:\Program Files\WSL
install dir (system.vhd physically gone until reboot) and produced a
confusing "vhd missing" failure - perceived as data loss.

This change:

* Stops swallowing 3010 in InstallMsipackageImpl. The MSI log is now
  preserved on 3010 (previously deleted) to aid diagnostics.
* Sets a volatile registry marker
  (HKLM\Software\Microsoft\Windows\CurrentVersion\Lxss\MSI\RebootPending)
  using REG_OPTION_VOLATILE so the kernel auto-clears it on reboot. No
  cleanup path is needed; the marker is gone iff the user has rebooted.
* Adds a marker check in LxssUserSession::_CreateInstance (service
  side) which throws a localized user-facing error
  (MessageUpdateRebootRequired) any time a client tries to launch a
  distro while the reboot is pending. This catches all distro-launching
  client paths through the single service entry point: wsl.exe (lifted
  and MSI-installed), wslg.exe, bash.exe, VS Code Remote-WSL, etc.
* Also checks the marker on entry to CallMsiPackage and throws on 3010
  in WaitForMsiInstall, so the wsl --update / lifted-client paths
  surface the same error.

User-visible behavior:

  > wsl
  WSL was updated but a system restart is required to complete the
  installation. Please reboot your machine and try again.
  Error code: Wsl/Service/CreateInstance/0x80070bc2

The user reboots; the volatile key is destroyed by the kernel; Windows'
pending file-rename queue swaps the staged file into place; WSL works
again.

Adds an integration test, InstallerTests::UpgradeWithLockedFileReportsRebootRequired,
that exercises the full path: uninstalls the MSI, memory-maps a dummy
file at the install path to make it unrenameable, runs the MSIX
installer to drive the WslInstaller service, polls for the marker, then
verifies wsl echo OK fails with the expected message before cleaning up.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-20 13:48:57 -07:00
..