From df8987216d2c3f0a30fc144c1634b7346ff2563b Mon Sep 17 00:00:00 2001 From: Blue Date: Tue, 13 Oct 2026 12:19:04 -0700 Subject: [PATCH 1/2] Add missing synchronization around load WinHttp proxy methods --- src/windows/service/exe/LxssHttpProxy.cpp | 67 ++++++++++++++--------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/src/windows/service/exe/LxssHttpProxy.cpp b/src/windows/service/exe/LxssHttpProxy.cpp index d1f4a2d8ca..0620921b34 100644 --- a/src/windows/service/exe/LxssHttpProxy.cpp +++ b/src/windows/service/exe/LxssHttpProxy.cpp @@ -34,37 +34,50 @@ try { static wil::shared_hmodule winHttpModule; static std::once_flag winHttpLoadFlag; + static HRESULT loadResult = E_UNEXPECTED; - // Load Winhttp dll only once std::call_once(winHttpLoadFlag, [&]() { - winHttpModule.reset(LoadLibraryEx(c_winhttpModuleName, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32)); - THROW_LAST_ERROR_IF(!winHttpModule); + loadResult = wil::ResultFromException([&]() { + winHttpModule.reset(LoadLibraryEx(c_winhttpModuleName, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32)); + THROW_LAST_ERROR_IF(!winHttpModule); + + // Initialize dynamic functions for the WinHttp Proxy OS APIs + // Not using the throwing constructor + // as failures should not show up in the Error logs as they can falsely flag failure to start the container + LxssDynamicFunction local_WinHttpRegisterProxyChangeNotification{ + DynamicFunctionErrorLogs::None}; + + LxssDynamicFunction local_WinHttpUnregisterProxyChangeNotification{ + DynamicFunctionErrorLogs::None}; + + LxssDynamicFunction local_WinHttpGetProxySettingsEx{DynamicFunctionErrorLogs::None}; + LxssDynamicFunction local_WinHttpGetProxySettingsResultEx{DynamicFunctionErrorLogs::None}; + LxssDynamicFunction local_WinHttpFreeProxySettingsEx{DynamicFunctionErrorLogs::None}; + + // try to load each function - only save if all succeed + RETURN_IF_FAILED_EXPECTED( + local_WinHttpRegisterProxyChangeNotification.load(winHttpModule, "WinHttpRegisterProxyChangeNotification")); + + RETURN_IF_FAILED_EXPECTED( + local_WinHttpUnregisterProxyChangeNotification.load(winHttpModule, "WinHttpUnregisterProxyChangeNotification")); + + RETURN_IF_FAILED_EXPECTED(local_WinHttpGetProxySettingsEx.load(winHttpModule, "WinHttpGetProxySettingsEx")); + + RETURN_IF_FAILED_EXPECTED( + local_WinHttpGetProxySettingsResultEx.load(winHttpModule, "WinHttpGetProxySettingsResultEx")); + + RETURN_IF_FAILED_EXPECTED(local_WinHttpFreeProxySettingsEx.load(winHttpModule, "WinHttpFreeProxySettingsEx")); + + s_WinHttpRegisterProxyChangeNotification.emplace(std::move(local_WinHttpRegisterProxyChangeNotification)); + s_WinHttpUnregisterProxyChangeNotification.emplace(std::move(local_WinHttpUnregisterProxyChangeNotification)); + s_WinHttpGetProxySettingsEx.emplace(std::move(local_WinHttpGetProxySettingsEx)); + s_WinHttpGetProxySettingsResultEx.emplace(std::move(local_WinHttpGetProxySettingsResultEx)); + s_WinHttpFreeProxySettingsEx.emplace(std::move(local_WinHttpFreeProxySettingsEx)); + return S_OK; + }); }); - // Initialize dynamic functions for the WinHttp Proxy OS APIs - // Not using the throwing constructor - // as failures should not show up in the Error logs as they can falsely flag failure to start the container - LxssDynamicFunction local_WinHttpRegisterProxyChangeNotification{DynamicFunctionErrorLogs::None}; - LxssDynamicFunction local_WinHttpUnregisterProxyChangeNotification{DynamicFunctionErrorLogs::None}; - LxssDynamicFunction local_WinHttpGetProxySettingsEx{DynamicFunctionErrorLogs::None}; - LxssDynamicFunction local_WinHttpGetProxySettingsResultEx{DynamicFunctionErrorLogs::None}; - LxssDynamicFunction local_WinHttpFreeProxySettingsEx{DynamicFunctionErrorLogs::None}; - - // try to load each function - only save if all succeed - RETURN_IF_FAILED_EXPECTED( - local_WinHttpRegisterProxyChangeNotification.load(winHttpModule, "WinHttpRegisterProxyChangeNotification")); - RETURN_IF_FAILED_EXPECTED( - local_WinHttpUnregisterProxyChangeNotification.load(winHttpModule, "WinHttpUnregisterProxyChangeNotification")); - RETURN_IF_FAILED_EXPECTED(local_WinHttpGetProxySettingsEx.load(winHttpModule, "WinHttpGetProxySettingsEx")); - RETURN_IF_FAILED_EXPECTED(local_WinHttpGetProxySettingsResultEx.load(winHttpModule, "WinHttpGetProxySettingsResultEx")); - RETURN_IF_FAILED_EXPECTED(local_WinHttpFreeProxySettingsEx.load(winHttpModule, "WinHttpFreeProxySettingsEx")); - - s_WinHttpRegisterProxyChangeNotification.emplace(std::move(local_WinHttpRegisterProxyChangeNotification)); - s_WinHttpUnregisterProxyChangeNotification.emplace(std::move(local_WinHttpUnregisterProxyChangeNotification)); - s_WinHttpGetProxySettingsEx.emplace(std::move(local_WinHttpGetProxySettingsEx)); - s_WinHttpGetProxySettingsResultEx.emplace(std::move(local_WinHttpGetProxySettingsResultEx)); - s_WinHttpFreeProxySettingsEx.emplace(std::move(local_WinHttpFreeProxySettingsEx)); - return S_OK; + return loadResult; } CATCH_RETURN() From 1cb801eb3df60db04ead12e282cf5265b0490d7e Mon Sep 17 00:00:00 2001 From: Blue Date: Tue, 13 Oct 2026 14:04:48 -0700 Subject: [PATCH 2/2] Fix loading logic --- src/windows/service/exe/LxssHttpProxy.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/windows/service/exe/LxssHttpProxy.cpp b/src/windows/service/exe/LxssHttpProxy.cpp index 0620921b34..f8f9525aea 100644 --- a/src/windows/service/exe/LxssHttpProxy.cpp +++ b/src/windows/service/exe/LxssHttpProxy.cpp @@ -37,9 +37,9 @@ try static HRESULT loadResult = E_UNEXPECTED; std::call_once(winHttpLoadFlag, [&]() { - loadResult = wil::ResultFromException([&]() { + loadResult = [&]() { winHttpModule.reset(LoadLibraryEx(c_winhttpModuleName, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32)); - THROW_LAST_ERROR_IF(!winHttpModule); + RETURN_LAST_ERROR_IF(!winHttpModule); // Initialize dynamic functions for the WinHttp Proxy OS APIs // Not using the throwing constructor @@ -74,7 +74,7 @@ try s_WinHttpGetProxySettingsResultEx.emplace(std::move(local_WinHttpGetProxySettingsResultEx)); s_WinHttpFreeProxySettingsEx.emplace(std::move(local_WinHttpFreeProxySettingsEx)); return S_OK; - }); + }(); }); return loadResult;