#include "URedirection.h"

void Check_Linker ()
{
	bHideLinker = false;
	bFakeLinker = false;

	if (bLogChecks)
	{
		GLog->Logf(L"************* Linker *************");
		GLog->Logf(L" Package : %ls", Linker->Filename);
		GLog->Logf(L" ");
	}

	URedirection_Package* Package = PackageList;

	while (Package)
	{
		if (appStricmp(*StripFilePath(Package->Filename), *StripFilePath(Linker->Filename)) == 0)
		{
			if (Package->Action == FILE_HIDE)
			{
				if (bLogChecks)
					GLog->Logf(L" -> Hidding Package!");

				bHideLinker = true;
			}

			if ((Package->Action == FILE_FAKE) || (Package->Action == FILE_REDIRECT))
			{
				if (bLogChecks)
					GLog->Logf(L" -> Faking Package!");

				bFakeLinker = true;
				StrLinker1 = Package->Linker;
			}

			if (bLogChecks)
				GLog->Logf(L" ");

			return;
		}

		Package = Package->Next;
	}
}

__declspec (naked) void Linkers ()
{
	_asm mov edx, [ecx+eax*4]
	_asm mov Linker, edx

	_asm pushad
	Check_Linker();
	_asm popad

	_asm cmp bHideLinker, 1
	_asm jz Inc_Linkers_jmp
	_asm cmp bFakeLinker, 1
	_asm jz Log_Linkers_jmp

	_asm jmp dwJmp_Linkers

Inc_Linkers_jmp:
	_asm jmp dwJmp_Inc_Linkers

Log_Linkers_jmp:
	_asm push StrLinker1
	_asm push StrLinker0
	_asm mov ecx, [ebp+0Ch]
	_asm jmp dwJmp_Log_Linkers
}

void Process_PlayerTick (FLOAT DeltaTime)
{
	URedirection_Plugin* Plugin = PluginList;

	while (Plugin)
	{
		if (Plugin->Object != NULL)
		{
			if (Plugin->Object->FindFunction(L"PlayerTick") != NULL)
				Plugin->Object->ProcessEvent(Plugin->Object->FindFunction(L"PlayerTick"), &DeltaTime);

			if (Plugin->Object->FindFunction(L"Tick") != NULL)
				Plugin->Object->ProcessEvent(Plugin->Object->FindFunction(L"Tick"), &DeltaTime);
		}

		Plugin = Plugin->Next;
	}
}

void Process_PostRender (class UCanvas* Canvas)
{
	URedirection_Plugin* Plugin = PluginList;

	while (Plugin)
	{
		if (Plugin->Object != NULL)
		{
			if (Plugin->Object->FindFunction(L"PostRender") != NULL)
				Plugin->Object->ProcessEvent(Plugin->Object->FindFunction(L"PostRender"), &Canvas);
		}

		Plugin = Plugin->Next;
	}
}

void Process_Command (const TCHAR* Cmd)
{
	URedirection_Plugin* Plugin = PluginList;

	while (Plugin)
	{
		if (Plugin->Object != NULL)
		{
			Plugin->Object->ScriptConsoleExec(Cmd, *GLog, Plugin->Object);
		}

		Plugin = Plugin->Next;
	}
}

void Process_AddPawn (class APawn* Target)
{
	URedirection_Plugin* Plugin = PluginList;

	while (Plugin)
	{
		if (Plugin->Object != NULL)
		{
			if (Plugin->Object->FindFunction(L"AddPawn"))
				Plugin->Object->ProcessEvent(Plugin->Object->FindFunction(L"AddPawn"), &Target);
		}

		Plugin = Plugin->Next;
	}
}

void Process_RemovePawn (class APawn* Target)
{
	URedirection_Plugin* Plugin = PluginList;

	while (Plugin)
	{
		if (Plugin->Object != NULL)
		{
			if (Plugin->Object->FindFunction(L"RemovePawn"))
				Plugin->Object->ProcessEvent(Plugin->Object->FindFunction(L"RemovePawn"), &Target);
		}

		Plugin = Plugin->Next;
	}
}

void Check_ServerCallback ()
{
	URedirection_Package* Package = PackageList;

	while (Package)
	{
		if (SecType == 3)
		{
			GLog->Logf(L"%ls", Data);	
		}
		else
		{
			bool bMatched = false;

			if (SecType == 0)
				bMatched = (appStricmp(*StripFileExt(StripFilePath(LastFile)), *StripFileExt(StripFilePath(Package->Filename))) == 0);
			else
				bMatched = (appStricmp(*StripFilePath(LastFile), *StripFilePath(Package->Filename)) == 0);

			if (bMatched)
			{
				if (Package->Action == FILE_FAKE)
				{
					if (SecType == 0)
					{
						Data = Package->GUID + Package->QuickMD5;
					}
					else
					{
						Data = Package->FullMD5;
					}
				}
			}
		}

		Package = Package->Next;
	}
}

void LoadPlugins ()
{
	URedirection_Plugin* Plugin = PluginList;

	while (Plugin)
	{
		if (!Plugin->Object)
		{
			UClass* Cls = (UClass*)UClass::StaticLoadObject(UClass::StaticClass(), NULL, *Plugin->Filename, NULL, LOAD_NoWarn, NULL);

			if (Cls != NULL)
			{
				UObject* Obj = ConstructObject<UObject>(Cls);

				if (Obj != NULL)
				{
					Obj->SetFlags(Obj->GetFlags() | RF_Keep);

					if (Obj->FindFunction(L"Initialized") != NULL)
						Obj->ProcessEvent(Obj->FindFunction(L"Initialized"), 0);

					if (Obj->FindFunction(L"PluginStart") != NULL)
						Obj->ProcessEvent(Obj->FindFunction(L"PluginStart"), 0);

					if (bHidePlugins)
					{
						URedirection_Package* Package = new URedirection_Package();

						if (Package)
						{
							Package->Filename	= FString::Printf(L"%ls.u", Obj->GetClass()->GetOuter()->GetName());
							Package->Redirect	= L"";
							Package->Action		= FILE_HIDE;
							Package->QuickMD5	= L"";
							Package->FullMD5	= L"";
							Package->GUID		= L"";
							Package->Linker		= L"";

							if (PackageList)
								Package->Next = PackageList;

							PackageList = Package;
						}

						Package = new URedirection_Package();

						if (Package)
						{
							Package->Filename	= FString::Printf(L"%ls.ini", Obj->GetClass()->GetOuter()->GetName());
							Package->Redirect	= L"";
							Package->Action		= FILE_HIDE;
							Package->QuickMD5	= L"";
							Package->FullMD5	= L"";
							Package->GUID		= L"";
							Package->Linker		= L"";

							if (PackageList)
								Package->Next = PackageList;

							PackageList = Package;				
						}
					}

					Plugin->Object = Obj;
				}
			}
		}

		Plugin = Plugin->Next;
	}
}

bool Plugin_Called (class UClass* OwnerClass)
{
	URedirection_Plugin* Plugin = PluginList;

	while (Plugin)
	{
		if (Plugin->Object)
		{
			if (OwnerClass == Plugin->Object->GetClass())
			{
				return true;
			}
		}

		Plugin = Plugin->Next;
	}

	return false;
}

DWORD dwOrg_Master_BeginPlay	= 0;
DWORD dwJmp_Master_BeginPlay	= 0;

__declspec (naked) void Master_BeginPlay ()
{
	_asm pushad
	LoadPlugins();
	_asm popad

	_asm  call [edi+10h]
	_asm jmp dwJmp_Master_BeginPlay
}

DWORD dwOrg_Master_PlayerTick	= 0;
DWORD dwJmp_Master_PlayerTick	= 0;
void* pParms;
APlayerController* PC;
UProperty* Prop;

__declspec (naked) void Master_PlayerTick ()
{
	_asm mov pParms, edx
	_asm mov PC, ecx

	_asm call [edi+10h]

	_asm pushad
	Process_PlayerTick(((APlayerController_eventPlayerTick_Parms*)pParms)->DeltaTime);

	if (PC != NULL)
	{
		Prop = PC->GetClass()->PropertyLink;

		while (Prop)
		{
			if (Prop->IsA(UStructProperty::StaticClass()))
			{
				if (wcsicmp(Prop->GetName(), L"pRealRotation") == 0)
				{
					*((FRotator*)((BYTE*)PC+Prop->Offset)) = PC->Rotation;

					break;
				}
			}

			Prop = Prop->PropertyLinkNext;
		}

		if ((PC->PlayerSecurity != NULL) && (wcsicmp(PC->PlayerSecurity->GetName(), L"AntiTCCSecurity") == 0))
		{
			Prop = PC->PlayerSecurity->GetClass()->PropertyLink;

			while (Prop)
			{
				if (Prop->IsA(UStructProperty::StaticClass()))
				{
					if ((wcsicmp(Prop->GetName(), L"pRealRotation") == 0) ||	// AntiTCC 119 Betas
						(wcsicmp(Prop->GetName(), L"O19232O") == 0) ||			// AntiTCC 2009 R2
						(wcsicmp(Prop->GetName(), L"O10827O") == 0) ||			// AntiTCC 2009 R3
						(wcsicmp(Prop->GetName(), L"O34672O") == 0)	||			// AntiTCC 2009 R4a
						(wcsicmp(Prop->GetName(), L"O62375O") == 0) ||			// AntiTCC 2009 R5
						(wcsicmp(Prop->GetName(), L"O47247O") == 0))			// AntiTCC 2009 R6
					{
						if (Prop->IsA(UStructProperty::StaticClass()))
						{
							*((FRotator*)((BYTE*)PC->PlayerSecurity+Prop->Offset)) = PC->Rotation;

							break;
						}
					}
				}

				Prop = Prop->PropertyLinkNext;
			}
		}
	}
	_asm popad

	_asm jmp dwJmp_Master_PlayerTick
}

DWORD dwOrg_Master_PostRender	= 0;
DWORD dwJmp_Master_PostRender	= 0;
class UCanvas* pCanvas			= 0;

_declspec (naked) void Master_PostRender ()
{
	_asm mov eax, [esp+4h]
	_asm mov pCanvas, eax

	_asm pushad
	Process_PostRender(pCanvas);
	_asm popad

	_asm push ebp
	_asm jmp dwJmp_Master_PostRender
}

bool bHideObject = false;
UObject* pObject;
UObject* pOuter;

void Check_Object ()
{
	bHideObject = false;

	URedirection_Plugin* Plugin = PluginList;

	while (Plugin)
	{
		if (Plugin->Object)
		{
			pOuter = pObject;

			while (pOuter)
			{
				if ((pOuter == Plugin->Object) || (pOuter == Plugin->Object->GetClass()) || (pOuter == Plugin->Object->GetClass()->GetOuter()))
				{
					bHideObject = true;

					if (pOuter->IsA(UObject::StaticClass()))
						pObject = GSys;

					if (pOuter->IsA(UClass::StaticClass()))
						pObject = GSys->GetClass();

					if (pOuter->IsA(UPackage::StaticClass()))
						pObject = GSys->GetClass()->GetOuter();
				}

				pOuter = pOuter->GetOuter();
			}
		}

		Plugin = Plugin->Next;
	}
}

DWORD dwJmp_Skip_Ref	= (DWORD)0x101488BA;

__declspec (naked) void GetReferencers ()
{
	_asm mov ebx, [edx+edi*4]
	_asm mov pObject, ebx

	_asm pushad
	Check_Object();
	_asm popad

	_asm cmp bHideObject, 1
	_asm jz Hide_Ref

	_asm jmp dwJmp_GetReferencers

Hide_Ref:
	_asm inc edi
	_asm jmp dwJmp_Skip_Ref
}

bool bHideDLO = false;

void Check_DLO ()
{
	bHideDLO = false;

	URedirection_Plugin* Plugin = PluginList;

	while (Plugin)
	{
		if (Plugin->Object)
		{
			if (appStricmp(*PointerToString(Pointer), *Plugin->Filename) == 0)
			{
				Data = FString::Printf(L"fuck.you");
				bHideDLO = true;
			}
		}

		Plugin = Plugin->Next;
	}
}

DWORD dwDynamicLoadObject		= 0;
DWORD dwJmp_DynamicLoadObject	= 0;
DWORD dwJmp_Skip_DLO			= (DWORD)0x1012CABB;

__declspec (naked) void DynamicLoadObject ()
{
	_asm mov Pointer, eax

	_asm pushad
	Check_DLO();
	_asm popad

	_asm cmp bHideDLO, 1
	_asm jz Hide_DLO

	_asm push eax
	_asm jmp dwJmp_DynamicLoadObject

Hide_DLO:
	_asm mov eax, Data
	_asm push eax
	_asm jmp dwJmp_DynamicLoadObject
}

DWORD dwJmp_Skip_Object = (DWORD)0x10131CD0;

__declspec (naked) void AllObjects ()
{
	_asm mov ecx, [edx+ebp*4]
	_asm mov pObject, ecx

	_asm pushad
	Check_Object();
	_asm popad

	_asm cmp bHideObject, 1
	_asm jz Hide_Object

	_asm jmp dwJmp_AllObjects

Hide_Object:
	_asm cmp pObject, ecx
	_asm jnz Fake_Object

	_asm inc ebp
	_asm jmp dwJmp_Skip_Object

Fake_Object:
	_asm mov ecx, pObject
	_asm jmp dwJmp_AllObjects
}

__declspec (naked) void GetCDKeyHash ()
{
	_asm cmp CDKeyHash, 0
	_asm jz Real_CDKeyHash

	_asm mov eax, CDKeyHash
	_asm jmp dwJmp_GetCDKeyHash

Real_CDKeyHash:
	_asm mov eax, edi
	_asm jmp dwJmp_GetCDKeyHash
}

void Perform_Check (const TCHAR* Function)
{
	LastFile = *PointerToString(Pointer);

	if (bLogChecks)
	{
		GLog->Logf(L"%ls", Function);
		GLog->Logf(L"SecType : %i", SecType);
		GLog->Logf(L"Param1  : %ls", Param1);
		GLog->Logf(L"Param2  : %ls", Param2);
		GLog->Logf(L" ");
	}

	URedirection_Package* Package = PackageList;

	while (Package)
	{
		bool bMatched = false;

		if (SecType != 2)
			bMatched = (appStricmp(*StripFileExt(StripFilePath(*PointerToString(Pointer))), *StripFileExt(StripFilePath(Package->Filename))) == 0);
		else
			bMatched = (appStricmp(*StripFilePath(PointerToString(Pointer)), *StripFilePath(Package->Filename)) == 0);

		if (bMatched)
		{
			if (Package->Action == FILE_HIDE)
			{
				if (bLogChecks)
					GLog->Logf(L" -> Hiding Package!");

				Param1 = L"HIDE-FILE.u";
			}

			if (Package->Action == FILE_FAKE)
			{
				if (bLogChecks)
					GLog->Logf(L" -> Faking Package!");

				Param1 = Param1;
			}

			if (Package->Action == FILE_REDIRECT)
			{
				if (bLogChecks)
					GLog->Logf(L" -> Redirecting Package!");
			
				Param1 = Package->Redirect;
			}

			if (bLogChecks)
				GLog->Logf(L" ");

			return;
		}

		Package = Package->Next;
	}
}

__declspec (naked) void LocalPerform_Init ()
{
	_asm add esp, 4h					// Fix call stack

	_asm mov eax, [ebp-6Ch]
	_asm mov SecType, eax
	_asm mov eax, [ebp-40h]
	_asm mov Param1, eax
	_asm mov Pointer, eax
	_asm mov eax, [ebp-68h]
	_asm mov Param2, eax

	_asm pushad
	Perform_Check(L"********** LocalPerform **********");
	_asm popad

	_asm mov eax, SecType
	_asm mov [ebp-6Ch], eax
	_asm mov eax, Param1
	_asm mov [ebp-40h], eax
	_asm mov eax, Param2
	_asm mov [ebp-68h], eax

	_asm jmp dwJmp_LP_Init
}

void QuickMD5_Check ()
{
	URedirection_Package* Package = PackageList;

	while (Package)
	{
		if (appStricmp(*StripFileExt(StripFilePath(Package->Filename)), *StripFilePath(LastFile)) == 0)
		{
			if (Package->Action == FILE_FAKE)
			{
				Str_GUID		= Package->GUID;
				Str_QuickMD5	= Package->QuickMD5;

				return;
			}
		}

		Package = Package->Next;
	}
}

__declspec (naked) void LocalPerform_QuickMD5 ()
{
	_asm mov Str_QuickMD5, edi
	_asm mov Str_GUID, eax

	_asm pushad
	QuickMD5_Check();
	_asm popad

	_asm mov edi, Str_QuickMD5
	_asm mov eax, Str_GUID

	_asm push edi

	_asm jmp dwJmp_LP_QuickMD5
}

void FullMD5_Check ()
{
	URedirection_Package* Package = PackageList;

	while (Package)
	{
		if (appStricmp(*StripFilePath(Package->Filename), *StripFilePath(LastFile)) == 0)
		{
			if (Package->Action == FILE_FAKE)
			{
				Str_FullMD5 = Package->FullMD5;

				return;
			}
		}

		Package = Package->Next;
	}
}

__declspec (naked) void LocalPerform_FullMD5 ()
{
	_asm mov edi, [ebp-14h]				// Fix call stack

	_asm mov eax, [ebp-28h]
	_asm mov Str_FullMD5, eax

	_asm pushad
	FullMD5_Check();
	_asm popad

	_asm mov eax, Str_FullMD5
	_asm mov [ebp-28h], eax

	_asm jmp dwJmp_LP_FullMD5
}

void Check_PackageList ()
{
	bHidePackage = false;
	bFakePackage = false;

	URedirection_Package* Package = PackageList;

	while (Package)
	{
		if (appStricmp(*StripFilePath(Package->Filename), *StripFilePath(Linker->Filename)) == 0)
		{
			if (Package->Action == FILE_HIDE)
			{
				if (bLogChecks)
					GLog->Logf(L" -> Hidding Package!");

				bHidePackage = true;
			}

			if ((Package->Action == FILE_FAKE) || (Package->Action == FILE_REDIRECT))
			{
				if (bLogChecks)
					GLog->Logf(L" -> Faking Package!");

				Param1			= Package->GUID;
				Param2			= Package->QuickMD5;

				bFakePackage = true;
			}	
		}

		Package = Package->Next;
	}
}

__declspec (naked) void LocalPerform_PackageList ()
{
	_asm mov Linker, edx

	_asm pushad
	Check_PackageList();
	_asm popad

	_asm cmp bHidePackage, 1
	_asm jz LP_PackageList_Hide
	_asm cmp bFakePackage, 1
	_asm jz LP_PackageList_Fake

	_asm call dwAddZeroed
	_asm jmp dwJmp_LP_PackageList

LP_PackageList_Hide:
	_asm mov eax, [ebp-1Ch]
	_asm inc eax
	_asm jmp dwJmp_LP_PackageList_Inc

LP_PackageList_Fake:
	_asm call dwAddZeroed
	_asm mov [ebp-50h],eax
  	_asm lea eax,[ebp-000000E0h]
  	_asm push eax
  	_asm mov ecx,esi
  	_asm call dwQuickMD5
  	_asm mov edi,eax
  	_asm mov edx,[esi]
  	_asm mov ecx,esi
  	_asm mov byte ptr [ebp-04h],10h
  	_asm call [edx+70h]
  	_asm mov ecx,edi
  	_asm mov [ebp-18h],eax
  	_asm call dwDFString
  	_asm lea ecx,[esi+54h]
  	_asm mov edi,eax
  	_asm call dwString
  	_asm mov ecx,[esi+2Ch]
  	_asm mov ebx,eax
  	_asm call dwGetName
  	_asm mov ecx,[ebp-18h]

	_asm mov edi, Param2
	_asm mov ebx, Param1

	_asm push ecx
	_asm push edi
	_asm push ebx
	_asm push eax
	_asm jmp dwJmp_LP_PackageList_Printf
}

__declspec (naked) void NativePerform_Init ()
{
	_asm add esp, 4h					// Fix call stack

	_asm mov eax, [ebp-18h]
	_asm mov SecType, eax
	_asm mov eax, [ebp-3Ch]
	_asm mov Param1, eax
	_asm mov Pointer, eax
	_asm mov eax, [ebp-48h]
	_asm mov Param2, eax

	_asm pushad
	Perform_Check(L"********** NativePerform *********");
	_asm popad

	_asm mov eax, SecType
	_asm mov [ebp-18h], eax
	_asm mov eax, Param1
	_asm mov [ebp-3Ch], eax
	_asm mov eax, Param2
	_asm mov [ebp-48h], eax

	_asm jmp dwJmp_NP_Init
}

void Check_File ()
{
	bHideFile = false;

	if (bLogChecks)
	{
		GLog->Logf(L"************ File Check **********");
		GLog->Logf(L" Package : %ls", *PointerToString(Pointer));
		GLog->Logf(L" ");
	}

	URedirection_Package* Package = PackageList;

	while (Package)
	{
		if (appStricmp(*StripFilePath(Package->Filename), *PointerToString(Pointer)) == 0)
		{
			if (Package->Action == FILE_HIDE)
			{
				if (bLogChecks)
					GLog->Logf(L" -> Hidding Package!");

				bHideFile = true;
			}

			if (bLogChecks)
				GLog->Logf(L" ");

			return;
		}

		Package = Package->Next;
	}
}

__declspec (naked) void GetDirectoryFiles ()
{
	_asm mov eax, [ecx]
	_asm mov Pointer, eax

	_asm pushad
	Check_File();
	_asm popad

	_asm cmp bHideFile, 1
	_asm jz Inc_Files_Jmp

	_asm jmp dwJmp_GetDirectoryFiles

Inc_Files_Jmp:
	_asm jmp dwJmp_Inc_Files
}

__declspec (naked) void PawnConstructor ()
{
	_asm mov pTarget, ecx

	_asm pushad
	if (pTarget != NULL)
	{
		Process_AddPawn(pTarget);
	}
	_asm popad


	_asm push ecx
	_asm jmp dwJmp_PawnConstructor
}

__declspec (naked) void PawnDestructor ()
{
	_asm mov pTarget, ecx

	_asm pushad
	if (pTarget != NULL)
	{
		Process_RemovePawn(pTarget);
	}
	_asm popad

	_asm push ecx
	_asm jmp dwJmp_PawnDestructor
}

LONG WINAPI ExceptionHandler (PEXCEPTION_POINTERS ExceptionInfo)
{
	if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_PRIVILEDGED_INSTRUCTION)
	{
		DWORD dwAddress		= (DWORD)ExceptionInfo->ExceptionRecord->ExceptionAddress;
		DWORD dwContinue	= (DWORD)0x0;

		if (dwAddress == dwLinkers)
			dwContinue = (DWORD)Linkers;

		if (dwAddress == dwGetReferencers)
			dwContinue = (DWORD)GetReferencers;

		if (dwAddress == dwDynamicLoadObject)
			dwContinue = (DWORD)DynamicLoadObject;

		if (dwAddress == dwAllObjects)
			dwContinue = (DWORD)AllObjects;

		if (dwAddress == dwGetDirectoryFiles)
			dwContinue = (DWORD)GetDirectoryFiles;

		if (dwAddress == dwGetCDKeyHash)
			dwContinue = (DWORD)GetCDKeyHash;
					
		if (dwAddress == dwLP_Init)
			dwContinue = (DWORD)LocalPerform_Init;

		if (dwAddress == dwLP_QuickMD5)
			dwContinue = (DWORD)LocalPerform_QuickMD5;

		if (dwAddress == dwLP_FullMD5)
			dwContinue = (DWORD)LocalPerform_FullMD5;

		if (dwAddress == dwLP_PackageList)
			dwContinue = (DWORD)LocalPerform_PackageList;

		if (dwAddress == dwNP_Init)
			dwContinue = (DWORD)NativePerform_Init;

		if (dwAddress == dwPawnConstructor)
			dwContinue = (DWORD)PawnConstructor;

		if (dwAddress == dwPawnDestructor)
			dwContinue = (DWORD)PawnDestructor;

		if (dwAddress == dwOrg_Master_BeginPlay)
			dwContinue = (DWORD)Master_BeginPlay;

		if (dwAddress == dwOrg_Master_PlayerTick)
			dwContinue = (DWORD)Master_PlayerTick;

		if (dwAddress == dwOrg_Master_PostRender)
			dwContinue = (DWORD)Master_PostRender;

		if (dwContinue != (DWORD)0x0)
		{
			ExceptionInfo->ContextRecord->Eip = dwContinue;

			return EXCEPTION_CONTINUE_EXECUTION;
		}
	}

	return EXCEPTION_CONTINUE_SEARCH;
}

void HookFunctions ()
{
	if (AddVectoredExceptionHandler(&ExceptionHandler))
	{
		HMODULE hCore = GetModuleHandleA("Core.dll");

		if (hCore != NULL)
		{
			dwAddZeroed					= ((DWORD)hCore + 0x01ED0);
			dwQuickMD5					= ((DWORD)hCore + 0x345F0);
			dwDFString					= ((DWORD)hCore + 0x0C4F0);
			dwString					= ((DWORD)hCore + 0x024D0);
			dwGetName					= ((DWORD)hCore + 0x0CC10);
			dwLinkers					= ((DWORD)hCore + 0x4F232);
			dwJmp_Inc_Linkers			= ((DWORD)hCore + 0x4F313);
			dwJmp_Log_Linkers			= ((DWORD)hCore + 0x4F307);
			dwGetReferencers			= ((DWORD)hCore + 0x488EC);
			dwDynamicLoadObject			= ((DWORD)hCore + 0x2CAAA);
			dwAllObjects				= ((DWORD)hCore + 0x31CF1);
			dwGetDirectoryFiles			= ((DWORD)hCore + 0x5FF57);
			dwJmp_Inc_Files				= ((DWORD)hCore + 0x5FF7A);

			dwJmp_Linkers				= HookFunction(dwLinkers, 3);
			dwJmp_GetReferencers		= HookFunction(dwGetReferencers, 3);
			dwJmp_DynamicLoadObject		= HookFunction(dwDynamicLoadObject, 1);
			dwJmp_AllObjects			= HookFunction(dwAllObjects, 3);
			dwJmp_GetDirectoryFiles		= HookFunction(dwGetDirectoryFiles, 2);
		}

		HMODULE hEngine = GetModuleHandleA("Engine.dll");

		if (hEngine != NULL)
		{
			dwGetCDKeyHash				= ((DWORD)hEngine + 0x0F59B5);
			dwLP_Init					= ((DWORD)hEngine + 0x1D2100);
			dwLP_QuickMD5				= ((DWORD)hEngine + 0x1D2213);
			dwLP_FullMD5				= ((DWORD)hEngine + 0x1D24ED);
			dwLP_PackageList			= ((DWORD)hEngine + 0x1D25F1);
			dwJmp_LP_PackageList_Inc	= ((DWORD)hEngine + 0x1D268C);
			dwJmp_LP_PackageList_Printf = ((DWORD)hEngine + 0x1D263E);
			dwNP_Init					= ((DWORD)hEngine + 0x1D1957);
			dwNP_ServerCallback			= ((DWORD)hEngine + 0x0);
			dwPawnConstructor			= ((DWORD)hEngine + 0x067AF5);	// 10367AF5  51                        		push	ecx
			dwPawnDestructor			= ((DWORD)hEngine + 0x067A55);	// 10367A55  51                        		push	ecx
			dwOrg_Master_BeginPlay		= ((DWORD)hEngine + 0x008277);  // 10308277  FF5710                    		call	[edi+10h]
			dwOrg_Master_PlayerTick		= ((DWORD)hEngine + 0x010724);	// 10310724  FF5710                    		call	[edi+10h]
			dwOrg_Master_PostRender		= ((DWORD)hEngine + 0x134980);	// 10434980  55                        		push	ebp

			dwJmp_GetCDKeyHash			= HookFunction(dwGetCDKeyHash, 2);
			dwJmp_LP_Init				= HookFunction(dwLP_Init, 3);
			dwJmp_LP_QuickMD5			= HookFunction(dwLP_QuickMD5, 1);
			dwJmp_LP_FullMD5			= HookFunction(dwLP_FullMD5, 3);
			dwJmp_LP_PackageList		= HookFunction(dwLP_PackageList, 6);
			dwJmp_NP_Init				= HookFunction(dwNP_Init, 3);
			dwJmp_NP_ServerCallback		= HookFunction(dwNP_ServerCallback, 0);
			dwJmp_PawnConstructor		= HookFunction(dwPawnConstructor, 1);
			dwJmp_PawnDestructor		= HookFunction(dwPawnDestructor, 1);
			dwJmp_Master_BeginPlay		= HookFunction(dwOrg_Master_BeginPlay, 3);
			dwJmp_Master_PlayerTick		= HookFunction(dwOrg_Master_PlayerTick, 3);
			dwJmp_Master_PostRender		= HookFunction(dwOrg_Master_PostRender, 1);
		}
	}
}

void ReadINI ()
{
	TCHAR* Buffer = new TCHAR[MAX_PATH];
	FString Result;
	INT Action;
	int PluginCount;
	int PackageCount;

	GConfig->GetBool(L"URedirection.Settings", L"bHidePlugins", bHidePlugins, L"URedirection.ini");
	GConfig->GetBool(L"URedirection.Settings", L"bLogPlugins", bLogPlugins, L"URedirection.ini");
	GConfig->GetBool(L"URedirection.Settings", L"bLogChecks", bLogChecks, L"URedirection.ini");

	GConfig->GetString(L"URedirection.Settings", L"KeyHash", CDKeyHash, L"URedirection.ini");
	GConfig->GetInt(L"URedirection.PluginMaster", L"PluginCount", PluginCount, L"URedirection.ini");

	for (int i=0; i < PluginCount; i++)
	{
		appSprintf(Buffer, L"Plugins[%i]", i);

		GConfig->GetString(L"URedirection.PluginMaster", Buffer, Result, L"URedirection.ini");

		if ((Result != L"") && (Result.InStr(L".") != -1))
		{
			URedirection_Plugin* Plugin = new URedirection_Plugin();

			if (Plugin)
			{
				Plugin->Filename = Result;
				Plugin->Object = NULL;

				if (PluginList)
					Plugin->Next = PluginList;

				PluginList = Plugin;
			}
		}
	}

	GConfig->GetInt(L"URedirection.FileSystem", L"PackageCount", PackageCount, L"URedirection.ini");

	for (int x=0; x < PackageCount; x++)
	{
		URedirection_Package* Package = new URedirection_Package();

		if (Package)
		{
			appSprintf(Buffer, L"Package[%i].Filename", x);
			GConfig->GetString(L"URedirection.FileSystem", Buffer, Result, L"URedirection.ini");
			Package->Filename = Result;

			appSprintf(Buffer, L"Package[%i].Redirect", x);
			GConfig->GetString(L"URedirection.FileSystem", Buffer, Result, L"URedirection.ini");
			Package->Redirect = Result;

			appSprintf(Buffer, L"Package[%i].Action", x);
			GConfig->GetInt(L"URedirection.FileSystem", Buffer, Action, L"URedirection.ini");

			switch (Action)
			{
				case 1:
					Package->Action = FILE_HIDE;
					break;

				case 2:
					Package->Action = FILE_FAKE;
					break;

				case 3:
					Package->Action = FILE_REDIRECT;
					break;
			}
			

			appSprintf(Buffer, L"Package[%i].QuickMD5", x);
			GConfig->GetString(L"URedirection.FileSystem", Buffer, Result, L"URedirection.ini");
			Package->QuickMD5 = Result;

			appSprintf(Buffer, L"Package[%i].FullMD5", x);
			GConfig->GetString(L"URedirection.FileSystem", Buffer, Result, L"URedirection.ini");
			Package->FullMD5 = Result;

			appSprintf(Buffer, L"Package[%i].GUID", x);
			GConfig->GetString(L"URedirection.FileSystem", Buffer, Result, L"URedirection.ini");
			Package->GUID = Result;

			appSprintf(Buffer, L"Package[%i].Linker", x);
			GConfig->GetString(L"URedirection.FileSystem", Buffer, Result, L"URedirection.ini");
			Package->Linker = Result;

			if (PackageList)
				Package->Next = PackageList;

			PackageList = Package;
		}
	}
}

BOOL APIENTRY DllMain (HMODULE hDll, DWORD dwReason, LPVOID lpReserved)
{
	if (dwReason == DLL_PROCESS_ATTACH)
	{
		DisableThreadLibraryCalls(hDll);
		
		ReadINI();
		HookFunctions();

	}

	return 1;
}