Updated CDetour code in TF2 extension to prevent crashes with spies. Updated windows sig.
3 * =============================================================================
5 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
29 * Version: $Id: detours.cpp 248 2008-08-27 00:56:22Z pred $
35 ISourcePawnEngine *CDetourManager::spengine = NULL;
36 IGameConfig *CDetourManager::gameconf = NULL;
38 void CDetourManager::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf)
40 CDetourManager::spengine = spengine;
41 CDetourManager::gameconf = gameconf;
44 CDetour *CDetourManager::CreateDetour(void *callbackfunction, void **trampoline, const char *signame)
46 CDetour *detour = new CDetour(callbackfunction, trampoline, signame);
49 if (!detour->Init(spengine, gameconf))
61 CDetour::CDetour(void *callbackfunction, void **trampoline, const char *signame)
65 detour_address = NULL;
66 detour_trampoline = NULL;
67 this->signame = signame;
68 this->detour_callback = callbackfunction;
71 this->trampoline = trampoline;
74 bool CDetour::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf)
76 this->spengine = spengine;
77 this->gameconf = gameconf;
90 void CDetour::Destroy()
96 bool CDetour::IsEnabled()
101 bool CDetour::CreateDetour()
103 if (!gameconf->GetMemSig(signame, &detour_address))
105 g_pSM->LogError(myself, "Could not locate %s - Disabling detour", signame);
111 g_pSM->LogError(myself, "Sigscan for %s failed - Disabling detour to prevent crashes", signame);
115 detour_restore.bytes = copy_bytes((unsigned char *)detour_address, NULL, OP_JMP_SIZE+1);
117 /* First, save restore bits */
118 for (size_t i=0; i<detour_restore.bytes; i++)
120 detour_restore.patch[i] = ((unsigned char *)detour_address)[i];
124 JitWriter *jit = ≀
125 jit_uint32_t CodeSize = 0;
132 /* Patch old bytes in */
133 if (wr.outbase != NULL)
135 copy_bytes((unsigned char *)detour_address, (unsigned char*)wr.outptr, detour_restore.bytes);
137 wr.outptr += detour_restore.bytes;
139 /* Return to the original function */
140 jitoffs_t call = IA32_Jump_Imm32(jit, 0);
141 IA32_Write_Jump32_Abs(jit, call, (unsigned char *)detour_address + detour_restore.bytes);
143 if (wr.outbase == NULL)
145 CodeSize = wr.get_outputpos();
146 wr.outbase = (jitcode_t)spengine->AllocatePageMemory(CodeSize);
147 spengine->SetReadWrite(wr.outbase);
148 wr.outptr = wr.outbase;
149 detour_trampoline = wr.outbase;
153 spengine->SetReadExecute(wr.outbase);
155 *trampoline = detour_trampoline;
160 void CDetour::DeleteDetour()
167 if (detour_trampoline)
169 /* Free the allocated trampoline memory */
170 spengine->FreePageMemory(detour_trampoline);
171 detour_trampoline = NULL;
175 void CDetour::EnableDetour()
179 DoGatePatch((unsigned char *)detour_address, &detour_callback);
184 void CDetour::DisableDetour()
188 /* Remove the patch */
189 ApplyPatch(detour_address, 0, &detour_restore, NULL);