diff --git a/msipackage/package.wix.in b/msipackage/package.wix.in
index 88dc3ea171..b3b476f801 100644
--- a/msipackage/package.wix.in
+++ b/msipackage/package.wix.in
@@ -386,6 +386,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/windows/WslcSDK/CrashDumpCallback.cpp b/src/windows/WslcSDK/CrashDumpCallback.cpp
index 4490d710be..42d92b51b3 100644
--- a/src/windows/WslcSDK/CrashDumpCallback.cpp
+++ b/src/windows/WslcSDK/CrashDumpCallback.cpp
@@ -8,7 +8,7 @@ Module Name:
Abstract:
- Implementation of a type that implements ICrashDumpCallback.
+ Implementation of a type that implements IWSLCCompatCrashDumpCallback.
--*/
#include "precomp.h"
diff --git a/src/windows/WslcSDK/CrashDumpCallback.h b/src/windows/WslcSDK/CrashDumpCallback.h
index 28014fd603..ede7bcd5a0 100644
--- a/src/windows/WslcSDK/CrashDumpCallback.h
+++ b/src/windows/WslcSDK/CrashDumpCallback.h
@@ -8,21 +8,21 @@ Module Name:
Abstract:
- Header for a type that implements ICrashDumpCallback. Bridges the COM
- ICrashDumpCallback interface back to the C-style SDK callback registered
+ Header for a type that implements IWSLCCompatCrashDumpCallback. Bridges the COM
+ IWSLCCompatCrashDumpCallback interface back to the C-style SDK callback registered
via WslcRegisterSessionCrashDumpCallback.
--*/
#pragma once
-#include "wslc.h"
+#include "WSLCCompat.h"
#include "wslcsdkprivate.h"
#include
-struct CrashDumpCallback : public winrt::implements
+struct CrashDumpCallback : public winrt::implements
{
CrashDumpCallback(WslcSessionCrashDumpCallback callback, PVOID context);
- // ICrashDumpCallback
+ // IWSLCCompatCrashDumpCallback
HRESULT STDMETHODCALLTYPE OnCrashDump(_In_ LPCWSTR DumpPath, _In_opt_ LPCSTR ProcessName, _In_ ULONGLONG Pid, _In_ ULONG Signal, _In_ ULONGLONG Timestamp) override;
private:
diff --git a/src/windows/WslcSDK/IOCallback.cpp b/src/windows/WslcSDK/IOCallback.cpp
index ffc1733ad1..36695773a2 100644
--- a/src/windows/WslcSDK/IOCallback.cpp
+++ b/src/windows/WslcSDK/IOCallback.cpp
@@ -14,7 +14,7 @@ Module Name:
#include "precomp.h"
#include "WslcsdkPrivate.h"
-IOCallback::IOCallback(IWSLCProcess* process, const WslcContainerProcessIOCallbackOptions& options) :
+IOCallback::IOCallback(IWSLCCompatProcess* process, const WslcContainerProcessIOCallbackOptions& options) :
m_process(process), m_callbackOptions(std::make_unique(options))
{
using namespace wsl::windows::common::io;
@@ -55,7 +55,7 @@ IOCallback::IOCallback(IWSLCProcess* process, const WslcContainerProcessIOCallba
if (runResult && m_process && m_callbackOptions && m_callbackOptions->onExit)
{
- WSLCProcessState state{};
+ WSLCCompatProcessState state{};
int exitCode = -1;
// Prefer to make the callback even if we don't properly retrieve the exit code.
@@ -66,7 +66,7 @@ IOCallback::IOCallback(IWSLCProcess* process, const WslcContainerProcessIOCallba
}
else
{
- WI_ASSERT(state == WslcProcessStateExited);
+ WI_ASSERT(state == WSLCCompatProcessStateExited);
}
// Regardless of our ability to get the proper exit code, inform the caller that the process
@@ -119,11 +119,12 @@ bool IOCallback::HasIOCallback(const WslcContainerProcessIOCallbackOptions& opti
return options.onStdOut || options.onStdErr || options.onExit;
}
-wil::unique_handle IOCallback::GetIOHandle(IWSLCProcess* process, WslcProcessIOHandle ioHandle)
+wil::unique_handle IOCallback::GetIOHandle(IWSLCCompatProcess* process, WslcProcessIOHandle ioHandle)
{
- wsl::windows::common::wslutil::COMOutputHandle handle;
+ WSLCCompatHandle handle{};
- THROW_IF_FAILED(process->GetStdHandle(static_cast(static_cast>(ioHandle)), &handle));
+ THROW_IF_FAILED(process->GetStdHandle(static_cast(static_cast>(ioHandle)), &handle));
- return handle.Release();
+ // The handle value is the same regardless of the union member that was populated.
+ return wil::unique_handle{handle.Handle.File};
}
diff --git a/src/windows/WslcSDK/IOCallback.h b/src/windows/WslcSDK/IOCallback.h
index f018eb1498..0e3a9cc0db 100644
--- a/src/windows/WslcSDK/IOCallback.h
+++ b/src/windows/WslcSDK/IOCallback.h
@@ -12,7 +12,7 @@ Module Name:
--*/
#pragma once
-#include "wslc.h"
+#include "WSLCCompat.h"
#include "relay.hpp"
#include
@@ -21,7 +21,7 @@ struct WslcContainerProcessOptionsInternal;
struct IOCallback
{
- IOCallback(IWSLCProcess* process, const WslcContainerProcessIOCallbackOptions& options);
+ IOCallback(IWSLCCompatProcess* process, const WslcContainerProcessIOCallbackOptions& options);
~IOCallback();
void Cancel();
@@ -32,10 +32,10 @@ struct IOCallback
static bool HasIOCallback(const WslcContainerProcessOptionsInternal* options);
static bool HasIOCallback(const WslcContainerProcessIOCallbackOptions& options);
- static wil::unique_handle GetIOHandle(IWSLCProcess* process, WslcProcessIOHandle ioHandle);
+ static wil::unique_handle GetIOHandle(IWSLCCompatProcess* process, WslcProcessIOHandle ioHandle);
private:
- wil::com_ptr m_process;
+ wil::com_ptr m_process;
std::unique_ptr m_callbackOptions;
std::thread m_thread;
wsl::windows::common::io::MultiHandleWait m_io;
diff --git a/src/windows/WslcSDK/ProgressCallback.cpp b/src/windows/WslcSDK/ProgressCallback.cpp
index 244480b4b9..b0aafc8e51 100644
--- a/src/windows/WslcSDK/ProgressCallback.cpp
+++ b/src/windows/WslcSDK/ProgressCallback.cpp
@@ -8,7 +8,7 @@ Module Name:
Abstract:
- Implementation of a type that implements IProgressCallback.
+ Implementation of a type that implements IWSLCCompatProgressCallback.
--*/
#include "precomp.h"
diff --git a/src/windows/WslcSDK/ProgressCallback.h b/src/windows/WslcSDK/ProgressCallback.h
index 8668a44cb0..6eb728717e 100644
--- a/src/windows/WslcSDK/ProgressCallback.h
+++ b/src/windows/WslcSDK/ProgressCallback.h
@@ -8,19 +8,19 @@ Module Name:
Abstract:
- Header for a type that implements IProgressCallback.
+ Header for a type that implements IWSLCCompatProgressCallback.
--*/
#pragma once
-#include "wslc.h"
+#include "WSLCCompat.h"
#include "wslcsdkprivate.h"
#include
-struct ProgressCallback : public winrt::implements
+struct ProgressCallback : public winrt::implements
{
ProgressCallback(WslcContainerImageProgressCallback callback, PVOID context);
- // IProgressCallback
+ // IWSLCCompatProgressCallback
HRESULT STDMETHODCALLTYPE OnProgress(LPCSTR Status, LPCSTR Id, ULONGLONG Current, ULONGLONG Total) override;
// Creates a ProgressCallback if the options provides a callback.
diff --git a/src/windows/WslcSDK/TerminationCallback.cpp b/src/windows/WslcSDK/TerminationCallback.cpp
index bd98a59529..c97e4343ee 100644
--- a/src/windows/WslcSDK/TerminationCallback.cpp
+++ b/src/windows/WslcSDK/TerminationCallback.cpp
@@ -8,20 +8,20 @@ Module Name:
Abstract:
- Implementation of a type that implements ITerminationCallback.
+ Implementation of a type that implements IWSLCCompatTerminationCallback.
--*/
#include "precomp.h"
#include "TerminationCallback.h"
namespace {
-WslcSessionTerminationReason ConvertReason(WSLCVirtualMachineTerminationReason Reason)
+WslcSessionTerminationReason ConvertReason(WSLCCompatVirtualMachineTerminationReason Reason)
{
switch (Reason)
{
- case WSLCVirtualMachineTerminationReasonShutdown:
+ case WSLCCompatVirtualMachineTerminationReasonShutdown:
return WSLC_SESSION_TERMINATION_REASON_SHUTDOWN;
- case WSLCVirtualMachineTerminationReasonCrashed:
+ case WSLCCompatVirtualMachineTerminationReasonCrashed:
return WSLC_SESSION_TERMINATION_REASON_CRASHED;
default:
return WSLC_SESSION_TERMINATION_REASON_UNKNOWN;
@@ -35,7 +35,7 @@ TerminationCallback::TerminationCallback(WslcSessionTerminationCallback callback
}
// TODO: Details from the runtime are dropped; should the SDK callback function be updated to include the reasons string?
-HRESULT STDMETHODCALLTYPE TerminationCallback::OnTermination(WSLCVirtualMachineTerminationReason Reason, LPCWSTR)
+HRESULT STDMETHODCALLTYPE TerminationCallback::OnTermination(WSLCCompatVirtualMachineTerminationReason Reason, LPCWSTR)
{
if (m_callback)
{
diff --git a/src/windows/WslcSDK/TerminationCallback.h b/src/windows/WslcSDK/TerminationCallback.h
index afd8542bf3..5a75192133 100644
--- a/src/windows/WslcSDK/TerminationCallback.h
+++ b/src/windows/WslcSDK/TerminationCallback.h
@@ -8,20 +8,20 @@ Module Name:
Abstract:
- Header for a type that implements ITerminationCallback.
+ Header for a type that implements IWSLCCompatTerminationCallback.
--*/
#pragma once
-#include "wslc.h"
+#include "WSLCCompat.h"
#include "wslcsdkprivate.h"
#include
-struct TerminationCallback : public winrt::implements
+struct TerminationCallback : public winrt::implements
{
TerminationCallback(WslcSessionTerminationCallback callback, PVOID context);
- // ITerminationCallback
- HRESULT STDMETHODCALLTYPE OnTermination(WSLCVirtualMachineTerminationReason Reason, LPCWSTR Details) override;
+ // IWSLCCompatTerminationCallback
+ HRESULT STDMETHODCALLTYPE OnTermination(WSLCCompatVirtualMachineTerminationReason Reason, LPCWSTR Details) override;
// Creates a TerminationCallback if the options provides a callback.
static winrt::com_ptr CreateIf(const WslcSessionOptionsInternal* options);
diff --git a/src/windows/WslcSDK/WslcsdkPrivate.h b/src/windows/WslcSDK/WslcsdkPrivate.h
index 5000363abd..cd0711de83 100644
--- a/src/windows/WslcSDK/WslcsdkPrivate.h
+++ b/src/windows/WslcSDK/WslcsdkPrivate.h
@@ -14,7 +14,7 @@ Module Name:
#pragma once
#include
#include "wslcsdk.h"
-#include "wslc.h"
+#include "WSLCCompat.h"
#include "IOCallback.h"
#include
#include // COM helpers
@@ -106,8 +106,8 @@ const WslcContainerOptionsInternal* GetInternalType(const WslcContainerSettings*
// Use to allocate the actual objects on the heap to keep it alive.
struct WslcSessionImpl
{
- wil::com_ptr session;
- wil::com_ptr terminationCallback;
+ wil::com_ptr session;
+ wil::com_ptr terminationCallback;
};
WslcSessionImpl* GetInternalType(WslcSession handle);
@@ -116,7 +116,7 @@ WslcSessionImpl* GetInternalType(WslcSession handle);
// subscription whose release unregisters the callback.
struct WslcCrashDumpSubscriptionImpl
{
- wil::com_ptr callback;
+ wil::com_ptr callback;
wil::com_ptr subscription;
};
@@ -124,7 +124,7 @@ WslcCrashDumpSubscriptionImpl* GetInternalType(WslcCrashDumpSubscription handle)
struct WslcContainerImpl
{
- wil::com_ptr container;
+ wil::com_ptr container;
WslcContainerProcessIOCallbackOptions ioCallbackOptions{};
std::atomic> ioCallbacks;
};
@@ -133,7 +133,7 @@ WslcContainerImpl* GetInternalType(WslcContainer handle);
struct WslcProcessImpl
{
- wil::com_ptr process;
+ wil::com_ptr process;
std::shared_ptr ioCallbacks;
};
diff --git a/src/windows/WslcSDK/wslcsdk.cpp b/src/windows/WslcSDK/wslcsdk.cpp
index 25dcdf1426..6299426e32 100644
--- a/src/windows/WslcSDK/wslcsdk.cpp
+++ b/src/windows/WslcSDK/wslcsdk.cpp
@@ -22,6 +22,7 @@ Module Name:
#include "Localization.h"
#include "WslInstall.h"
#include "wslutil.h"
+#include "APICompat.h"
#include "WindowsUpdateIntegration.h"
using namespace std::string_view_literals;
@@ -41,35 +42,35 @@ struct FlagsTraits
template <>
struct FlagsTraits
{
- using WslcType = WSLCFeatureFlags;
+ using WslcType = WSLCCompatFeatureFlags;
constexpr static WslcSessionFeatureFlags Mask = WSLC_SESSION_FEATURE_FLAG_ENABLE_GPU;
- WSLC_FLAG_VALUE_ASSERT(WSLC_SESSION_FEATURE_FLAG_ENABLE_GPU, WslcFeatureFlagsGPU);
+ WSLC_FLAG_VALUE_ASSERT(WSLC_SESSION_FEATURE_FLAG_ENABLE_GPU, WSLCCompatFeatureFlagsGPU);
};
template <>
struct FlagsTraits
{
- using WslcType = WSLCContainerFlags;
+ using WslcType = WSLCCompatContainerFlags;
constexpr static WslcContainerFlags Mask = WSLC_CONTAINER_FLAG_AUTO_REMOVE | WSLC_CONTAINER_FLAG_ENABLE_GPU;
- WSLC_FLAG_VALUE_ASSERT(WSLC_CONTAINER_FLAG_AUTO_REMOVE, WSLCContainerFlagsRm);
- WSLC_FLAG_VALUE_ASSERT(WSLC_CONTAINER_FLAG_ENABLE_GPU, WSLCContainerFlagsGpu);
+ WSLC_FLAG_VALUE_ASSERT(WSLC_CONTAINER_FLAG_AUTO_REMOVE, WSLCCompatContainerFlagsRm);
+ WSLC_FLAG_VALUE_ASSERT(WSLC_CONTAINER_FLAG_ENABLE_GPU, WSLCCompatContainerFlagsGpu);
// TODO: WSLC_CONTAINER_FLAG_PRIVILEGED has no associated runtime value
};
template <>
struct FlagsTraits
{
- using WslcType = WSLCContainerStartFlags;
+ using WslcType = WSLCCompatContainerStartFlags;
constexpr static WslcContainerStartFlags Mask = WSLC_CONTAINER_START_FLAG_ATTACH;
- WSLC_FLAG_VALUE_ASSERT(WSLC_CONTAINER_START_FLAG_ATTACH, WSLCContainerStartFlagsAttach);
+ WSLC_FLAG_VALUE_ASSERT(WSLC_CONTAINER_START_FLAG_ATTACH, WSLCCompatContainerStartFlagsAttach);
};
template <>
struct FlagsTraits
{
- using WslcType = WSLCDeleteFlags;
+ using WslcType = WSLCCompatDeleteFlags;
constexpr static WslcDeleteContainerFlags Mask = WSLC_DELETE_CONTAINER_FLAG_FORCE;
- WSLC_FLAG_VALUE_ASSERT(WSLC_DELETE_CONTAINER_FLAG_FORCE, WSLCDeleteFlagsForce);
+ WSLC_FLAG_VALUE_ASSERT(WSLC_DELETE_CONTAINER_FLAG_FORCE, WSLCCompatDeleteFlagsForce);
};
template
@@ -79,22 +80,22 @@ typename FlagsTraits::WslcType ConvertFlags(Flags flags)
return static_cast(flags & traits::Mask);
}
-WSLCSignal Convert(WslcSignal signal)
+WSLCCompatSignal Convert(WslcSignal signal)
{
switch (signal)
{
case WSLC_SIGNAL_NONE:
- return WSLCSignal::WSLCSignalNone;
+ return WSLCCompatSignal::WSLCCompatSignalNone;
case WSLC_SIGNAL_SIGHUP:
- return WSLCSignal::WSLCSignalSIGHUP;
+ return WSLCCompatSignal::WSLCCompatSignalSIGHUP;
case WSLC_SIGNAL_SIGINT:
- return WSLCSignal::WSLCSignalSIGINT;
+ return WSLCCompatSignal::WSLCCompatSignalSIGINT;
case WSLC_SIGNAL_SIGQUIT:
- return WSLCSignal::WSLCSignalSIGQUIT;
+ return WSLCCompatSignal::WSLCCompatSignalSIGQUIT;
case WSLC_SIGNAL_SIGKILL:
- return WSLCSignal::WSLCSignalSIGKILL;
+ return WSLCCompatSignal::WSLCCompatSignalSIGKILL;
case WSLC_SIGNAL_SIGTERM:
- return WSLCSignal::WSLCSignalSIGTERM;
+ return WSLCCompatSignal::WSLCCompatSignalSIGTERM;
default:
THROW_HR_MSG(E_INVALIDARG, "Invalid WslcSignal: %i", signal);
}
@@ -208,7 +209,7 @@ static HRESULT InetNtopToHresult(int af, const void* src, char* dst, size_t dstC
return S_OK;
}
-bool CopyProcessSettingsToRuntime(WSLCProcessOptions& runtimeOptions, const WslcContainerProcessOptionsInternal* initProcessOptions)
+bool CopyProcessSettingsToRuntime(WSLCCompatProcessOptions& runtimeOptions, const WslcContainerProcessOptionsInternal* initProcessOptions)
{
if (initProcessOptions)
{
@@ -306,13 +307,13 @@ WslRuntimeState CheckWslRuntimeState()
return DoesWslRuntimeVersionSupportWslc(version) ? WslRuntimeState::InstalledWithWslcSupport : WslRuntimeState::InstalledWithoutWslcSupport;
}
-std::pair, HRESULT> CreateSessionManagerRaw()
+std::pair, HRESULT> CreateSessionManagerRaw()
{
- wil::com_ptr result;
+ wil::com_ptr result;
HRESULT hr = CoCreateInstance(__uuidof(WSLCSessionManager), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&result));
if (SUCCEEDED(hr))
{
- const WSLCVersion clientVersion{WSL_PACKAGE_VERSION_MAJOR, WSL_PACKAGE_VERSION_MINOR, WSL_PACKAGE_VERSION_REVISION};
+ const WSLCCompatVersion clientVersion{WSL_PACKAGE_VERSION_MAJOR, WSL_PACKAGE_VERSION_MINOR, WSL_PACKAGE_VERSION_REVISION};
BOOL isSupported = FALSE;
THROW_IF_FAILED(result->IsClientVersionSupported(&clientVersion, &isSupported));
@@ -332,7 +333,7 @@ std::pair, HRESULT> CreateSessionManagerRaw()
return {result, hr};
}
-wil::com_ptr CreateSessionManager()
+wil::com_ptr CreateSessionManager()
{
auto [result, hr] = CreateSessionManagerRaw();
@@ -424,29 +425,29 @@ try
ErrorInfoWrapper errorInfoWrapper{errorMessage};
auto internalType = CheckAndGetInternalType(sessionSettings);
- wil::com_ptr sessionManager = CreateSessionManager();
+ wil::com_ptr sessionManager = CreateSessionManager();
auto result = std::make_unique();
- WSLCSessionSettings runtimeSettings{};
+ WSLCCompatSessionSettings runtimeSettings{};
runtimeSettings.DisplayName = internalType->displayName;
runtimeSettings.StoragePath = internalType->storagePath;
runtimeSettings.MaximumStorageSizeMb = internalType->vhdRequirements.sizeBytes / _1MB;
runtimeSettings.CpuCount = internalType->cpuCount;
runtimeSettings.MemoryMb = internalType->memoryMb;
runtimeSettings.BootTimeoutMs = internalType->timeoutMS;
- runtimeSettings.NetworkingMode = WSLCNetworkingModeVirtioProxy;
+ runtimeSettings.NetworkingMode = WSLCCompatNetworkingModeVirtioProxy;
auto terminationCallback = TerminationCallback::CreateIf(internalType);
if (terminationCallback)
{
- result->terminationCallback.attach(terminationCallback.as().detach());
+ result->terminationCallback.attach(terminationCallback.as().detach());
runtimeSettings.TerminationCallback = terminationCallback.get();
}
runtimeSettings.FeatureFlags = ConvertFlags(internalType->featureFlags);
- WI_SetFlag(runtimeSettings.FeatureFlags, WslcFeatureFlagsVirtioFs);
- WI_SetFlag(runtimeSettings.FeatureFlags, WslcFeatureFlagsDnsTunneling);
+ WI_SetFlag(runtimeSettings.FeatureFlags, WSLCCompatFeatureFlagsVirtioFs);
+ WI_SetFlag(runtimeSettings.FeatureFlags, WSLCCompatFeatureFlagsDnsTunneling);
if (SUCCEEDED(errorInfoWrapper.CaptureResult(
- sessionManager->CreateSession(&runtimeSettings, WSLCSessionFlagsNone, nullptr, &result->session))))
+ sessionManager->CreateSession(&runtimeSettings, WSLCCompatSessionFlagsNone, nullptr, &result->session))))
{
wsl::windows::common::security::ConfigureForCOMImpersonation(result->session.get());
*session = reinterpret_cast(result.release());
@@ -506,7 +507,7 @@ try
std::string uidStr;
std::string gidStr;
- std::vector driverOpts;
+ std::vector driverOpts;
driverOpts.push_back({"SizeBytes", sizeStr.c_str()});
if (options->type == WSLC_VHD_TYPE_FIXED)
@@ -526,13 +527,13 @@ try
driverOpts.push_back({"Gid", gidStr.c_str()});
}
- WSLCVolumeOptions volumeOptions{};
+ WSLCCompatVolumeOptions volumeOptions{};
volumeOptions.Name = options->name;
volumeOptions.Driver = "vhd";
volumeOptions.DriverOpts = driverOpts.data();
volumeOptions.DriverOptsCount = static_cast(driverOpts.size());
- WSLCVolumeInformation volumeInfo{};
+ WSLCCompatVolumeInformation volumeInfo{};
return errorInfoWrapper.CaptureResult(internalType->session->CreateVolume(&volumeOptions, &volumeInfo));
}
CATCH_RETURN();
@@ -675,10 +676,10 @@ try
// If the container has an IO callback registered, and the container has exited, wait until the IO callback has processed all IO.
try
{
- WSLCContainerState state{};
+ WSLCCompatContainerState state{};
THROW_IF_FAILED(internalType->container->GetState(&state));
- if (state == WslcContainerStateExited || state == WslcContainerStateDeleted)
+ if (state == WSLCCompatContainerStateExited || state == WSLCCompatContainerStateDeleted)
{
ioCallback->Complete();
}
@@ -710,11 +711,11 @@ try
try
{
- WSLCProcessState state{};
+ WSLCCompatProcessState state{};
int exitCode{};
THROW_IF_FAILED(internalType->process->GetState(&state, &exitCode));
- if (state == WslcProcessStateExited || state == WslcProcessStateSignalled)
+ if (state == WSLCCompatProcessStateExited || state == WSLCCompatProcessStateSignalled)
{
internalType->ioCallbacks->Complete();
}
@@ -756,8 +757,8 @@ try
auto result = std::make_unique();
- WSLCContainerOptions containerOptions{};
- std::unique_ptr convertedPorts; // this must stay in same scope as containerOptions since containerOptions.Ports is getting a raw pointer to the array owned by convertedPorts.
+ WSLCCompatContainerOptions containerOptions{};
+ std::unique_ptr convertedPorts; // this must stay in same scope as containerOptions since containerOptions.Ports is getting a raw pointer to the array owned by convertedPorts.
containerOptions.Image = internalContainerSettings->image;
containerOptions.Name = internalContainerSettings->runtimeName;
@@ -767,14 +768,14 @@ try
CopyProcessSettingsToRuntime(containerOptions.InitProcessOptions, internalContainerSettings->initProcessOptions);
- std::unique_ptr convertedVolumes;
+ std::unique_ptr convertedVolumes;
if (internalContainerSettings->volumes && internalContainerSettings->volumesCount)
{
- convertedVolumes = std::make_unique(internalContainerSettings->volumesCount);
+ convertedVolumes = std::make_unique(internalContainerSettings->volumesCount);
for (uint32_t i = 0; i < internalContainerSettings->volumesCount; ++i)
{
const WslcContainerVolume& internalVolume = internalContainerSettings->volumes[i];
- WSLCVolume& convertedVolume = convertedVolumes[i];
+ WSLCCompatVolume& convertedVolume = convertedVolumes[i];
convertedVolume.HostPath = internalVolume.windowsPath;
convertedVolume.ContainerPath = internalVolume.containerPath;
@@ -784,14 +785,14 @@ try
containerOptions.VolumesCount = static_cast(internalContainerSettings->volumesCount);
}
- std::unique_ptr convertedNamedVolumes;
+ std::unique_ptr convertedNamedVolumes;
if (internalContainerSettings->namedVolumes && internalContainerSettings->namedVolumesCount)
{
- convertedNamedVolumes = std::make_unique(internalContainerSettings->namedVolumesCount);
+ convertedNamedVolumes = std::make_unique(internalContainerSettings->namedVolumesCount);
for (uint32_t i = 0; i < internalContainerSettings->namedVolumesCount; ++i)
{
const WslcContainerNamedVolume& internalVolume = internalContainerSettings->namedVolumes[i];
- WSLCNamedVolume& convertedVolume = convertedNamedVolumes[i];
+ WSLCCompatNamedVolume& convertedVolume = convertedNamedVolumes[i];
convertedVolume.Name = internalVolume.name;
convertedVolume.ContainerPath = internalVolume.containerPath;
@@ -803,11 +804,11 @@ try
if (internalContainerSettings->ports && internalContainerSettings->portsCount)
{
- convertedPorts = std::make_unique(internalContainerSettings->portsCount);
+ convertedPorts = std::make_unique(internalContainerSettings->portsCount);
for (uint32_t i = 0; i < internalContainerSettings->portsCount; ++i)
{
const WslcContainerPortMapping& internalPort = internalContainerSettings->ports[i];
- WSLCPortMapping& convertedPort = convertedPorts[i];
+ WSLCCompatPortMapping& convertedPort = convertedPorts[i];
convertedPort.HostPort = internalPort.windowsPort;
convertedPort.ContainerPort = internalPort.containerPort;
@@ -904,11 +905,11 @@ try
// TODO: Consider if we should just override flags when callbacks were provided instead.
RETURN_HR_IF(E_INVALIDARG, WI_IsFlagClear(flags, WSLC_CONTAINER_START_FLAG_ATTACH) && hasIOCallback);
- if (SUCCEEDED(errorInfoWrapper.CaptureResult(internalType->container->Start(ConvertFlags(flags), nullptr, nullptr))))
+ if (SUCCEEDED(errorInfoWrapper.CaptureResult(internalType->container->Start(ConvertFlags(flags)))))
{
if (hasIOCallback)
{
- wil::com_ptr process;
+ wil::com_ptr process;
RETURN_IF_FAILED(internalType->container->GetInitProcess(&process));
wsl::windows::common::security::ConfigureForCOMImpersonation(process.get());
internalType->ioCallbacks = std::make_shared(process.get(), internalType->ioCallbackOptions);
@@ -1065,11 +1066,11 @@ try
auto internalProcessSettings = CheckAndGetInternalType(newProcessSettings);
RETURN_HR_IF(E_INVALIDARG, internalProcessSettings->commandLine == nullptr || internalProcessSettings->commandLineCount == 0);
- WSLCProcessOptions runtimeOptions{};
+ WSLCCompatProcessOptions runtimeOptions{};
CopyProcessSettingsToRuntime(runtimeOptions, internalProcessSettings);
auto result = std::make_unique();
- if (SUCCEEDED(errorInfoWrapper.CaptureResult(internalContainer->container->Exec(&runtimeOptions, nullptr, &result->process))))
+ if (SUCCEEDED(errorInfoWrapper.CaptureResult(internalContainer->container->Exec(&runtimeOptions, &result->process))))
{
wsl::windows::common::security::ConfigureForCOMImpersonation(result->process.get());
@@ -1090,7 +1091,7 @@ CATCH_RETURN();
STDAPI WslcGetContainerID(WslcContainer container, CHAR containerID[WSLC_CONTAINER_ID_BUFFER_SIZE])
try
{
- static_assert(WSLC_CONTAINER_ID_BUFFER_SIZE == sizeof(WSLCContainerId), "Container ID lengths differ.");
+ static_assert(WSLC_CONTAINER_ID_BUFFER_SIZE == sizeof(WSLCCompatContainerId), "Container ID lengths differ.");
auto internalType = CheckAndGetInternalType(container);
RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), internalType->container);
@@ -1144,9 +1145,9 @@ STDAPI WslcGetContainerState(_In_ WslcContainer container, _Out_ WslcContainerSt
try
{
static_assert(
- WSLC_CONTAINER_STATE_INVALID == WslcContainerStateInvalid && WSLC_CONTAINER_STATE_CREATED == WslcContainerStateCreated &&
- WSLC_CONTAINER_STATE_RUNNING == WslcContainerStateRunning &&
- WSLC_CONTAINER_STATE_EXITED == WslcContainerStateExited && WSLC_CONTAINER_STATE_DELETED == WslcContainerStateDeleted,
+ WSLC_CONTAINER_STATE_INVALID == WSLCCompatContainerStateInvalid && WSLC_CONTAINER_STATE_CREATED == WSLCCompatContainerStateCreated &&
+ WSLC_CONTAINER_STATE_RUNNING == WSLCCompatContainerStateRunning &&
+ WSLC_CONTAINER_STATE_EXITED == WSLCCompatContainerStateExited && WSLC_CONTAINER_STATE_DELETED == WSLCCompatContainerStateDeleted,
"Container state enum values mismatch.");
auto internalType = CheckAndGetInternalType(container);
@@ -1155,7 +1156,7 @@ try
*state = WSLC_CONTAINER_STATE_INVALID;
- WSLCContainerState runtimeState{};
+ WSLCCompatContainerState runtimeState{};
RETURN_IF_FAILED(internalType->container->GetState(&runtimeState));
*state = static_cast(runtimeState);
@@ -1279,8 +1280,8 @@ STDAPI WslcGetProcessState(_In_ WslcProcess process, _Out_ WslcProcessState* sta
try
{
static_assert(
- WSLC_PROCESS_STATE_UNKNOWN == WslcProcessStateUnknown && WSLC_PROCESS_STATE_RUNNING == WslcProcessStateRunning &&
- WSLC_PROCESS_STATE_EXITED == WslcProcessStateExited && WSLC_PROCESS_STATE_SIGNALLED == WslcProcessStateSignalled,
+ WSLC_PROCESS_STATE_UNKNOWN == WSLCCompatProcessStateUnknown && WSLC_PROCESS_STATE_RUNNING == WSLCCompatProcessStateRunning &&
+ WSLC_PROCESS_STATE_EXITED == WSLCCompatProcessStateExited && WSLC_PROCESS_STATE_SIGNALLED == WSLCCompatProcessStateSignalled,
"Process state enum values mismatch.");
auto internalType = CheckAndGetInternalType(process);
@@ -1289,7 +1290,7 @@ try
*state = WSLC_PROCESS_STATE_UNKNOWN;
- WSLCProcessState runtimeState{};
+ WSLCCompatProcessState runtimeState{};
int exitCode{};
RETURN_IF_FAILED(internalType->process->GetState(&runtimeState, &exitCode));
@@ -1307,9 +1308,9 @@ try
*exitCode = -1;
- WSLCProcessState runtimeState{};
+ WSLCCompatProcessState runtimeState{};
RETURN_IF_FAILED(internalType->process->GetState(&runtimeState, exitCode));
- RETURN_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), runtimeState != WslcProcessStateExited);
+ RETURN_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), runtimeState != WSLCCompatProcessStateExited);
return S_OK;
}
CATCH_RETURN();
@@ -1386,7 +1387,11 @@ static HRESULT WslcImportSessionImageImpl(
auto progressCallback = ProgressCallback::CreateIf(options);
return errorInfoWrapper.CaptureResult(internalSession->session->ImportImage(
- ToCOMInputHandle(imageFile.Handle()), imageName, progressCallback.get(), imageFile.Length(), nullptr));
+ wsl::windows::common::apicompat::Convert(ToCOMInputHandle(imageFile.Handle())),
+ imageName,
+ progressCallback.get(),
+ imageFile.Length(),
+ nullptr));
}
STDAPI WslcImportSessionImage(
@@ -1423,8 +1428,8 @@ static HRESULT WslcLoadSessionImageImpl(
{
auto progressCallback = ProgressCallback::CreateIf(options);
- return errorInfoWrapper.CaptureResult(
- internalSession->session->LoadImage(ToCOMInputHandle(imageFile.Handle()), progressCallback.get(), imageFile.Length(), nullptr));
+ return errorInfoWrapper.CaptureResult(internalSession->session->LoadImage(
+ wsl::windows::common::apicompat::Convert(ToCOMInputHandle(imageFile.Handle())), progressCallback.get(), imageFile.Length(), nullptr));
}
STDAPI WslcLoadSessionImage(
@@ -1460,11 +1465,11 @@ try
RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), internalType->session);
RETURN_HR_IF_NULL(E_POINTER, nameOrID);
- WSLCDeleteImageOptions options{};
+ WSLCCompatDeleteImageOptions options{};
options.Image = nameOrID;
// TODO: Flags? (Force and NoPrune)
- wil::unique_cotaskmem_array_ptr deletedImageInformation;
+ wil::unique_cotaskmem_array_ptr deletedImageInformation;
return errorInfoWrapper.CaptureResult(
internalType->session->DeleteImage(&options, &deletedImageInformation, deletedImageInformation.size_address()));
@@ -1482,7 +1487,7 @@ try
RETURN_HR_IF_NULL(E_INVALIDARG, options->repo);
RETURN_HR_IF_NULL(E_INVALIDARG, options->tag);
- WSLCTagImageOptions runtimeOptions{};
+ WSLCCompatTagImageOptions runtimeOptions{};
runtimeOptions.Image = options->image;
runtimeOptions.Repo = options->repo;
runtimeOptions.Tag = options->tag;
@@ -1542,7 +1547,7 @@ STDAPI WslcListSessionImages(_In_ WslcSession session, _Outptr_result_buffer_(*c
try
{
static_assert(
- sizeof(decltype(WslcImageInfo::name)) == sizeof(decltype(WSLCImageInformation::Image)), "Image name size mismatch.");
+ sizeof(decltype(WslcImageInfo::name)) == sizeof(decltype(WSLCCompatImageInformation::Image)), "Image name size mismatch.");
RETURN_HR_IF_NULL(E_POINTER, images);
*images = nullptr;
@@ -1553,7 +1558,7 @@ try
// TODO: Many filtering options are available via WSLC_LIST_IMAGES_OPTIONS
- wil::unique_cotaskmem_array_ptr imageInformation;
+ wil::unique_cotaskmem_array_ptr imageInformation;
RETURN_IF_FAILED(internalType->session->ListImages(nullptr, &imageInformation, imageInformation.size_address()));
@@ -1564,14 +1569,14 @@ try
for (size_t i = 0; i < imageInformation.size(); ++i)
{
WslcImageInfo& currentResult = result[i];
- WSLCImageInformation& currentImage = imageInformation[i];
+ WSLCCompatImageInformation& currentImage = imageInformation[i];
static_assert(std::is_trivial_v, "WslcImageInfo must be trivial.");
currentResult = {};
THROW_HR_IF(
E_UNEXPECTED,
- memcpy_s(currentResult.name, sizeof(decltype(WslcImageInfo::name)), currentImage.Image, sizeof(decltype(WSLCImageInformation::Image))) !=
+ memcpy_s(currentResult.name, sizeof(decltype(WslcImageInfo::name)), currentImage.Image, sizeof(decltype(WSLCCompatImageInformation::Image))) !=
0);
ConvertSHA256Hash(currentImage.Hash, currentResult.sha256);
currentResult.sizeBytes = currentImage.Size;
@@ -1629,9 +1634,9 @@ try
static_assert(std::is_trivial_v, "WslcVersion must be trivial");
*version = {};
- wil::com_ptr sessionManager = CreateSessionManager();
+ wil::com_ptr sessionManager = CreateSessionManager();
- WSLCVersion runtimeVersion{};
+ WSLCCompatVersion runtimeVersion{};
RETURN_IF_FAILED(sessionManager->GetVersion(&runtimeVersion));
version->major = runtimeVersion.Major;
diff --git a/src/windows/common/APICompat.cpp b/src/windows/common/APICompat.cpp
new file mode 100644
index 0000000000..c83c26a6b4
--- /dev/null
+++ b/src/windows/common/APICompat.cpp
@@ -0,0 +1,770 @@
+// Copyright (C) Microsoft Corporation. All rights reserved.
+
+#include "precomp.h"
+#include "APICompat.h"
+#include
+
+namespace wsl::windows::common::apicompat {
+
+namespace {
+
+ template
+ void CopyString(char (&Destination)[Size], const char* Source)
+ {
+ THROW_HR_IF(E_UNEXPECTED, strcpy_s(Destination, Source) != 0);
+ }
+
+ // Throws E_INVALIDARG if Value contains any bit outside of KnownMask.
+ template
+ void ThrowIfUnknownFlags(TValue Value, TMask KnownMask, PCSTR Name)
+ {
+ const auto value = static_cast(Value);
+ const auto mask = static_cast(KnownMask);
+ THROW_HR_IF_MSG(E_INVALIDARG, (value & ~mask) != 0, "Invalid %hs value: 0x%llx", Name, value);
+ }
+
+ template
+ std::vector ConvertArray(const TIn* Items, ULONG Count)
+ {
+ std::vector result;
+ if (Items == nullptr || Count == 0)
+ {
+ return result;
+ }
+
+ result.reserve(Count);
+ for (ULONG index = 0; index < Count; index++)
+ {
+ result.push_back(Convert(Items[index]));
+ }
+
+ return result;
+ }
+
+ class TerminationCallbackAdapter
+ : public Microsoft::WRL::RuntimeClass, ITerminationCallback>
+ {
+ public:
+ TerminationCallbackAdapter(IWSLCCompatTerminationCallback* Inner) : m_inner(Inner)
+ {
+ }
+
+ IFACEMETHOD(OnTermination)(WSLCVirtualMachineTerminationReason Reason, LPCWSTR Details) override
+ {
+ return m_inner->OnTermination(Convert(Reason), Details);
+ }
+
+ private:
+ Microsoft::WRL::ComPtr m_inner;
+ };
+
+ class CrashDumpCallbackAdapter
+ : public Microsoft::WRL::RuntimeClass, ICrashDumpCallback>
+ {
+ public:
+ CrashDumpCallbackAdapter(IWSLCCompatCrashDumpCallback* Inner) : m_inner(Inner)
+ {
+ }
+
+ IFACEMETHOD(OnCrashDump)(LPCWSTR DumpPath, LPCSTR ProcessName, ULONGLONG Pid, ULONG Signal, ULONGLONG Timestamp) override
+ {
+ return m_inner->OnCrashDump(DumpPath, ProcessName, Pid, Signal, Timestamp);
+ }
+
+ private:
+ Microsoft::WRL::ComPtr m_inner;
+ };
+
+ class ProgressCallbackAdapter
+ : public Microsoft::WRL::RuntimeClass, IProgressCallback>
+ {
+ public:
+ ProgressCallbackAdapter(IWSLCCompatProgressCallback* Inner) : m_inner(Inner)
+ {
+ }
+
+ IFACEMETHOD(OnProgress)(LPCSTR Status, LPCSTR Id, ULONGLONG Current, ULONGLONG Total) override
+ {
+ return m_inner->OnProgress(Status, Id, Current, Total);
+ }
+
+ private:
+ Microsoft::WRL::ComPtr m_inner;
+ };
+
+ class WarningCallbackAdapter
+ : public Microsoft::WRL::RuntimeClass, IWarningCallback>
+ {
+ public:
+ WarningCallbackAdapter(IWSLCCompatWarningCallback* Inner) : m_inner(Inner)
+ {
+ }
+
+ IFACEMETHOD(OnWarning)(LPCWSTR Message) override
+ {
+ return m_inner->OnWarning(Message);
+ }
+
+ private:
+ Microsoft::WRL::ComPtr m_inner;
+ };
+
+} // namespace
+
+//
+// Enum conversions.
+//
+
+WSLCFD Convert(WSLCCompatFD Fd)
+{
+ switch (Fd)
+ {
+ case WSLCCompatFDStdin:
+ return WSLCFDStdin;
+ case WSLCCompatFDStdout:
+ return WSLCFDStdout;
+ case WSLCCompatFDStderr:
+ return WSLCFDStderr;
+ case WSLCCompatFDTty:
+ return WSLCFDTty;
+ }
+
+ THROW_HR_MSG(E_INVALIDARG, "Invalid WSLCCompatFD value: %i", static_cast(Fd));
+}
+
+WSLCSignal Convert(WSLCCompatSignal Signal)
+{
+ switch (Signal)
+ {
+ case WSLCCompatSignalNone:
+ return WSLCSignalNone;
+ case WSLCCompatSignalSIGHUP:
+ return WSLCSignalSIGHUP;
+ case WSLCCompatSignalSIGINT:
+ return WSLCSignalSIGINT;
+ case WSLCCompatSignalSIGQUIT:
+ return WSLCSignalSIGQUIT;
+ case WSLCCompatSignalSIGILL:
+ return WSLCSignalSIGILL;
+ case WSLCCompatSignalSIGTRAP:
+ return WSLCSignalSIGTRAP;
+ case WSLCCompatSignalSIGABRT:
+ return WSLCSignalSIGABRT;
+ case WSLCCompatSignalSIGBUS:
+ return WSLCSignalSIGBUS;
+ case WSLCCompatSignalSIGFPE:
+ return WSLCSignalSIGFPE;
+ case WSLCCompatSignalSIGKILL:
+ return WSLCSignalSIGKILL;
+ case WSLCCompatSignalSIGUSR1:
+ return WSLCSignalSIGUSR1;
+ case WSLCCompatSignalSIGSEGV:
+ return WSLCSignalSIGSEGV;
+ case WSLCCompatSignalSIGUSR2:
+ return WSLCSignalSIGUSR2;
+ case WSLCCompatSignalSIGPIPE:
+ return WSLCSignalSIGPIPE;
+ case WSLCCompatSignalSIGALRM:
+ return WSLCSignalSIGALRM;
+ case WSLCCompatSignalSIGTERM:
+ return WSLCSignalSIGTERM;
+ case WSLCCompatSignalSIGTKFLT:
+ return WSLCSignalSIGTKFLT;
+ case WSLCCompatSignalSIGCHLD:
+ return WSLCSignalSIGCHLD;
+ case WSLCCompatSignalSIGCONT:
+ return WSLCSignalSIGCONT;
+ case WSLCCompatSignalSIGSTOP:
+ return WSLCSignalSIGSTOP;
+ case WSLCCompatSignalSIGTSTP:
+ return WSLCSignalSIGTSTP;
+ case WSLCCompatSignalSIGTTIN:
+ return WSLCSignalSIGTTIN;
+ case WSLCCompatSignalSIGTTOU:
+ return WSLCSignalSIGTTOU;
+ case WSLCCompatSignalSIGURG:
+ return WSLCSignalSIGURG;
+ case WSLCCompatSignalSIGXCPU:
+ return WSLCSignalSIGXCPU;
+ case WSLCCompatSignalSIGXFSZ:
+ return WSLCSignalSIGXFSZ;
+ case WSLCCompatSignalSIGVTALRM:
+ return WSLCSignalSIGVTALRM;
+ case WSLCCompatSignalSIGPROF:
+ return WSLCSignalSIGPROF;
+ case WSLCCompatSignalSIGWINCH:
+ return WSLCSignalSIGWINCH;
+ case WSLCCompatSignalSIGIO:
+ return WSLCSignalSIGIO;
+ case WSLCCompatSignalSIGPWR:
+ return WSLCSignalSIGPWR;
+ case WSLCCompatSignalSIGSYS:
+ return WSLCSignalSIGSYS;
+ }
+
+ THROW_HR_MSG(E_INVALIDARG, "Invalid Signal value: %i", static_cast(Signal));
+}
+
+WSLCProcessFlags Convert(WSLCCompatProcessFlags Flags)
+{
+ ThrowIfUnknownFlags(Flags, WSLCCompatProcessFlagsStdin | WSLCCompatProcessFlagsTty, "WSLCCompatProcessFlags");
+
+ WSLCProcessFlags result = WSLCProcessFlagsNone;
+ WI_SetFlagIf(result, WSLCProcessFlagsStdin, WI_IsFlagSet(Flags, WSLCCompatProcessFlagsStdin));
+ WI_SetFlagIf(result, WSLCProcessFlagsTty, WI_IsFlagSet(Flags, WSLCCompatProcessFlagsTty));
+ return result;
+}
+
+WSLCContainerFlags Convert(WSLCCompatContainerFlags Flags)
+{
+ ThrowIfUnknownFlags(
+ Flags,
+ WSLCCompatContainerFlagsRm | WSLCCompatContainerFlagsGpu | WSLCCompatContainerFlagsInit | WSLCCompatContainerFlagsPublishAll,
+ "WSLCCompatContainerFlags");
+
+ WSLCContainerFlags result = WSLCContainerFlagsNone;
+ WI_SetFlagIf(result, WSLCContainerFlagsRm, WI_IsFlagSet(Flags, WSLCCompatContainerFlagsRm));
+ WI_SetFlagIf(result, WSLCContainerFlagsGpu, WI_IsFlagSet(Flags, WSLCCompatContainerFlagsGpu));
+ WI_SetFlagIf(result, WSLCContainerFlagsInit, WI_IsFlagSet(Flags, WSLCCompatContainerFlagsInit));
+ WI_SetFlagIf(result, WSLCContainerFlagsPublishAll, WI_IsFlagSet(Flags, WSLCCompatContainerFlagsPublishAll));
+ return result;
+}
+
+WSLCContainerStartFlags Convert(WSLCCompatContainerStartFlags Flags)
+{
+ ThrowIfUnknownFlags(Flags, WSLCCompatContainerStartFlagsAttach, "WSLCCompatContainerStartFlags");
+
+ WSLCContainerStartFlags result = WSLCContainerStartFlagsNone;
+ WI_SetFlagIf(result, WSLCContainerStartFlagsAttach, WI_IsFlagSet(Flags, WSLCCompatContainerStartFlagsAttach));
+ return result;
+}
+
+WSLCDeleteFlags Convert(WSLCCompatDeleteFlags Flags)
+{
+ ThrowIfUnknownFlags(Flags, WSLCCompatDeleteFlagsForce | WSLCCompatDeleteFlagsDeleteVolumes, "WSLCCompatDeleteFlags");
+
+ WSLCDeleteFlags result = WSLCDeleteFlagsNone;
+ WI_SetFlagIf(result, WSLCDeleteFlagsForce, WI_IsFlagSet(Flags, WSLCCompatDeleteFlagsForce));
+ WI_SetFlagIf(result, WSLCDeleteFlagsDeleteVolumes, WI_IsFlagSet(Flags, WSLCCompatDeleteFlagsDeleteVolumes));
+ return result;
+}
+
+WSLCNetworkingMode Convert(WSLCCompatNetworkingMode Mode)
+{
+ switch (Mode)
+ {
+ case WSLCCompatNetworkingModeNone:
+ return WSLCNetworkingModeNone;
+ case WSLCCompatNetworkingModeNAT:
+ return WSLCNetworkingModeNAT;
+ case WSLCCompatNetworkingModeVirtioProxy:
+ return WSLCNetworkingModeVirtioProxy;
+ }
+
+ THROW_HR_MSG(E_INVALIDARG, "Invalid WSLCCompatNetworkingMode value: %i", static_cast(Mode));
+}
+
+WSLCFeatureFlags Convert(WSLCCompatFeatureFlags Flags)
+{
+ ThrowIfUnknownFlags(
+ Flags,
+ WSLCCompatFeatureFlagsDnsTunneling | WSLCCompatFeatureFlagsEarlyBootDmesg | WSLCCompatFeatureFlagsGPU |
+ WSLCCompatFeatureFlagsVirtioFs | WSLCCompatFeatureFlagsDebug,
+ "WSLCCompatFeatureFlags");
+
+ WSLCFeatureFlags result = WslcFeatureFlagsNone;
+ WI_SetFlagIf(result, WslcFeatureFlagsDnsTunneling, WI_IsFlagSet(Flags, WSLCCompatFeatureFlagsDnsTunneling));
+ WI_SetFlagIf(result, WslcFeatureFlagsEarlyBootDmesg, WI_IsFlagSet(Flags, WSLCCompatFeatureFlagsEarlyBootDmesg));
+ WI_SetFlagIf(result, WslcFeatureFlagsGPU, WI_IsFlagSet(Flags, WSLCCompatFeatureFlagsGPU));
+ WI_SetFlagIf(result, WslcFeatureFlagsVirtioFs, WI_IsFlagSet(Flags, WSLCCompatFeatureFlagsVirtioFs));
+ WI_SetFlagIf(result, WslcFeatureFlagsDebug, WI_IsFlagSet(Flags, WSLCCompatFeatureFlagsDebug));
+ return result;
+}
+
+WSLCSessionStorageFlags Convert(WSLCCompatSessionStorageFlags Flags)
+{
+ ThrowIfUnknownFlags(Flags, WSLCCompatSessionStorageFlagsNoCreate, "WSLCCompatSessionStorageFlags");
+
+ WSLCSessionStorageFlags result = WSLCSessionStorageFlagsNone;
+ WI_SetFlagIf(result, WSLCSessionStorageFlagsNoCreate, WI_IsFlagSet(Flags, WSLCCompatSessionStorageFlagsNoCreate));
+ return result;
+}
+
+WSLCSessionFlags Convert(WSLCCompatSessionFlags Flags)
+{
+ ThrowIfUnknownFlags(Flags, WSLCCompatSessionFlagsPersistent | WSLCCompatSessionFlagsOpenExisting, "WSLCCompatSessionFlags");
+
+ WSLCSessionFlags result = WSLCSessionFlagsNone;
+ WI_SetFlagIf(result, WSLCSessionFlagsPersistent, WI_IsFlagSet(Flags, WSLCCompatSessionFlagsPersistent));
+ WI_SetFlagIf(result, WSLCSessionFlagsOpenExisting, WI_IsFlagSet(Flags, WSLCCompatSessionFlagsOpenExisting));
+ return result;
+}
+
+WSLCListImagesFlags Convert(WSLCCompatListImagesFlags Flags)
+{
+ ThrowIfUnknownFlags(Flags, WSLCCompatListImagesFlagsAll | WSLCCompatListImagesFlagsDigests, "WSLCCompatListImagesFlags");
+
+ WSLCListImagesFlags result = WSLCListImagesFlagsNone;
+ WI_SetFlagIf(result, WSLCListImagesFlagsAll, WI_IsFlagSet(Flags, WSLCCompatListImagesFlagsAll));
+ WI_SetFlagIf(result, WSLCListImagesFlagsDigests, WI_IsFlagSet(Flags, WSLCCompatListImagesFlagsDigests));
+ return result;
+}
+
+WSLCDeleteImageFlags Convert(WSLCCompatDeleteImageFlags Flags)
+{
+ ThrowIfUnknownFlags(Flags, WSLCCompatDeleteImageFlagsForce | WSLCCompatDeleteImageFlagsNoPrune, "WSLCCompatDeleteImageFlags");
+
+ WSLCDeleteImageFlags result = WSLCDeleteImageFlagsNone;
+ WI_SetFlagIf(result, WSLCDeleteImageFlagsForce, WI_IsFlagSet(Flags, WSLCCompatDeleteImageFlagsForce));
+ WI_SetFlagIf(result, WSLCDeleteImageFlagsNoPrune, WI_IsFlagSet(Flags, WSLCCompatDeleteImageFlagsNoPrune));
+ return result;
+}
+
+WSLCHandleType Convert(WSLCCompatHandleType Type)
+{
+ switch (Type)
+ {
+ case WSLCCompatHandleTypeUnknown:
+ return WSLCHandleTypeUnknown;
+ case WSLCCompatHandleTypeFile:
+ return WSLCHandleTypeFile;
+ case WSLCCompatHandleTypePipe:
+ return WSLCHandleTypePipe;
+ case WSLCCompatHandleTypeSocket:
+ return WSLCHandleTypeSocket;
+ }
+
+ THROW_HR_MSG(E_INVALIDARG, "Invalid WSLCCompatHandleType value: %i", static_cast(Type));
+}
+
+WSLCCompatProcessState Convert(WSLCProcessState State)
+{
+ switch (State)
+ {
+ case WslcProcessStateUnknown:
+ return WSLCCompatProcessStateUnknown;
+ case WslcProcessStateRunning:
+ return WSLCCompatProcessStateRunning;
+ case WslcProcessStateExited:
+ return WSLCCompatProcessStateExited;
+ case WslcProcessStateSignalled:
+ return WSLCCompatProcessStateSignalled;
+ }
+
+ THROW_HR_MSG(E_INVALIDARG, "Invalid WSLCProcessState value: %i", static_cast(State));
+}
+
+WSLCCompatContainerState Convert(WSLCContainerState State)
+{
+ switch (State)
+ {
+ case WslcContainerStateInvalid:
+ return WSLCCompatContainerStateInvalid;
+ case WslcContainerStateCreated:
+ return WSLCCompatContainerStateCreated;
+ case WslcContainerStateRunning:
+ return WSLCCompatContainerStateRunning;
+ case WslcContainerStateExited:
+ return WSLCCompatContainerStateExited;
+ case WslcContainerStateDeleted:
+ return WSLCCompatContainerStateDeleted;
+ }
+
+ THROW_HR_MSG(E_INVALIDARG, "Invalid WSLCContainerState value: %i", static_cast(State));
+}
+
+WSLCCompatVirtualMachineTerminationReason Convert(WSLCVirtualMachineTerminationReason Reason)
+{
+ switch (Reason)
+ {
+ case WSLCVirtualMachineTerminationReasonUnknown:
+ return WSLCCompatVirtualMachineTerminationReasonUnknown;
+ case WSLCVirtualMachineTerminationReasonShutdown:
+ return WSLCCompatVirtualMachineTerminationReasonShutdown;
+ case WSLCVirtualMachineTerminationReasonCrashed:
+ return WSLCCompatVirtualMachineTerminationReasonCrashed;
+ }
+
+ THROW_HR_MSG(E_INVALIDARG, "Invalid WSLCVirtualMachineTerminationReason value: %i", static_cast(Reason));
+}
+
+WSLCCompatHandleType Convert(WSLCHandleType Type)
+{
+ switch (Type)
+ {
+ case WSLCHandleTypeUnknown:
+ return WSLCCompatHandleTypeUnknown;
+ case WSLCHandleTypeFile:
+ return WSLCCompatHandleTypeFile;
+ case WSLCHandleTypePipe:
+ return WSLCCompatHandleTypePipe;
+ case WSLCHandleTypeSocket:
+ return WSLCCompatHandleTypeSocket;
+ }
+
+ THROW_HR_MSG(E_INVALIDARG, "Invalid WSLCHandleType value: %i", static_cast(Type));
+}
+
+WSLCCompatDeletedImageType Convert(WSLCDeletedImageType Type)
+{
+ switch (Type)
+ {
+ case WSLCDeletedImageTypeDeleted:
+ return WSLCCompatDeletedImageTypeDeleted;
+ case WSLCDeletedImageTypeUntagged:
+ return WSLCCompatDeletedImageTypeUntagged;
+ }
+
+ THROW_HR_MSG(E_INVALIDARG, "Invalid WSLCDeletedImageType value: %i", static_cast(Type));
+}
+
+//
+// Scalar / non-owning struct conversions.
+//
+
+WSLCVersion Convert(const WSLCCompatVersion& Version)
+{
+ WSLCVersion result{};
+ result.Major = Version.Major;
+ result.Minor = Version.Minor;
+ result.Revision = Version.Revision;
+ return result;
+}
+
+WSLCCompatVersion Convert(const WSLCVersion& Version)
+{
+ WSLCCompatVersion result{};
+ result.Major = Version.Major;
+ result.Minor = Version.Minor;
+ result.Revision = Version.Revision;
+ return result;
+}
+
+WSLCHandle Convert(const WSLCCompatHandle& Handle)
+{
+ WSLCHandle result{};
+ result.Type = Convert(Handle.Type);
+ switch (Handle.Type)
+ {
+ case WSLCCompatHandleTypeFile:
+ result.Handle.File = Handle.Handle.File;
+ break;
+ case WSLCCompatHandleTypePipe:
+ result.Handle.Pipe = Handle.Handle.Pipe;
+ break;
+ case WSLCCompatHandleTypeSocket:
+ result.Handle.Socket = Handle.Handle.Socket;
+ break;
+ case WSLCCompatHandleTypeUnknown:
+ break;
+ }
+
+ return result;
+}
+
+WSLCCompatHandle Convert(const WSLCHandle& Handle)
+{
+ WSLCCompatHandle result{};
+ result.Type = Convert(Handle.Type);
+ switch (Handle.Type)
+ {
+ case WSLCHandleTypeFile:
+ result.Handle.File = Handle.Handle.File;
+ break;
+ case WSLCHandleTypePipe:
+ result.Handle.Pipe = Handle.Handle.Pipe;
+ break;
+ case WSLCHandleTypeSocket:
+ result.Handle.Socket = Handle.Handle.Socket;
+ break;
+ case WSLCHandleTypeUnknown:
+ break;
+ }
+
+ return result;
+}
+
+WSLCStringArray Convert(const WSLCCompatStringArray& Array)
+{
+ WSLCStringArray result{};
+ result.Values = Array.Values;
+ result.Count = Array.Count;
+ return result;
+}
+
+WSLCProcessOptions Convert(const WSLCCompatProcessOptions& Options)
+{
+ WSLCProcessOptions result{};
+ result.CurrentDirectory = Options.CurrentDirectory;
+ result.User = Options.User;
+ result.CommandLine = Convert(Options.CommandLine);
+ result.Environment = Convert(Options.Environment);
+ result.Flags = Convert(Options.Flags);
+ return result;
+}
+
+KeyValuePair Convert(const WSLCCompatKeyValuePair& Pair)
+{
+ KeyValuePair result{};
+ result.Key = Pair.Key;
+ result.Value = Pair.Value;
+ return result;
+}
+
+WSLCVolume Convert(const WSLCCompatVolume& Volume)
+{
+ WSLCVolume result{};
+ result.HostPath = Volume.HostPath;
+ result.ContainerPath = Volume.ContainerPath;
+ result.ReadOnly = Volume.ReadOnly;
+ return result;
+}
+
+WSLCNamedVolume Convert(const WSLCCompatNamedVolume& Volume)
+{
+ WSLCNamedVolume result{};
+ result.Name = Volume.Name;
+ result.ContainerPath = Volume.ContainerPath;
+ result.ReadOnly = Volume.ReadOnly;
+ return result;
+}
+
+WSLCPortMapping Convert(const WSLCCompatPortMapping& Port)
+{
+ WSLCPortMapping result{};
+ result.HostPort = Port.HostPort;
+ result.ContainerPort = Port.ContainerPort;
+ result.Family = Port.Family;
+ result.Protocol = Port.Protocol;
+ CopyString(result.BindingAddress, Port.BindingAddress);
+ return result;
+}
+
+WSLCTmpfsMount Convert(const WSLCCompatTmpfsMount& Mount)
+{
+ WSLCTmpfsMount result{};
+ result.Destination = Mount.Destination;
+ result.Options = Mount.Options;
+ return result;
+}
+
+WSLCUlimit Convert(const WSLCCompatUlimit& Ulimit)
+{
+ WSLCUlimit result{};
+ result.Name = Ulimit.Name;
+ result.Soft = Ulimit.Soft;
+ result.Hard = Ulimit.Hard;
+ return result;
+}
+
+WSLCDeleteImageOptions Convert(const WSLCCompatDeleteImageOptions& Options)
+{
+ WSLCDeleteImageOptions result{};
+ result.Image = Options.Image;
+ result.Flags = static_cast(Convert(static_cast(Options.Flags)));
+ return result;
+}
+
+WSLCTagImageOptions Convert(const WSLCCompatTagImageOptions& Options)
+{
+ WSLCTagImageOptions result{};
+ result.Image = Options.Image;
+ result.Repo = Options.Repo;
+ result.Tag = Options.Tag;
+ return result;
+}
+
+WSLCCompatImageInformation Convert(const WSLCImageInformation& Image)
+{
+ WSLCCompatImageInformation result{};
+ CopyString(result.Image, Image.Image);
+ CopyString(result.Hash, Image.Hash);
+ CopyString(result.Digest, Image.Digest);
+ result.Size = Image.Size;
+ result.Created = Image.Created;
+ CopyString(result.ParentId, Image.ParentId);
+ return result;
+}
+
+WSLCCompatDeletedImageInformation Convert(const WSLCDeletedImageInformation& Image)
+{
+ WSLCCompatDeletedImageInformation result{};
+ CopyString(result.Image, Image.Image);
+ result.Type = Convert(Image.Type);
+ return result;
+}
+
+WSLCCompatVolumeInformation Convert(const WSLCVolumeInformation& Volume)
+{
+ WSLCCompatVolumeInformation result{};
+ CopyString(result.Name, Volume.Name);
+ CopyString(result.Driver, Volume.Driver);
+ return result;
+}
+
+//
+// Composite struct conversions.
+//
+
+ContainerOptionsConversion::ContainerOptionsConversion(const WSLCCompatContainerOptions& Options)
+{
+ m_value.Image = Options.Image;
+ m_value.Name = Options.Name;
+ m_value.Entrypoint = Convert(Options.Entrypoint);
+ m_value.InitProcessOptions = Convert(Options.InitProcessOptions);
+
+ m_volumes = ConvertArray(Options.Volumes, Options.VolumesCount);
+ m_value.Volumes = m_volumes.empty() ? nullptr : m_volumes.data();
+ m_value.VolumesCount = Options.VolumesCount;
+
+ m_ports = ConvertArray(Options.Ports, Options.PortsCount);
+ m_value.Ports = m_ports.empty() ? nullptr : m_ports.data();
+ m_value.PortsCount = Options.PortsCount;
+
+ m_labels = ConvertArray(Options.Labels, Options.LabelsCount);
+ m_value.Labels = m_labels.empty() ? nullptr : m_labels.data();
+ m_value.LabelsCount = Options.LabelsCount;
+
+ m_value.Flags = Convert(Options.Flags);
+ m_value.StopSignal = Convert(Options.StopSignal);
+ m_value.HostName = Options.HostName;
+ m_value.DomainName = Options.DomainName;
+
+ m_value.DnsServers = Convert(Options.DnsServers);
+ m_value.DnsSearchDomains = Convert(Options.DnsSearchDomains);
+ m_value.DnsOptions = Convert(Options.DnsOptions);
+
+ m_value.ShmSize = Options.ShmSize;
+
+ // Container network (nested arrays whose elements have their own arrays).
+ m_value.ContainerNetwork.NetworkMode = Options.ContainerNetwork.NetworkMode;
+ const ULONG networksCount = Options.ContainerNetwork.NetworksCount;
+ THROW_HR_IF(E_INVALIDARG, networksCount > 0 && Options.ContainerNetwork.Networks == nullptr);
+
+ m_networks.reserve(networksCount);
+ m_networkSettings.reserve(networksCount);
+ for (ULONG index = 0; index < networksCount; index++)
+ {
+ const auto& network = Options.ContainerNetwork.Networks[index];
+ THROW_HR_IF(E_INVALIDARG, network.SettingsCount > 0 && network.Settings == nullptr);
+
+ m_networkSettings.push_back(ConvertArray(network.Settings, network.SettingsCount));
+
+ WSLCNetworkConnection connection{};
+ connection.NetworkName = network.NetworkName;
+ connection.Settings = m_networkSettings.back().empty() ? nullptr : m_networkSettings.back().data();
+ connection.SettingsCount = network.SettingsCount;
+ m_networks.push_back(connection);
+ }
+
+ m_value.ContainerNetwork.Networks = m_networks.empty() ? nullptr : m_networks.data();
+ m_value.ContainerNetwork.NetworksCount = networksCount;
+
+ m_tmpfs = ConvertArray(Options.Tmpfs, Options.TmpfsCount);
+ m_value.Tmpfs = m_tmpfs.empty() ? nullptr : m_tmpfs.data();
+ m_value.TmpfsCount = Options.TmpfsCount;
+
+ m_namedVolumes = ConvertArray(Options.NamedVolumes, Options.NamedVolumesCount);
+ m_value.NamedVolumes = m_namedVolumes.empty() ? nullptr : m_namedVolumes.data();
+ m_value.NamedVolumesCount = Options.NamedVolumesCount;
+
+ m_value.MemoryBytes = Options.MemoryBytes;
+ m_value.NanoCpus = Options.NanoCpus;
+
+ m_ulimits = ConvertArray(Options.Ulimits, Options.UlimitsCount);
+ m_value.Ulimits = m_ulimits.empty() ? nullptr : m_ulimits.data();
+ m_value.UlimitsCount = Options.UlimitsCount;
+}
+
+ListImagesOptionsConversion::ListImagesOptionsConversion(const WSLCCompatListImagesOptions& Options)
+{
+ m_value.Flags = static_cast(Convert(static_cast(Options.Flags)));
+
+ m_filters = ConvertArray(Options.Filters, Options.FiltersCount);
+ m_value.Filters = m_filters.empty() ? nullptr : m_filters.data();
+ m_value.FiltersCount = Options.FiltersCount;
+}
+
+VolumeOptionsConversion::VolumeOptionsConversion(const WSLCCompatVolumeOptions& Options)
+{
+ m_value.Name = Options.Name;
+ m_value.Driver = Options.Driver;
+
+ m_driverOpts = ConvertArray(Options.DriverOpts, Options.DriverOptsCount);
+ m_value.DriverOpts = m_driverOpts.empty() ? nullptr : m_driverOpts.data();
+ m_value.DriverOptsCount = Options.DriverOptsCount;
+
+ m_labels = ConvertArray(Options.Labels, Options.LabelsCount);
+ m_value.Labels = m_labels.empty() ? nullptr : m_labels.data();
+ m_value.LabelsCount = Options.LabelsCount;
+}
+
+SessionSettingsConversion::SessionSettingsConversion(const WSLCCompatSessionSettings& Settings)
+{
+ m_value.DisplayName = Settings.DisplayName;
+ m_value.StoragePath = Settings.StoragePath;
+ m_value.MaximumStorageSizeMb = Settings.MaximumStorageSizeMb;
+ m_value.CpuCount = Settings.CpuCount;
+ m_value.MemoryMb = Settings.MemoryMb;
+ m_value.BootTimeoutMs = Settings.BootTimeoutMs;
+ m_value.NetworkingMode = Convert(Settings.NetworkingMode);
+
+ m_terminationCallback = Convert(Settings.TerminationCallback);
+ m_value.TerminationCallback = m_terminationCallback.Get();
+
+ m_value.FeatureFlags = Convert(Settings.FeatureFlags);
+ m_value.DmesgOutput = Convert(Settings.DmesgOutput);
+ m_value.StorageFlags = Convert(Settings.StorageFlags);
+ m_value.RootVhdOverride = Settings.RootVhdOverride;
+ m_value.RootVhdTypeOverride = Settings.RootVhdTypeOverride;
+}
+
+//
+// Callback conversions.
+//
+
+Microsoft::WRL::ComPtr Convert(IWSLCCompatTerminationCallback* Callback)
+{
+ Microsoft::WRL::ComPtr result;
+ if (Callback != nullptr)
+ {
+ result = Microsoft::WRL::Make(Callback);
+ }
+
+ return result;
+}
+
+Microsoft::WRL::ComPtr Convert(IWSLCCompatCrashDumpCallback* Callback)
+{
+ Microsoft::WRL::ComPtr result;
+ if (Callback != nullptr)
+ {
+ result = Microsoft::WRL::Make(Callback);
+ }
+
+ return result;
+}
+
+Microsoft::WRL::ComPtr Convert(IWSLCCompatProgressCallback* Callback)
+{
+ Microsoft::WRL::ComPtr result;
+ if (Callback != nullptr)
+ {
+ result = Microsoft::WRL::Make(Callback);
+ }
+
+ return result;
+}
+
+Microsoft::WRL::ComPtr Convert(IWSLCCompatWarningCallback* Callback)
+{
+ Microsoft::WRL::ComPtr result;
+ if (Callback != nullptr)
+ {
+ result = Microsoft::WRL::Make(Callback);
+ }
+
+ return result;
+}
+
+} // namespace wsl::windows::common::apicompat
diff --git a/src/windows/common/APICompat.h b/src/windows/common/APICompat.h
new file mode 100644
index 0000000000..c3811652fa
--- /dev/null
+++ b/src/windows/common/APICompat.h
@@ -0,0 +1,184 @@
+/*++
+
+Copyright (c) Microsoft. All rights reserved.
+
+Module Name:
+
+ APICompat.h
+
+Abstract:
+
+ API compatibility layer between the wslc.idl and wslccompat.idl.
+
+--*/
+
+#pragma once
+
+#include
+#include
+#include "wslc.h"
+#include "WSLCCompat.h"
+
+namespace wsl::windows::common::apicompat {
+
+//
+// Enum conversions.
+//
+
+// Forward (WSLCCompat -> wslc.idl).
+WSLCFD Convert(WSLCCompatFD Fd);
+WSLCSignal Convert(WSLCCompatSignal Signal);
+WSLCProcessFlags Convert(WSLCCompatProcessFlags Flags);
+WSLCContainerFlags Convert(WSLCCompatContainerFlags Flags);
+WSLCContainerStartFlags Convert(WSLCCompatContainerStartFlags Flags);
+WSLCDeleteFlags Convert(WSLCCompatDeleteFlags Flags);
+WSLCNetworkingMode Convert(WSLCCompatNetworkingMode Mode);
+WSLCFeatureFlags Convert(WSLCCompatFeatureFlags Flags);
+WSLCSessionStorageFlags Convert(WSLCCompatSessionStorageFlags Flags);
+WSLCSessionFlags Convert(WSLCCompatSessionFlags Flags);
+WSLCListImagesFlags Convert(WSLCCompatListImagesFlags Flags);
+WSLCDeleteImageFlags Convert(WSLCCompatDeleteImageFlags Flags);
+WSLCHandleType Convert(WSLCCompatHandleType Type);
+
+// Reverse (wslc.idl -> WSLCCompat).
+WSLCCompatProcessState Convert(WSLCProcessState State);
+WSLCCompatContainerState Convert(WSLCContainerState State);
+WSLCCompatVirtualMachineTerminationReason Convert(WSLCVirtualMachineTerminationReason Reason);
+WSLCCompatHandleType Convert(WSLCHandleType Type);
+WSLCCompatDeletedImageType Convert(WSLCDeletedImageType Type);
+
+// Forward (WSLCCompat -> wslc.idl).
+WSLCVersion Convert(const WSLCCompatVersion& Version);
+WSLCHandle Convert(const WSLCCompatHandle& Handle);
+WSLCStringArray Convert(const WSLCCompatStringArray& Array);
+WSLCProcessOptions Convert(const WSLCCompatProcessOptions& Options);
+KeyValuePair Convert(const WSLCCompatKeyValuePair& Pair);
+WSLCVolume Convert(const WSLCCompatVolume& Volume);
+WSLCNamedVolume Convert(const WSLCCompatNamedVolume& Volume);
+WSLCPortMapping Convert(const WSLCCompatPortMapping& Port);
+WSLCTmpfsMount Convert(const WSLCCompatTmpfsMount& Mount);
+WSLCUlimit Convert(const WSLCCompatUlimit& Ulimit);
+WSLCDeleteImageOptions Convert(const WSLCCompatDeleteImageOptions& Options);
+WSLCTagImageOptions Convert(const WSLCCompatTagImageOptions& Options);
+
+// Reverse (wslc.idl -> WSLCCompat).
+WSLCCompatVersion Convert(const WSLCVersion& Version);
+WSLCCompatHandle Convert(const WSLCHandle& Handle);
+WSLCCompatImageInformation Convert(const WSLCImageInformation& Image);
+WSLCCompatDeletedImageInformation Convert(const WSLCDeletedImageInformation& Image);
+WSLCCompatVolumeInformation Convert(const WSLCVolumeInformation& Volume);
+
+//
+// Composite struct conversions.
+//
+
+class ContainerOptionsConversion
+{
+public:
+ NON_COPYABLE(ContainerOptionsConversion);
+ DEFAULT_MOVABLE(ContainerOptionsConversion);
+
+ explicit ContainerOptionsConversion(const WSLCCompatContainerOptions& Options);
+
+ const WSLCContainerOptions* Get() const noexcept
+ {
+ return &m_value;
+ }
+
+private:
+ WSLCContainerOptions m_value{};
+ std::vector m_volumes;
+ std::vector m_ports;
+ std::vector m_labels;
+ std::vector m_tmpfs;
+ std::vector m_namedVolumes;
+ std::vector m_ulimits;
+ std::vector m_networks;
+ std::vector> m_networkSettings;
+};
+
+class ListImagesOptionsConversion
+{
+public:
+ NON_COPYABLE(ListImagesOptionsConversion);
+ DEFAULT_MOVABLE(ListImagesOptionsConversion);
+
+ explicit ListImagesOptionsConversion(const WSLCCompatListImagesOptions& Options);
+
+ const WSLCListImagesOptions* Get() const noexcept
+ {
+ return &m_value;
+ }
+
+private:
+ WSLCListImagesOptions m_value{};
+ std::vector m_filters;
+};
+
+class VolumeOptionsConversion
+{
+public:
+ NON_COPYABLE(VolumeOptionsConversion);
+ DEFAULT_MOVABLE(VolumeOptionsConversion);
+
+ explicit VolumeOptionsConversion(const WSLCCompatVolumeOptions& Options);
+
+ const WSLCVolumeOptions* Get() const noexcept
+ {
+ return &m_value;
+ }
+
+private:
+ WSLCVolumeOptions m_value{};
+ std::vector m_driverOpts;
+ std::vector m_labels;
+};
+
+class SessionSettingsConversion
+{
+public:
+ NON_COPYABLE(SessionSettingsConversion);
+ DEFAULT_MOVABLE(SessionSettingsConversion);
+
+ explicit SessionSettingsConversion(const WSLCCompatSessionSettings& Settings);
+
+ const WSLCSessionSettings* Get() const noexcept
+ {
+ return &m_value;
+ }
+
+private:
+ WSLCSessionSettings m_value{};
+ Microsoft::WRL::ComPtr m_terminationCallback;
+};
+
+inline ContainerOptionsConversion Convert(const WSLCCompatContainerOptions& Options)
+{
+ return ContainerOptionsConversion(Options);
+}
+
+inline ListImagesOptionsConversion Convert(const WSLCCompatListImagesOptions& Options)
+{
+ return ListImagesOptionsConversion(Options);
+}
+
+inline VolumeOptionsConversion Convert(const WSLCCompatVolumeOptions& Options)
+{
+ return VolumeOptionsConversion(Options);
+}
+
+inline SessionSettingsConversion Convert(const WSLCCompatSessionSettings& Settings)
+{
+ return SessionSettingsConversion(Settings);
+}
+
+//
+// Callback conversions.
+//
+
+Microsoft::WRL::ComPtr Convert(IWSLCCompatTerminationCallback* Callback);
+Microsoft::WRL::ComPtr Convert(IWSLCCompatCrashDumpCallback* Callback);
+Microsoft::WRL::ComPtr Convert(IWSLCCompatProgressCallback* Callback);
+Microsoft::WRL::ComPtr Convert(IWSLCCompatWarningCallback* Callback);
+
+} // namespace wsl::windows::common::apicompat
diff --git a/src/windows/common/CMakeLists.txt b/src/windows/common/CMakeLists.txt
index fafd201352..e5a5ca5207 100644
--- a/src/windows/common/CMakeLists.txt
+++ b/src/windows/common/CMakeLists.txt
@@ -1,4 +1,5 @@
set(SOURCES
+ APICompat.cpp
ConsoleProgressBar.cpp
ConsoleProgressIndicator.cpp
ConsoleState.cpp
@@ -57,6 +58,7 @@ set(SOURCES
set(HEADERS
../../../generated/Localization.h
+ APICompat.h
../inc/docker_schema.h
../inc/wslc_schema.h
../inc/lxssbusclient.h
diff --git a/src/windows/service/exe/WSLCSessionManager.cpp b/src/windows/service/exe/WSLCSessionManager.cpp
index 339f3ce6ca..05a2569692 100644
--- a/src/windows/service/exe/WSLCSessionManager.cpp
+++ b/src/windows/service/exe/WSLCSessionManager.cpp
@@ -37,6 +37,7 @@ Module Name:
#include "helpers.hpp"
#include "wslutil.h"
#include "filesystem.hpp"
+#include "APICompat.h"
extern wsl::windows::service::PluginManager g_pluginManager;
@@ -47,6 +48,7 @@ using wsl::windows::service::wslc::WSLCPluginNotifier;
using wsl::windows::service::wslc::WSLCSessionManagerImpl;
using wsl::windows::service::wslc::WSLCVirtualMachineFactory;
namespace wslutil = wsl::windows::common::wslutil;
+namespace apicompat = wsl::windows::common::apicompat;
namespace settings = wsl::windows::wslc::settings;
namespace {
@@ -541,7 +543,7 @@ try
}
CATCH_RETURN();
-HRESULT WSLCSessionManager::IsClientVersionSupported(_In_ const WSLCVersion* ClientVersion, _Out_ BOOL* IsSupported)
+HRESULT WSLCSessionManager::IsClientVersionSupported(_In_ const WSLCCompatVersion* ClientVersion, _Out_ BOOL* IsSupported)
try
{
RETURN_HR_IF(E_POINTER, ClientVersion == nullptr || IsSupported == nullptr);
@@ -601,6 +603,45 @@ HRESULT WSLCSessionManager::OpenSessionByName(_In_ LPCWSTR DisplayName, _Out_ IW
return CallImpl(&WSLCSessionManagerImpl::OpenSessionByName, DisplayName, Session);
}
+HRESULT WSLCSessionManager::GetVersion(_Out_ WSLCCompatVersion* Version)
+try
+{
+ RETURN_HR_IF_NULL(E_POINTER, Version);
+
+ WSLCVersion version{};
+ RETURN_IF_FAILED(GetVersion(&version));
+
+ *Version = apicompat::Convert(version);
+ return S_OK;
+}
+CATCH_RETURN();
+
+HRESULT WSLCSessionManager::CreateSession(
+ const WSLCCompatSessionSettings* Settings, WSLCCompatSessionFlags Flags, IWSLCCompatWarningCallback* WarningCallback, IWSLCCompatSession** Session)
+try
+{
+ RETURN_HR_IF_NULL(E_POINTER, Session);
+ *Session = nullptr;
+
+ const auto warning = apicompat::Convert(WarningCallback);
+
+ Microsoft::WRL::ComPtr session;
+ if (Settings == nullptr)
+ {
+ RETURN_IF_FAILED(CreateSession(static_cast(nullptr), apicompat::Convert(Flags), warning.Get(), &session));
+ }
+ else
+ {
+ const auto settings = apicompat::Convert(*Settings);
+ RETURN_IF_FAILED(CreateSession(settings.Get(), apicompat::Convert(Flags), warning.Get(), &session));
+ }
+
+ RETURN_HR_IF_NULL(E_UNEXPECTED, session);
+
+ return session.CopyTo(Session);
+}
+CATCH_RETURN();
+
namespace wsl::windows::service::wslc {
WSLCSessionManagerImpl* WSLCSessionManagerImpl::Instance() noexcept
diff --git a/src/windows/service/exe/WSLCSessionManager.h b/src/windows/service/exe/WSLCSessionManager.h
index d48f52e430..f0735aa067 100644
--- a/src/windows/service/exe/WSLCSessionManager.h
+++ b/src/windows/service/exe/WSLCSessionManager.h
@@ -32,6 +32,7 @@ Module Name:
#pragma once
#include "wslc.h"
+#include "WSLCCompat.h"
#include "COMImplClass.h"
#include "wslutil.h"
#include
@@ -187,7 +188,7 @@ class WSLCSessionManagerImpl
} // namespace wsl::windows::service::wslc
class DECLSPEC_UUID("a9b7a1b9-0671-405c-95f1-e0612cb4ce8f") WSLCSessionManager
- : public Microsoft::WRL::RuntimeClass, IWSLCSessionManager, IFastRundown>,
+ : public Microsoft::WRL::RuntimeClass, IWSLCSessionManager, IWSLCCompatSessionManager, IFastRundown>,
public wsl::windows::service::wslc::COMImplClass
{
public:
@@ -197,11 +198,19 @@ class DECLSPEC_UUID("a9b7a1b9-0671-405c-95f1-e0612cb4ce8f") WSLCSessionManager
WSLCSessionManager(wsl::windows::service::wslc::WSLCSessionManagerImpl* Impl);
IFACEMETHOD(GetVersion)(_Out_ WSLCVersion* Version) override;
- IFACEMETHOD(IsClientVersionSupported)(_In_ const WSLCVersion* ClientVersion, _Out_ BOOL* IsSupported) override;
IFACEMETHOD(CreateSession)(
const WSLCSessionSettings* WslcSessionSettings, WSLCSessionFlags Flags, IWarningCallback* WarningCallback, IWSLCSession** WslcSession) override;
IFACEMETHOD(EnterSession)(_In_ LPCWSTR DisplayName, _In_ LPCWSTR StoragePath, IWarningCallback* WarningCallback, IWSLCSession** WslcSession) override;
IFACEMETHOD(ListSessions)(_Out_ WSLCSessionListEntry** Sessions, _Out_ ULONG* SessionsCount) override;
IFACEMETHOD(OpenSession)(_In_ ULONG Id, _Out_ IWSLCSession** Session) override;
IFACEMETHOD(OpenSessionByName)(_In_ LPCWSTR DisplayName, _Out_ IWSLCSession** Session) override;
+
+ // IWSLCCompatSessionManager.
+ IFACEMETHOD(GetVersion)(_Out_ WSLCCompatVersion* Version) override;
+ IFACEMETHOD(IsClientVersionSupported)(_In_ const WSLCCompatVersion* ClientVersion, _Out_ BOOL* IsSupported) override;
+ IFACEMETHOD(CreateSession)(
+ const WSLCCompatSessionSettings* Settings,
+ WSLCCompatSessionFlags Flags,
+ IWSLCCompatWarningCallback* WarningCallback,
+ IWSLCCompatSession** Session) override;
};
diff --git a/src/windows/service/inc/CMakeLists.txt b/src/windows/service/inc/CMakeLists.txt
index 59888c441f..6a552cf06d 100644
--- a/src/windows/service/inc/CMakeLists.txt
+++ b/src/windows/service/inc/CMakeLists.txt
@@ -1,3 +1,3 @@
-add_idl(wslserviceidl "wslservice.idl;wslc.idl" "windowsdefs.idl")
+add_idl(wslserviceidl "wslservice.idl;wslc.idl;WSLCCompat.idl" "windowsdefs.idl")
set_target_properties(wslserviceidl PROPERTIES FOLDER windows)
diff --git a/src/windows/service/inc/WSLCCompat.idl b/src/windows/service/inc/WSLCCompat.idl
new file mode 100644
index 0000000000..075b6c5855
--- /dev/null
+++ b/src/windows/service/inc/WSLCCompat.idl
@@ -0,0 +1,537 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ WSLCCompat.idl
+
+Abstract:
+
+ This file contains the WSLC SDK-facing COM object definitions.
+ Changes in this file must maintain backwards compatibility
+
+--*/
+
+import "unknwn.idl";
+import "wtypes.idl";
+
+cpp_quote("#ifdef __cplusplus")
+cpp_quote("class DECLSPEC_UUID(\"a9b7a1b9-0671-405c-95f1-e0612cb4ce8f\") WSLCCompatSessionManager;")
+cpp_quote("class DECLSPEC_UUID(\"9fcd2067-9fc6-4efa-9eb0-698169ebf7d3\") WSLCCompatSessionManagerFactory;")
+cpp_quote("#endif")
+
+#define WSLCCompat_MAX_IMAGE_NAME_LENGTH 255
+#define WSLCCompat_MAX_VOLUME_NAME_LENGTH 255
+#define WSLCCompat_MAX_VOLUME_DRIVER_LENGTH 255
+#define WSLCCompat_CONTAINER_ID_LENGTH 64
+#define WSLCCompat_MAX_BINDING_ADDRESS_LENGTH 45
+
+typedef
+struct _WSLCCompatVersion {
+ ULONG Major;
+ ULONG Minor;
+ ULONG Revision;
+} WSLCCompatVersion;
+
+typedef enum _WSLCCompatVirtualMachineTerminationReason
+{
+ WSLCCompatVirtualMachineTerminationReasonUnknown,
+ WSLCCompatVirtualMachineTerminationReasonShutdown,
+ WSLCCompatVirtualMachineTerminationReasonCrashed,
+} WSLCCompatVirtualMachineTerminationReason;
+
+typedef enum _WSLCCompatFD
+{
+ WSLCCompatFDStdin = 0,
+ WSLCCompatFDStdout = 1,
+ WSLCCompatFDStderr = 2,
+ WSLCCompatFDTty = 3,
+} WSLCCompatFD;
+
+typedef enum _WSLCCompatSignal
+{
+ WSLCCompatSignalNone = 0,
+ WSLCCompatSignalSIGHUP = 1,
+ WSLCCompatSignalSIGINT = 2,
+ WSLCCompatSignalSIGQUIT = 3,
+ WSLCCompatSignalSIGILL = 4,
+ WSLCCompatSignalSIGTRAP = 5,
+ WSLCCompatSignalSIGABRT = 6,
+ WSLCCompatSignalSIGIOT = 6, // SIGABRT and SIGIOT are equivalent.
+ WSLCCompatSignalSIGBUS = 7,
+ WSLCCompatSignalSIGFPE = 8,
+ WSLCCompatSignalSIGKILL = 9,
+ WSLCCompatSignalSIGUSR1 = 10,
+ WSLCCompatSignalSIGSEGV = 11,
+ WSLCCompatSignalSIGUSR2 = 12,
+ WSLCCompatSignalSIGPIPE = 13,
+ WSLCCompatSignalSIGALRM = 14,
+ WSLCCompatSignalSIGTERM = 15,
+ WSLCCompatSignalSIGTKFLT = 16,
+ WSLCCompatSignalSIGCHLD = 17,
+ WSLCCompatSignalSIGCONT = 18,
+ WSLCCompatSignalSIGSTOP = 19,
+ WSLCCompatSignalSIGTSTP = 20,
+ WSLCCompatSignalSIGTTIN = 21,
+ WSLCCompatSignalSIGTTOU = 22,
+ WSLCCompatSignalSIGURG = 23,
+ WSLCCompatSignalSIGXCPU = 24,
+ WSLCCompatSignalSIGXFSZ = 25,
+ WSLCCompatSignalSIGVTALRM = 26,
+ WSLCCompatSignalSIGPROF = 27,
+ WSLCCompatSignalSIGWINCH = 28,
+ WSLCCompatSignalSIGIO = 29,
+ WSLCCompatSignalSIGPOLL = 29, // SIGIO and SIGPOLL are equivalent.
+ WSLCCompatSignalSIGPWR = 30,
+ WSLCCompatSignalSIGSYS = 31
+} WSLCCompatSignal;
+
+[
+ uuid(86A807EA-F2A1-4382-93E5-09FB5F2F4A31),
+ pointer_default(unique),
+ object
+]
+interface IWSLCCompatTerminationCallback : IUnknown
+{
+ HRESULT OnTermination(WSLCCompatVirtualMachineTerminationReason Reason, LPCWSTR Details);
+};
+
+[
+ uuid(EAA15E20-7FCC-485B-B798-ED4095DBACA5),
+ pointer_default(unique),
+ object
+]
+interface IWSLCCompatCrashDumpCallback : IUnknown
+{
+ HRESULT OnCrashDump(
+ [in, string] LPCWSTR DumpPath,
+ [in, unique, string] LPCSTR ProcessName,
+ [in] ULONGLONG Pid,
+ [in] ULONG Signal,
+ [in] ULONGLONG Timestamp);
+};
+
+[
+ uuid(06154F2A-ACA7-461E-94FC-92781BA1F6F6),
+ pointer_default(unique),
+ object
+]
+interface IWSLCCompatProgressCallback : IUnknown
+{
+ HRESULT OnProgress(LPCSTR Status, LPCSTR Id, ULONGLONG Current, ULONGLONG Total);
+};
+
+[
+ uuid(290C58A1-328C-4E90-B09B-0A9D32C40074),
+ pointer_default(unique),
+ object
+]
+interface IWSLCCompatWarningCallback : IUnknown
+{
+ HRESULT OnWarning([in, string] LPCWSTR Message);
+};
+
+typedef struct _WSLCCompatImageInformation
+{
+ char Image[WSLCCompat_MAX_IMAGE_NAME_LENGTH + 1];
+ char Hash[256];
+ char Digest[256];
+ LONGLONG Size; // Matches Docker's int64 image size
+ LONGLONG Created; // Unix timestamp
+ char ParentId[256];
+} WSLCCompatImageInformation;
+
+typedef enum _WSLCCompatListImagesFlags
+{
+ WSLCCompatListImagesFlagsNone = 0,
+ WSLCCompatListImagesFlagsAll = 1, // Show all images (default hides intermediate images)
+ WSLCCompatListImagesFlagsDigests = 2, // Include digest information
+} WSLCCompatListImagesFlags;
+
+cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(WSLCCompatListImagesFlags);")
+
+typedef struct _WSLCCompatKeyValuePair
+{
+ [string] LPCSTR Key;
+ [string] LPCSTR Value;
+} WSLCCompatKeyValuePair;
+
+typedef WSLCCompatKeyValuePair WSLCCompatLabel;
+typedef WSLCCompatKeyValuePair WSLCCompatDriverOption;
+typedef WSLCCompatKeyValuePair WSLCCompatFilter;
+
+typedef struct _WSLCCompatListImagesOptions
+{
+ DWORD Flags; // WSLCCompatListImagesFlags (can combine with bitwise OR)
+ [unique, size_is(FiltersCount)] const WSLCCompatFilter* Filters;
+ ULONG FiltersCount;
+} WSLCCompatListImagesOptions;
+
+typedef enum _WSLCCompatProcessFlags
+{
+ WSLCCompatProcessFlagsNone = 0,
+ WSLCCompatProcessFlagsStdin = 1,
+ WSLCCompatProcessFlagsTty = 2
+} WSLCCompatProcessFlags;
+
+cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(WSLCCompatProcessFlags);")
+
+typedef struct _WSLCCompatStringArray
+{
+ [unique, size_is(Count)] LPCSTR const* Values;
+ ULONG Count;
+} WSLCCompatStringArray;
+
+typedef struct _WSLCCompatProcessOptions
+{
+ [unique] LPCSTR CurrentDirectory;
+ [unique] LPCSTR User;
+ WSLCCompatStringArray CommandLine;
+ WSLCCompatStringArray Environment;
+ WSLCCompatProcessFlags Flags;
+} WSLCCompatProcessOptions;
+
+typedef struct _WSLCCompatNamedVolume
+{
+ LPCSTR Name;
+ LPCSTR ContainerPath;
+ BOOL ReadOnly;
+} WSLCCompatNamedVolume;
+
+typedef struct _WSLCCompatVolume
+{
+ LPCWSTR HostPath;
+ LPCSTR ContainerPath;
+ BOOL ReadOnly;
+} WSLCCompatVolume;
+
+typedef struct _WSLCCompatPortMapping
+{
+ USHORT HostPort;
+ USHORT ContainerPort;
+ int Family;
+ int Protocol;
+ char BindingAddress[WSLCCompat_MAX_BINDING_ADDRESS_LENGTH + 1];
+} WSLCCompatPortMapping;
+
+typedef struct _WSLCCompatTmpfsMount
+{
+ LPCSTR Destination;
+ [unique] LPCSTR Options;
+} WSLCCompatTmpfsMount;
+
+typedef struct _WSLCCompatUlimit
+{
+ [string] LPCSTR Name;
+ LONGLONG Soft;
+ LONGLONG Hard;
+} WSLCCompatUlimit;
+
+typedef struct _WSLCCompatNetworkConnection
+{
+ [string] LPCSTR NetworkName;
+ [unique, size_is(SettingsCount)] const WSLCCompatKeyValuePair* Settings;
+ ULONG SettingsCount;
+} WSLCCompatNetworkConnection;
+
+typedef struct _WSLCCompatContainerNetwork
+{
+ [unique, string] LPCSTR NetworkMode;
+
+ [unique, size_is(NetworksCount)] const WSLCCompatNetworkConnection* Networks;
+ ULONG NetworksCount;
+} WSLCCompatContainerNetwork;
+
+typedef enum _WSLCCompatContainerFlags
+{
+ WSLCCompatContainerFlagsNone = 0,
+ WSLCCompatContainerFlagsRm = 1, // Delete the container when it exits.
+ WSLCCompatContainerFlagsGpu = 2, // Enable GPU access.
+ WSLCCompatContainerFlagsInit = 4, // Run the container under an init process.
+ WSLCCompatContainerFlagsPublishAll = 8, // Publish all exposed ports.
+} WSLCCompatContainerFlags;
+
+cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(WSLCCompatContainerFlags);")
+
+typedef enum _WSLCCompatContainerStartFlags
+{
+ WSLCCompatContainerStartFlagsNone = 0,
+ WSLCCompatContainerStartFlagsAttach = 1, // Attach stdio handles on start.
+} WSLCCompatContainerStartFlags;
+
+cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(WSLCCompatContainerStartFlags);")
+
+typedef struct _WSLCCompatContainerOptions
+{
+ LPCSTR Image;
+ [unique] LPCSTR Name;
+ WSLCCompatStringArray Entrypoint;
+ WSLCCompatProcessOptions InitProcessOptions;
+ [unique, size_is(VolumesCount)] WSLCCompatVolume* Volumes;
+ ULONG VolumesCount;
+ [unique, size_is(PortsCount)] WSLCCompatPortMapping* Ports;
+ ULONG PortsCount;
+ [unique, size_is(LabelsCount)] const WSLCCompatLabel* Labels;
+ ULONG LabelsCount;
+ WSLCCompatContainerFlags Flags;
+ WSLCCompatSignal StopSignal;
+ [unique] LPCSTR HostName;
+ [unique] LPCSTR DomainName;
+
+ WSLCCompatStringArray DnsServers;
+ WSLCCompatStringArray DnsSearchDomains;
+ WSLCCompatStringArray DnsOptions;
+
+ LONGLONG ShmSize;
+ WSLCCompatContainerNetwork ContainerNetwork;
+ [unique, size_is(TmpfsCount)] const WSLCCompatTmpfsMount* Tmpfs;
+ ULONG TmpfsCount;
+
+ [unique, size_is(NamedVolumesCount)] WSLCCompatNamedVolume* NamedVolumes;
+ ULONG NamedVolumesCount;
+
+ LONGLONG MemoryBytes;
+ LONGLONG NanoCpus;
+ [unique, size_is(UlimitsCount)] const WSLCCompatUlimit* Ulimits;
+ ULONG UlimitsCount;
+} WSLCCompatContainerOptions;
+
+typedef enum _WSLCCompatContainerState
+{
+ WSLCCompatContainerStateInvalid = 0,
+ WSLCCompatContainerStateCreated = 1,
+ WSLCCompatContainerStateRunning = 2,
+ WSLCCompatContainerStateExited = 3,
+ WSLCCompatContainerStateDeleted = 4,
+} WSLCCompatContainerState;
+
+typedef char WSLCCompatContainerId[WSLCCompat_CONTAINER_ID_LENGTH + 1];
+
+typedef [system_handle(sh_file)] HANDLE WSLCCompatFileHandle;
+typedef [system_handle(sh_pipe)] HANDLE WSLCCompatPipeHandle;
+typedef [system_handle(sh_socket)] HANDLE WSLCCompatSocketHandle;
+
+typedef enum _WSLCCompatHandleType
+{
+ WSLCCompatHandleTypeUnknown = 0,
+ WSLCCompatHandleTypeFile = 1,
+ WSLCCompatHandleTypePipe = 2,
+ WSLCCompatHandleTypeSocket = 3
+} WSLCCompatHandleType;
+
+typedef struct _WSLCCompatHandle
+{
+ WSLCCompatHandleType Type;
+
+ [switch_type(WSLCCompatHandleType), switch_is(Type)]
+ union
+ {
+ [case(WSLCCompatHandleTypeFile)]
+ WSLCCompatFileHandle File;
+ [case(WSLCCompatHandleTypePipe)]
+ WSLCCompatPipeHandle Pipe;
+ [case(WSLCCompatHandleTypeSocket)]
+ WSLCCompatSocketHandle Socket;
+ [default];
+ } Handle;
+} WSLCCompatHandle;
+
+typedef enum _WSLCCompatProcessState
+{
+ WSLCCompatProcessStateUnknown = 0,
+ WSLCCompatProcessStateRunning = 1,
+ WSLCCompatProcessStateExited = 2,
+ WSLCCompatProcessStateSignalled = 3
+} WSLCCompatProcessState;
+
+[
+ uuid(AC69DD0D-6616-4C4F-91F2-C39D6034EA82),
+ pointer_default(unique),
+ object
+]
+interface IWSLCCompatProcess : IUnknown
+{
+ HRESULT Signal([in] int Signal);
+ HRESULT GetExitEvent([out, system_handle(sh_event)] HANDLE* EventHandle);
+ HRESULT GetStdHandle([in] WSLCCompatFD Fd, [out] WSLCCompatHandle* Handle);
+ HRESULT GetPid([out] int* Pid);
+ HRESULT GetState([out] WSLCCompatProcessState* State, [out] int* Code);
+}
+
+typedef enum _WSLCCompatNetworkingMode
+{
+ WSLCCompatNetworkingModeNone,
+ WSLCCompatNetworkingModeNAT,
+ WSLCCompatNetworkingModeVirtioProxy
+} WSLCCompatNetworkingMode;
+
+typedef enum _WSLCCompatFeatureFlags
+{
+ WSLCCompatFeatureFlagsNone = 0,
+ WSLCCompatFeatureFlagsDnsTunneling = 1,
+ WSLCCompatFeatureFlagsEarlyBootDmesg = 2,
+ WSLCCompatFeatureFlagsGPU = 4,
+ WSLCCompatFeatureFlagsVirtioFs = 8,
+ WSLCCompatFeatureFlagsDebug = 16,
+} WSLCCompatFeatureFlags;
+
+cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(WSLCCompatFeatureFlags);")
+
+typedef enum _WSLCCompatSessionStorageFlags
+{
+ WSLCCompatSessionStorageFlagsNone = 0,
+ WSLCCompatSessionStorageFlagsNoCreate = 1, // Open an existing storage path, but don't create a new one.
+} WSLCCompatSessionStorageFlags;
+
+cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(WSLCCompatSessionStorageFlags);")
+
+typedef struct _WSLCCompatSessionSettings {
+ LPCWSTR DisplayName;
+ LPCWSTR StoragePath;
+ ULONGLONG MaximumStorageSizeMb;
+ ULONG CpuCount;
+ ULONG MemoryMb;
+ ULONG BootTimeoutMs;
+ WSLCCompatNetworkingMode NetworkingMode;
+ [unique] IWSLCCompatTerminationCallback* TerminationCallback;
+ WSLCCompatFeatureFlags FeatureFlags;
+ WSLCCompatHandle DmesgOutput;
+ WSLCCompatSessionStorageFlags StorageFlags;
+
+ // Below options are used for debugging purposes only.
+ [unique] LPCWSTR RootVhdOverride;
+ [unique] LPCSTR RootVhdTypeOverride;
+} WSLCCompatSessionSettings;
+
+typedef enum _WSLCCompatDeleteFlags
+{
+ WSLCCompatDeleteFlagsNone = 0,
+ WSLCCompatDeleteFlagsForce = 1,
+ WSLCCompatDeleteFlagsDeleteVolumes = 2,
+} WSLCCompatDeleteFlags;
+
+cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(WSLCCompatDeleteFlags);")
+
+[
+ uuid(8C3C91FA-D550-41B9-AD9D-23DCBF96F549),
+ pointer_default(unique),
+ object
+]
+interface IWSLCCompatContainer : IUnknown
+{
+ HRESULT Stop([in] WSLCCompatSignal Signal, [in] LONG TimeoutSeconds);
+ HRESULT Start([in] WSLCCompatContainerStartFlags Flags);
+ HRESULT Delete([in] WSLCCompatDeleteFlags Flags);
+ HRESULT GetState([out] WSLCCompatContainerState* State);
+ HRESULT GetInitProcess([out] IWSLCCompatProcess** Process);
+ HRESULT Exec([in, ref] const WSLCCompatProcessOptions* Options, [out] IWSLCCompatProcess** Process);
+ HRESULT Inspect([out] LPSTR* Output);
+ HRESULT GetId([out, string] WSLCCompatContainerId Id);
+}
+
+typedef enum _WSLCCompatDeletedImageType
+{
+ WSLCCompatDeletedImageTypeDeleted = 0,
+ WSLCCompatDeletedImageTypeUntagged = 1
+} WSLCCompatDeletedImageType;
+
+typedef struct _WSLCCompatDeletedImageInformation
+{
+ char Image[WSLCCompat_MAX_IMAGE_NAME_LENGTH + 1];
+ WSLCCompatDeletedImageType Type;
+} WSLCCompatDeletedImageInformation;
+
+typedef enum _WSLCCompatDeleteImageFlags
+{
+ WSLCCompatDeleteImageFlagsNone = 0,
+ WSLCCompatDeleteImageFlagsForce = 1,
+ WSLCCompatDeleteImageFlagsNoPrune = 2,
+} WSLCCompatDeleteImageFlags;
+
+cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(WSLCCompatDeleteImageFlags);")
+
+typedef struct _WSLCCompatDeleteImageOptions
+{
+ LPCSTR Image; // Image can be ID or Repo:Tag.
+ DWORD Flags; // WSLCCompatDeleteImageFlags
+} WSLCCompatDeleteImageOptions;
+
+typedef struct _WSLCCompatTagImageOptions
+{
+ LPCSTR Image; // Source image name or ID.
+ LPCSTR Repo; // Target repository name.
+ LPCSTR Tag; // Target tag name.
+} WSLCCompatTagImageOptions;
+
+typedef struct _WSLCCompatVolumeOptions
+{
+ [unique] LPCSTR Name;
+ [unique] LPCSTR Driver;
+ [unique, size_is(DriverOptsCount)] const WSLCCompatDriverOption* DriverOpts;
+ ULONG DriverOptsCount;
+ [unique, size_is(LabelsCount)] const WSLCCompatLabel* Labels;
+ ULONG LabelsCount;
+} WSLCCompatVolumeOptions;
+
+typedef char WSLCCompatVolumeName[WSLCCompat_MAX_VOLUME_NAME_LENGTH + 1];
+
+typedef struct _WSLCCompatVolumeInformation
+{
+ WSLCCompatVolumeName Name;
+ char Driver[WSLCCompat_MAX_VOLUME_DRIVER_LENGTH + 1];
+} WSLCCompatVolumeInformation;
+
+[
+ uuid(DD7B2EF9-AA01-4F21-8A3A-29D394CBB579),
+ pointer_default(unique),
+ object
+]
+interface IWSLCCompatSession : IUnknown
+{
+ // Image management.
+ HRESULT PullImage([in] LPCSTR Image, [in, unique] LPCSTR RegistryAuthenticationInformation, [in, unique] IWSLCCompatProgressCallback* ProgressCallback, [in, unique] IWSLCCompatWarningCallback* WarningCallback);
+ HRESULT LoadImage([in] WSLCCompatHandle ImageHandle, [in, unique] IWSLCCompatProgressCallback* ProgressCallback, [in] ULONGLONG ContentLength, [in, unique] IWSLCCompatWarningCallback* WarningCallback);
+ HRESULT ImportImage([in] WSLCCompatHandle ImageHandle, [in] LPCSTR ImageName, [in, unique] IWSLCCompatProgressCallback* ProgressCallback, [in] ULONGLONG ContentLength, [in, unique] IWSLCCompatWarningCallback* WarningCallback);
+ HRESULT ListImages([in, unique] const WSLCCompatListImagesOptions* Options, [out, size_is(, *Count)] WSLCCompatImageInformation** Images, [out] ULONG* Count);
+ HRESULT DeleteImage([in] const WSLCCompatDeleteImageOptions* Options, [out, size_is(, *Count)] WSLCCompatDeletedImageInformation** DeletedImages, [out] ULONG* Count);
+ HRESULT TagImage([in] const WSLCCompatTagImageOptions* Options);
+
+ // Container management.
+ HRESULT CreateContainer([in] const WSLCCompatContainerOptions* Options, [in, unique] IWSLCCompatWarningCallback* WarningCallback, [out] IWSLCCompatContainer** Container);
+
+ // Terminate the VM and containers.
+ HRESULT Terminate();
+
+ // Volume management.
+ HRESULT CreateVolume([in] const WSLCCompatVolumeOptions* Options, [out] WSLCCompatVolumeInformation* VolumeInfo);
+ HRESULT DeleteVolume([in] LPCSTR Name);
+
+ HRESULT Authenticate([in] LPCSTR ServerAddress, [in] LPCSTR Username, [in] LPCSTR Password, [out] LPSTR* IdentityToken);
+ HRESULT PushImage([in] LPCSTR Image, [in] LPCSTR RegistryAuthenticationInformation, [in, unique] IWSLCCompatProgressCallback* ProgressCallback, [in, unique] IWSLCCompatWarningCallback* WarningCallback);
+
+ HRESULT RegisterCrashDumpCallback([in] IWSLCCompatCrashDumpCallback* Callback, [out] IUnknown** Subscription);
+}
+
+typedef enum _WSLCCompatSessionFlags
+{
+ WSLCCompatSessionFlagsNone = 0,
+ WSLCCompatSessionFlagsPersistent = 1, // Session remains active after its COM reference is released.
+ WSLCCompatSessionFlagsOpenExisting = 2, // Open an existing session if the name is in use.
+} WSLCCompatSessionFlags;
+
+cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(WSLCCompatSessionFlags);")
+
+[
+ uuid(279F2047-DA35-45A3-B671-AFD2302D5D16),
+ pointer_default(unique),
+ object
+]
+interface IWSLCCompatSessionManager : IUnknown
+{
+ HRESULT GetVersion([out] WSLCCompatVersion* Version);
+ HRESULT IsClientVersionSupported([in] const WSLCCompatVersion* ClientVersion, [out] BOOL* IsSupported);
+
+ // Session management.
+ HRESULT CreateSession([in, unique] const WSLCCompatSessionSettings* Settings, WSLCCompatSessionFlags Flags, [in, unique] IWSLCCompatWarningCallback* WarningCallback, [out] IWSLCCompatSession** Session);
+}
diff --git a/src/windows/service/inc/wslc.idl b/src/windows/service/inc/wslc.idl
index 04ff531cc1..ba3073372a 100644
--- a/src/windows/service/inc/wslc.idl
+++ b/src/windows/service/inc/wslc.idl
@@ -9,6 +9,8 @@ Module Name:
Abstract:
This file contains the WSLC-related COM object definitions.
+ // N.B. ABI breaking changes in this file are OK, since both client & server always ship together.
+ // The WSLC SDK must not use this file, and instead use WSLCCompat.idl
--*/
@@ -17,7 +19,7 @@ import "wtypes.idl";
cpp_quote("#ifdef __cplusplus")
cpp_quote("class DECLSPEC_UUID(\"a9b7a1b9-0671-405c-95f1-e0612cb4ce8f\") WSLCSessionManager;")
-cpp_quote("class DECLSPEC_UUID(\"9FCD2067-9FC6-4EFA-9EB0-698169EBF7D3\") WSLCSessionFactory;")
+cpp_quote("class DECLSPEC_UUID(\"9fcd2067-9fc6-4efa-9eb0-698169ebf7d3\") WSLCSessionFactory;")
cpp_quote("#endif")
#define WSLC_MAX_CONTAINER_NAME_LENGTH 255
@@ -919,8 +921,6 @@ cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(WSLCSessionFlags);")
interface IWSLCSessionManager : IUnknown
{
HRESULT GetVersion([out] WSLCVersion* Version);
- HRESULT IsClientVersionSupported([in] const WSLCVersion* ClientVersion, [out] BOOL* IsSupported);
-
// Session management.
HRESULT CreateSession([in, unique] const WSLCSessionSettings* Settings, WSLCSessionFlags Flags, [in, unique] IWarningCallback* WarningCallback, [out] IWSLCSession** Session);
HRESULT EnterSession([in, ref] LPCWSTR DisplayName, [in, ref] LPCWSTR StoragePath, [in, unique] IWarningCallback* WarningCallback, [out] IWSLCSession** Session);
diff --git a/src/windows/service/stub/CMakeLists.txt b/src/windows/service/stub/CMakeLists.txt
index c0308d6dcd..d6dfc408ef 100644
--- a/src/windows/service/stub/CMakeLists.txt
+++ b/src/windows/service/stub/CMakeLists.txt
@@ -3,6 +3,8 @@ set(SOURCES
${CMAKE_CURRENT_BINARY_DIR}/../inc/${TARGET_PLATFORM}/${CMAKE_BUILD_TYPE}/wslservice_p_${TARGET_PLATFORM}.c
${CMAKE_CURRENT_BINARY_DIR}/../inc/${TARGET_PLATFORM}/${CMAKE_BUILD_TYPE}/wslc_i_${TARGET_PLATFORM}.c
${CMAKE_CURRENT_BINARY_DIR}/../inc/${TARGET_PLATFORM}/${CMAKE_BUILD_TYPE}/wslc_p_${TARGET_PLATFORM}.c
+ ${CMAKE_CURRENT_BINARY_DIR}/../inc/${TARGET_PLATFORM}/${CMAKE_BUILD_TYPE}/WSLCCompat_i_${TARGET_PLATFORM}.c
+ ${CMAKE_CURRENT_BINARY_DIR}/../inc/${TARGET_PLATFORM}/${CMAKE_BUILD_TYPE}/WSLCCompat_p_${TARGET_PLATFORM}.c
${CMAKE_CURRENT_BINARY_DIR}/../inc/${TARGET_PLATFORM}/${CMAKE_BUILD_TYPE}/dlldata_${TARGET_PLATFORM}.c
${CMAKE_CURRENT_LIST_DIR}/WslServiceProxyStub.def
${CMAKE_CURRENT_LIST_DIR}/WslServiceProxyStub.rc)
diff --git a/src/windows/wslcsession/WSLCContainer.cpp b/src/windows/wslcsession/WSLCContainer.cpp
index 03baa3e3ab..91814e6ef1 100644
--- a/src/windows/wslcsession/WSLCContainer.cpp
+++ b/src/windows/wslcsession/WSLCContainer.cpp
@@ -23,6 +23,9 @@ Module Name:
#include "WSLCProcess.h"
#include "WSLCProcessIO.h"
#include "WSLCVolumes.h"
+#include "APICompat.h"
+
+namespace apicompat = wsl::windows::common::apicompat;
using wsl::windows::common::COMServiceExecutionContext;
using wsl::windows::common::docker_schema::ErrorResponse;
@@ -2457,5 +2460,64 @@ CATCH_RETURN();
HRESULT WSLCContainer::InterfaceSupportsErrorInfo(REFIID riid)
{
- return riid == __uuidof(IWSLCContainer) ? S_OK : S_FALSE;
+ return riid == __uuidof(IWSLCContainer) || riid == __uuidof(IWSLCCompatContainer) ? S_OK : S_FALSE;
+}
+
+HRESULT WSLCContainer::Stop(WSLCCompatSignal Signal, LONG TimeoutSeconds)
+{
+ return Stop(apicompat::Convert(Signal), TimeoutSeconds);
+}
+
+HRESULT WSLCContainer::Start(WSLCCompatContainerStartFlags Flags)
+{
+ return Start(apicompat::Convert(Flags), nullptr, nullptr);
+}
+
+HRESULT WSLCContainer::Delete(WSLCCompatDeleteFlags Flags)
+{
+ return Delete(apicompat::Convert(Flags));
+}
+
+HRESULT WSLCContainer::GetState(WSLCCompatContainerState* State)
+try
+{
+ RETURN_HR_IF_NULL(E_POINTER, State);
+
+ WSLCContainerState state{};
+ RETURN_IF_FAILED(GetState(&state));
+
+ *State = apicompat::Convert(state);
+ return S_OK;
+}
+CATCH_RETURN();
+
+HRESULT WSLCContainer::GetInitProcess(IWSLCCompatProcess** Process)
+try
+{
+ RETURN_HR_IF_NULL(E_POINTER, Process);
+ *Process = nullptr;
+
+ Microsoft::WRL::ComPtr process;
+ RETURN_IF_FAILED(GetInitProcess(&process));
+ RETURN_HR_IF_NULL(E_UNEXPECTED, process);
+
+ return process.CopyTo(Process);
}
+CATCH_RETURN();
+
+HRESULT WSLCContainer::Exec(const WSLCCompatProcessOptions* Options, IWSLCCompatProcess** Process)
+try
+{
+ RETURN_HR_IF_NULL(E_POINTER, Options);
+ RETURN_HR_IF_NULL(E_POINTER, Process);
+ *Process = nullptr;
+
+ const auto options = apicompat::Convert(*Options);
+
+ Microsoft::WRL::ComPtr process;
+ RETURN_IF_FAILED(Exec(&options, nullptr, &process));
+ RETURN_HR_IF_NULL(E_UNEXPECTED, process);
+
+ return process.CopyTo(Process);
+}
+CATCH_RETURN();
diff --git a/src/windows/wslcsession/WSLCContainer.h b/src/windows/wslcsession/WSLCContainer.h
index c3ad79288c..59516685c1 100644
--- a/src/windows/wslcsession/WSLCContainer.h
+++ b/src/windows/wslcsession/WSLCContainer.h
@@ -22,6 +22,7 @@ Module Name:
#include "IORelay.h"
#include "COMImplClass.h"
#include "wslc_schema.h"
+#include "WSLCCompat.h"
#include "WSLCContainerMetadata.h"
#include "WSLCNetworkMetadata.h"
#include "WSLCVhdVolume.h"
@@ -217,7 +218,7 @@ class WSLCContainerImpl
};
class DECLSPEC_UUID("B1F1C4E3-C225-4CAE-AD8A-34C004DE1AE4") WSLCContainer
- : public Microsoft::WRL::RuntimeClass, IWSLCContainer, IFastRundown, ISupportErrorInfo>,
+ : public Microsoft::WRL::RuntimeClass, IWSLCContainer, IWSLCCompatContainer, IFastRundown, ISupportErrorInfo>,
public COMImplClass
{
@@ -242,6 +243,14 @@ class DECLSPEC_UUID("B1F1C4E3-C225-4CAE-AD8A-34C004DE1AE4") WSLCContainer
IFACEMETHOD(ConnectToNetwork)(_In_ const WSLCNetworkConnectionOptions* Options) override;
IFACEMETHOD(DisconnectFromNetwork)(_In_ LPCSTR NetworkName) override;
+ // IWSLCCompatContainer.
+ IFACEMETHOD(Stop)(_In_ WSLCCompatSignal Signal, _In_ LONG TimeoutSeconds) override;
+ IFACEMETHOD(Start)(_In_ WSLCCompatContainerStartFlags Flags) override;
+ IFACEMETHOD(Delete)(_In_ WSLCCompatDeleteFlags Flags) override;
+ IFACEMETHOD(GetState)(_Out_ WSLCCompatContainerState* State) override;
+ IFACEMETHOD(GetInitProcess)(_Out_ IWSLCCompatProcess** Process) override;
+ IFACEMETHOD(Exec)(_In_ const WSLCCompatProcessOptions* Options, _Out_ IWSLCCompatProcess** Process) override;
+
IFACEMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
// Cache read-only properties so they remain accessible after the impl is disconnected.
diff --git a/src/windows/wslcsession/WSLCProcess.cpp b/src/windows/wslcsession/WSLCProcess.cpp
index 04decf9ec6..268a3caf1b 100644
--- a/src/windows/wslcsession/WSLCProcess.cpp
+++ b/src/windows/wslcsession/WSLCProcess.cpp
@@ -15,8 +15,10 @@ Module Name:
#include "precomp.h"
#include "WSLCProcess.h"
#include "WSLCVirtualMachine.h"
+#include "APICompat.h"
using wsl::windows::service::wslc::WSLCProcess;
+namespace apicompat = wsl::windows::common::apicompat;
WSLCProcess::WSLCProcess(std::shared_ptr Control, std::unique_ptr&& Io, WSLCProcessFlags Flags) :
m_control(std::move(Control)), m_io(std::move(Io)), m_flags(Flags)
@@ -122,4 +124,30 @@ try
m_control->ResizeTty(Rows, Columns);
return S_OK;
}
+CATCH_RETURN();
+
+HRESULT WSLCProcess::GetStdHandle(WSLCCompatFD Fd, WSLCCompatHandle* Handle)
+try
+{
+ RETURN_HR_IF_NULL(E_POINTER, Handle);
+
+ WSLCHandle handle{};
+ RETURN_IF_FAILED(GetStdHandle(apicompat::Convert(Fd), &handle));
+
+ *Handle = apicompat::Convert(handle);
+ return S_OK;
+}
+CATCH_RETURN();
+
+HRESULT WSLCProcess::GetState(WSLCCompatProcessState* State, int* Code)
+try
+{
+ RETURN_HR_IF_NULL(E_POINTER, State);
+
+ WSLCProcessState state{};
+ RETURN_IF_FAILED(GetState(&state, Code));
+
+ *State = apicompat::Convert(state);
+ return S_OK;
+}
CATCH_RETURN();
\ No newline at end of file
diff --git a/src/windows/wslcsession/WSLCProcess.h b/src/windows/wslcsession/WSLCProcess.h
index cce5543d91..da981ff52c 100644
--- a/src/windows/wslcsession/WSLCProcess.h
+++ b/src/windows/wslcsession/WSLCProcess.h
@@ -14,6 +14,7 @@ Module Name:
#pragma once
#include "wslc.h"
+#include "WSLCCompat.h"
#include "WSLCProcessControl.h"
#include "WSLCProcessIO.h"
@@ -22,7 +23,7 @@ namespace wsl::windows::service::wslc {
class WSLCVirtualMachine;
class DECLSPEC_UUID("AFBEA6D6-D8A4-4F81-8FED-F947EB74B33B") WSLCProcess
- : public Microsoft::WRL::RuntimeClass, IWSLCProcess, IFastRundown>
+ : public Microsoft::WRL::RuntimeClass, IWSLCProcess, IWSLCCompatProcess, IFastRundown>
{
public:
WSLCProcess(std::shared_ptr Control, std::unique_ptr&& Io, WSLCProcessFlags Flags);
@@ -37,6 +38,10 @@ class DECLSPEC_UUID("AFBEA6D6-D8A4-4F81-8FED-F947EB74B33B") WSLCProcess
IFACEMETHOD(GetState)(_Out_ WSLCProcessState* State, _Out_ int* Code) override;
IFACEMETHOD(ResizeTty)(_In_ ULONG Rows, _In_ ULONG Columns) override;
+ // IWSLCCompatProcess - converts the WSLCCompat types to the wslc.idl types and forwards to the methods above.
+ IFACEMETHOD(GetStdHandle)(_In_ WSLCCompatFD Fd, _Out_ WSLCCompatHandle* Handle) override;
+ IFACEMETHOD(GetState)(_Out_ WSLCCompatProcessState* State, _Out_ int* Code) override;
+
wil::unique_handle GetStdHandle(int Index);
HANDLE GetExitEvent();
int GetPid() const;
diff --git a/src/windows/wslcsession/WSLCSession.cpp b/src/windows/wslcsession/WSLCSession.cpp
index 2be375fe99..c31dbd49d1 100644
--- a/src/windows/wslcsession/WSLCSession.cpp
+++ b/src/windows/wslcsession/WSLCSession.cpp
@@ -21,6 +21,7 @@ Module Name:
#include "ServiceProcessLauncher.h"
#include "WslCoreFilesystem.h"
#include "wslpolicies.h"
+#include "APICompat.h"
using namespace wsl::windows::common;
using io::MultiHandleWait;
@@ -2830,7 +2831,172 @@ CATCH_RETURN();
HRESULT WSLCSession::InterfaceSupportsErrorInfo(REFIID riid)
{
- return riid == __uuidof(IWSLCSession) ? S_OK : S_FALSE;
+ return riid == __uuidof(IWSLCSession) || riid == __uuidof(IWSLCCompatSession) ? S_OK : S_FALSE;
+}
+
+HRESULT WSLCSession::PullImage(LPCSTR Image, LPCSTR RegistryAuthenticationInformation, IWSLCCompatProgressCallback* ProgressCallback, IWSLCCompatWarningCallback* WarningCallback)
+{
+ const auto progress = apicompat::Convert(ProgressCallback);
+ const auto warning = apicompat::Convert(WarningCallback);
+
+ return PullImage(Image, RegistryAuthenticationInformation, progress.Get(), warning.Get());
+}
+
+HRESULT WSLCSession::LoadImage(WSLCCompatHandle ImageHandle, IWSLCCompatProgressCallback* ProgressCallback, ULONGLONG ContentLength, IWSLCCompatWarningCallback* WarningCallback)
+{
+ const auto handle = apicompat::Convert(ImageHandle);
+ const auto progress = apicompat::Convert(ProgressCallback);
+ const auto warning = apicompat::Convert(WarningCallback);
+
+ return LoadImage(handle, progress.Get(), ContentLength, warning.Get());
+}
+
+HRESULT WSLCSession::ImportImage(
+ WSLCCompatHandle ImageHandle, LPCSTR ImageName, IWSLCCompatProgressCallback* ProgressCallback, ULONGLONG ContentLength, IWSLCCompatWarningCallback* WarningCallback)
+{
+ const auto handle = apicompat::Convert(ImageHandle);
+ const auto progress = apicompat::Convert(ProgressCallback);
+ const auto warning = apicompat::Convert(WarningCallback);
+
+ return ImportImage(handle, ImageName, progress.Get(), ContentLength, warning.Get());
+}
+
+HRESULT WSLCSession::ListImages(const WSLCCompatListImagesOptions* Options, WSLCCompatImageInformation** Images, ULONG* Count)
+try
+{
+ RETURN_HR_IF_NULL(E_POINTER, Images);
+ RETURN_HR_IF_NULL(E_POINTER, Count);
+
+ *Images = nullptr;
+ *Count = 0;
+
+ wil::unique_cotaskmem_array_ptr imagesImpl;
+
+ ULONG count = 0;
+ if (Options == nullptr)
+ {
+ RETURN_IF_FAILED(ListImages(static_cast(nullptr), &imagesImpl, &count));
+ }
+ else
+ {
+ const auto options = apicompat::Convert(*Options);
+ RETURN_IF_FAILED(ListImages(options.Get(), &imagesImpl, &count));
+ }
+
+ if (count > 0)
+ {
+ auto converted = wil::make_unique_cotaskmem_nothrow(count);
+ RETURN_IF_NULL_ALLOC(converted);
+
+ for (ULONG index = 0; index < count; index++)
+ {
+ converted[index] = apicompat::Convert(imagesImpl[index]);
+ }
+
+ *Images = converted.release();
+ }
+
+ *Count = count;
+ return S_OK;
+}
+CATCH_RETURN();
+
+HRESULT WSLCSession::DeleteImage(const WSLCCompatDeleteImageOptions* Options, WSLCCompatDeletedImageInformation** DeletedImages, ULONG* Count)
+try
+{
+ RETURN_HR_IF_NULL(E_POINTER, Options);
+ RETURN_HR_IF_NULL(E_POINTER, DeletedImages);
+ RETURN_HR_IF_NULL(E_POINTER, Count);
+
+ *DeletedImages = nullptr;
+ *Count = 0;
+
+ const auto options = apicompat::Convert(*Options);
+
+ wil::unique_cotaskmem_array_ptr imagesImpl;
+
+ ULONG count = 0;
+ RETURN_IF_FAILED(DeleteImage(&options, &imagesImpl, &count));
+
+ if (count > 0)
+ {
+ auto converted = wil::make_unique_cotaskmem_nothrow(count);
+ RETURN_IF_NULL_ALLOC(converted);
+
+ for (ULONG index = 0; index < count; index++)
+ {
+ converted[index] = apicompat::Convert(imagesImpl[index]);
+ }
+
+ *DeletedImages = converted.release();
+ }
+
+ *Count = count;
+ return S_OK;
+}
+CATCH_RETURN();
+
+HRESULT WSLCSession::TagImage(const WSLCCompatTagImageOptions* Options)
+try
+{
+ RETURN_HR_IF_NULL(E_POINTER, Options);
+
+ const auto options = apicompat::Convert(*Options);
+ return TagImage(&options);
+}
+CATCH_RETURN();
+
+HRESULT WSLCSession::PushImage(LPCSTR Image, LPCSTR RegistryAuthenticationInformation, IWSLCCompatProgressCallback* ProgressCallback, IWSLCCompatWarningCallback* WarningCallback)
+{
+ const auto progress = apicompat::Convert(ProgressCallback);
+ const auto warning = apicompat::Convert(WarningCallback);
+
+ return PushImage(Image, RegistryAuthenticationInformation, progress.Get(), warning.Get());
+}
+
+HRESULT WSLCSession::CreateContainer(const WSLCCompatContainerOptions* Options, IWSLCCompatWarningCallback* WarningCallback, IWSLCCompatContainer** Container)
+try
+{
+ RETURN_HR_IF_NULL(E_POINTER, Options);
+ RETURN_HR_IF_NULL(E_POINTER, Container);
+ *Container = nullptr;
+
+ const auto warning = apicompat::Convert(WarningCallback);
+ const auto options = apicompat::Convert(*Options);
+
+ Microsoft::WRL::ComPtr container;
+ RETURN_IF_FAILED(CreateContainer(options.Get(), warning.Get(), &container));
+ RETURN_HR_IF_NULL(E_UNEXPECTED, container);
+
+ return container.CopyTo(Container);
+}
+CATCH_RETURN();
+
+HRESULT WSLCSession::CreateVolume(const WSLCCompatVolumeOptions* Options, WSLCCompatVolumeInformation* VolumeInfo)
+try
+{
+ RETURN_HR_IF_NULL(E_POINTER, Options);
+
+ const auto options = apicompat::Convert(*Options);
+
+ WSLCVolumeInformation info{};
+ WSLCVolumeInformation* internalInfo = (VolumeInfo != nullptr) ? &info : nullptr;
+ RETURN_IF_FAILED(CreateVolume(options.Get(), internalInfo));
+
+ if (VolumeInfo != nullptr)
+ {
+ *VolumeInfo = apicompat::Convert(info);
+ }
+
+ return S_OK;
+}
+CATCH_RETURN();
+
+HRESULT WSLCSession::RegisterCrashDumpCallback(IWSLCCompatCrashDumpCallback* Callback, IUnknown** Subscription)
+{
+ const auto callback = apicompat::Convert(Callback);
+
+ return RegisterCrashDumpCallback(callback.Get(), Subscription);
}
MultiHandleWait WSLCSession::CreateIOContext(HANDLE CancelHandle)
diff --git a/src/windows/wslcsession/WSLCSession.h b/src/windows/wslcsession/WSLCSession.h
index 5c7bee2227..e196eb61e7 100644
--- a/src/windows/wslcsession/WSLCSession.h
+++ b/src/windows/wslcsession/WSLCSession.h
@@ -15,6 +15,7 @@ Module Name:
#pragma once
#include "wslc.h"
+#include "WSLCCompat.h"
#include "WSLCVirtualMachine.h"
#include "WSLCContainer.h"
#include "WSLCVolumes.h"
@@ -73,7 +74,7 @@ class UserCOMCallback
// The SYSTEM service creates the VM and passes IWSLCVirtualMachine to Initialize().
//
class DECLSPEC_UUID("4877FEFC-4977-4929-A958-9F36AA1892A4") WSLCSession
- : public Microsoft::WRL::RuntimeClass, IWSLCSession, IFastRundown, ISupportErrorInfo>
+ : public Microsoft::WRL::RuntimeClass, IWSLCSession, IWSLCCompatSession, IFastRundown, ISupportErrorInfo>
{
public:
WSLCSession() = default;
@@ -193,6 +194,40 @@ class DECLSPEC_UUID("4877FEFC-4977-4929-A958-9F36AA1892A4") WSLCSession
IFACEMETHOD(MapVmPort)(_In_ int Family, _In_ unsigned short WindowsPort, _In_ unsigned short LinuxPort) override;
IFACEMETHOD(UnmapVmPort)(_In_ int Family, _In_ unsigned short WindowsPort, _In_ unsigned short LinuxPort) override;
+ // IWSLCCompatSession - converts the WSLCCompat types to the wslc.idl types and forwards to the methods above.
+ // Methods that have an identical signature in both interfaces (Terminate, DeleteVolume, Authenticate) are
+ // served by the single existing override and require no additional code here.
+ IFACEMETHOD(PullImage)(
+ _In_ LPCSTR Image,
+ _In_opt_ LPCSTR RegistryAuthenticationInformation,
+ _In_opt_ IWSLCCompatProgressCallback* ProgressCallback,
+ _In_opt_ IWSLCCompatWarningCallback* WarningCallback) override;
+ IFACEMETHOD(LoadImage)(
+ _In_ WSLCCompatHandle ImageHandle,
+ _In_opt_ IWSLCCompatProgressCallback* ProgressCallback,
+ _In_ ULONGLONG ContentLength,
+ _In_opt_ IWSLCCompatWarningCallback* WarningCallback) override;
+ IFACEMETHOD(ImportImage)(
+ _In_ WSLCCompatHandle ImageHandle,
+ _In_ LPCSTR ImageName,
+ _In_opt_ IWSLCCompatProgressCallback* ProgressCallback,
+ _In_ ULONGLONG ContentLength,
+ _In_opt_ IWSLCCompatWarningCallback* WarningCallback) override;
+ IFACEMETHOD(ListImages)(_In_opt_ const WSLCCompatListImagesOptions* Options, _Out_ WSLCCompatImageInformation** Images, _Out_ ULONG* Count) override;
+ IFACEMETHOD(DeleteImage)(_In_ const WSLCCompatDeleteImageOptions* Options, _Out_ WSLCCompatDeletedImageInformation** DeletedImages, _Out_ ULONG* Count) override;
+ IFACEMETHOD(TagImage)(_In_ const WSLCCompatTagImageOptions* Options) override;
+ IFACEMETHOD(PushImage)(
+ _In_ LPCSTR Image,
+ _In_ LPCSTR RegistryAuthenticationInformation,
+ _In_opt_ IWSLCCompatProgressCallback* ProgressCallback,
+ _In_opt_ IWSLCCompatWarningCallback* WarningCallback) override;
+ IFACEMETHOD(CreateContainer)(
+ _In_ const WSLCCompatContainerOptions* Options,
+ _In_opt_ IWSLCCompatWarningCallback* WarningCallback,
+ _Out_ IWSLCCompatContainer** Container) override;
+ IFACEMETHOD(CreateVolume)(_In_ const WSLCCompatVolumeOptions* Options, _Out_ WSLCCompatVolumeInformation* VolumeInfo) override;
+ IFACEMETHOD(RegisterCrashDumpCallback)(_In_ IWSLCCompatCrashDumpCallback* Callback, _Out_ IUnknown** Subscription) override;
+
common::io::MultiHandleWait CreateIOContext(HANDLE CancelHandle = nullptr);
UserHandle OpenUserHandle(WSLCHandle Handle);
diff --git a/test/windows/WSLCTests.cpp b/test/windows/WSLCTests.cpp
index 1bbe99f07d..0b45bec465 100644
--- a/test/windows/WSLCTests.cpp
+++ b/test/windows/WSLCTests.cpp
@@ -15,6 +15,7 @@ Module Name:
#include "precomp.h"
#include "Common.h"
#include "wslc.h"
+#include "wslccompat.h"
#include "WSLCProcessLauncher.h"
#include "WSLCContainerLauncher.h"
#include "WslCoreFilesystem.h"
@@ -235,23 +236,23 @@ class WSLCTests
WSLC_TEST_METHOD(IsClientVersionSupported)
{
- wil::com_ptr sessionManager;
+ wil::com_ptr sessionManager;
VERIFY_SUCCEEDED(CoCreateInstance(__uuidof(WSLCSessionManager), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&sessionManager)));
BOOL isSupported = FALSE;
// The current version should always be supported.
- const WSLCVersion currentVersion{WSL_PACKAGE_VERSION_MAJOR, WSL_PACKAGE_VERSION_MINOR, WSL_PACKAGE_VERSION_REVISION};
+ const WSLCCompatVersion currentVersion{WSL_PACKAGE_VERSION_MAJOR, WSL_PACKAGE_VERSION_MINOR, WSL_PACKAGE_VERSION_REVISION};
VERIFY_SUCCEEDED(sessionManager->IsClientVersionSupported(¤tVersion, &isSupported));
VERIFY_IS_TRUE(isSupported);
// A very old version should not be supported.
- const WSLCVersion oldVersion{1, 0, 0};
+ const WSLCCompatVersion oldVersion{1, 0, 0};
VERIFY_SUCCEEDED(sessionManager->IsClientVersionSupported(&oldVersion, &isSupported));
VERIFY_IS_FALSE(isSupported);
// A very high version should be supported.
- const WSLCVersion futureVersion{99, 0, 0};
+ const WSLCCompatVersion futureVersion{99, 0, 0};
VERIFY_SUCCEEDED(sessionManager->IsClientVersionSupported(&futureVersion, &isSupported));
VERIFY_IS_TRUE(isSupported);
}
diff --git a/test/windows/WslcSdkTests.cpp b/test/windows/WslcSdkTests.cpp
index 2588a13fe2..8a569db196 100644
--- a/test/windows/WslcSdkTests.cpp
+++ b/test/windows/WslcSdkTests.cpp
@@ -362,10 +362,10 @@ class WslcSdkTests
UniqueCrashDumpSubscription subscription;
VERIFY_SUCCEEDED(WslcRegisterSessionCrashDumpCallback(session.get(), callback, &promise, &subscription, nullptr));
- auto& comSession = *reinterpret_cast(session.get())->session;
+ auto comSession = reinterpret_cast(session.get())->session.query();
wsl::windows::common::WSLCProcessLauncher launcher{"/bin/sh", {"/bin/sh", "-c", "kill -SEGV $$"}};
- auto process = launcher.Launch(comSession);
+ auto process = launcher.Launch(*comSession);
auto result = process.WaitAndCaptureOutput();
VERIFY_ARE_EQUAL(result.Code, 128 + WSLCSignalSIGSEGV);
@@ -2239,8 +2239,8 @@ class WslcSdkTests
launcher.AddPort(port, port, AF_INET);
// Get the IWSLCSession COM object from the SDK session handle.
- auto& session = *reinterpret_cast(m_defaultSession)->session;
- auto container = launcher.Launch(session, WSLCContainerStartFlagsNone);
+ auto session = reinterpret_cast(m_defaultSession)->session.query();
+ auto container = launcher.Launch(*session, WSLCContainerStartFlagsNone);
auto registryAddress = std::format("127.0.0.1:{}", port);
diff --git a/test/windows/WslcSdkWinRTTests.cpp b/test/windows/WslcSdkWinRTTests.cpp
index 5336618df4..496ba25d6f 100644
--- a/test/windows/WslcSdkWinRTTests.cpp
+++ b/test/windows/WslcSdkWinRTTests.cpp
@@ -185,8 +185,9 @@ class WslcSdkWinRtTests
launcher.AddPort(port, port, AF_INET);
// Get the IWSLCSession COM object from the SDK session handle.
- auto& comSession = *reinterpret_cast(WSLCSDK::implementation::GetHandle(m_defaultSession))->session;
- auto container = launcher.Launch(comSession, WSLCContainerStartFlagsNone);
+ auto comSession =
+ reinterpret_cast(WSLCSDK::implementation::GetHandle(m_defaultSession))->session.query();
+ auto container = launcher.Launch(*comSession, WSLCContainerStartFlagsNone);
auto registryAddress = std::format("127.0.0.1:{}", port);