-
Notifications
You must be signed in to change notification settings - Fork 58
/
Copy pathwin_cmd_wrapper.c
109 lines (90 loc) · 3.09 KB
/
win_cmd_wrapper.c
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
103
104
105
106
107
108
109
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <tchar.h>
#include <windows.h>
#include "create_pipe_ex.h"
#include "read_file_timeout.h"
#include "win_cmd_wrapper.h"
int run_command_wrapper(const wchar_t* cmd, const wchar_t* argv_fmt, ...)
{
wchar_t buffer[MAX_PATH * 2] = { 0 };
va_list arg;
va_start(arg, argv_fmt);
vswprintf(buffer, ARRAYSIZE(buffer), argv_fmt, arg);
va_end(arg);
return run_command(cmd, buffer);
}
int run_command(const wchar_t* cmd, const wchar_t* args)
{
#define BUFSIZE 4096
STARTUPINFOW si;
PROCESS_INFORMATION pi;
DWORD exit_code = 0;
size_t len = 0;
wchar_t* buffer = NULL;
HANDLE g_hChildStd_OUT_Rd = INVALID_HANDLE_VALUE;
HANDLE g_hChildStd_OUT_Wr = INVALID_HANDLE_VALUE;
SECURITY_ATTRIBUTES saAttr = { sizeof(saAttr), NULL, TRUE };
DWORD dwRead = 0;
CHAR chBuf[BUFSIZE] = { 0 };
LARGE_INTEGER ByteOffset = { 0 };
// Create a pipe for the child process's STDOUT.
if (!MyCreatePipeEx(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0, FILE_FLAG_OVERLAPPED, 0)) {
return -1;
}
// Ensure the read handle to the pipe for STDOUT is not inherited.
if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) {
return -1;
}
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags |= (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW);
si.wShowWindow = SW_HIDE;
si.hStdError = g_hChildStd_OUT_Wr;
/*
si.hStdOutput = g_hChildStd_OUT_Wr;
si.hStdInput = g_hChildStd_IN_Rd;
*/
ZeroMemory(&pi, sizeof(pi));
len = lstrlenW(cmd) + lstrlenW(args) + 10;
buffer = (wchar_t*)calloc(len, sizeof(wchar_t));
if (cmd[0] == L'"') {
swprintf(buffer, len, L"%s %s", cmd, args);
} else {
swprintf(buffer, len, L"\"%s\" %s", cmd, args);
}
// Start the child process.
if (!CreateProcessW(NULL, // No module name (use command line)
buffer, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
TRUE, // Set handle inheritance to TRUE
CREATE_NO_WINDOW | CREATE_NEW_CONSOLE, // Creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
) {
wprintf(L"CreateProcess failed (%d).\n", GetLastError());
free(buffer);
return -1;
}
// Wait until child process exits.
WaitForSingleObject(pi.hProcess, INFINITE);
GetExitCodeProcess(pi.hProcess, &exit_code);
ReadFileTimeout(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, &ByteOffset, 10);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(g_hChildStd_OUT_Wr);
CloseHandle(g_hChildStd_OUT_Rd);
if ((exit_code == 0) && (lstrlenA(chBuf) != 0)) {
exit_code = -1;
}
free(buffer);
return (int)exit_code;
}