diff --git a/localization/strings/en-US/Resources.resw b/localization/strings/en-US/Resources.resw
index 42030d93b..929bbb4e2 100644
--- a/localization/strings/en-US/Resources.resw
+++ b/localization/strings/en-US/Resources.resw
@@ -217,9 +217,6 @@ Install using 'wsl.exe {} <Distro>'.
To get a list of valid distributions, use 'wsl.exe --list --online'.
{FixedPlaceholder="{}"}{Locked="--list "}{Locked="--online'"}Command line arguments, file names and string inserts should not be translated
-
- The Windows Subsystem for Linux instance has terminated.
-
Invalid command line argument: {}
Please use '{} --help' to get a list of supported arguments.
@@ -853,6 +850,10 @@ For information please visit https://aka.ms/wslinstall
Failed to create the swap disk in '{}': {}
{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated
+
+ Failed to create disk '{}': {}
+ {FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated
+
Nested virtualization is not supported on this machine.
diff --git a/src/windows/common/WslCoreFilesystem.cpp b/src/windows/common/WslCoreFilesystem.cpp
index 5f80fa847..989eee13c 100644
--- a/src/windows/common/WslCoreFilesystem.cpp
+++ b/src/windows/common/WslCoreFilesystem.cpp
@@ -66,11 +66,15 @@ void wsl::core::filesystem::CreateVhd(_In_ LPCWSTR target, _In_ ULONGLONG maximu
// N.B. This ensures that HcsGrantVmAccess is able to add the required ACL
// to the VHD because the operation is done while impersonating the user.
auto sd = windows::common::security::CreateSecurityDescriptor(userSid);
+
wil::unique_hfile vhd{};
- THROW_IF_WIN32_ERROR_MSG(
- ::CreateVirtualDisk(&storageType, target, VIRTUAL_DISK_ACCESS_NONE, &sd, flags, 0, &createVhdParameters, nullptr, &vhd),
- "Path: %ls",
- target);
+ auto result = HRESULT_FROM_WIN32(
+ ::CreateVirtualDisk(&storageType, target, VIRTUAL_DISK_ACCESS_NONE, &sd, flags, 0, &createVhdParameters, nullptr, &vhd));
+ if (FAILED(result))
+ {
+ THROW_HR_WITH_USER_ERROR(
+ result, shared::Localization::MessageFailedToCreateDisk(target, windows::common::wslutil::GetErrorString(result)));
+ }
}
wil::unique_handle wsl::core::filesystem::OpenVhd(_In_ LPCWSTR Path, _In_ VIRTUAL_DISK_ACCESS_MASK Mask)
diff --git a/src/windows/common/wslutil.cpp b/src/windows/common/wslutil.cpp
index d9a71e77f..a598a5743 100644
--- a/src/windows/common/wslutil.cpp
+++ b/src/windows/common/wslutil.cpp
@@ -636,22 +636,12 @@ std::wstring wsl::windows::common::wslutil::GetErrorString(HRESULT result)
case WSL_E_DEFAULT_DISTRO_NOT_FOUND:
return Localization::MessageNoDefaultDistro();
- case HRESULT_FROM_WIN32(WSAECONNABORTED):
- case HRESULT_FROM_WIN32(ERROR_SHUTDOWN_IN_PROGRESS):
- return Localization::MessageInstanceTerminated();
-
case WSL_E_DISTRO_NOT_FOUND:
return Localization::MessageDistroNotFound();
- case HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS):
- return Localization::MessageDistroNameAlreadyExists();
-
case WSL_E_DISTRIBUTION_NAME_NEEDED:
return Localization::MessageDistributionNameNeeded();
- case HRESULT_FROM_WIN32(ERROR_FILE_EXISTS):
- return Localization::MessageDistroInstallPathAlreadyExists();
-
case WSL_E_TOO_MANY_DISKS_ATTACHED:
return Localization::MessageTooManyDisks();
diff --git a/src/windows/service/exe/LxssUserSession.cpp b/src/windows/service/exe/LxssUserSession.cpp
index 2ad6469c9..ed8c9c1bb 100644
--- a/src/windows/service/exe/LxssUserSession.cpp
+++ b/src/windows/service/exe/LxssUserSession.cpp
@@ -3787,11 +3787,12 @@ void LxssUserSessionImpl::_ValidateDistributionNameAndPathNotInUse(
if (Name != nullptr && wsl::shared::string::IsEqual(Name, configuration.Name, true))
{
- THROW_HR_MSG(
- (configuration.State == LxssDistributionStateInstalled) ? HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) : E_ILLEGAL_STATE_CHANGE,
- "%ls already registered (state = %d)",
- Name,
- configuration.State);
+ THROW_HR_WITH_USER_ERROR_IF(
+ HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS),
+ wsl::shared::Localization::MessageDistroNameAlreadyExists(),
+ configuration.State == LxssDistributionStateInstalled);
+
+ THROW_HR_MSG(E_ILLEGAL_STATE_CHANGE, "%ls already registered (state = %d)", Name, configuration.State);
}
if (Path != nullptr)
@@ -3803,8 +3804,9 @@ void LxssUserSessionImpl::_ValidateDistributionNameAndPathNotInUse(
}
// Ensure another distribution by a different name is not already registered to the same location.
- THROW_HR_IF(
+ THROW_HR_WITH_USER_ERROR_IF(
HRESULT_FROM_WIN32(ERROR_FILE_EXISTS),
+ wsl::shared::Localization::MessageDistroInstallPathAlreadyExists(),
wsl::windows::common::string::IsPathComponentEqual(error ? configuration.BasePath.native() : canonicalDistroPath.native(), Path));
}
}
diff --git a/test/windows/UnitTests.cpp b/test/windows/UnitTests.cpp
index b1d2284a9..ee275aa12 100644
--- a/test/windows/UnitTests.cpp
+++ b/test/windows/UnitTests.cpp
@@ -960,7 +960,7 @@ class UnitTests
VERIFY_IS_FALSE(!vhdFile);
}
- auto validateOutput = [](LPCWSTR commandLine, LPCWSTR expectedOutput, DWORD expectedExitCode = -1) {
+ auto validateOutput = [](LPCWSTR commandLine, const std::wstring& expectedOutput, DWORD expectedExitCode = -1) {
auto [out, err] = LxsstuLaunchWslAndCaptureOutput(commandLine, expectedExitCode);
VERIFY_ARE_EQUAL(expectedOutput, out);
VERIFY_ARE_EQUAL(L"", err);
@@ -968,10 +968,22 @@ class UnitTests
auto version = LxsstuVmMode() ? 2 : 1;
auto commandLine = std::format(L"--import dummy {} {} --version {}", LXSST_IMPORT_DISTRO_TEST_DIR, tarFileName, version);
- validateOutput(
- commandLine.c_str(),
- L"The supplied install location is already in use.\r\n"
- L"Error code: Wsl/Service/RegisterDistro/ERROR_FILE_EXISTS\r\n");
+ if (LxsstuVmMode())
+ {
+ validateOutput(
+ commandLine.c_str(),
+ std::format(
+ L"Failed to create disk '{}ext4.vhdx': The file exists. \r\n"
+ L"Error code: Wsl/Service/RegisterDistro/ERROR_FILE_EXISTS\r\n",
+ LXSST_IMPORT_DISTRO_TEST_DIR));
+ }
+ else
+ {
+ validateOutput(
+ commandLine.c_str(),
+ L"The file exists. \r\n"
+ L"Error code: Wsl/Service/RegisterDistro/ERROR_FILE_EXISTS\r\n");
+ }
commandLine = std::format(L"--import dummy {} {} --version {}", LXSST_IMPORT_DISTRO_TEST_DIR, vhdFileName, version);
validateOutput(commandLine.c_str(), L"This looks like a VHD file. Use --vhd to import a VHD instead of a tar.\r\n");
@@ -985,6 +997,25 @@ class UnitTests
L"Error code: Wsl/Service/RegisterDistro/WSL_E_WSL2_NEEDED\r\n");
}
+ //
+ // Verify that importing a distribution with a different name into the same path as an
+ // already registered distribution (test_distro) returns the path-already-exists error.
+ //
+
+ {
+ const auto distroKey = OpenDistributionKey(LXSS_DISTRO_NAME_TEST_L);
+ VERIFY_IS_TRUE(!!distroKey);
+
+ auto basePath = wsl::windows::common::registry::ReadString(distroKey.get(), nullptr, L"BasePath", L"");
+ VERIFY_IS_FALSE(basePath.empty());
+
+ commandLine = std::format(L"--import path-conflict-distro \"{}\" \"{}\" --version {}", basePath, tarFileName, version);
+ validateOutput(
+ commandLine.c_str(),
+ L"The supplied install location is already in use.\r\n"
+ L"Error code: Wsl/Service/RegisterDistro/ERROR_FILE_EXISTS\r\n");
+ }
+
//
// Create and import a new distro that where /bin/sh is an absolute symlink.
//
@@ -5361,7 +5392,7 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND\r\n",
VERIFY_ARE_EQUAL(
out,
- L"A distribution with the supplied name already exists. Use --name to chose a different name.\r\n"
+ L"Cannot create a file when that file already exists. \r\n"
L"Error code: Wsl/InstallDistro/ERROR_ALREADY_EXISTS\r\n");
VERIFY_ARE_EQUAL(err, L"");
@@ -5372,7 +5403,7 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND\r\n",
VERIFY_ARE_EQUAL(
out,
- L"A distribution with the supplied name already exists. Use --name to chose a different name.\r\n"
+ L"Cannot create a file when that file already exists. \r\n"
L"Error code: Wsl/InstallDistro/ERROR_ALREADY_EXISTS\r\n");
VERIFY_ARE_EQUAL(err, L"");