Add stub methods

This commit is contained in:
Blue 2025-11-06 18:57:03 -08:00
parent b4018e37ed
commit a28015836b
12 changed files with 347 additions and 10 deletions

View File

@ -252,6 +252,18 @@
<RegistryValue Name="LocalService" Value="WSLAService" Type="string" />
</RegistryKey>
<!-- WSLAContainer -->
<RegistryKey Root="HKCR" Key="CLSID\{B1F1C4E3-C225-4CAE-AD8A-34C004DE1AE4}">
<RegistryValue Name="AppId" Value="{E9B79997-57E3-4201-AECC-6A464E530DD2}" Type="string" />
<RegistryValue Value="WSLAContainer" Type="string" />
</RegistryKey>
<!-- WSLAProcess -->
<RegistryKey Root="HKCR" Key="CLSID\{AFBEA6D6-D8A4-4F81-8FED-F947EB74B33B}">
<RegistryValue Name="AppId" Value="{E9B79997-57E3-4201-AECC-6A464E530DD2}" Type="string" />
<RegistryValue Value="WSLAProcess" Type="string" />
</RegistryKey>
<!-- WSLAUserSession -->
<RegistryKey Root="HKCR" Key="CLSID\{a9b7a1b9-0671-405c-95f1-e0612cb4ce8f}">
<RegistryValue Name="AppId" Value="{E9B79997-57E3-4201-AECC-6A464E530DD2}" Type="string" />
@ -263,7 +275,6 @@
<RegistryValue Name="AppId" Value="{E9B79997-57E3-4201-AECC-6A464E530DD2}" Type="string" />
<RegistryValue Value="WSLAVirtualMachine" Type="string" />
</RegistryKey>
<!-- WSLASession -->
<RegistryKey Root="HKCR" Key="CLSID\{4877FEFC-4977-4929-A958-9F36AA1892A4}">
<RegistryValue Name="AppId" Value="{E9B79997-57E3-4201-AECC-6A464E530DD2}" Type="string" />
@ -286,6 +297,22 @@
</RegistryKey>
</RegistryKey>
<!-- IWSLAContainer-->
<RegistryKey Root="HKCR" Key="Interface\{7577FE8D-DE85-471E-B870-11669986F332}">
<RegistryValue Value="IWSLAContainer" Type="string" />
<RegistryKey Key="ProxyStubClsid32">
<RegistryValue Value="{4EA0C6DD-E9FF-48E7-994E-13A31D10DC61}" Type="string" />
</RegistryKey>
</RegistryKey>
<!-- IWSLAProcess-->
<RegistryKey Root="HKCR" Key="Interface\{1AD163CD-393D-4B33-83A2-8A3F3F23E608}">
<RegistryValue Value="IWSLAProcess" Type="string" />
<RegistryKey Key="ProxyStubClsid32">
<RegistryValue Value="{4EA0C6DD-E9FF-48E7-994E-13A31D10DC61}" Type="string" />
</RegistryKey>
</RegistryKey>
<!-- ITerminationCallback-->
<RegistryKey Root="HKCR" Key="Interface\{7BC4E198-6531-4FA6-ADE2-5EF3D2A04DFE}">
<RegistryValue Value="ITerminationCallback" Type="string" />
@ -294,6 +321,14 @@
</RegistryKey>
</RegistryKey>
<!-- IProgressCallback-->
<RegistryKey Root="HKCR" Key="Interface\{5038842F-53DB-4F30-A6D0-A41B02C94AC1}">
<RegistryValue Value="IProgressCallback" Type="string" />
<RegistryKey Key="ProxyStubClsid32">
<RegistryValue Value="{4EA0C6DD-E9FF-48E7-994E-13A31D10DC61}" Type="string" />
</RegistryKey>
</RegistryKey>
<!-- IWSLASession-->
<RegistryKey Root="HKCR" Key="Interface\{EF0661E4-6364-40EA-B433-E2FDF11F3519}">
<RegistryValue Value="IWSLASession" Type="string" />

View File

@ -2,6 +2,8 @@ set(SOURCES
application.manifest
main.rc
ServiceMain.cpp
WSLAContainer.cpp
WSLAProcess.cpp
WSLASession.cpp
WSLAUserSession.cpp
WSLAUserSessionFactory.cpp
@ -9,6 +11,8 @@ set(SOURCES
)
set(HEADERS
WSLAContainer.h
WSLAProcess.h
WSLASession.h
WSLAUserSession.h
WSLAUserSessionFactory.h

View File

@ -0,0 +1,55 @@
/*++
Copyright (c) Microsoft. All rights reserved.
Module Name:
WSLAContainer.cpp
Abstract:
Contains the implementation of WSLAContainer.
--*/
#include "precomp.h"
#include "WSLAContainer.h"
#include "WSLAProcess.h"
using wsl::windows::service::wsla::WSLAContainer;
HRESULT WSLAContainer::Start()
{
return E_NOTIMPL;
}
HRESULT WSLAContainer::Stop(int Signal, ULONG TimeoutMs)
{
return E_NOTIMPL;
}
HRESULT WSLAContainer::Delete()
{
return E_NOTIMPL;
}
HRESULT WSLAContainer::GetState(WSLA_CONTAINER_STATE* State)
{
return E_NOTIMPL;
}
HRESULT WSLAContainer::GetInitProcess(IWSLAProcess** process)
{
return E_NOTIMPL;
}
HRESULT WSLAContainer::Exec(const WSLA_PROCESS_OPTIONS* Options, IWSLAProcess** Process)
try
{
auto process = wil::MakeOrThrow<WSLAProcess>();
process.CopyTo(__uuidof(IWSLAProcess), (void**)Process);
return S_OK;
}
CATCH_RETURN();

View File

@ -0,0 +1,38 @@
/*++
Copyright (c) Microsoft. All rights reserved.
Module Name:
WSLAContainer.h
Abstract:
Contains the definition for WSLAContainer.
--*/
#pragma once
#include "wslaservice.h"
namespace wsl::windows::service::wsla {
class DECLSPEC_UUID("B1F1C4E3-C225-4CAE-AD8A-34C004DE1AE4") WSLAContainer
: public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWSLAContainer, IFastRundown>
{
public:
WSLAContainer() = default; // TODO
WSLAContainer(const WSLAContainer&) = delete;
WSLAContainer& operator=(const WSLAContainer&) = delete;
IFACEMETHOD(Start)() override;
IFACEMETHOD(Stop)(_In_ int Signal, _In_ ULONG TimeoutMs) override;
IFACEMETHOD(Delete)() override;
IFACEMETHOD(GetState)(_Out_ WSLA_CONTAINER_STATE* State) override;
IFACEMETHOD(GetInitProcess)(_Out_ IWSLAProcess** process) override;
IFACEMETHOD(Exec)(_In_ const WSLA_PROCESS_OPTIONS* Options, _Out_ IWSLAProcess** Process) override;
private:
};
} // namespace wsl::windows::service::wsla

View File

@ -0,0 +1,46 @@
/*++
Copyright (c) Microsoft. All rights reserved.
Module Name:
WSLAProcess.cpp
Abstract:
Contains the implementation of WSLAProcess.
--*/
#include "precomp.h"
#include "WSLAProcess.h"
using wsl::windows::service::wsla::WSLAProcess;
HRESULT WSLAProcess::Signal(int Signal)
{
return E_NOTIMPL;
}
HRESULT WSLAProcess::GetExitEvent(ULONG* Event)
try
{
*Event = HandleToUlong(common::wslutil::DuplicateHandleToCallingProcess(m_exitEvent.get()));
return S_OK;
}
CATCH_RETURN();
HRESULT WSLAProcess::GetStdHandle(ULONG Index, ULONG* Handle)
{
return E_NOTIMPL;
}
HRESULT WSLAProcess::GetPid(int* Pid)
{
return E_NOTIMPL;
}
HRESULT WSLAProcess::GetState(WSLA_PROCESS_STATE* State, int* Code)
{
return E_NOTIMPL;
}

View File

@ -0,0 +1,38 @@
/*++
Copyright (c) Microsoft. All rights reserved.
Module Name:
WSLAProcess.h
Abstract:
Contains the definition for WSLAProcess
--*/
#pragma once
#include "wslaservice.h"
namespace wsl::windows::service::wsla {
class DECLSPEC_UUID("AFBEA6D6-D8A4-4F81-8FED-F947EB74B33B") WSLAProcess
: public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWSLAProcess, IFastRundown>
{
public:
WSLAProcess() = default; // TODO
WSLAProcess(const WSLAProcess&) = delete;
WSLAProcess& operator=(const WSLAProcess&) = delete;
IFACEMETHOD(Signal)(_In_ int Signal) override;
IFACEMETHOD(GetExitEvent)(_Out_ ULONG* Event) override;
IFACEMETHOD(GetStdHandle)(_In_ ULONG Index, _Out_ ULONG* Handle) override;
IFACEMETHOD(GetPid)(_Out_ int* Pid) override;
IFACEMETHOD(GetState)(_Out_ WSLA_PROCESS_STATE* State, _Out_ int* Code) override;
private:
std::vector<wil::unique_handle> m_handles;
wil::unique_event m_exitEvent{wil::EventOptions::ManualReset};
};
} // namespace wsl::windows::service::wsla

View File

@ -12,8 +12,10 @@ Abstract:
--*/
#include "precomp.h"
#include "WSLASession.h"
#include "WSLAUserSession.h"
#include "WSLAContainer.h"
using wsl::windows::service::wsla::WSLASession;
@ -32,8 +34,61 @@ HRESULT WSLASession::GetDisplayName(LPWSTR* DisplayName)
return S_OK;
}
HRESULT WSLASession::PullImage(LPCWSTR Image, const WSLA_REGISTRY_AUTHENTICATION_INFORMATION* RegistryInformation, IProgressCallback* ProgressCallback)
{
return E_NOTIMPL;
}
HRESULT WSLASession::ImportImage(ULONG Handle, LPCWSTR Image, IProgressCallback* ProgressCallback)
{
return E_NOTIMPL;
}
HRESULT WSLASession::ListImages(WSLA_IMAGE_INFORMATION** Images, ULONG* Count)
{
return E_NOTIMPL;
}
HRESULT WSLASession::DeleteImage(LPCWSTR Image)
{
return E_NOTIMPL;
}
HRESULT WSLASession::CreateContainer(const WSLA_CONTAINER_OPTIONS* Options, IWSLAContainer** Container)
try
{
// Basic instanciation for testing.
// TODO: Implement.
auto container = wil::MakeOrThrow<WSLAContainer>();
container.CopyTo(__uuidof(IWSLAContainer), (void**)Container);
return S_OK;
}
CATCH_RETURN();
HRESULT WSLASession::OpenContainer(LPCWSTR Name, IWSLAContainer** Container)
{
return E_NOTIMPL;
}
HRESULT WSLASession::ListContainers(WSLA_CONTAINER** Images, ULONG* Count)
{
return E_NOTIMPL;
}
HRESULT WSLASession::GetVirtualMachine(IWSLAVirtualMachine** VirtualMachine)
{
THROW_IF_FAILED(m_virtualMachine.QueryInterface(__uuidof(IWSLAVirtualMachine), (void**)VirtualMachine));
return S_OK;
}
HRESULT WSLASession::CreateRootNamespaceProcess(const WSLA_PROCESS_OPTIONS* Options, IWSLAProcess** VirtualMachine)
{
return E_NOTIMPL;
}
HRESULT WSLASession::FormatVirtualDisk(LPCWSTR Path)
{
return E_NOTIMPL;
}

View File

@ -24,8 +24,26 @@ class DECLSPEC_UUID("4877FEFC-4977-4929-A958-9F36AA1892A4") WSLASession
{
public:
WSLASession(const WSLA_SESSION_SETTINGS& Settings, WSLAUserSessionImpl& userSessionImpl, const VIRTUAL_MACHINE_SETTINGS& VmSettings);
IFACEMETHOD(GetDisplayName)(LPWSTR* DisplayName);
IFACEMETHOD(GetVirtualMachine)(IWSLAVirtualMachine** VirtualMachine);
IFACEMETHOD(GetDisplayName)(LPWSTR* DisplayName) override;
// 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;
IFACEMETHOD(ListImages)(_Out_ WSLA_IMAGE_INFORMATION** Images, _Out_ ULONG* Count) override;
IFACEMETHOD(DeleteImage)(_In_ LPCWSTR Image) override;
// Container management.
IFACEMETHOD(CreateContainer)(_In_ const WSLA_CONTAINER_OPTIONS* Options, _Out_ IWSLAContainer** Container) override;
IFACEMETHOD(OpenContainer)(_In_ LPCWSTR Name, _In_ IWSLAContainer** Container) override;
IFACEMETHOD(ListContainers)(_Out_ WSLA_CONTAINER** Images, _Out_ ULONG* Count) override;
// VM management.
IFACEMETHOD(GetVirtualMachine)(IWSLAVirtualMachine** VirtualMachine) override;
IFACEMETHOD(CreateRootNamespaceProcess)(_In_ const WSLA_PROCESS_OPTIONS* Options, _Out_ IWSLAProcess** VirtualMachine) override;
// Disk management.
IFACEMETHOD(FormatVirtualDisk)(_In_ LPCWSTR Path) override;
private:
WSLA_SESSION_SETTINGS m_sessionSettings; // TODO: Revisit to see if we should have session settings as a member or not

View File

@ -113,3 +113,12 @@ try
return session->CreateSession(Settings, VmSettings, WslaSession);
}
CATCH_RETURN();
HRESULT wsl::windows::service::wsla::WSLAUserSession::ListSessions(WSLA_SESSION_INFORMATION** Sessions, ULONG* SessionsCount)
{
return E_NOTIMPL;
}
HRESULT wsl::windows::service::wsla::WSLAUserSession::OpenSession(ULONG Id, IWSLASession** Session)
{
return E_NOTIMPL;
}

View File

@ -57,7 +57,9 @@ public:
IFACEMETHOD(GetVersion)(_Out_ WSL_VERSION* Version) override;
IFACEMETHOD(CreateVirtualMachine)(const VIRTUAL_MACHINE_SETTINGS* Settings, IWSLAVirtualMachine** VirtualMachine) override; // TODO: Remove virtual machine awareness from WSLAUserSession
IFACEMETHOD(CreateSession)(const WSLA_SESSION_SETTINGS* WslaSessionSettings, const VIRTUAL_MACHINE_SETTINGS* VmSettings, IWSLASession** WslaSession);
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;
private:
std::weak_ptr<WSLAUserSessionImpl> m_session;

View File

@ -159,8 +159,8 @@ struct WSLA_PORT_MAPPING
struct WSLA_CONTAINER_OPTIONS
{
LPCWSTR Image;
LPCWSTR Name;
LPCSTR Image;
LPCSTR Name;
struct WSLA_PROCESS_OPTIONS* InitProcessOptions;
[unique, size_is(VolumesCount)] struct WSLA_VOLUME* Volumes;
ULONG VolumesCount;
@ -227,7 +227,7 @@ interface IWSLAContainer : IUnknown
HRESULT Delete(); // TODO: Look into lifetime logic.
HRESULT GetState([out] enum WSLA_CONTAINER_STATE* State);
HRESULT GetInitProcess([out] IWSLAProcess** Process);
HRESULT Exec([in] struct WSLA_PROCESS_OPTIONS* Options, [out] IWSLAProcess** Process);
HRESULT Exec([in] const struct WSLA_PROCESS_OPTIONS* Options, [out] IWSLAProcess** Process);
// Anonymous host port allocation (P1).
//HRESULT AllocateHostPort([in] LPCSTR Name, [in] USHORT ContainerPort, [out] USHORT* AllocatedHostPort);
@ -242,18 +242,18 @@ interface IWSLAContainer : IUnknown
interface IWSLASession : IUnknown
{
// Image management.
HRESULT PullImage([in] LPCWSTR Image, [in, unique] struct WSLA_REGISTRY_AUTHENTICATION_INFORMATION* RegistryInformation, [in, unique] IProgressCallback* ProgressCallback);
HRESULT PullImage([in] LPCWSTR Image, [in, unique] const struct WSLA_REGISTRY_AUTHENTICATION_INFORMATION* RegistryInformation, [in, unique] IProgressCallback* ProgressCallback);
HRESULT ImportImage([in] ULONG Handle, [in] LPCWSTR Image, [in, unique] IProgressCallback* ProgressCallback);
HRESULT ListImages([out, size_is(, *Count)] struct WSLA_IMAGE_INFORMATION** Images, [out] ULONG* Count);
HRESULT DeleteImage([in] LPCWSTR Image);
// Container management.
HRESULT CreateContainer([in] struct WSLA_CONTAINER_OPTIONS* Options, [out] IWSLAContainer** Container);
HRESULT CreateContainer([in] const struct WSLA_CONTAINER_OPTIONS* Options, [out] IWSLAContainer** Container);
HRESULT OpenContainer([in] LPCWSTR Name, [out] IWSLAContainer** Container);
HRESULT ListContainers([out, size_is(, *Count)] struct WSLA_CONTAINER** Images, [out] ULONG* Count);
// Create a process at the VM level. This is meant for debugging.
HRESULT CreateRootNamespaceProcess([in] struct WSLA_PROCESS_OPTIONS* Options, [out] IWSLAProcess** Process);
HRESULT CreateRootNamespaceProcess([in] const struct WSLA_PROCESS_OPTIONS* Options, [out] IWSLAProcess** Process);
// TODO: an OpenProcess() method can be added later if needed.

View File

@ -1131,4 +1131,41 @@ class WSLATests
VERIFY_ARE_EQUAL(returnedDisplayName.get(), std::wstring(L"my-display-name"));
}
TEST_METHOD(WiringSmokeTest)
{
wil::com_ptr<IWSLAUserSession> userSession;
VERIFY_SUCCEEDED(CoCreateInstance(__uuidof(WSLAUserSession), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&userSession)));
wsl::windows::common::security::ConfigureForCOMImpersonation(userSession.get());
WSLA_SESSION_SETTINGS settings{L"my-display-name"};
wil::com_ptr<IWSLASession> session;
VIRTUAL_MACHINE_SETTINGS vmSettings{};
vmSettings.BootTimeoutMs = 30 * 1000;
vmSettings.DisplayName = L"WSLA";
vmSettings.MemoryMb = 2048;
vmSettings.CpuCount = 4;
vmSettings.NetworkingMode = WslNetworkingModeNone;
vmSettings.EnableDebugShell = true;
VERIFY_SUCCEEDED(userSession->CreateSession(&settings, &vmSettings, &session));
wil::com_ptr<IWSLAContainer> container;
WSLA_CONTAINER_OPTIONS containerOptions{};
containerOptions.Image = "dummy";
containerOptions.Name = "dummy";
VERIFY_SUCCEEDED(session->CreateContainer(&containerOptions, &container));
wil::com_ptr<IWSLAProcess> process;
WSLA_PROCESS_OPTIONS processOptions{};
processOptions.Executable = "dummy";
VERIFY_SUCCEEDED(container->Exec(&processOptions, &process));
wil::unique_handle exitEvent;
VERIFY_SUCCEEDED(process->GetExitEvent(reinterpret_cast<ULONG*>(exitEvent.addressof())));
// Verify that the event handle is valid.
VERIFY_ARE_EQUAL(WaitForSingleObject(exitEvent.get(), 0), WAIT_TIMEOUT);
}
};