Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 0 additions & 12 deletions src/windows/WslcSDK/ProgressCallback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,3 @@ HRESULT STDMETHODCALLTYPE ProgressCallback::OnProgress(LPCSTR Status, LPCSTR Id,

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;
}
}
13 changes: 12 additions & 1 deletion src/windows/WslcSDK/ProgressCallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,18 @@ struct ProgressCallback : public winrt::implements<ProgressCallback, IProgressCa
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);
template <typename Options>
static winrt::com_ptr<ProgressCallback> CreateIf(const Options* options)
{
if (options->progressCallback)
{
return winrt::make_self<ProgressCallback>(options->progressCallback, options->progressCallbackContext);
}
else
{
return nullptr;
}
}

private:
WslcContainerImageProgressCallback m_callback = nullptr;
Expand Down
2 changes: 1 addition & 1 deletion src/windows/WslcSDK/WslcsdkPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ typedef struct WSLC_CONTAINER_OPTIONS_INTERNAL
const WslcContainerVolume* volumes;
uint32_t volumesCount;
const WSLC_CONTAINER_PROCESS_OPTIONS_INTERNAL* initProcessOptions;
WslcContainerNetworkingMode networking;
WSLA_CONTAINER_NETWORK_TYPE networking;
WslcContainerFlags containerFlags;

} WSLC_CONTAINER_OPTIONS_INTERNAL;
Expand Down
177 changes: 143 additions & 34 deletions src/windows/WslcSDK/wslcsdk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,20 @@ WSLASignal ConvertSignal(WslcSignal signal)
case WSLC_SIGNAL_SIGTERM:
return WSLASignal::WSLASignalSIGTERM;
default:
THROW_HR(E_INVALIDARG);
THROW_HR_MSG(E_INVALIDARG, "Invalid WslcSignal: %i", signal);
}
}

WSLA_CONTAINER_NETWORK_TYPE Convert(WslcContainerNetworkingMode mode)
{
switch (mode)
{
case WSLC_CONTAINER_NETWORKING_MODE_NONE:
return WSLA_CONTAINER_NETWORK_NONE;
case WSLC_CONTAINER_NETWORKING_MODE_BRIDGED:
return WSLA_CONTAINER_NETWORK_BRIDGE;
default:
THROW_HR_MSG(E_INVALIDARG, "Invalid WslcContainerNetworkingMode: %i", mode);
}
}

Expand All @@ -102,6 +115,24 @@ void GetErrorInfoFromCOM(PWSTR* errorMessage)
}
}
}

void EnsureAbsolutePath(const std::filesystem::path& path, bool containerPath)
{
THROW_HR_IF(E_INVALIDARG, path.empty());

if (containerPath)
{
auto pathString = path.native();
// Not allowed to mount to root
THROW_HR_IF(E_INVALIDARG, pathString.length() < 2);
// Must be absolute
THROW_HR_IF(E_INVALIDARG, pathString[0] != L'/');
}
else
{
THROW_HR_IF(E_INVALIDARG, path.is_relative());
}
}
} // namespace

// SESSION DEFINITIONS
Expand Down Expand Up @@ -220,15 +251,6 @@ try
}
CATCH_RETURN();

STDAPI WslcContainerSettingsSetNetworkingMode(_In_ WslcContainerSettings* containerSettings, _In_ WslcContainerNetworkingMode networkingMode)
try
{
UNREFERENCED_PARAMETER(networkingMode);
UNREFERENCED_PARAMETER(containerSettings);
return E_NOTIMPL;
}
CATCH_RETURN();

STDAPI WslcSessionSettingsSetTimeout(_In_ WslcSessionSettings* sessionSettings, _In_ uint32_t timeoutMS)
try
{
Expand Down Expand Up @@ -360,6 +382,8 @@ try
*internalType = {};

internalType->image = imageName;
// Default network configuration to WSLC SDK `0`, which is NONE.
internalType->networking = WSLA_CONTAINER_NETWORK_NONE;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We might want to default to NAT since this is often the default when creating containers on the command line

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

My only argument is that we should default to the 0 value of the SDK enum. NAT isn't a runtime value though, not sure if that is another name for HOST or BRIDGE, or a reference to the session networking mode.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sorry yeah by NAT I actually meant "bridged". We could make that the '0' value yeah


return S_OK;
}
Expand Down Expand Up @@ -400,12 +424,45 @@ try
// containerOptions.InitProcessOptions.User;
}

// TODO: Implement
// containerOptions.Volumes;
// containerOptions.VolumesCount;
// containerOptions.Ports;
// containerOptions.PortsCount;
// containerOptions.ContainerNetwork;
std::unique_ptr<WSLA_VOLUME[]> convertedVolumes;
Comment thread
JohnMcPMS marked this conversation as resolved.
if (internalContainerSettings->volumes && internalContainerSettings->volumesCount)
{
convertedVolumes = std::make_unique<WSLA_VOLUME[]>(internalContainerSettings->volumesCount);
for (uint32_t i = 0; i < internalContainerSettings->volumesCount; ++i)
{
const WslcContainerVolume& internalVolume = internalContainerSettings->volumes[i];
WSLA_VOLUME& convertedVolume = convertedVolumes[i];

convertedVolume.HostPath = internalVolume.windowsPath;
convertedVolume.ContainerPath = internalVolume.containerPath;
convertedVolume.ReadOnly = internalVolume.readOnly;
}
containerOptions.Volumes = convertedVolumes.get();
containerOptions.VolumesCount = static_cast<ULONG>(internalContainerSettings->volumesCount);
}

std::unique_ptr<WSLA_PORT_MAPPING[]> convertedPorts;
if (internalContainerSettings->ports && internalContainerSettings->portsCount)
{
convertedPorts = std::make_unique<WSLA_PORT_MAPPING[]>(internalContainerSettings->portsCount);
for (uint32_t i = 0; i < internalContainerSettings->portsCount; ++i)
{
const WslcContainerPortMapping& internalPort = internalContainerSettings->ports[i];
WSLA_PORT_MAPPING& convertedPort = convertedPorts[i];

convertedPort.HostPort = internalPort.windowsPort;
convertedPort.ContainerPort = internalPort.containerPort;
// TODO: Only other supported value right now is AF_INET6; no user access.
convertedPort.Family = AF_INET;

// TODO: Unused protocol?
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

That's right, those aren't implemented in the service right now

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

If they are both planned I can at least E_NOTIMPL what I can.

The port mapping in the runtime provides a choice between v4 and v6; should the SDK just create two mapping at all times (one for each IP version)? Or should we provide the user this control?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we should let the user control that

// TODO: Unused windowsAddress?
Comment thread
JohnMcPMS marked this conversation as resolved.
}
containerOptions.Ports = convertedPorts.get();
containerOptions.PortsCount = static_cast<ULONG>(internalContainerSettings->portsCount);
}

containerOptions.ContainerNetwork.ContainerNetworkType = internalContainerSettings->networking;

// TODO: No user access
// containerOptions.Entrypoint;
Expand Down Expand Up @@ -473,24 +530,56 @@ try
}
CATCH_RETURN();

STDAPI WslcContainerSettingsSetNetworkingMode(_In_ WslcContainerSettings* containerSettings, _In_ WslcContainerNetworkingMode networkingMode)
try
{
auto internalType = CheckAndGetInternalType(containerSettings);

internalType->networking = Convert(networkingMode);

return S_OK;
}
CATCH_RETURN();

STDAPI WslcContainerSettingsSetPortMapping(
_In_ WslcContainerSettings* containerSettings, _In_reads_(portMappingCount) const WslcContainerPortMapping* portMappings, _In_ uint32_t portMappingCount)
try
{
UNREFERENCED_PARAMETER(portMappings);
UNREFERENCED_PARAMETER(containerSettings);
UNREFERENCED_PARAMETER(portMappingCount);
return E_NOTIMPL;
auto internalType = CheckAndGetInternalType(containerSettings);
RETURN_HR_IF(E_INVALIDARG, (portMappings == nullptr && portMappingCount != 0) || (portMappings != nullptr && portMappingCount == 0));

for (uint32_t i = 0; i < portMappingCount; ++i)
{
RETURN_HR_IF(E_NOTIMPL, portMappings[i].windowsAddress != nullptr);
RETURN_HR_IF(E_NOTIMPL, portMappings[i].protocol != 0);
}

internalType->ports = portMappings;
internalType->portsCount = portMappingCount;

return S_OK;
}
Comment thread
JohnMcPMS marked this conversation as resolved.
CATCH_RETURN();

STDAPI WslcContainerSettingsAddVolume(_In_ WslcContainerSettings* containerSettings, _In_reads_(volumeCount) const WslcContainerVolume* volumes, _In_ uint32_t volumeCount)
STDAPI WslcContainerSettingsSetVolumes(
_In_ WslcContainerSettings* containerSettings, _In_reads_(volumeCount) const WslcContainerVolume* volumes, _In_ uint32_t volumeCount)
try
{
UNREFERENCED_PARAMETER(volumes);
UNREFERENCED_PARAMETER(volumeCount);
UNREFERENCED_PARAMETER(containerSettings);
return E_NOTIMPL;
auto internalType = CheckAndGetInternalType(containerSettings);
RETURN_HR_IF(E_INVALIDARG, (volumes == nullptr && volumeCount != 0) || (volumes != nullptr && volumeCount == 0));

for (uint32_t i = 0; i < volumeCount; ++i)
{
RETURN_HR_IF_NULL(E_INVALIDARG, volumes[i].windowsPath);
EnsureAbsolutePath(volumes[i].windowsPath, false);
RETURN_HR_IF_NULL(E_INVALIDARG, volumes[i].containerPath);
EnsureAbsolutePath(volumes[i].containerPath, true);
}

internalType->volumes = volumes;
Comment thread
JohnMcPMS marked this conversation as resolved.
internalType->volumesCount = volumeCount;

return S_OK;
}
Comment thread
JohnMcPMS marked this conversation as resolved.
CATCH_RETURN();

Expand Down Expand Up @@ -608,10 +697,10 @@ try
RETURN_HR_IF(
E_INVALIDARG,
(argv == nullptr && argc != 0) || (argv != nullptr && argc == 0) ||
(argc > static_cast<size_t>(std::numeric_limits<UINT32>::max())));
(argc > static_cast<size_t>(std::numeric_limits<uint32_t>::max())));

internalType->commandLine = argv;
internalType->commandLineCount = static_cast<UINT32>(argc);
internalType->commandLineCount = static_cast<uint32_t>(argc);

return S_OK;
}
Expand All @@ -620,10 +709,16 @@ CATCH_RETURN();
STDAPI WslcProcessSettingsSetEnvVariables(_In_ WslcProcessSettings* processSettings, _In_reads_(argc) PCSTR const* key_value, size_t argc)
try
{
UNREFERENCED_PARAMETER(key_value);
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(processSettings);
return E_NOTIMPL;
auto internalType = CheckAndGetInternalType(processSettings);
RETURN_HR_IF(
E_INVALIDARG,
(key_value == nullptr && argc != 0) || (key_value != nullptr && argc == 0) ||
(argc > static_cast<size_t>(std::numeric_limits<uint32_t>::max())));
Comment thread
JohnMcPMS marked this conversation as resolved.

internalType->environment = key_value;
internalType->environmentCount = static_cast<uint32_t>(argc);

return S_OK;
}
CATCH_RETURN();

Expand Down Expand Up @@ -748,9 +843,23 @@ CATCH_RETURN();
STDAPI WslcSessionImageLoad(_In_ WslcSession session, _In_ const WslcLoadImageOptions* options)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit For a future PR: We might want to also expose something like:

WslcSessionImageLoadFromFile(WslcSession session, LPCWSTR Path);

So that the caller doesn't have to manually open the handle and get the file size

try
{
UNREFERENCED_PARAMETER(session);
UNREFERENCED_PARAMETER(options);
return E_NOTIMPL;
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(E_INVALIDARG, options->ImageHandle == nullptr || options->ImageHandle == INVALID_HANDLE_VALUE);
RETURN_HR_IF(E_INVALIDARG, options->ContentLength == 0);

auto progressCallback = ProgressCallback::CreateIf(options);

HRESULT hr = internalType->session->LoadImage(HandleToULong(options->ImageHandle), progressCallback.get(), options->ContentLength);

if (FAILED_LOG(hr))
{
// TODO: Expected error message changes
// GetErrorInfoFromCOM(errorMessage);
Comment thread
JohnMcPMS marked this conversation as resolved.
}

return hr;
}
CATCH_RETURN();

Expand Down
2 changes: 1 addition & 1 deletion src/windows/WslcSDK/wslcsdk.def
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ WslcContainerSettingsSetDomainName
WslcContainerSettingsSetName
WslcContainerSettingsSetNetworkingMode
WslcContainerSettingsSetHostName
WslcContainerSettingsAddVolume
WslcContainerSettingsSetVolumes
WslcContainerSettingsSetInitProcess
WslcContainerSettingsSetFlags
WslcContainerSettingsSetPortMapping
Expand Down
2 changes: 1 addition & 1 deletion src/windows/WslcSDK/wslcsdk.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ STDAPI WslcContainerSettingsSetPortMapping(
_In_ WslcContainerSettings* containerSettings, _In_reads_(portMappingCount) const WslcContainerPortMapping* portMappings, _In_ uint32_t portMappingCount);

// Add the container volumes to the volumes array
STDAPI WslcContainerSettingsAddVolume(
STDAPI WslcContainerSettingsSetVolumes(
_In_ WslcContainerSettings* containerSettings, _In_reads_(volumeCount) const WslcContainerVolume* volumes, _In_ uint32_t volumeCount);

STDAPI WslcContainerExec(_In_ WslcContainer container, _In_ WslcProcessSettings* newProcessSettings, _Out_ WslcProcess* newProcess);
Expand Down
Loading