AuroraRuntime/Source/Processes/Process.Win32.cpp

155 lines
3.8 KiB
C++
Raw Normal View History

2021-06-27 21:25:29 +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
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
{
static HANDLE gLeaderJob = INVALID_HANDLE_VALUE;
2021-06-27 21:25:29 +00:00
void InitWin32()
{
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");
}
}
void DeinitWin32()
{
AuWin32CloseHandle(gLeaderJob);
}
void AssignJobWorker(HANDLE handle)
2021-06-27 21:25:29 +00:00
{
if (gLeaderJob)
2021-06-27 21:25:29 +00:00
{
if (!AssignProcessToJobObject(gLeaderJob, handle))
{
SysPushErrorGen("Could not AssignProcessToObject");
}
2021-06-27 21:25:29 +00:00
}
}
static bool HasWin32ProcessExited(HANDLE handle)
{
DWORD exitCode;
if (!GetExitCodeProcess(handle, &exitCode))
{
return true;
}
return exitCode != STILL_ACTIVE;
}
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;
}
static bool SendExtermianteWinloopCloseMessages(HANDLE handle)
2021-06-27 21:25:29 +00:00
{
THREADENTRY32 te{};
HANDLE h{};
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;
}
return true;
2021-06-27 21:25:29 +00:00
}
static bool SendControlCEquiv(HANDLE handle)
2021-06-27 21:25:29 +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
if (SetConsoleCtrlHandler({}, true))
{
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
SysAssert(FreeConsole(), "Couldn't pop off zombie process console");
Sleep(750);
}
else
{
SysAssert(FreeConsole(), "Couldn't pop off zombie process console");
return false;
}
if (!SetConsoleCtrlHandler({}, true))
{
SysPushErrorHAL("Couldn't swap control+c handler -> wont accept control termination on exit");
}
return true;
2021-06-27 21:25:29 +00:00
}
static bool Wait2500OrUntilClose(HANDLE handle)
2021-06-27 21:25:29 +00:00
{
return Threading::YieldPoll(true, 2500, [=]()
{
return !HasWin32ProcessExited(handle);
});
2021-06-27 21:25:29 +00:00
}
bool SendExitSignal(HANDLE handle)
2021-06-27 21:25:29 +00:00
{
if (handle == INVALID_HANDLE_VALUE)
2021-06-27 21:25:29 +00:00
{
return false;
}
if (!(SendControlCEquiv(handle) // send GenerateConsoleCtrlEvent
|| SendExtermianteWinloopCloseMessages(handle))) // send WM_CLOSE
{
return false;
}
2021-06-27 21:25:29 +00:00
return Wait2500OrUntilClose(handle);
2021-06-27 21:25:29 +00:00
}
}