Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
694443e
Add Clang requirement to vswhere usage
JohnMcPMS Feb 9, 2026
437a912
EOD checkin - session settings done, creation needs work
JohnMcPMS Feb 10, 2026
4216049
Primary session management implemented, needs TODOs looked at, needs …
JohnMcPMS Feb 10, 2026
cb3f04d
Merge from user/rechfr
JohnMcPMS Feb 10, 2026
5fca876
Post-merge fixes and implementations
JohnMcPMS Feb 10, 2026
243d358
Pull image almost impl
JohnMcPMS Feb 11, 2026
ca94797
WSLA error info wrapper and use
JohnMcPMS Feb 11, 2026
6ca21d3
Merge from user/richfr
JohnMcPMS Feb 11, 2026
d15c57e
Merge branch 'user/richfr' into sdk-session
JohnMcPMS Feb 11, 2026
694734e
Update for wsla feature merge
JohnMcPMS Feb 11, 2026
3181022
Implement for demo and fixes for same
JohnMcPMS Feb 12, 2026
37e9a89
Swap to always attach at container start
JohnMcPMS Feb 12, 2026
877bf26
Merge from user/richfr
JohnMcPMS Feb 12, 2026
4557def
Update for pull and implement container flags and delete
JohnMcPMS Feb 12, 2026
7f800ed
clang format
JohnMcPMS Feb 12, 2026
d33a7fa
implement getprocessexitevent
JohnMcPMS Feb 12, 2026
144d00c
Merge branch 'feature/wsl-for-apps' into sdk-session
JohnMcPMS Feb 12, 2026
bc357c7
cleanup
JohnMcPMS Feb 12, 2026
0bdb1df
clang format
JohnMcPMS Feb 12, 2026
f542a14
clang format
JohnMcPMS Feb 12, 2026
c65c4a2
Update src/windows/WslcSDK/ProgressCallback.h
JohnMcPMS Feb 12, 2026
61f1c5e
PR feedback
JohnMcPMS Feb 13, 2026
32d797b
clang format
JohnMcPMS Feb 13, 2026
713dff4
Revert cmake cp
JohnMcPMS Feb 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/windows/WslcSDK/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
set(SOURCES wslcsdk.cpp)
set(SOURCES
ProgressCallback.cpp
TerminationCallback.cpp
wslcsdk.cpp
WslcsdkPrivate.cpp
)
set(HEADERS
ProgressCallback.h
TerminationCallback.h
wslcsdk.h
WslcsdkPrivate.h
)
Expand Down
74 changes: 74 additions & 0 deletions src/windows/WslcSDK/ProgressCallback.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*++

Copyright (c) Microsoft. All rights reserved.

Module Name:

ProgressCallback.cpp

Abstract:

Implementation of a type that implements IProgressCallback.

--*/
#include "precomp.h"
#include "ProgressCallback.h"

using namespace std::string_view_literals;

namespace {
WslcImageProgressStatus ConvertStatus(LPCSTR Status)
{
#define WSLC_STRING_TO_STATUS_MAPPING(_status_, _string_) \
if (_string_##sv == Status) \
{ \
return _status_; \
}

// TODO: Mapping engine strings to status values seems fragile.
// WSLA is intentionally avoiding this kind of thing for localization of engine strings, which amounts to the same
// thing. If we keep this, a test should be added to explicitly validate that each status is returned properly.
WSLC_STRING_TO_STATUS_MAPPING(WSLC_IMAGE_PROGRESS_STATUS_PULLING, "Pulling fs layer");
WSLC_STRING_TO_STATUS_MAPPING(WSLC_IMAGE_PROGRESS_STATUS_WAITING, "Waiting");
WSLC_STRING_TO_STATUS_MAPPING(WSLC_IMAGE_PROGRESS_STATUS_DOWNLOADING, "Downloading");
WSLC_STRING_TO_STATUS_MAPPING(WSLC_IMAGE_PROGRESS_STATUS_VERIFYING, "Verifying Checksum");
WSLC_STRING_TO_STATUS_MAPPING(WSLC_IMAGE_PROGRESS_STATUS_EXTRACTING, "Extracting");
WSLC_STRING_TO_STATUS_MAPPING(WSLC_IMAGE_PROGRESS_STATUS_COMPLETE, "Pull complete");

return WSLC_IMAGE_PROGRESS_STATUS_UNKNOWN;
}
} // namespace

ProgressCallback::ProgressCallback(WslcContainerImageProgressCallback callback, PVOID context) :
m_callback(callback), m_context(context)
{
}

HRESULT STDMETHODCALLTYPE ProgressCallback::OnProgress(LPCSTR Status, LPCSTR Id, ULONGLONG Current, ULONGLONG Total)
{
if (m_callback)
{
WslcImageProgressMessage message{};

message.id = Id;
message.status = ConvertStatus(Status);
message.detail.current = Current;
message.detail.total = Total;

m_callback(&message, m_context);
}

return S_OK;
}

winrt::com_ptr<ProgressCallback> ProgressCallback::CreateIf(const WslcPullImageOptions* options)
{
if (options->progressCallback)
{
return winrt::make_self<ProgressCallback>(options->progressCallback, options->progressCallbackContext);
}
else
{
return nullptr;
}
}
32 changes: 32 additions & 0 deletions src/windows/WslcSDK/ProgressCallback.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*++

Copyright (c) Microsoft. All rights reserved.

Module Name:

ProgressCallback.h

Abstract:

Header for a type that implements IProgressCallback.

--*/
#pragma once
#include "wslaservice.h"
#include "wslcsdkprivate.h"
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Header include casing is inconsistent with the actual filename (WslcsdkPrivate.h). Using #include "wslcsdkprivate.h" can break builds on case-sensitive filesystems/tools. Please match the on-disk casing consistently across the project.

Suggested change
#include "wslcsdkprivate.h"
#include "WslcsdkPrivate.h"

Copilot uses AI. Check for mistakes.
#include <winrt/base.h>

struct ProgressCallback : public winrt::implements<ProgressCallback, IProgressCallback>
{
ProgressCallback(WslcContainerImageProgressCallback callback, PVOID context);

// IProgressCallback
HRESULT STDMETHODCALLTYPE OnProgress(LPCSTR Status, LPCSTR Id, ULONGLONG Current, ULONGLONG Total) override;

// Creates a ProgressCallback if the options provides a callback.
static winrt::com_ptr<ProgressCallback> CreateIf(const WslcPullImageOptions* options);

private:
WslcContainerImageProgressCallback m_callback = nullptr;
PVOID m_context = nullptr;
};
58 changes: 58 additions & 0 deletions src/windows/WslcSDK/TerminationCallback.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*++

Copyright (c) Microsoft. All rights reserved.

Module Name:

TerminationCallback.cpp

Abstract:

Implementation of a type that implements ITerminationCallback.

--*/
#include "precomp.h"
#include "TerminationCallback.h"

namespace {
WslcSessionTerminationReason ConvertReason(WSLAVirtualMachineTerminationReason Reason)
{
switch (Reason)
{
case WSLAVirtualMachineTerminationReasonShutdown:
return WSLC_SESSION_TERMINATION_REASON_SHUTDOWN;
case WSLAVirtualMachineTerminationReasonCrashed:
return WSLC_SESSION_TERMINATION_REASON_CRASHED;
default:
return WSLC_SESSION_TERMINATION_REASON_UNKNOWN;
}
}
} // namespace

TerminationCallback::TerminationCallback(WslcSessionTerminationCallback callback, PVOID context) :
m_callback(callback), m_context(context)
{
}

// TODO: Details from the runtime are dropped; should the SDK callback function be updated to include the reasons string?
HRESULT STDMETHODCALLTYPE TerminationCallback::OnTermination(WSLAVirtualMachineTerminationReason Reason, LPCWSTR)
{
if (m_callback)
{
m_callback(ConvertReason(Reason), m_context);
}

return S_OK;
}

winrt::com_ptr<TerminationCallback> TerminationCallback::CreateIf(const WSLC_SESSION_OPTIONS_INTERNAL* options)
{
if (options->terminationCallback)
{
return winrt::make_self<TerminationCallback>(options->terminationCallback, options->terminationCallbackContext);
}
else
{
return nullptr;
}
}
32 changes: 32 additions & 0 deletions src/windows/WslcSDK/TerminationCallback.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*++

Copyright (c) Microsoft. All rights reserved.

Module Name:

TerminationCallback.h

Abstract:

Header for a type that implements ITerminationCallback.

--*/
#pragma once
#include "wslaservice.h"
#include "wslcsdkprivate.h"
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Header include casing is inconsistent with the actual filename (WslcsdkPrivate.h). Using #include "wslcsdkprivate.h" can break builds on case-sensitive filesystems/tools. Please match the on-disk casing consistently across the project.

Suggested change
#include "wslcsdkprivate.h"
#include "WslcsdkPrivate.h"

Copilot uses AI. Check for mistakes.
#include <winrt/base.h>

struct TerminationCallback : public winrt::implements<TerminationCallback, ITerminationCallback>
{
TerminationCallback(WslcSessionTerminationCallback callback, PVOID context);

// ITerminationCallback
HRESULT STDMETHODCALLTYPE OnTermination(WSLAVirtualMachineTerminationReason Reason, LPCWSTR Details) override;

// Creates a TerminationCallback if the options provides a callback.
static winrt::com_ptr<TerminationCallback> CreateIf(const WSLC_SESSION_OPTIONS_INTERNAL* options);

private:
WslcSessionTerminationCallback m_callback = nullptr;
PVOID m_context = nullptr;
};
46 changes: 46 additions & 0 deletions src/windows/WslcSDK/WslcsdkPrivate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*++

Copyright (c) Microsoft. All rights reserved.

Module Name:

WslcSDKPrivate.cpp

Abstract:

This file contains the private WSL Container SDK implementations.

--*/
#include "precomp.h"

#include "wslcsdkprivate.h"
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Include casing is inconsistent with the actual filename (WslcsdkPrivate.h). Using #include "wslcsdkprivate.h" can break builds on case-sensitive filesystems/tools. Please match the on-disk casing consistently across the project.

Suggested change
#include "wslcsdkprivate.h"
#include "WslcsdkPrivate.h"

Copilot uses AI. Check for mistakes.

WSLC_SESSION_OPTIONS_INTERNAL* GetInternalType(WslcSessionSettings* settings)
{
return reinterpret_cast<WSLC_SESSION_OPTIONS_INTERNAL*>(settings);
}

WSLC_CONTAINER_PROCESS_OPTIONS_INTERNAL* GetInternalType(WslcProcessSettings* settings)
{
return reinterpret_cast<WSLC_CONTAINER_PROCESS_OPTIONS_INTERNAL*>(settings);
}

WSLC_CONTAINER_OPTIONS_INTERNAL* GetInternalType(WslcContainerSettings* settings)
{
return reinterpret_cast<WSLC_CONTAINER_OPTIONS_INTERNAL*>(settings);
}

WslcSessionImpl* GetInternalType(WslcSession handle)
{
return reinterpret_cast<WslcSessionImpl*>(handle);
}

WslcContainerImpl* GetInternalType(WslcContainer handle)
{
return reinterpret_cast<WslcContainerImpl*>(handle);
}

WslcProcessImpl* GetInternalType(WslcProcess handle)
{
return reinterpret_cast<WslcProcessImpl*>(handle);
}
40 changes: 36 additions & 4 deletions src/windows/WslcSDK/WslcsdkPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ typedef struct WSLC_SESSION_OPTIONS_INTERNAL
PCWSTR storagePath;

uint32_t cpuCount;
uint64_t memoryMb;
uint32_t memoryMb;
uint32_t timeoutMS;

WslcVhdRequirements vhdRequirements;
Expand All @@ -42,13 +42,17 @@ static_assert(
__alignof(WSLC_SESSION_OPTIONS_INTERNAL) == WSLC_SESSION_OPTIONS_ALIGNMENT,
"WSLC_SESSION_OPTIONS_INTERNAL alignment mismatch");

static_assert(std::is_trivial_v<WSLC_SESSION_OPTIONS_INTERNAL>, "WSLC_SESSION_OPTIONS_INTERNAL must be trivial");

WSLC_SESSION_OPTIONS_INTERNAL* GetInternalType(WslcSessionSettings* settings);

// PROCESS DEFINITIONS
typedef struct WSLC_CONTAINER_PROCESS_OPTIONS_INTERNAL
{
PCSTR executable; // path to executable inside container
PCSTR* commandLine;
PCSTR const* commandLine;
uint32_t commandLineCount;
PCSTR* environment;
PCSTR const* environment;
uint32_t environmentCount;
PCSTR currentDirectory;
} WSLC_CONTAINER_PROCESS_OPTIONS_INTERNAL;
Expand All @@ -60,6 +64,11 @@ static_assert(
__alignof(WSLC_CONTAINER_PROCESS_OPTIONS_INTERNAL) == WSLC_CONTAINER_PROCESS_OPTIONS_ALIGNMENT,
"WSLC_CONTAINER_PROCESS_OPTIONS_INTERNAL must be 8-byte aligned");

static_assert(
std::is_trivial_v<WSLC_CONTAINER_PROCESS_OPTIONS_INTERNAL>, "WSLC_CONTAINER_PROCESS_OPTIONS_INTERNAL must be trivial");

WSLC_CONTAINER_PROCESS_OPTIONS_INTERNAL* GetInternalType(WslcProcessSettings* settings);

// CONTAINER DEFINITIONS
typedef struct WSLC_CONTAINER_OPTIONS_INTERNAL
{
Expand All @@ -76,24 +85,47 @@ typedef struct WSLC_CONTAINER_OPTIONS_INTERNAL
WslcContainerFlags containerFlags;

} WSLC_CONTAINER_OPTIONS_INTERNAL;

static_assert(
sizeof(WSLC_CONTAINER_OPTIONS_INTERNAL) == WSLC_CONTAINER_OPTIONS_SIZE, "WSLC_CONTAINER_OPTIONS_INTERNAL must be 80 bytes");
static_assert(
__alignof(WSLC_CONTAINER_OPTIONS_INTERNAL) == WSLC_CONTAINER_OPTIONS_ALIGNMENT,
"WSLC_CONTAINER_OPTIONS_INTERNAL must be 8-byte aligned");

static_assert(std::is_trivial_v<WSLC_CONTAINER_OPTIONS_INTERNAL>, "WSLC_CONTAINER_OPTIONS_INTERNAL must be trivial");

WSLC_CONTAINER_OPTIONS_INTERNAL* GetInternalType(WslcContainerSettings* settings);

// Use to allocate the actual objects on the heap to keep it alive.
struct WslcSessionImpl
{
wil::com_ptr<IWSLASessionManager> sessionManager;
wil::com_ptr<IWSLASession> session;
wil::com_ptr<ITerminationCallback> terminationCallback;
};

WslcSessionImpl* GetInternalType(WslcSession handle);

struct WslcContainerImpl
{
wil::com_ptr<IWSLAContainer> container;
};

WslcContainerImpl* GetInternalType(WslcContainer handle);

struct WslcProcessImpl
{
wil::com_ptr<IWSLAProcess> process;
};

WslcProcessImpl* GetInternalType(WslcProcess handle);

// Converts to the internal type and returns an error on null input.
#define WSLC_GET_INTERNAL_TYPE(_input_) \
GetInternalType(_input_); \
RETURN_HR_IF_NULL(E_POINTER, _input_)

Comment on lines +122 to +126
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The WSLC_GET_INTERNAL_TYPE macro expands to multiple statements and includes an early-return (RETURN_HR_IF_NULL). This makes it fragile (e.g., it cannot be used as a normal expression argument) and obscures control flow. Consider replacing it with explicit RETURN_HR_IF_NULL + GetInternalType(...) statements at call sites, or reworking into a safer helper pattern (e.g., a small inline function that returns HRESULT and sets an out param).

Copilot uses AI. Check for mistakes.
// Converts to a unique_ptr of the internal type and returns an error on null input.
// Use for Release functions to clean up the implementation object on return.
#define WSLC_GET_INTERNAL_TYPE_FOR_RELEASE(_input_) \
std::unique_ptr<std::remove_pointer_t<decltype(GetInternalType(_input_))>>{GetInternalType(_input_)}; \
RETURN_HR_IF_NULL(E_POINTER, _input_)\
Comment on lines +127 to +131
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WSLC_GET_INTERNAL_TYPE_FOR_RELEASE has the same multi-statement / hidden-return fragility as WSLC_GET_INTERNAL_TYPE, and additionally it’s easy to accidentally create a temporary unique_ptr (deleting the handle immediately) when used as a standalone statement. Consider making the lifetime/ownership explicit in the Release functions instead of encoding it in a macro.

Copilot uses AI. Check for mistakes.
Loading
Loading