teame06@1245: /** teame06@1245: * vim: set ts=4 : ds@1330: * ============================================================================= teame06@1245: * SourceMod SDKTools Extension ds@1947: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. ds@1330: * ============================================================================= teame06@1245: * ds@1330: * This program is free software; you can redistribute it and/or modify it under ds@1330: * the terms of the GNU General Public License, version 3.0, as published by the ds@1330: * Free Software Foundation. teame06@1245: * ds@1330: * This program is distributed in the hope that it will be useful, but WITHOUT ds@1330: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ds@1330: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more ds@1330: * details. teame06@1245: * ds@1330: * You should have received a copy of the GNU General Public License along with ds@1330: * this program. If not, see . teame06@1245: * ds@1330: * As a special exception, AlliedModders LLC gives you permission to link the ds@1330: * code of this program (as well as its derivative works) to "Half-Life 2," the ds@1330: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software ds@1330: * by the Valve Corporation. You must obey the GNU General Public License in ds@1330: * all respects for all other code used. Additionally, AlliedModders LLC grants ds@1330: * this exception to all derivative works. AlliedModders LLC defines further ds@1330: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), ds@1330: * or . faluco@1247: * faluco@1247: * Version: $Id$ faluco@1247: */ faluco@1247: faluco@1247: #include "extension.h" faluco@1247: faluco@1247: void **g_pGameRules = NULL; faluco@1247: void *g_EntList = NULL; faluco@1247: pred@2746: faluco@1247: void InitializeValveGlobals() faluco@1247: { pred@2746: g_EntList = gamehelpers->GetGlobalEntityList(); faluco@1247: skamonkey@3221: /* skamonkey@3221: * g_pGameRules skamonkey@3221: * skamonkey@3221: * First try to lookup pointer directly for platforms with symbols. skamonkey@3221: * If symbols aren't present (Windows or stripped Linux/Mac), skamonkey@3221: * attempt find via CreateGameRulesObject + offset skamonkey@3221: */ faluco@1718: skamonkey@3221: char *addr; skamonkey@3221: if (g_pGameConf->GetMemSig("g_pGameRules", (void **)&addr) && addr) faluco@1718: { skamonkey@3221: g_pGameRules = reinterpret_cast(addr); faluco@1718: } skamonkey@3221: else if (g_pGameConf->GetMemSig("CreateGameRulesObject", (void **)&addr) && addr) faluco@1247: { skamonkey@3221: int offset; skamonkey@3221: if (!g_pGameConf->GetOffset("g_pGameRules", &offset) || !offset) skamonkey@3221: { skamonkey@3221: return; skamonkey@3221: } skamonkey@3221: g_pGameRules = *reinterpret_cast(addr + offset); faluco@1247: } faluco@1247: } faluco@1769: ds@2535: size_t UTIL_StringToSignature(const char *str, char buffer[], size_t maxlength) ds@1952: { ds@2535: size_t real_bytes = 0; ds@2535: size_t length = strlen(str); ds@1952: ds@2535: for (size_t i=0; i= maxlength) ds@2535: { ds@2535: break; ds@2535: } ds@2535: buffer[real_bytes++] = (unsigned char)str[i]; ds@2535: if (str[i] == '\\' ds@2535: && str[i+1] == 'x') ds@2535: { ds@2535: if (i + 3 >= length) ds@2535: { ds@2535: continue; ds@2535: } ds@2535: /* Get the hex part */ ds@2535: char s_byte[3]; ds@2535: int r_byte; ds@2535: s_byte[0] = str[i+2]; ds@2535: s_byte[1] = str[i+3]; ds@2535: s_byte[2] = '\n'; ds@2535: /* Read it as an integer */ ds@2535: sscanf(s_byte, "%x", &r_byte); ds@2535: /* Save the value */ ds@2535: buffer[real_bytes-1] = (unsigned char)r_byte; ds@2535: /* Adjust index */ ds@2535: i += 3; ds@2535: } ds@2535: } ds@2535: ds@2535: return real_bytes; ds@2535: } ds@2535: ds@2535: bool UTIL_VerifySignature(const void *addr, const char *sig, size_t len) ds@2535: { ds@2535: unsigned char *addr1 = (unsigned char *) addr; ds@2535: unsigned char *addr2 = (unsigned char *) sig; ds@2535: ds@2535: for (size_t i = 0; i < len; i++) ds@1952: { ds@1952: if (addr2[i] == '*') ds@1952: continue; ds@1952: if (addr1[i] != addr2[i]) ds@1952: return false; ds@1952: } ds@1952: ds@1952: return true; faluco@1773: } faluco@1773: faluco@1769: #if defined PLATFORM_WINDOWS faluco@1769: void GetIServer() faluco@1769: { ds@2535: const char *sigstr; ds@2535: char sig[32]; ds@2535: size_t siglen; faluco@1769: int offset; faluco@1769: void *vfunc = NULL; faluco@1769: ds@2858: #if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11 faluco@1769: /* Get the CreateFakeClient function pointer */ faluco@1769: if (!(vfunc=SH_GET_ORIG_VFNPTR_ENTRY(engine, &IVEngineServer::CreateFakeClient))) faluco@1769: { faluco@1769: return; faluco@1769: } faluco@1769: #else faluco@1769: /* Get the interface manually */ faluco@1769: SourceHook::MemFuncInfo info = {true, -1, 0, 0}; faluco@1769: SourceHook::GetFuncInfo(&IVEngineServer::CreateFakeClient, info); faluco@1769: faluco@1769: vfunc = enginePatch->GetOrigFunc(info.vtbloffs, info.vtblindex); faluco@1769: if (!vfunc) faluco@1769: { faluco@1769: void **vtable = *reinterpret_cast(enginePatch->GetThisPtr() + info.thisptroffs + info.vtbloffs); faluco@1769: vfunc = vtable[info.vtblindex]; faluco@1769: } ds@2535: #endif ds@2535: ds@2535: /* Get signature string for IVEngineServer::CreateFakeClient() */ ds@2535: sigstr = g_pGameConf->GetKeyValue("CreateFakeClient_Windows"); ds@2535: ds@2535: if (!sigstr) faluco@1773: { faluco@1773: return; faluco@1773: } faluco@1769: ds@2535: /* Convert signature string to signature bytes */ ds@2535: siglen = UTIL_StringToSignature(sigstr, sig, sizeof(sig)); ds@2535: ds@2535: /* Check if we're on the expected function */ ds@2535: if (!UTIL_VerifySignature(vfunc, sig, siglen)) ds@2535: { ds@2535: return; ds@2535: } ds@2535: ds@2535: /* Get the offset into CreateFakeClient */ ds@2535: if (!g_pGameConf->GetOffset("sv", &offset)) ds@2535: { ds@2535: return; ds@2535: } ds@2535: ds@2535: /* Finally we have the interface we were looking for */ faluco@1769: iserver = *reinterpret_cast(reinterpret_cast(vfunc) + offset); faluco@1769: } faluco@1769: #elif defined PLATFORM_POSIX faluco@1769: void GetIServer() faluco@1769: { faluco@1769: void *addr; faluco@1769: if (!g_pGameConf->GetMemSig("sv", &addr) || !addr) faluco@1769: { faluco@1769: return; faluco@1769: } faluco@1769: faluco@1773: iserver = reinterpret_cast(addr); faluco@1769: } faluco@1769: #endif