Skip to content

Instantly share code, notes, and snippets.

@mbikovitsky
Created February 28, 2022 19:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mbikovitsky/18a4339f690d86fc340bd4052e12d39a to your computer and use it in GitHub Desktop.
Save mbikovitsky/18a4339f690d86fc340bd4052e12d39a to your computer and use it in GitHub Desktop.
Passing arbitrary data to a child process. Inspired by https://github.com/microsoft/vscode-python/issues/18561#issuecomment-1054306197
#include <assert.h>
#include <Windows.h>
#pragma pack(push, 1)
typedef struct MAGIC_SAUCE
{
INT nHandleCount;
HANDLE hEvent;
} MAGIC_SAUCE;
#pragma pack(pop)
INT wmain(VOID)
{
HRESULT hrResult = E_FAIL;
DWORD eWaitStatus = WAIT_FAILED;
STARTUPINFOW tOriginalStartupInfo = {0};
MAGIC_SAUCE UNALIGNED * ptSauce = NULL;
HANDLE hEventToSignal = NULL;
WCHAR wszExecutable[MAX_PATH + 1] = {L'\0'};
DWORD cchCopied = 0;
SECURITY_ATTRIBUTES tEventAttributes = {0};
HANDLE hEvent = NULL;
MAGIC_SAUCE tSauce = {0};
STARTUPINFOW tNewStartupInfo = {0};
PROCESS_INFORMATION tProcessInfo = {0};
HANDLE ahObjectsToWaitOn[2] = {NULL};
GetStartupInfoW(&tOriginalStartupInfo);
if (sizeof(MAGIC_SAUCE) == tOriginalStartupInfo.cbReserved2)
{
ptSauce = (MAGIC_SAUCE UNALIGNED *)tOriginalStartupInfo.lpReserved2;
if (NULL != ptSauce && 0 == ptSauce->nHandleCount)
{
// This is the child process.
hEventToSignal = ptSauce->hEvent;
if (NULL == hEventToSignal)
{
hrResult = E_INVALIDARG;
goto lblCleanup;
}
if (!SetEvent(hEventToSignal))
{
hrResult = HRESULT_FROM_WIN32(GetLastError());
goto lblCleanup;
}
hrResult = S_OK;
goto lblCleanup;
}
}
cchCopied = GetModuleFileNameW(NULL, wszExecutable, ARRAYSIZE(wszExecutable));
if (0 == cchCopied)
{
hrResult = HRESULT_FROM_WIN32(GetLastError());
goto lblCleanup;
}
else if (ARRAYSIZE(wszExecutable) == cchCopied)
{
hrResult = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
goto lblCleanup;
}
tEventAttributes.nLength = sizeof(tEventAttributes);
tEventAttributes.bInheritHandle = TRUE;
hEvent = CreateEventW(&tEventAttributes, TRUE, FALSE, NULL);
if (NULL == hEvent)
{
hrResult = HRESULT_FROM_WIN32(GetLastError());
goto lblCleanup;
}
tSauce.nHandleCount = 0;
tSauce.hEvent = hEvent;
tNewStartupInfo.cb = sizeof(tNewStartupInfo);
tNewStartupInfo.cbReserved2 = sizeof(tSauce);
tNewStartupInfo.lpReserved2 = (PBYTE)&tSauce;
if (!CreateProcessW(wszExecutable,
NULL,
NULL,
NULL,
TRUE,
CREATE_UNICODE_ENVIRONMENT,
NULL,
NULL,
&tNewStartupInfo,
&tProcessInfo))
{
hrResult = HRESULT_FROM_WIN32(GetLastError());
goto lblCleanup;
}
ahObjectsToWaitOn[0] = hEvent;
ahObjectsToWaitOn[1] = tProcessInfo.hProcess;
eWaitStatus =
WaitForMultipleObjects(ARRAYSIZE(ahObjectsToWaitOn), ahObjectsToWaitOn, TRUE, INFINITE);
if (WAIT_OBJECT_0 != eWaitStatus)
{
hrResult = HRESULT_FROM_WIN32(GetLastError());
assert(WAIT_FAILED == eWaitStatus);
goto lblCleanup;
}
hrResult = S_OK;
lblCleanup:
if (NULL != tProcessInfo.hThread)
{
(VOID) CloseHandle(tProcessInfo.hThread);
tProcessInfo.hThread = NULL;
}
if (NULL != tProcessInfo.hProcess)
{
(VOID) CloseHandle(tProcessInfo.hProcess);
tProcessInfo.hProcess = NULL;
}
if (NULL != hEvent)
{
(VOID) CloseHandle(hEvent);
hEvent = NULL;
}
if (NULL != hEventToSignal)
{
(VOID) CloseHandle(hEventToSignal);
hEventToSignal = NULL;
}
return (INT)hrResult;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment