-
-
Save vtorri/85660e0de3683d0ceef04e45f2decac0 to your computer and use it in GitHub Desktop.
CreateProcess() and environment variable
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <windows.h> | |
#define STRSAFE_NO_CB_FUNCTIONS | |
#include <strsafe.h> | |
#define DBG(s) \ | |
do { \ | |
printf("%s failed: %ld %s\n", (s), GetLastError(), win32_error()); \ | |
} while (0) | |
#define CLOSE_PIPE(p_) \ | |
do \ | |
{ \ | |
if ((p_) != INVALID_HANDLE_VALUE && !CloseHandle(p_)) \ | |
DBG("failed to close pipe"); \ | |
p_ = INVALID_HANDLE_VALUE; \ | |
} while (0) | |
typedef struct | |
{ | |
OVERLAPPED overlap; /* not used right now */ | |
HANDLE pipe[2]; | |
} Pipe; | |
static int dont_capture = 0; | |
static char _msg[4096]; | |
static const char *chdir = "c:\\users\\vincent.torri"; | |
Pipe pipe_out, pipe_err; | |
const char *win32_error(void) | |
{ | |
LPTSTR msg; | |
DWORD err; | |
*_msg = '\0'; | |
err = GetLastError(); | |
if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0UL, (LPTSTR)&msg, 0UL, NULL)) { | |
StringCchPrintf(_msg, sizeof(_msg), "FormatMessage() failed with error Id %ld", GetLastError()); | |
return _msg; | |
} | |
StringCchCat(_msg, sizeof(_msg), msg); | |
LocalFree(msg); | |
return _msg; | |
} | |
int create_pipe(SECURITY_ATTRIBUTES *sa) | |
{ | |
char *pipe_out_name = "\\\\.\\pipe\\run_cmd_pipe_out1"; | |
char *pipe_err_name = "\\\\.\\pipe\\run_cmd_pipe_errz"; | |
HANDLE p; | |
pipe_out.pipe[0] = INVALID_HANDLE_VALUE; | |
pipe_out.pipe[1] = INVALID_HANDLE_VALUE; | |
pipe_err.pipe[0] = INVALID_HANDLE_VALUE; | |
pipe_err.pipe[1] = INVALID_HANDLE_VALUE; | |
/* pipe_out */ | |
p = CreateNamedPipe(pipe_out_name, | |
PIPE_ACCESS_INBOUND, | |
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, | |
1UL, | |
4096, 4096, | |
0UL, | |
sa); | |
if (p == INVALID_HANDLE_VALUE) | |
{ | |
DBG("CreateNamedPipe() failed to create read end of the pipe"); | |
return 0; | |
} | |
pipe_out.pipe[0] = p; | |
p = CreateFile(pipe_out_name, | |
FILE_WRITE_DATA | SYNCHRONIZE, | |
0UL, | |
sa, | |
OPEN_EXISTING, | |
FILE_ATTRIBUTE_NORMAL, | |
0UL); | |
if (p == INVALID_HANDLE_VALUE) | |
{ | |
DBG("CreateFile() failed to create write end of the pipe"); | |
CLOSE_PIPE(pipe_out.pipe[0]); | |
return 0; | |
} | |
pipe_out.pipe[1] = p; | |
/* pipe_err */ | |
p = CreateNamedPipe(pipe_err_name, | |
PIPE_ACCESS_INBOUND,// | FILE_FLAG_OVERLAPPED, | |
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, | |
1UL, | |
4096, 4096, | |
0UL, | |
sa); | |
if (p == INVALID_HANDLE_VALUE) | |
{ | |
DBG("CreateNamedPipe() failed to create read end of the pipe"); | |
CLOSE_PIPE(pipe_out.pipe[1]); | |
CLOSE_PIPE(pipe_out.pipe[0]); | |
return 0; | |
} | |
pipe_err.pipe[0] = p; | |
p = CreateFile(pipe_err_name, | |
FILE_WRITE_DATA | SYNCHRONIZE, | |
0UL, | |
sa, | |
OPEN_EXISTING, | |
FILE_ATTRIBUTE_NORMAL, | |
0UL); | |
if (p == INVALID_HANDLE_VALUE) | |
{ | |
DBG("CreateFile() failed to create write end of the pipe"); | |
CLOSE_PIPE(pipe_err.pipe[0]); | |
CLOSE_PIPE(pipe_out.pipe[1]); | |
CLOSE_PIPE(pipe_err.pipe[0]); | |
return 0; | |
} | |
pipe_err.pipe[1] = p; | |
return 1; | |
} | |
void | |
run_cmd(const char *cmd, char *options) | |
{ | |
PROCESS_INFORMATION pi; | |
STARTUPINFO si; | |
SECURITY_ATTRIBUTES sa; | |
HANDLE process; | |
BOOL res; | |
char *env; | |
sa.nLength = sizeof(SECURITY_ATTRIBUTES); | |
sa.lpSecurityDescriptor = NULL; | |
sa.bInheritHandle = TRUE; | |
if (!create_pipe(&sa)) | |
return; | |
ZeroMemory(&si,sizeof(STARTUPINFO)); | |
si.cb = sizeof(STARTUPINFO); | |
si.dwFlags = (dont_capture) ? 0UL : STARTF_USESTDHANDLES; | |
si.hStdOutput = pipe_out.pipe[1]; | |
// FIXME TODO stdin | |
si.hStdInput = NULL; | |
si.hStdError = pipe_err.pipe[1]; | |
//env = "MUON_PATH=foo\0"; | |
env = NULL; | |
res = CreateProcess("C:\\Documents\\msys2\\mingw64\\bin/python3.exe", | |
"\"-c\" \"C:\\Documents\\msys2\\home\\vincent.torri\\gitroot_64\\muon_gh\\mon_test/get-version.py\"", | |
NULL, NULL, TRUE, CREATE_SUSPENDED, env, chdir, &si, &pi); | |
if (!res) | |
{ | |
DBG("CreateProcess"); | |
return; | |
} | |
CLOSE_PIPE(pipe_err.pipe[1]); | |
CLOSE_PIPE(pipe_out.pipe[1]); | |
process = pi.hProcess; | |
ResumeThread(pi.hThread); | |
size_t sz = 1024; | |
size_t len = 0; | |
char *buf = calloc(sz, sizeof(char)); | |
while (1) | |
{ | |
DWORD bytes_read; | |
BOOL res; | |
res = ReadFile(pipe_out.pipe[0], &buf[len], sz - len, &bytes_read, NULL); | |
printf("res : %d %ld\n", res, bytes_read); | |
if (!res || !bytes_read) { | |
if (GetLastError() == ERROR_BROKEN_PIPE) { | |
break; | |
} | |
} | |
len += bytes_read; | |
if ((len + 1024) > sz) { | |
sz *= 2; | |
buf = realloc(buf, sz + 1); | |
memset(&buf[len], 0, (sz + 1) - len); | |
} | |
} | |
printf("child output: \"%s\"\n", buf); | |
#if 0 | |
DWORD ret; | |
ret = WaitForSingleObject(process, INFINITE); | |
switch (ret) | |
{ | |
case WAIT_OBJECT_0: | |
break; | |
default: | |
printf("child exited abnormally\n"); | |
} | |
#endif | |
} | |
int main() | |
{ | |
run_cmd("child.exe", "--version"); | |
CLOSE_PIPE(pipe_err.pipe[0]); | |
CLOSE_PIPE(pipe_out.pipe[0]); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment