| 1 | /*++ |
| 2 | |
| 3 | Copyright (c) Microsoft. All rights reserved. |
| 4 | |
| 5 | Module Name: |
| 6 | |
| 7 | WslcSDK.h |
| 8 | |
| 9 | Abstract: |
| 10 | |
| 11 | This file contains the public WSL Container SDK api definitions. |
| 12 | |
| 13 | PREVIEW NOTICE: This API is currently in preview and is subject to breaking |
| 14 | changes in future releases without prior notice. Do not rely on API stability |
| 15 | for production workloads. Features, function signatures, and behaviors may |
| 16 | change between releases during the preview period. |
| 17 | |
| 18 | --*/ |
| 19 | #pragma once |
| 20 | #include <winsock2.h> |
| 21 | #include <ws2tcpip.h> |
| 22 | #include <windows.h> |
| 23 | #include <stdint.h> |
| 24 | #include <specstrings.h> |
| 25 | |
| 26 | EXTERN_C_START |
| 27 | |
| 28 | // WSLC specific error codes |
| 29 | // Ensure wslc.idl and wslcsdk.idl are also updated. |
| 30 | #define WSLC_E_BASE (0x0600) |
| 31 | #define WSLC_E_IMAGE_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 1) /* 0x80040601 */ |
| 32 | #define WSLC_E_CONTAINER_PREFIX_AMBIGUOUS MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 2) /* 0x80040602 */ |
| 33 | #define WSLC_E_CONTAINER_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 3) /* 0x80040603 */ |
| 34 | #define WSLC_E_VOLUME_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 4) /* 0x80040604 */ |
| 35 | #define WSLC_E_CONTAINER_NOT_RUNNING MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 5) /* 0x80040605 */ |
| 36 | #define WSLC_E_CONTAINER_IS_RUNNING MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 6) /* 0x80040606 */ |
| 37 | #define WSLC_E_SESSION_RESERVED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 7) /* 0x80040607 */ |
| 38 | #define WSLC_E_INVALID_SESSION_NAME MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 8) /* 0x80040608 */ |
| 39 | #define WSLC_E_NETWORK_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 9) /* 0x80040609 */ |
| 40 | #define WSLC_E_WU_SEARCH_FAILED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 10) /* 0x8004060A */ |
| 41 | #define WSLC_E_SDK_UPDATE_NEEDED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 11) /* 0x8004060B */ |
| 42 | #define WSLC_E_CONTAINER_DISABLED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 12) /* 0x8004060C */ |
| 43 | #define WSLC_E_REGISTRY_BLOCKED_BY_POLICY MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 13) /* 0x8004060D */ |
| 44 | #define WSLC_E_VOLUME_NOT_AVAILABLE MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 14) /* 0x8004060E */ |
| 45 | #define WSLC_E_SESSION_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 15) /* 0x8004060F */ |
| 46 | #define WSLC_E_VM_NOT_RUNNING MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 16) /* 0x80040610 */ |
| 47 | #define WSLC_E_EVENTS_LOST MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 17) /* 0x80040611 */ |
| 48 | #define WSLC_E_EVENT_STREAM_FINISHED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 18) /* 0x80040612 */ |
| 49 | #define WSLC_E_CONTAINER_DELETED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 19) /* 0x80040613 */ |
| 50 | |
| 51 | // Session values |
| 52 | #define WSLC_SESSION_OPTIONS_SIZE 72 |
| 53 | #define WSLC_SESSION_OPTIONS_ALIGNMENT 8 |
| 54 | |
| 55 | typedef struct WslcSessionSettings |
| 56 | { |
| 57 | __declspec(align(WSLC_SESSION_OPTIONS_ALIGNMENT)) BYTE _opaque[WSLC_SESSION_OPTIONS_SIZE]; |
| 58 | } WslcSessionSettings; |
| 59 | |
| 60 | DECLARE_HANDLE(WslcSession); |
| 61 | |
| 62 | // Container values |
| 63 | #define WSLC_CONTAINER_OPTIONS_SIZE 104 |
| 64 | #define WSLC_CONTAINER_OPTIONS_ALIGNMENT 8 |
| 65 | |
| 66 | typedef struct WslcContainerSettings |
| 67 | { |
| 68 | __declspec(align(WSLC_CONTAINER_OPTIONS_ALIGNMENT)) BYTE _opaque[WSLC_CONTAINER_OPTIONS_SIZE]; |
| 69 | } WslcContainerSettings; |
| 70 | |
| 71 | DECLARE_HANDLE(WslcContainer); |
| 72 | |
| 73 | // Process values |
| 74 | #define WSLC_CONTAINER_PROCESS_OPTIONS_SIZE 72 |
| 75 | #define WSLC_CONTAINER_PROCESS_OPTIONS_ALIGNMENT 8 |
| 76 | typedef struct WslcProcessSettings |
| 77 | { |
| 78 | __declspec(align(WSLC_CONTAINER_PROCESS_OPTIONS_ALIGNMENT)) BYTE _opaque[WSLC_CONTAINER_PROCESS_OPTIONS_SIZE]; |
| 79 | } WslcProcessSettings; |
| 80 | |
| 81 | DECLARE_HANDLE(WslcProcess); |
| 82 | |
| 83 | typedef enum WslcContainerNetworkingMode |
| 84 | { |
| 85 | WSLC_CONTAINER_NETWORKING_MODE_NONE = 0, // No networking / isolated |
| 86 | WSLC_CONTAINER_NETWORKING_MODE_BRIDGED = 1 |
| 87 | } WslcContainerNetworkingMode; |
| 88 | |
| 89 | typedef enum WslcVhdType |
| 90 | { |
| 91 | WSLC_VHD_TYPE_DYNAMIC = 0, // Expanding VHDX (default) |
| 92 | WSLC_VHD_TYPE_FIXED = 1 // Fixed-allocation VHDX (only honored by WslcCreateSessionVhdVolume) |
| 93 | } WslcVhdType; |
| 94 | |
| 95 | typedef enum WslcVhdRequirementsFlags |
| 96 | { |
| 97 | WSLC_VHD_REQ_FLAG_NONE = 0x00000000, |
| 98 | // When set, WslcVhdRequirements::uid and gid are honored. When clear, |
| 99 | // those fields are ignored and the volume is left owned by root:root. |
| 100 | WSLC_VHD_REQ_FLAG_OWNER = 0x00000001, |
| 101 | } WslcVhdRequirementsFlags; |
| 102 | |
| 103 | DEFINE_ENUM_FLAG_OPERATORS(WslcVhdRequirementsFlags); |
| 104 | |
| 105 | typedef struct WslcVhdRequirements |
| 106 | { |
| 107 | // Ignored by WslcSetSessionSettingsVhd |
| 108 | _In_z_ PCSTR name; |
| 109 | _In_ uint64_t sizeBytes; // Desired size (for create/expand) |
| 110 | _In_ WslcVhdType type; |
| 111 | // The remaining fields are only honored by WslcCreateSessionVhdVolume. |
| 112 | // WslcSetSessionSettingsVhd rejects non-NONE flags with E_INVALIDARG. |
| 113 | _In_ WslcVhdRequirementsFlags flags; |
| 114 | _In_ uint32_t uid; // honored iff (flags & WSLC_VHD_REQ_FLAG_OWNER) |
| 115 | _In_ uint32_t gid; // honored iff (flags & WSLC_VHD_REQ_FLAG_OWNER) |
| 116 | } WslcVhdRequirements; |
| 117 | |
| 118 | typedef enum WslcSessionFeatureFlags |
| 119 | { |
| 120 | WSLC_SESSION_FEATURE_FLAG_NONE = 0x00000000, |
| 121 | WSLC_SESSION_FEATURE_FLAG_ENABLE_GPU = 0x00000004 |
| 122 | } WslcSessionFeatureFlags; |
| 123 | |
| 124 | DEFINE_ENUM_FLAG_OPERATORS(WslcSessionFeatureFlags); |
| 125 | |
| 126 | typedef enum WslcSessionTerminationReason |
| 127 | { |
| 128 | WSLC_SESSION_TERMINATION_REASON_UNKNOWN = 0, |
| 129 | WSLC_SESSION_TERMINATION_REASON_SHUTDOWN = 1, |
| 130 | WSLC_SESSION_TERMINATION_REASON_CRASHED = 2, |
| 131 | } WslcSessionTerminationReason; |
| 132 | |
| 133 | typedef struct WslcSessionCrashDumpInfo |
| 134 | { |
| 135 | _Field_z_ PCWSTR dumpPath; |
| 136 | _Field_z_ PCSTR processName; |
| 137 | uint32_t pid; |
| 138 | uint32_t signal; |
| 139 | uint64_t timestamp; |
| 140 | } WslcSessionCrashDumpInfo; |
| 141 | |
| 142 | typedef __callback void(CALLBACK* WslcSessionCrashDumpCallback)(_In_ const WslcSessionCrashDumpInfo* info, _In_opt_ PVOID context); |
| 143 | |
| 144 | // Opaque handle returned by WslcRegisterSessionCrashDumpCallback. Holding it keeps the crash dump |
| 145 | // registration alive; pass it to WslcReleaseCrashDumpSubscription to unsubscribe. |
| 146 | DECLARE_HANDLE(WslcCrashDumpSubscription); |
| 147 | |
| 148 | STDAPI WslcInitSessionSettings(_In_ PCWSTR name, _In_ PCWSTR storagePath, _Out_ WslcSessionSettings* sessionSettings); |
| 149 | |
| 150 | STDAPI WslcCreateSession(_In_ WslcSessionSettings* sessionSettings, _Out_ WslcSession* session, _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 151 | |
| 152 | // OPTIONAL SESSION SETTINGS |
| 153 | STDAPI WslcSetSessionSettingsCpuCount(_In_ WslcSessionSettings* sessionSettings, _In_ uint32_t cpuCount); |
| 154 | STDAPI WslcSetSessionSettingsMemory(_In_ WslcSessionSettings* sessionSettings, _In_ uint32_t memoryMB); |
| 155 | STDAPI WslcSetSessionSettingsTimeout(_In_ WslcSessionSettings* sessionSettings, _In_ uint32_t timeoutMS); |
| 156 | |
| 157 | STDAPI WslcSetSessionSettingsVhd(_In_ WslcSessionSettings* sessionSettings, _In_opt_ const WslcVhdRequirements* vhdRequirements); |
| 158 | |
| 159 | STDAPI WslcSetSessionSettingsFeatureFlags(_In_ WslcSessionSettings* sessionSettings, _In_ WslcSessionFeatureFlags flags); |
| 160 | |
| 161 | STDAPI WslcGetSessionTerminationEvent(_In_ WslcSession session, _Out_ HANDLE* terminationEvent); |
| 162 | STDAPI WslcGetSessionTerminationReason(_In_ WslcSession session, _Out_ WslcSessionTerminationReason* reason); |
| 163 | |
| 164 | STDAPI WslcTerminateSession(_In_ WslcSession session); |
| 165 | STDAPI WslcReleaseSession(_In_ WslcSession session); |
| 166 | |
| 167 | // Registers a callback invoked when a Linux process crash dump is written for the session. |
| 168 | // Works for any caller holding a live session. The returned subscription keeps the registration |
| 169 | // alive; release it with WslcReleaseCrashDumpSubscription to unsubscribe. Multiple subscriptions |
| 170 | // can be registered against the same session. |
| 171 | STDAPI WslcRegisterSessionCrashDumpCallback( |
| 172 | _In_ WslcSession session, |
| 173 | _In_ WslcSessionCrashDumpCallback crashDumpCallback, |
| 174 | _In_opt_ PVOID crashDumpContext, |
| 175 | _Out_ WslcCrashDumpSubscription* subscription, |
| 176 | _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 177 | |
| 178 | STDAPI WslcReleaseCrashDumpSubscription(_In_ WslcCrashDumpSubscription subscription); |
| 179 | |
| 180 | // CONTAINER DEFINITIONS |
| 181 | |
| 182 | typedef enum WslcPortProtocol |
| 183 | { |
| 184 | WSLC_PORT_PROTOCOL_TCP = 0, |
| 185 | WSLC_PORT_PROTOCOL_UDP = 1 |
| 186 | } WslcPortProtocol; |
| 187 | |
| 188 | typedef struct WslcContainerPortMapping |
| 189 | { |
| 190 | _In_ uint16_t windowsPort; // Port on Windows host |
| 191 | _In_ uint16_t containerPort; // Port inside container |
| 192 | _In_ WslcPortProtocol protocol; // TCP or UDP |
| 193 | |
| 194 | // if you want to override the default binding address |
| 195 | _In_opt_ struct sockaddr_storage* windowsAddress; // accepts ipv4/6 |
| 196 | } WslcContainerPortMapping; |
| 197 | |
| 198 | typedef struct WslcContainerVolume |
| 199 | { |
| 200 | _In_z_ PCWSTR windowsPath; |
| 201 | _In_z_ PCSTR containerPath; |
| 202 | _In_ BOOL readOnly; |
| 203 | } WslcContainerVolume; |
| 204 | |
| 205 | typedef struct WslcContainerNamedVolume |
| 206 | { |
| 207 | _In_z_ PCSTR name; // Name of the session volume (from WslcVhdRequirements.name) |
| 208 | _In_z_ PCSTR containerPath; // Absolute path inside the container |
| 209 | _In_ BOOL readOnly; |
| 210 | } WslcContainerNamedVolume; |
| 211 | |
| 212 | typedef enum WslcContainerFlags |
| 213 | { |
| 214 | WSLC_CONTAINER_FLAG_NONE = 0x00000000, |
| 215 | WSLC_CONTAINER_FLAG_AUTO_REMOVE = 0x00000001, |
| 216 | WSLC_CONTAINER_FLAG_ENABLE_GPU = 0x00000002, |
| 217 | WSLC_CONTAINER_FLAG_PRIVILEGED = 0x00000004, |
| 218 | |
| 219 | } WslcContainerFlags; |
| 220 | |
| 221 | DEFINE_ENUM_FLAG_OPERATORS(WslcContainerFlags); |
| 222 | |
| 223 | typedef enum WslcContainerStartFlags |
| 224 | { |
| 225 | WSLC_CONTAINER_START_FLAG_NONE = 0x00000000, |
| 226 | WSLC_CONTAINER_START_FLAG_ATTACH = 0x00000001, |
| 227 | |
| 228 | } WslcContainerStartFlags; |
| 229 | |
| 230 | DEFINE_ENUM_FLAG_OPERATORS(WslcContainerStartFlags); |
| 231 | |
| 232 | STDAPI WslcInitContainerSettings(_In_ PCSTR imageName, _Out_ WslcContainerSettings* containerSettings); |
| 233 | |
| 234 | STDAPI WslcCreateContainer(_In_ WslcSession session, _In_ const WslcContainerSettings* containerSettings, _Out_ WslcContainer* container, _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 235 | |
| 236 | // Opens an existing container by name, full ID, or partial ID prefix. |
| 237 | // The returned WslcContainer handle is owned by the caller; release it with WslcReleaseContainer. |
| 238 | // Returns WSLC_E_CONTAINER_NOT_FOUND if no matching container exists, or |
| 239 | // WSLC_E_CONTAINER_PREFIX_AMBIGUOUS if the given prefix matches more than one container. |
| 240 | STDAPI WslcOpenContainer(_In_ WslcSession session, _In_z_ PCSTR nameOrId, _Out_ WslcContainer* container, _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 241 | |
| 242 | STDAPI WslcStartContainer(_In_ WslcContainer container, _In_ WslcContainerStartFlags flags, _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 243 | |
| 244 | // OPTIONAL CONTAINER SETTINGS |
| 245 | STDAPI WslcSetContainerSettingsName(_In_ WslcContainerSettings* containerSettings, _In_ PCSTR name); |
| 246 | |
| 247 | STDAPI WslcSetContainerSettingsInitProcess(_In_ WslcContainerSettings* containerSettings, _In_ WslcProcessSettings* initProcess); |
| 248 | |
| 249 | STDAPI WslcSetContainerSettingsNetworkingMode(_In_ WslcContainerSettings* containerSettings, _In_ WslcContainerNetworkingMode networkingMode); |
| 250 | |
| 251 | STDAPI WslcSetContainerSettingsHostName(_In_ WslcContainerSettings* containerSettings, _In_ PCSTR hostName); |
| 252 | |
| 253 | STDAPI WslcSetContainerSettingsDomainName(_In_ WslcContainerSettings* containerSettings, _In_ PCSTR domainName); |
| 254 | |
| 255 | STDAPI WslcSetContainerSettingsFlags(_In_ WslcContainerSettings* containerSettings, _In_ WslcContainerFlags flags); |
| 256 | |
| 257 | STDAPI WslcSetContainerSettingsPortMappings( |
| 258 | _In_ WslcContainerSettings* containerSettings, |
| 259 | _In_reads_opt_(portMappingCount) const WslcContainerPortMapping* portMappings, |
| 260 | _In_ uint32_t portMappingCount); |
| 261 | |
| 262 | // Add the container volumes to the volumes array |
| 263 | STDAPI WslcSetContainerSettingsVolumes( |
| 264 | _In_ WslcContainerSettings* containerSettings, _In_reads_opt_(volumeCount) const WslcContainerVolume* volumes, _In_ uint32_t volumeCount); |
| 265 | |
| 266 | // Add named session volumes (created via WslcCreateSessionVhdVolume) to the container settings |
| 267 | STDAPI WslcSetContainerSettingsNamedVolumes( |
| 268 | _In_ WslcContainerSettings* containerSettings, |
| 269 | _In_reads_opt_(namedVolumeCount) const WslcContainerNamedVolume* namedVolumes, |
| 270 | _In_ uint32_t namedVolumeCount); |
| 271 | |
| 272 | STDAPI WslcCreateContainerProcess( |
| 273 | _In_ WslcContainer container, _In_ WslcProcessSettings* newProcessSettings, _Out_ WslcProcess* newProcess, _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 274 | |
| 275 | STDAPI WslcReleaseContainer(_In_ WslcContainer container); |
| 276 | |
| 277 | // GENERAL CONTAINER MANAGEMENT |
| 278 | |
| 279 | #define WSLC_CONTAINER_ID_BUFFER_SIZE 65 // 64 hex chars + null terminator |
| 280 | |
| 281 | STDAPI WslcGetContainerID(_In_ WslcContainer container, _Out_writes_(WSLC_CONTAINER_ID_BUFFER_SIZE) CHAR containerID[WSLC_CONTAINER_ID_BUFFER_SIZE]); |
| 282 | |
| 283 | STDAPI WslcGetContainerInitProcess(_In_ WslcContainer container, _Out_ WslcProcess* initProcess); |
| 284 | |
| 285 | // Retrieves the inspection data for a container. |
| 286 | // |
| 287 | // Parameters: |
| 288 | // container |
| 289 | // A valid WslcContainer handle representing the container to inspect. |
| 290 | // |
| 291 | // inspectData |
| 292 | // On success, receives a pointer to a null-terminated ANSI string |
| 293 | // containing the inspection data. |
| 294 | // |
| 295 | // The string is allocated using CoTaskMemAlloc. The caller takes |
| 296 | // ownership of the returned memory and must free it by calling |
| 297 | // CoTaskMemFree when it is no longer needed. |
| 298 | // |
| 299 | // Return Value: |
| 300 | // S_OK on success. Otherwise, an HRESULT error code indicating the failure. |
| 301 | STDAPI WslcInspectContainer(_In_ WslcContainer container, _Outptr_result_z_ PSTR* inspectData); |
| 302 | |
| 303 | typedef enum WslcContainerState |
| 304 | { |
| 305 | WSLC_CONTAINER_STATE_INVALID = 0, |
| 306 | WSLC_CONTAINER_STATE_CREATED = 1, |
| 307 | WSLC_CONTAINER_STATE_RUNNING = 2, |
| 308 | WSLC_CONTAINER_STATE_EXITED = 3, |
| 309 | WSLC_CONTAINER_STATE_DELETED = 4, |
| 310 | } WslcContainerState; |
| 311 | |
| 312 | STDAPI WslcGetContainerState(_In_ WslcContainer container, _Out_ WslcContainerState* state); |
| 313 | |
| 314 | // Will define more signals as needed: |
| 315 | typedef enum WslcSignal |
| 316 | { |
| 317 | WSLC_SIGNAL_NONE = 0, // No signal; reserved for future use |
| 318 | WSLC_SIGNAL_SIGHUP = 1, // SIGHUP: reload / hangup |
| 319 | WSLC_SIGNAL_SIGINT = 2, // SIGINT: interrupt (Ctrl-C) |
| 320 | WSLC_SIGNAL_SIGQUIT = 3, // SIGQUIT: quit with core dump |
| 321 | WSLC_SIGNAL_SIGKILL = 9, // SIGKILL: immediate termination |
| 322 | WSLC_SIGNAL_SIGTERM = 15, // SIGTERM: graceful shutdown |
| 323 | } WslcSignal; |
| 324 | |
| 325 | STDAPI WslcStopContainer(_In_ WslcContainer container, _In_ WslcSignal signal, _In_ uint32_t timeoutSeconds, _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 326 | |
| 327 | typedef enum WslcDeleteContainerFlags |
| 328 | { |
| 329 | WSLC_DELETE_CONTAINER_FLAG_NONE = 0, |
| 330 | WSLC_DELETE_CONTAINER_FLAG_FORCE = 0x01 |
| 331 | } WslcDeleteContainerFlags; |
| 332 | |
| 333 | DEFINE_ENUM_FLAG_OPERATORS(WslcDeleteContainerFlags); |
| 334 | |
| 335 | STDAPI WslcDeleteContainer(_In_ WslcContainer container, _In_ WslcDeleteContainerFlags flags, _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 336 | |
| 337 | // PROCESS DEFINITIONS |
| 338 | STDAPI WslcInitProcessSettings(_Out_ WslcProcessSettings* processSettings); |
| 339 | |
| 340 | // OPTIONAL PROCESS SETTINGS |
| 341 | |
| 342 | STDAPI WslcSetProcessSettingsWorkingDirectory(_In_ WslcProcessSettings* processSettings, _In_ PCSTR workingDirectory); |
| 343 | |
| 344 | STDAPI WslcSetProcessSettingsCmdLine(_In_ WslcProcessSettings* processSettings, _In_reads_(argc) PCSTR const* argv, size_t argc); |
| 345 | |
| 346 | STDAPI WslcSetProcessSettingsEnvVariables(_In_ WslcProcessSettings* processSettings, _In_reads_(argc) PCSTR const* key_value, size_t argc); |
| 347 | |
| 348 | typedef enum WslcProcessIOHandle |
| 349 | { |
| 350 | WSLC_PROCESS_IO_HANDLE_STDIN = 0, |
| 351 | WSLC_PROCESS_IO_HANDLE_STDOUT = 1, |
| 352 | WSLC_PROCESS_IO_HANDLE_STDERR = 2 |
| 353 | } WslcProcessIOHandle; |
| 354 | |
| 355 | // Callback invoked when stdout or stderr data is available from a running |
| 356 | // WSLC process. |
| 357 | // |
| 358 | // Parameters: |
| 359 | // ioHandle |
| 360 | // The WslcProcessIOHandle that the IO callback is for. |
| 361 | // Only STDOUT and STDERR will receive callbacks. |
| 362 | // |
| 363 | // data |
| 364 | // Pointer to a buffer containing the bytes read. The buffer is owned |
| 365 | // by WSLC and is valid only for the duration of the callback. |
| 366 | // |
| 367 | // The caller must not free, modify, or retain the pointer. If the |
| 368 | // caller needs to keep the data, it must copy the contents before |
| 369 | // returning from the callback. |
| 370 | // |
| 371 | // dataBytes |
| 372 | // Number of bytes available in the data buffer. |
| 373 | // |
| 374 | // context |
| 375 | // Caller-supplied context pointer that was provided when the callback |
| 376 | // was registered. |
| 377 | // |
| 378 | // Notes: |
| 379 | // - WSLC frees or reuses the buffer immediately after the callback returns. |
| 380 | // - The callback must return promptly; long-running operations may block |
| 381 | // WSLC's internal I/O processing. |
| 382 | // - The buffer is not null-terminated; it is a raw byte sequence. |
| 383 | // |
| 384 | typedef __callback void(CALLBACK* WslcStdIOCallback)( |
| 385 | WslcProcessIOHandle ioHandle, _In_reads_bytes_(dataBytes) const BYTE* data, _In_ uint32_t dataBytes, _In_opt_ PVOID context); |
| 386 | |
| 387 | // Callback invoked when a WSLC process has exited AND any remaining IO has been flushed. |
| 388 | // |
| 389 | // Parameters: |
| 390 | // exitCode |
| 391 | // The exit code of the process. |
| 392 | // |
| 393 | // context |
| 394 | // Caller-supplied context pointer that was provided when the callback |
| 395 | // was registered. |
| 396 | // |
| 397 | // Notes: |
| 398 | // - Once this callback is invoked, any registered IO callbacks will no longer be called. |
| 399 | // |
| 400 | typedef __callback void(CALLBACK* WslcProcessExitCallback)(INT32 exitCode, _In_opt_ PVOID context); |
| 401 | |
| 402 | // Using any callbacks will consume the IO handles, preventing acquisition through WslcGetProcessIOHandle. |
| 403 | // If using IO callbacks, also use the exit callback to prevent a race between process exit and IO buffer flushing. |
| 404 | typedef struct WslcProcessCallbacks |
| 405 | { |
| 406 | WslcStdIOCallback onStdOut; |
| 407 | WslcStdIOCallback onStdErr; |
| 408 | WslcProcessExitCallback onExit; |
| 409 | } WslcProcessCallbacks; |
| 410 | |
| 411 | STDAPI WslcSetProcessSettingsCallbacks(_In_ WslcProcessSettings* processSettings, _In_ const WslcProcessCallbacks* callbacks, _In_opt_ PVOID context); |
| 412 | |
| 413 | // Sets IO callbacks for the init process of a container. |
| 414 | // Must be called before WslcStartContainer (with WSLC_CONTAINER_START_FLAG_ATTACH). |
| 415 | // Has no effect on a container that is already running. |
| 416 | STDAPI WslcSetContainerInitProcessIOCallbacks(_In_ WslcContainer container, _In_ const WslcProcessCallbacks* callbacks, _In_opt_ PVOID context); |
| 417 | |
| 418 | // PROCESS MANAGEMENT |
| 419 | |
| 420 | STDAPI WslcGetProcessPid(_In_ WslcProcess process, _Out_ uint32_t* pid); |
| 421 | |
| 422 | STDAPI WslcGetProcessExitEvent(_In_ WslcProcess process, _Out_ HANDLE* exitEvent); |
| 423 | |
| 424 | typedef enum WslcProcessState |
| 425 | { |
| 426 | WSLC_PROCESS_STATE_UNKNOWN = 0, |
| 427 | WSLC_PROCESS_STATE_RUNNING = 1, |
| 428 | WSLC_PROCESS_STATE_EXITED = 2, |
| 429 | WSLC_PROCESS_STATE_SIGNALLED = 3 |
| 430 | } WslcProcessState; |
| 431 | |
| 432 | STDAPI WslcGetProcessState(_In_ WslcProcess process, _Out_ WslcProcessState* state); |
| 433 | |
| 434 | STDAPI WslcGetProcessExitCode(_In_ WslcProcess process, _Out_ PINT32 exitCode); |
| 435 | |
| 436 | STDAPI WslcSignalProcess(_In_ WslcProcess process, _In_ WslcSignal signal); |
| 437 | |
| 438 | STDAPI WslcGetProcessIOHandle(_In_ WslcProcess process, _In_ WslcProcessIOHandle ioHandle, _Out_ HANDLE* handle); |
| 439 | |
| 440 | STDAPI WslcReleaseProcess(_In_ WslcProcess process); |
| 441 | |
| 442 | // IMAGE MANAGEMENT |
| 443 | |
| 444 | // Container image |
| 445 | typedef struct WslcImageProgressDetail |
| 446 | { |
| 447 | _Out_ uint64_t currentBytes; // bytes downloaded so far |
| 448 | _Out_ uint64_t totalBytes; // total bytes expected |
| 449 | } WslcImageProgressDetail; |
| 450 | |
| 451 | typedef enum WslcImageProgressStatus |
| 452 | { |
| 453 | WSLC_IMAGE_PROGRESS_STATUS_UNKNOWN = 0, |
| 454 | WSLC_IMAGE_PROGRESS_STATUS_PULLING = 1, // "Pulling fs layer" |
| 455 | WSLC_IMAGE_PROGRESS_STATUS_WAITING = 2, // "Waiting" |
| 456 | WSLC_IMAGE_PROGRESS_STATUS_DOWNLOADING = 3, // "Downloading" |
| 457 | WSLC_IMAGE_PROGRESS_STATUS_VERIFYING = 4, // "Verifying Checksum" |
| 458 | WSLC_IMAGE_PROGRESS_STATUS_EXTRACTING = 5, // "Extracting" |
| 459 | WSLC_IMAGE_PROGRESS_STATUS_COMPLETE = 6 // "Pull complete" |
| 460 | } WslcImageProgressStatus; |
| 461 | |
| 462 | typedef struct WslcImageProgressMessage |
| 463 | { |
| 464 | _Out_ PCSTR id; // layer ID or digest |
| 465 | _Out_ WslcImageProgressStatus status; // "Downloading", "Extracting", etc. |
| 466 | _Out_ WslcImageProgressDetail detail; |
| 467 | } WslcImageProgressMessage; |
| 468 | |
| 469 | // pointer-to-function typedef (unambiguous) |
| 470 | typedef HRESULT(CALLBACK* WslcContainerImageProgressCallback)(const WslcImageProgressMessage* progress, PVOID context); |
| 471 | |
| 472 | // options struct typedef is a pointer type and _In_opt_ is valid |
| 473 | typedef struct WslcPullImageOptions |
| 474 | { |
| 475 | _In_z_ PCSTR uri; |
| 476 | WslcContainerImageProgressCallback progressCallback; |
| 477 | PVOID progressCallbackContext; |
| 478 | _In_opt_z_ PCSTR registryAuth; |
| 479 | } WslcPullImageOptions; |
| 480 | |
| 481 | STDAPI WslcPullSessionImage(_In_ WslcSession session, _In_ const WslcPullImageOptions* options, _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 482 | |
| 483 | typedef struct WslcImportImageOptions |
| 484 | { |
| 485 | _In_opt_ WslcContainerImageProgressCallback progressCallback; |
| 486 | _In_opt_ PVOID progressCallbackContext; |
| 487 | } WslcImportImageOptions; |
| 488 | |
| 489 | STDAPI WslcImportSessionImage( |
| 490 | _In_ WslcSession session, |
| 491 | _In_z_ PCSTR imageName, |
| 492 | _In_ HANDLE imageContent, |
| 493 | _In_ uint64_t imageContentBytes, |
| 494 | _In_opt_ const WslcImportImageOptions* options, |
| 495 | _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 496 | |
| 497 | STDAPI WslcImportSessionImageFromFile( |
| 498 | _In_ WslcSession session, _In_z_ PCSTR imageName, _In_z_ PCWSTR path, _In_opt_ const WslcImportImageOptions* options, _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 499 | |
| 500 | typedef struct WslcLoadImageOptions |
| 501 | { |
| 502 | _In_opt_ WslcContainerImageProgressCallback progressCallback; |
| 503 | _In_opt_ PVOID progressCallbackContext; |
| 504 | } WslcLoadImageOptions; |
| 505 | |
| 506 | STDAPI WslcLoadSessionImage( |
| 507 | _In_ WslcSession session, |
| 508 | _In_ HANDLE imageContent, |
| 509 | _In_ uint64_t imageContentBytes, |
| 510 | _In_opt_ const WslcLoadImageOptions* options, |
| 511 | _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 512 | |
| 513 | STDAPI WslcLoadSessionImageFromFile( |
| 514 | _In_ WslcSession session, _In_z_ PCWSTR path, _In_opt_ const WslcLoadImageOptions* options, _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 515 | |
| 516 | #define WSLC_IMAGE_NAME_LENGTH 256 // 255 chars + null |
| 517 | |
| 518 | typedef struct WslcImageInfo |
| 519 | { |
| 520 | // we should expose this |
| 521 | CHAR name[WSLC_IMAGE_NAME_LENGTH]; |
| 522 | uint8_t sha256[32]; |
| 523 | int64_t sizeBytes; |
| 524 | uint64_t createdUnixTime; |
| 525 | } WslcImageInfo; |
| 526 | |
| 527 | STDAPI WslcDeleteSessionImage(_In_ WslcSession session, _In_z_ PCSTR nameOrID, _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 528 | |
| 529 | typedef struct WslcTagImageOptions |
| 530 | { |
| 531 | _In_z_ PCSTR image; // Source image name or ID. |
| 532 | _In_z_ PCSTR repo; // Target repository name. |
| 533 | _In_z_ PCSTR tag; // Target tag name. |
| 534 | } WslcTagImageOptions; |
| 535 | |
| 536 | STDAPI WslcTagSessionImage(_In_ WslcSession session, _In_ const WslcTagImageOptions* options, _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 537 | |
| 538 | typedef struct WslcPushImageOptions |
| 539 | { |
| 540 | _In_z_ PCSTR image; |
| 541 | _In_z_ PCSTR registryAuth; // Base64-encoded X-Registry-Auth header value. |
| 542 | _In_opt_ WslcContainerImageProgressCallback progressCallback; |
| 543 | _In_opt_ PVOID progressCallbackContext; |
| 544 | } WslcPushImageOptions; |
| 545 | |
| 546 | STDAPI WslcPushSessionImage(_In_ WslcSession session, _In_ const WslcPushImageOptions* options, _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 547 | |
| 548 | typedef enum WslcIdentityTokenType |
| 549 | { |
| 550 | WSLC_IDENTITY_TOKEN_TYPE_UNKNOWN = 0, |
| 551 | WSLC_IDENTITY_TOKEN_TYPE_TOKEN = 1, |
| 552 | WSLC_IDENTITY_TOKEN_TYPE_CREDENTIALS = 2, |
| 553 | } WslcIdentityTokenType; |
| 554 | |
| 555 | // Authenticates with a container registry and returns an identity token suitable for use as |
| 556 | // the registryAuth value in WslcPullSessionImage and WslcPushSessionImage. |
| 557 | // |
| 558 | // Parameters: |
| 559 | // session |
| 560 | // A valid WslcSession handle. |
| 561 | // |
| 562 | // serverAddress |
| 563 | // The registry server address (e.g. "127.0.0.1:5000"). |
| 564 | // |
| 565 | // username |
| 566 | // The username for authentication. |
| 567 | // |
| 568 | // password |
| 569 | // The password for authentication. |
| 570 | // |
| 571 | // identityToken |
| 572 | // On success, receives a pointer to a null-terminated ANSI string containing a |
| 573 | // base64-encoded JSON object that can be passed directly as the registryAuth value to |
| 574 | // WslcPullSessionImage or WslcPushSessionImage. |
| 575 | // |
| 576 | // The string is allocated using CoTaskMemAlloc. The caller takes ownership of the |
| 577 | // returned memory and must free it by calling CoTaskMemFree when it is no longer needed. |
| 578 | // |
| 579 | // tokenType |
| 580 | // Optional. On success, receives the type of credential embedded in identityToken: |
| 581 | // WSLC_IDENTITY_TOKEN_TYPE_TOKEN - the server returned an identity token; |
| 582 | // identityToken encodes {"identitytoken": ...} |
| 583 | // WSLC_IDENTITY_TOKEN_TYPE_CREDENTIALS - the server returned no token; the supplied |
| 584 | // username/password are embedded instead as |
| 585 | // {"username": ..., "password": ...} |
| 586 | // On failure, set to WSLC_IDENTITY_TOKEN_TYPE_UNKNOWN. |
| 587 | // May be null if the caller does not need the token type. |
| 588 | // |
| 589 | // errorMessage |
| 590 | // Optional. On failure, receives a human-readable error message. May be null. |
| 591 | // |
| 592 | // Return Value: |
| 593 | // S_OK on success. Otherwise, an HRESULT error code indicating the failure. |
| 594 | // |
| 595 | // Outcome table: |
| 596 | // Outcome | HRESULT | identityToken | tokenType |
| 597 | // ------------------------------|---------|--------------------------------------|---------- |
| 598 | // Failure | FAILED | nullptr | UNKNOWN |
| 599 | // Success, server returns token | S_OK | base64({"identitytoken": "<token>"}) | TOKEN |
| 600 | // Success, no token returned | S_OK | base64({"username":..,"password":..})| CREDENTIALS |
| 601 | STDAPI WslcSessionAuthenticate( |
| 602 | _In_ WslcSession session, |
| 603 | _In_z_ PCSTR serverAddress, |
| 604 | _In_z_ PCSTR username, |
| 605 | _In_z_ PCSTR password, |
| 606 | _Outptr_result_z_ PSTR* identityToken, |
| 607 | _Out_opt_ WslcIdentityTokenType* tokenType, |
| 608 | _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 609 | |
| 610 | // Retrieves the list of container images |
| 611 | // Parameters: |
| 612 | // session |
| 613 | // A valid WslcSession handle. |
| 614 | // |
| 615 | // images |
| 616 | // On success, receives a pointer to a contiguous array of |
| 617 | // WslcImageInfo structures describing the images |
| 618 | // |
| 619 | // The array is allocated using CoTaskMemAlloc. The caller takes |
| 620 | // ownership of the memory and must free it by calling |
| 621 | // CoTaskMemFree when it is no longer needed. |
| 622 | // |
| 623 | // count |
| 624 | // On success, receives the number of elements in the images array. |
| 625 | // On failure, *count is set to 0. |
| 626 | // |
| 627 | // Return Value: |
| 628 | // S_OK on success. Otherwise, an HRESULT error code indicating the |
| 629 | // reason for failure. |
| 630 | // |
| 631 | // Notes: |
| 632 | // - The caller must pass non-null pointers for both 'images' and 'count'. |
| 633 | // |
| 634 | |
| 635 | STDAPI WslcListSessionImages(_In_ WslcSession session, _Outptr_result_buffer_(*count) WslcImageInfo** images, _Out_ uint32_t* count); |
| 636 | |
| 637 | // STORAGE |
| 638 | |
| 639 | STDAPI WslcCreateSessionVhdVolume(_In_ WslcSession session, _In_ const WslcVhdRequirements* options, _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 640 | STDAPI WslcDeleteSessionVhdVolume(_In_ WslcSession session, _In_z_ PCSTR name, _Outptr_opt_result_z_ PWSTR* errorMessage); |
| 641 | |
| 642 | // INSTALL |
| 643 | |
| 644 | typedef enum WslcComponentFlags |
| 645 | { |
| 646 | WSLC_COMPONENT_FLAG_NONE = 0, |
| 647 | // Services provided by the Virtual Machine Platform optional feature (other optional features may provide these services as |
| 648 | // well). Installing this component will require a reboot. |
| 649 | WSLC_COMPONENT_FLAG_VIRTUAL_MACHINE_PLATFORM = 1, |
| 650 | // The WSL runtime package, at an appropriate version to provide support for WSLC. |
| 651 | WSLC_COMPONENT_FLAG_WSL_PACKAGE = 2, |
| 652 | // Set if the WSLC SDK itself needs to be updated. |
| 653 | WSLC_COMPONENT_FLAG_SDK_NEEDS_UPDATE = 4, |
| 654 | } WslcComponentFlags; |
| 655 | |
| 656 | DEFINE_ENUM_FLAG_OPERATORS(WslcComponentFlags); |
| 657 | |
| 658 | STDAPI WslcGetMissingComponents(_Out_ WslcComponentFlags* missingComponents); |
| 659 | |
| 660 | typedef struct WslcVersion |
| 661 | { |
| 662 | uint32_t major; |
| 663 | uint32_t minor; |
| 664 | uint32_t revision; |
| 665 | } WslcVersion; |
| 666 | STDAPI WslcGetVersion(_Out_writes_(1) WslcVersion* version); |
| 667 | |
| 668 | typedef __callback void(CALLBACK* WslcInstallCallback)( |
| 669 | _In_ WslcComponentFlags component, _In_ uint32_t progressSteps, _In_ uint32_t totalSteps, _In_opt_ PVOID context); |
| 670 | |
| 671 | typedef enum WslcInstallOptions |
| 672 | { |
| 673 | WSLC_INSTALL_OPTION_NONE = 0, |
| 674 | // Allows components to be reinstalled. |
| 675 | WSLC_INSTALL_OPTION_REPAIR = 1, |
| 676 | } WslcInstallOptions; |
| 677 | |
| 678 | DEFINE_ENUM_FLAG_OPERATORS(WslcInstallOptions); |
| 679 | |
| 680 | // Callbacks will only be made for components that are actively installed by this call. |
| 681 | // The list of required components can be acquired prior to this call with `WslcGetMissingComponents`. |
| 682 | STDAPI WslcInstallWithDependencies( |
| 683 | _In_ WslcComponentFlags components, _In_ WslcInstallOptions options, _In_opt_ WslcInstallCallback progressCallback, _In_opt_ PVOID context); |
| 684 | |
| 685 | EXTERN_C_END |