|
18 | 18 | #include "llvm/Config/config.h"
|
19 | 19 | #include "llvm/Support/Allocator.h"
|
20 | 20 | #include "llvm/Support/Program.h"
|
| 21 | +#if defined(_WIN32) |
| 22 | +#include "llvm/Support/Windows/WindowsSupport.h" |
| 23 | +#endif |
21 | 24 |
|
| 25 | +#include <memory> |
22 | 26 | #include <system_error>
|
23 | 27 |
|
24 | 28 | #if HAVE_POSIX_SPAWN
|
|
29 | 33 | #include <unistd.h>
|
30 | 34 | #endif
|
31 | 35 |
|
| 36 | +#if defined(_WIN32) |
| 37 | +#define WIN32_LEAN_AND_MEAN |
| 38 | +#include <Windows.h> |
| 39 | +#include <io.h> |
| 40 | +#endif |
| 41 | + |
32 | 42 | using namespace swift;
|
33 | 43 |
|
34 | 44 | int swift::ExecuteInPlace(const char *Program, const char **args,
|
@@ -178,6 +188,97 @@ swift::ExecuteWithPipe(llvm::StringRef program,
|
178 | 188 | return ChildProcessInfo(pid, p1.write, p2.read);
|
179 | 189 | }
|
180 | 190 |
|
| 191 | +#elif defined(_WIN32) |
| 192 | + |
| 193 | +llvm::ErrorOr<swift::ChildProcessInfo> |
| 194 | +swift::ExecuteWithPipe(llvm::StringRef program, |
| 195 | + llvm::ArrayRef<llvm::StringRef> args, |
| 196 | + llvm::Optional<llvm::ArrayRef<llvm::StringRef>> env) { |
| 197 | + using unique_handle = std::unique_ptr<void, decltype(&CloseHandle)>; |
| 198 | + enum { PI_READ, PI_WRITE }; |
| 199 | + |
| 200 | + unique_handle input[2] = { |
| 201 | + {INVALID_HANDLE_VALUE, CloseHandle}, |
| 202 | + {INVALID_HANDLE_VALUE, CloseHandle}, |
| 203 | + }; |
| 204 | + unique_handle output[2] = { |
| 205 | + {INVALID_HANDLE_VALUE, CloseHandle}, |
| 206 | + {INVALID_HANDLE_VALUE, CloseHandle}, |
| 207 | + }; |
| 208 | + unique_handle error{INVALID_HANDLE_VALUE, CloseHandle}; |
| 209 | + HANDLE hRead = INVALID_HANDLE_VALUE, hWrite = INVALID_HANDLE_VALUE; |
| 210 | + SECURITY_ATTRIBUTES saAttrs{sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; |
| 211 | + |
| 212 | + if (!CreatePipe(&hRead, &hWrite, &saAttrs, 0)) |
| 213 | + return std::error_code(GetLastError(), std::system_category()); |
| 214 | + output[PI_READ].reset(hRead); |
| 215 | + output[PI_WRITE].reset(hWrite); |
| 216 | + |
| 217 | + if (!SetHandleInformation(output[PI_READ].get(), HANDLE_FLAG_INHERIT, FALSE)) |
| 218 | + return std::error_code(GetLastError(), std::system_category()); |
| 219 | + |
| 220 | + if (!CreatePipe(&hRead, &hWrite, &saAttrs, 0)) |
| 221 | + return std::error_code(GetLastError(), std::system_category()); |
| 222 | + input[PI_READ].reset(hRead); |
| 223 | + input[PI_WRITE].reset(hWrite); |
| 224 | + |
| 225 | + if (!SetHandleInformation(input[PI_WRITE].get(), HANDLE_FLAG_INHERIT, FALSE)) |
| 226 | + return std::error_code(GetLastError(), std::system_category()); |
| 227 | + |
| 228 | + if (!DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_ERROR_HANDLE), |
| 229 | + GetCurrentProcess(), &hWrite, DUPLICATE_SAME_ACCESS, |
| 230 | + TRUE, DUPLICATE_SAME_ACCESS)) |
| 231 | + return std::error_code(GetLastError(), std::system_category()); |
| 232 | + error.reset(hWrite); |
| 233 | + |
| 234 | + STARTUPINFO si = {0}; |
| 235 | + si.cb = sizeof(si); |
| 236 | + si.hStdInput = input[PI_READ].get(); |
| 237 | + si.hStdOutput = output[PI_WRITE].get(); |
| 238 | + si.hStdError = error.get(); |
| 239 | + si.dwFlags = STARTF_USESTDHANDLES; |
| 240 | + |
| 241 | + llvm::SmallVector<wchar_t, MAX_PATH> executable; |
| 242 | + if (std::error_code ec = llvm::sys::windows::widenPath(program, executable)) |
| 243 | + return ec; |
| 244 | + |
| 245 | + std::vector<StringRef> components; |
| 246 | + components.push_back(program); |
| 247 | + components.assign(args.begin(), args.end()); |
| 248 | + llvm::ErrorOr<std::wstring> commandline = |
| 249 | + llvm::sys::flattenWindowsCommandLine(components); |
| 250 | + if (!commandline) |
| 251 | + return commandline.getError(); |
| 252 | + |
| 253 | + std::vector<wchar_t> command(commandline->size() + 1, 0); |
| 254 | + std::copy(commandline->begin(), commandline->end(), command.begin()); |
| 255 | + |
| 256 | + PROCESS_INFORMATION pi = {0}; |
| 257 | + if (!CreateProcessW(executable.data(), |
| 258 | + command.data(), nullptr, nullptr, TRUE, 0, nullptr, |
| 259 | + nullptr, &si, &pi)) |
| 260 | + return std::error_code(GetLastError(), std::system_category()); |
| 261 | + |
| 262 | + unique_handle hThread{pi.hThread, CloseHandle}; |
| 263 | + unique_handle hProcess{pi.hProcess, CloseHandle}; |
| 264 | + |
| 265 | + int ifd = _open_osfhandle(reinterpret_cast<intptr_t>(input[PI_WRITE].get()), 0); |
| 266 | + if (ifd < 0) |
| 267 | + return std::error_code(errno, std::system_category()); |
| 268 | + input[PI_WRITE].release(); |
| 269 | + |
| 270 | + int ofd = _open_osfhandle(reinterpret_cast<intptr_t>(output[PI_READ].get()), 0); |
| 271 | + if (ofd < 0) { |
| 272 | + _close(ifd); |
| 273 | + return std::error_code(errno, std::system_category()); |
| 274 | + } |
| 275 | + output[PI_READ].release(); |
| 276 | + |
| 277 | + llvm::sys::ProcessInfo proc; |
| 278 | + proc.Process = pi.hProcess; |
| 279 | + return ChildProcessInfo(proc, ifd, ofd); |
| 280 | +} |
| 281 | + |
181 | 282 | #else // HAVE_UNISTD_H
|
182 | 283 |
|
183 | 284 | llvm::ErrorOr<swift::ChildProcessInfo>
|
|
0 commit comments