diff options
Diffstat (limited to 'source/Host/windows/ProcessLauncherWindows.cpp')
-rw-r--r-- | source/Host/windows/ProcessLauncherWindows.cpp | 235 |
1 files changed, 119 insertions, 116 deletions
diff --git a/source/Host/windows/ProcessLauncherWindows.cpp b/source/Host/windows/ProcessLauncherWindows.cpp index caf0fc71e121..16805ba7df88 100644 --- a/source/Host/windows/ProcessLauncherWindows.cpp +++ b/source/Host/windows/ProcessLauncherWindows.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Host/HostProcess.h" #include "lldb/Host/windows/ProcessLauncherWindows.h" +#include "lldb/Host/HostProcess.h" #include "lldb/Target/ProcessLaunchInfo.h" #include "llvm/ADT/SmallVector.h" @@ -20,127 +20,130 @@ using namespace lldb; using namespace lldb_private; -namespace -{ -void -CreateEnvironmentBuffer(const Args &env, std::vector<char> &buffer) -{ - if (env.GetArgumentCount() == 0) - return; - - // Environment buffer is a null terminated list of null terminated strings - for (int i = 0; i < env.GetArgumentCount(); ++i) - { - std::wstring warg; - if (llvm::ConvertUTF8toWide(env.GetArgumentAtIndex(i), warg)) - { - buffer.insert(buffer.end(), (char *)warg.c_str(), (char *)(warg.c_str() + warg.size() + 1)); - } +namespace { +void CreateEnvironmentBuffer(const Args &env, std::vector<char> &buffer) { + if (env.GetArgumentCount() == 0) + return; + + // Environment buffer is a null terminated list of null terminated strings + for (auto &entry : env.entries()) { + std::wstring warg; + if (llvm::ConvertUTF8toWide(entry.ref, warg)) { + buffer.insert(buffer.end(), (char *)warg.c_str(), + (char *)(warg.c_str() + warg.size() + 1)); } - // One null wchar_t (to end the block) is two null bytes - buffer.push_back(0); - buffer.push_back(0); + } + // One null wchar_t (to end the block) is two null bytes + buffer.push_back(0); + buffer.push_back(0); } } HostProcess -ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) -{ - error.Clear(); - - std::string executable; - std::string commandLine; - std::vector<char> environment; - STARTUPINFO startupinfo = {0}; - PROCESS_INFORMATION pi = {0}; - - HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO); - HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO); - HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO); - - startupinfo.cb = sizeof(startupinfo); - startupinfo.dwFlags |= STARTF_USESTDHANDLES; - startupinfo.hStdError = stderr_handle ? stderr_handle : ::GetStdHandle(STD_ERROR_HANDLE); - startupinfo.hStdInput = stdin_handle ? stdin_handle : ::GetStdHandle(STD_INPUT_HANDLE); - startupinfo.hStdOutput = stdout_handle ? stdout_handle : ::GetStdHandle(STD_OUTPUT_HANDLE); - - const char *hide_console_var = getenv("LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE"); - if (hide_console_var && llvm::StringRef(hide_console_var).equals_lower("true")) - { - startupinfo.dwFlags |= STARTF_USESHOWWINDOW; - startupinfo.wShowWindow = SW_HIDE; - } - - DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT; - if (launch_info.GetFlags().Test(eLaunchFlagDebug)) - flags |= DEBUG_ONLY_THIS_PROCESS; - - auto &env = const_cast<Args &>(launch_info.GetEnvironmentEntries()); - LPVOID env_block = nullptr; - ::CreateEnvironmentBuffer(env, environment); - if (!environment.empty()) - env_block = environment.data(); - - executable = launch_info.GetExecutableFile().GetPath(); - launch_info.GetArguments().GetQuotedCommandString(commandLine); - - std::wstring wexecutable, wcommandLine, wworkingDirectory; - llvm::ConvertUTF8toWide(executable, wexecutable); - llvm::ConvertUTF8toWide(commandLine, wcommandLine); - llvm::ConvertUTF8toWide(launch_info.GetWorkingDirectory().GetCString(), wworkingDirectory); - - wcommandLine.resize(PATH_MAX); // Needs to be over-allocated because CreateProcessW can modify it - BOOL result = ::CreateProcessW(wexecutable.c_str(), &wcommandLine[0], NULL, NULL, TRUE, flags, env_block, - wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(), &startupinfo, &pi); - if (result) - { - // Do not call CloseHandle on pi.hProcess, since we want to pass that back through the HostProcess. - ::CloseHandle(pi.hThread); - } - - if (stdin_handle) - ::CloseHandle(stdin_handle); - if (stdout_handle) - ::CloseHandle(stdout_handle); - if (stderr_handle) - ::CloseHandle(stderr_handle); - - if (!result) - error.SetError(::GetLastError(), eErrorTypeWin32); - return HostProcess(pi.hProcess); +ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, + Error &error) { + error.Clear(); + + std::string executable; + std::string commandLine; + std::vector<char> environment; + STARTUPINFO startupinfo = {}; + PROCESS_INFORMATION pi = {}; + + HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO); + HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO); + HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO); + + startupinfo.cb = sizeof(startupinfo); + startupinfo.dwFlags |= STARTF_USESTDHANDLES; + startupinfo.hStdError = + stderr_handle ? stderr_handle : ::GetStdHandle(STD_ERROR_HANDLE); + startupinfo.hStdInput = + stdin_handle ? stdin_handle : ::GetStdHandle(STD_INPUT_HANDLE); + startupinfo.hStdOutput = + stdout_handle ? stdout_handle : ::GetStdHandle(STD_OUTPUT_HANDLE); + + const char *hide_console_var = + getenv("LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE"); + if (hide_console_var && + llvm::StringRef(hide_console_var).equals_lower("true")) { + startupinfo.dwFlags |= STARTF_USESHOWWINDOW; + startupinfo.wShowWindow = SW_HIDE; + } + + DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT; + if (launch_info.GetFlags().Test(eLaunchFlagDebug)) + flags |= DEBUG_ONLY_THIS_PROCESS; + + auto &env = const_cast<Args &>(launch_info.GetEnvironmentEntries()); + LPVOID env_block = nullptr; + ::CreateEnvironmentBuffer(env, environment); + if (!environment.empty()) + env_block = environment.data(); + + executable = launch_info.GetExecutableFile().GetPath(); + launch_info.GetArguments().GetQuotedCommandString(commandLine); + + std::wstring wexecutable, wcommandLine, wworkingDirectory; + llvm::ConvertUTF8toWide(executable, wexecutable); + llvm::ConvertUTF8toWide(commandLine, wcommandLine); + llvm::ConvertUTF8toWide(launch_info.GetWorkingDirectory().GetCString(), + wworkingDirectory); + + wcommandLine.resize(PATH_MAX); // Needs to be over-allocated because + // CreateProcessW can modify it + BOOL result = ::CreateProcessW( + wexecutable.c_str(), &wcommandLine[0], NULL, NULL, TRUE, flags, env_block, + wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(), + &startupinfo, &pi); + if (result) { + // Do not call CloseHandle on pi.hProcess, since we want to pass that back + // through the HostProcess. + ::CloseHandle(pi.hThread); + } + + if (stdin_handle) + ::CloseHandle(stdin_handle); + if (stdout_handle) + ::CloseHandle(stdout_handle); + if (stderr_handle) + ::CloseHandle(stderr_handle); + + if (!result) + error.SetError(::GetLastError(), eErrorTypeWin32); + return HostProcess(pi.hProcess); } HANDLE -ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info, int fd) -{ - const FileAction *action = launch_info.GetFileActionForFD(fd); - if (action == nullptr) - return NULL; - SECURITY_ATTRIBUTES secattr = {0}; - secattr.nLength = sizeof(SECURITY_ATTRIBUTES); - secattr.bInheritHandle = TRUE; - - const char *path = action->GetPath(); - DWORD access = 0; - DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; - DWORD create = 0; - DWORD flags = 0; - if (fd == STDIN_FILENO) - { - access = GENERIC_READ; - create = OPEN_EXISTING; - flags = FILE_ATTRIBUTE_READONLY; - } - if (fd == STDOUT_FILENO || fd == STDERR_FILENO) - { - access = GENERIC_WRITE; - create = CREATE_ALWAYS; - if (fd == STDERR_FILENO) - flags = FILE_FLAG_WRITE_THROUGH; - } - - std::wstring wpath; - llvm::ConvertUTF8toWide(path, wpath); - HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create, flags, NULL); - return (result == INVALID_HANDLE_VALUE) ? NULL : result; +ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info, + int fd) { + const FileAction *action = launch_info.GetFileActionForFD(fd); + if (action == nullptr) + return NULL; + SECURITY_ATTRIBUTES secattr = {}; + secattr.nLength = sizeof(SECURITY_ATTRIBUTES); + secattr.bInheritHandle = TRUE; + + llvm::StringRef path = action->GetPath(); + DWORD access = 0; + DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; + DWORD create = 0; + DWORD flags = 0; + if (fd == STDIN_FILENO) { + access = GENERIC_READ; + create = OPEN_EXISTING; + flags = FILE_ATTRIBUTE_READONLY; + } + if (fd == STDOUT_FILENO || fd == STDERR_FILENO) { + access = GENERIC_WRITE; + create = CREATE_ALWAYS; + if (fd == STDERR_FILENO) + flags = FILE_FLAG_WRITE_THROUGH; + } + + std::wstring wpath; + llvm::ConvertUTF8toWide(path, wpath); + HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create, + flags, NULL); + return (result == INVALID_HANDLE_VALUE) ? NULL : result; } |