From 9c5b4a5e4add852cc384f38efdc429283842ce03 Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Thu, 4 Jun 2026 15:12:03 +0800 Subject: [PATCH 1/5] download to a sub folder under temp to avoid winrt quirk --- src/windows/common/wslutil.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/windows/common/wslutil.cpp b/src/windows/common/wslutil.cpp index 03decb3e1..562e3ed45 100644 --- a/src/windows/common/wslutil.cpp +++ b/src/windows/common/wslutil.cpp @@ -368,8 +368,17 @@ std::wstring wsl::windows::common::wslutil::DownloadFileImpl( Filename = Url.substr(lastSlash + 1); } - const auto downloadFolder = - winrt::Windows::Storage::StorageFolder::GetFolderFromPathAsync(std::filesystem::temp_directory_path().wstring()).get(); + // GetFolderFromPathAsync does not accept hidden or system path. + // To avoid the temp path having those attributes (mainly hidden), + // we need to create a subfolder without those attributes. + auto downloadFolderPath = std::filesystem::temp_directory_path() / L"wsl-downloads"; + std::filesystem::create_directories(downloadFolderPath); + + const auto attributes = GetFileAttributesW(downloadFolderPath.c_str()); + THROW_LAST_ERROR_IF(attributes == INVALID_FILE_ATTRIBUTES); + THROW_IF_WIN32_BOOL_FALSE(SetFileAttributesW(downloadFolderPath.c_str(), attributes & ~(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM))); + + const auto downloadFolder = winrt::Windows::Storage::StorageFolder::GetFolderFromPathAsync(downloadFolderPath.wstring()).get(); const auto file = downloadFolder.CreateFileAsync(Filename, winrt::Windows::Storage::CreationCollisionOption::GenerateUniqueName).get(); From 45e2df722f7306d5751e35b62d3cd305efb288d9 Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Thu, 4 Jun 2026 15:39:06 +0800 Subject: [PATCH 2/5] add unit test --- test/windows/UnitTests.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/test/windows/UnitTests.cpp b/test/windows/UnitTests.cpp index b9d54b369..d681ac9e0 100644 --- a/test/windows/UnitTests.cpp +++ b/test/windows/UnitTests.cpp @@ -5143,7 +5143,7 @@ Error code: Wsl/Service/RegisterDistro/E_INVALIDARG\r\n"; wsl::shared::string::MultiByteToWide("01:23:45:67:89:AB")); } - TEST_METHOD(ModernDistroInstall) + static void ModernDistroInstallImpl() { auto tarPath = "file://" + wsl::shared::string::WideToMultiByte(EscapePath(g_testDistroPath)); @@ -5779,6 +5779,24 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n", } } + TEST_METHOD(ModernDistroInstall) + { + ModernDistroInstallImpl(); + } + + TEST_METHOD(ModernDistroInstallWithHiddenTempFolder) + { + const auto tempFolder = std::filesystem::temp_directory_path(); + const auto originalAttributes = GetFileAttributesW(tempFolder.c_str()); + VERIFY_IS_TRUE(originalAttributes != INVALID_FILE_ATTRIBUTES); + VERIFY_IS_TRUE(SetFileAttributesW(tempFolder.c_str(), originalAttributes | FILE_ATTRIBUTE_HIDDEN)); + + auto restoreAttributes = wil::scope_exit_log( + WI_DIAGNOSTICS_INFO, [&] { SetFileAttributesW(tempFolder.c_str(), originalAttributes); }); + + ModernDistroInstallImpl(); + } + TEST_METHOD(ModernInstallEndToEnd) { constexpr auto tarName = L"end2end.tar"; From d63c68c71fce2830d69de2fefc01478a7967ec0c Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Thu, 4 Jun 2026 16:18:03 +0800 Subject: [PATCH 3/5] avoid modifying the real temp folder for testing --- test/windows/Common.cpp | 23 +++++++++++++++++++++-- test/windows/Common.h | 10 +++++----- test/windows/UnitTests.cpp | 17 ++++++++++++----- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/test/windows/Common.cpp b/test/windows/Common.cpp index f5aa3b1a0..07c45892e 100644 --- a/test/windows/Common.cpp +++ b/test/windows/Common.cpp @@ -2474,14 +2474,33 @@ void Trim(std::wstring& string) std::erase_if(string, [](auto c) { return !isalnum(c); }); } -ScopedEnvVariable::ScopedEnvVariable(const std::wstring& Name, const std::wstring& Value) : m_name(Name) +ScopedEnvVariable::ScopedEnvVariable(const std::wstring& Name, const std::wstring& Value, bool restore) : + m_name(Name), m_restore(restore) { + if (m_restore) + { + std::wstring value; + const auto result = wil::GetEnvironmentVariableW(Name.c_str(), value); + if (result != HRESULT_FROM_WIN32(ERROR_ENVVAR_NOT_FOUND)) + { + VERIFY_SUCCEEDED(result); + m_originalValue = std::move(value); + } + } + VERIFY_IS_TRUE(SetEnvironmentVariable(Name.c_str(), Value.c_str())); } ScopedEnvVariable::~ScopedEnvVariable() { - VERIFY_IS_TRUE(SetEnvironmentVariable(m_name.c_str(), nullptr)); + if (m_restore && m_originalValue.has_value()) + { + VERIFY_IS_TRUE(SetEnvironmentVariable(m_name.c_str(), m_originalValue->c_str())); + } + else + { + VERIFY_IS_TRUE(SetEnvironmentVariable(m_name.c_str(), nullptr)); + } } UniqueWebServer::UniqueWebServer(LPCWSTR Endpoint, LPCWSTR Content) diff --git a/test/windows/Common.h b/test/windows/Common.h index ad2706ebf..2b84910cf 100644 --- a/test/windows/Common.h +++ b/test/windows/Common.h @@ -309,16 +309,16 @@ class RegistryKeyChange class ScopedEnvVariable { public: - ScopedEnvVariable(const std::wstring& Name, const std::wstring& Value); + ScopedEnvVariable(const std::wstring& Name, const std::wstring& Value, bool restore = false); ~ScopedEnvVariable(); - ScopedEnvVariable(const WslConfigChange&) = delete; - ScopedEnvVariable(WslConfigChange&&) = delete; - const ScopedEnvVariable& operator=(ScopedEnvVariable&&) = delete; - const ScopedEnvVariable& operator=(ScopedEnvVariable&) = delete; + NON_COPYABLE(ScopedEnvVariable); + NON_MOVABLE(ScopedEnvVariable); private: std::wstring m_name; + bool m_restore; + std::optional m_originalValue{std::nullopt}; }; class UniqueWebServer diff --git a/test/windows/UnitTests.cpp b/test/windows/UnitTests.cpp index d681ac9e0..a0c46530f 100644 --- a/test/windows/UnitTests.cpp +++ b/test/windows/UnitTests.cpp @@ -5786,13 +5786,20 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n", TEST_METHOD(ModernDistroInstallWithHiddenTempFolder) { - const auto tempFolder = std::filesystem::temp_directory_path(); - const auto originalAttributes = GetFileAttributesW(tempFolder.c_str()); + // Avoid contaminating the real temp folder. + const auto testTempFolder = std::filesystem::temp_directory_path() / L"wsl-install-test"; + std::filesystem::create_directories(testTempFolder); + auto cleanupTempFolder = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&] { + std::error_code error; + std::filesystem::remove_all(testTempFolder, error); + }); + + const auto originalAttributes = GetFileAttributesW(testTempFolder.c_str()); VERIFY_IS_TRUE(originalAttributes != INVALID_FILE_ATTRIBUTES); - VERIFY_IS_TRUE(SetFileAttributesW(tempFolder.c_str(), originalAttributes | FILE_ATTRIBUTE_HIDDEN)); + VERIFY_IS_TRUE(SetFileAttributesW(testTempFolder.c_str(), originalAttributes | FILE_ATTRIBUTE_HIDDEN)); - auto restoreAttributes = wil::scope_exit_log( - WI_DIAGNOSTICS_INFO, [&] { SetFileAttributesW(tempFolder.c_str(), originalAttributes); }); + ScopedEnvVariable temp(L"TEMP", testTempFolder.wstring(), true); + ScopedEnvVariable tmp(L"TMP", testTempFolder.wstring(), true); ModernDistroInstallImpl(); } From 68625107d3842446c9f2184ec2e3f02add12624b Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Thu, 4 Jun 2026 16:22:52 +0800 Subject: [PATCH 4/5] simplify logic --- test/windows/Common.cpp | 7 +++---- test/windows/Common.h | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/test/windows/Common.cpp b/test/windows/Common.cpp index 07c45892e..fedb76f93 100644 --- a/test/windows/Common.cpp +++ b/test/windows/Common.cpp @@ -2474,10 +2474,9 @@ void Trim(std::wstring& string) std::erase_if(string, [](auto c) { return !isalnum(c); }); } -ScopedEnvVariable::ScopedEnvVariable(const std::wstring& Name, const std::wstring& Value, bool restore) : - m_name(Name), m_restore(restore) +ScopedEnvVariable::ScopedEnvVariable(const std::wstring& Name, const std::wstring& Value, bool restore) : m_name(Name) { - if (m_restore) + if (restore) { std::wstring value; const auto result = wil::GetEnvironmentVariableW(Name.c_str(), value); @@ -2493,7 +2492,7 @@ ScopedEnvVariable::ScopedEnvVariable(const std::wstring& Name, const std::wstrin ScopedEnvVariable::~ScopedEnvVariable() { - if (m_restore && m_originalValue.has_value()) + if (m_originalValue.has_value()) { VERIFY_IS_TRUE(SetEnvironmentVariable(m_name.c_str(), m_originalValue->c_str())); } diff --git a/test/windows/Common.h b/test/windows/Common.h index 2b84910cf..074699166 100644 --- a/test/windows/Common.h +++ b/test/windows/Common.h @@ -317,7 +317,6 @@ class ScopedEnvVariable private: std::wstring m_name; - bool m_restore; std::optional m_originalValue{std::nullopt}; }; From 7242bb5045a60b917070d8972165d06dbc268a1f Mon Sep 17 00:00:00 2001 From: Feng Wang Date: Fri, 5 Jun 2026 10:25:34 +0800 Subject: [PATCH 5/5] avoid redundant operation --- src/windows/common/wslutil.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/windows/common/wslutil.cpp b/src/windows/common/wslutil.cpp index 562e3ed45..f43f7450e 100644 --- a/src/windows/common/wslutil.cpp +++ b/src/windows/common/wslutil.cpp @@ -376,7 +376,10 @@ std::wstring wsl::windows::common::wslutil::DownloadFileImpl( const auto attributes = GetFileAttributesW(downloadFolderPath.c_str()); THROW_LAST_ERROR_IF(attributes == INVALID_FILE_ATTRIBUTES); - THROW_IF_WIN32_BOOL_FALSE(SetFileAttributesW(downloadFolderPath.c_str(), attributes & ~(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM))); + if (attributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) + { + THROW_IF_WIN32_BOOL_FALSE(SetFileAttributesW(downloadFolderPath.c_str(), attributes & ~(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM))); + } const auto downloadFolder = winrt::Windows::Storage::StorageFolder::GetFolderFromPathAsync(downloadFolderPath.wstring()).get();