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"");