#include <windows.h>
#include <detours.h>
#include <math.h>
#include <stdio.h>

#include "Core.h"
#include "Engine.h"

#define EXCEPTION_PRIVILEDGED_INSTRUCTION (DWORD)0xc0000096

struct URedirection_Plugin {
	class UObject* Object;
	URedirection_Plugin* Next;
};

struct URedirection_Package {
	FString Filename;
	FString Redirect;
	INT Action;
	FString QuickMD5;
	FString FullMD5;
	FString GUID;
	URedirection_Package* Next;
};

URedirection_Plugin* PluginList		= 0;
URedirection_Package* PackageList	= 0;

static bool bHidePlugins		= 1;
static bool bLogPlugins			= 1;
static bool bLogChecks			= 1;

// Core 3369 hook related
DWORD dwFString_0				= 0;	// 10110BD0									??0FString@@QAE@PBG@Z
DWORD dwFString_4				= 0;	// 10110D30									??4FString@@QAEAAV0@ABV0@@Z
DWORD dwString					= 0;	// 101024D0									?String@FGuid@@QBEPAGXZ
DWORD dwPrintf					= 0;	// 1013C9C0									?Printf@FString@@SA?AV1@PBGZZ:
DWORD dwGetName					= 0;	// 1010CC10									?GetName@UObject@@QBEPBGXZ

DWORD dwProcessEvent			= 0;	// 1012FFC0									?ProcessEvent@UObject@@UAEXPAVUFunction@@PAX1@Z
DWORD dwGetReferencers			= 0;	// 10149F1B  83C408                    		add	esp,00000008h
DWORD dwAllObjects				= 0;	// 10131C00									?execAllObjects@UObject@@QAEXAAUFFrame@@QAX@Z

DWORD dwJmp_ProcessEvent		= 0;
DWORD dwJmp_GetReferencers		= 0;
DWORD dwJmp_AllObjects			= 0;

// Engine 3369 hook related
DWORD dwLP_Init					= 0;	// 104D2100  83C404                    		add	esp,00000004h
DWORD dwLP_ServerJoin			= 0;	// 10424BA8  FF15D8676110              		call	[Core.dll!?String@FGuid@@QBEPAGXZ]
DWORD dwLP_QuickMD5				= 0;	// 104D220B  8BF8                      		mov	edi,eax
DWORD dwLP_FullMD5				= 0;	// 104D24ED  8B7DEC                    		mov	edi,[ebp-14h]
DWORD dwLP_PackageList			= 0;	// 104D2631  FF159C616110              		call	[Core.dll!?GetName@UObject@@QBEPBGXZ]
DWORD dwNP_Init					= 0;	// 104D1957  83C404                    		add	esp,00000004h
 
DWORD dwJmp_LP_Init				= 0;
DWORD dwJmp_LP_ServerJoin		= 0;
DWORD dwJmp_LP_PackageList		= 0;
DWORD dwJmp_LP_QuickMD5			= 0;
DWORD dwJmp_LP_FullMD5			= 0;
DWORD dwJmp_NP_Init				= 0;

// Local function parameters
class UFunction* pFunction;
void* pParms;
int SecType;
FString Param1;
FString Param2;
void* Pointer;
FString Result;
FString LastFile;

bool AddVectoredExceptionHandler (void* pHandler)
{
	void* AddVectoredExceptionHandler = (void*)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "AddVectoredExceptionHandler");

	if (AddVectoredExceptionHandler)
	{
		_asm
		{
			push pHandler
			push 1
			call AddVectoredExceptionHandler
		}
	}

	return true;
}

DWORD HookFunction (DWORD dwAddress, int iSkip)
{
	if (iSkip < 1)
		return 0;

	DWORD dwProtect = PAGE_EXECUTE_READWRITE;

	VirtualProtect((void*)dwAddress, 1, dwProtect, &dwProtect);
	((BYTE*)dwAddress)[0] = 0xF4;
	VirtualProtect((void*)dwAddress, 1, dwProtect, &dwProtect);

	return (DWORD)(dwAddress + iSkip);
}
