/*

 **********************************************************************
 *
 * Original Axis by:
 * Copyright (C) Philip A. Esterle 1998-2002 + (C) parts Adron 2002
 *
 * 55r,56(x) Mods, and Axis2 re-build by:
 * Copyright (C) Benoit Croussette 2004-2006
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 **********************************************************************

*/

// Common.cpp : implementation file
//


#include "StdAfx.h"
#include "Axis2.h"
#include "Common.h"
#include "ScriptObjects.h"
#include <direct.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


//******************
//Default Table Objects


CTObject::CTObject()
{
	m_bType = 0;
}

CTObject::~CTObject()
{
}


//******************
//Default Script Objects

const char * pSObjectTags [11] =
{
	"CATEGORY",		//0
	"SUBSECTION",	//1
	"DESCRIPTION",	//2
	"DUPEITEM",		//3
	"DEFNAME",		//4
	"ID",			//5
	"COLOR",		//6
	"NAME",			//7
	"GROUP",		//8
	"P",			//9
	"POINT",		//10
};

CSObject::CSObject()
{
	this->m_csCategory = "<none>";
	this->m_csSubsection = "<none>";
	this->m_csDescription = "<unnamed>";
}

CSObject::~CSObject()
{
}

CString CSObject::ReadBlock(CStdioFile &csfInput)
{
	CString csLine;
	BOOL bStatus = TRUE;
	while ( bStatus )
	{
		bStatus = csfInput.ReadString(csLine);
		if ( !bStatus )
			break;
		if ( csLine.Find("[") == 0 )
		{
			break;
		}
		if ( ( csLine.Find("=") == -1) || (csLine.Find("=") == csLine.GetLength()))
			continue;
		CString csTag = csLine.SpanExcluding("=");
		CString csValue = csLine.Mid(csLine.Find("=") + 1);
		csTag.Trim();
		csValue.Trim();
		switch (FindTable(csTag, pSObjectTags, 11))
		{
		case 0:
			this->m_csCategory = csValue;
			break;
		case 1:
			this->m_csSubsection = csValue;
			break;
		case 2:
			this->m_csDescription = csValue;
			break;
		case 3:
			this->m_csDupeItem = csValue;
			break;
		case 4:
		{
			if(csValue.CompareNoCase(this->m_csValue) != 0)
			{
				this->m_csID = csValue;
				CSObject * pDef = new CSObject;
				pDef->m_csValue = csValue;
				pDef->m_csID = this->m_csValue;
				Main->m_pScripts->m_aDefList.Insert(pDef);
			}
		}
			break;
		case 5:
		{
			this->m_csDisplay = csValue;
			this->m_csValue = m_csID;
			int iFind = Main->m_pScripts->m_aDefList.Find(this->m_csValue);
			if ( iFind != -1 )
			{
				CSObject * pFind = (CSObject *) Main->m_pScripts->m_aDefList.GetAt(iFind);
				pFind->m_csID = csValue;
			}
		}
			break;
		case 6:
			this->m_csColor = csValue;
			break;
		case 7:
		{
			if (this->m_bType == TYPE_AREA)
			this->m_csDescription = csValue;
		}
			break;
		case 8:
			this->m_csSubsection = csValue;
			break;
		case 9:
		{
			if (this->m_bType == TYPE_AREA)
			{
				CString csX, csY, csZ, csM, csTemp;
				csX = csValue.SpanExcluding(",");
				csY = csValue.Mid(csValue.Find(",") + 1);
				if (csY.Find(",") != -1)
					csZ = csY.Mid(csY.Find(",") + 1);
				else
					csZ = "0";
				csY = csY.SpanExcluding(",");
				if (csZ.Find(",") != -1)
					csM = csZ.Mid(csZ.Find(",") + 1);
				else
					csM = "0";
				csZ = csZ.SpanExcluding(",");
				csTemp.Format("%s,%s,%s", csX, csY, csZ);
				this->m_csID = csTemp;
				this->m_csDisplay = csM;
				csTemp.Format("Map %d Regions", atoi(csM));
				this->m_csCategory = csTemp;
			}
		}
		case 10:
		{
			CString csX, csY, csZ, csM, csTemp;
			csX = csValue.SpanExcluding(",");
			csY = csValue.Mid(csValue.Find(",") + 1);
			if (csY.Find(",") != -1)
				csZ = csY.Mid(csY.Find(",") + 1);
			else
				csZ = "0";
			csY = csY.SpanExcluding(",");
			if (csZ.Find(",") != -1)
				csM = csZ.Mid(csZ.Find(",") + 1);
			else
				csM = "0";
			csZ = csZ.SpanExcluding(",");
			csTemp.Format("%s,%s,%s", csX, csY, csZ);
			this->m_csID = csTemp;
			this->m_csDisplay = csM;
		}
		}
	}
	return csLine;
}

void CSObject::WriteBlock(CStdioFile &csfInput)
{
	CString csLine;
	switch (this->m_bType)
	{
	case 0:
	case 3:
		break;
	case 1:
		csLine.Format("[ITEMDEF %s] \n",this->m_csValue);
		break;
	case 2:
		csLine.Format("[CHARDEF %s] \n",this->m_csValue);
		break;
	case 4:
		csLine.Format("[AREADEF %s] \n",this->m_csValue);
		break;
	case 5:
		csLine.Format("[SPAWN %s] \n",this->m_csValue);
		break;
	case 6:
		csLine.Format("[TEMPLATE %s] \n",this->m_csValue);
		break;
	}
	csfInput.WriteString(csLine);

	if (this->m_csID != "" )
	{
		csLine.Format("DEFNAME = %s \n",this->m_csID);
		csfInput.WriteString(csLine);
	}
	if (this->m_csDisplay != "" )
	{
		csLine.Format("ID = %s \n",this->m_csDisplay);
		csfInput.WriteString(csLine);
	}
	if (this->m_csCategory != "" )
	{
		csLine.Format("CATEGORY = %s \n",this->m_csCategory);
		csfInput.WriteString(csLine);
	}
	if (this->m_csSubsection != "" )
	{
		csLine.Format("SUBSECTION = %s \n",this->m_csSubsection);
		csfInput.WriteString(csLine);
	}
	if (this->m_csDescription != "" )
	{
		csLine.Format("DESCRIPTION = %s \n",this->m_csDescription);
		csfInput.WriteString(csLine);
	}
	if (this->m_csColor != "" )
	{
		csLine.Format("COLOR = %s \n",this->m_csColor);
		csfInput.WriteString(csLine);
	}
	if (this->m_csDupeItem != "" )
	{
		csLine.Format("DUPEITEM = %s \n",this->m_csDupeItem);
		csfInput.WriteString(csLine);
	}
	csfInput.WriteString("\n");
}

//******************
//Script Array

CScriptArray::CScriptArray()
{
}

CScriptArray::~CScriptArray()
{
	CPtrArray::RemoveAll();
}

int CScriptArray::Find(CString csName)
{
	if ( this->GetSize() == 0 )
		return -1;
	INT_PTR iLower = 0;
	INT_PTR iUpper = this->GetUpperBound();
	INT_PTR iIndex = 0;
	while ( iLower <= iUpper )
	{
		iIndex = (iUpper + iLower ) / 2;
		CSObject * pTest = (CSObject *) this->GetAt(iIndex);
		CString csExisting = pTest->m_csValue;
		if ( csExisting.CompareNoCase(csName) == 0 )
			return (int)iIndex;
		if ( csExisting.CompareNoCase(csName) > 0 )
			iUpper = iIndex - 1;
		else
			iLower = iIndex + 1;
	}
	return -1;
}

int CScriptArray::Insert(CTObject * pScript)
{
	if (( pScript->m_csValue == "" )&&( !pScript->m_bCustom ))
	{
		delete pScript;
		return -1;
	}
	INT_PTR iLower = 0;
	INT_PTR iUpper = this->GetUpperBound();
	if ( iUpper == -1 )
	{
		this->InsertAt(0, pScript);
		return 0;
	}
	INT_PTR iIndex = 0;
	INT_PTR iCompare = 0;
	while ( iLower <= iUpper )
	{
		iIndex = (iUpper + iLower ) / 2;
		CSObject * pTest = (CSObject *) this->GetAt(iIndex);
		if ( pTest->m_csValue.CompareNoCase(pScript->m_csValue) > 0 )
		{
			iCompare = 0;
			iUpper = iIndex - 1;
		}
		else
		{
			iCompare = 1;
			iLower = iIndex + 1;
		}
	}
	iIndex += iCompare;
	this->InsertAt(iIndex, (void *) pScript);
	return (int)iIndex;
}

//******************
//String Array

int CAdvStringArray::Find(CString csName)
{
	if ( this->GetSize() == 0 )
		return -1;
	INT_PTR iLower = 0;
	INT_PTR iUpper = this->GetUpperBound();
	INT_PTR iIndex = 0;
	while ( iLower <= iUpper )
	{
		iIndex = (iUpper + iLower ) / 2;
		CString csExisting = this->GetAt(iIndex);
		if ( csExisting.CompareNoCase(csName) == 0 )
			return (int)iIndex;
		if ( csExisting.CompareNoCase(csName) > 0 )
			iUpper = iIndex - 1;
		else
			iLower = iIndex + 1;
	}
	return -1;
}

int CAdvStringArray::Insert(CString csName)
{
	if ( csName == "" )
		return -1;
	INT_PTR iLower = 0;
	INT_PTR iUpper = this->GetUpperBound();
	if ( iUpper == -1 )
	{
		this->InsertAt(0, csName);
		return 0;
	}
	INT_PTR iIndex = 0;
	INT_PTR iCompare = 0;
	while ( iLower <= iUpper )
	{
		iIndex = (iUpper + iLower ) / 2;
		CString csTest = this->GetAt(iIndex);
		if ( csTest.CompareNoCase(csName) > 0 )
		{
			iCompare = 0;
			iUpper = iIndex - 1;
		}
		else
		{
			iCompare = 1;
			iLower = iIndex + 1;
		}
	}
	iIndex += iCompare;
	this->InsertAt(iIndex, csName);
	return (int)iIndex;
}

//******************
//Objects Categories

CCategory::CCategory()
{
	this->m_csName = "<none>";
}

CSubsection::CSubsection()
{
	this->m_csName = "<none>";
}

CCategory * FindCategory(CPtrList * pPtrList, CString csName, bool bCreate)
{
	CCategory * pCategory = NULL;
	if (!pPtrList->IsEmpty())
	{
		POSITION pos = pPtrList->GetHeadPosition();
		while (pos != NULL)
		{
			CCategory * pTest = (CCategory *) pPtrList->GetNext(pos);
			if (pTest->m_csName == csName)
			{
				pCategory = pTest;
				break;
			}
		}
	}
	if (pCategory == NULL && bCreate == true)
	{
		// Category didn't exist.  Create a new one
		pCategory = new (CCategory);
		pCategory->m_csName = csName;
		if (pPtrList->IsEmpty())
			pPtrList->AddHead(pCategory);
		else
			pPtrList->AddTail(pCategory);
	}
	return pCategory;
}

CSubsection * FindSubsection(CCategory * pCategory, CString csName, bool bCreate)
{
	CSubsection * pSubsection = NULL;
	if (!pCategory->m_SubsectionList.IsEmpty())
	{
		POSITION pos = pCategory->m_SubsectionList.GetHeadPosition();
		while (pos != NULL)
		{
			CSubsection * pTest = (CSubsection *) pCategory->m_SubsectionList.GetNext(pos);
			if (pTest->m_csName == csName)
			{
				pSubsection = pTest;
				break;
			}
		}
	}
	if (pSubsection == NULL && bCreate == true)
	{
		// Subsection didn't exist.  Create a new one
		pSubsection = new (CSubsection);
		pSubsection->m_csName = csName;
		if (pCategory->m_SubsectionList.IsEmpty())
			pCategory->m_SubsectionList.AddHead(pSubsection);
		else
			pCategory->m_SubsectionList.AddTail(pSubsection);
	}
	return pSubsection;
}


//******************


int FindTable( const char * pFind, const char * const * ppTable, int iCount, int iElemSize )
{
	for ( int i=0; i<iCount; i++ )
	{
		if ( ! _strcmpi( *ppTable, pFind ))
			return( i );
		ppTable = (const char * const *)((( const BYTE*) ppTable ) + iElemSize );
	}
	return( -1 );
}

DWORD alltoi( const char * pszStr, int iSkip)
{
	CString csText, csTemp;
	csText = pszStr;
	DWORD dwTemp;
	
	int i = Main->m_pScripts->m_aDefList.Find(csText);
	if ( i != -1 )
	{
		CSObject * pTemp = (CSObject *) Main->m_pScripts->m_aDefList.GetAt(i);
		dwTemp = alltoi( pTemp->m_csID );
		return( dwTemp );
	}
	else
	{
		csText.Trim();
		if(csText.Find('{') != -1)
		{
			if (iSkip == 1)
			{
				csTemp = csText.Mid(csText.ReverseFind('{')+1);
				csTemp = csTemp.SpanExcluding("}");
				dwTemp = alltoi( csTemp );
			}
			else
			{
				csTemp = csText.Mid(csText.Find("{")+1);
				csTemp = csTemp.Left(csTemp.ReverseFind('}'));
				dwTemp = alltoi( csTemp, 1 );
			}
			return( dwTemp );
		}
		else if (csText.Find(' ') != -1)
		{
			DWORD dwMin, dwMax;
			csTemp = csText.SpanExcluding(" ");
			if(ahextoi(csTemp) != 0)
			{
				dwMin = ahextoi(csTemp);
				csTemp = csText.Mid(csText.Find(' ') + 1);
				dwMax = ahextoi(csTemp);
				return (getrand(dwMin,dwMax));
			}
			else
			{
				dwTemp = alltoi( csTemp );
				return( dwTemp );
			}

		}
		else
			return(ahextoi(csText));
	}
}

DWORD getrand( DWORD dwMin, DWORD dwMax )
{
	if(dwMin == dwMax)
		return dwMin;
	srand((unsigned int)time(NULL));
	return ((DWORD) (rand() % (dwMax - dwMin) ) + dwMin);
}

DWORD ahextoi( const char * pszStr ) // Convert hex string to integer
{
	// Unfortunatly the library func cant handle the number FFFFFFFF
	// char * sstop; return( strtol( s, &sstop, 16 ));

	GETNONWHITESPACE( pszStr );

	DWORD val = 0;
	CString cs_test = pszStr;
	if (cs_test.GetAt(0) != '0')
	{
		while ( 1 )
		{ 
			char ch = *pszStr;
				if (( ch > '32' && ch <'0' ) || ( ch > '9' && ch <'127' ))
				{
					val = 0;
					break;
				}
			if ( ch < '0' || ch > '9' ) break;

			ch -= '0';
			val *= 0x0a;
			val += ch;
			pszStr ++;
		}
		return( val );
	}
	else
	{
		while ( 1 )
		{
			char ch = *pszStr;
			if ( ch >= '0' && ch <= '9' )
				ch -= '0';
			else
			{
				ch |= 0x20;
				if (( ch > '32' && ch <'a' ) || ( ch > 'f' && ch <'127' ))
				{
					val = 0;
					break;
				}		

				if ( ch > 'f' || ch <'a' ) break;
				ch -= 'a' - 10;
			}
			val *= 0x10;
			val += ch;
			pszStr ++;
		}
		return( val );
	}
}

bool IsNumber( const char * pszStr )
{

	GETNONWHITESPACE( pszStr );
	CString cs_test = pszStr;
	while ( 1 )
	{ 
		char ch = *pszStr;
		if (( ch > '32' && ch <'0' ) || ( ch > '9' && ch <'127' )) return false;
		if ( ch < '0' || ch > '9' ) break;
		pszStr ++;
	}
	return true;
}

CString Encrypt(CString csValue)
{
	CString csKey = _T("LmheGeEBuBeiZuElnbiASnuZenCLMAKa");
	CString csEncrypted = csValue;

	for (int i = 0; i < csValue.GetLength(); i++)
	{
		csKey.SetAt(i, csKey[i] ^ 128);
		csEncrypted.SetAt(i, csValue[i] ^ csKey[i]);
	}
	
	return csEncrypted;
}

CString EncryptUO(CString csValue)
{
	CString csEncrypted = csValue;

	for (int i = 0; i < csValue.GetLength(); i++)
	{
		char cNew = csValue[i];
		cNew += 0x0d;
		if ( cNew > 0x7f )
			cNew -= 0x5f;
		csEncrypted.SetAt(i, cNew);
	}
	return csEncrypted;
}

bool ReplaceFiles( CString csNewFile, CString csOldFile )
{
	// Loop through this a few times
	int i = 0;
	bool bSuccess = false;
	while ( i < 5 && !bSuccess )
	try
	{
		CFileStatus st;
		if ( CFile::GetStatus( csOldFile, st ) )
			CFile::Remove( csOldFile );
		CFile::Rename( csNewFile, csOldFile );
		bSuccess = true;
	}
	catch ( CFileException * e )
	{
		i++;
		if ( i < 5 )
		{
			Sleep( 500 );
			e->Delete();
		}
		else
		{
			CString csMessage;
			char szCause[MAX_BUFFER];
			memset(szCause, 0x00, sizeof(szCause));
			e->GetErrorMessage( &szCause[0], MAX_BUFFER - 1 );
			csMessage.Format("An exception occured while moving files.\n\n%s", szCause);
			csMessage+= "\n\nAxis can attempt to rename the existing file, and move in the new file.\nWould you like to try this?";
			e->Delete();
			if ( AfxMessageBox( csMessage, MB_YESNO | MB_ICONQUESTION ) == IDYES )
			{
				CString csBackup;
				CTime ct = CTime::GetCurrentTime();
				csBackup.Format("%s.%s", csOldFile, ct.Format("%Y%m%d%H%M%S"));
				try
				{
					CFile::Rename( csOldFile, csBackup );
					CFile::Rename( csNewFile, csOldFile );
					CString csMessage;
					csMessage.Format("Rename was successful.  The backup file is now stored in\n%s", csBackup);
					AfxMessageBox(csMessage, MB_OK | MB_ICONINFORMATION);
					return true;
				}
				catch ( CFileException * e )
				{
					e->Delete();
					AfxMessageBox("Rename failed.", MB_OK | MB_ICONSTOP );
					return false;
				}
			}
			return false;
		}
	}
	return true;
}

UINT LoadProfileThread(LPVOID pParam)
{
	UINT idefault = (UINT)pParam;
	CString sProfile;
	if (idefault)
		sProfile = Main->GetRegistryString("Default Profile");
	else
	{
		CProfileTab * pProfile = (CProfileTab *)Main->m_pcppProfileTab->m_dcCurrentPage;
		pProfile->m_ceName.GetWindowText(sProfile);
	}

	Main->m_pScripts->LoadProfile(sProfile);
	return 0;
}

UINT TrackingThread(LPVOID pParam)
{
	DWORD dwProcessID;
	HANDLE m_hProcess;
	LPVOID lpAddress;
	CString csCoords;
	byte * pointer = new byte[Main->sizeX];
	byte * pointer1 = new byte[Main->sizeY];
	byte * pointer2 = new byte[Main->sizeZ];
	byte * pointer3 = new byte[Main->sizeM];

	if (!Main->calibrated)
		Calibrate();

	while (Main->calibrated)
	{
		EnumWindows(EnumWindowsProc, 1);
		if ((Main->bMemoryAccess) && (hwndUOClient))
		{

			GetWindowThreadProcessId(hwndUOClient, &dwProcessID);
			m_hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID);

			
			lpAddress = (LPVOID)((DWORD)Main->LocX);
			ReadProcessMemory(m_hProcess, lpAddress, pointer, Main->sizeX, NULL);
			int x = (short)(pointer[0] | (pointer[1] << 8));

			lpAddress = (LPVOID)((DWORD)Main->LocY);
			ReadProcessMemory(m_hProcess, lpAddress, pointer1, Main->sizeY, NULL);
			int y = (short)(pointer1[0] | (pointer1[1] << 8));

			lpAddress = (LPVOID)((DWORD)Main->LocZ);
			ReadProcessMemory(m_hProcess, lpAddress, pointer2, Main->sizeZ, NULL);
			int z = (short)(pointer2[0] | (pointer2[1] << 8));

			lpAddress = (LPVOID)((DWORD)Main->LocM);
			ReadProcessMemory(m_hProcess, lpAddress, pointer3, Main->sizeM, NULL);
			int m = (byte)pointer3[0];

			csCoords.Format("%d",m);
			CTravelTab * pTravel = (CTravelTab *)Main->m_pcppTravelTab->m_dcCurrentPage;
			pTravel->m_ceMapPlane.SetWindowText(csCoords);

			pTravel->RemoteRecenter(x,y,z);
			CloseHandle( m_hProcess );
			Sleep(1000);
		}
		else
			break;
	}
	return 0;
}

bool Calibrate()
{
	int LocX, sizeX = 0;
	int LocY, sizeY = 0;
	int LocZ, sizeZ = 0;
	int LocM, sizeM = 0;

	//Location
	byte mask[] = { 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00 };
	byte vals[] = { 0x8B, 0x15, 0x00, 0x00, 0x00, 0x00, 0x83, 0xC4, 0x10, 0x66, 0x89, 0x5A, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x66, 0x89, 0x78, 0x00, 0x8B, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x66, 0x89, 0x71, 0x00 };
	byte ptrX[] = { 0x02, 0x04, 0x04, 0x0C, 0x01, 0x02 };
	byte ptrY[] = { 0x0E, 0x04, 0x04, 0x15, 0x01, 0x02 };
	byte ptrZ[] = { 0x18, 0x04, 0x04, 0x1F, 0x01, 0x02 };
	//Map
	byte mask2[] = { 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
	byte vals2[] = { 0xA0, 0x00, 0x00, 0x00, 0x00, 0x84, 0xC0, 0x0F, 0x85, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x0D };
	byte ptrM[] = { 0x01, 0x04, 0xFF, 0xFF, 0xFF, 0x01 };
	int ptr = CalibrateEntry(mask, vals, sizeof(mask));
	if ( ptr != 0 )
	{
		LocX = CalibrateCoord(ptrX, ptr); sizeX = ptrX[5];
		LocY = CalibrateCoord(ptrY, ptr); sizeY = ptrY[5];
		LocZ = CalibrateCoord(ptrZ, ptr); sizeZ = ptrZ[5];
	}
	int ptr2 = CalibrateEntry(mask2, vals2, sizeof(mask2));
	if ( ptr2 != 0 )
		LocM = CalibrateCoord(ptrM, ptr2); sizeM = ptrM[5];

	if (( LocX !=0 )&&( LocY !=0 )&&( LocZ !=0 )&&( LocM !=0 ))
	{
		Main->LocX = LocX;
		Main->LocY = LocY;
		Main->LocZ = LocZ;
		Main->LocM = LocM;
		Main->sizeX = sizeX;
		Main->sizeY = sizeY;
		Main->sizeZ = sizeZ;
		Main->sizeM = sizeM;
		Main->calibrated = true;
		return true;
	}
	Main->calibrated = false;
	return false;
}

int CalibrateCoord(byte * ptrX, int MaskLocation)
{
	EnumWindows(EnumWindowsProc, 1);
	if ((Main->bMemoryAccess) && (hwndUOClient))
	{
		DWORD dwProcessID;
		HANDLE m_hProcess;
		LPVOID lpAddress;
		int coordPointer = 0;

		GetWindowThreadProcessId(hwndUOClient, &dwProcessID);
		m_hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID);

		if (MaskLocation)
		{
			lpAddress = (LPVOID)((DWORD)MaskLocation + ptrX[0]);
			byte * pointer = new byte[ptrX[1]];
			ReadProcessMemory(m_hProcess, lpAddress, pointer, ptrX[1], NULL);
			switch (ptrX[1])
			{
				case 1: coordPointer = (byte)pointer[0]; break;
				case 2: coordPointer = (short)(pointer[0] | (pointer[1] << 8)); break;
				case 4: coordPointer = (int)(pointer[0] | (pointer[1] << 8) | (pointer[2] << 16) | (pointer[3] << 24)); break;
			}
			byte * pointer2 = new byte[ptrX[2]];
			if ( ptrX[2] < 0xFF )
			{
				lpAddress = (LPVOID)((DWORD)coordPointer);
				ReadProcessMemory(m_hProcess, lpAddress, pointer2, ptrX[2], NULL);
				switch (ptrX[2])
				{
					case 1: coordPointer = (byte)pointer2[0]; break;
					case 2: coordPointer = (short)(pointer2[0] | (pointer2[1] << 8)); break;
					case 4: coordPointer = (int)(pointer2[0] | (pointer2[1] << 8) | (pointer2[2] << 16) | (pointer2[3] << 24)); break;
				}
			}
			byte * pointer3 = new byte[ptrX[4]];
			if ( ptrX[3] < 0xFF )
			{
				lpAddress = (LPVOID)((DWORD)MaskLocation + ptrX[3]);
				ReadProcessMemory(m_hProcess, lpAddress, pointer3, ptrX[4], NULL);
				switch (ptrX[4])
				{
					case 1: coordPointer += (byte)pointer3[0]; break;
					case 2: coordPointer += (short)(pointer3[0] | (pointer3[1] << 8)); break;
					case 4: coordPointer += (int)(pointer3[0] | (pointer3[1] << 8) | (pointer3[2] << 16) | (pointer3[3] << 24)); break;
				}
			}
		}
		CloseHandle( m_hProcess );
		return coordPointer;
	}
	return 0;
}


int CalibrateEntry(byte * mask, byte * vals, int size)
{
	EnumWindows(EnumWindowsProc, 1);
	if ((Main->bMemoryAccess) && (hwndUOClient))
	{
		const int chunkSize = 4096;
		int readSize = chunkSize + size;
		DWORD dwProcessID;
		HANDLE m_hProcess;
		LPVOID lpAddress;

		GetWindowThreadProcessId(hwndUOClient, &dwProcessID);
		m_hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID);

		byte * read = new byte[readSize];

		for ( int i = 0;; ++i )
		{
			lpAddress = (LPVOID)((DWORD)0x400000 + (i * chunkSize));;
			if ( !ReadProcessMemory(m_hProcess, lpAddress, read, readSize, NULL) )
				break;

			for ( int j = 0; j < chunkSize; ++j )
			{
				bool ok = true;

				for ( int k = 0; ok && k < size; ++k )
					ok = ( (read[j + k] & mask[k]) == vals[k] );
				
				if ( ok )
				{
					CloseHandle( m_hProcess );
					return 0x400000 + (i * chunkSize) + j;
				}
			}
		}
		CloseHandle( m_hProcess );
	}
	return 0;
}

bool AdjustPrivileges() 
{
	HANDLE hToken;
	TOKEN_PRIVILEGES tp;
	TOKEN_PRIVILEGES oldtp;
	DWORD dwSize = sizeof(TOKEN_PRIVILEGES);
	LUID luid;

	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
	{
		if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
			return true;
		return false;
	}

	if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
	{
		CloseHandle(hToken);
		return false;
	}

	ZeroMemory(&tp, sizeof(tp));
	tp.PrivilegeCount = 1;
	tp.Privileges[0].Luid = luid;
	tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

	/* Adjust Token Privileges */
	if (!AdjustTokenPrivileges (hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &oldtp, &dwSize))
	{
		CloseHandle(hToken);
		return false;
	}
	// close handles
    CloseHandle(hToken);

	return true;
}

CString GetInternetCodeString(DWORD dwRet)
{
	switch(dwRet)
	{
	case 100:
		return "OK to continue with request.";
	case 101:
		return "server has switched protocols in upgrade header.";
	case 200:
		return "request completed.";
	case 201:
		return "object created, reason = new URI.";
	case 202:
		return "async completion (TBS).";
	case 203:
		return "partial completion.";
	case 204:
		return "no info to return.";
	case 205:
		return "request completed, but clear form.";
	case 206:
		return "partial GET furfilled.";
	case 300:
		return "server couldn't decide what to return.";
	case 301:
		return "object permanently moved.";
	case 302:
		return "object temporarily moved.";
	case 303:
		return "redirection w/ new access method.";
	case 304:
		return "if-modified-since was not modified.";
	case 305:
		return "redirection to proxy, location header specifies proxy to use.";
	case 307:
		return "HTTP/1.1: keep same verb.";
	case 400:
		return "invalid syntax.";
	case 401:
		return "access denied.";
	case 402:
		return "payment required.";
	case 403:
		return "request forbidden.";
	case 404:
		return "object not found.";
	case 405:
		return "method is not allowed.";
	case 406:
		return "no response acceptable to client found.";
	case 407:
		return "proxy authentication required.";
	case 408:
		return "server timed out waiting for request.";
	case 409:
		return "user should resubmit with more info.";
	case 410:
		return "the resource is no longer available.";
	case 411:
		return "the server refused to accept request w/o a length.";
	case 412:
		return "precondition given in request failed.";
	case 413:
		return "request entity was too large.";
	case 414:
		return "request URI too long.";
	case 415:
		return "unsupported media type.";
	case 449:
		return "retry after doing the appropriate action.";
	case 500:
		return "internal server error.";
	case 501:
		return "required not supported.";
	case 502:
		return "error response received from gateway.";
	case 503:
		return "temporarily overloaded.";
	case 504:
		return "timed out waiting for gateway.";
	case 505:
		return "HTTP version not supported.";
	default:
		return "Unknown Error.";
	}
}
