Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions localization/strings/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,10 @@ Build time: {}</value>
<value>The custom system distribution specified in {} was not found or is not the correct format.</value>
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
</data>
<data name="MessageSystemDistroMissing" xml:space="preserve">
<value>A required WSL package file is missing: '{}'. Please run 'wsl --update' to restore it.</value>
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated. {Locked="WSL"} {Locked="wsl --update"}</comment>
</data>
<data name="MessageWslgUsage" xml:space="preserve">
<value>Copyright (c) Microsoft Corporation. All rights reserved.
For privacy information about this product please visit https://aka.ms/privacy.
Expand Down
2 changes: 1 addition & 1 deletion msipackage/package.wix.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Package Name="Windows Subsystem for Linux" Language="1033" InstallerVersion="500" Version="${PACKAGE_VERSION}" Manufacturer="Microsoft Corporation" UpgradeCode="6D5B792B-1EDC-4DE9-8EAD-201B820F8E82" Scope="perMachine" Compressed="${COMPRESS_PACKAGE}">
<MajorUpgrade AllowDowngrades="yes" Disallow="no" />
<MajorUpgrade AllowDowngrades="yes" Disallow="no" Schedule="afterInstallInitialize" />
<MediaTemplate EmbedCab="yes" />

<StandardDirectory Id="ProgramFiles64Folder">
Expand Down
6 changes: 6 additions & 0 deletions src/windows/common/wslutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ static const std::map<HRESULT, LPCWSTR> g_commonErrors{
X(WSL_E_DISTRIBUTION_NAME_NEEDED),
X(WSL_E_INVALID_JSON),
X(WSL_E_VM_CRASHED),
X(WSL_E_SYSTEM_DISTRO_MISSING),
X(WSL_E_NOT_A_LINUX_DISTRO),
X(WSLC_E_CONTAINER_PREFIX_AMBIGUOUS),
X(E_ACCESSDENIED),
Expand Down Expand Up @@ -783,6 +784,11 @@ std::wstring wsl::windows::common::wslutil::GetErrorString(HRESULT result)
case WSL_E_NOT_A_LINUX_DISTRO:
return Localization::MessageInvalidDistributionTar();

case WSL_E_SYSTEM_DISTRO_MISSING:
// Generic fallback for paths that don't set a specific user message (e.g., WSLC).
// WslCoreVm.cpp paths use THROW_HR_WITH_USER_ERROR_IF with the specific missing path.
return Localization::MessageSystemDistroMissing(wslutil::GetMsiPackagePath().value_or(L""));

case WSL_E_INVALID_USAGE:
{
const auto* context = wsl::windows::common::ExecutionContext::Current();
Expand Down
10 changes: 10 additions & 0 deletions src/windows/service/exe/HcsVirtualMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Module Name:
#include "NatNetworking.h"
#include "wslsecurity.h"
#include "wslutil.h"
#include "filesystem.hpp"
#include "lxinitshared.h"
#include "DnsResolver.h"

Expand Down Expand Up @@ -221,6 +222,15 @@ HcsVirtualMachine::HcsVirtualMachine(_In_ const WSLCSessionSettings* Settings)
#endif
}

// Validate required package files exist before attempting to attach them.
// Only check default (non-override) paths — overrides are user-provided.
if (Settings->RootVhdOverride == nullptr)
{
THROW_HR_IF(WSL_E_SYSTEM_DISTRO_MISSING, !wsl::windows::common::filesystem::FileExists(rootVhdPath.c_str()));
}

THROW_HR_IF(WSL_E_SYSTEM_DISTRO_MISSING, !wsl::windows::common::filesystem::FileExists(kernelModulesPath.c_str()));
Comment on lines +229 to +232
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By design — HcsVirtualMachine.cpp doesn't have ExecutionContext. The fallback in GetErrorString now uses GetMsiPackagePath() so users get a meaningful message.


// Setup boot VHDs
hcs::Scsi scsiController{};
auto attachScsiDisk = [&](PCWSTR path) {
Expand Down
9 changes: 8 additions & 1 deletion src/windows/service/exe/WslCoreVm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,10 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken
#else

m_vmConfig.KernelModulesPath = m_rootFsPath / L"modules.vhd";
THROW_HR_WITH_USER_ERROR_IF(
WSL_E_SYSTEM_DISTRO_MISSING,
Localization::MessageSystemDistroMissing(m_vmConfig.KernelModulesPath),
!wsl::windows::common::filesystem::FileExists(m_vmConfig.KernelModulesPath.c_str()));

#endif
}
Expand Down Expand Up @@ -1421,7 +1425,10 @@ std::wstring WslCoreVm::GenerateConfigJson()

m_systemDistroDeviceType = LxMiniInitMountDeviceTypeLun;
m_vmConfig.SystemDistroPath = (m_installPath / L"system.vhd").wstring();
WI_ASSERT(wsl::windows::common::filesystem::FileExists(m_vmConfig.SystemDistroPath.c_str()));
THROW_HR_WITH_USER_ERROR_IF(
WSL_E_SYSTEM_DISTRO_MISSING,
Localization::MessageSystemDistroMissing(m_vmConfig.SystemDistroPath),
!wsl::windows::common::filesystem::FileExists(m_vmConfig.SystemDistroPath.c_str()));
Comment on lines +1428 to +1431
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Manual runtime rollback test documented in PR comments validates the core scenario (locked file → install failure → rollback → VHDs intact). Automated test would require deleting system.vhd from a live install — happy to add in a follow-up PR.


#endif
}
Expand Down
1 change: 1 addition & 0 deletions src/windows/service/inc/wslservice.idl
Original file line number Diff line number Diff line change
Expand Up @@ -395,3 +395,4 @@ cpp_quote("#define WSL_E_DISK_CORRUPTED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_IT
cpp_quote("#define WSL_E_DISTRIBUTION_NAME_NEEDED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSL_E_BASE + 0x30) /* 0x80040330 */")
cpp_quote("#define WSL_E_INVALID_JSON MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSL_E_BASE + 0x31) /* 0x80040331 */")
cpp_quote("#define WSL_E_VM_CRASHED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSL_E_BASE + 0x32) /* 0x80040332 */")
cpp_quote("#define WSL_E_SYSTEM_DISTRO_MISSING MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSL_E_BASE + 0x33) /* 0x80040333 */")