blob: f470d580e2d476bddef8f48c5cec452a80f3e7a4 [file] [log] [blame]
Zachary Turner172d37d2014-10-14 21:55:08 +00001//===-- ProcessLauncherWindows.cpp ------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Host/HostProcess.h"
11#include "lldb/Host/windows/ProcessLauncherWindows.h"
12#include "lldb/Target/ProcessLaunchInfo.h"
13
14#include <string>
15#include <vector>
16
17using namespace lldb;
18using namespace lldb_private;
19
20HostProcess
21ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error)
22{
23 error.Clear();
24
25 std::string executable;
26 std::string commandLine;
27 std::vector<char> environment;
28 STARTUPINFO startupinfo = {0};
29 PROCESS_INFORMATION pi = {0};
30
31 HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO);
32 HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO);
33 HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO);
34
35 startupinfo.cb = sizeof(startupinfo);
36 startupinfo.dwFlags |= STARTF_USESTDHANDLES;
37 startupinfo.hStdError = stderr_handle;
38 startupinfo.hStdInput = stdin_handle;
39 startupinfo.hStdOutput = stdout_handle;
40
Zachary Turner742346a2014-11-05 22:16:28 +000041 DWORD flags = CREATE_NEW_CONSOLE;
42 if (launch_info.GetFlags().Test(eLaunchFlagDebug))
43 flags |= DEBUG_ONLY_THIS_PROCESS;
44
Zachary Turner172d37d2014-10-14 21:55:08 +000045 executable = launch_info.GetExecutableFile().GetPath();
46 launch_info.GetArguments().GetQuotedCommandString(commandLine);
Zachary Turner742346a2014-11-05 22:16:28 +000047 BOOL result = ::CreateProcessA(executable.c_str(), const_cast<char *>(commandLine.c_str()), NULL, NULL, TRUE, flags, NULL,
Zachary Turner172d37d2014-10-14 21:55:08 +000048 launch_info.GetWorkingDirectory(), &startupinfo, &pi);
49 if (result)
50 {
51 // Do not call CloseHandle on pi.hProcess, since we want to pass that back through the HostProcess.
52 ::CloseHandle(pi.hThread);
53 }
54
55 if (stdin_handle)
56 ::CloseHandle(stdin_handle);
57 if (stdout_handle)
58 ::CloseHandle(stdout_handle);
59 if (stderr_handle)
60 ::CloseHandle(stderr_handle);
61
62 if (!result)
63 error.SetError(::GetLastError(), eErrorTypeWin32);
64 return HostProcess(pi.hProcess);
65}
66
67HANDLE
68ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info, int fd)
69{
70 const FileAction *action = launch_info.GetFileActionForFD(fd);
71 if (action == nullptr)
72 return NULL;
73 SECURITY_ATTRIBUTES secattr = {0};
74 secattr.nLength = sizeof(SECURITY_ATTRIBUTES);
75 secattr.bInheritHandle = TRUE;
76
77 const char *path = action->GetPath();
78 DWORD access = 0;
79 DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE;
80 DWORD create = 0;
81 DWORD flags = 0;
82 if (fd == STDIN_FILENO)
83 {
84 access = GENERIC_READ;
85 create = OPEN_EXISTING;
86 flags = FILE_ATTRIBUTE_READONLY;
87 }
88 if (fd == STDOUT_FILENO || fd == STDERR_FILENO)
89 {
90 access = GENERIC_WRITE;
91 create = CREATE_ALWAYS;
92 if (fd == STDERR_FILENO)
93 flags = FILE_FLAG_WRITE_THROUGH;
94 }
95
96 HANDLE result = ::CreateFile(path, access, share, &secattr, create, flags, NULL);
97 return (result == INVALID_HANDLE_VALUE) ? NULL : result;
98}