Skip to content
Merged
10 changes: 6 additions & 4 deletions src/windows/WslcSDK/WslcsdkPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ typedef struct WslcContainerProcessOptionsInternal

static_assert(
sizeof(WslcContainerProcessOptionsInternal) == WSLC_CONTAINER_PROCESS_OPTIONS_SIZE,
"WSLC_CONTAINER_PROCESS_OPTIONS_INTERNAL must be 72 bytes");
"WSLC_CONTAINER_PROCESS_OPTIONS_INTERNAL size mismatch");
static_assert(
__alignof(WslcContainerProcessOptionsInternal) == WSLC_CONTAINER_PROCESS_OPTIONS_ALIGNMENT,
"WSLC_CONTAINER_PROCESS_OPTIONS_INTERNAL must be 8-byte aligned");
"WSLC_CONTAINER_PROCESS_OPTIONS_INTERNAL alignment mismatch");

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

Expand All @@ -84,17 +84,19 @@ typedef struct WslcContainerOptionsInternal
uint32_t portsCount;
const WslcContainerVolume* volumes;
uint32_t volumesCount;
const WslcContainerNamedVolume* namedVolumes;
uint32_t namedVolumesCount;
const WslcContainerProcessOptionsInternal* initProcessOptions;
WSLCContainerNetworkType networking;
WslcContainerFlags containerFlags;

} WslcContainerOptionsInternal;

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

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

Expand Down
109 changes: 88 additions & 21 deletions src/windows/WslcSDK/wslcsdk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,6 @@ try
WSLCSessionSettings runtimeSettings{};
runtimeSettings.DisplayName = internalType->displayName;
runtimeSettings.StoragePath = internalType->storagePath;
// TODO: Is this the intended use for vhdRequirements.sizeInBytes?
runtimeSettings.MaximumStorageSizeMb = internalType->vhdRequirements.sizeInBytes / _1MB;
runtimeSettings.CpuCount = internalType->cpuCount;
runtimeSettings.MemoryMb = internalType->memoryMb;
Expand All @@ -432,16 +431,6 @@ try
runtimeSettings.FeatureFlags = ConvertFlags(internalType->featureFlags);
WI_SetFlag(runtimeSettings.FeatureFlags, WslcFeatureFlagsVirtioFs);

// TODO: Debug message output? No user control? Expects a handle value as a ULONG (to write debug info to?)
// runtimeSettings.DmesgOutput;

// TODO: VHD overrides; I'm not sure if we intend these to be provided.
// runtimeSettings.RootVhdOverride = internalType->vhdRequirements.path;
// TODO: I don't think that this VHD type override can be reused from the VHD requirements type
// Tracking the code suggests that this is the `filesystemtype` to the linux `mount` function.
// Not clear how to map dynamic and fixed to values like `ext4` and `tmpfs`.
// runtimeSettings.RootVhdTypeOverride = ConvertType(internalType->vhdRequirements.type);

if (SUCCEEDED(errorInfoWrapper.CaptureResult(sessionManager->CreateSession(&runtimeSettings, WSLCSessionFlagsNone, &result->session))))
{
wsl::windows::common::security::ConfigureForCOMImpersonation(result->session.get());
Expand Down Expand Up @@ -480,23 +469,54 @@ try
}
CATCH_RETURN();

STDAPI WslcCreateSessionVhd(_In_ WslcSession session, _In_ const WslcVhdRequirements* options, _Outptr_opt_result_z_ PWSTR* errorMessage)
STDAPI WslcCreateSessionVhdVolume(_In_ WslcSession session, _In_ const WslcVhdRequirements* options, _Outptr_opt_result_z_ PWSTR* errorMessage)
try
{
UNREFERENCED_PARAMETER(session);
UNREFERENCED_PARAMETER(options);
UNREFERENCED_PARAMETER(errorMessage);
return E_NOTIMPL;
ErrorInfoWrapper errorInfoWrapper{errorMessage};

auto internalType = CheckAndGetInternalType(session);
RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), internalType->session);
RETURN_HR_IF_NULL(E_POINTER, options);

RETURN_HR_IF_NULL(E_INVALIDARG, options->name);
RETURN_HR_IF(E_INVALIDARG, options->sizeInBytes == 0);
RETURN_HR_IF(E_NOTIMPL, options->type != WSLC_VHD_TYPE_DYNAMIC);

WSLCVolumeOptions volumeOptions{};
volumeOptions.Name = options->name;
// Only supported value currently
volumeOptions.Type = "vhd";

auto dynamicOptions = std::format(R"({{ "SizeBytes": "{}" }})", options->sizeInBytes);
volumeOptions.Options = dynamicOptions.c_str();

return errorInfoWrapper.CaptureResult(internalType->session->CreateVolume(&volumeOptions));
}
CATCH_RETURN();

STDAPI WslcDeleteSessionVhdVolume(_In_ WslcSession session, _In_z_ PCSTR name, _Outptr_opt_result_z_ PWSTR* errorMessage)
try
{
ErrorInfoWrapper errorInfoWrapper{errorMessage};

auto internalType = CheckAndGetInternalType(session);
RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), internalType->session);
RETURN_HR_IF_NULL(E_POINTER, name);

return errorInfoWrapper.CaptureResult(internalType->session->DeleteVolume(name));
}
CATCH_RETURN();

STDAPI WslcSetSessionSettingsVHD(_In_ WslcSessionSettings* sessionSettings, _In_ const WslcVhdRequirements* vhdRequirements)
STDAPI WslcSetSessionSettingsVhd(_In_ WslcSessionSettings* sessionSettings, _In_opt_ const WslcVhdRequirements* vhdRequirements)
try
{
auto internalType = CheckAndGetInternalType(sessionSettings);

if (vhdRequirements)
{
RETURN_HR_IF(E_INVALIDARG, vhdRequirements->sizeInBytes == 0);
RETURN_HR_IF(E_NOTIMPL, vhdRequirements->type != WSLC_VHD_TYPE_DYNAMIC);

internalType->vhdRequirements = *vhdRequirements;
}
else
Expand Down Expand Up @@ -621,6 +641,23 @@ try
containerOptions.VolumesCount = static_cast<ULONG>(internalContainerSettings->volumesCount);
}

std::unique_ptr<WSLCNamedVolume[]> convertedNamedVolumes;
if (internalContainerSettings->namedVolumes && internalContainerSettings->namedVolumesCount)
{
convertedNamedVolumes = std::make_unique<WSLCNamedVolume[]>(internalContainerSettings->namedVolumesCount);
for (uint32_t i = 0; i < internalContainerSettings->namedVolumesCount; ++i)
{
const WslcContainerNamedVolume& internalVolume = internalContainerSettings->namedVolumes[i];
WSLCNamedVolume& convertedVolume = convertedNamedVolumes[i];

convertedVolume.Name = internalVolume.name;
convertedVolume.ContainerPath = internalVolume.containerPath;
convertedVolume.ReadOnly = internalVolume.readOnly;
}
containerOptions.NamedVolumes = convertedNamedVolumes.get();
containerOptions.NamedVolumesCount = static_cast<ULONG>(internalContainerSettings->namedVolumesCount);
}

std::unique_ptr<WSLCPortMapping[]> convertedPorts;
if (internalContainerSettings->ports && internalContainerSettings->portsCount)
{
Expand Down Expand Up @@ -804,6 +841,27 @@ try
}
CATCH_RETURN();

STDAPI WslcSetContainerSettingsNamedVolumes(
_In_ WslcContainerSettings* containerSettings, _In_reads_opt_(namedVolumeCount) const WslcContainerNamedVolume* namedVolumes, _In_ uint32_t namedVolumeCount)
try
{
auto internalType = CheckAndGetInternalType(containerSettings);
RETURN_HR_IF(E_INVALIDARG, (namedVolumes == nullptr && namedVolumeCount != 0) || (namedVolumes != nullptr && namedVolumeCount == 0));

for (uint32_t i = 0; i < namedVolumeCount; ++i)
{
RETURN_HR_IF_NULL(E_INVALIDARG, namedVolumes[i].name);
RETURN_HR_IF_NULL(E_INVALIDARG, namedVolumes[i].containerPath);
EnsureAbsolutePath(namedVolumes[i].containerPath, true);
}

internalType->namedVolumes = namedVolumes;
internalType->namedVolumesCount = namedVolumeCount;

return S_OK;
}
CATCH_RETURN();

STDAPI WslcCreateContainerProcess(
_In_ WslcContainer container, _In_ WslcProcessSettings* newProcessSettings, _Out_ WslcProcess* newProcess, _Outptr_opt_result_z_ PWSTR* errorMessage)
try
Expand Down Expand Up @@ -851,12 +909,21 @@ try
}
CATCH_RETURN();

STDAPI WslcInspectContainer(_In_ WslcContainer container, _Outptr_result_z_ PCSTR* inspectData)
STDAPI WslcInspectContainer(_In_ WslcContainer container, _Outptr_result_z_ PSTR* inspectData)
try
{
UNREFERENCED_PARAMETER(container);
UNREFERENCED_PARAMETER(inspectData);
return E_NOTIMPL;
auto internalType = CheckAndGetInternalType(container);
RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), internalType->container);
RETURN_HR_IF_NULL(E_POINTER, inspectData);

*inspectData = nullptr;

wil::unique_cotaskmem_ansistring result;
RETURN_IF_FAILED(internalType->container->Inspect(&result));

*inspectData = result.release();

return S_OK;
}
CATCH_RETURN();

Expand Down
6 changes: 4 additions & 2 deletions src/windows/WslcSDK/wslcsdk.def
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ WslcSetSessionSettingsTerminationCallback
WslcSetSessionSettingsCpuCount
WslcSetSessionSettingsMemory
WslcSetSessionSettingsTimeout
WslcSetSessionSettingsVHD
WslcSetSessionSettingsVhd

WslcTerminateSession
WslcPullSessionImage
Expand All @@ -28,13 +28,15 @@ WslcLoadSessionImage
WslcLoadSessionImageFromFile
WslcDeleteSessionImage
WslcListSessionImages
WslcCreateSessionVhd
WslcCreateSessionVhdVolume
WslcDeleteSessionVhdVolume

WslcSetContainerSettingsDomainName
WslcSetContainerSettingsName
WslcSetContainerSettingsNetworkingMode
WslcSetContainerSettingsHostName
WslcSetContainerSettingsVolumes
WslcSetContainerSettingsNamedVolumes
WslcSetContainerSettingsInitProcess
WslcSetContainerSettingsFlags
WslcSetContainerSettingsPortMappings
Expand Down
30 changes: 21 additions & 9 deletions src/windows/WslcSDK/wslcsdk.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Module Name:
EXTERN_C_START

// Session values
#define WSLC_SESSION_OPTIONS_SIZE 72
#define WSLC_SESSION_OPTIONS_SIZE 80
#define WSLC_SESSION_OPTIONS_ALIGNMENT 8

typedef struct WslcSessionSettings
Expand All @@ -32,7 +32,7 @@ typedef struct WslcSessionSettings
DECLARE_HANDLE(WslcSession);

// Container values
#define WSLC_CONTAINER_OPTIONS_SIZE 80
#define WSLC_CONTAINER_OPTIONS_SIZE 96
#define WSLC_CONTAINER_OPTIONS_ALIGNMENT 8

typedef struct WslcContainerSettings
Expand Down Expand Up @@ -66,6 +66,8 @@ typedef enum WslcVhdType

typedef struct WslcVhdRequirements
{
// Ignored by WslcSetSessionSettingsVHD
_In_z_ PCSTR name;
_In_ uint64_t sizeInBytes; // Desired size (for create/expand)
_In_ WslcVhdType type;
} WslcVhdRequirements;
Expand Down Expand Up @@ -96,7 +98,7 @@ STDAPI WslcSetSessionSettingsCpuCount(_In_ WslcSessionSettings* sessionSettings,
STDAPI WslcSetSessionSettingsMemory(_In_ WslcSessionSettings* sessionSettings, _In_ uint32_t memoryMb);
STDAPI WslcSetSessionSettingsTimeout(_In_ WslcSessionSettings* sessionSettings, _In_ uint32_t timeoutMS);

STDAPI WslcSetSessionSettingsVHD(_In_ WslcSessionSettings* sessionSettings, _In_ const WslcVhdRequirements* vhdRequirements);
STDAPI WslcSetSessionSettingsVhd(_In_ WslcSessionSettings* sessionSettings, _In_opt_ const WslcVhdRequirements* vhdRequirements);

STDAPI WslcSetSessionSettingsFeatureFlags(_In_ WslcSessionSettings* sessionSettings, _In_ WslcSessionFeatureFlags flags);

Expand Down Expand Up @@ -132,6 +134,13 @@ typedef struct WslcContainerVolume
_In_ BOOL readOnly;
} WslcContainerVolume;

typedef struct WslcContainerNamedVolume
{
_In_z_ PCSTR name; // Name of the session volume (from WslcVhdRequirements.name)
_In_z_ PCSTR containerPath; // Absolute path inside the container
_In_ BOOL readOnly;
} WslcContainerNamedVolume;

typedef enum WslcContainerFlags
{
WSLC_CONTAINER_FLAG_NONE = 0x00000000,
Expand Down Expand Up @@ -180,6 +189,12 @@ STDAPI WslcSetContainerSettingsPortMappings(
STDAPI WslcSetContainerSettingsVolumes(
_In_ WslcContainerSettings* containerSettings, _In_reads_opt_(volumeCount) const WslcContainerVolume* volumes, _In_ uint32_t volumeCount);

// Add named session volumes (created via WslcCreateSessionVhdVolume) to the container settings
STDAPI WslcSetContainerSettingsNamedVolumes(
_In_ WslcContainerSettings* containerSettings,
_In_reads_opt_(namedVolumeCount) const WslcContainerNamedVolume* namedVolumes,
_In_ uint32_t namedVolumeCount);

STDAPI WslcCreateContainerProcess(
_In_ WslcContainer container, _In_ WslcProcessSettings* newProcessSettings, _Out_ WslcProcess* newProcess, _Outptr_opt_result_z_ PWSTR* errorMessage);

Expand Down Expand Up @@ -209,11 +224,7 @@ STDAPI WslcGetContainerInitProcess(_In_ WslcContainer container, _Out_ WslcProce
//
// Return Value:
// S_OK on success. Otherwise, an HRESULT error code indicating the failure.
//
// Notes:
// - The caller must pass a non-null pointer to a PCSTR variable.
// - The returned string is immutable and must not be modified by the caller.
STDAPI WslcInspectContainer(_In_ WslcContainer container, _Outptr_result_z_ PCSTR* inspectData);
STDAPI WslcInspectContainer(_In_ WslcContainer container, _Outptr_result_z_ PSTR* inspectData);

typedef enum WslcContainerState
{
Expand Down Expand Up @@ -470,7 +481,8 @@ STDAPI WslcListSessionImages(_In_ WslcSession session, _Outptr_result_buffer_(*c

// STORAGE

STDAPI WslcCreateSessionVhd(_In_ WslcSession session, _In_ const WslcVhdRequirements* options, _Outptr_opt_result_z_ PWSTR* errorMessage);
STDAPI WslcCreateSessionVhdVolume(_In_ WslcSession session, _In_ const WslcVhdRequirements* options, _Outptr_opt_result_z_ PWSTR* errorMessage);
STDAPI WslcDeleteSessionVhdVolume(_In_ WslcSession session, _In_z_ PCSTR name, _Outptr_opt_result_z_ PWSTR* errorMessage);

// INSTALL

Expand Down
Loading