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);
49 void Process::platform_get_self_info(Private &priv)
51 priv.info.hProcess = GetCurrentProcess();
52 priv.info.hThread = nullptr;
53 priv.info.dwProcessId = GetCurrentProcessId();
54 priv.info.dwThreadId = 0;
57 void Process::execute(const string &command, bool path_search, const Arguments &args)
59 string cmdline = quote_argument(command);
60 for(const string &a: args)
61 append(cmdline, " ", quote_argument(a));
64 startup.cb = sizeof(STARTUPINFO);
65 startup.lpReserved = nullptr;
66 startup.lpDesktop = nullptr;
67 startup.lpTitle = nullptr;
69 startup.cbReserved2 = 0;
70 startup.lpReserved2 = nullptr;
73 startup.dwFlags |= STARTF_USESTDHANDLES;
74 HANDLE self_handle = self().priv->info.hProcess;
75 HANDLE cin_handle = (cin ? *cin->get_handle(IO::M_READ) : GetStdHandle(STD_INPUT_HANDLE));
76 DuplicateHandle(self_handle, cin_handle, self_handle, &startup.hStdInput, 0, true, DUPLICATE_SAME_ACCESS);
77 HANDLE cout_handle = (cout ? *cout->get_handle(IO::M_WRITE) : GetStdHandle(STD_OUTPUT_HANDLE));
78 DuplicateHandle(self_handle, cout_handle, self_handle, &startup.hStdOutput, 0, true, DUPLICATE_SAME_ACCESS);
79 HANDLE cerr_handle = (cerr ? *cerr->get_handle(IO::M_WRITE) : GetStdHandle(STD_ERROR_HANDLE));
80 DuplicateHandle(self_handle, cerr_handle, self_handle, &startup.hStdError, 0, true, DUPLICATE_SAME_ACCESS);
82 const char *cmdptr = (path_search ? nullptr : command.c_str());
83 const char *wd = (work_dir.empty() ? nullptr : work_dir.c_str());
84 if(!CreateProcess(cmdptr, const_cast<char *>(cmdline.c_str()), nullptr, nullptr, true, 0, nullptr, wd, &startup, &priv->info))
85 throw system_error("CreateProcess");
89 CloseHandle(startup.hStdInput);
90 CloseHandle(startup.hStdOutput);
91 CloseHandle(startup.hStdError);
97 TerminateProcess(priv->info.hProcess, 0);
100 bool Process::wait(bool block)
103 throw invalid_state("not running");
105 DWORD ret = WaitForSingleObject(priv->info.hProcess, (block ? INFINITE : 0));
107 throw system_error("WaitForSingleObject");
109 if(ret==WAIT_OBJECT_0)
114 if(GetExitCodeProcess(priv->info.hProcess, &ec))
121 void Process::terminate()
123 TerminateProcess(priv->info.hProcess, 1);
128 TerminateProcess(priv->info.hProcess, 1);
131 void Process::interrupt()
133 TerminateProcess(priv->info.hProcess, 1);
137 Process::Private::Private()
139 info.hProcess = nullptr;
140 info.hThread = nullptr;
141 info.dwProcessId = 0;