mirror of
https://github.com/decompals/wibo.git
synced 2025-10-16 07:05:11 +00:00
117 lines
3.5 KiB
C
117 lines
3.5 KiB
C
#include "test_assert.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <windows.h>
|
|
|
|
static DWORD parse_exit_code(const char *value) {
|
|
TEST_CHECK(value != NULL);
|
|
DWORD result = 0;
|
|
for (const char *p = value; *p; ++p) {
|
|
TEST_CHECK(*p >= '0' && *p <= '9');
|
|
result = result * 10u + (DWORD)(*p - '0');
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static int child_main(int argc, char **argv) {
|
|
TEST_CHECK(argc >= 2);
|
|
(void)argv;
|
|
|
|
char exitBuffer[16];
|
|
DWORD exitLen = GetEnvironmentVariableA("WIBO_TEST_PROC_EXIT", exitBuffer, sizeof(exitBuffer));
|
|
TEST_CHECK(exitLen > 0 && exitLen < sizeof(exitBuffer));
|
|
DWORD desiredExit = parse_exit_code(exitBuffer);
|
|
|
|
Sleep(200);
|
|
return (int)desiredExit;
|
|
}
|
|
|
|
static void test_createprocess_failure(void) {
|
|
STARTUPINFOA si;
|
|
PROCESS_INFORMATION pi;
|
|
ZeroMemory(&si, sizeof(si));
|
|
si.cb = sizeof(si);
|
|
ZeroMemory(&pi, sizeof(pi));
|
|
|
|
SetLastError(0);
|
|
char bogusCommandLine[] = "child";
|
|
TEST_CHECK(
|
|
!CreateProcessA("Z:/definitely/missing.exe", bogusCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi));
|
|
DWORD error = GetLastError();
|
|
TEST_CHECK_MSG(error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND, "CreateProcessA missing file -> %lu",
|
|
(unsigned long)error);
|
|
}
|
|
|
|
static int parent_main(void) {
|
|
test_createprocess_failure();
|
|
|
|
char modulePath[MAX_PATH];
|
|
DWORD pathLen = GetModuleFileNameA(NULL, modulePath, (DWORD)sizeof(modulePath));
|
|
TEST_CHECK(pathLen > 0 && pathLen < sizeof(modulePath));
|
|
|
|
const DWORD childExitCode = 0x24u;
|
|
char commandLine[256];
|
|
snprintf(commandLine, sizeof(commandLine), "child placeholder %lu", (unsigned long)childExitCode);
|
|
|
|
char exitEnv[16];
|
|
snprintf(exitEnv, sizeof(exitEnv), "%lu", (unsigned long)childExitCode);
|
|
TEST_CHECK(SetEnvironmentVariableA("WIBO_TEST_PROC_EXIT", exitEnv));
|
|
TEST_CHECK(SetEnvironmentVariableA("WIBO_TEST_PROC_ROLE", "child"));
|
|
|
|
STARTUPINFOA si;
|
|
PROCESS_INFORMATION pi;
|
|
ZeroMemory(&si, sizeof(si));
|
|
si.cb = sizeof(si);
|
|
GetStartupInfoA(&si);
|
|
ZeroMemory(&pi, sizeof(pi));
|
|
|
|
TEST_CHECK(CreateProcessA(modulePath, commandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi));
|
|
TEST_CHECK(pi.hProcess != NULL);
|
|
SetEnvironmentVariableA("WIBO_TEST_PROC_EXIT", NULL);
|
|
SetEnvironmentVariableA("WIBO_TEST_PROC_ROLE", NULL);
|
|
|
|
HANDLE processHandle = NULL;
|
|
TEST_CHECK(DuplicateHandle(GetCurrentProcess(), pi.hProcess, GetCurrentProcess(), &processHandle, 0, FALSE,
|
|
DUPLICATE_SAME_ACCESS));
|
|
TEST_CHECK(processHandle != NULL);
|
|
TEST_CHECK(processHandle != pi.hProcess);
|
|
|
|
TEST_CHECK(CloseHandle(pi.hProcess));
|
|
TEST_CHECK_EQ(WAIT_FAILED, WaitForSingleObject(pi.hProcess, 0));
|
|
pi.hProcess = NULL;
|
|
|
|
Sleep(50);
|
|
|
|
TEST_CHECK_EQ(WAIT_TIMEOUT, WaitForSingleObject(processHandle, 0));
|
|
|
|
DWORD exitCode = 0;
|
|
TEST_CHECK(GetExitCodeProcess(processHandle, &exitCode));
|
|
TEST_CHECK_EQ(STILL_ACTIVE, exitCode);
|
|
|
|
TEST_CHECK_EQ(WAIT_TIMEOUT, WaitForSingleObject(processHandle, 10));
|
|
TEST_CHECK_EQ(WAIT_OBJECT_0, WaitForSingleObject(processHandle, 5000));
|
|
|
|
TEST_CHECK(GetExitCodeProcess(processHandle, &exitCode));
|
|
TEST_CHECK_EQ(childExitCode, exitCode);
|
|
|
|
TEST_CHECK(CloseHandle(processHandle));
|
|
if (pi.hThread) {
|
|
TEST_CHECK(CloseHandle(pi.hThread));
|
|
}
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
char role[16];
|
|
DWORD roleLen = GetEnvironmentVariableA("WIBO_TEST_PROC_ROLE", role, sizeof(role));
|
|
if (roleLen > 0 && roleLen < sizeof(role) && strcmp(role, "child") == 0) {
|
|
return child_main(argc, argv);
|
|
}
|
|
if (argc > 1 && strcmp(argv[1], "child") == 0) {
|
|
return child_main(argc, argv);
|
|
}
|
|
return parent_main();
|
|
}
|