master
h 280 lines 12.7 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 WslPluginApi.h
8
9 Abstract:
10
11 This file contains the interface for WSL plugins to interact with WSL distributions.
12
13 --*/
14
15 #pragma once
16
17 #include <stdint.h>
18
19 // Must be lowercase. See: https://github.com/microsoft/WSL/issues/12580
20 #include <windows.h>
21
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25
26 #define WSLPLUGINAPI_ENTRYPOINTV1 WSLPluginAPIV1_EntryPoint
27 #define WSL_E_PLUGIN_REQUIRES_UPDATE MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x032A)
28
29 // Returned by the WSLC plugin API calls below when the session has no running VM.
30 // N.B. This value is also defined in wslc.idl; the two definitions must stay in sync.
31 #ifndef WSLC_E_VM_NOT_RUNNING
32 #define WSLC_E_VM_NOT_RUNNING MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0610)
33 #endif
34
35 #define WSL_PLUGIN_REQUIRE_VERSION(_Major, _Minor, _Revision, Api) \
36 if (Api->Version.Major < (_Major) || (Api->Version.Major == (_Major) && Api->Version.Minor < (_Minor)) || \
37 (Api->Version.Major == (_Major) && Api->Version.Minor == (_Minor) && Api->Version.Revision < (_Revision))) \
38 { \
39 return WSL_E_PLUGIN_REQUIRES_UPDATE; \
40 }
41
42 struct WSLVersion
43 {
44 uint32_t Major;
45 uint32_t Minor;
46 uint32_t Revision;
47 };
48
49 enum WSLUserConfiguration
50 {
51 None = 0,
52 WSLUserConfigurationCustomKernel = 1,
53 WSLUserConfigurationCustomKernelCommandLine = 2
54 };
55
56 #ifdef __cplusplus
57 DEFINE_ENUM_FLAG_OPERATORS(WSLUserConfiguration);
58 #endif
59
60 struct WSLVmCreationSettings
61 {
62 enum WSLUserConfiguration CustomConfigurationFlags;
63 };
64
65 typedef DWORD WSLSessionId;
66
67 struct WSLSessionInformation
68 {
69 WSLSessionId SessionId;
70 HANDLE UserToken;
71 PSID UserSid;
72 };
73
74 struct WSLDistributionInformation
75 {
76 GUID Id; // Distribution ID, guaranteed to be the same across reboots
77 LPCWSTR Name;
78 uint64_t PidNamespace;
79 LPCWSTR PackageFamilyName; // Package family name, or NULL if none
80 uint32_t InitPid; // Pid of the init process. Introduced in 2.0.5
81 LPCWSTR Flavor; // Type of distribution (ubuntu, debian, ...). Introduced in 2.4.4
82 LPCWSTR Version; // Distribution version. Introduced in 2.4.4
83 };
84
85 struct WslOfflineDistributionInformation
86 {
87 GUID Id; // Distribution ID, guaranteed to be the same across reboots
88 LPCWSTR Name;
89 LPCWSTR PackageFamilyName; // Package family name, or NULL if none
90 LPCWSTR Flavor; // Type of distribution (ubuntu, debian, ...). Introduced in 2.4.4
91 LPCWSTR Version; // Distribution version. Introduced in 2.4.4
92 };
93
94 // Identifies a WSLC session inside the WSLC plugin API. Distinct from WSLSessionId.
95 typedef DWORD WSLCSessionId;
96
97 // Information about a WSLC session passed to plugin notifications.
98 struct WSLCSessionInformation
99 {
100 WSLCSessionId SessionId;
101 LPCWSTR DisplayName;
102 DWORD ApplicationPid;
103 HANDLE UserToken;
104 PSID UserSid;
105 };
106
107 // Opaque handle to a WSLC process created via WSLCPluginAPI_CreateProcess.
108 // Must be released with WSLCPluginAPI_ReleaseProcess.
109 typedef void* WSLCProcessHandle;
110
111 typedef enum _WSLCProcessFd
112 {
113 WSLCProcessFdStdin = 0,
114 WSLCProcessFdStdout = 1,
115 WSLCProcessFdStderr = 2
116 } WSLCProcessFd;
117
118 // Create plan9 mount between Windows & Linux
119 typedef HRESULT (*WSLPluginAPI_MountFolder)(WSLSessionId Session, LPCWSTR WindowsPath, LPCWSTR LinuxPath, BOOL ReadOnly, LPCWSTR Name);
120
121 // Execute a program in the root namespace.
122 // On success, 'Socket' is connected to stdin & stdout (stderr goes to dmesg) // 'Arguments' is expected to be NULL terminated
123 typedef HRESULT (*WSLPluginAPI_ExecuteBinary)(WSLSessionId Session, LPCSTR Path, LPCSTR* Arguments, SOCKET* Socket);
124
125 //
126 // WSLC plugin hooks.
127 //
128
129 // Called when a WSLC session is created. Returning an error prevents the session creation.
130 typedef HRESULT (*WSLPluginAPI_OnSessionCreated)(const struct WSLCSessionInformation* Session);
131
132 // Called when a WSLC session is about to stop. Errors are ignored.
133 typedef HRESULT (*WSLPluginAPI_OnSessionStopping)(const struct WSLCSessionInformation* Session);
134
135 // Called when a container starts. Returning an error prevents the container creation.
136 // 'InspectContainer' is a JSON document that follows the wslc_schema::InspectContainer format.
137 typedef HRESULT (*WSLPluginAPI_ContainerStarted)(const struct WSLCSessionInformation* Session, LPCSTR InspectContainer);
138
139 // Called when a container is about to stop. 'ContainerId' is the container identifier. Errors are ignored.
140 typedef HRESULT (*WSLPluginAPI_ContainerStopping)(const struct WSLCSessionInformation* Session, LPCSTR ContainerId);
141
142 // Called when an image is created (either pulled, or imported). Errors are ignored.
143 // 'InspectImage' is a JSON document that follows the wslc_schema::InspectImage format.
144 // N.B. This callback is currently only invoked when images are pulled or imported. Images created via load or build are not reported.
145 typedef HRESULT (*WSLPluginAPI_ImageCreated)(const struct WSLCSessionInformation* Session, LPCSTR InspectImage);
146
147 // Called when an image is deleted. 'ImageId' is the deleted image identifier. Errors are ignored.
148 typedef HRESULT (*WSLPluginAPI_ImageDeleted)(const struct WSLCSessionInformation* Session, LPCSTR ImageId);
149
150 // Called when the VM backing a WSLC session has started. Unlike OnSessionCreated (which fires once
151 // per session), this fires every time a VM is created for the session: on the first operation that
152 // needs a VM, and again each time the VM is recreated after being idle-terminated. Errors are logged
153 // but ignored (they do not abort VM startup or the triggering operation).
154 typedef HRESULT (*WSLPluginAPI_OnWslcVmStarted)(const struct WSLCSessionInformation* Session);
155
156 // Called when the VM backing a WSLC session is about to stop (idle teardown, explicit termination,
157 // or unexpected exit). Fires exactly once per OnWslcVmStarted. Errors are logged but ignored.
158 //
159 // The VM is still alive for the duration of this call, so a callback may run last-minute work in it
160 // (e.g. WSLCCreateProcess) to react to the VM going away. During a permanent session termination
161 // such a call fails cleanly, because the session itself is being torn down.
162 //
163 // The stop is guaranteed: the VM is torn down as soon as this call returns, and nothing the callback
164 // does can keep it alive. Any work the callback leaves running in the VM -- a process it did not wait
165 // for, for example -- dies with it. Calls made by other threads while this callback is running are
166 // served by the same stopping VM, on the same terms; once the teardown starts they fail with
167 // WSLC_E_VM_NOT_RUNNING rather than waiting for or creating another VM.
168 typedef HRESULT (*WSLPluginAPI_OnWslcVmStopping)(const struct WSLCSessionInformation* Session);
169
170 //
171 // WSLC plugin API calls.
172 //
173 // These operate on the VM that is currently backing the session; they never create one. A call made
174 // while the session has no running VM fails with WSLC_E_VM_NOT_RUNNING, so a plugin that needs a VM
175 // should do its work from OnWslcVmStarted (or before OnWslcVmStopping returns) rather than from a
176 // session-level callback.
177 //
178
179 // Mount a Windows folder into the WSLC session VM at the given 'Mountpoint' path. If the 'Mountpoint' doesn't exist, it will be created.
180 typedef HRESULT (*WSLCPluginAPI_MountFolder)(WSLCSessionId Session, LPCWSTR WindowsPath, LPCSTR Mountpoint, BOOL ReadOnly);
181
182 // Unmount a folder previously mounted via WSLCPluginAPI_MountFolder.
183 typedef HRESULT (*WSLCPluginAPI_UnmountFolder)(WSLCSessionId Session, LPCSTR Mountpoint);
184
185 // Create a process in the WSLC session's root namespace.
186 // 'Arguments' and 'Env' are NULL-terminated arrays. 'Env' may be NULL.
187 // 'Errno' is optional and receives the errno value if the process creation fails.
188 // On success, 'Process' receives an opaque handle that must be released with WSLCPluginAPI_ReleaseProcess.
189 typedef HRESULT (*WSLCPluginAPI_CreateProcess)(
190 WSLCSessionId Session, LPCSTR Executable, LPCSTR* Arguments, LPCSTR* Env, WSLCProcessHandle* Process, int* Errno);
191
192 // Get a stdio handle from a WSLC process. The caller takes ownership and must close it with CloseHandle().
193 typedef HRESULT (*WSLCPluginAPI_ProcessGetFd)(WSLCProcessHandle Process, WSLCProcessFd Fd, HANDLE* Handle);
194
195 // Get the exit event for a WSLC process. Signaled when the process exits.
196 // The caller takes ownership and must close it with CloseHandle().
197 typedef HRESULT (*WSLCPluginAPI_ProcessGetExitEvent)(WSLCProcessHandle Process, HANDLE* ExitEvent);
198
199 // Get the exit code of a WSLC process. The process must have exited.
200 typedef HRESULT (*WSLCPluginAPI_ProcessGetExitCode)(WSLCProcessHandle Process, int* ExitCode);
201
202 // Release a WSLC process handle. All outstanding handles obtained via
203 // WSLCPluginAPI_ProcessGetFd/GetExitEvent must be closed before calling this.
204 typedef void (*WSLCPluginAPI_ReleaseProcess)(WSLCProcessHandle Process);
205
206 // Execute a program in a user distribution
207 // On success, 'Socket' is connected to stdin & stdout (stderr goes to dmesg) // 'Arguments' is expected to be NULL terminated
208 typedef HRESULT (*WSLPluginAPI_ExecuteBinaryInDistribution)(WSLSessionId Session, const GUID* Distribution, LPCSTR Path, LPCSTR* Arguments, SOCKET* Socket);
209
210 // Set the error message to display to the user if the VM or distribution creation fails.
211 // Must be called synchronously in either OnVMStarted() or OnDistributionStarted().
212 typedef HRESULT (*WSLPluginAPI_PluginError)(LPCWSTR UserMessage);
213
214 // Synchronous notifications sent to the plugin
215
216 // Called when the VM has started.
217 // 'Session' and 'UserSettings' are only valid during while the call is in progress.
218 typedef HRESULT (*WSLPluginAPI_OnVMStarted)(const struct WSLSessionInformation* Session, const struct WSLVmCreationSettings* UserSettings);
219
220 // Called when the VM is about to stop.
221 // 'Session' is only valid during while the call is in progress.
222 typedef HRESULT (*WSLPluginAPI_OnVMStopping)(const struct WSLSessionInformation* Session);
223
224 // Called when a distribution has started.
225 // 'Session' and 'Distribution' is only valid during while the call is in progress.
226 typedef HRESULT (*WSLPluginAPI_OnDistributionStarted)(const struct WSLSessionInformation* Session, const struct WSLDistributionInformation* Distribution);
227
228 // Called when a distribution is about to stop.
229 // 'Session' and 'Distribution' is only valid during while the call is in progress.
230 // Note: It's possible that stopping a distribution fails (for instance if a file is in use).
231 // In this case, it's possible for this notification to be called multiple times for the same distribution.
232 typedef HRESULT (*WSLPluginAPI_OnDistributionStopping)(const struct WSLSessionInformation* Session, const struct WSLDistributionInformation* Distribution);
233
234 // Called when a distribution is registered or unregistered.
235 // Returning failure will NOT cause the operation to fail.
236 typedef HRESULT (*WSLPluginAPI_OnDistributionRegistered)(const struct WSLSessionInformation* Session, const struct WslOfflineDistributionInformation* Distribution);
237
238 struct WSLPluginHooksV1
239 {
240 WSLPluginAPI_OnVMStarted OnVMStarted;
241 WSLPluginAPI_OnVMStopping OnVMStopping;
242 WSLPluginAPI_OnDistributionStarted OnDistributionStarted;
243 WSLPluginAPI_OnDistributionStopping OnDistributionStopping;
244 WSLPluginAPI_OnDistributionRegistered OnDistributionRegistered; // Introduced in 2.1.2
245 WSLPluginAPI_OnDistributionRegistered OnDistributionUnregistered; // Introduced in 2.1.2
246
247 // WSLC hooks. Plugins compiled against older headers leave these zero-initialized.
248 WSLPluginAPI_OnSessionCreated OnSessionCreated;
249 WSLPluginAPI_OnSessionStopping OnSessionStopping;
250 WSLPluginAPI_ContainerStarted ContainerStarted;
251 WSLPluginAPI_ContainerStopping ContainerStopping;
252 WSLPluginAPI_ImageCreated ImageCreated;
253 WSLPluginAPI_ImageDeleted ImageDeleted;
254 WSLPluginAPI_OnWslcVmStarted WslcVmStarted; // Introduced in 2.9.5
255 WSLPluginAPI_OnWslcVmStopping WslcVmStopping; // Introduced in 2.9.5
256 };
257
258 struct WSLPluginAPIV1
259 {
260 struct WSLVersion Version;
261 WSLPluginAPI_MountFolder MountFolder;
262 WSLPluginAPI_ExecuteBinary ExecuteBinary;
263 WSLPluginAPI_PluginError PluginError;
264 WSLPluginAPI_ExecuteBinaryInDistribution ExecuteBinaryInDistribution; // Introduced in 2.1.2
265
266 // WSLC API calls.
267 WSLCPluginAPI_MountFolder WSLCMountFolder; // Introduced in 2.9.0
268 WSLCPluginAPI_UnmountFolder WSLCUnmountFolder; // Introduced in 2.9.0
269 WSLCPluginAPI_CreateProcess WSLCCreateProcess; // Introduced in 2.9.0
270 WSLCPluginAPI_ProcessGetFd WSLCProcessGetFd; // Introduced in 2.9.0
271 WSLCPluginAPI_ProcessGetExitEvent WSLCProcessGetExitEvent; // Introduced in 2.9.0
272 WSLCPluginAPI_ProcessGetExitCode WSLCProcessGetExitCode; // Introduced in 2.9.0
273 WSLCPluginAPI_ReleaseProcess WSLCReleaseProcess; // Introduced in 2.9.0
274 };
275
276 typedef HRESULT (*WSLPluginAPI_EntryPointV1)(const struct WSLPluginAPIV1* Api, struct WSLPluginHooksV1* Hooks);
277
278 #ifdef __cplusplus
279 }
280 #endif