Files
UnrealEngine/Engine/Source/Programs/UnrealBuildAccelerator/Detours/Private/Windows/UbaDetoursMainWin.cpp
2025-05-18 13:04:45 +08:00

183 lines
4.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#if defined( __clang_analyzer__ )
#include <corecrt.h>
#undef __DEFINE_CPP_OVERLOAD_SECURE_FUNC_SPLITPATH
#define __DEFINE_CPP_OVERLOAD_SECURE_FUNC_SPLITPATH(_ReturnType, _FuncName, _DstType, _Src)
#endif
#include "UbaProtocol.h"
#include "UbaProcessStats.h"
#include "UbaDetoursPayload.h"
#include "UbaDetoursShared.h"
#include "UbaDetoursFunctionsWin.h"
#include <detours/detours.h>
#include <stdio.h>
namespace uba
{
HANDLE g_hostProcess;
HANDLE g_writeEvent;
HANDLE g_readEvent;
HANDLE g_cancelEvent;
HANDLE g_messageMappingHandle;
u8* g_readMessageMappingMem;
u8* g_writeMessageMappingMem;
bool WasCancelled()
{
return WaitForSingleObject(g_cancelEvent, 0) != WAIT_TIMEOUT;
}
int Connect(DetoursPayload& payload)
{
g_hostProcess = payload.hostProcess;
if (!DuplicateHandle(g_hostProcess, payload.cancelEvent, GetCurrentProcess(), &g_cancelEvent, SYNCHRONIZE, false, 0))
{
UBA_ASSERT(!WasCancelled());
return -4;
}
// Sync primitive for writing message to host process
if (!DuplicateHandle(g_hostProcess, payload.readEvent, GetCurrentProcess(), &g_writeEvent, EVENT_MODIFY_STATE, false, 0))
return -2;
// Sync primitive for reading messages from host process
if (!DuplicateHandle(g_hostProcess, payload.writeEvent, GetCurrentProcess(), &g_readEvent, SYNCHRONIZE, false, 0))
return -3;
if (!DuplicateHandle(g_hostProcess, payload.communicationHandle, GetCurrentProcess(), &g_messageMappingHandle, FILE_MAP_READ | FILE_MAP_WRITE, false, 0))
{
UBA_ASSERT(!WasCancelled());
return -4;
}
u8* mem = (u8*)::MapViewOfFile(g_messageMappingHandle, FILE_MAP_READ | FILE_MAP_WRITE, ToHigh(payload.communicationOffset), ToLow(payload.communicationOffset), CommunicationMemSize);
g_readMessageMappingMem = mem;
g_writeMessageMappingMem = mem;// +CommunicationMemSize / 2;
return 0;
}
int Disconnect()
{
UnmapViewOfFile(g_writeMessageMappingMem);
CloseHandle(g_messageMappingHandle);
CloseHandle(g_cancelEvent);
CloseHandle(g_readEvent);
CloseHandle(g_writeEvent);
CloseHandle(g_hostProcess);
return 0;
}
ANALYSIS_NORETURN void TerminateCurrentProcess(u32 exitCode)
{
if (True_TerminateProcess)
True_TerminateProcess(GetCurrentProcess(), exitCode);
else
TerminateProcess(GetCurrentProcess(), exitCode);
}
BinaryWriter::BinaryWriter()
{
m_begin = g_writeMessageMappingMem;
m_pos = m_begin;
m_end = m_begin + CommunicationMemSize;// / 2;
}
void BinaryWriter::Flush(bool waitOnResponse)
{
if (!waitOnResponse)
{
SetEvent(g_writeEvent);
return;
}
TimerScope ts(g_stats.waitOnResponse);
DWORD res = SignalObjectAndWait(g_writeEvent, g_readEvent, 1000, FALSE);
do
{
if (res == WAIT_OBJECT_0)
break;
if (res != WAIT_TIMEOUT)
TerminateCurrentProcess(1337);
DWORD exitCode;
if (!True_GetExitCodeProcess(g_hostProcess, &exitCode))
TerminateCurrentProcess(1338);
if (exitCode != STILL_ACTIVE)
TerminateCurrentProcess(1339);
DWORD cancelRes = True_WaitForSingleObject(g_cancelEvent, 0);
if (cancelRes == WAIT_OBJECT_0)
ExitProcess(1339);
else if (cancelRes != WAIT_TIMEOUT)
TerminateCurrentProcess(1353);
res = True_WaitForSingleObject(g_readEvent, 500);
} while (true);
}
BinaryReader::BinaryReader()
{
m_begin = g_readMessageMappingMem;
m_pos = m_begin;
m_end = m_begin + CommunicationMemSize;// / 2;
}
}
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{
using namespace uba;
static GROUP_AFFINITY GroupAffinity;
u64 startTime = GetTime();
if (DetourIsHelperProcess())
return TRUE;
if (dwReason == DLL_PROCESS_ATTACH)
{
GetThreadGroupAffinity(GetCurrentThread(), &GroupAffinity);
if (!DetourRestoreAfterWith())
TerminateCurrentProcess(1344);
DetoursPayload* payload = (DetoursPayload*)DetourFindPayloadEx(DetoursPayloadGuid, nullptr);
if (!payload)
TerminateCurrentProcess(1342);
if (payload->version != ProcessMessageVersion)
TerminateCurrentProcess(1398);
PreInit(*payload);
int result = Connect(*payload);
if (result != 0)
{
Disconnect();
TerminateCurrentProcess(result);
}
Init(*payload, startTime);
}
else if (dwReason == DLL_THREAD_ATTACH)
{
SetThreadGroupAffinity(GetCurrentThread(), &GroupAffinity, NULL);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
Deinit(startTime);
Disconnect();
PostDeinit();
}
return TRUE;
}