1 #include "command.h"
2
3 #include "config.h"
4 #include "log.h"
5 #include "str_util.h"
6
7 static int
build_cmd(char * cmd,size_t len,const char * const argv[])8 build_cmd(char *cmd, size_t len, const char *const argv[]) {
9 // Windows command-line parsing is WTF:
10 // <http://daviddeley.com/autohotkey/parameters/parameters.htm#WINPASS>
11 // only make it work for this very specific program
12 // (don't handle escaping nor quotes)
13 size_t ret = xstrjoin(cmd, argv, ' ', len);
14 if (ret >= len) {
15 LOGE("Command too long (%" PRIsizet " chars)", len - 1);
16 return -1;
17 }
18 return 0;
19 }
20
21 enum process_result
cmd_execute(const char * path,const char * const argv[],HANDLE * handle)22 cmd_execute(const char *path, const char *const argv[], HANDLE *handle) {
23 STARTUPINFOW si;
24 PROCESS_INFORMATION pi;
25 memset(&si, 0, sizeof(si));
26 si.cb = sizeof(si);
27
28 char cmd[256];
29 if (build_cmd(cmd, sizeof(cmd), argv)) {
30 *handle = NULL;
31 return PROCESS_ERROR_GENERIC;
32 }
33
34 wchar_t *wide = utf8_to_wide_char(cmd);
35 if (!wide) {
36 LOGC("Cannot allocate wide char string");
37 return PROCESS_ERROR_GENERIC;
38 }
39
40 #ifdef WINDOWS_NOCONSOLE
41 int flags = CREATE_NO_WINDOW;
42 #else
43 int flags = 0;
44 #endif
45 if (!CreateProcessW(NULL, wide, NULL, NULL, FALSE, flags, NULL, NULL, &si,
46 &pi)) {
47 SDL_free(wide);
48 *handle = NULL;
49 if (GetLastError() == ERROR_FILE_NOT_FOUND) {
50 return PROCESS_ERROR_MISSING_BINARY;
51 }
52 return PROCESS_ERROR_GENERIC;
53 }
54
55 SDL_free(wide);
56 *handle = pi.hProcess;
57 return PROCESS_SUCCESS;
58 }
59
60 bool
cmd_terminate(HANDLE handle)61 cmd_terminate(HANDLE handle) {
62 return TerminateProcess(handle, 1) && CloseHandle(handle);
63 }
64
65 bool
cmd_simple_wait(HANDLE handle,DWORD * exit_code)66 cmd_simple_wait(HANDLE handle, DWORD *exit_code) {
67 DWORD code;
68 if (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0
69 || !GetExitCodeProcess(handle, &code)) {
70 // cannot wait or retrieve the exit code
71 code = -1; // max value, it's unsigned
72 }
73 if (exit_code) {
74 *exit_code = code;
75 }
76 return !code;
77 }
78
79 char *
get_executable_path(void)80 get_executable_path(void) {
81 HMODULE hModule = GetModuleHandleW(NULL);
82 if (!hModule) {
83 return NULL;
84 }
85 WCHAR buf[MAX_PATH + 1]; // +1 for the null byte
86 int len = GetModuleFileNameW(hModule, buf, MAX_PATH);
87 if (!len) {
88 return NULL;
89 }
90 buf[len] = '\0';
91 return utf8_from_wide_char(buf);
92 }
93