From 7273a418dc1797f0dff66f42ed845e4961a4c5a5 Mon Sep 17 00:00:00 2001 From: Beena Chauhan Date: Fri, 14 Nov 2025 12:07:55 -0800 Subject: [PATCH 01/12] WSLA: Add initial wsladiag tool with basic --list support and placeholder ListSessions implementation --- CMakeLists.txt | 1 + src/windows/wsladiag/CMakeLists.txt | 7 +++ src/windows/wsladiag/main.cpp | 44 +++++++++++++++++++ .../wslaservice/exe/WSLAUserSession.cpp | 12 ++++- 4 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/windows/wsladiag/CMakeLists.txt create mode 100644 src/windows/wsladiag/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e66a48936..84a0ec2bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -425,6 +425,7 @@ add_subdirectory(src/windows/wslhost) add_subdirectory(src/windows/wslrelay) add_subdirectory(src/windows/wslinstall) add_subdirectory(src/windows/wslaclient) +add_subdirectory(src/windows/wsladiag) if (WSL_BUILD_WSL_SETTINGS) add_subdirectory(src/windows/libwsl) diff --git a/src/windows/wsladiag/CMakeLists.txt b/src/windows/wsladiag/CMakeLists.txt new file mode 100644 index 000000000..acee993df --- /dev/null +++ b/src/windows/wsladiag/CMakeLists.txt @@ -0,0 +1,7 @@ +set(SOURCES main.cpp) + + add_executable(wsladiag ${SOURCES}) + + target_link_libraries(wsladiag ${COMMON_LINK_LIBRARIES} common) + + target_precompile_headers(wsladiag REUSE_FROM common) set_target_properties(wsladiag PROPERTIES FOLDER windows) diff --git a/src/windows/wsladiag/main.cpp b/src/windows/wsladiag/main.cpp new file mode 100644 index 000000000..5109f8cf3 --- /dev/null +++ b/src/windows/wsladiag/main.cpp @@ -0,0 +1,44 @@ +#include +#include + +int wmain(int argc, wchar_t** argv) +{ + bool list = false; + bool help = false; + + // Simple argument parsing: look for --list or --help + for (int i = 1; i < argc; ++i) + { + if (wcscmp(argv[i], L"--list") == 0) + { + list = true; + } + else if (wcscmp(argv[i], L"--help") == 0 || wcscmp(argv[i], L"-h") == 0) + { + help = true; + } + } + + if (help) + { + std::wcout << L"wsladiag - WSLA diagnostics tool\n" + L"Usage:\n" + L" wsladiag --list List WSLA sessions\n" + L" wsladiag --help Show this help\n"; + return 0; + } + + if (list) + { + std::wcout << L"[wsladiag] --list: placeholder.\n" + L"Next step: call WSLA service ListSessions and display sessions.\n"; + return 0; + } + + // No args → show usage + std::wcout << L"wsladiag - WSLA diagnostics tool\n" + L"Usage:\n" + L" wsladiag --list List WSLA sessions\n" + L" wsladiag --help Show this help\n"; + return 0; +} diff --git a/src/windows/wslaservice/exe/WSLAUserSession.cpp b/src/windows/wslaservice/exe/WSLAUserSession.cpp index 63cf42c03..3476ff74a 100644 --- a/src/windows/wslaservice/exe/WSLAUserSession.cpp +++ b/src/windows/wslaservice/exe/WSLAUserSession.cpp @@ -116,8 +116,18 @@ CATCH_RETURN(); HRESULT wsl::windows::service::wsla::WSLAUserSession::ListSessions(WSLA_SESSION_INFORMATION** Sessions, ULONG* SessionsCount) { - return E_NOTIMPL; + if (!Sessions || !SessionsCount) + { + return E_INVALIDARG; + } + + // For now, return an empty list. We'll populate this from m_sessions later. + *Sessions = nullptr; + *SessionsCount = 0; + + return S_OK; } + HRESULT wsl::windows::service::wsla::WSLAUserSession::OpenSession(ULONG Id, IWSLASession** Session) { return E_NOTIMPL; From 71d3514b4804a274c1dc772e3904f5e260d5e440 Mon Sep 17 00:00:00 2001 From: Beena Chauhan Date: Fri, 14 Nov 2025 13:15:46 -0800 Subject: [PATCH 02/12] Fix CMakeLists.txt formatting issue for wsladiag --- src/windows/wsladiag/CMakeLists.txt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/windows/wsladiag/CMakeLists.txt b/src/windows/wsladiag/CMakeLists.txt index acee993df..8d48ac9fc 100644 --- a/src/windows/wsladiag/CMakeLists.txt +++ b/src/windows/wsladiag/CMakeLists.txt @@ -1,7 +1,14 @@ -set(SOURCES main.cpp) +set(SOURCES + main.cpp +) - add_executable(wsladiag ${SOURCES}) +add_executable(wsladiag ${SOURCES}) - target_link_libraries(wsladiag ${COMMON_LINK_LIBRARIES} common) +target_link_libraries(wsladiag + ${COMMON_LINK_LIBRARIES} + common +) - target_precompile_headers(wsladiag REUSE_FROM common) set_target_properties(wsladiag PROPERTIES FOLDER windows) +target_precompile_headers(wsladiag REUSE_FROM common) + +set_target_properties(wsladiag PROPERTIES FOLDER windows) \ No newline at end of file From 06fd79ba4b49433ef23a9f53f05a66faa9dd4450 Mon Sep 17 00:00:00 2001 From: Beena Chauhan Date: Mon, 17 Nov 2025 23:16:08 -0800 Subject: [PATCH 03/12] Add wsladiag + MSI entries --- msipackage/CMakeLists.txt | 4 +- msipackage/package.wix.in | 1 + src/windows/wsladiag/main.cpp | 111 +++++++++++++++++++++++++--------- 3 files changed, 87 insertions(+), 29 deletions(-) diff --git a/msipackage/CMakeLists.txt b/msipackage/CMakeLists.txt index 7f7bcb1ed..699638700 100644 --- a/msipackage/CMakeLists.txt +++ b/msipackage/CMakeLists.txt @@ -3,7 +3,7 @@ set(OUTPUT_PACKAGE ${BIN}/wsl.msi) set(PACKAGE_WIX_IN ${CMAKE_CURRENT_LIST_DIR}/package.wix.in) set(PACKAGE_WIX ${BIN}/package.wix) set(CAB_CACHE ${BIN}/cab) -set(BINARIES wsl.exe;wslg.exe;wslhost.exe;wslrelay.exe;wslservice.exe;wslserviceproxystub.dll;init;initrd.img;wslinstall.dll;wslaserviceproxystub.dll;wslaservice.exe) +set(BINARIES wsl.exe;wslg.exe;wslhost.exe;wslrelay.exe;wslservice.exe;wslserviceproxystub.dll;init;initrd.img;wslinstall.dll;wslaserviceproxystub.dll;wslaservice.exe;wsladiag.exe) if (WSL_BUILD_WSL_SETTINGS) list(APPEND BINARIES_DEPENDENCIES "wslsettings/wslsettings.dll;wslsettings/wslsettings.exe;libwsl.dll") @@ -39,7 +39,7 @@ add_custom_command( add_custom_target(msipackage DEPENDS ${OUTPUT_PACKAGE}) set_target_properties(msipackage PROPERTIES EXCLUDE_FROM_ALL FALSE SOURCES ${PACKAGE_WIX_IN}) -add_dependencies(msipackage wsl wslg wslservice wslhost wslrelay wslserviceproxystub init initramfs wslinstall msixgluepackage wslaservice wslaserviceproxystub) +add_dependencies(msipackage wsl wslg wslservice wslhost wslrelay wslserviceproxystub init initramfs wslinstall msixgluepackage wslaservice wslaserviceproxystub wsladiag) if (WSL_BUILD_WSL_SETTINGS) add_dependencies(msipackage wslsettings libwsl) diff --git a/msipackage/package.wix.in b/msipackage/package.wix.in index f51bc8f3a..4b4dc3e27 100644 --- a/msipackage/package.wix.in +++ b/msipackage/package.wix.in @@ -27,6 +27,7 @@ + diff --git a/src/windows/wsladiag/main.cpp b/src/windows/wsladiag/main.cpp index 5109f8cf3..b1ca20c29 100644 --- a/src/windows/wsladiag/main.cpp +++ b/src/windows/wsladiag/main.cpp @@ -1,44 +1,101 @@ -#include -#include +/*++ -int wmain(int argc, wchar_t** argv) +Copyright (c) Microsoft. All rights reserved. + +Module Name: + + main.cpp + +Abstract: + + Entry point for the wsladiag tool, performs WSL runtime initialization and parses --list/--help. + +--*/ + +#include "precomp.h" +#include "CommandLine.h" +#include "wslutil.h" + +using namespace wsl::shared; +namespace wslutil = wsl::windows::common::wslutil; + +int wsladiag_main(std::wstring_view commandLine) { - bool list = false; + // + // Standard process initialization (matches other WSL tools) + // + wslutil::ConfigureCrt(); + wslutil::InitializeWil(); + + WslTraceLoggingInitialize(LxssTelemetryProvider, !wsl::shared::OfficialBuild); + auto cleanupTelemetry = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() + { + WslTraceLoggingUninitialize(); + }); + + wslutil::SetCrtEncoding(_O_U8TEXT); + + auto coInit = wil::CoInitializeEx(COINIT_MULTITHREADED); + wslutil::CoInitializeSecurity(); + + WSADATA data{}; + THROW_IF_WIN32_ERROR(WSAStartup(MAKEWORD(2, 2), &data)); + auto wsaCleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() + { + WSACleanup(); + }); + + // + // Command-line parsing using ArgumentParser + // + ArgumentParser parser(std::wstring{commandLine}, L"wsladiag"); + bool help = false; + bool list = false; + + parser.AddArgument(list, L"--list"); + parser.AddArgument(help, L"--help", L'h'); // short option is a single wide char + parser.Parse(); - // Simple argument parsing: look for --list or --help - for (int i = 1; i < argc; ++i) + auto printUsage = []() { - if (wcscmp(argv[i], L"--list") == 0) - { - list = true; - } - else if (wcscmp(argv[i], L"--help") == 0 || wcscmp(argv[i], L"-h") == 0) - { - help = true; - } - } + wslutil::PrintMessage( + L"wsladiag - WSLA diagnostics tool\n" + L"Usage:\n" + L" wsladiag --list List WSLA sessions\n" + L" wsladiag --help Show this help", + stdout); + }; + // Slightly clearer help logic if (help) { - std::wcout << L"wsladiag - WSLA diagnostics tool\n" - L"Usage:\n" - L" wsladiag --list List WSLA sessions\n" - L" wsladiag --help Show this help\n"; + printUsage(); return 0; } - if (list) + if (!list) { - std::wcout << L"[wsladiag] --list: placeholder.\n" - L"Next step: call WSLA service ListSessions and display sessions.\n"; + // No recognized command → show usage + printUsage(); return 0; } - // No args → show usage - std::wcout << L"wsladiag - WSLA diagnostics tool\n" - L"Usage:\n" - L" wsladiag --list List WSLA sessions\n" - L" wsladiag --help Show this help\n"; + // --list + wslutil::PrintMessage( + L"[wsladiag] --list: placeholder.\n" + L"Next step: call WSLA service ListSessions and display sessions.", + stdout); + // TODO: call WSLA service COM interface to retrieve and display sessions. return 0; } + +int wmain(int /*argc*/, wchar_t** /*argv*/) +{ + try + { + // Use the full command line so ArgumentParser sees the raw string + return wsladiag_main(GetCommandLineW()); + } + CATCH_RETURN(); +} From de1522989a7fd7df7877867ca71f6a9ae0861f0b Mon Sep 17 00:00:00 2001 From: Beena Chauhan Date: Wed, 19 Nov 2025 10:19:42 -0800 Subject: [PATCH 04/12] Add initial implementation of --list command to wsladiag --- src/windows/wsladiag/main.cpp | 103 +++++++++++++++++++++++++--------- 1 file changed, 76 insertions(+), 27 deletions(-) diff --git a/src/windows/wsladiag/main.cpp b/src/windows/wsladiag/main.cpp index b1ca20c29..3ace0aeaa 100644 --- a/src/windows/wsladiag/main.cpp +++ b/src/windows/wsladiag/main.cpp @@ -15,23 +15,19 @@ Module Name: #include "precomp.h" #include "CommandLine.h" #include "wslutil.h" +#include "wslaservice.h" +#include "WslSecurity.h" using namespace wsl::shared; namespace wslutil = wsl::windows::common::wslutil; int wsladiag_main(std::wstring_view commandLine) { - // - // Standard process initialization (matches other WSL tools) - // wslutil::ConfigureCrt(); wslutil::InitializeWil(); WslTraceLoggingInitialize(LxssTelemetryProvider, !wsl::shared::OfficialBuild); - auto cleanupTelemetry = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() - { - WslTraceLoggingUninitialize(); - }); + auto cleanupTelemetry = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() { WslTraceLoggingUninitialize(); }); wslutil::SetCrtEncoding(_O_U8TEXT); @@ -40,34 +36,28 @@ int wsladiag_main(std::wstring_view commandLine) WSADATA data{}; THROW_IF_WIN32_ERROR(WSAStartup(MAKEWORD(2, 2), &data)); - auto wsaCleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() - { - WSACleanup(); - }); + auto wsaCleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() { WSACleanup(); }); - // - // Command-line parsing using ArgumentParser - // + // Command-line parsing using ArgumentParser. ArgumentParser parser(std::wstring{commandLine}, L"wsladiag"); bool help = false; bool list = false; parser.AddArgument(list, L"--list"); - parser.AddArgument(help, L"--help", L'h'); // short option is a single wide char + parser.AddArgument(help, L"--help", L'h'); // short option is a single wide char parser.Parse(); - auto printUsage = []() - { + auto printUsage = []() { wslutil::PrintMessage( L"wsladiag - WSLA diagnostics tool\n" L"Usage:\n" L" wsladiag --list List WSLA sessions\n" L" wsladiag --help Show this help", - stdout); + stderr); }; - // Slightly clearer help logic + // If '--help' was requested, print usage and exit. if (help) { printUsage(); @@ -81,20 +71,79 @@ int wsladiag_main(std::wstring_view commandLine) return 0; } - // --list - wslutil::PrintMessage( - L"[wsladiag] --list: placeholder.\n" - L"Next step: call WSLA service ListSessions and display sessions.", - stdout); - // TODO: call WSLA service COM interface to retrieve and display sessions. - return 0; + // --list: Call WSLA service COM interface to retrieve and display sessions. + try + { + wil::com_ptr userSession; + THROW_IF_FAILED(CoCreateInstance(__uuidof(WSLAUserSession), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&userSession))); + + wsl::windows::common::security::ConfigureForCOMImpersonation(userSession.get()); + + WSLA_SESSION_INFORMATION* sessions = nullptr; + ULONG sessionCount = 0; + + THROW_IF_FAILED(userSession->ListSessions(&sessions, &sessionCount)); + + auto cleanupSessions = wil::scope_exit([&]() { + if (sessions != nullptr) + { + // Free the CoTaskMem-allocated memory + for (ULONG i = 0; i < sessionCount; i++) + { + if (sessions[i].DisplayName != nullptr) + { + CoTaskMemFree(sessions[i].DisplayName); + } + } + CoTaskMemFree(sessions); + } + }); + + if (sessionCount == 0) + { + wslutil::PrintMessage(L"No WSLA sessions found.\n", stdout); + } + else + { + wslutil::PrintMessage(std::format(L"Found {} WSLA session{}:\n", sessionCount, sessionCount > 1 ? L"s" : L""), stdout); + + wslutil::PrintMessage(L"ID\tCreator PID\tDisplay Name\n", stdout); + wslutil::PrintMessage(L"--\t-----------\t------------\n", stdout); + + for (ULONG i = 0; i < sessionCount; i++) + { + const auto& session = sessions[i]; + + std::wstring displayName = L""; + if (session.DisplayName != nullptr) + { + const int length = MultiByteToWideChar(CP_UTF8, 0, session.DisplayName, -1, nullptr, 0); + if (length > 0) + { + displayName.resize(length - 1); + MultiByteToWideChar(CP_UTF8, 0, session.DisplayName, -1, displayName.data(), length); + } + } + + wslutil::PrintMessage(std::format(L"{}\t{}\t\t{}\n", session.Id, session.CreatorPid, displayName), stdout); + } + } + + return 0; + } + catch (...) + { + const auto hr = wil::ResultFromCaughtException(); + wslutil::PrintMessage(std::format(L"Error listing WSLA sessions: 0x{:08x}\n", static_cast(hr)), stderr); + return 1; + } } int wmain(int /*argc*/, wchar_t** /*argv*/) { try { - // Use the full command line so ArgumentParser sees the raw string + // Use raw Unicode command line so ArgumentParser gets original input. return wsladiag_main(GetCommandLineW()); } CATCH_RETURN(); From 7ec00b4f3927e303e399c28d2fc142c6a2bd596b Mon Sep 17 00:00:00 2001 From: Beena Chauhan Date: Thu, 20 Nov 2025 10:33:22 -0800 Subject: [PATCH 05/12] Update WSLA telemetry provider and improve session enumeration --- src/windows/common/WslTelemetry.cpp | 2 +- src/windows/common/WslTelemetry.h | 2 +- src/windows/wsladiag/main.cpp | 84 ++++++++++++++------- src/windows/wslaservice/exe/ServiceMain.cpp | 2 +- 4 files changed, 60 insertions(+), 30 deletions(-) diff --git a/src/windows/common/WslTelemetry.cpp b/src/windows/common/WslTelemetry.cpp index 766513d2c..cac31bb69 100644 --- a/src/windows/common/WslTelemetry.cpp +++ b/src/windows/common/WslTelemetry.cpp @@ -33,7 +33,7 @@ TRACELOGGING_DEFINE_PROVIDER( TraceLoggingOptionMicrosoftTelemetry()); TRACELOGGING_DEFINE_PROVIDER( - WslaServiceTelemetryProvider, + WslaTelemetryProvider, "Microsoft.Windows.Wsla", // {0383CE62-8F86-4766-AFB2-9D66A7FB1E90} (0x383ce62, 0x8f86, 0x4766, 0xaf, 0xb2, 0x9d, 0x66, 0xa7, 0xfb, 0x1e, 0x90), diff --git a/src/windows/common/WslTelemetry.h b/src/windows/common/WslTelemetry.h index 209dfd6ff..96ee3dead 100644 --- a/src/windows/common/WslTelemetry.h +++ b/src/windows/common/WslTelemetry.h @@ -28,7 +28,7 @@ extern "C" { #endif TRACELOGGING_DECLARE_PROVIDER(LxssTelemetryProvider); TRACELOGGING_DECLARE_PROVIDER(WslServiceTelemetryProvider); -TRACELOGGING_DECLARE_PROVIDER(WslaServiceTelemetryProvider); +TRACELOGGING_DECLARE_PROVIDER(WslaTelemetryProvider); #ifdef __cplusplus } #endif diff --git a/src/windows/wsladiag/main.cpp b/src/windows/wsladiag/main.cpp index 3ace0aeaa..97140cf53 100644 --- a/src/windows/wsladiag/main.cpp +++ b/src/windows/wsladiag/main.cpp @@ -26,7 +26,7 @@ int wsladiag_main(std::wstring_view commandLine) wslutil::ConfigureCrt(); wslutil::InitializeWil(); - WslTraceLoggingInitialize(LxssTelemetryProvider, !wsl::shared::OfficialBuild); + WslTraceLoggingInitialize(WslaTelemetryProvider, !wsl::shared::OfficialBuild); auto cleanupTelemetry = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() { WslTraceLoggingUninitialize(); }); wslutil::SetCrtEncoding(_O_U8TEXT); @@ -79,51 +79,71 @@ int wsladiag_main(std::wstring_view commandLine) wsl::windows::common::security::ConfigureForCOMImpersonation(userSession.get()); - WSLA_SESSION_INFORMATION* sessions = nullptr; - ULONG sessionCount = 0; + wil::unique_cotaskmem_array_ptr sessions; - THROW_IF_FAILED(userSession->ListSessions(&sessions, &sessionCount)); + THROW_IF_FAILED(userSession->ListSessions(&sessions, sessions.size_address())); - auto cleanupSessions = wil::scope_exit([&]() { - if (sessions != nullptr) + // Free inner CoTaskMem-allocated strings before the array is freed. + auto cleanupInnerStrings = wil::scope_exit([&]() { + for (ULONG i = 0; i < sessions.size(); ++i) { - // Free the CoTaskMem-allocated memory - for (ULONG i = 0; i < sessionCount; i++) + if (sessions[i].DisplayName != nullptr) { - if (sessions[i].DisplayName != nullptr) - { - CoTaskMemFree(sessions[i].DisplayName); - } + CoTaskMemFree(sessions[i].DisplayName); + sessions[i].DisplayName = nullptr; } - CoTaskMemFree(sessions); } }); - if (sessionCount == 0) + auto Utf8ToDisplayName = [](const char* utf8) -> std::wstring { + if (!utf8) + { + return L""; + } + + const int length = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, nullptr, 0); + if (length <= 0) + { + return L""; + } + + // length includes the null terminator + std::wstring result(length, L'\0'); + + const int written = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, result.data(), length); + if (written <= 0) + { + return L""; + } + + // MultiByteToWideChar returns the number of wide chars written including the terminating NUL. + // Resize to drop the trailing NUL only when the result is sane; otherwise return the fallback. + if (written > 0 && written <= length) + { + WI_ASSERT(result[written - 1] == L'\0'); + result.resize(written - 1); // drop trailing NUL + return result; + } + + return L""; + }; + + if (sessions.size() == 0) { wslutil::PrintMessage(L"No WSLA sessions found.\n", stdout); } else { - wslutil::PrintMessage(std::format(L"Found {} WSLA session{}:\n", sessionCount, sessionCount > 1 ? L"s" : L""), stdout); + wslutil::PrintMessage(std::format(L"Found {} WSLA session{}:\n", sessions.size(), sessions.size() > 1 ? L"s" : L""), stdout); wslutil::PrintMessage(L"ID\tCreator PID\tDisplay Name\n", stdout); wslutil::PrintMessage(L"--\t-----------\t------------\n", stdout); - for (ULONG i = 0; i < sessionCount; i++) + for (ULONG i = 0; i < sessions.size(); ++i) { const auto& session = sessions[i]; - std::wstring displayName = L""; - if (session.DisplayName != nullptr) - { - const int length = MultiByteToWideChar(CP_UTF8, 0, session.DisplayName, -1, nullptr, 0); - if (length > 0) - { - displayName.resize(length - 1); - MultiByteToWideChar(CP_UTF8, 0, session.DisplayName, -1, displayName.data(), length); - } - } + const std::wstring displayName = Utf8ToDisplayName(session.DisplayName); wslutil::PrintMessage(std::format(L"{}\t{}\t\t{}\n", session.Id, session.CreatorPid, displayName), stdout); } @@ -134,7 +154,17 @@ int wsladiag_main(std::wstring_view commandLine) catch (...) { const auto hr = wil::ResultFromCaughtException(); - wslutil::PrintMessage(std::format(L"Error listing WSLA sessions: 0x{:08x}\n", static_cast(hr)), stderr); + const std::wstring hrMessage = wslutil::ErrorCodeToString(hr); + + if (!hrMessage.empty()) + { + wslutil::PrintMessage(std::format(L"Error listing WSLA sessions: 0x{:08x} - {}\n", static_cast(hr), hrMessage), stderr); + } + else + { + wslutil::PrintMessage(std::format(L"Error listing WSLA sessions: 0x{:08x}\n", static_cast(hr)), stderr); + } + return 1; } } diff --git a/src/windows/wslaservice/exe/ServiceMain.cpp b/src/windows/wslaservice/exe/ServiceMain.cpp index 66218a430..2c5136d9f 100644 --- a/src/windows/wslaservice/exe/ServiceMain.cpp +++ b/src/windows/wslaservice/exe/ServiceMain.cpp @@ -67,7 +67,7 @@ try // Initialize telemetry. // TODO-WSLA: Create a dedicated WSLA provider - WslTraceLoggingInitialize(WslaServiceTelemetryProvider, !wsl::shared::OfficialBuild); + WslTraceLoggingInitialize(WslaTelemetryProvider, !wsl::shared::OfficialBuild); WSL_LOG("Service starting", TraceLoggingLevel(WINEVENT_LEVEL_INFO)); From dc7781e7be63bc7d8c6c1a8da5ce862e1d6cd72f Mon Sep 17 00:00:00 2001 From: Beena Chauhan Date: Thu, 20 Nov 2025 16:13:25 -0800 Subject: [PATCH 06/12] Remove Utf8ToDisplayName and rely on std::formatter for conversion* --- src/windows/wsladiag/main.cpp | 47 +++++++++-------------------------- 1 file changed, 12 insertions(+), 35 deletions(-) diff --git a/src/windows/wsladiag/main.cpp b/src/windows/wsladiag/main.cpp index 97140cf53..d65756173 100644 --- a/src/windows/wsladiag/main.cpp +++ b/src/windows/wsladiag/main.cpp @@ -95,39 +95,6 @@ int wsladiag_main(std::wstring_view commandLine) } }); - auto Utf8ToDisplayName = [](const char* utf8) -> std::wstring { - if (!utf8) - { - return L""; - } - - const int length = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, nullptr, 0); - if (length <= 0) - { - return L""; - } - - // length includes the null terminator - std::wstring result(length, L'\0'); - - const int written = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, result.data(), length); - if (written <= 0) - { - return L""; - } - - // MultiByteToWideChar returns the number of wide chars written including the terminating NUL. - // Resize to drop the trailing NUL only when the result is sane; otherwise return the fallback. - if (written > 0 && written <= length) - { - WI_ASSERT(result[written - 1] == L'\0'); - result.resize(written - 1); // drop trailing NUL - return result; - } - - return L""; - }; - if (sessions.size() == 0) { wslutil::PrintMessage(L"No WSLA sessions found.\n", stdout); @@ -143,9 +110,19 @@ int wsladiag_main(std::wstring_view commandLine) { const auto& session = sessions[i]; - const std::wstring displayName = Utf8ToDisplayName(session.DisplayName); + const char* displayName = session.DisplayName; + if (displayName == nullptr) + { + displayName = ""; + } - wslutil::PrintMessage(std::format(L"{}\t{}\t\t{}\n", session.Id, session.CreatorPid, displayName), stdout); + wslutil::PrintMessage( + std::format( + L"{}\t{}\t\t{}\n", + session.Id, + session.CreatorPid, + displayName), // std::formatter does UTF-8 → wide + stdout); } } From e02bd5deea74afb0ca6a1a59197b4a64684babba Mon Sep 17 00:00:00 2001 From: Beena352 Date: Wed, 26 Nov 2025 12:50:02 -0800 Subject: [PATCH 07/12] WIP: before cherry-picking WSLA session fix --- msipackage/package.wix.in | 1 - src/windows/wsladiag/CMakeLists.txt | 9 +++++-- src/windows/wsladiag/main.cpp | 12 +++------ src/windows/wslaservice/exe/WSLASession.cpp | 5 +++- src/windows/wslaservice/exe/WSLASession.h | 8 +++++- .../wslaservice/exe/WSLAUserSession.cpp | 26 ++++++++++++++++--- src/windows/wslaservice/exe/WSLAUserSession.h | 4 +-- src/windows/wslaservice/inc/wslaservice.idl | 4 +-- 8 files changed, 48 insertions(+), 21 deletions(-) diff --git a/msipackage/package.wix.in b/msipackage/package.wix.in index 4b4dc3e27..ea3a47f9f 100644 --- a/msipackage/package.wix.in +++ b/msipackage/package.wix.in @@ -379,7 +379,6 @@ - diff --git a/src/windows/wsladiag/CMakeLists.txt b/src/windows/wsladiag/CMakeLists.txt index 8d48ac9fc..5bee2bda7 100644 --- a/src/windows/wsladiag/CMakeLists.txt +++ b/src/windows/wsladiag/CMakeLists.txt @@ -1,3 +1,5 @@ +cmake_minimum_required(VERSION 3.20) # add this at the very top + set(SOURCES main.cpp ) @@ -9,6 +11,9 @@ target_link_libraries(wsladiag common ) -target_precompile_headers(wsladiag REUSE_FROM common) +# Only try to reuse precompiled headers if 'common' exists +if (TARGET common) + target_precompile_headers(wsladiag REUSE_FROM common) +endif() -set_target_properties(wsladiag PROPERTIES FOLDER windows) \ No newline at end of file +set_target_properties(wsladiag PROPERTIES FOLDER windows) diff --git a/src/windows/wsladiag/main.cpp b/src/windows/wsladiag/main.cpp index d65756173..3be5b4553 100644 --- a/src/windows/wsladiag/main.cpp +++ b/src/windows/wsladiag/main.cpp @@ -72,6 +72,7 @@ int wsladiag_main(std::wstring_view commandLine) } // --list: Call WSLA service COM interface to retrieve and display sessions. + try { wil::com_ptr userSession; @@ -110,19 +111,14 @@ int wsladiag_main(std::wstring_view commandLine) { const auto& session = sessions[i]; - const char* displayName = session.DisplayName; + const auto * displayName = session.DisplayName; if (displayName == nullptr) { - displayName = ""; + displayName = L""; } wslutil::PrintMessage( - std::format( - L"{}\t{}\t\t{}\n", - session.Id, - session.CreatorPid, - displayName), // std::formatter does UTF-8 → wide - stdout); + std::format(L"{}\t{}\t\t{}\n", session.SessionId, session.CreatorPid, static_cast(displayName)), stdout); } } diff --git a/src/windows/wslaservice/exe/WSLASession.cpp b/src/windows/wslaservice/exe/WSLASession.cpp index 2d96805c6..0f4777462 100644 --- a/src/windows/wslaservice/exe/WSLASession.cpp +++ b/src/windows/wslaservice/exe/WSLASession.cpp @@ -19,7 +19,10 @@ Module Name: using wsl::windows::service::wsla::WSLASession; -WSLASession::WSLASession(const WSLA_SESSION_SETTINGS& Settings, WSLAUserSessionImpl& userSessionImpl, const VIRTUAL_MACHINE_SETTINGS& VmSettings) : +WSLASession::WSLASession(ULONG id, const WSLA_SESSION_SETTINGS& Settings, + WSLAUserSessionImpl& userSessionImpl, + const VIRTUAL_MACHINE_SETTINGS& VmSettings) : + m_id(id), m_sessionSettings(Settings), m_userSession(userSessionImpl), m_virtualMachine(std::make_optional(VmSettings, userSessionImpl.GetUserSid(), &userSessionImpl)), diff --git a/src/windows/wslaservice/exe/WSLASession.h b/src/windows/wslaservice/exe/WSLASession.h index a8b725690..666416925 100644 --- a/src/windows/wslaservice/exe/WSLASession.h +++ b/src/windows/wslaservice/exe/WSLASession.h @@ -23,7 +23,12 @@ class DECLSPEC_UUID("4877FEFC-4977-4929-A958-9F36AA1892A4") WSLASession : public Microsoft::WRL::RuntimeClass, IWSLASession, IFastRundown> { public: - WSLASession(const WSLA_SESSION_SETTINGS& Settings, WSLAUserSessionImpl& userSessionImpl, const VIRTUAL_MACHINE_SETTINGS& VmSettings); + WSLASession(ULONG id, const WSLA_SESSION_SETTINGS& Settings, WSLAUserSessionImpl& userSessionImpl, const VIRTUAL_MACHINE_SETTINGS& VmSettings); + + ULONG GetId() const noexcept + { + return m_id; + } IFACEMETHOD(GetDisplayName)(LPWSTR* DisplayName) override; @@ -48,6 +53,7 @@ class DECLSPEC_UUID("4877FEFC-4977-4929-A958-9F36AA1892A4") WSLASession IFACEMETHOD(Shutdown(_In_ ULONG)) override; private: + ULONG m_id = 0; WSLA_SESSION_SETTINGS m_sessionSettings; // TODO: Revisit to see if we should have session settings as a member or not WSLAUserSessionImpl& m_userSession; std::optional m_virtualMachine; diff --git a/src/windows/wslaservice/exe/WSLAUserSession.cpp b/src/windows/wslaservice/exe/WSLAUserSession.cpp index 3476ff74a..898a43cea 100644 --- a/src/windows/wslaservice/exe/WSLAUserSession.cpp +++ b/src/windows/wslaservice/exe/WSLAUserSession.cpp @@ -67,7 +67,9 @@ PSID WSLAUserSessionImpl::GetUserSid() const HRESULT wsl::windows::service::wsla::WSLAUserSessionImpl::CreateSession( const WSLA_SESSION_SETTINGS* Settings, const VIRTUAL_MACHINE_SETTINGS* VmSettings, IWSLASession** WslaSession) { - auto session = wil::MakeOrThrow(*Settings, *this, *VmSettings); + OutputDebugStringW(L"[WSLA] CreateSession called\n"); //temp + ULONG id = m_nextSessionId++; + auto session = wil::MakeOrThrow(id, *Settings, *this, *VmSettings); { std::lock_guard lock(m_wslaSessionsLock); @@ -79,6 +81,21 @@ HRESULT wsl::windows::service::wsla::WSLAUserSessionImpl::CreateSession( return S_OK; } +HRESULT wsl::windows::service::wsla::WSLAUserSessionImpl::ListSessions(_Out_ WSLA_SESSION_INFORMATION** Sessions, _Out_ ULONG* SessionsCount) +{ + OutputDebugStringW(L"[WSLA] ListSessions called\n"); // temp + auto output = wil::make_unique_cotaskmem(m_wslaSessions.size()); + std::lock_guard lock(m_wslaSessionsLock); + for (size_t i = 0; i < m_wslaSessions.size(); ++i) + { + output[i].SessionId = m_wslaSessions[i]->GetId(); + m_wslaSessions[i]->GetDisplayName(&output[i].DisplayName); + } + *Sessions = output.release(); + *SessionsCount = static_cast(m_wslaSessions.size()); + return S_OK; +} + wsl::windows::service::wsla::WSLAUserSession::WSLAUserSession(std::weak_ptr&& Session) : m_session(std::move(Session)) { @@ -115,6 +132,7 @@ try CATCH_RETURN(); HRESULT wsl::windows::service::wsla::WSLAUserSession::ListSessions(WSLA_SESSION_INFORMATION** Sessions, ULONG* SessionsCount) + { if (!Sessions || !SessionsCount) { @@ -122,10 +140,10 @@ HRESULT wsl::windows::service::wsla::WSLAUserSession::ListSessions(WSLA_SESSION_ } // For now, return an empty list. We'll populate this from m_sessions later. - *Sessions = nullptr; - *SessionsCount = 0; + auto session = m_session.lock(); + RETURN_HR_IF(RPC_E_DISCONNECTED, !session); - return S_OK; + return session->ListSessions(Sessions, SessionsCount); } HRESULT wsl::windows::service::wsla::WSLAUserSession::OpenSession(ULONG Id, IWSLASession** Session) diff --git a/src/windows/wslaservice/exe/WSLAUserSession.h b/src/windows/wslaservice/exe/WSLAUserSession.h index 22f610fff..dba9a1fa4 100644 --- a/src/windows/wslaservice/exe/WSLAUserSession.h +++ b/src/windows/wslaservice/exe/WSLAUserSession.h @@ -31,12 +31,12 @@ class WSLAUserSessionImpl HRESULT CreateVirtualMachine(const VIRTUAL_MACHINE_SETTINGS* Settings, IWSLAVirtualMachine** VirtualMachine); HRESULT CreateSession(const WSLA_SESSION_SETTINGS* Settings, const VIRTUAL_MACHINE_SETTINGS* VmSettings, IWSLASession** WslaSession); - + HRESULT ListSessions(_Out_ WSLA_SESSION_INFORMATION** Sessions, _Out_ ULONG* SessionsCount); void OnVmTerminated(WSLAVirtualMachine* machine); private: wil::unique_tokeninfo_ptr m_tokenInfo; - + ULONG m_nextSessionId = 1; std::recursive_mutex m_wslaSessionsLock; // TODO-WSLA: Consider using a weak_ptr to easily destroy when the last client reference is released. std::vector> m_wslaSessions; diff --git a/src/windows/wslaservice/inc/wslaservice.idl b/src/windows/wslaservice/inc/wslaservice.idl index a3745b2b2..843fe6cfe 100644 --- a/src/windows/wslaservice/inc/wslaservice.idl +++ b/src/windows/wslaservice/inc/wslaservice.idl @@ -261,9 +261,9 @@ interface IWSLASession : IUnknown struct WSLA_SESSION_INFORMATION { - ULONG Id; + ULONG SessionId; DWORD CreatorPid; - LPSTR DisplayName; + LPWSTR DisplayName; }; [ From 637a121b2b6cc2f9657e19ff345015bee51c2b89 Mon Sep 17 00:00:00 2001 From: Blue Date: Wed, 26 Nov 2025 12:35:14 -0800 Subject: [PATCH 08/12] wsla: Fix incorrect call to EqualSid causing WSLAUserSession to always be created --- src/windows/wslaservice/exe/WSLAUserSessionFactory.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/windows/wslaservice/exe/WSLAUserSessionFactory.cpp b/src/windows/wslaservice/exe/WSLAUserSessionFactory.cpp index e13effec7..0a28ede8e 100644 --- a/src/windows/wslaservice/exe/WSLAUserSessionFactory.cpp +++ b/src/windows/wslaservice/exe/WSLAUserSessionFactory.cpp @@ -50,11 +50,15 @@ HRESULT WSLAUserSessionFactory::CreateInstance(_In_ IUnknown* pUnkOuter, _In_ RE THROW_HR_IF(CO_E_SERVER_STOPPING, !g_sessions.has_value()); auto session = std::find_if(g_sessions->begin(), g_sessions->end(), [&tokenInfo](auto it) { - return EqualSid(it->GetUserSid(), &tokenInfo->User.Sid); + return EqualSid(it->GetUserSid(), tokenInfo->User.Sid); }); if (session == g_sessions->end()) { + wil::unique_hlocal_string sid; + THROW_IF_WIN32_BOOL_FALSE(ConvertSidToStringSid(tokenInfo->User.Sid, &sid)); + WSL_LOG("WSLAUserSession created", TraceLoggingValue(sid.get(), "sid")); + session = g_sessions->insert(g_sessions->end(), std::make_shared(userToken.get(), std::move(tokenInfo))); } From 494da272a70d2b53cf9f92b53c347715589f2fef Mon Sep 17 00:00:00 2001 From: Beena352 Date: Wed, 26 Nov 2025 14:49:04 -0800 Subject: [PATCH 09/12] WSLA: Implement ListSessions and correct CreateSession storage --- src/windows/wslaservice/exe/WSLAUserSession.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/windows/wslaservice/exe/WSLAUserSession.cpp b/src/windows/wslaservice/exe/WSLAUserSession.cpp index 898a43cea..65cab9e75 100644 --- a/src/windows/wslaservice/exe/WSLAUserSession.cpp +++ b/src/windows/wslaservice/exe/WSLAUserSession.cpp @@ -67,13 +67,12 @@ PSID WSLAUserSessionImpl::GetUserSid() const HRESULT wsl::windows::service::wsla::WSLAUserSessionImpl::CreateSession( const WSLA_SESSION_SETTINGS* Settings, const VIRTUAL_MACHINE_SETTINGS* VmSettings, IWSLASession** WslaSession) { - OutputDebugStringW(L"[WSLA] CreateSession called\n"); //temp ULONG id = m_nextSessionId++; auto session = wil::MakeOrThrow(id, *Settings, *this, *VmSettings); { std::lock_guard lock(m_wslaSessionsLock); - m_wslaSessions.emplace_back(session.Get()); + m_wslaSessions.emplace_back(session); } THROW_IF_FAILED(session.CopyTo(__uuidof(IWSLASession), (void**)WslaSession)); @@ -83,7 +82,6 @@ HRESULT wsl::windows::service::wsla::WSLAUserSessionImpl::CreateSession( HRESULT wsl::windows::service::wsla::WSLAUserSessionImpl::ListSessions(_Out_ WSLA_SESSION_INFORMATION** Sessions, _Out_ ULONG* SessionsCount) { - OutputDebugStringW(L"[WSLA] ListSessions called\n"); // temp auto output = wil::make_unique_cotaskmem(m_wslaSessions.size()); std::lock_guard lock(m_wslaSessionsLock); for (size_t i = 0; i < m_wslaSessions.size(); ++i) From b09a6668e7c3355725a292c41a467a934a68c627 Mon Sep 17 00:00:00 2001 From: Beena352 Date: Sat, 29 Nov 2025 19:26:54 -0800 Subject: [PATCH 10/12] Address PR feedback: atomic session ID, CATCH_LOG, fixed-size DisplayName, cleaned wsladiag output --- src/windows/wsladiag/CMakeLists.txt | 7 ++----- src/windows/wsladiag/main.cpp | 6 ++---- .../wslaservice/exe/WSLAUserSession.cpp | 19 ++++++++++++++++--- src/windows/wslaservice/exe/WSLAUserSession.h | 3 ++- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/windows/wsladiag/CMakeLists.txt b/src/windows/wsladiag/CMakeLists.txt index 5bee2bda7..041124538 100644 --- a/src/windows/wsladiag/CMakeLists.txt +++ b/src/windows/wsladiag/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.20) # add this at the very top + set(SOURCES main.cpp @@ -11,9 +11,6 @@ target_link_libraries(wsladiag common ) -# Only try to reuse precompiled headers if 'common' exists -if (TARGET common) - target_precompile_headers(wsladiag REUSE_FROM common) -endif() +target_precompile_headers(wsladiag REUSE_FROM common) set_target_properties(wsladiag PROPERTIES FOLDER windows) diff --git a/src/windows/wsladiag/main.cpp b/src/windows/wsladiag/main.cpp index 3be5b4553..abf14e207 100644 --- a/src/windows/wsladiag/main.cpp +++ b/src/windows/wsladiag/main.cpp @@ -107,12 +107,10 @@ int wsladiag_main(std::wstring_view commandLine) wslutil::PrintMessage(L"ID\tCreator PID\tDisplay Name\n", stdout); wslutil::PrintMessage(L"--\t-----------\t------------\n", stdout); - for (ULONG i = 0; i < sessions.size(); ++i) + for (const auto& session : sessions) { - const auto& session = sessions[i]; - const auto * displayName = session.DisplayName; - if (displayName == nullptr) + if (displayName[0] == L'\0') { displayName = L""; } diff --git a/src/windows/wslaservice/exe/WSLAUserSession.cpp b/src/windows/wslaservice/exe/WSLAUserSession.cpp index ff67a1775..45e947f4c 100644 --- a/src/windows/wslaservice/exe/WSLAUserSession.cpp +++ b/src/windows/wslaservice/exe/WSLAUserSession.cpp @@ -73,7 +73,20 @@ HRESULT wsl::windows::service::wsla::WSLAUserSessionImpl::ListSessions(_Out_ WSL for (size_t i = 0; i < m_wslaSessions.size(); ++i) { output[i].SessionId = m_wslaSessions[i]->GetId(); - m_wslaSessions[i]->GetDisplayName(&output[i].DisplayName); + output[i].CreatorPid = 0; // placeholder until we populate this later + PWSTR tempName = nullptr; + + RETURN_IF_FAILED(m_wslaSessions[i]->GetDisplayName(&tempName)); + if (tempName) + { + wcscpy_s(output[i].DisplayName, _countof(output[i].DisplayName), tempName); + CoTaskMemFree(tempName); + } + else + { + output[i].DisplayName[0] = L'\0'; + } + } *Sessions = output.release(); *SessionsCount = static_cast(m_wslaSessions.size()); @@ -106,19 +119,19 @@ try CATCH_RETURN(); HRESULT wsl::windows::service::wsla::WSLAUserSession::ListSessions(WSLA_SESSION_INFORMATION** Sessions, ULONG* SessionsCount) - +try { if (!Sessions || !SessionsCount) { return E_INVALIDARG; } - // For now, return an empty list. We'll populate this from m_sessions later. auto session = m_session.lock(); RETURN_HR_IF(RPC_E_DISCONNECTED, !session); return session->ListSessions(Sessions, SessionsCount); } +CATCH_LOG(); HRESULT wsl::windows::service::wsla::WSLAUserSession::OpenSession(ULONG Id, IWSLASession** Session) { diff --git a/src/windows/wslaservice/exe/WSLAUserSession.h b/src/windows/wslaservice/exe/WSLAUserSession.h index 633314d17..631bb4dd1 100644 --- a/src/windows/wslaservice/exe/WSLAUserSession.h +++ b/src/windows/wslaservice/exe/WSLAUserSession.h @@ -15,6 +15,7 @@ Module Name: #pragma once #include "WSLAVirtualMachine.h" #include "WSLASession.h" +#include namespace wsl::windows::service::wsla { @@ -36,7 +37,7 @@ class WSLAUserSessionImpl private: wil::unique_tokeninfo_ptr m_tokenInfo; - ULONG m_nextSessionId = 1; + std::atomic m_nextSessionId{1}; std::recursive_mutex m_wslaSessionsLock; std::recursive_mutex m_lock; From be46f232eef1fa9dca8d43908daa28a1e288c1e1 Mon Sep 17 00:00:00 2001 From: Beena352 Date: Sun, 30 Nov 2025 23:48:58 -0800 Subject: [PATCH 11/12] Address build issues and formatting corrections --- src/windows/wsladiag/main.cpp | 14 +------------- src/windows/wslaservice/exe/WSLAUserSession.cpp | 11 +++++++---- src/windows/wslaservice/exe/WSLAUserSession.h | 3 +++ src/windows/wslaservice/inc/wslaservice.idl | 2 +- 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/windows/wsladiag/main.cpp b/src/windows/wsladiag/main.cpp index abf14e207..a8e10fbb3 100644 --- a/src/windows/wsladiag/main.cpp +++ b/src/windows/wsladiag/main.cpp @@ -84,18 +84,6 @@ int wsladiag_main(std::wstring_view commandLine) THROW_IF_FAILED(userSession->ListSessions(&sessions, sessions.size_address())); - // Free inner CoTaskMem-allocated strings before the array is freed. - auto cleanupInnerStrings = wil::scope_exit([&]() { - for (ULONG i = 0; i < sessions.size(); ++i) - { - if (sessions[i].DisplayName != nullptr) - { - CoTaskMemFree(sessions[i].DisplayName); - sessions[i].DisplayName = nullptr; - } - } - }); - if (sessions.size() == 0) { wslutil::PrintMessage(L"No WSLA sessions found.\n", stdout); @@ -116,7 +104,7 @@ int wsladiag_main(std::wstring_view commandLine) } wslutil::PrintMessage( - std::format(L"{}\t{}\t\t{}\n", session.SessionId, session.CreatorPid, static_cast(displayName)), stdout); + std::format(L"{}\t{}\t\t{}\n", session.SessionId, session.CreatorPid, displayName), stdout); } } diff --git a/src/windows/wslaservice/exe/WSLAUserSession.cpp b/src/windows/wslaservice/exe/WSLAUserSession.cpp index 45e947f4c..9ebe2f0b7 100644 --- a/src/windows/wslaservice/exe/WSLAUserSession.cpp +++ b/src/windows/wslaservice/exe/WSLAUserSession.cpp @@ -68,6 +68,7 @@ HRESULT wsl::windows::service::wsla::WSLAUserSessionImpl::CreateSession( HRESULT wsl::windows::service::wsla::WSLAUserSessionImpl::ListSessions(_Out_ WSLA_SESSION_INFORMATION** Sessions, _Out_ ULONG* SessionsCount) { + const auto count = m_wslaSessions.size(); auto output = wil::make_unique_cotaskmem(m_wslaSessions.size()); std::lock_guard lock(m_wslaSessionsLock); for (size_t i = 0; i < m_wslaSessions.size(); ++i) @@ -77,9 +78,10 @@ HRESULT wsl::windows::service::wsla::WSLAUserSessionImpl::ListSessions(_Out_ WSL PWSTR tempName = nullptr; RETURN_IF_FAILED(m_wslaSessions[i]->GetDisplayName(&tempName)); + if (tempName) { - wcscpy_s(output[i].DisplayName, _countof(output[i].DisplayName), tempName); + wcscpy_s(output[i].DisplayName, tempName); CoTaskMemFree(tempName); } else @@ -89,7 +91,7 @@ HRESULT wsl::windows::service::wsla::WSLAUserSessionImpl::ListSessions(_Out_ WSL } *Sessions = output.release(); - *SessionsCount = static_cast(m_wslaSessions.size()); + *SessionsCount = static_cast(count); return S_OK; } @@ -129,9 +131,10 @@ try auto session = m_session.lock(); RETURN_HR_IF(RPC_E_DISCONNECTED, !session); - return session->ListSessions(Sessions, SessionsCount); + RETURN_IF_FAILED(session->ListSessions(Sessions, SessionsCount)); + return S_OK; } -CATCH_LOG(); +CATCH_RETURN(); HRESULT wsl::windows::service::wsla::WSLAUserSession::OpenSession(ULONG Id, IWSLASession** Session) { diff --git a/src/windows/wslaservice/exe/WSLAUserSession.h b/src/windows/wslaservice/exe/WSLAUserSession.h index 631bb4dd1..8657b77d4 100644 --- a/src/windows/wslaservice/exe/WSLAUserSession.h +++ b/src/windows/wslaservice/exe/WSLAUserSession.h @@ -16,6 +16,7 @@ Module Name: #include "WSLAVirtualMachine.h" #include "WSLASession.h" #include +#include namespace wsl::windows::service::wsla { @@ -40,6 +41,8 @@ class WSLAUserSessionImpl std::atomic m_nextSessionId{1}; std::recursive_mutex m_wslaSessionsLock; std::recursive_mutex m_lock; + // Track active sessions for diagnostics / ListSessions. + std::vector> m_wslaSessions; // TODO-WSLA: Consider using a weak_ptr to easily destroy when the last client reference is released. std::unordered_set m_sessions; diff --git a/src/windows/wslaservice/inc/wslaservice.idl b/src/windows/wslaservice/inc/wslaservice.idl index e8f9d98e7..a25317e93 100644 --- a/src/windows/wslaservice/inc/wslaservice.idl +++ b/src/windows/wslaservice/inc/wslaservice.idl @@ -298,7 +298,7 @@ struct WSLA_SESSION_INFORMATION { ULONG SessionId; DWORD CreatorPid; - LPWSTR DisplayName; + wchar_t DisplayName[256]; }; [ From f3b59039d58907e8a4f730198fbf1a561c02ff3f Mon Sep 17 00:00:00 2001 From: Beena352 Date: Mon, 1 Dec 2025 10:32:28 -0800 Subject: [PATCH 12/12] Sync WSLAVirtualMachine interface changes from upstream --- src/windows/wslaservice/exe/WSLAVirtualMachine.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/windows/wslaservice/exe/WSLAVirtualMachine.h b/src/windows/wslaservice/exe/WSLAVirtualMachine.h index a2ed05323..b0f01a957 100644 --- a/src/windows/wslaservice/exe/WSLAVirtualMachine.h +++ b/src/windows/wslaservice/exe/WSLAVirtualMachine.h @@ -48,29 +48,29 @@ class DECLSPEC_UUID("0CFC5DC1-B6A7-45FC-8034-3FA9ED73CE30") WSLAVirtualMachine ~WSLAVirtualMachine(); void Start(); - void OnSessionTerminated(); + void OnSessionTerminating(); IFACEMETHOD(CreateLinuxProcess(_In_ const WSLA_PROCESS_OPTIONS* Options, _Out_ IWSLAProcess** Process, _Out_ int* Errno)) override; IFACEMETHOD(WaitPid(_In_ LONG Pid, _In_ ULONGLONG TimeoutMs, _Out_ ULONG* State, _Out_ int* Code)) override; IFACEMETHOD(Signal(_In_ LONG Pid, _In_ int Signal)) override; IFACEMETHOD(Shutdown(ULONGLONG _In_ TimeoutMs)) override; + IFACEMETHOD(RegisterCallback(_In_ ITerminationCallback* callback)) override; IFACEMETHOD(GetDebugShellPipe(_Out_ LPWSTR* pipePath)) override; IFACEMETHOD(MapPort(_In_ int Family, _In_ short WindowsPort, _In_ short LinuxPort, _In_ BOOL Remove)) override; IFACEMETHOD(Unmount(_In_ const char* Path)) override; + IFACEMETHOD(DetachDisk(_In_ ULONG Lun)) override; IFACEMETHOD(MountWindowsFolder(_In_ LPCWSTR WindowsPath, _In_ LPCSTR LinuxPath, _In_ BOOL ReadOnly)) override; IFACEMETHOD(UnmountWindowsFolder(_In_ LPCSTR LinuxPath)) override; void MountGpuLibraries(_In_ LPCSTR LibrariesMountPoint, _In_ LPCSTR DriversMountpoint, _In_ DWORD Flags); void OnProcessReleased(int Pid); - void RegisterCallback(_In_ ITerminationCallback* callback); Microsoft::WRL::ComPtr CreateLinuxProcess( _In_ const WSLA_PROCESS_OPTIONS& Options, int* Errno = nullptr, const TPrepareCommandLine& PrepareCommandLine = [](const auto&) {}); +private: std::pair AttachDisk(_In_ PCWSTR Path, _In_ BOOL ReadOnly); - void DetachDisk(_In_ ULONG Lun); -private: static void Mount(wsl::shared::SocketChannel& Channel, LPCSTR Source, _In_ LPCSTR Target, _In_ LPCSTR Type, _In_ LPCSTR Options, _In_ ULONG Flags); static void CALLBACK s_OnExit(_In_ HCS_EVENT* Event, _In_opt_ void* Context); static bool ParseTtyInformation( @@ -82,8 +82,7 @@ class DECLSPEC_UUID("0CFC5DC1-B6A7-45FC-8034-3FA9ED73CE30") WSLAVirtualMachine void OnCrash(_In_ const HCS_EVENT* Event); std::tuple Fork(enum WSLA_FORK::ForkType Type); - std::tuple Fork( - wsl::shared::SocketChannel& Channel, enum WSLA_FORK::ForkType Type, ULONG TtyRows = 0, ULONG TtyColumns = 0); + std::tuple Fork(wsl::shared::SocketChannel& Channel, enum WSLA_FORK::ForkType Type); int32_t ExpectClosedChannelOrError(wsl::shared::SocketChannel& Channel); ConnectedSocket ConnectSocket(wsl::shared::SocketChannel& Channel, int32_t Fd); @@ -122,8 +121,6 @@ class DECLSPEC_UUID("0CFC5DC1-B6A7-45FC-8034-3FA9ED73CE30") WSLAVirtualMachine PSID m_userSid{}; wil::unique_handle m_userToken; std::wstring m_debugShellPipe; - - std::mutex m_trackedProcessesLock; std::vector m_trackedProcesses; wsl::windows::common::hcs::unique_hcs_system m_computeSystem; @@ -147,5 +144,6 @@ class DECLSPEC_UUID("0CFC5DC1-B6A7-45FC-8034-3FA9ED73CE30") WSLAVirtualMachine std::map m_plan9Mounts; std::recursive_mutex m_lock; std::mutex m_portRelaylock; + WSLAUserSessionImpl* m_userSession; }; } // namespace wsl::windows::service::wsla \ No newline at end of file