master
h 892 lines 31.1 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 LxssUserSession.h
8
9 Abstract:
10
11 This file contains session function declarations.
12
13 --*/
14
15 #pragma once
16
17 #include "LxssPort.h"
18 #include "LxssMessagePort.h"
19 #include "LxssCreateProcess.h"
20 #include "filesystem.hpp"
21 #include "LxssHttpProxy.h"
22 #include "WslCoreVm.h"
23 #include "PluginManager.h"
24 #include "Lifetime.h"
25 #include "DistributionRegistration.h"
26
27 #define WSL_NEW_DISTRO_LXFS L"NewDistributionLxFs"
28 #define WSL_DISTRO_CONFIG_DEFAULT_UID L"DefaultUid"
29
30 #define LXSS_DELETE_DISTRO_FLAGS_ROOTFS 0x1
31 #define LXSS_DELETE_DISTRO_FLAGS_VHD 0x2
32 #define LXSS_DELETE_DISTRO_FLAGS_WSLG_SHORTCUTS 0x4
33 #define LXSS_DELETE_DISTRO_FLAGS_SHORTCUTS 0x8
34 #define LXSS_DELETE_DISTRO_FLAGS_UNMOUNT 0x10
35 #define LXSS_DELETE_DISTRO_FLAGS_ALL \
36 (LXSS_DELETE_DISTRO_FLAGS_ROOTFS | LXSS_DELETE_DISTRO_FLAGS_VHD | LXSS_DELETE_DISTRO_FLAGS_WSLG_SHORTCUTS | \
37 LXSS_DELETE_DISTRO_FLAGS_SHORTCUTS | LXSS_DELETE_DISTRO_FLAGS_UNMOUNT)
38
39 class ConsoleManager;
40 class LxssRunningInstance;
41 class WslCoreVm;
42 class LxssUserSessionImpl;
43
44 typedef struct _LXSS_RUN_ELF_CONTEXT
45 {
46 wil::unique_event instanceTerminatedEvent;
47 wil::unique_handle instanceHandle;
48 } LXSS_RUN_ELF_CONTEXT, *PLXSS_RUN_ELF_CONTEXT;
49
50 typedef struct _LXSS_VM_MODE_SETUP_CONTEXT
51 {
52 wil::unique_socket tarSocket;
53 wil::unique_socket errorSocket;
54 std::shared_ptr<LxssRunningInstance> instance;
55 } LXSS_VM_MODE_SETUP_CONTEXT, *PLXSS_VM_MODE_SETUP_CONTEXT;
56
57 enum class ShutdownBehavior
58 {
59 Wait,
60 Force,
61 ForceAfter30Seconds
62 };
63
64 /// <summary>
65 /// Each COM client gets a unique LxssUserSession object which contains a std::weak_ptr to a LxssUserSessionImpl for that user.
66 /// </summary>
67
68 class DECLSPEC_UUID("a9b7a1b9-0671-405c-95f1-e0612cb4ce7e") LxssUserSession
69 : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ILxssUserSession, IWslSupport, IFastRundown>
70 {
71 public:
72 LxssUserSession(_In_ const std::weak_ptr<LxssUserSessionImpl>& Session);
73 LxssUserSession(const LxssUserSession&) = delete;
74 LxssUserSession& operator=(const LxssUserSession&) = delete;
75
76 /// <summary>
77 /// Configures a distribution.
78 /// </summary>
79 IFACEMETHOD(ConfigureDistribution)(_In_opt_ LPCGUID DistroGuid, _In_ ULONG DefaultUid, _In_ ULONG Flags, _Out_ LXSS_ERROR_INFO* Error) override;
80
81 /// <summary>
82 /// Creates an instance of the specified distro. The method blocks until the
83 /// new instance is started.
84 /// </summary>
85 IFACEMETHOD(CreateInstance)(_In_opt_ LPCGUID DistroGuid, _In_ ULONG Flags, _Out_ LXSS_ERROR_INFO* Error) override;
86
87 /// <summary>
88 /// Create a Linux process.
89 /// </summary>
90 IFACEMETHOD(CreateLxProcess)(
91 _In_opt_ LPCGUID DistroGuid,
92 _In_opt_ LPCSTR Filename,
93 _In_ ULONG CommandLineCount,
94 _In_reads_opt_(CommandLineCount) LPCSTR* CommandLine,
95 _In_opt_ LPCWSTR CurrentWorkingDirectory,
96 _In_opt_ LPCWSTR NtPath,
97 _In_reads_opt_(NtEnvironmentLength) PWCHAR NtEnvironment,
98 _In_ ULONG NtEnvironmentLength,
99 _In_opt_ LPCWSTR Username,
100 _In_ SHORT Columns,
101 _In_ SHORT Rows,
102 _In_ ULONG ConsoleHandle,
103 _In_ PLXSS_STD_HANDLES StdHandles,
104 _In_ ULONG Flags,
105 _Out_ GUID* DistributionId,
106 _Out_ GUID* InstanceId,
107 _Out_ HANDLE* ProcessHandle,
108 _Out_ HANDLE* ServerHandle,
109 _Out_ HANDLE* StandardIn,
110 _Out_ HANDLE* StandardOut,
111 _Out_ HANDLE* StandardErr,
112 _Out_ HANDLE* CommunicationChannel,
113 _Out_ HANDLE* InteropSocket,
114 _Out_ LXSS_ERROR_INFO* Error) override;
115
116 /// <summary>
117 /// Enumerates all registered distributions.
118 /// </summary>
119 IFACEMETHOD(EnumerateDistributions)(_Out_ PULONG DistributionCount, _Out_ LXSS_ENUMERATE_INFO** Distributions, _Out_ LXSS_ERROR_INFO* Error) override;
120
121 /// <summary>
122 /// Exports a distribution from to tar file.
123 /// </summary>
124 IFACEMETHOD(ExportDistribution)(
125 _In_opt_ LPCGUID DistroGuid, _In_ HANDLE FileHandle, _In_ HANDLE ErrorHandle, _In_ ULONG Flags, _Out_ LXSS_ERROR_INFO* Error) override;
126
127 /// <summary>
128 /// Exports a distribution to a pipe.
129 /// </summary>
130 IFACEMETHOD(ExportDistributionPipe)(
131 _In_opt_ LPCGUID DistroGuid, _In_ HANDLE PipeHandle, _In_ HANDLE ErrorHandle, _In_ ULONG Flags, _Out_ LXSS_ERROR_INFO* Error) override;
132
133 /// <summary>
134 /// Queries the default distribution.
135 /// </summary>
136 IFACEMETHOD(GetDefaultDistribution)(_Out_ LXSS_ERROR_INFO* Error, _Out_ LPGUID DefaultDistribution) override;
137
138 /// <summary>
139 /// Returns the configuration for the specified distribution.
140 /// </summary>
141 IFACEMETHOD(GetDistributionConfiguration)(
142 _In_opt_ LPCGUID DistroGuid,
143 _Out_ LPWSTR* DistributionName,
144 _Out_ ULONG* Version,
145 _Out_ ULONG* DefaultUid,
146 _Out_ ULONG* DefaultEnvironmentCount,
147 _Out_ LPSTR** DefaultEnvironment,
148 _Out_ ULONG* Flags,
149 _Out_ LXSS_ERROR_INFO* Error) override;
150
151 /// <summary>
152 /// Returns the GUID of a distribution with the specified name.
153 /// </summary>
154 IFACEMETHOD(GetDistributionId)(_In_ LPCWSTR DistributionName, _In_ ULONG Flags, _Out_ LXSS_ERROR_INFO* Error, _Out_ GUID* pDistroGuid) override;
155
156 /// <summary>
157 /// Registers a distribution from a tar file.
158 /// </summary>
159 IFACEMETHOD(RegisterDistribution)(
160 _In_ LPCWSTR DistributionName,
161 _In_ ULONG Version,
162 _In_ HANDLE FileHandle,
163 _In_ HANDLE ErrorHandle,
164 _In_ LPCWSTR TargetDirectory,
165 _In_ ULONG Flags,
166 _In_ ULONG64 VhdSize,
167 _In_opt_ LPCWSTR PackageFamilyName,
168 _Out_ LPWSTR* InstalledDistributionName,
169 _Out_ LXSS_ERROR_INFO* Error,
170 _Out_ GUID* pDistroGuid) override;
171
172 /// <summary>
173 /// Registers a distribution from a pipe.
174 /// </summary>
175 IFACEMETHOD(RegisterDistributionPipe)(
176 _In_ LPCWSTR DistributionName,
177 _In_ ULONG Version,
178 _In_ HANDLE PipeHandle,
179 _In_ HANDLE ErrorHandle,
180 _In_ LPCWSTR TargetDirectory,
181 _In_ ULONG Flags,
182 _In_ ULONG64 VhdSize,
183 _In_opt_ LPCWSTR PackageFamilyName,
184 _Out_ LPWSTR* InstalledDistributionName,
185 _Out_ LXSS_ERROR_INFO* Error,
186 _Out_ GUID* pDistroGuid) override;
187
188 /// <summary>
189 /// Resizes the virtual disk of a distribution.
190 /// </summary>
191 IFACEMETHOD(ResizeDistribution)(_In_ LPCGUID DistroGuid, _In_ HANDLE OutputHandle, _In_ ULONG64 NewSize, _Out_ LXSS_ERROR_INFO* Error) override;
192
193 /// <summary>
194 /// Compacts the virtual disk of a distribution.
195 /// </summary>
196 IFACEMETHOD(CompactDistribution)(_In_ LPCGUID DistroGuid, _Out_ LXSS_ERROR_INFO* Error) override;
197
198 /// <summary>
199 /// Sets the default distribution.
200 /// </summary>
201 IFACEMETHOD(SetDefaultDistribution)(_In_ LPCGUID DistroGuid, _Out_ LXSS_ERROR_INFO* Error) override;
202
203 /// <summary>
204 /// Sets or unsets the sparse flag for a distribution.
205 /// </summary>
206 IFACEMETHOD(SetSparse)(_In_ LPCGUID DistroGuid, _In_ BOOLEAN Sparse, _In_ BOOLEAN AllowUnsafe, _Out_ LXSS_ERROR_INFO* Error) override;
207
208 /// <summary>
209 /// Sets the version for a distribution.
210 /// </summary>
211 IFACEMETHOD(SetVersion)(_In_ LPCGUID DistroGuid, _In_ ULONG Version, _In_ HANDLE StdErrHandle, _Out_ LXSS_ERROR_INFO* Error) override;
212
213 /// <summary>
214 /// Pass through a disk to the utility VM.
215 /// </summary>
216 IFACEMETHOD(AttachDisk)(_In_ LPCWSTR Disk, _In_ ULONG Flags, _Out_ LXSS_ERROR_INFO* Error) override;
217
218 /// <summary>
219 /// Detach a passthrough disk from the utility VM.
220 /// </summary>
221 IFACEMETHOD(DetachDisk)(_In_ LPCWSTR Disk, _Out_ int* Result, _Out_ int* Step, _Out_ LXSS_ERROR_INFO* Error) override;
222
223 /// <summary>
224 /// Mount a disk.
225 /// </summary>
226 IFACEMETHOD(MountDisk)(
227 _In_ LPCWSTR Disk,
228 _In_ ULONG Flags,
229 _In_ ULONG PartitionIndex,
230 _In_opt_ LPCWSTR Name,
231 _In_opt_ LPCWSTR Type,
232 _In_opt_ LPCWSTR Options,
233 _Out_ int* Result,
234 _Out_ int* Step,
235 _Out_ LPWSTR* MountName,
236 _Out_ LXSS_ERROR_INFO* Error) override;
237
238 /// <summary>
239 /// Move a distribution to a new location
240 /// </summary>
241 IFACEMETHOD(MoveDistribution)(_In_ LPCGUID DistroGuid, _In_ LPCWSTR Location, _Out_ LXSS_ERROR_INFO* Error) override;
242
243 /// <summary>
244 /// Terminates all running instances and the Linux utility vm.
245 /// </summary>
246 IFACEMETHOD(Shutdown)() override;
247 IFACEMETHOD(Shutdown)(_In_ BOOL Force);
248
249 /// <summary>
250 /// Imports a distribution inplace.
251 /// </summary>
252 IFACEMETHOD(ImportDistributionInplace)(_In_ LPCWSTR DistributionName, _In_ LPCWSTR VhdPath, _Out_ LXSS_ERROR_INFO* Error, _Out_ GUID* pDistroGuid) override;
253
254 /// <summary>
255 /// Terminates a distribution by it's client identifier.
256 /// </summary>
257 void TerminateByClientId(_In_ ULONG ClientId);
258
259 /// <summary>
260 /// Sets the execution state of this instance.
261 /// </summary>
262 IFACEMETHOD(TerminateDistribution)(_In_opt_ LPCGUID DistroGuid, _Out_ LXSS_ERROR_INFO* Error) override;
263
264 /// <summary>
265 /// Unregisters a distribution.
266 /// </summary>
267 IFACEMETHOD(UnregisterDistribution)(_In_ LPCGUID DistroGuid, _Out_ LXSS_ERROR_INFO* Error) override;
268
269 // IWslSupport methods.
270
271 /// <summary>
272 /// Registers a distribution.
273 /// </summary>
274 HRESULT RegisterDistribution(
275 _Inout_ LPCWSTR DistributionName, _In_ ULONG Version, _In_opt_ HANDLE TarGzFile, _In_opt_ HANDLE TarGzPipe, _In_ LPCWSTR TargetDirectory) override;
276
277 /// <summary>
278 /// Unregisters a distribution.
279 /// </summary>
280 HRESULT
281 UnregisterDistribution(_In_ LPCWSTR DistributionName) override;
282
283 /// <summary>
284 /// Returns the configuration for the specified distribution.
285 /// </summary>
286 HRESULT GetDistributionConfiguration(
287 _In_ LPCWSTR DistributionName,
288 _Out_ ULONG* Version,
289 _Out_ ULONG* DefaultUid,
290 _Out_ ULONG* DefaultEnvironmentCount,
291 _Out_ LPSTR** DefaultEnvironment,
292 _Out_ ULONG* WslFlags) override;
293
294 /// <summary>
295 /// Configures a distribution.
296 /// </summary>
297 HRESULT SetDistributionConfiguration(_In_ LPCWSTR DistributionName, _In_ ULONG DefaultUid, _In_ ULONG WslFlags) override;
298
299 /// <summary>
300 /// Returns a list of runnable distributions.
301 /// </summary>
302 HRESULT ListDistributions(_Out_ ULONG* Count, _Out_ LPWSTR** Distributions) override;
303
304 /// <summary>
305 /// Creates an instance of the specified distro.
306 /// </summary>
307 HRESULT CreateInstance(_In_ LPCWSTR DistributionName, _In_ ULONG Flags) override;
308
309 private:
310 std::weak_ptr<LxssUserSessionImpl> m_session;
311 };
312
313 /// <summary>
314 /// Each user gets its own LxssUserSessionImpl object, This object manages the lifetime of running instances.
315 /// </summary>
316 class LxssUserSessionImpl : public std::enable_shared_from_this<LxssUserSessionImpl>
317 {
318 public:
319 LxssUserSessionImpl(_In_ PSID userSid, _In_ DWORD sessionId, _Inout_ wsl::windows::service::PluginManager& pluginManager);
320 virtual ~LxssUserSessionImpl();
321 LxssUserSessionImpl(const LxssUserSessionImpl&) = delete;
322 LxssUserSessionImpl& operator=(const LxssUserSessionImpl&) = delete;
323
324 /// <summary>
325 /// Configures a distribution.
326 /// </summary>
327 HRESULT
328 ConfigureDistribution(_In_opt_ LPCGUID DistroGuid, _In_ ULONG DefaultUid, _In_ ULONG Flags);
329
330 /// <summary>
331 /// Creates an instance of the specified distro. The method blocks until the
332 /// new instance is started.
333 /// </summary>
334 HRESULT
335 CreateInstance(_In_opt_ LPCGUID DistroGuid, _In_ ULONG Flags);
336
337 /// <summary>
338 /// Create a Linux process.
339 /// </summary>
340 HRESULT
341 CreateLxProcess(
342 _In_opt_ LPCGUID DistroGuid,
343 _In_opt_ LPCSTR Filename,
344 _In_ ULONG CommandLineCount,
345 _In_reads_opt_(CommandLineCount) LPCSTR* CommandLine,
346 _In_opt_ LPCWSTR CurrentWorkingDirectory,
347 _In_opt_ LPCWSTR NtPath,
348 _In_reads_opt_(NtEnvironmentLength) PWCHAR NtEnvironment,
349 _In_ ULONG NtEnvironmentLength,
350 _In_opt_ LPCWSTR Username,
351 _In_ SHORT Columns,
352 _In_ SHORT Rows,
353 _In_ HANDLE ConsoleHandle,
354 _In_ PLXSS_STD_HANDLES StdHandles,
355 _In_ ULONG Flags,
356 _Out_ GUID* DistributionId,
357 _Out_ GUID* InstanceId,
358 _Out_ HANDLE* ProcessHandle,
359 _Out_ HANDLE* ServerHandle,
360 _Out_ HANDLE* StandardIn,
361 _Out_ HANDLE* StandardOut,
362 _Out_ HANDLE* StandardErr,
363 _Out_ HANDLE* CommunicationChannel,
364 _Out_ HANDLE* InteropSocket);
365
366 /// <summary>
367 /// Clears the state of an attached disk in the registry
368 /// </summary>
369 void ClearDiskStateInRegistry(_In_opt_ LPCWSTR Disk);
370
371 /// <summary>
372 /// Start a process in the root namespace or in a user distribution.
373 /// </summary>
374 HRESULT CreateLinuxProcess(_In_opt_ const GUID* Distro, _In_ LPCSTR Path, _In_ LPCSTR* Arguments, _Out_ SOCKET* socket);
375
376 /// <summary>
377 /// Enumerates registered distributions, optionally including ones that are
378 /// currently being registered, unregistered, or converted.
379 /// </summary>
380 HRESULT
381 EnumerateDistributions(_Out_ PULONG DistributionCount, _Out_ LXSS_ENUMERATE_INFO** Distributions);
382
383 /// <summary>
384 /// Exports a distribution.
385 /// </summary>
386 HRESULT
387 ExportDistribution(_In_opt_ LPCGUID DistroGuid, _In_ HANDLE FileHandle, _In_ HANDLE ErrorHandle, _In_ ULONG Flags);
388
389 /// <summary>
390 /// Queries the default distribution.
391 /// </summary>
392 HRESULT
393 GetDefaultDistribution(_Out_ LPGUID DefaultDistribution);
394
395 /// <summary>
396 /// Returns the configuration for the specified distribution.
397 /// </summary>
398 HRESULT
399 GetDistributionConfiguration(
400 _In_opt_ LPCGUID DistroGuid,
401 _Out_ LPWSTR* DistributionName,
402 _Out_ ULONG* Version,
403 _Out_ ULONG* DefaultUid,
404 _Out_ ULONG* DefaultEnvironmentCount,
405 _Out_ LPSTR** DefaultEnvironment,
406 _Out_ ULONG* Flags);
407
408 /// <summary>
409 /// Returns the GUID of a distribution with the specified name.
410 /// </summary>
411 HRESULT
412 GetDistributionId(_In_ LPCWSTR DistributionName, _In_ ULONG Flags, _Out_ GUID* pDistroGuid);
413
414 /// <summary>
415 /// Returns the session cookie
416 /// </summary>
417 DWORD GetSessionCookie() const;
418
419 /// <summary>
420 /// Returns the session ID of the user.
421 /// </summary>
422 DWORD GetSessionId() const;
423
424 /// <summary>
425 /// Returns the sid for the user session.
426 /// </summary>
427 PSID GetUserSid();
428
429 /// <summary>
430 /// Imports a distribution inplace.
431 /// </summary>
432 HRESULT
433 ImportDistributionInplace(_In_ LPCWSTR DistributionName, _In_ LPCWSTR VhdPath, _Out_ GUID* pDistroGuid);
434
435 /// <summary>
436 /// Mount a disk.
437 /// </summary>
438 HRESULT MountDisk(
439 _In_ LPCWSTR Disk,
440 _In_ ULONG Flags,
441 _In_ ULONG PartitionIndex,
442 _In_opt_ LPCWSTR Name,
443 _In_opt_ LPCWSTR Type,
444 _In_opt_ LPCWSTR Options,
445 _Out_ int* Result,
446 _Out_ int* Step,
447 _Out_ LPWSTR* MountName);
448
449 HRESULT MoveDistribution(_In_ LPCGUID DistroGuid, _In_ LPCWSTR Location);
450
451 HRESULT MountRootNamespaceFolder(_In_ LPCWSTR HostPath, _In_ LPCWSTR GuestPath, _In_ bool ReadOnly, _In_ LPCWSTR Name);
452
453 /// <summary>
454 /// Registers a distribution.
455 /// </summary>
456 HRESULT
457 RegisterDistribution(
458 _In_ LPCWSTR DistributionName,
459 _In_ ULONG Version,
460 _In_ HANDLE FileHandle,
461 _In_ HANDLE ErrorHandle,
462 _In_ LPCWSTR TargetDirectory,
463 _In_ ULONG Flags,
464 _In_ ULONG64 VhdSize,
465 _In_opt_ LPCWSTR PackageFamilyName,
466 _Out_opt_ LPWSTR* InstalledDistributionName,
467 _Out_ GUID* pDistroGuid);
468
469 /// <summary>
470 /// Resizes the disk of a distribution.
471 /// </summary>
472 HRESULT
473 ResizeDistribution(_In_ LPCGUID DistroGuid, _In_ HANDLE OutputHandle, _In_ ULONG64 NewSize);
474
475 /// <summary>
476 /// Compacts the disk of a distribution.
477 /// </summary>
478 HRESULT
479 CompactDistribution(_In_ LPCGUID DistroGuid);
480
481 /// <summary>
482 /// Sets the default distribution.
483 /// </summary>
484 HRESULT
485 SetDefaultDistribution(_In_ LPCGUID DistroGuid);
486
487 /// <summary>
488 /// Marks/unmarks the backing vhdx as sparse.
489 /// </summary>
490 HRESULT
491 SetSparse(_In_ LPCGUID DistroGuid, _In_ BOOLEAN Sparse, _In_ BOOLEAN AllowUnsafe);
492
493 /// <summary>
494 /// Sets the version for a distribution.
495 /// </summary>
496 HRESULT
497 SetVersion(_In_ LPCGUID DistroGuid, _In_ ULONG Version, _In_ HANDLE StdErrHandle);
498
499 /// <summary>
500 /// Pass through a disk to the utility VM.
501 /// </summary>
502 HRESULT AttachDisk(_In_ LPCWSTR Disk, _In_ ULONG Flags);
503
504 /// <summary>
505 /// Detach a passthrough disk from the utility VM.
506 /// </summary>
507 HRESULT DetachDisk(_In_ LPCWSTR Disk, _Out_ int* Result, _Out_ int* Step);
508
509 /// <summary>
510 /// Terminates all running instances and the Linux utility vm.
511 /// </summary>
512 HRESULT Shutdown(_In_ bool PreventNewInstances = false, ShutdownBehavior Behavior = ShutdownBehavior::Wait);
513
514 /// <summary>
515 /// Worker thread for logging telemetry about processes running inside of WSL.
516 /// </summary>
517 void TelemetryWorker(_In_ wil::unique_socket&& socket) const;
518
519 /// <summary>
520 /// Terminates a distribution by it's client identifier.
521 /// </summary>
522 void TerminateByClientId(_In_ ULONG ClientId);
523
524 /// <summary>
525 /// Terminates a distribution by it's client identifier (assumes lock is held).
526 /// </summary>
527 void TerminateByClientIdLockHeld(_In_ ULONG ClientId);
528
529 /// <summary>
530 /// Sets the execution state of this instance.
531 /// </summary>
532 HRESULT
533 TerminateDistribution(_In_opt_ LPCGUID DistroGuid);
534
535 /// <summary>
536 /// Unregisters a distribution.
537 /// </summary>
538 HRESULT
539 UnregisterDistribution(_In_ LPCGUID DistroGuid);
540
541 /// <summary>
542 /// Queries a distribution's default UID, default environment, and flags.
543 /// </summary>
544 static CreateLxProcessContext s_GetCreateProcessContext(_In_ const GUID& DistroGuid, _In_ bool SystemDistro);
545
546 private:
547 /// <summary>
548 /// Adds a distro to the list of converting distros.
549 /// </summary>
550 _Requires_lock_held_(m_instanceLock)
551 void _ConversionBegin(_In_ GUID DistroGuid, _In_ LxssDistributionState State);
552
553 /// <summary>
554 /// Removes a distro from the list of converting distros and checks if the
555 /// Linux utility VM is idle.
556 /// </summary>
557 _Requires_lock_not_held_(m_instanceLock)
558 void _ConversionComplete(_In_ GUID DistroGuid);
559
560 /// <summary>
561 /// Creates a distribution registration for legacy installs.
562 /// </summary>
563 _Requires_exclusive_lock_held_(m_instanceLock)
564 void _CreateLegacyRegistration(_In_ HKEY LxssKey, _In_ HANDLE UserToken);
565
566 /// <summary>
567 /// Creates the set of WSL mounts required for setup and ext4 conversion.
568 /// </summary>
569 static std::vector<wsl::windows::common::filesystem::unique_lxss_addmount> _CreateSetupMounts(_In_ const LXSS_DISTRO_CONFIGURATION& Configuration);
570
571 /// <summary>
572 /// Creates and initializes a utility VM. If a VM is already running, the
573 /// running VM is returned.
574 /// </summary>
575 _Requires_lock_not_held_(m_instanceLock)
576 std::shared_ptr<LxssRunningInstance> _CreateInstance(_In_opt_ LPCGUID DistroGuid, _In_ ULONG Flags = LXSS_CREATE_INSTANCE_FLAGS_ALLOW_FS_UPGRADE);
577
578 static void _CreateDistributionShortcut(
579 _In_ LPCWSTR DistributionName, LPCWSTR Shortcut, LPCWSTR ExecutablePath, wsl::windows::service::DistributionRegistration& registration);
580
581 static void _CreateTerminalProfile(
582 _In_ const std::string_view& Template,
583 _In_ const std::filesystem::path& IconPath,
584 _In_ const LXSS_DISTRO_CONFIGURATION& Configuration,
585 wsl::windows::service::DistributionRegistration& Registration);
586
587 /// <summary>
588 /// Ensures that the utility VM has been created.
589 /// </summary>
590 _Requires_exclusive_lock_held_(m_instanceLock)
591 void _CreateVm();
592
593 /// <summary>
594 /// Deletes distribution filesystem.
595 /// </summary>
596 void _DeleteDistribution(_In_ const LXSS_DISTRO_CONFIGURATION& Configuration, _In_ ULONG Flags = LXSS_DELETE_DISTRO_FLAGS_ALL);
597
598 /// <summary>
599 /// Deletes distribution filesystem.
600 /// </summary>
601 _Requires_exclusive_lock_held_(m_instanceLock)
602 void _DeleteDistributionLockHeld(_In_ const LXSS_DISTRO_CONFIGURATION& Configuration, _In_ ULONG Flags = LXSS_DELETE_DISTRO_FLAGS_ALL) const;
603
604 /// <summary>
605 /// Enumerates and validates all registered distributions for the calling
606 /// process. If ListAll is true this will return all distributions including
607 /// those that are in the progress of being installed or uninstalled.
608 /// </summary>
609 _Requires_exclusive_lock_held_(m_instanceLock)
610 std::vector<wsl::windows::service::DistributionRegistration> _EnumerateDistributions(
611 _In_ HKEY LxssKey, _In_ bool ListAll = false, _In_ const std::optional<GUID>& Exclude = {});
612
613 /// <summary>
614 /// Validates that the specified distribution is not currently performing
615 /// a filesystem conversion.
616 /// </summary>
617 _Requires_lock_held_(m_instanceLock)
618 void _EnsureNotLocked(_In_ LPCGUID DistroGuid, const std::source_location& location = std::source_location::current());
619
620 /// <summary>
621 /// Queries the GUID of the default distribution for the calling process.
622 /// </summary>
623 _Requires_exclusive_lock_held_(m_instanceLock)
624 GUID _GetDefaultDistro(_In_ HKEY LxssKey);
625
626 /// <summary>
627 /// Waits for the elf binary to exit and returns the exit status.
628 /// </summary>
629 static LONG _GetElfExitStatus(_In_ const LXSS_RUN_ELF_CONTEXT& Context);
630
631 /// <summary>
632 /// Return a new config after policies have been applied.
633 /// </summary>
634 wsl::core::Config _GetResultantConfig(_In_ const HANDLE userToken);
635
636 _Requires_exclusive_lock_held_(m_instanceLock)
637 void _LoadDiskMount(_In_ HKEY Key, _In_ const std::wstring& LunStr) const;
638
639 _Requires_exclusive_lock_held_(m_instanceLock)
640 void _LoadDiskMounts();
641
642 _Requires_exclusive_lock_held_(m_instanceLock)
643 void _LoadNetworkingSettings(_Inout_ wsl::core::Config& config, _In_ HANDLE userToken);
644
645 void _ProcessImportResultMessage(
646 const LX_MINI_INIT_IMPORT_RESULT& message,
647 const gsl::span<gsl::byte> span,
648 HKEY LxssKey,
649 LXSS_DISTRO_CONFIGURATION& configuration,
650 wsl::windows::service::DistributionRegistration& registration);
651
652 /// <summary>
653 /// Runs a single ELF binary without using the init daemon.
654 /// </summary>
655 static LXSS_RUN_ELF_CONTEXT _RunElfBinary(
656 _In_ LPCSTR CommandLine,
657 _In_ LPCWSTR TargetDirectory,
658 _In_ HANDLE ClientProcess,
659 _In_opt_ HANDLE StdIn = nullptr,
660 _In_opt_ HANDLE StdOut = nullptr,
661 _In_opt_ HANDLE StdErr = nullptr,
662 _In_opt_count_(NumMounts) PLX_KMAPPATHS_ADDMOUNT Mounts = nullptr,
663 _In_opt_ ULONG NumMounts = 0);
664
665 /// <summary>
666 /// Returns the currently running utility vm, if one exists.
667 /// </summary>
668 _Requires_lock_held_(m_instanceLock)
669 std::shared_ptr<LxssRunningInstance> _RunningInstance(_In_ LPCGUID DistroGuid);
670
671 /// <summary>
672 /// Creates a utility VM to perform a setup operation.
673 /// </summary>
674 LXSS_VM_MODE_SETUP_CONTEXT
675 _RunUtilityVmSetup(_In_ const LXSS_DISTRO_CONFIGURATION& Configuration, _In_ LX_MESSAGE_TYPE MessageType, _In_ ULONG ExportFlags = 0, _In_ bool SetVersion = false);
676
677 void _SendDistributionRegisteredEvent(_In_ const LXSS_DISTRO_CONFIGURATION& Configuration) const;
678
679 /// <summary>
680 /// Set the specified distribution as installed. If there is no default distribution
681 /// this routine also marks this distribution as the default.
682 /// </summary>
683 _Requires_lock_held_(m_instanceLock)
684 static void _SetDistributionInstalled(_In_ HKEY LxssKey, _In_ const GUID& DistroGuid);
685
686 /// <summary>
687 /// Removes a utility vm from the list.
688 /// </summary>
689 _Requires_lock_not_held_(m_instanceLock)
690 bool _TerminateInstance(_In_ LPCGUID DistroGuid, _In_ bool CheckForClients);
691
692 _Requires_exclusive_lock_held_(m_instanceLock)
693 bool _TerminateInstanceInternal(_In_ LPCGUID DistroGuid, _In_ bool CheckForClients = false);
694
695 /// <summary>
696 /// Ensures the WSL1 init binary is up-to-date.
697 /// </summary>
698 wil::srwlock m_initUpdateLock;
699 _Guarded_by_(m_initUpdateLock) std::vector<GUID> m_updatedInitDistros;
700 void _UpdateInit(_In_ const LXSS_DISTRO_CONFIGURATION& Configuration);
701
702 /// <summary>
703 /// Unregisters the specified distribution.
704 /// </summary>
705 _Requires_exclusive_lock_held_(m_instanceLock)
706 void _UnregisterDistributionLockHeld(_In_ HKEY LxssKey, _In_ const LXSS_DISTRO_CONFIGURATION& Configuration);
707
708 /// <summary>
709 /// Updates timezone information for each running instance and utility VM.
710 /// </summary>
711 void _TimezoneUpdated();
712
713 /// <summary>
714 /// Validates if the package for a specified distribution is still installed.
715 /// </summary>
716 _Requires_lock_held_(m_instanceLock)
717 static bool _ValidateDistro(_In_ HKEY LxssKey, _In_ LPCGUID DistroGuid);
718
719 /// <summary>
720 /// Validates that the given path or name is not already in use by a registered distribution.
721 /// </summary>
722 _Requires_lock_held_(m_instanceLock)
723 void _ValidateDistributionNameAndPathNotInUse(
724 _In_ HKEY LxssKey, _In_opt_ LPCWSTR Path, _In_opt_ LPCWSTR Name, const std::optional<GUID>& Exclude = {});
725
726 /// <summary>
727 /// Queues a threadpool timer to terminate an idle utility VM.
728 /// </summary>
729 _Requires_exclusive_lock_held_(m_instanceLock)
730 void _VmCheckIdle();
731
732 /// <summary>
733 /// Terminate the Linux utility VM if there are no running distros.
734 /// </summary>
735 _Requires_lock_not_held_(m_instanceLock)
736 void _VmIdleTerminate();
737
738 /// <summary>
739 /// Queries if the Linux utility VM has any running distros.
740 /// </summary>
741 _Requires_exclusive_lock_held_(m_instanceLock)
742 bool _VmIsIdle();
743
744 /// <summary>
745 /// Terminates the Linux utility VM.
746 /// </summary>
747 _Requires_exclusive_lock_held_(m_instanceLock)
748 void _VmTerminate();
749
750 /// <summary>
751 /// Configures HttpProxy info for the process
752 /// </summary>
753 void _SetHttpProxyInfo(_Inout_ std::vector<std::string>& environment) const noexcept;
754
755 /// <summary>
756 /// Launch OOBE for the first time or skip.
757 /// </summary>
758 void _LaunchOOBEIfNeeded() noexcept;
759
760 /// <summary>
761 /// Inputs proxy environment values into an environment if they're not already present.
762 /// </summary>
763 static void s_AddHttpProxyToEnvironment(_In_ const HttpProxySettings& proxySettings, _Inout_ std::vector<std::string>& environment) noexcept;
764
765 /// <summary>
766 /// Query information about a distribution config.
767 /// </summary>
768 static LXSS_DISTRO_CONFIGURATION s_GetDistributionConfiguration(const wsl::windows::service::DistributionRegistration& Distro, bool skipName = false);
769
770 /// <summary>
771 /// Impersonate the specified user and open the lxss registry key.
772 /// </summary>
773 static wil::unique_hkey s_OpenLxssUserKey(_In_ HANDLE UserToken);
774
775 static LX_INIT_DRVFS_MOUNT s_InitializeDrvFs(_In_ const std::weak_ptr<LxssUserSessionImpl>& Session, _In_ const GUID& VmId, _In_ HANDLE UserToken) noexcept;
776
777 /// <summary>
778 /// Ensures the distribution name is valid.
779 /// </summary>
780 static void s_ValidateDistroName(_In_ LPCWSTR Name);
781
782 /// <summary>
783 /// Callback for when a VM unexpectedly exits (crashes).
784 /// </summary>
785 static void s_VmTerminated(_Inout_ LxssUserSessionImpl* UserSession, _In_ const GUID& VmId);
786
787 /// <summary>
788 /// Callback to terminate a utility VM.
789 /// </summary>
790 static bool s_TerminateInstance(_Inout_ LxssUserSessionImpl* UserSession, _In_ GUID DistroGuid, _In_ bool CheckForClients);
791
792 /// <summary>
793 /// Ensures that the init binary for the specified distribution is up-to-date.
794 /// </summary>
795 static void s_UpdateInit(_Inout_ LxssUserSessionImpl* UserSession, _In_ const LXSS_DISTRO_CONFIGURATION& Configuration);
796
797 /// <summary>
798 /// Callback to determine if the Linux VM can terminate.
799 /// </summary>
800 static VOID CALLBACK s_VmIdleTerminate(_Inout_ PTP_CALLBACK_INSTANCE, _Inout_opt_ PVOID Context, _Inout_ PTP_TIMER Timer);
801
802 static LRESULT CALLBACK s_TimezoneWindowProc(HWND windowHandle, UINT messageCode, WPARAM wParameter, LPARAM lParameter);
803
804 /// <summary>
805 /// Lock for protecting various lists.
806 /// </summary>
807 std::recursive_timed_mutex m_instanceLock;
808
809 /// <summary>
810 /// Contains the currently running utility VM's.
811 /// </summary>
812 _Guarded_by_(m_instanceLock) std::map<GUID, std::shared_ptr<LxssRunningInstance>, wsl::windows::common::helpers::GuidLess> m_runningInstances;
813
814 /// <summary>
815 /// Contains a list of instances that have been terminated.
816 /// </summary>
817 wil::srwlock m_terminatedInstanceLock;
818 _Guarded_by_(m_terminatedInstanceLock) std::list<std::shared_ptr<LxssRunningInstance>> m_terminatedInstances;
819
820 /// <summary>
821 /// Contains a list of distribution are toggling VM mode.
822 /// </summary>
823 _Guarded_by_(m_instanceLock) std::list<std::pair<GUID, LxssDistributionState>> m_lockedDistributions;
824
825 /// <summary>
826 /// The running utility vm for WSL2 distributions.
827 ///
828 _Guarded_by_(m_instanceLock) std::unique_ptr<WslCoreVm> m_utilityVm;
829
830 std::atomic<GUID> m_vmId{GUID_NULL};
831
832 /// <summary>
833 /// True when the VM termination callback should not perform session cleanup.
834 /// </summary>
835 std::atomic<bool> m_suppressVmTerminationCallback{false};
836
837 /// <summary>
838 /// Contains the user sid for the session.
839 /// </summary>
840 SE_SID m_userSid;
841
842 /// <summary>
843 /// Contains the session ID.
844 /// </summary>
845 DWORD m_sessionId;
846
847 /// <summary>
848 /// Class to keep track of any client processes.
849 /// </summary>
850 LifetimeManager m_lifetimeManager;
851
852 /// <summary>
853 /// Timer to control terminating the Linux utility VM.
854 /// </summary>
855 wil::unique_threadpool_timer m_vmTerminationTimer;
856
857 /// <summary>
858 /// Signaled when the utility vm is terminating.
859 /// </summary>
860 wil::unique_event m_vmTerminating{wil::EventOptions::ManualReset};
861
862 /// <summary>
863 /// Thread for logging usage telemetry from the WSL VM.
864 /// </summary>
865 std::thread m_telemetryThread;
866
867 /// <summary>
868 /// True when this session shouldn't allow creating new instances.
869 /// (Used when the session is being deleted).
870 /// </summary>
871 bool m_disableNewInstanceCreation = false;
872
873 /// <summary>
874 /// The user's token. Shared with WslCoreVm and plugins.
875 /// </summary>
876 wil::shared_handle m_userToken;
877
878 WSLSessionInformation m_session{};
879
880 wsl::windows::service::PluginManager& m_pluginManager;
881
882 /// <summary>
883 /// Listens to host http proxy setting changes, tracks ongoing proxy queries, and stores current settings.
884 /// Information used to configure Linux proxy environment variables.
885 /// </summary>
886 std::shared_ptr<HttpProxyStateTracker> m_httpProxyStateTracker{};
887
888 std::thread m_timezoneThread;
889 };
890
891 #define LXSS_CLIENT_ID_WILDCARD ((ULONG)0)
892 #define LXSS_CLIENT_ID_INVALID ((ULONG) - 1)