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