2021-06-27 21:25:29 +00:00
|
|
|
/***
|
2022-01-29 11:49:11 +00:00
|
|
|
Copyright (C) 2021-2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
2021-06-27 21:25:29 +00:00
|
|
|
|
|
|
|
File: Process.Win32.cpp
|
2022-01-29 11:49:11 +00:00
|
|
|
Date: 2022-1-29
|
2021-06-27 21:25:29 +00:00
|
|
|
Author: Reece
|
|
|
|
***/
|
2021-09-30 14:57:41 +00:00
|
|
|
#include <Source/RuntimeInternal.hpp>
|
2021-06-27 21:25:29 +00:00
|
|
|
#include "Process.Win32.hpp"
|
|
|
|
#include <shellapi.h>
|
|
|
|
#include <tlhelp32.h>
|
2021-09-06 10:58:08 +00:00
|
|
|
#include <process.h>
|
2021-06-27 21:25:29 +00:00
|
|
|
|
|
|
|
namespace Aurora::Processes
|
|
|
|
{
|
2022-01-26 00:01:06 +00:00
|
|
|
static HANDLE gLeaderJob = INVALID_HANDLE_VALUE;
|
2021-06-27 21:25:29 +00:00
|
|
|
|
|
|
|
void InitWin32()
|
|
|
|
{
|
2022-01-29 11:49:11 +00:00
|
|
|
gLeaderJob = CreateJobObject(NULL, NULL);
|
2021-06-27 21:25:29 +00:00
|
|
|
if (!gLeaderJob)
|
|
|
|
{
|
|
|
|
SysPushErrorArg("CreateJobObject error");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli {};
|
|
|
|
jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
|
|
|
|
if (!SetInformationJobObject(gLeaderJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
|
|
|
|
{
|
|
|
|
SysPushErrorGen("SetInformationJobObject error");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-26 00:01:06 +00:00
|
|
|
void DeinitWin32()
|
|
|
|
{
|
|
|
|
AuWin32CloseHandle(gLeaderJob);
|
|
|
|
}
|
2021-11-05 17:34:23 +00:00
|
|
|
|
2022-01-29 11:49:11 +00:00
|
|
|
void AssignJobWorker(HANDLE handle)
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
2022-01-29 11:49:11 +00:00
|
|
|
if (gLeaderJob)
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
2022-01-29 11:49:11 +00:00
|
|
|
if (!AssignProcessToJobObject(gLeaderJob, handle))
|
|
|
|
{
|
|
|
|
SysPushErrorGen("Could not AssignProcessToObject");
|
|
|
|
}
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-29 11:49:11 +00:00
|
|
|
|
|
|
|
static bool HasWin32ProcessExited(HANDLE handle)
|
2022-01-26 00:01:06 +00:00
|
|
|
{
|
2022-01-29 11:49:11 +00:00
|
|
|
DWORD exitCode;
|
|
|
|
if (!GetExitCodeProcess(handle, &exitCode))
|
2022-01-26 00:01:06 +00:00
|
|
|
{
|
2022-01-29 11:49:11 +00:00
|
|
|
return true;
|
2022-01-26 00:01:06 +00:00
|
|
|
}
|
2022-01-29 11:49:11 +00:00
|
|
|
|
|
|
|
return exitCode != STILL_ACTIVE;
|
2022-01-26 00:01:06 +00:00
|
|
|
}
|
2022-01-29 11:49:11 +00:00
|
|
|
|
2021-06-27 21:25:29 +00:00
|
|
|
static BOOL TermWinHandleWin32Thread(HWND handle, LPARAM a)
|
|
|
|
{
|
|
|
|
SendMessageA(handle, WM_CLOSE, 0, 0);
|
|
|
|
(*reinterpret_cast<AuUInt32 *>(a))++;
|
|
|
|
return true;
|
|
|
|
}
|
2022-01-29 11:49:11 +00:00
|
|
|
|
|
|
|
static bool SendExtermianteWinloopCloseMessages(HANDLE handle)
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
|
|
|
THREADENTRY32 te{};
|
|
|
|
HANDLE h{};
|
|
|
|
|
2022-01-29 11:49:11 +00:00
|
|
|
h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, GetProcessId(handle));
|
2021-06-27 21:25:29 +00:00
|
|
|
if (h == INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
te.dwSize = sizeof(te);
|
|
|
|
AuUInt32 count{};
|
|
|
|
if (Thread32First(h, &te))
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
|
|
|
|
sizeof(te.th32OwnerProcessID))
|
|
|
|
{
|
|
|
|
EnumThreadWindows(te.th32ThreadID, TermWinHandleWin32Thread, reinterpret_cast<LPARAM>(&count));
|
|
|
|
}
|
|
|
|
te.dwSize = sizeof(te);
|
|
|
|
} while (Thread32Next(h, &te));
|
|
|
|
}
|
|
|
|
|
|
|
|
CloseHandle(h);
|
|
|
|
|
|
|
|
if (!count)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2022-01-29 11:49:11 +00:00
|
|
|
|
|
|
|
return true;
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
2022-01-29 11:49:11 +00:00
|
|
|
|
|
|
|
static bool SendControlCEquiv(HANDLE handle)
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
2022-01-29 11:49:11 +00:00
|
|
|
if (!(AttachConsole(GetProcessId(handle))))
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
2021-09-06 10:58:08 +00:00
|
|
|
return false;
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
2021-09-06 10:58:08 +00:00
|
|
|
|
2022-01-29 11:49:11 +00:00
|
|
|
if (SetConsoleCtrlHandler({}, true))
|
|
|
|
{
|
|
|
|
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
|
|
|
|
SysAssert(FreeConsole(), "Couldn't pop off zombie process console");
|
|
|
|
Sleep(750);
|
|
|
|
}
|
|
|
|
else
|
2021-12-24 14:34:55 +00:00
|
|
|
{
|
2022-01-29 11:49:11 +00:00
|
|
|
SysAssert(FreeConsole(), "Couldn't pop off zombie process console");
|
2021-12-24 14:34:55 +00:00
|
|
|
return false;
|
|
|
|
}
|
2022-01-29 11:49:11 +00:00
|
|
|
|
|
|
|
if (!SetConsoleCtrlHandler({}, true))
|
2021-12-24 14:34:55 +00:00
|
|
|
{
|
2022-01-29 11:49:11 +00:00
|
|
|
SysPushErrorHAL("Couldn't swap control+c handler -> wont accept control termination on exit");
|
2021-12-24 14:34:55 +00:00
|
|
|
}
|
2022-01-29 11:49:11 +00:00
|
|
|
|
|
|
|
return true;
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
2022-01-29 11:49:11 +00:00
|
|
|
|
|
|
|
static bool Wait2500OrUntilClose(HANDLE handle)
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
2022-01-29 11:49:11 +00:00
|
|
|
return Threading::YieldPoll(true, 2500, [=]()
|
|
|
|
{
|
|
|
|
return !HasWin32ProcessExited(handle);
|
|
|
|
});
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
2022-01-29 11:49:11 +00:00
|
|
|
|
|
|
|
bool SendExitSignal(HANDLE handle)
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
2022-01-29 11:49:11 +00:00
|
|
|
if (handle == INVALID_HANDLE_VALUE)
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-01-29 11:49:11 +00:00
|
|
|
if (!(SendControlCEquiv(handle) // send GenerateConsoleCtrlEvent
|
|
|
|
|| SendExtermianteWinloopCloseMessages(handle))) // send WM_CLOSE
|
2021-10-24 10:19:47 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2021-06-27 21:25:29 +00:00
|
|
|
|
2022-01-29 11:49:11 +00:00
|
|
|
return Wait2500OrUntilClose(handle);
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
|
|
|
}
|