| 3470 | |
| 3471 | # if !USE_SHELL_API |
| 3472 | static |
| 3473 | int |
| 3474 | run_program(const std::string& command) |
| 3475 | { |
| 3476 | STARTUPINFO si{}; |
| 3477 | si.cb = sizeof(si); |
| 3478 | PROCESS_INFORMATION pi{}; |
| 3479 | |
| 3480 | // Allegedly CreateProcess overwrites the command line. Ugh. |
| 3481 | std::string mutable_command(command); |
| 3482 | if (CreateProcess(nullptr, &mutable_command[0], |
| 3483 | nullptr, nullptr, FALSE, CREATE_NO_WINDOW, nullptr, nullptr, &si, &pi)) |
| 3484 | { |
| 3485 | WaitForSingleObject(pi.hProcess, INFINITE); |
| 3486 | DWORD exit_code; |
| 3487 | bool got_exit_code = !!GetExitCodeProcess(pi.hProcess, &exit_code); |
| 3488 | CloseHandle(pi.hProcess); |
| 3489 | CloseHandle(pi.hThread); |
| 3490 | // Not 100% sure about this still active thing is correct, |
| 3491 | // but I'm going with it because I *think* WaitForSingleObject might |
| 3492 | // return in some cases without INFINITE-ly waiting. |
| 3493 | // But why/wouldn't GetExitCodeProcess return false in that case? |
| 3494 | if (got_exit_code && exit_code != STILL_ACTIVE) |
| 3495 | return static_cast<int>(exit_code); |
| 3496 | } |
| 3497 | return EXIT_FAILURE; |
| 3498 | } |
| 3499 | # endif // !USE_SHELL_API |
| 3500 | |
| 3501 | static |