extensions/tf2/CDetour/detours.cpp
changeset 2600 f78e5656cc6f
parent 2184 d6b9d57ed4cd
     1.1 --- a/extensions/tf2/CDetour/detours.cpp	Thu Feb 19 14:22:22 2009 +1300
     1.2 +++ b/extensions/tf2/CDetour/detours.cpp	Thu Feb 26 12:42:13 2009 +1300
     1.3 @@ -26,7 +26,7 @@
     1.4  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
     1.5  * or <http://www.sourcemod.net/license.php>.
     1.6  *
     1.7 -* Version: $Id$
     1.8 +* Version: $Id: detours.cpp 248 2008-08-27 00:56:22Z pred $
     1.9  */
    1.10  
    1.11  #include "detours.h"
    1.12 @@ -34,7 +34,6 @@
    1.13  
    1.14  ISourcePawnEngine *CDetourManager::spengine = NULL;
    1.15  IGameConfig *CDetourManager::gameconf = NULL;
    1.16 -int CDetourManager::returnValue = 0;
    1.17  
    1.18  void CDetourManager::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf)
    1.19  {
    1.20 @@ -42,9 +41,9 @@
    1.21  	CDetourManager::gameconf = gameconf;
    1.22  }
    1.23  
    1.24 -CDetour *CDetourManager::CreateDetour(void *callbackfunction, size_t paramsize, const char *signame)
    1.25 +CDetour *CDetourManager::CreateDetour(void *callbackfunction, void **trampoline, const char *signame)
    1.26  {
    1.27 -	CDetour *detour = new CDetour(callbackfunction, paramsize, signame);
    1.28 +	CDetour *detour = new CDetour(callbackfunction, trampoline, signame);
    1.29  	if (detour)
    1.30  	{
    1.31  		if (!detour->Init(spengine, gameconf))
    1.32 @@ -59,50 +58,17 @@
    1.33  	return NULL;
    1.34  }
    1.35  
    1.36 -void CDetourManager::DeleteDetour(CDetour *detour)
    1.37 -{
    1.38 -	delete detour;
    1.39 -}
    1.40 -
    1.41 -CBlocker * CDetourManager::CreateFunctionBlock( const char *signame, bool isVoid )
    1.42 -{
    1.43 -	CBlocker *block = new CBlocker(signame, isVoid);
    1.44 -
    1.45 -	if (block)
    1.46 -	{
    1.47 -		if (!block->Init(spengine, gameconf))
    1.48 -		{
    1.49 -			delete block;
    1.50 -			return NULL;
    1.51 -		}
    1.52 -
    1.53 -		return block;
    1.54 -	}
    1.55 -
    1.56 -	return NULL;
    1.57 -}
    1.58 -
    1.59 -void CDetourManager::DeleteFunctionBlock(CBlocker *block)
    1.60 -{
    1.61 -	delete block;
    1.62 -}
    1.63 -
    1.64 -CDetour::CDetour(void *callbackfunction, size_t paramsize, const char *signame)
    1.65 +CDetour::CDetour(void *callbackfunction, void **trampoline, const char *signame)
    1.66  {
    1.67  	enabled = false;
    1.68  	detoured = false;
    1.69  	detour_address = NULL;
    1.70 -	detour_callback = NULL;
    1.71 +	detour_trampoline = NULL;
    1.72  	this->signame = signame;
    1.73 -	this->callbackfunction = callbackfunction;
    1.74 +	this->detour_callback = callbackfunction;
    1.75  	spengine = NULL;
    1.76  	gameconf = NULL;
    1.77 -	this->paramsize = paramsize;
    1.78 -}
    1.79 -
    1.80 -CDetour::~CDetour()
    1.81 -{
    1.82 -	DeleteDetour();
    1.83 +	this->trampoline = trampoline;
    1.84  }
    1.85  
    1.86  bool CDetour::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf)
    1.87 @@ -121,6 +87,12 @@
    1.88  	return enabled;
    1.89  }
    1.90  
    1.91 +void CDetour::Destroy()
    1.92 +{
    1.93 +	DeleteDetour();
    1.94 +	delete this;
    1.95 +}
    1.96 +
    1.97  bool CDetour::IsEnabled()
    1.98  {
    1.99  	return enabled;
   1.100 @@ -148,7 +120,6 @@
   1.101  		detour_restore.patch[i] = ((unsigned char *)detour_address)[i];
   1.102  	}
   1.103  
   1.104 -	//detour_callback = spengine->ExecAlloc(100);
   1.105  	JitWriter wr;
   1.106  	JitWriter *jit = &wr;
   1.107  	jit_uint32_t CodeSize = 0;
   1.108 @@ -158,47 +129,6 @@
   1.109  
   1.110  jit_rewind:
   1.111  
   1.112 -	/* Push all our params onto the stack */
   1.113 -	for (size_t i=0; i<paramsize; i++)
   1.114 -	{
   1.115 -#if defined PLATFORM_WINDOWS
   1.116 -		IA32_Push_Rm_Disp8_ESP(jit, (paramsize*4));
   1.117 -#elif defined PLATFORM_LINUX
   1.118 -		IA32_Push_Rm_Disp8_ESP(jit, 4 +(paramsize*4));
   1.119 -#endif
   1.120 -	}
   1.121 -
   1.122 -	/* Push thisptr onto the stack */
   1.123 -#if defined PLATFORM_WINDOWS
   1.124 -	IA32_Push_Reg(jit, REG_ECX);
   1.125 -#elif defined PLATFORM_LINUX
   1.126 -	IA32_Push_Rm_Disp8_ESP(jit, 4 + (paramsize*4));
   1.127 -#endif
   1.128 -
   1.129 -	jitoffs_t call = IA32_Call_Imm32(jit, 0); 
   1.130 -	IA32_Write_Jump32_Abs(jit, call, callbackfunction);
   1.131 -
   1.132 -	/* Pop thisptr */
   1.133 -#if defined PLATFORM_LINUX
   1.134 -	IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);		//add esp, 4
   1.135 -#elif defined PLATFORM_WINDOWS
   1.136 -	IA32_Pop_Reg(jit, REG_ECX);
   1.137 -#endif
   1.138 -
   1.139 -	/* Pop params from the stack */
   1.140 -	for (size_t i=0; i<paramsize; i++)
   1.141 -	{
   1.142 -		IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);	
   1.143 -	}
   1.144 -
   1.145 -	//If TempDetour returns non-zero we want to load something into eax and return this value
   1.146 -
   1.147 -	//test eax, eax
   1.148 -	IA32_Test_Rm_Reg(jit,  REG_EAX, REG_EAX, MOD_REG);
   1.149 -
   1.150 -	//jnz _skip
   1.151 -	jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_NZ, 0);
   1.152 -
   1.153  	/* Patch old bytes in */
   1.154  	if (wr.outbase != NULL)
   1.155  	{
   1.156 @@ -207,15 +137,8 @@
   1.157  	wr.outptr += detour_restore.bytes;
   1.158  
   1.159  	/* Return to the original function */
   1.160 -	call = IA32_Jump_Imm32(jit, 0);
   1.161 +	jitoffs_t call = IA32_Jump_Imm32(jit, 0);
   1.162  	IA32_Write_Jump32_Abs(jit, call, (unsigned char *)detour_address + detour_restore.bytes);
   1.163 -	
   1.164 -	//_skip:
   1.165 -	//mov eax, [g_returnvalue]
   1.166 -	//ret
   1.167 -	IA32_Send_Jump8_Here(jit, jmp);
   1.168 -	IA32_Mov_Eax_Mem(jit, (jit_int32_t)&CDetourManager::returnValue);
   1.169 -	IA32_Return(jit);
   1.170  
   1.171  	if (wr.outbase == NULL)
   1.172  	{
   1.173 @@ -223,15 +146,32 @@
   1.174  		wr.outbase = (jitcode_t)spengine->AllocatePageMemory(CodeSize);
   1.175  		spengine->SetReadWrite(wr.outbase);
   1.176  		wr.outptr = wr.outbase;
   1.177 -		detour_callback = wr.outbase;
   1.178 +		detour_trampoline = wr.outbase;
   1.179  		goto jit_rewind;
   1.180  	}
   1.181  
   1.182  	spengine->SetReadExecute(wr.outbase);
   1.183  
   1.184 +	*trampoline = detour_trampoline;
   1.185 +
   1.186  	return true;
   1.187  }
   1.188  
   1.189 +void CDetour::DeleteDetour()
   1.190 +{
   1.191 +	if (detoured)
   1.192 +	{
   1.193 +		DisableDetour();
   1.194 +	}
   1.195 +
   1.196 +	if (detour_trampoline)
   1.197 +	{
   1.198 +		/* Free the allocated trampoline memory */
   1.199 +		spengine->FreePageMemory(detour_trampoline);
   1.200 +		detour_trampoline = NULL;
   1.201 +	}
   1.202 +}
   1.203 +
   1.204  void CDetour::EnableDetour()
   1.205  {
   1.206  	if (!detoured)
   1.207 @@ -241,132 +181,12 @@
   1.208  	}
   1.209  }
   1.210  
   1.211 -void CDetour::DeleteDetour()
   1.212 -{
   1.213 -	if (detoured)
   1.214 -	{
   1.215 -		DisableDetour();
   1.216 -	}
   1.217 -
   1.218 -	if (detour_callback)
   1.219 -	{
   1.220 -		/* Free the gate */
   1.221 -		spengine->FreePageMemory(detour_callback);
   1.222 -		detour_callback = NULL;
   1.223 -	}
   1.224 -}
   1.225 -
   1.226  void CDetour::DisableDetour()
   1.227  {
   1.228  	if (detoured)
   1.229  	{
   1.230  		/* Remove the patch */
   1.231 -		/* This may screw up */
   1.232  		ApplyPatch(detour_address, 0, &detour_restore, NULL);
   1.233  		detoured = false;
   1.234  	}
   1.235  }
   1.236 -
   1.237 -CBlocker::CBlocker( const char *signame, bool isVoid )
   1.238 -{
   1.239 -	this->isVoid = isVoid;
   1.240 -	isEnabled = false;
   1.241 -	isValid = false;
   1.242 -
   1.243 -	spengine = NULL;
   1.244 -	gameconf = NULL;
   1.245 -	block_address = NULL;
   1.246 -	block_sig = signame;
   1.247 -
   1.248 -	if (isVoid)
   1.249 -	{
   1.250 -		/* Void functions we only patch in a 'ret' (1 byte) */
   1.251 -		block_restore.bytes = 1;
   1.252 -	}
   1.253 -	else
   1.254 -	{
   1.255 -		/* Normal functions need an mov eax, value */
   1.256 -		block_restore.bytes = 6;
   1.257 -	}
   1.258 -}
   1.259 -
   1.260 -void CBlocker::EnableBlock( int returnValue )
   1.261 -{
   1.262 -	if (!isValid || isEnabled)
   1.263 -	{
   1.264 -		return;
   1.265 -	}
   1.266 -
   1.267 -	/* First, save restore bits */
   1.268 -	for (size_t i=0; i<block_restore.bytes; i++)
   1.269 -	{
   1.270 -		block_restore.patch[i] = ((unsigned char *)block_address)[i];
   1.271 -	}
   1.272 -
   1.273 -	JitWriter wr;
   1.274 -	JitWriter *jit = &wr;
   1.275 -	wr.outbase = (jitcode_t)block_address;
   1.276 -	wr.outptr = wr.outbase;
   1.277 -
   1.278 -	if (isVoid)
   1.279 -	{
   1.280 -		IA32_Return(jit);
   1.281 -	}
   1.282 -	else
   1.283 -	{
   1.284 -		IA32_Mov_Reg_Imm32(jit, REG_EAX, returnValue);
   1.285 -		IA32_Return(jit);
   1.286 -	}
   1.287 -
   1.288 -	isEnabled = true;
   1.289 -}
   1.290 -
   1.291 -void CBlocker::DisableBlock()
   1.292 -{
   1.293 -	if (!isValid || !isEnabled)
   1.294 -	{
   1.295 -		return;
   1.296 -	}
   1.297 -
   1.298 -	/* First, save restore bits */
   1.299 -	for (size_t i=0; i<block_restore.bytes; i++)
   1.300 -	{
   1.301 -		((unsigned char *)block_address)[i] = block_restore.patch[i];
   1.302 -	}
   1.303 -
   1.304 -	isEnabled = false;
   1.305 -}
   1.306 -
   1.307 -CBlocker::~CBlocker()
   1.308 -{
   1.309 -	if (!isValid || !isEnabled)
   1.310 -	{
   1.311 -		return;
   1.312 -	}
   1.313 -
   1.314 -	DisableBlock();
   1.315 -}
   1.316 -
   1.317 -bool CBlocker::Init( ISourcePawnEngine *spengine, IGameConfig *gameconf )
   1.318 -{
   1.319 -	this->spengine = spengine;
   1.320 -	this->gameconf = gameconf;
   1.321 -
   1.322 -	if (!gameconf->GetMemSig(block_sig, &block_address))
   1.323 -	{
   1.324 -		g_pSM->LogError(myself, "Could not locate %s - Disabling blocker", block_sig);
   1.325 -		isValid = false;
   1.326 -		return false;
   1.327 -	}
   1.328 -
   1.329 -	if (!block_address)
   1.330 -	{
   1.331 -		g_pSM->LogError(myself, "Sigscan for %s failed - Disabling blocker", block_sig);
   1.332 -		isValid = false;
   1.333 -		return false;
   1.334 -	}
   1.335 -
   1.336 -	isValid = true;
   1.337 -
   1.338 -	return true;
   1.339 -}