-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrun.cpp
102 lines (79 loc) · 2.98 KB
/
run.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <nall/run.hpp>
#include <nall/path.hpp>
#if defined(PLATFORM_WINDOWS)
#include <shellapi.h>
#endif
namespace nall {
#if defined(PLATFORM_WINDOWS)
NALL_HEADER_INLINE auto execute(const string& name, vector<string> argl) -> execute_result_t {
for(auto& arg : argl) if(arg.find(" ")) arg = {"\"", arg, "\""};
string arguments = argl.merge(" ");
SECURITY_ATTRIBUTES sa;
ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = true;
sa.lpSecurityDescriptor = nullptr;
HANDLE stdoutRead;
HANDLE stdoutWrite;
if(!CreatePipe(&stdoutRead, &stdoutWrite, &sa, 0)) return {};
if(!SetHandleInformation(stdoutRead, HANDLE_FLAG_INHERIT, 0)) return {};
HANDLE stderrRead;
HANDLE stderrWrite;
if(!CreatePipe(&stderrRead, &stderrWrite, &sa, 0)) return {};
if(!SetHandleInformation(stderrRead, HANDLE_FLAG_INHERIT, 0)) return {};
HANDLE stdinRead;
HANDLE stdinWrite;
if(!CreatePipe(&stdinRead, &stdinWrite, &sa, 0)) return {};
if(!SetHandleInformation(stdinWrite, HANDLE_FLAG_INHERIT, 0)) return {};
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.hStdOutput = stdoutWrite;
si.hStdError = stderrWrite;
si.hStdInput = stdinRead;
si.dwFlags = STARTF_USESTDHANDLES;
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
if(!CreateProcess(
nullptr, utf16_t(arguments),
nullptr, nullptr, true, CREATE_NO_WINDOW,
nullptr, nullptr, &si, &pi
)) return {};
DWORD exitCode = EXIT_FAILURE;
if(WaitForSingleObject(pi.hProcess, INFINITE)) return {};
if(!GetExitCodeProcess(pi.hProcess, &exitCode)) return {};
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
char buffer[256];
execute_result_t result;
result.code = exitCode;
while(true) {
DWORD read, available, remaining;
if(!PeekNamedPipe(stdoutRead, nullptr, sizeof(buffer), &read, &available, &remaining)) break;
if(read == 0) break;
if(!ReadFile(stdoutRead, buffer, sizeof(buffer), &read, nullptr)) break;
if(read == 0) break;
auto offset = result.output.size();
result.output.resize(offset + read);
memory::copy(result.output.get() + offset, buffer, read);
}
while(true) {
DWORD read, available, remaining;
if(!PeekNamedPipe(stderrRead, nullptr, sizeof(buffer), &read, &available, &remaining)) break;
if(read == 0) break;
if(!ReadFile(stderrRead, buffer, sizeof(buffer), &read, nullptr)) break;
if(read == 0) break;
auto offset = result.error.size();
result.error.resize(offset + read);
memory::copy(result.error.get() + offset, buffer, read);
}
return result;
}
NALL_HEADER_INLINE auto invoke(const string& name, vector<string> argl) -> void {
for(auto& arg : argl) if(arg.find(" ")) arg = {"\"", arg, "\""};
string arguments = argl.merge(" ");
string directory = Path::program().replace("/", "\\");
ShellExecute(nullptr, nullptr, utf16_t(name), utf16_t(arguments), utf16_t(directory), SW_SHOWNORMAL);
}
#endif
}