2 #include <msp/core/systemerror.h>
3 #include <msp/io/handle_private.h>
4 #include <msp/strings/utils.h>
7 #include "process_private.h"
13 string quote_argument(const string &arg)
16 bool need_quotes = false;
17 bool backslash = false;
34 return "\""+result+"\"";
45 CloseHandle(priv->info.hProcess);
46 CloseHandle(priv->info.hThread);
50 void Process::platform_get_self_info(Private &priv)
52 priv.info.hProcess = GetCurrentProcess();
53 priv.info.hThread = nullptr;
54 priv.info.dwProcessId = GetCurrentProcessId();
55 priv.info.dwThreadId = 0;
58 void Process::execute(const string &command, bool path_search, const Arguments &args)
60 string cmdline = quote_argument(command);
61 for(const string &a: args)
62 append(cmdline, " ", quote_argument(a));
65 startup.cb = sizeof(STARTUPINFO);
66 startup.lpReserved = nullptr;
67 startup.lpDesktop = nullptr;
68 startup.lpTitle = nullptr;
70 startup.cbReserved2 = 0;
71 startup.lpReserved2 = nullptr;
74 startup.dwFlags |= STARTF_USESTDHANDLES;
75 HANDLE self_handle = self().priv->info.hProcess;
76 HANDLE cin_handle = (cin ? *cin->get_handle(IO::M_READ) : GetStdHandle(STD_INPUT_HANDLE));
77 DuplicateHandle(self_handle, cin_handle, self_handle, &startup.hStdInput, 0, true, DUPLICATE_SAME_ACCESS);
78 HANDLE cout_handle = (cout ? *cout->get_handle(IO::M_WRITE) : GetStdHandle(STD_OUTPUT_HANDLE));
79 DuplicateHandle(self_handle, cout_handle, self_handle, &startup.hStdOutput, 0, true, DUPLICATE_SAME_ACCESS);
80 HANDLE cerr_handle = (cerr ? *cerr->get_handle(IO::M_WRITE) : GetStdHandle(STD_ERROR_HANDLE));
81 DuplicateHandle(self_handle, cerr_handle, self_handle, &startup.hStdError, 0, true, DUPLICATE_SAME_ACCESS);
83 const char *cmdptr = (path_search ? nullptr : command.c_str());
84 const char *wd = (work_dir.empty() ? nullptr : work_dir.c_str());
85 if(!CreateProcess(cmdptr, const_cast<char *>(cmdline.c_str()), nullptr, nullptr, true, 0, nullptr, wd, &startup, &priv->info))
86 throw system_error("CreateProcess");
90 CloseHandle(startup.hStdInput);
91 CloseHandle(startup.hStdOutput);
92 CloseHandle(startup.hStdError);
98 TerminateProcess(priv->info.hProcess, 0);
101 bool Process::wait(bool block)
104 throw invalid_state("not running");
106 DWORD ret = WaitForSingleObject(priv->info.hProcess, (block ? INFINITE : 0));
108 throw system_error("WaitForSingleObject");
110 if(ret==WAIT_OBJECT_0)
115 if(GetExitCodeProcess(priv->info.hProcess, &ec))
122 void Process::terminate()
124 TerminateProcess(priv->info.hProcess, 1);
129 TerminateProcess(priv->info.hProcess, 1);
132 void Process::interrupt()
134 TerminateProcess(priv->info.hProcess, 1);
138 Process::Private::Private()
140 info.hProcess = nullptr;
141 info.hThread = nullptr;
142 info.dwProcessId = 0;