Modified uniproc_create_process signature to take a command and a list of arguments Updated uniproc_win64.c to terminate the process before closing the handles Updated uniproc_win64.c to convert the command and list of arguments into a command-line string
122 lines
3.2 KiB
C
122 lines
3.2 KiB
C
#if defined(_WIN32) || defined(_WIN64)
|
|
#include "uniproc.h"
|
|
#include <Windows.h>
|
|
#include <fcntl.h>
|
|
#include <io.h>
|
|
|
|
uniproc_process uniproc_create_process(const char* cmd, const size_t num_args, const char** argv)
|
|
{
|
|
// Create pipes
|
|
HANDLE child_in;
|
|
HANDLE in;
|
|
HANDLE child_out;
|
|
HANDLE out;
|
|
HANDLE child_err;
|
|
HANDLE err;
|
|
|
|
SECURITY_ATTRIBUTES pipe_attribs;
|
|
pipe_attribs.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
pipe_attribs.bInheritHandle = 1;
|
|
pipe_attribs.lpSecurityDescriptor = NULL;
|
|
|
|
// Actually create the pipes
|
|
if (!CreatePipe(&out, &child_out, &pipe_attribs, 0))
|
|
exit(EXIT_FAILURE);
|
|
if (!CreatePipe(&err, &child_err, &pipe_attribs, 0))
|
|
exit(EXIT_FAILURE);
|
|
if (!CreatePipe(&child_in, &in, &pipe_attribs, 0))
|
|
exit(EXIT_FAILURE);
|
|
|
|
// Unset inherrit flags for the pipes
|
|
if (!SetHandleInformation(out, HANDLE_FLAG_INHERIT, 0))
|
|
exit(EXIT_FAILURE);
|
|
if (!SetHandleInformation(err, HANDLE_FLAG_INHERIT, 0))
|
|
exit(EXIT_FAILURE);
|
|
if (!SetHandleInformation(in, HANDLE_FLAG_INHERIT, 0))
|
|
exit(EXIT_FAILURE);
|
|
|
|
// Create child process
|
|
uniproc_process p;
|
|
|
|
// Create p_cmd by appending all argv's to cmd
|
|
size_t x = strlen(cmd);
|
|
size_t cmd_len = x + 1;
|
|
for (size_t i = 0; i < num_args; ++i)
|
|
cmd_len += strlen(argv[i]) + 1;
|
|
char* p_cmd = malloc((cmd_len+1) * sizeof(char));
|
|
memcpy(p_cmd, cmd, x * sizeof(char));
|
|
x += 1; // Account for space after cmd
|
|
for (size_t i = 0; i < num_args; ++i)
|
|
{
|
|
size_t arglen = strlen(argv[i]);
|
|
memcpy(p_cmd + x, argv[i], arglen);
|
|
p_cmd[x + arglen] = ' ';
|
|
x += arglen + 1
|
|
}
|
|
p_cmd[cmd_len] = '\0';
|
|
|
|
PROCESS_INFORMATION p_info;
|
|
STARTUPINFOA p_startup;
|
|
memset(&p_info, 0, sizeof(PROCESS_INFORMATION));
|
|
memset(&p_startup, 0, sizeof(STARTUPINFOA));
|
|
|
|
p_startup.cb = sizeof(STARTUPINFOA);
|
|
p_startup.dwFlags |= STARTF_USESTDHANDLES;
|
|
p_startup.hStdInput = child_in;
|
|
p_startup.hStdOutput = child_out;
|
|
p_startup.hStdError = child_err;
|
|
|
|
int is_ok = CreateProcessA(
|
|
NULL,// Application name
|
|
p_cmd, // Command to execute
|
|
NULL,// Security attributes
|
|
NULL,// Primary thread security
|
|
1, // Inherrit handles
|
|
0, // Creation flags
|
|
NULL,// Environment (use parent's)
|
|
NULL,// Current directory (use parent's)
|
|
&p_startup,
|
|
&p_info
|
|
);
|
|
free(p_cmd);
|
|
|
|
if (!is_ok)
|
|
exit(EXIT_FAILURE);
|
|
|
|
p.err = _fdopen(_open_osfhandle((intptr_t)err, _O_RDONLY), "r");
|
|
p.out = _fdopen(_open_osfhandle((intptr_t)out, _O_RDONLY), "r");
|
|
p.in = _fdopen(_open_osfhandle( (intptr_t)in, _O_WRONLY), "w");
|
|
p._proc_hdl = (uint32_t)p_info.hProcess;
|
|
|
|
CloseHandle(child_in);
|
|
CloseHandle(child_out);
|
|
CloseHandle(child_err);
|
|
CloseHandle(p_info.hThread);
|
|
|
|
return p;
|
|
}
|
|
|
|
void uniproc_await_processes(uniproc_process* p, int* return_codes, size_t num_processes)
|
|
{
|
|
HANDLE* h = (HANDLE*)malloc(num_processes*sizeof(HANDLE));
|
|
for (size_t i = 0; i < num_processes; ++i)
|
|
h[i] = (HANDLE)p[i]._proc_hdl;
|
|
|
|
WaitForMultipleObjects(num_processes, h, 1, INFINITE);
|
|
free(h);
|
|
|
|
if (return_codes == NULL) return;
|
|
for (size_t i = 0; i < num_processes; ++i)
|
|
GetExitCodeProcess((HANDLE)p[i]._proc_hdl, (LPDWORD)(return_codes+i));
|
|
}
|
|
|
|
void uniproc_close_process(uniproc_process* p)
|
|
{
|
|
TerminateProcess((HANDLE)p->_proc_hdl, 2);
|
|
CloseHandle((HANDLE)p->_proc_hdl);
|
|
fclose(p->in);
|
|
fclose(p->out);
|
|
fclose(p->err);
|
|
}
|
|
|
|
#endif |