Skip to content

Instantly share code, notes, and snippets.

@vtorri
Created December 9, 2022 10:54
Show Gist options
  • Save vtorri/85660e0de3683d0ceef04e45f2decac0 to your computer and use it in GitHub Desktop.
Save vtorri/85660e0de3683d0ceef04e45f2decac0 to your computer and use it in GitHub Desktop.
CreateProcess() and environment variable
#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