diff --git a/src/windows/common/WslClient.cpp b/src/windows/common/WslClient.cpp index 4e94a8c..dedeb2d 100644 --- a/src/windows/common/WslClient.cpp +++ b/src/windows/common/WslClient.cpp @@ -1551,6 +1551,7 @@ int WslaShell(_In_ std::wstring_view commandLine) std::wstring containerRootVhd; std::string containerImage; bool help = false; + std::wstring debugShell; ArgumentParser parser(std::wstring{commandLine}, WSL_BINARY_NAME); parser.AddArgument(vhd, L"--vhd"); @@ -1561,6 +1562,7 @@ int WslaShell(_In_ std::wstring_view commandLine) parser.AddArgument(Utf8String(fsType), L"--fstype"); parser.AddArgument(containerRootVhd, L"--container-vhd"); parser.AddArgument(Utf8String(containerImage), L"--image"); + parser.AddArgument(debugShell, L"--debug-shell"); parser.AddArgument(help, L"--help"); parser.Parse(); @@ -1596,16 +1598,24 @@ int WslaShell(_In_ std::wstring_view commandLine) wil::com_ptr session; settings.RootVhd = vhd.c_str(); settings.RootVhdType = fsType.c_str(); - THROW_IF_FAILED(userSession->CreateSession(&sessionSettings, &settings, &session)); - THROW_IF_FAILED(session->GetVirtualMachine(&virtualMachine)); - wsl::windows::common::security::ConfigureForCOMImpersonation(userSession.get()); - - if (!containerRootVhd.empty()) + if (!debugShell.empty()) { - wsl::windows::common::WSLAProcessLauncher initProcessLauncher{shell, {shell, "/etc/lsw-init.sh"}}; - auto initProcess = initProcessLauncher.Launch(*session); - THROW_HR_IF(E_FAIL, initProcess.WaitAndCaptureOutput().Code != 0); + THROW_IF_FAILED(userSession->OpenSessionByName(debugShell.c_str(), &session)); + } + else + { + THROW_IF_FAILED(userSession->CreateSession(&sessionSettings, &settings, &session)); + THROW_IF_FAILED(session->GetVirtualMachine(&virtualMachine)); + + wsl::windows::common::security::ConfigureForCOMImpersonation(userSession.get()); + + if (!containerRootVhd.empty()) + { + wsl::windows::common::WSLAProcessLauncher initProcessLauncher{shell, {shell, "/etc/lsw-init.sh"}}; + auto initProcess = initProcessLauncher.Launch(*session); + THROW_HR_IF(E_FAIL, initProcess.WaitAndCaptureOutput().Code != 0); + } } std::optional> container; diff --git a/src/windows/common/wslutil.cpp b/src/windows/common/wslutil.cpp index fd0f10c..43da515 100644 --- a/src/windows/common/wslutil.cpp +++ b/src/windows/common/wslutil.cpp @@ -143,7 +143,8 @@ static const std::map g_commonErrors{ X_WIN32(ERROR_OPERATION_ABORTED), X_WIN32(WSAECONNREFUSED), X_WIN32(ERROR_BAD_PATHNAME), - X(WININET_E_TIMEOUT)}; + X(WININET_E_TIMEOUT), + X_WIN32(ERROR_INVALID_SID)}; #undef X diff --git a/src/windows/wslaservice/exe/WSLAProcess.cpp b/src/windows/wslaservice/exe/WSLAProcess.cpp index 30c1c24..95269a3 100644 --- a/src/windows/wslaservice/exe/WSLAProcess.cpp +++ b/src/windows/wslaservice/exe/WSLAProcess.cpp @@ -44,6 +44,8 @@ void WSLAProcess::OnVmTerminated() { m_state = WslaProcessStateSignalled; m_exitedCode = 9; // SIGKILL + + m_exitEvent.SetEvent(); } } diff --git a/src/windows/wslaservice/exe/WSLASession.cpp b/src/windows/wslaservice/exe/WSLASession.cpp index 3104dfa..bbfceff 100644 --- a/src/windows/wslaservice/exe/WSLASession.cpp +++ b/src/windows/wslaservice/exe/WSLASession.cpp @@ -60,6 +60,11 @@ HRESULT WSLASession::GetDisplayName(LPWSTR* DisplayName) return S_OK; } +const std::wstring& WSLASession::DisplayName() const +{ + return m_displayName; +} + HRESULT WSLASession::PullImage(LPCWSTR Image, const WSLA_REGISTRY_AUTHENTICATION_INFORMATION* RegistryInformation, IProgressCallback* ProgressCallback) { return E_NOTIMPL; diff --git a/src/windows/wslaservice/exe/WSLASession.h b/src/windows/wslaservice/exe/WSLASession.h index 5dc8796..362a70e 100644 --- a/src/windows/wslaservice/exe/WSLASession.h +++ b/src/windows/wslaservice/exe/WSLASession.h @@ -27,6 +27,7 @@ public: ~WSLASession(); IFACEMETHOD(GetDisplayName)(LPWSTR* DisplayName) override; + const std::wstring& DisplayName() const; // Image management. IFACEMETHOD(PullImage)(_In_ LPCWSTR Image, _In_ const WSLA_REGISTRY_AUTHENTICATION_INFORMATION* RegistryInformation, _In_ IProgressCallback* ProgressCallback) override; diff --git a/src/windows/wslaservice/exe/WSLAUserSession.cpp b/src/windows/wslaservice/exe/WSLAUserSession.cpp index f7d5941..95daaf9 100644 --- a/src/windows/wslaservice/exe/WSLAUserSession.cpp +++ b/src/windows/wslaservice/exe/WSLAUserSession.cpp @@ -47,8 +47,7 @@ PSID WSLAUserSessionImpl::GetUserSid() const return m_tokenInfo->User.Sid; } -HRESULT wsl::windows::service::wsla::WSLAUserSessionImpl::CreateSession( - const WSLA_SESSION_SETTINGS* Settings, const VIRTUAL_MACHINE_SETTINGS* VmSettings, IWSLASession** WslaSession) +HRESULT WSLAUserSessionImpl::CreateSession(const WSLA_SESSION_SETTINGS* Settings, const VIRTUAL_MACHINE_SETTINGS* VmSettings, IWSLASession** WslaSession) { auto session = wil::MakeOrThrow(*Settings, *this, *VmSettings); @@ -63,6 +62,23 @@ HRESULT wsl::windows::service::wsla::WSLAUserSessionImpl::CreateSession( return S_OK; } +HRESULT WSLAUserSessionImpl::OpenSessionByName(LPCWSTR DisplayName, IWSLASession** Session) +{ + std::lock_guard lock(m_wslaSessionsLock); + + // TODO: Check for duplicate on session creation. + for (auto& e : m_sessions) + { + if (e->DisplayName() == DisplayName) + { + THROW_IF_FAILED(e->QueryInterface(__uuidof(IWSLASession), (void**)Session)); + return S_OK; + } + } + + return HRESULT_FROM_WIN32(ERROR_NOT_FOUND); +} + wsl::windows::service::wsla::WSLAUserSession::WSLAUserSession(std::weak_ptr&& Session) : m_session(std::move(Session)) { @@ -92,7 +108,18 @@ HRESULT wsl::windows::service::wsla::WSLAUserSession::ListSessions(WSLA_SESSION_ { return E_NOTIMPL; } + HRESULT wsl::windows::service::wsla::WSLAUserSession::OpenSession(ULONG Id, IWSLASession** Session) { return E_NOTIMPL; } + +HRESULT wsl::windows::service::wsla::WSLAUserSession::OpenSessionByName(LPCWSTR DisplayName, IWSLASession** Session) +try +{ + auto session = m_session.lock(); + RETURN_HR_IF(RPC_E_DISCONNECTED, !session); + + return session->OpenSessionByName(DisplayName, Session); +} +CATCH_RETURN(); \ No newline at end of file diff --git a/src/windows/wslaservice/exe/WSLAUserSession.h b/src/windows/wslaservice/exe/WSLAUserSession.h index a7b6635..d0fcca5 100644 --- a/src/windows/wslaservice/exe/WSLAUserSession.h +++ b/src/windows/wslaservice/exe/WSLAUserSession.h @@ -30,6 +30,7 @@ public: PSID GetUserSid() const; HRESULT CreateSession(const WSLA_SESSION_SETTINGS* Settings, const VIRTUAL_MACHINE_SETTINGS* VmSettings, IWSLASession** WslaSession); + HRESULT OpenSessionByName(_In_ LPCWSTR DisplayName, _Out_ IWSLASession** Session); void OnSessionTerminated(WSLASession* Session); @@ -55,6 +56,7 @@ public: IFACEMETHOD(CreateSession)(const WSLA_SESSION_SETTINGS* WslaSessionSettings, const VIRTUAL_MACHINE_SETTINGS* VmSettings, IWSLASession** WslaSession) override; IFACEMETHOD(ListSessions)(_Out_ WSLA_SESSION_INFORMATION** Sessions, _Out_ ULONG* SessionsCount) override; IFACEMETHOD(OpenSession)(_In_ ULONG Id, _Out_ IWSLASession** Session) override; + IFACEMETHOD(OpenSessionByName)(_In_ LPCWSTR DisplayName, _Out_ IWSLASession** Session) override; private: std::weak_ptr m_session; diff --git a/src/windows/wslaservice/exe/WSLAUserSessionFactory.cpp b/src/windows/wslaservice/exe/WSLAUserSessionFactory.cpp index e13effe..0a28ede 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))); } diff --git a/src/windows/wslaservice/inc/wslaservice.idl b/src/windows/wslaservice/inc/wslaservice.idl index ef94c04..a3736c6 100644 --- a/src/windows/wslaservice/inc/wslaservice.idl +++ b/src/windows/wslaservice/inc/wslaservice.idl @@ -319,6 +319,7 @@ interface IWSLAUserSession : IUnknown HRESULT CreateSession([in] const struct WSLA_SESSION_SETTINGS* Settings, [in] const VIRTUAL_MACHINE_SETTINGS* VmSettings, [out]IWSLASession** Session); HRESULT ListSessions([out, size_is(, *SessionsCount)] struct WSLA_SESSION_INFORMATION** Sessions, [out] ULONG* SessionsCount); HRESULT OpenSession([in] ULONG Id, [out]IWSLASession** Session); + HRESULT OpenSessionByName([in] LPCWSTR DisplayName, [out]IWSLASession** Session); // TODO: Do we need 'TerminateSession()' ? } \ No newline at end of file diff --git a/test/windows/WSLATests.cpp b/test/windows/WSLATests.cpp index 3b06ddd..b0e2a46 100644 --- a/test/windows/WSLATests.cpp +++ b/test/windows/WSLATests.cpp @@ -1167,7 +1167,7 @@ class WSLATests // TODO: Remove once the proper rootfs VHD is available. ExpectCommandResult(session.get(), {"/etc/lsw-init.sh"}, 0); - // Test a simple container start. + /*// Test a simple container start. { WSLAContainerLauncher launcher("debian:latest", "test-simple", "echo", {"OK"}); auto container = launcher.Launch(*session); @@ -1178,16 +1178,15 @@ class WSLATests // Validate that env is correctly wired. { - WSLAContainerLauncher launcher("debian:latest", "test-env", "/bin/bash", {"-c", "echo $testenv"}, {{"testenv=testvalue"}}); - auto container = launcher.Launch(*session); - auto process = container.GetInitProcess(); + WSLAContainerLauncher launcher("debian:latest", "test-env", "/bin/bash", {"-c", "echo $testenv"}, + {{"testenv=testvalue"}}); auto container = launcher.Launch(*session); auto process = container.GetInitProcess(); ValidateProcessOutput(process, {{1, "testvalue\n"}}); - } + }*/ // Validate that starting containers work with the default entrypoint. - // TODO: This is hanging. Need wsladbg to see why cat seems to be stuck. + // TODO: This is hanging. nerdctl run seems to hang with -i is passed outside of a TTY context. /* { WSLAContainerLauncher launcher(