IEntityFactoryDictionary *EntityFactoryDictionary() { if(g_entityFactoryDictionary) return g_entityFactoryDictionary; if ( g_nServerToolsVersion >= 2 ) { g_entityFactoryDictionary = servertools->GetEntityFactoryDictionary(); return g_entityFactoryDictionary; } #ifdef WIN32 ConCommandBase *pPtr = pAdminOP.GetCommands(); while (pPtr) { if (pPtr->IsCommand() && strcmp(pPtr->GetName(), "dumpentityfactories") == 0) { ConCommand *ptr = (ConCommand*)pPtr; //CEntityFactoryDictionary *dict = ( CEntityFactoryDictionary * )*(int *)( ((char*)VFuncs::GetCommandCallback(ptr))+0x14 ); CEntityFactoryDictionary *dict = VFuncs::GetEntityDictionary(ptr); if ( dict ) { g_entityFactoryDictionary = dict; return dict; } } pPtr = const_cast<ConCommandBase*>(pPtr->GetNext()); } #else g_entityFactoryDictionary = VFuncs::GetEntityDictionary(NULL); return g_entityFactoryDictionary; #endif return NULL; }
//Thanks to fysh for the idea of extracting info from "echo" and for // having the original offsets at hand! bool CSmmAPI::CacheCmds() { ICvar *pCvar = g_Engine.icvar; ConCommandBase *pBase = pCvar->GetCommands(); unsigned char *ptr = NULL; FnCommandCallback callback = NULL; int offs = 0; while (pBase) { if ( strcmp(pBase->GetName(), "echo") == 0 ) { //callback = //*((FnCommandCallback *)((char *)pBase + offsetof(ConCommand, m_fnCommandCallback))); callback = ((ConCommand *)pBase)->GetCallback(); ptr = (unsigned char *)callback; #ifdef OS_LINUX if (UTIL_VerifySignature(ptr, ENGINE486_SIG, SIGLEN)) { offs = ENGINE486_OFFS; } else if (UTIL_VerifySignature(ptr, ENGINE686_SIG, SIGLEN)) { offs = ENGINE686_OFFS; } else if (UTIL_VerifySignature(ptr, ENGINEAMD_SIG, SIGLEN)) { offs = ENGINEAMD_OFFS; } #elif defined OS_WIN32 // Only one Windows engine binary so far... if (UTIL_VerifySignature(ptr, ENGINEW32_SIG, SIGLEN)) { offs = ENGINEW32_OFFS; } #endif if (!offs || ptr[offs - 1] != IA32_CALL) { m_ConPrintf = (CONPRINTF_FUNC)Msg; return false; } //get the relative offset m_ConPrintf = *((CONPRINTF_FUNC *)(ptr + offs)); //add the base offset, to the ip (which is the address+offset + 4 bytes for next instruction) m_ConPrintf = (CONPRINTF_FUNC)((unsigned long)m_ConPrintf + (unsigned long)(ptr + offs) + 4); m_CmdCache = true; return true; } pBase = const_cast<ConCommandBase *>(pBase->GetNext()); } m_ConPrintf = (CONPRINTF_FUNC)Msg; return false; }
void CSourceMMMAP::HookConCommands() { //find the commands in the server's CVAR list #if defined (GAME_CSGO) pSayCmd = static_cast<ConCommand *>(g_pCVar->FindCommand("say")); pTeamSayCmd = static_cast<ConCommand *>(g_pCVar->FindCommand("say_team")); pChangeLevelCmd = static_cast<ConCommand *>(g_pCVar->FindCommand("changelevel")); pAutoBuyCmd = static_cast<ConCommand *>(g_pCVar->FindCommand("autobuy")); pReBuyCmd = static_cast<ConCommand *>(g_pCVar->FindCommand("rebuy")); pRespawnEntities = static_cast<ConCommand *>(g_pCVar->FindCommand("respawn_entities")); #else ConCommandBase *pCmd = g_pCVar->GetCommands(); while (pCmd) { if (pCmd->IsCommand()) { if (strcmp(pCmd->GetName(), "say") == 0) pSayCmd = static_cast<ConCommand *>(pCmd); else if (strcmp(pCmd->GetName(), "say_team") == 0) pTeamSayCmd = static_cast<ConCommand *>(pCmd); else if (strcmp(pCmd->GetName(), "changelevel") == 0) pChangeLevelCmd = static_cast<ConCommand *>(pCmd); else if (strcmp(pCmd->GetName(), "autobuy") == 0) pAutoBuyCmd = static_cast<ConCommand *>(pCmd); else if (strcmp(pCmd->GetName(), "rebuy") == 0) pReBuyCmd = static_cast<ConCommand *>(pCmd); else if (strcmp(pCmd->GetName(), "respawn_entities") == 0) pRespawnEntities = static_cast<ConCommand *>(pCmd); } pCmd = const_cast<ConCommandBase *>(pCmd->GetNext()); } #endif #if !defined GAME_ORANGE && defined SOURCEMM if (pSayCmd) SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pSayCmd, Say_handler, false); if (pRespawnEntities) SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pRespawnEntities, RespawnEntities_handler, false); if (pTeamSayCmd) SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pTeamSayCmd, TeamSay_handler, false); if (pChangeLevelCmd) SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pChangeLevelCmd, ChangeLevel_handler, false); if (pAutoBuyCmd) { SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pAutoBuyCmd, AutoBuy_handler, false); autobuy_cc = SH_GET_CALLCLASS(pAutoBuyCmd); } if (pReBuyCmd) { SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pReBuyCmd, ReBuy_handler, false); rebuy_cc = SH_GET_CALLCLASS(pReBuyCmd); } #else if (pSayCmd) SH_ADD_HOOK(ConCommand, Dispatch, pSayCmd, SH_STATIC(Say_handler), false); if (pRespawnEntities) SH_ADD_HOOK(ConCommand, Dispatch, pRespawnEntities, SH_STATIC(RespawnEntities_handler), false); if (pTeamSayCmd) SH_ADD_HOOK(ConCommand, Dispatch, pTeamSayCmd, SH_STATIC(TeamSay_handler), false); if (pChangeLevelCmd) SH_ADD_HOOK(ConCommand, Dispatch, pChangeLevelCmd, SH_STATIC(ChangeLevel_handler), false); if (pAutoBuyCmd) SH_ADD_HOOK(ConCommand, Dispatch, pAutoBuyCmd, SH_STATIC(AutoBuy_handler), false); if (pReBuyCmd) SH_ADD_HOOK(ConCommand, Dispatch, pReBuyCmd, SH_STATIC(ReBuy_handler), false); #endif }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void ConVar::RevertAll( void ) { ConCommandBase *p = s_pConCommandBases; while ( p ) { if ( !p->IsCommand() ) { ConVar *var = ( ConVar * )p; var->Revert(); } p = p->m_pNext; } }
// // Name: CC_BalanceMacroReport( const CCommand& args ) // Author: Hekar Khani // Description: ConCommand to display a simple report of the current balance macros // Notes: // void CC_BalanceMacroReport( const CCommand& args ) { ConCommandBase *Command = cvar->GetCommands(); for ( ; Command != NULL; Command = Command->GetNext()) { ConVar *convar = dynamic_cast< ConVar * > ( Command ); if ( !convar ) { continue; } const char *convarname = convar->GetName(); if ( Q_strstr( convarname, "lfm" ) ) { Msg( "Name: %s\t\tValue: %s\t\tDesc: %s\n", convar->GetName(), convar->GetString(), convar->GetHelpText() ); } } }
void SMConVarAccessor::Unregister(ConCommandBase *pCommand) { #if SOURCE_ENGINE >= SE_ORANGEBOX icvar->UnregisterConCommand(pCommand); #else ConCommandBase *pCur = NULL; ConCommandBase *pPrev = NULL; if (!pCommand) { return; } pCur = icvar->GetCommands(); if (!m_TopConCommandBase || !pCur) { return; } if (pCur == pCommand) { *m_TopConCommandBase = const_cast<ConCommandBase *>(pCommand->GetNext()); pCommand->SetNext(NULL); return; } pPrev = pCur; pCur = const_cast<ConCommandBase *>(pCur->GetNext()); while (pCur) { if (pCur == pCommand) { pPrev->SetNext(const_cast<ConCommandBase *>(pCommand->GetNext())); pCommand->SetNext(NULL); } pPrev = pCur; pCur = const_cast<ConCommandBase *>(pCur->GetNext()); } #endif }
// // Name: CC_BalanceMacroReport( const CCommand& args ) // Author: Hekar Khani // Description: ConCommand to display a report of the current balance macros in CSV format // Notes: // void CC_BalanceMacroReportCSV( const CCommand& args ) { // HODO: add ability to write to file ConCommandBase *Command = cvar->GetCommands(); for ( ; Command != NULL; Command = Command->GetNext()) { ConVar *convar = dynamic_cast< ConVar * > ( Command ); if ( !convar ) { continue; } Msg( "Convar, Value, Description\n" ); const char *convarname = convar->GetName(); if ( Q_strstr( convarname, "lfm" ) ) { Msg( "%s, %s, %s\n", convar->GetName(), convar->GetString(), convar->GetHelpText() ); } } }
bool SetFlags(const char *name, int flags) { ConCommandBase *pCmd; if (m_CmdFlags.retrieve(name, &pCmd)) { pCmd->SetFlags(flags); TrackConCommandBase(pCmd, this); return true; } else if ((pCmd=FindCommandBase(name))) { m_CmdFlags.insert(name, pCmd); pCmd->SetFlags(flags); TrackConCommandBase(pCmd, this); return true; } else { return false; } }
void SMConVarAccessor::Unregister(ConCommandBase *pCommand) { ConCommandBase *pCur = NULL; ConCommandBase *pPrev = NULL; if (!pCommand || !pCommand->IsRegistered()) { return; } pCur = g_Engine.icvar->GetCommands(); pCommand->SetRegistered(false); if (!m_TopConCommandBase || !pCur) { return; } if (pCur == pCommand) { *m_TopConCommandBase = const_cast<ConCommandBase *>(pCommand->GetNext()); pCommand->SetNext(NULL); return; } pPrev = pCur; pCur = const_cast<ConCommandBase *>(pCur->GetNext()); while (pCur) { if (pCur == pCommand) { pPrev->SetNext(const_cast<ConCommandBase *>(pCommand->GetNext())); pCommand->SetNext(NULL); } pPrev = pCur; pCur = const_cast<ConCommandBase *>(pCur->GetNext()); } }
bool GetFlags(const char *name, int *flags) { ConCommandBase **ppCmd; ConCommandBase *pCmd; if ((ppCmd=m_CmdFlags.retrieve(name))) { TrackConCommandBase((*ppCmd), this); *flags = (*ppCmd)->GetFlags(); return true; } else if ((pCmd=FindCommandBase(name))) { m_CmdFlags.insert(name, pCmd); TrackConCommandBase(pCmd, this); *flags = pCmd->GetFlags(); return true; } else { return false; } }
void ChatTriggers::OnSourceModGameInitialized() { unsigned int total = 2; ConCommandBase *pCmd = icvar->GetCommands(); const char *name; while (pCmd) { if (pCmd->IsCommand()) { name = pCmd->GetName(); if (!m_pSayCmd && strcmp(name, "say") == 0) { m_pSayCmd = (ConCommand *)pCmd; if (--total == 0) { break; } } else if (!m_pSayTeamCmd && strcmp(name, "say_team") == 0) { m_pSayTeamCmd = (ConCommand *)pCmd; if (--total == 0) { break; } } } pCmd = const_cast<ConCommandBase *>(pCmd->GetNext()); } if (m_pSayCmd) { SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Pre, false); SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Post, true); } if (m_pSayTeamCmd) { SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Pre, false); SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Post, true); } }
void ManiSMMHooks::HookConCommands() { //find the commands in the server's CVAR list #if defined (GAME_CSGO) pSayCmd = static_cast<ConCommand *>(g_pCVar->FindCommand("say")); pTeamSayCmd = static_cast<ConCommand *>(g_pCVar->FindCommand("say_team")); pChangeLevelCmd = static_cast<ConCommand *>(g_pCVar->FindCommand("changelevel")); pAutoBuyCmd = static_cast<ConCommand *>(g_pCVar->FindCommand("autobuy")); pReBuyCmd = static_cast<ConCommand *>(g_pCVar->FindCommand("rebuy")); pRespawnEntities = static_cast<ConCommand *>(g_pCVar->FindCommand("respawn_entities")); #else ConCommandBase *pCmd = NULL; pCmd = g_pCVar->GetCommands(); while (pCmd) { if (pCmd->IsCommand()) { if (strcmp(pCmd->GetName(), "say") == 0) pSayCmd = static_cast<ConCommand *>(pCmd); else if (strcmp(pCmd->GetName(), "say_team") == 0) pTeamSayCmd = static_cast<ConCommand *>(pCmd); else if (strcmp(pCmd->GetName(), "changelevel") == 0) pChangeLevelCmd = static_cast<ConCommand *>(pCmd); else if (strcmp(pCmd->GetName(), "autobuy") == 0) pAutoBuyCmd = static_cast<ConCommand *>(pCmd); else if (strcmp(pCmd->GetName(), "rebuy") == 0) pReBuyCmd = static_cast<ConCommand *>(pCmd); else if (strcmp(pCmd->GetName(), "respawn_entities") == 0) pRespawnEntities = static_cast<ConCommand *>(pCmd); } pCmd = const_cast<ConCommandBase *>(pCmd->GetNext()); } #endif if (pSayCmd) SH_ADD_HOOK(ConCommand, Dispatch, pSayCmd, SH_STATIC(Say_handler), false); if (pRespawnEntities) SH_ADD_HOOK(ConCommand, Dispatch, pRespawnEntities, SH_STATIC(RespawnEntities_handler), false); if (pTeamSayCmd) SH_ADD_HOOK(ConCommand, Dispatch, pTeamSayCmd, SH_STATIC(TeamSay_handler), false); if (pChangeLevelCmd) SH_ADD_HOOK(ConCommand, Dispatch, pChangeLevelCmd, SH_STATIC(ChangeLevel_handler), false); if (pAutoBuyCmd) SH_ADD_HOOK(ConCommand, Dispatch, pAutoBuyCmd, SH_STATIC(AutoBuy_handler), false); if (pReBuyCmd) SH_ADD_HOOK(ConCommand, Dispatch, pReBuyCmd, SH_STATIC(ReBuy_handler), false); }
bool MyPlugin::Load(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory) { serverGameDLL = (IServerGameDLL *)gameServerFactory(INTERFACEVERSION_SERVERGAMEDLL, NULL); if (serverGameDLL) { ServerClass *svrclass = serverGameDLL->GetAllServerClasses(); while (svrclass) { const char *classname = svrclass->GetName(); Msg("[%s]\n", classname); if (strcmp(classname, "CBasePlayer") == 0) { SendTable *st = svrclass->m_pTable; for (int i = 0; i < st->m_nProps; i++) { SendProp *sp = st->GetProp(i); const char *propname = sp->GetName(); Msg("Prop name: %s | Prop Offset: %d | Type: %d | IsSigned: %d\n", propname, sp->GetOffset(), sp->GetType(), sp->IsSigned()); if (strcmp(propname, "m_fFlags") == 0) { m_fFlags_off = sp->GetOffset(); continue; } if (strcmp(propname, "m_iHealth") == 0) { m_iHealth_off = sp->GetOffset(); continue; } } } if (strcmp(classname, "CBaseEntity") == 0) { SendTable *st = svrclass->m_pTable; for (int i = 0; i < st->m_nProps; i++) { SendProp *sp = st->GetProp(i); const char *propname = sp->GetName(); Msg("Prop name: %s | Prop Offset: %d | Type: %d | IsSigned: %d\n", propname, sp->GetOffset(), sp->GetType(), sp->IsSigned()); if (strcmp(propname, "m_iTeamNum") == 0) { m_iTeamNum_off = sp->GetOffset(); continue; } if (strcmp(propname, "m_iPendingTeamNum") == 0) { m_iPendingTeamNum_off = sp->GetOffset(); continue; } if (strcmp(propname, "m_fEffects") == 0) { m_fEffects_off = sp->GetOffset(); continue; } if (strcmp(propname, "m_nRenderMode") == 0) { m_nRenderMode_off = sp->GetOffset(); continue; } } } /*if (strcmp(classname, "CBaseCombatWeapon") == 0) { SendTable *st = svrclass->m_pTable; for (int i = 0; i < st->m_nProps; i++) { SendProp *sp = st->GetProp(i); const char *propname = sp->GetName(); Msg("Prop name: %s | Prop Offset: %d | Type: %d | IsSigned: %d\n", propname, sp->GetOffset(), sp->GetType(), sp->IsSigned()); } }*/ svrclass = svrclass->m_pNext; } } else { Warning("Unable to load IServerGameDLL.\n"); return false; } serverGameEnts = (IServerGameEnts *)gameServerFactory(INTERFACEVERSION_SERVERGAMEENTS, NULL); if (!serverGameEnts) { Warning("Unable to load IServerGameEnts.\n"); return false; } playerInfoManager = (IPlayerInfoManager *)gameServerFactory(INTERFACEVERSION_PLAYERINFOMANAGER, NULL); if (playerInfoManager) { globalVars = playerInfoManager->GetGlobalVars(); } else { Warning("Unable to load IPlayerInfoManager.\n"); return false; } g_pCVar = (ICvar *)interfaceFactory(CVAR_INTERFACE_VERSION, NULL); if (g_pCVar) { ICvar::Iterator iter(g_pCVar); for (iter.SetFirst(); iter.IsValid(); iter.Next()) { ConCommandBase *cmd = iter.Get(); if (cmd->IsCommand()) continue; const char *cmdname = cmd->GetName(); ConVar *cvar = (ConVar *)cmd; if (strcmp(cmdname, "net_maxcleartime") == 0) cvar->SetValue(0.001f); /*if (strcmp(cmdname, "net_minroutable") == 0) cvar->SetValue(1000);*/ } } else { Warning("Unable to load ICVar.\n"); return false; } gameEventManager2 = (IGameEventManager2 *)interfaceFactory(INTERFACEVERSION_GAMEEVENTSMANAGER2, NULL); if (!gameEventManager2) { Warning("Unable to load IGameEventManager2.\n"); return false; } vEngineServer = (IVEngineServer *)interfaceFactory(INTERFACEVERSION_VENGINESERVER, NULL); if (!vEngineServer) { Warning("Unable to load IVEngineServer.\n"); return false; } serverTools = (IServerTools *)gameServerFactory(VSERVERTOOLS_INTERFACE_VERSION, NULL); if (!serverTools) { Warning("Unable to load IServerTools.\n"); return false; } serverPluginHelpers = (IServerPluginHelpers *)interfaceFactory(INTERFACEVERSION_ISERVERPLUGINHELPERS, NULL); if (!serverPluginHelpers) { Warning("Unable to load IServerPluginHelpers.\n"); return false; } //playerDeathEvent = new PlayerDeathEvent(); //playerSayEvent = new PlayerSayEvent(); //playerConnectEvent = new PlayerConnectEvent(); //playerDisconnectEvent = new PlayerDisconnectEvent(); roundStartEvent = new RoundStartEvent(); //itemPickupEvent = new ItemPickupEvent(); //playerSpawnEvent = new PlayerSpawnEvent(); //playerSpawnedEvent = new PlayerSpawnedEvent(); //announphaseendevent = new AnnouncePhaseEndEvent(); return true; }
bool ConCommandBaseMgr::Fixup(ConCommandBase* pConCommand) { ConCommandBase *pCur; ConCommandBase *pPrev2; ConCommandBase *pCur2; ConCommandBase *pNext2; const char *name; static int initCount = 0; // xboxissue - cvars and its class hierarchy could not be made to instance per subsystem // without massive mangling and re-arranging, instead... // there is only a single chain and therefore single /init/fixup // missing: need to identify which subsystem // could pass as part of declaration in constructor, but how to hide parameter for pc // the accessors (aka callbacks to subsystems) to register with engine // cannot be invoked as their unlink logic expect private lists // so this just mimics the expected end result // must handle early and late constructors // late constructors are usually function scoped static if (!pConCommand) { // the caller is one-time-init if (++initCount > 1) { // the list has already been fixed return true; } } else { // the caller is a console command constructor if (!initCount) { // the list has not been fixed yet // no special behavior return false; } else { // the list has already been fixed // the console command is a late constructor // add in to fixed list bool hasParent = false; if (!pConCommand->IsCommand()) { pCur = ConCommandBase::s_pConCommandBases; while (pCur) { if (pCur->IsCommand() && !stricmp(pCur->m_pszName, pConCommand->m_pszName)) { // set its parent ((ConVar*)pConCommand)->m_pParent = ((ConVar*)pCur)->m_pParent; hasParent = true; break; } pCur = pCur->m_pNext; } } if (!hasParent) { // add to head of list pConCommand->m_pNext = ConCommandBase::s_pConCommandBases; ConCommandBase::s_pConCommandBases = pConCommand; } else return true; } } if (initCount == 1) { // iterate the cvars and set their possible proxy parents // skip over registered (fixed) entries pCur = ConCommandBase::s_pConCommandBases; while (pCur) { if (!pCur->IsCommand() && !pCur->m_bRegistered) { // iterate from the next node until end of list name = pCur->m_pszName; pPrev2 = pCur; pCur2 = pCur->m_pNext; while (pCur2) { pNext2 = pCur2->m_pNext; if (!pCur2->IsCommand() && !stricmp(pCur2->m_pszName, name)) { // found duplicate // unlink and fixup pCur2->m_pNext = NULL; pPrev2->m_pNext = pNext2; // set its parent ((ConVar*)pCur2)->m_pParent = ((ConVar*)pCur)->m_pParent; } else { // no unlink, advance to next node pPrev2 = pCur2; } pCur2 = pNext2; } char const *pValue = GetCommandLineValue(name); if (pValue) ((ConVar*)pCur)->SetValue(pValue); } pCur = pCur->m_pNext; } } #if !defined( _RETAIL ) XBX_rTimeStampLog( Plat_FloatTime(), "xbx PublishCommands:Start" ); PublishCommands( false ); XBX_rTimeStampLog( Plat_FloatTime(), "xbx PublishCommands:Done" ); #endif // fixup has been performed return true; }
void FindConPrintf(void) { ConCommandBase *pBase = NULL; unsigned char *ptr = NULL; #ifdef GAME_ORANGE FnCommandCallback_t callback = NULL; #else FnCommandCallback callback = NULL; #endif int offs = 0; #if !defined ( GAME_CSGO ) pBase = g_pCVar->GetCommands(); while (pBase) { if ( strcmp(pBase->GetName(), "echo") == 0 ) { //callback = //*((FnCommandCallback *)((char *)pBase + offsetof(ConCommand, m_fnCommandCallback))); callback = ((ConCommand *)pBase)->m_fnCommandCallback; ptr = (unsigned char *)callback; if (vcmp(ptr, ENGINE486_SIG, SIGLEN)) { offs = ENGINE486_OFFS; } else if (vcmp(ptr, ENGINE686_SIG, SIGLEN)) { offs = ENGINE686_OFFS; } else if (vcmp(ptr, ENGINEAMD_SIG, SIGLEN)) { offs = ENGINEAMD_OFFS; } else if (vcmp(ptr, ENGINEW32_SIG, SIGLEN)) { offs = ENGINEW32_OFFS; } if (!offs || ptr[offs-1] != IA32_CALL) { return; } //get the relative offset MMsg = *((CONPRINTF_FUNC *)(ptr + offs)); //add the base offset, to the ip (which is the address+offset + 4 bytes for next instruction) MMsg = (CONPRINTF_FUNC)((unsigned long)MMsg + (unsigned long)(ptr + offs) + 4); Msg("Using conprintf\n"); return; } pBase = const_cast<ConCommandBase *>(pBase->GetNext()); } #else pBase = g_pCVar->FindCommand("echo"); callback = ((ConCommand *)pBase)->m_fnCommandCallback; ptr = (unsigned char *)callback; if (vcmp(ptr, ENGINE486_SIG, SIGLEN)) { offs = ENGINE486_OFFS; } else if (vcmp(ptr, ENGINE686_SIG, SIGLEN)) { offs = ENGINE686_OFFS; } else if (vcmp(ptr, ENGINEAMD_SIG, SIGLEN)) { offs = ENGINEAMD_OFFS; } else if (vcmp(ptr, ENGINEW32_SIG, SIGLEN)) { offs = ENGINEW32_OFFS; } if (!offs || ptr[offs-1] != IA32_CALL) { return; } //get the relative offset MMsg = *((CONPRINTF_FUNC *)(ptr + offs)); //add the base offset, to the ip (which is the address+offset + 4 bytes for next instruction) MMsg = (CONPRINTF_FUNC)((unsigned long)MMsg + (unsigned long)(ptr + offs) + 4); Msg("Using conprintf\n"); return; #endif Msg("Using Msg()\n"); MMsg = (CONPRINTF_FUNC)Msg; return; }