Skip to content

Merge the WSL Container SDK DLL project into the main feature branch#14172

Open
1wizkid wants to merge 3 commits intofeature/wsl-for-appsfrom
user/richfr
Open

Merge the WSL Container SDK DLL project into the main feature branch#14172
1wizkid wants to merge 3 commits intofeature/wsl-for-appsfrom
user/richfr

Conversation

@1wizkid
Copy link

@1wizkid 1wizkid commented Feb 6, 2026

this adds a new project src/windows/wslcsdk and the necessary .h and cpp files to build the WSLCSDK.DLL.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@benhillis benhillis changed the base branch from master to feature/wsl-for-apps February 6, 2026 21:51
@benhillis benhillis requested a review from a team as a code owner February 6, 2026 21:51
@benhillis
Copy link
Member

I've updated the target branch.

@benhillis benhillis requested review from Copilot and removed request for a team, Brian-Perkins and craigloewen-msft February 6, 2026 22:58
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 24 comments.

Comment on lines +15 to +17
#include <windows.h>
#include <stdint.h>
#include <winsock2.h>
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

Including <windows.h> before <winsock2.h> can cause Winsock header conflicts for consumers of this public SDK header (unless they happen to define _WINSOCKAPI_ first). Consider including <winsock2.h> before <windows.h> (or define _WINSOCKAPI_/use a lean include strategy) to make the header safe to include standalone.

Suggested change
#include <windows.h>
#include <stdint.h>
#include <winsock2.h>
#include <winsock2.h>
#include <windows.h>
#include <stdint.h>

Copilot uses AI. Check for mistakes.
Comment on lines +100 to +111
STDAPI WslcSessionSettingsVHD(_In_ WslcSessionSettings sessionSettings,
_In_ WSLC_VHD_REQUIREMENTS vhdRequirements);

STDAPI WslcSessionSettingsTimeout(_In_ WslcSessionSettings sessionSettings,
uint32_t timeoutMS);


STDAPI WslcSessionSettingsFlags(_In_ WslcSessionSettings sessionSettings,
_In_ WSLC_SESSION_FLAGS flags);

// Pass in Null for callback to clear the termination callback
STDAPI WslcSessionSettingsTerminateCallback(_In_ WslcSessionSettings sessionSettings,
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

The optional “settings” mutator APIs take the settings structs by value (e.g., WslcSessionSettingsTimeout(_In_ WslcSessionSettings sessionSettings, ...)). Since WslcSessionSettings/WslcContainerSettings/WslcProcessSettings are opaque byte blobs, passing by value means changes cannot propagate back to the caller, making these functions ineffective. These should take an _Inout_ pointer to the settings (and similarly for the container/process settings mutators).

Suggested change
STDAPI WslcSessionSettingsVHD(_In_ WslcSessionSettings sessionSettings,
_In_ WSLC_VHD_REQUIREMENTS vhdRequirements);
STDAPI WslcSessionSettingsTimeout(_In_ WslcSessionSettings sessionSettings,
uint32_t timeoutMS);
STDAPI WslcSessionSettingsFlags(_In_ WslcSessionSettings sessionSettings,
_In_ WSLC_SESSION_FLAGS flags);
// Pass in Null for callback to clear the termination callback
STDAPI WslcSessionSettingsTerminateCallback(_In_ WslcSessionSettings sessionSettings,
STDAPI WslcSessionSettingsVHD(_Inout_ WslcSessionSettings* sessionSettings,
_In_ WSLC_VHD_REQUIREMENTS vhdRequirements);
STDAPI WslcSessionSettingsTimeout(_Inout_ WslcSessionSettings* sessionSettings,
uint32_t timeoutMS);
STDAPI WslcSessionSettingsFlags(_Inout_ WslcSessionSettings* sessionSettings,
_In_ WSLC_SESSION_FLAGS flags);
// Pass in Null for callback to clear the termination callback
STDAPI WslcSessionSettingsTerminateCallback(_Inout_ WslcSessionSettings* sessionSettings,

Copilot uses AI. Check for mistakes.
STDAPI WslcSessionInitSettings(_In_ PCWSTR storagePath,
_In_ uint32_t cpuCount,
_In_ uint64_t memoryMb,
_In_ WslcSessionSettings* sessionSettings);
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

WslcSessionInitSettings writes to sessionSettings, but it is annotated as _In_. This should be an _Out_/_Inout_ annotation (and ideally a size-aware annotation) to match the function’s behavior and avoid incorrect static analysis.

Suggested change
_In_ WslcSessionSettings* sessionSettings);
_Out_ WslcSessionSettings* sessionSettings);

Copilot uses AI. Check for mistakes.
//PROCESS MANAGEMENT

STDAPI WslcProcessGetPid(_In_ WslcProcess process,
_Out_ const UINT32* pid);
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

WslcProcessGetPid declares the out parameter as const UINT32*, which prevents the function from writing the PID. This should be a non-const output pointer (e.g., UINT32*) to match the intent of an out parameter.

Suggested change
_Out_ const UINT32* pid);
_Out_ UINT32* pid);

Copilot uses AI. Check for mistakes.
Comment on lines +397 to +407
typedef struct WLSC_PULL_IMAGE_OPTIONS
{
_In_z_ PCSTR uri; // e.g. "my.registry.io/hello-world:latest" or just "hello-world:latest" which will default to docker
_In_opt_ WslcContainerImageProgressCallback progressCallback;
_In_opt_ PVOID progressCallbackContext;
_In_opt_ WSLC_REGISTRY_AUTHENTICATION_INFORMATION authInfo;
} WLSC_PULL_IMAGE_OPTIONS;


STDAPI WslcSessionImagePull(_In_ WslcSession session,
_In_ const WLSC_PULL_IMAGE_OPTIONS* options,
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

In WLSC_PULL_IMAGE_OPTIONS, the type name prefix is WLSC_... while the rest of the API uses WSLC_..., which looks inconsistent/typo-prone for a public SDK. Also authInfo is marked _In_opt_ but is a by-value struct (cannot be optional); consider making it a pointer or adding an explicit hasAuthInfo flag.

Suggested change
typedef struct WLSC_PULL_IMAGE_OPTIONS
{
_In_z_ PCSTR uri; // e.g. "my.registry.io/hello-world:latest" or just "hello-world:latest" which will default to docker
_In_opt_ WslcContainerImageProgressCallback progressCallback;
_In_opt_ PVOID progressCallbackContext;
_In_opt_ WSLC_REGISTRY_AUTHENTICATION_INFORMATION authInfo;
} WLSC_PULL_IMAGE_OPTIONS;
STDAPI WslcSessionImagePull(_In_ WslcSession session,
_In_ const WLSC_PULL_IMAGE_OPTIONS* options,
typedef struct WSLC_PULL_IMAGE_OPTIONS
{
_In_z_ PCSTR uri; // e.g. "my.registry.io/hello-world:latest" or just "hello-world:latest" which will default to docker
_In_opt_ WslcContainerImageProgressCallback progressCallback;
_In_opt_ PVOID progressCallbackContext;
_In_opt_ const WSLC_REGISTRY_AUTHENTICATION_INFORMATION* authInfo;
} WSLC_PULL_IMAGE_OPTIONS;
STDAPI WslcSessionImagePull(_In_ WslcSession session,
_In_ const WSLC_PULL_IMAGE_OPTIONS* options,

Copilot uses AI. Check for mistakes.
Comment on lines +136 to +137
// if you want to override the default binding address
_In_opt_ struct sockaddr_storage windowsAddress; // accepts ipv4/6
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

windowsAddress is declared as a by-value sockaddr_storage but annotated _In_opt_ and described as optional. A non-pointer field cannot be null/optional. Consider changing this to a pointer (with an explicit length/family) or add an explicit flag indicating whether the address is present, and update the SAL accordingly.

Suggested change
// if you want to override the default binding address
_In_opt_ struct sockaddr_storage windowsAddress; // accepts ipv4/6
// Optional override for the default binding address. If NULL, the default
// address will be used. The buffer must point to a valid sockaddr (IPv4 or
// IPv6) of length windowsAddressLength bytes.
_In_reads_bytes_opt_(windowsAddressLength) const struct sockaddr* windowsAddress;
_In_ INT windowsAddressLength;

Copilot uses AI. Check for mistakes.
// Pass in Null for stdIOCallback to clear the callback for the given handle
STDAPI WslcProcessSettingsIoCallback(_In_ WslcProcessSettings processSettings,
_In_ WSLC_PROCESS_IO_HANDLE ioHandle,
_In_ WslcStdIOCallback stdIOCallback);
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

WslcProcessSettingsIoCallback documents passing NULL to clear the callback, but the parameter is annotated _In_ (non-optional). Mark the callback parameter as optional and ensure the implementation handles a null callback consistently.

Suggested change
_In_ WslcStdIOCallback stdIOCallback);
_In_opt_ WslcStdIOCallback stdIOCallback);

Copilot uses AI. Check for mistakes.
Comment on lines +188 to +194
_In_ const WSLC_CONTAINER_PORT_MAPPING* portMappings);

// Add the container volume to the volumes array
STDAPI WslcContainerSettingsVolume(_In_ WslcContainerSettings containerSettings, _In_ const WSLC_CONTAINER_VOLUME* volumes);



Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

WslcContainerSettingsPortMapping/WslcContainerSettingsVolume accept a pointer to mappings/volumes but provide no count/length and no documented terminator convention. Since the internal options struct tracks portsCount/volumesCount, the public API needs a way to specify the number of entries (or clearly document a sentinel-terminated array) to avoid undefined reads.

Suggested change
_In_ const WSLC_CONTAINER_PORT_MAPPING* portMappings);
// Add the container volume to the volumes array
STDAPI WslcContainerSettingsVolume(_In_ WslcContainerSettings containerSettings, _In_ const WSLC_CONTAINER_VOLUME* volumes);
_In_reads_(portMappingsCount) const WSLC_CONTAINER_PORT_MAPPING* portMappings,
_In_ UINT32 portMappingsCount);
// Add the container volume to the volumes array
STDAPI WslcContainerSettingsVolume(_In_ WslcContainerSettings containerSettings,
_In_reads_(volumesCount) const WSLC_CONTAINER_VOLUME* volumes,
_In_ UINT32 volumesCount);

Copilot uses AI. Check for mistakes.
Comment on lines +60 to +65
STDAPI WslcSessionSettingsDisplayName(_In_ WslcSessionSettings sessionSettings,
_In_ PCWSTR displayName)
{
UNREFERENCED_PARAMETER(displayName);
UNREFERENCED_PARAMETER(sessionSettings);
return E_NOTIMPL;
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

WslcSessionSettingsDisplayName is exported in the .def file, but it isn’t declared in wslcsdk.h. Because of that, this definition will be emitted with C++ name mangling (no prior extern "C" declaration), and the .def export WslcSessionSettingsDisplayName will fail to link. Add the declaration under EXTERN_C_START in wslcsdk.h (or wrap this definition in EXTERN_C_START/END).

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +12
set(SOURCES wslcsdk.cpp)
set(HEADERS
wslcsdk.h
wslcsdkprivate.h
)

add_library(wslcsdk SHARED ${SOURCES} ${HEADERS} wslcsdk.def)
set_target_properties(wslcsdk PROPERTIES EXCLUDE_FROM_ALL FALSE)
add_dependencies(wslcsdk wslaserviceidl)
target_link_libraries(wslcsdk ${COMMON_LINK_LIBRARIES} legacy_stdio_definitions common)
target_precompile_headers(wslcsdk REUSE_FROM common)
set_target_properties(wslcsdk PROPERTIES FOLDER windows)
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

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

This file is named cmakelists.txt, but CMake only auto-loads CMakeLists.txt in an add_subdirectory() directory. As-is, CMake will fail to configure this target unless the file is renamed to CMakeLists.txt (matching exact casing).

Copilot uses AI. Check for mistakes.
Copy link
Collaborator

@OneBlue OneBlue left a comment

Choose a reason for hiding this comment

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

Thank you for doing this. Added a couple comments, most of the copilot comments seem to be accurate

UNREFERENCED_PARAMETER(session);
return E_NOTIMPL;
}
STDAPI WslcContainerSettingsNetworkingMode(_In_ WslcContainerSettings containerSettings,
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: I'd rename to WslcContainerSettingsSetNetworkingMode (same for below method) to follow the get / set naming

return E_NOTIMPL;
}
STDAPI WslcContainerSettingsHostName(_In_ WslcContainerSettings containerSettings,
_In_ const PCSTR hostName)
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: const is not needed here (already in PCSTR)`

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also I recommend using the long pointer version (LPCSTR) since that's what modern Windows APIs do



// SESSION DEFINITIONS
STDAPI WslcSessionInitSettings(_In_ PCWSTR storagePath,
Copy link
Collaborator

Choose a reason for hiding this comment

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

This method can't fail, since I recommend returning the sessions by copy to simplify things. This also remove the need for the "release" method for settings

UNREFERENCED_PARAMETER(containerSettings);
return E_NOTIMPL;
}
STDAPI WslcContainerSettingsRuntimeName(_In_ WslcContainerSettings containerSettings,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd just use WslcContainerSettingsSetName (runtime is implied)

return E_NOTIMPL;
}

STDAPI WslcContainerExecProcess(_In_ WslcContainer container,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I recommend just WslcContainerExec here

WSLA_VhdTypeFixed, // Fully allocated VHDX
} WSLC_VhdType;

typedef struct WSLC_VHD_REQUIREMENTS
Copy link
Collaborator

Choose a reason for hiding this comment

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

I recommend using the same casing for all enum and structures (WSLCVhdRequirements)

Same for below enums


typedef struct WSLC_CONTAINER_PORT_MAPPING
{
_In_ UINT16 windowsPort; // Port on Windows host
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's use uint16_t to match the rest of the API

typedef __callback VOID(CALLBACK WslcStdIOCallback)(_In_reads_bytes_(dataSize) const BYTE* data, _In_ UINT32 dataSize, _In_opt_ PVOID context);
typedef enum WSLC_PROCESS_IO_HANDLE
{
stdIn = 0,
Copy link
Collaborator

Choose a reason for hiding this comment

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

This will conflicts with predefined std handles. I recommend prefixing the enum values with the enum type name (for all enums)

//#include <wil/result.h> // error handling

// SESSION DEFINITIONS
typedef struct WSLC_SESSION_OPTIONS_INTERNAL
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's make this a C++ header (no need for typedef struct)

PVOID terminationCallbackContext;
} WSLC_SESSION_OPTIONS_INTERNAL;

typedef char WSLC_SESSION_OPTIONS_INTERNAL_SIZE_ASSERT[sizeof(WSLC_SESSION_OPTIONS_INTERNAL)];//size = 80
Copy link
Collaborator

Choose a reason for hiding this comment

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

I recommend static_assert instead of this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants