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