| 1 | /*++ |
| 2 | |
| 3 | Copyright (c) Microsoft. All rights reserved. |
| 4 | |
| 5 | Module Name: |
| 6 | |
| 7 | LxssCreateProcess.h |
| 8 | |
| 9 | Abstract: |
| 10 | |
| 11 | This file contains process creation function declarations. |
| 12 | |
| 13 | --*/ |
| 14 | |
| 15 | #pragma once |
| 16 | |
| 17 | #include "SocketChannel.h" |
| 18 | #include "WslPluginApi.h" |
| 19 | |
| 20 | // Macro to test if Windows interop is enabled. |
| 21 | #define LXSS_INTEROP_FLAGS (LXSS_DISTRO_FLAGS_ENABLE_DRIVE_MOUNTING | LXSS_DISTRO_FLAGS_ENABLE_INTEROP) |
| 22 | |
| 23 | #define LXSS_INTEROP_ENABLED(_flags) (((_flags) & LXSS_INTEROP_FLAGS) == LXSS_INTEROP_FLAGS) |
| 24 | |
| 25 | using CreateLxProcessConsoleData = struct |
| 26 | { |
| 27 | wil::unique_handle ConsoleHandle; |
| 28 | wil::unique_handle ClientProcess; |
| 29 | }; |
| 30 | |
| 31 | using CreateLxProcessContext = struct |
| 32 | { |
| 33 | ULONG Flags; |
| 34 | std::vector<std::string> DefaultEnvironment; |
| 35 | wil::unique_handle UserToken; |
| 36 | bool Elevated; |
| 37 | }; |
| 38 | |
| 39 | using CreateLxProcessData = struct |
| 40 | { |
| 41 | std::string Filename; |
| 42 | std::vector<std::string> CommandLine; |
| 43 | std::vector<std::string> Environment; |
| 44 | std::vector<std::string> NtEnvironment; |
| 45 | CREATE_PROCESS_SHELL_OPTIONS ShellOptions; |
| 46 | std::string NtPath; |
| 47 | std::string CurrentWorkingDirectory; |
| 48 | std::string Username; |
| 49 | }; |
| 50 | |
| 51 | class LxssCreateProcess |
| 52 | { |
| 53 | public: |
| 54 | /// <summary> |
| 55 | /// Allocates and initializes a create process message. |
| 56 | /// </summary> |
| 57 | static std::vector<gsl::byte> CreateMessage(_In_ LX_MESSAGE_TYPE MessageType, _In_ const CreateLxProcessData& CreateProcessData, _In_ ULONG DefaultUid); |
| 58 | |
| 59 | /// <summary> |
| 60 | /// Parses create process arguments. |
| 61 | /// </summary> |
| 62 | static CreateLxProcessData ParseArguments( |
| 63 | _In_opt_ LPCSTR Filename, |
| 64 | _In_ ULONG CommandLineCount, |
| 65 | _In_reads_opt_(CommandLineCount) LPCSTR* CommandLine, |
| 66 | _In_opt_ LPCWSTR CurrentWorkingDirectory, |
| 67 | _In_opt_ LPCWSTR NtPath, |
| 68 | _In_reads_opt_(NtEnvironmentLength) PWCHAR NtEnvironment, |
| 69 | _In_ ULONG NtEnvironmentLength, |
| 70 | _In_opt_ LPCWSTR Username, |
| 71 | _In_ const std::vector<std::string>& DefaultEnvironment, |
| 72 | _In_ ULONG Flags); |
| 73 | |
| 74 | static inline wil::unique_socket CreateLinuxProcess( |
| 75 | _In_ LPCSTR Path, _In_ LPCSTR* Arguments, const GUID& RuntimeId, wsl::shared::SocketChannel& channel, HANDLE terminatingEvent, DWORD Timeout) |
| 76 | { |
| 77 | std::vector<char> ArgumentsData; |
| 78 | for (const auto* e = Arguments; *e != nullptr; e++) |
| 79 | { |
| 80 | ArgumentsData.insert(ArgumentsData.end(), *e, *e + strlen(*e) + 1); |
| 81 | } |
| 82 | |
| 83 | ArgumentsData.emplace_back('\0'); |
| 84 | |
| 85 | wsl::shared::MessageWriter<CREATE_PROCESS_MESSAGE> message(LxInitCreateProcess); |
| 86 | message.WriteString(message->PathIndex, Path); |
| 87 | gsl::copy(as_bytes(gsl::span(ArgumentsData)), message.InsertBuffer(message->CommandLineIndex, ArgumentsData.size())); |
| 88 | auto transaction = channel.StartTransaction(Timeout); |
| 89 | transaction.Send<CREATE_PROCESS_MESSAGE>(message.Span()); |
| 90 | |
| 91 | auto readResult = [&]() { |
| 92 | const auto& message = transaction.Receive<RESULT_MESSAGE<int32_t>>(); |
| 93 | return message.Result; |
| 94 | }; |
| 95 | |
| 96 | auto processSocket = wsl::windows::common::hvsocket::Connect(RuntimeId, readResult(), terminatingEvent); |
| 97 | const auto execResult = readResult(); |
| 98 | THROW_HR_IF_MSG(E_FAIL, execResult != 0, "Failed to execute '%hs', error=%d", Path, execResult); |
| 99 | |
| 100 | return processSocket; |
| 101 | } |
| 102 | }; |
| 103 | |
| 104 | typedef struct _LXSS_DISTRO_CONFIGURATION |
| 105 | { |
| 106 | GUID DistroId; |
| 107 | DWORD State; |
| 108 | std::wstring Name; |
| 109 | DWORD Version; |
| 110 | std::filesystem::path BasePath; |
| 111 | std::wstring PackageFamilyName; |
| 112 | std::filesystem::path VhdFilePath; |
| 113 | ULONG Flags; |
| 114 | std::wstring Flavor; |
| 115 | std::wstring OsVersion; |
| 116 | std::optional<std::wstring> ShortcutPath; |
| 117 | bool RunOOBE; |
| 118 | } LXSS_DISTRO_CONFIGURATION, *PLXSS_DISTRO_CONFIGURATION; |
| 119 | |
| 120 | class LxssRunningInstance |
| 121 | { |
| 122 | public: |
| 123 | LxssRunningInstance(int IdleTimeout) : m_idleTimeout(IdleTimeout) |
| 124 | { |
| 125 | } |
| 126 | |
| 127 | LxssRunningInstance(const LxssRunningInstance&) = delete; |
| 128 | LxssRunningInstance(LxssRunningInstance&&) = delete; |
| 129 | void operator=(const LxssRunningInstance&) = delete; |
| 130 | void operator=(LxssRunningInstance&&) = delete; |
| 131 | |
| 132 | virtual void CreateLxProcess( |
| 133 | _In_ const CreateLxProcessData& CreateProcessData, |
| 134 | _In_ const CreateLxProcessContext& CreateProcessContext, |
| 135 | _In_ const CreateLxProcessConsoleData& ConsoleData, |
| 136 | _In_ SHORT Columns, |
| 137 | _In_ SHORT Rows, |
| 138 | _In_ PLXSS_STD_HANDLES StdHandles, |
| 139 | _Out_ GUID* InstanceId, |
| 140 | _Out_ HANDLE* ProcessHandle, |
| 141 | _Out_ HANDLE* ServerHandle, |
| 142 | _Out_ HANDLE* StandardIn, |
| 143 | _Out_ HANDLE* StandardOut, |
| 144 | _Out_ HANDLE* StandardErr, |
| 145 | _Out_ HANDLE* CommunicationChannel, |
| 146 | _Out_ HANDLE* InteropSocket) = 0; |
| 147 | |
| 148 | virtual GUID GetDistributionId() const = 0; |
| 149 | virtual std::shared_ptr<LxssPort> GetInitPort() = 0; |
| 150 | virtual ULONG64 GetLifetimeManagerId() const = 0; |
| 151 | virtual ULONG GetClientId() const = 0; |
| 152 | virtual void Initialize() = 0; |
| 153 | virtual bool RequestStop(_In_ bool Force) = 0; |
| 154 | virtual void Stop() = 0; |
| 155 | virtual void RegisterPlan9ConnectionTarget(_In_ HANDLE userToken) = 0; |
| 156 | virtual void UpdateTimezone() = 0; |
| 157 | virtual const WSLDistributionInformation* DistributionInformation() const noexcept = 0; |
| 158 | |
| 159 | int GetIdleTimeout() const noexcept |
| 160 | { |
| 161 | return m_idleTimeout; |
| 162 | }; |
| 163 | |
| 164 | private: |
| 165 | int m_idleTimeout; |
| 166 | }; |