2 #include <msp/core/systemerror.h>
3 #include <msp/io/handle_private.h>
5 #include "process_private.h"
11 string quote_argument(const string &arg)
14 bool need_quotes = false;
15 bool backslash = false;
16 for(string::const_iterator i=arg.begin(); i!=arg.end(); ++i)
32 return "\""+result+"\"";
43 CloseHandle(priv->info.hProcess);
44 CloseHandle(priv->info.hThread);
47 void Process::platform_get_self_info(Private &priv)
49 priv.info.hProcess = GetCurrentProcess();
50 priv.info.hThread = 0;
51 priv.info.dwProcessId = GetCurrentProcessId();
52 priv.info.dwThreadId = 0;
55 void Process::execute(const string &command, bool path_search, const Arguments &args)
57 string cmdline = quote_argument(command);
58 for(Arguments::const_iterator i=args.begin(); i!=args.end(); ++i)
61 cmdline += quote_argument(*i);
65 startup.cb = sizeof(STARTUPINFO);
66 startup.lpReserved = 0;
67 startup.lpDesktop = 0;
70 startup.cbReserved2 = 0;
71 startup.lpReserved2 = 0;
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 ? 0 : command.c_str());
84 const char *wd = (work_dir.empty() ? 0 : work_dir.c_str());
85 if(!CreateProcess(cmdptr, const_cast<char *>(cmdline.c_str()), 0, 0, false, 0, 0, wd, &startup, &priv->info))
86 throw system_error("CreateProcess");
87 // XXX Should we close the duplicated handles? What if CreateProcess fails?
92 TerminateProcess(priv->info.hProcess, 0);
95 bool Process::wait(bool block)
98 throw logic_error("not running");
100 DWORD ret = WaitForSingleObject(priv->info.hProcess, (block ? INFINITE : 0));
102 throw system_error("WaitForSingleObject");
104 if(ret==WAIT_OBJECT_0)
113 void Process::terminate()
115 TerminateProcess(priv->info.hProcess, 1);
120 TerminateProcess(priv->info.hProcess, 1);
123 void Process::interrupt()
125 TerminateProcess(priv->info.hProcess, 1);
129 Process::Private::Private()
133 info.dwProcessId = 0;