Merge branch 'feature/wsl-for-apps' into user/oneblue/container-events

This commit is contained in:
Blue 2025-12-09 00:32:23 +00:00 committed by GitHub
commit 6cb910a3cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 222 additions and 24 deletions

View File

@ -431,6 +431,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)

View File

@ -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)
@ -47,7 +47,7 @@ endif()
set_source_files_properties(${OUTPUT_PACKAGE} PROPERTIES GENERATED TRUE)
if (DEFINED WSL_POST_BUILD_COMMAND)
if (DEFINED WSL_POST_BUILD_COMMAND AND NOT "${WSL_POST_BUILD_COMMAND}" STREQUAL "")
add_custom_command(
TARGET msipackage
POST_BUILD

View File

@ -27,6 +27,7 @@
</File>
<File Id="wslg.exe" Name="wslg.exe" Source="${BIN}/wslg.exe" />
<File Id="wsladiag.exe" Name="wsladiag.exe" Source="${BIN}/wsladiag.exe" />
<File Id="wslhost.exe" Name="wslhost.exe" Source="${BIN}/wslhost.exe" />
<File Id="wslrelay.exe" Name="wslrelay.exe" Source="${BIN}/wslrelay.exe" />
<File Id="wslserviceproxystub.dll" Name="wslserviceproxystub.dll" Source="${BIN}/wslserviceproxystub.dll" />

View File

@ -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),

View File

@ -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

View File

@ -0,0 +1,14 @@
set(SOURCES
wsladiag.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)

View File

@ -0,0 +1,134 @@
/*++
Copyright (c) Microsoft. All rights reserved.
Module Name:
wsladiag.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"
#include "wslaservice.h"
#include "WslSecurity.h"
using namespace wsl::shared;
namespace wslutil = wsl::windows::common::wslutil;
int wsladiag_main(std::wstring_view commandLine)
{
wslutil::ConfigureCrt();
wslutil::InitializeWil();
WslTraceLoggingInitialize(WslaTelemetryProvider, !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();
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",
stderr);
};
// If '--help' was requested, print usage and exit.
if (help)
{
printUsage();
return 0;
}
if (!list)
{
// No recognized command → show usage
printUsage();
return 0;
}
// --list: Call WSLA service COM interface to retrieve and display sessions.
try
{
wil::com_ptr<IWSLAUserSession> userSession;
THROW_IF_FAILED(CoCreateInstance(__uuidof(WSLAUserSession), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&userSession)));
wsl::windows::common::security::ConfigureForCOMImpersonation(userSession.get());
wil::unique_cotaskmem_array_ptr<WSLA_SESSION_INFORMATION> sessions;
THROW_IF_FAILED(userSession->ListSessions(&sessions, sessions.size_address<ULONG>()));
if (sessions.size() == 0)
{
wslutil::PrintMessage(L"No WSLA sessions found.\n", stdout);
}
else
{
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 (const auto& session : sessions)
{
const auto* displayName = session.DisplayName;
wslutil::PrintMessage(std::format(L"{}\t{}\t\t{}\n", session.SessionId, session.CreatorPid, displayName), stdout);
}
}
return 0;
}
catch (...)
{
const auto hr = wil::ResultFromCaughtException();
const std::wstring hrMessage = wslutil::ErrorCodeToString(hr);
if (!hrMessage.empty())
{
wslutil::PrintMessage(std::format(L"Error listing WSLA sessions: 0x{:08x} - {}\n", static_cast<unsigned int>(hr), hrMessage), stderr);
}
else
{
wslutil::PrintMessage(std::format(L"Error listing WSLA sessions: 0x{:08x}\n", static_cast<unsigned int>(hr)), stderr);
}
return 1;
}
}
int wmain(int /*argc*/, wchar_t** /*argv*/)
{
try
{
// Use raw Unicode command line so ArgumentParser gets original input.
return wsladiag_main(GetCommandLineW());
}
CATCH_RETURN();
}

View File

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

View File

@ -22,8 +22,9 @@ Abstract:
using wsl::windows::service::wsla::WSLASession;
using wsl::windows::service::wsla::WSLAVirtualMachine;
WSLASession::WSLASession(const WSLA_SESSION_SETTINGS& Settings, WSLAUserSessionImpl& userSessionImpl) :
m_sessionSettings(Settings), m_userSession(&userSessionImpl), m_displayName(Settings.DisplayName)
WSLASession::WSLASession(ULONG id, const WSLA_SESSION_SETTINGS& Settings, WSLAUserSessionImpl& userSessionImpl) :
m_id(id), m_sessionSettings(Settings), m_userSession(&userSessionImpl), m_displayName(Settings.DisplayName)
{
WSL_LOG("SessionCreated", TraceLoggingValue(m_displayName.c_str(), "DisplayName"));
@ -192,17 +193,22 @@ void WSLASession::ConfigureStorage(const WSLA_SESSION_SETTINGS& Settings)
deleteVhdOnFailure.release();
}
HRESULT WSLASession::GetDisplayName(LPWSTR* DisplayName)
{
*DisplayName = wil::make_unique_string<wil::unique_cotaskmem_string>(m_displayName.c_str()).release();
return S_OK;
}
const std::wstring& WSLASession::DisplayName() const
{
return m_displayName;
}
ULONG WSLASession::GetId() const noexcept
{
return m_id;
}
void WSLASession::CopyDisplayName(_Out_writes_z_(bufferLength) PWSTR buffer, size_t bufferLength) const
{
THROW_HR_IF(E_BOUNDS, m_displayName.size() + 1 > bufferLength);
wcscpy_s(buffer, bufferLength, m_displayName.c_str());
}
HRESULT WSLASession::PullImage(LPCWSTR Image, const WSLA_REGISTRY_AUTHENTICATION_INFORMATION* RegistryInformation, IProgressCallback* ProgressCallback)
{
return E_NOTIMPL;

View File

@ -25,12 +25,16 @@ class DECLSPEC_UUID("4877FEFC-4977-4929-A958-9F36AA1892A4") WSLASession
: public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWSLASession, IFastRundown>
{
public:
WSLASession(const WSLA_SESSION_SETTINGS& Settings, WSLAUserSessionImpl& userSessionImpl);
WSLASession(ULONG id, const WSLA_SESSION_SETTINGS& Settings, WSLAUserSessionImpl& userSessionImpl);
~WSLASession();
IFACEMETHOD(GetDisplayName)(LPWSTR* DisplayName) override;
ULONG GetId() const noexcept;
const std::wstring& DisplayName() const;
void CopyDisplayName(_Out_writes_z_(bufferLength) PWSTR buffer, size_t bufferLength) const;
// Image management.
IFACEMETHOD(PullImage)(_In_ LPCWSTR Image, _In_ const WSLA_REGISTRY_AUTHENTICATION_INFORMATION* RegistryInformation, _In_ IProgressCallback* ProgressCallback) override;
IFACEMETHOD(ImportImage)(_In_ ULONG Handle, _In_ LPCWSTR Image, _In_ IProgressCallback* ProgressCallback) override;
@ -54,6 +58,8 @@ public:
void OnUserSessionTerminating();
private:
ULONG m_id = 0;
static WSLAVirtualMachine::Settings CreateVmSettings(const WSLA_SESSION_SETTINGS& Settings);
void ConfigureStorage(const WSLA_SESSION_SETTINGS& Settings);

View File

@ -27,7 +27,7 @@ WSLAUserSessionImpl::~WSLAUserSessionImpl()
// In case there are still COM references on sessions, signal that the user session is terminating
// so the sessions are all in a 'terminated' state.
{
std::lock_guard lock(m_lock);
std::lock_guard lock(m_wslaSessionsLock);
for (auto& e : m_sessions)
{
@ -38,7 +38,7 @@ WSLAUserSessionImpl::~WSLAUserSessionImpl()
void WSLAUserSessionImpl::OnSessionTerminated(WSLASession* Session)
{
std::lock_guard lock(m_lock);
std::lock_guard lock(m_wslaSessionsLock);
WI_VERIFY(m_sessions.erase(Session) == 1);
}
@ -49,7 +49,8 @@ PSID WSLAUserSessionImpl::GetUserSid() const
HRESULT WSLAUserSessionImpl::CreateSession(const WSLA_SESSION_SETTINGS* Settings, IWSLASession** WslaSession)
{
auto session = wil::MakeOrThrow<WSLASession>(*Settings, *this);
ULONG id = m_nextSessionId++;
auto session = wil::MakeOrThrow<WSLASession>(id, *Settings, *this);
std::lock_guard lock(m_wslaSessionsLock);
auto it = m_sessions.emplace(session.Get());
@ -80,6 +81,26 @@ HRESULT WSLAUserSessionImpl::OpenSessionByName(LPCWSTR DisplayName, IWSLASession
return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
}
HRESULT wsl::windows::service::wsla::WSLAUserSessionImpl::ListSessions(_Out_ WSLA_SESSION_INFORMATION** Sessions, _Out_ ULONG* SessionsCount)
{
std::lock_guard lock(m_wslaSessionsLock);
auto output = wil::make_unique_cotaskmem<WSLA_SESSION_INFORMATION[]>(m_sessions.size());
size_t index = 0;
for (auto* session : m_sessions)
{
output[index].SessionId = session->GetId();
output[index].CreatorPid = 0; // placeholder until we populate this later
session->CopyDisplayName(output[index].DisplayName, _countof(output[index].DisplayName));
++index;
}
*Sessions = output.release();
*SessionsCount = static_cast<ULONG>(m_sessions.size());
return S_OK;
}
wsl::windows::service::wsla::WSLAUserSession::WSLAUserSession(std::weak_ptr<WSLAUserSessionImpl>&& Session) :
m_session(std::move(Session))
{
@ -105,10 +126,21 @@ try
CATCH_RETURN();
HRESULT wsl::windows::service::wsla::WSLAUserSession::ListSessions(WSLA_SESSION_INFORMATION** Sessions, ULONG* SessionsCount)
try
{
return E_NOTIMPL;
if (!Sessions || !SessionsCount)
{
return E_INVALIDARG;
}
auto session = m_session.lock();
RETURN_HR_IF(RPC_E_DISCONNECTED, !session);
RETURN_IF_FAILED(session->ListSessions(Sessions, SessionsCount));
return S_OK;
}
CATCH_RETURN();
HRESULT wsl::windows::service::wsla::WSLAUserSession::OpenSession(ULONG Id, IWSLASession** Session)
{
return E_NOTIMPL;

View File

@ -15,6 +15,10 @@ Abstract:
#pragma once
#include "WSLAVirtualMachine.h"
#include "WSLASession.h"
#include <atomic>
#include <vector>
#include <mutex>
#include <unordered_set>
namespace wsl::windows::service::wsla {
@ -31,14 +35,15 @@ public:
HRESULT CreateSession(const WSLA_SESSION_SETTINGS* Settings, IWSLASession** WslaSession);
HRESULT OpenSessionByName(_In_ LPCWSTR DisplayName, _Out_ IWSLASession** Session);
HRESULT ListSessions(_Out_ WSLA_SESSION_INFORMATION** Sessions, _Out_ ULONG* SessionsCount);
void OnSessionTerminated(WSLASession* Session);
private:
wil::unique_tokeninfo_ptr<TOKEN_USER> m_tokenInfo;
std::atomic<ULONG> m_nextSessionId{1};
std::recursive_mutex m_wslaSessionsLock;
std::recursive_mutex m_lock;
// TODO-WSLA: Consider using a weak_ptr to easily destroy when the last client reference is released.
std::unordered_set<WSLASession*> m_sessions;

View File

@ -299,15 +299,14 @@ interface IWSLASession : IUnknown
HRESULT Shutdown([in] ULONG TimeoutMs);
// To be deleted.
HRESULT GetDisplayName([out] LPWSTR* DisplayName);
HRESULT GetVirtualMachine([out] IWSLAVirtualMachine **VirtualMachine);
}
struct WSLA_SESSION_INFORMATION
{
ULONG Id;
ULONG SessionId;
DWORD CreatorPid;
LPSTR DisplayName;
wchar_t DisplayName[256];
};
[