mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2025-12-07 02:18:30 +00:00
removed old providers location
replaced sourcehook with v4.5 --HG-- branch : sourcemm-1.6.0 extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/branches/sourcemm-1.6.0%40436
This commit is contained in:
parent
c9b52f2cf0
commit
98aeb7b419
@ -1,70 +0,0 @@
|
||||
#(C)2004-2007 SourceMM Development Team
|
||||
# Makefile written by David "BAILOPAN" Anderson
|
||||
|
||||
HL2SDK = ../../../hl2sdk
|
||||
SMM_ROOT = ..
|
||||
SRCDS = ~/srcds
|
||||
|
||||
### EDIT BELOW FOR OTHER PROJECTS ###
|
||||
|
||||
OPT_FLAGS = -O2 -funroll-loops -s -pipe
|
||||
GCC4_FLAGS = -fvisibility=hidden -fvisibility-inlines-hidden
|
||||
DEBUG_FLAGS = -g -ggdb3
|
||||
CPP = gcc-4.1
|
||||
BINARY = provider_ep1_i486.so
|
||||
|
||||
HL2PUB = $(HL2SDK)/public
|
||||
HL2LIB = $(HL2SDK)/linux_sdk
|
||||
|
||||
OBJECTS = provider_util.cpp episode1/provider_ep1.cpp episode1/console.cpp
|
||||
|
||||
LINK = $(HL2LIB)/tier1_i486.a vstdlib_i486.so tier0_i486.so -static-libgcc
|
||||
|
||||
INCLUDE = -I. -I$(HL2PUB) -I$(HL2PUB)/dlls -I$(HL2PUB)/engine -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 \
|
||||
-I$(HL2PUB)/vstdlib -I$(HL2SDK)/tier1 -I$(SMM_ROOT) -I$(SMM_ROOT)/sourcehook \
|
||||
-I$(SMM_ROOT)/sourcemm
|
||||
|
||||
ifeq "$(DEBUG)" "true"
|
||||
BIN_DIR = Debug
|
||||
CFLAGS = $(DEBUG_FLAGS)
|
||||
else
|
||||
BIN_DIR = Release
|
||||
CFLAGS = $(OPT_FLAGS)
|
||||
endif
|
||||
|
||||
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
|
||||
|
||||
CFLAGS += -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Wno-non-virtual-dtor -Werror -fPIC -fno-exceptions -fno-rtti -msse
|
||||
|
||||
ifeq "$(GCC_VERSION)" "4"
|
||||
CFLAGS += $(GCC4_FLAGS)
|
||||
endif
|
||||
|
||||
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
|
||||
|
||||
$(BIN_DIR)/%.o: %.cpp
|
||||
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
all:
|
||||
mkdir -p $(BIN_DIR)
|
||||
mkdir -p $(BIN_DIR)/episode1
|
||||
ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so
|
||||
ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so
|
||||
$(MAKE) -f Makefile.ep1 provider
|
||||
rm -rf $(BINARY)
|
||||
|
||||
provider: $(OBJ_LINUX)
|
||||
$(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
|
||||
|
||||
debug:
|
||||
$(MAKE) -f Makefile.ep1 all DEBUG=true
|
||||
|
||||
default: all
|
||||
|
||||
clean:
|
||||
rm -rf Release/episode1/*.o
|
||||
rm -rf Release/*.o
|
||||
rm -rf Release/$(BINARY)
|
||||
rm -rf Debug/episode1/*.o
|
||||
rm -rf Debug/*.o
|
||||
rm -rf Debug/$(BINARY)
|
||||
@ -1,111 +0,0 @@
|
||||
#include "console.h"
|
||||
#include "provider_ep1.h"
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
SMConVarAccessor g_SMConVarAccessor;
|
||||
|
||||
class CAlwaysRegisterableCommand : public ConCommandBase
|
||||
{
|
||||
public:
|
||||
CAlwaysRegisterableCommand()
|
||||
{
|
||||
Create("metamod_eternal", NULL, FCVAR_UNREGISTERED|FCVAR_GAMEDLL);
|
||||
}
|
||||
bool IsRegistered( void ) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
void BringToFront()
|
||||
{
|
||||
// First, let's try to find us!
|
||||
ConCommandBase *pPtr = icvar->GetCommands();
|
||||
|
||||
if (pPtr == this)
|
||||
{
|
||||
// We are already at the beginning; Nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
while (pPtr)
|
||||
{
|
||||
if (pPtr == this)
|
||||
{
|
||||
break;
|
||||
}
|
||||
ConCommandBase *pPrev = NULL;
|
||||
while (pPtr)
|
||||
{
|
||||
if (pPtr == this)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pPrev = pPtr;
|
||||
pPtr = const_cast<ConCommandBase*>(pPtr->GetNext());
|
||||
}
|
||||
if (pPrev && pPtr == this)
|
||||
{
|
||||
pPrev->SetNext(m_pNext); // Remove us from the list
|
||||
}
|
||||
// Now, register us
|
||||
SetNext(NULL);
|
||||
icvar->RegisterConCommandBase(this);
|
||||
}
|
||||
}
|
||||
} s_EternalCommand;
|
||||
|
||||
bool SMConVarAccessor::RegisterConCommandBase(ConCommandBase *pCommand)
|
||||
{
|
||||
m_RegisteredCommands.push_back(pCommand);
|
||||
pCommand->SetNext(NULL);
|
||||
icvar->RegisterConCommandBase(pCommand);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SMConVarAccessor::Register(ConCommandBase *pCommand)
|
||||
{
|
||||
pCommand->SetNext(NULL);
|
||||
icvar->RegisterConCommandBase(pCommand);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SMConVarAccessor::MarkCommandsAsGameDLL()
|
||||
{
|
||||
for (List<ConCommandBase*>::iterator iter = m_RegisteredCommands.begin();
|
||||
iter != m_RegisteredCommands.end(); ++iter)
|
||||
{
|
||||
(*iter)->AddFlags(FCVAR_GAMEDLL);
|
||||
}
|
||||
}
|
||||
|
||||
void SMConVarAccessor::Unregister(ConCommandBase *pCommand)
|
||||
{
|
||||
ConCommandBase *ptr = icvar->GetCommands();
|
||||
|
||||
if (ptr == pCommand)
|
||||
{
|
||||
s_EternalCommand.BringToFront();
|
||||
s_EternalCommand.SetNext(const_cast<ConCommandBase *>(pCommand->GetNext()));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Find us and unregister us */
|
||||
ConCommandBase *pPrev = NULL;
|
||||
while (ptr)
|
||||
{
|
||||
if (ptr == pCommand)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pPrev = ptr;
|
||||
ptr = const_cast<ConCommandBase *>(ptr->GetNext());
|
||||
}
|
||||
if (pPrev && ptr == pCommand)
|
||||
{
|
||||
pPrev->SetNext(const_cast<ConCommandBase *>(pCommand->GetNext()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
#ifndef _INCLUDE_CONSOLE_MMS_H_
|
||||
#define _INCLUDE_CONSOLE_MMS_H_
|
||||
|
||||
#include "convar_smm.h"
|
||||
#include <interface.h>
|
||||
#include <eiface.h>
|
||||
#include <sh_list.h>
|
||||
|
||||
class SMConVarAccessor : public IConCommandBaseAccessor
|
||||
{
|
||||
public:
|
||||
bool RegisterConCommandBase(ConCommandBase *pCommand);
|
||||
bool Register(ConCommandBase *pCommand);
|
||||
void MarkCommandsAsGameDLL();
|
||||
void Unregister(ConCommandBase *pCommand);
|
||||
void UnregisterGameDLLCommands();
|
||||
private:
|
||||
SourceHook::List<ConCommandBase*> m_RegisteredCommands;
|
||||
};
|
||||
|
||||
extern SMConVarAccessor g_SMConVarAccessor;
|
||||
|
||||
#endif //_INCLUDE_CONSOLE_MMS_H_
|
||||
|
||||
@ -1,523 +0,0 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: 2007-02-08 04:19:19 -0500 (Thu, 08 Feb 2007) $
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef CONVAR_H
|
||||
#define CONVAR_H
|
||||
#if _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "tier0/dbg.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define FORCEINLINE_CVAR FORCEINLINE
|
||||
#elif _LINUX
|
||||
#define FORCEINLINE_CVAR __inline__ FORCEINLINE
|
||||
#else
|
||||
#error "implement me"
|
||||
#endif
|
||||
|
||||
// The default, no flags at all
|
||||
#define FCVAR_NONE 0
|
||||
|
||||
// Command to ConVars and ConCommands
|
||||
// ConVar Systems
|
||||
#define FCVAR_UNREGISTERED (1<<0) // If this is set, don't add to linked list, etc.
|
||||
#define FCVAR_LAUNCHER (1<<1) // defined by launcher
|
||||
#define FCVAR_GAMEDLL (1<<2) // defined by the game DLL
|
||||
#define FCVAR_CLIENTDLL (1<<3) // defined by the client DLL
|
||||
#define FCVAR_MATERIAL_SYSTEM (1<<4) // Defined by the material system.
|
||||
#define FCVAR_DATACACHE (1<<19) // Defined by the datacache system.
|
||||
#define FCVAR_STUDIORENDER (1<<15) // Defined by the studiorender system.
|
||||
#define FCVAR_FILESYSTEM (1<<21) // Defined by the file system.
|
||||
#define FCVAR_PLUGIN (1<<18) // Defined by a 3rd party plugin.
|
||||
#define FCVAR_TOOLSYSTEM (1<<20) // Defined by an IToolSystem library
|
||||
#define FCVAR_SOUNDSYSTEM (1<<23) // Defined by the soundsystem library
|
||||
#define FCVAR_INPUTSYSTEM (1<<25) // Defined by the inputsystem dll
|
||||
#define FCVAR_NETWORKSYSTEM (1<<26) // Defined by the network system
|
||||
// NOTE!! if you add a cvar system, add it here too!!!!
|
||||
// the engine lacks a cvar flag, but needs it for xbox
|
||||
// an engine cvar is thus a cvar not marked with any other system
|
||||
#define FCVAR_NON_ENGINE ((FCVAR_LAUNCHER|FCVAR_GAMEDLL|FCVAR_CLIENTDLL|FCVAR_MATERIAL_SYSTEM|FCVAR_DATACACHE|FCVAR_STUDIORENDER|FCVAR_FILESYSTEM|FCVAR_PLUGIN|FCVAR_TOOLSYSTEM|FCVAR_SOUNDSYSTEM|FCVAR_INPUTSYSTEM|FCVAR_NETWORKSYSTEM))
|
||||
|
||||
// ConVar only
|
||||
#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value
|
||||
#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server.
|
||||
#define FCVAR_ARCHIVE (1<<7) // set to cause it to be saved to vars.rc
|
||||
#define FCVAR_NOTIFY (1<<8) // notifies players when changed
|
||||
#define FCVAR_USERINFO (1<<9) // changes the client's info string
|
||||
#define FCVAR_CHEAT (1<<14) // Only useable in singleplayer / debug / multiplayer & sv_cheats
|
||||
|
||||
#define FCVAR_PRINTABLEONLY (1<<10) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
|
||||
#define FCVAR_UNLOGGED (1<<11) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
|
||||
#define FCVAR_NEVER_AS_STRING (1<<12) // never try to print that cvar
|
||||
|
||||
// It's a ConVar that's shared between the client and the server.
|
||||
// At signon, the values of all such ConVars are sent from the server to the client (skipped for local
|
||||
// client, of course )
|
||||
// If a change is requested it must come from the console (i.e., no remote client changes)
|
||||
// If a value is changed while a server is active, it's replicated to all connected clients
|
||||
#define FCVAR_REPLICATED (1<<13) // server setting enforced on clients, TODO rename to FCAR_SERVER at some time
|
||||
#define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file
|
||||
#define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles
|
||||
|
||||
#define FCVAR_NOT_CONNECTED (1<<22) // cvar cannot be changed by a client that is connected to a server
|
||||
|
||||
#define FCVAR_ARCHIVE_XBOX (1<<24) // cvar written to config.cfg on the Xbox
|
||||
|
||||
|
||||
// #define FCVAR_AVAILABLE (1<<27)
|
||||
// #define FCVAR_AVAILABLE (1<<28)
|
||||
// #define FCVAR_AVAILABLE (1<<29)
|
||||
// #define FCVAR_AVAILABLE (1<<30)
|
||||
// #define FCVAR_AVAILABLE (1<<31)
|
||||
|
||||
|
||||
class ConVar;
|
||||
class ConCommand;
|
||||
class ConCommandBase;
|
||||
|
||||
// Any executable that wants to use ConVars need to implement one of
|
||||
// these to hook up access to console variables.
|
||||
class IConCommandBaseAccessor
|
||||
{
|
||||
public:
|
||||
// Flags is a combination of FCVAR flags in cvar.h.
|
||||
// hOut is filled in with a handle to the variable.
|
||||
virtual bool RegisterConCommandBase( ConCommandBase *pVar )=0;
|
||||
};
|
||||
|
||||
|
||||
// You don't have to instantiate one of these, just call its
|
||||
// OneTimeInit function when your executable is initializing.
|
||||
class ConCommandBaseMgr
|
||||
{
|
||||
public:
|
||||
// Call this ONCE when the executable starts up.
|
||||
static void OneTimeInit( IConCommandBaseAccessor *pAccessor );
|
||||
#ifdef _XBOX
|
||||
static bool Fixup( ConCommandBase* pConCommandBase );
|
||||
#ifndef _RETAIL
|
||||
static void PublishCommands( bool bForce );
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
// Called when a ConVar changes value
|
||||
typedef void ( *FnChangeCallback )( ConVar *var, char const *pOldString );
|
||||
|
||||
// Called when a ConCommand needs to execute
|
||||
typedef void ( *FnCommandCallback )( void );
|
||||
|
||||
#define COMMAND_COMPLETION_MAXITEMS 64
|
||||
#define COMMAND_COMPLETION_ITEM_LENGTH 64
|
||||
|
||||
// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
|
||||
typedef int ( *FnCommandCompletionCallback )( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: The base console invoked command/cvar interface
|
||||
//-----------------------------------------------------------------------------
|
||||
class ConCommandBase
|
||||
{
|
||||
friend class ConCommandBaseMgr;
|
||||
friend class CCvar;
|
||||
friend class ConVar;
|
||||
friend class ConCommand;
|
||||
|
||||
public:
|
||||
ConCommandBase( void );
|
||||
ConCommandBase( char const *pName, char const *pHelpString = 0,
|
||||
int flags = 0 );
|
||||
|
||||
virtual ~ConCommandBase( void );
|
||||
|
||||
virtual bool IsCommand( void ) const;
|
||||
|
||||
// Check flag
|
||||
virtual bool IsBitSet( int flag ) const;
|
||||
// Set flag
|
||||
virtual void AddFlags( int flags );
|
||||
|
||||
// Return name of cvar
|
||||
virtual char const *GetName( void ) const;
|
||||
|
||||
// Return help text for cvar
|
||||
virtual char const *GetHelpText( void ) const;
|
||||
|
||||
// Deal with next pointer
|
||||
const ConCommandBase *GetNext( void ) const;
|
||||
void SetNext( ConCommandBase *next );
|
||||
|
||||
virtual bool IsRegistered( void ) const;
|
||||
|
||||
// Global methods
|
||||
static ConCommandBase const *GetCommands( void );
|
||||
static void AddToList( ConCommandBase *var );
|
||||
static void RemoveFlaggedCommands( int flag );
|
||||
static void RevertFlaggedCvars( int flag );
|
||||
static ConCommandBase const *FindCommand( char const *name );
|
||||
|
||||
protected:
|
||||
virtual void Create( char const *pName, char const *pHelpString = 0,
|
||||
int flags = 0 );
|
||||
|
||||
// Used internally by OneTimeInit to initialize.
|
||||
virtual void Init();
|
||||
|
||||
// Internal copy routine ( uses new operator from correct module )
|
||||
char *CopyString( char const *from );
|
||||
|
||||
// Next ConVar in chain
|
||||
ConCommandBase *m_pNext;
|
||||
|
||||
private:
|
||||
// Has the cvar been added to the global list?
|
||||
bool m_bRegistered;
|
||||
|
||||
// Static data
|
||||
char const *m_pszName;
|
||||
char const *m_pszHelpString;
|
||||
|
||||
// ConVar flags
|
||||
int m_nFlags;
|
||||
|
||||
protected:
|
||||
|
||||
// ConVars add themselves to this list for the executable. Then ConVarMgr::Init() runs through
|
||||
// all the console variables and registers them.
|
||||
static ConCommandBase *s_pConCommandBases;
|
||||
|
||||
// ConVars in this executable use this 'global' to access values.
|
||||
static IConCommandBaseAccessor *s_pAccessor;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: The console invoked command
|
||||
//-----------------------------------------------------------------------------
|
||||
class ConCommand : public ConCommandBase
|
||||
{
|
||||
friend class ConCommandBaseMgr;
|
||||
friend class CCvar;
|
||||
#ifdef _STATIC_LINKED
|
||||
friend class G_ConCommand;
|
||||
friend class C_ConCommand;
|
||||
friend class M_ConCommand;
|
||||
friend class S_ConCommand;
|
||||
friend class D_ConCommand;
|
||||
#endif
|
||||
|
||||
public:
|
||||
typedef ConCommandBase BaseClass;
|
||||
|
||||
ConCommand( void );
|
||||
ConCommand( char const *pName, FnCommandCallback callback,
|
||||
char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
|
||||
|
||||
virtual ~ConCommand( void );
|
||||
|
||||
virtual bool IsCommand( void ) const;
|
||||
|
||||
virtual int AutoCompleteSuggest( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
|
||||
|
||||
virtual bool CanAutoComplete( void );
|
||||
|
||||
// Invoke the function
|
||||
virtual void Dispatch( void );
|
||||
private:
|
||||
virtual void Create( char const *pName, FnCommandCallback callback,
|
||||
char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
|
||||
|
||||
// Call this function when executing the command
|
||||
FnCommandCallback m_fnCommandCallback;
|
||||
|
||||
FnCommandCompletionCallback m_fnCompletionCallback;
|
||||
bool m_bHasCompletionCallback;
|
||||
public:
|
||||
FnCommandCallback GetCallback() { return m_fnCommandCallback; }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: A console variable
|
||||
//-----------------------------------------------------------------------------
|
||||
class ConVar : public ConCommandBase
|
||||
{
|
||||
friend class ConCommandBaseMgr;
|
||||
friend class CCvar;
|
||||
friend class CDefaultCvar;
|
||||
#ifdef _STATIC_LINKED
|
||||
friend class G_ConVar;
|
||||
friend class C_ConVar;
|
||||
friend class M_ConVar;
|
||||
friend class S_ConVar;
|
||||
friend class D_ConVar;
|
||||
#endif
|
||||
|
||||
public:
|
||||
typedef ConCommandBase BaseClass;
|
||||
|
||||
ConVar( char const *pName, char const *pDefaultValue, int flags = 0);
|
||||
|
||||
ConVar( char const *pName, char const *pDefaultValue, int flags,
|
||||
char const *pHelpString );
|
||||
ConVar( char const *pName, char const *pDefaultValue, int flags,
|
||||
char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
|
||||
ConVar( char const *pName, char const *pDefaultValue, int flags,
|
||||
char const *pHelpString, FnChangeCallback callback );
|
||||
ConVar( char const *pName, char const *pDefaultValue, int flags,
|
||||
char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
|
||||
FnChangeCallback callback );
|
||||
|
||||
virtual ~ConVar( void );
|
||||
|
||||
virtual bool IsBitSet( int flag ) const;
|
||||
virtual char const* GetHelpText( void ) const;
|
||||
virtual bool IsRegistered( void ) const;
|
||||
virtual char const *GetName( void ) const;
|
||||
virtual void AddFlags( int flags );
|
||||
virtual bool IsCommand( void ) const;
|
||||
|
||||
// Install a change callback (there shouldn't already be one....)
|
||||
void InstallChangeCallback( FnChangeCallback callback );
|
||||
|
||||
// Retrieve value
|
||||
FORCEINLINE_CVAR float GetFloat( void ) const;
|
||||
FORCEINLINE_CVAR int GetInt( void ) const;
|
||||
FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); }
|
||||
FORCEINLINE_CVAR char const *GetString( void ) const;
|
||||
|
||||
// Any function that allocates/frees memory needs to be virtual or else you'll have crashes
|
||||
// from alloc/free across dll/exe boundaries.
|
||||
|
||||
// These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue).
|
||||
virtual void SetValue( char const *value );
|
||||
virtual void SetValue( float value );
|
||||
virtual void SetValue( int value );
|
||||
|
||||
// Reset to default value
|
||||
void Revert( void );
|
||||
|
||||
// True if it has a min/max setting
|
||||
bool GetMin( float& minVal ) const;
|
||||
bool GetMax( float& maxVal ) const;
|
||||
char const *GetDefault( void ) const;
|
||||
|
||||
static void RevertAll( void );
|
||||
private:
|
||||
// Called by CCvar when the value of a var is changing.
|
||||
virtual void InternalSetValue(char const *value);
|
||||
// For CVARs marked FCVAR_NEVER_AS_STRING
|
||||
virtual void InternalSetFloatValue( float fNewValue );
|
||||
virtual void InternalSetIntValue( int nValue );
|
||||
|
||||
virtual bool ClampValue( float& value );
|
||||
virtual void ChangeStringValue( char const *tempVal );
|
||||
|
||||
virtual void Create( char const *pName, char const *pDefaultValue, int flags = 0,
|
||||
char const *pHelpString = 0, bool bMin = false, float fMin = 0.0,
|
||||
bool bMax = false, float fMax = false, FnChangeCallback callback = 0 );
|
||||
|
||||
// Used internally by OneTimeInit to initialize.
|
||||
virtual void Init();
|
||||
|
||||
private:
|
||||
|
||||
// This either points to "this" or it points to the original declaration of a ConVar.
|
||||
// This allows ConVars to exist in separate modules, and they all use the first one to be declared.
|
||||
// m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar).
|
||||
ConVar *m_pParent;
|
||||
|
||||
// Static data
|
||||
char const *m_pszDefaultValue;
|
||||
|
||||
// Value
|
||||
// Dynamically allocated
|
||||
char *m_pszString;
|
||||
int m_StringLength;
|
||||
|
||||
// Values
|
||||
float m_fValue;
|
||||
int m_nValue;
|
||||
|
||||
// Min/Max values
|
||||
bool m_bHasMin;
|
||||
float m_fMinVal;
|
||||
bool m_bHasMax;
|
||||
float m_fMaxVal;
|
||||
|
||||
// Call this function when ConVar changes
|
||||
FnChangeCallback m_fnChangeCallback;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a float
|
||||
// Output : float
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE_CVAR float ConVar::GetFloat( void ) const
|
||||
{
|
||||
return m_pParent->m_fValue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as an int
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE_CVAR int ConVar::GetInt( void ) const
|
||||
{
|
||||
return m_pParent->m_nValue;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
|
||||
// Output : char const *
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE_CVAR char const *ConVar::GetString( void ) const
|
||||
{
|
||||
if ( m_nFlags & FCVAR_NEVER_AS_STRING )
|
||||
{
|
||||
return "FCVAR_NEVER_AS_STRING";
|
||||
}
|
||||
|
||||
return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : "";
|
||||
}
|
||||
|
||||
|
||||
#ifdef _STATIC_LINKED
|
||||
// identifies subsystem via piggybacking constructors with flags
|
||||
class G_ConCommand : public ConCommand
|
||||
{
|
||||
public:
|
||||
G_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_GAMEDLL, completionFunc) {}
|
||||
};
|
||||
|
||||
class C_ConCommand : public ConCommand
|
||||
{
|
||||
public:
|
||||
C_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_CLIENTDLL, completionFunc) {}
|
||||
};
|
||||
|
||||
class M_ConCommand : public ConCommand
|
||||
{
|
||||
public:
|
||||
M_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_MATERIAL_SYSTEM, completionFunc) {}
|
||||
};
|
||||
|
||||
class S_ConCommand : public ConCommand
|
||||
{
|
||||
public:
|
||||
S_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_STUDIORENDER, completionFunc) {}
|
||||
};
|
||||
|
||||
class D_ConCommand : public ConCommand
|
||||
{
|
||||
public:
|
||||
D_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_DATACACHE, completionFunc) {}
|
||||
};
|
||||
|
||||
typedef void ( *G_FnChangeCallback )( G_ConVar *var, char const *pOldString );
|
||||
typedef void ( *C_FnChangeCallback )( C_ConVar *var, char const *pOldString );
|
||||
typedef void ( *M_FnChangeCallback )( M_ConVar *var, char const *pOldString );
|
||||
typedef void ( *S_FnChangeCallback )( S_ConVar *var, char const *pOldString );
|
||||
typedef void ( *D_FnChangeCallback )( D_ConVar *var, char const *pOldString );
|
||||
|
||||
class G_ConVar : public ConVar
|
||||
{
|
||||
public:
|
||||
G_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL) {}
|
||||
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString ) {}
|
||||
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, bMin, fMin, bMax, fMax) {}
|
||||
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, G_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, (FnChangeCallback)callback ) {}
|
||||
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, G_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
|
||||
};
|
||||
|
||||
class C_ConVar : public ConVar
|
||||
{
|
||||
public:
|
||||
C_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL) {}
|
||||
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString ) {}
|
||||
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, bMin, fMin, bMax, fMax) {}
|
||||
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, C_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, (FnChangeCallback)callback ) {}
|
||||
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, C_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
|
||||
};
|
||||
|
||||
class M_ConVar : public ConVar
|
||||
{
|
||||
public:
|
||||
M_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM) {}
|
||||
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString ) {}
|
||||
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, bMin, fMin, bMax, fMax) {}
|
||||
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, (FnChangeCallback)callback ) {}
|
||||
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
|
||||
};
|
||||
|
||||
class S_ConVar : public ConVar
|
||||
{
|
||||
public:
|
||||
S_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER) {}
|
||||
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString ) {}
|
||||
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, bMin, fMin, bMax, fMax) {}
|
||||
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, (FnChangeCallback)callback ) {}
|
||||
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, S_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
|
||||
};
|
||||
|
||||
class D_ConVar : public ConVar
|
||||
{
|
||||
public:
|
||||
D_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE) {}
|
||||
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString ) {}
|
||||
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, bMin, fMin, bMax, fMax) {}
|
||||
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, (FnChangeCallback)callback ) {}
|
||||
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, D_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
|
||||
};
|
||||
|
||||
// redirect these declarations to their specific subsystem
|
||||
#ifdef GAME_DLL
|
||||
#define ConCommand G_ConCommand
|
||||
#define ConVar G_ConVar
|
||||
#endif
|
||||
#ifdef CLIENT_DLL
|
||||
#define ConCommand C_ConCommand
|
||||
#define ConVar C_ConVar
|
||||
#endif
|
||||
#ifdef MATERIALSYSTEM_DLL
|
||||
#define ConCommand M_ConCommand
|
||||
#define ConVar M_ConVar
|
||||
#endif
|
||||
#ifdef STUDIORENDER_DLL
|
||||
#define ConCommand S_ConCommand
|
||||
#define ConVar S_ConVar
|
||||
#endif
|
||||
#ifdef DATACACHE_DLL
|
||||
#define ConCommand D_ConCommand
|
||||
#define ConVar D_ConVar
|
||||
#endif
|
||||
#endif // _STATIC_LINKED
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Utility to quicky generate a simple console command
|
||||
//-----------------------------------------------------------------------------
|
||||
#define CON_COMMAND( name, description ) \
|
||||
static void name(); \
|
||||
static ConCommand name##_command( #name, name, description ); \
|
||||
static void name()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Utility to quicky generate a simple console command
|
||||
//-----------------------------------------------------------------------------
|
||||
#define CON_COMMAND_F( name, description, flags ) \
|
||||
static void name(); \
|
||||
static ConCommand name##_command( #name, name, description, flags ); \
|
||||
static void name()
|
||||
|
||||
|
||||
#endif // CONVAR_H
|
||||
@ -1,502 +0,0 @@
|
||||
#include "convar_smm.h"
|
||||
#include <eiface.h>
|
||||
#include <tier0/icommandline.h>
|
||||
#include <tier1/utldict.h>
|
||||
#include <sourcehook/sourcehook.h>
|
||||
#include <sh_vector.h>
|
||||
#include <sh_string.h>
|
||||
#include "provider_util.h"
|
||||
#include "provider_ep1.h"
|
||||
#include "console.h"
|
||||
|
||||
/* Types */
|
||||
typedef void (*CONPRINTF_FUNC)(const char *, ...);
|
||||
struct UsrMsgInfo
|
||||
{
|
||||
int size;
|
||||
String name;
|
||||
};
|
||||
/* Imports */
|
||||
#undef CommandLine
|
||||
DLL_IMPORT ICommandLine *CommandLine();
|
||||
/* Functions */
|
||||
CONPRINTF_FUNC ExtractRemotePrinter();
|
||||
bool CacheUserMessages();
|
||||
void ClientCommand(edict_t *pEdict);
|
||||
/* Variables */
|
||||
bool usermsgs_extracted = false;
|
||||
CVector<UsrMsgInfo> usermsgs_list;
|
||||
CONPRINTF_FUNC echo_msg_func = NULL;
|
||||
METAMOD_COMMAND client_cmd_handler = NULL;
|
||||
ICvar *icvar = NULL;
|
||||
ISourceHook *g_SHPtr = NULL;
|
||||
IVEngineServer *engine = NULL;
|
||||
IServerGameDLL *server = NULL;
|
||||
IServerGameClients *gameclients = NULL;
|
||||
unsigned int g_PLID;
|
||||
|
||||
SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *);
|
||||
|
||||
void BaseProvider::ConsolePrint(const char *str)
|
||||
{
|
||||
if (echo_msg_func != NULL)
|
||||
{
|
||||
echo_msg_func("%s", str);
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg("%s", str);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseProvider::Notify_DLLInit_Pre()
|
||||
{
|
||||
echo_msg_func = ExtractRemotePrinter();
|
||||
usermsgs_extracted = CacheUserMessages();
|
||||
|
||||
SH_ADD_HOOK_STATICFUNC(IServerGameClients, ClientCommand, gameclients, ClientCommand, false);
|
||||
}
|
||||
|
||||
bool BaseProvider::IsRemotePrintingAvailable()
|
||||
{
|
||||
return (echo_msg_func != NULL);
|
||||
}
|
||||
|
||||
void BaseProvider::ClientConsolePrint(edict_t *client, const char *message)
|
||||
{
|
||||
engine->ClientPrintf(client, message);
|
||||
}
|
||||
|
||||
void BaseProvider::ServerCommand(const char *cmd)
|
||||
{
|
||||
engine->ServerCommand(cmd);
|
||||
}
|
||||
|
||||
const char *BaseProvider::GetConVarString(ConVar *convar)
|
||||
{
|
||||
return convar->GetString();
|
||||
}
|
||||
|
||||
bool BaseProvider::IsConCommandBaseACommand(ConCommandBase *pCommand)
|
||||
{
|
||||
return pCommand->IsCommand();
|
||||
}
|
||||
|
||||
|
||||
bool BaseProvider::IsSourceEngineBuildCompatible(int build)
|
||||
{
|
||||
return (build == SOURCE_ENGINE_ORIGINAL
|
||||
|| build == SOURCE_ENGINE_EPISODEONE);
|
||||
}
|
||||
|
||||
const char *BaseProvider::GetCommandLineValue(const char *key, const char *defval)
|
||||
{
|
||||
if (key[0] == '-' || key[0] == '+')
|
||||
{
|
||||
return CommandLine()->ParmValue(key, defval);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *val;
|
||||
if ((val = icvar->GetCommandLineValue(key)) == NULL)
|
||||
{
|
||||
return defval;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
int BaseProvider::TryServerGameDLL(const char *iface)
|
||||
{
|
||||
if (strncmp(iface, "ServerGameDLL", 13) != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return atoi(&iface[13]);
|
||||
}
|
||||
|
||||
bool BaseProvider::LogMessage(const char *buffer)
|
||||
{
|
||||
if (!engine)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
engine->LogPrint(buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BaseProvider::GetHookInfo(ProvidedHooks hook, SourceHook::MemFuncInfo *pInfo)
|
||||
{
|
||||
SourceHook::MemFuncInfo mfi = {true, -1, 0, 0};
|
||||
|
||||
if (hook == ProvidedHook_LevelInit)
|
||||
{
|
||||
SourceHook::GetFuncInfo(&IServerGameDLL::LevelInit, mfi);
|
||||
}
|
||||
else if (hook == ProvidedHook_LevelShutdown)
|
||||
{
|
||||
SourceHook::GetFuncInfo(&IServerGameDLL::LevelShutdown, mfi);
|
||||
}
|
||||
else if (hook == ProvidedHook_GameInit)
|
||||
{
|
||||
SourceHook::GetFuncInfo(&IServerGameDLL::GameInit, mfi);
|
||||
}
|
||||
else if (hook == ProvidedHook_DLLShutdown)
|
||||
{
|
||||
SourceHook::GetFuncInfo(&IServerGameDLL::DLLShutdown, mfi);
|
||||
}
|
||||
else if (hook == ProvidedHook_DLLInit)
|
||||
{
|
||||
SourceHook::GetFuncInfo(&IServerGameDLL::DLLInit, mfi);
|
||||
}
|
||||
|
||||
*pInfo = mfi;
|
||||
|
||||
return (mfi.thisptroffs >= 0);
|
||||
}
|
||||
|
||||
void BaseProvider::DisplayError(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buffer[2048];
|
||||
|
||||
va_start(ap, fmt);
|
||||
UTIL_FormatArgs(buffer, sizeof(buffer), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
Error(buffer);
|
||||
}
|
||||
|
||||
void BaseProvider::DisplayWarning(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buffer[2048];
|
||||
|
||||
va_start(ap, fmt);
|
||||
UTIL_FormatArgs(buffer, sizeof(buffer), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
Warning(buffer);
|
||||
}
|
||||
|
||||
IConCommandBaseAccessor *BaseProvider::GetConCommandBaseAccessor()
|
||||
{
|
||||
return &g_SMConVarAccessor;
|
||||
}
|
||||
|
||||
bool BaseProvider::RegisterConCommandBase(ConCommandBase *pCommand)
|
||||
{
|
||||
return g_SMConVarAccessor.Register(pCommand);
|
||||
}
|
||||
|
||||
void BaseProvider::UnregisterConCommandBase(ConCommandBase *pCommand)
|
||||
{
|
||||
return g_SMConVarAccessor.Unregister(pCommand);
|
||||
}
|
||||
|
||||
int BaseProvider::GetUserMessageCount()
|
||||
{
|
||||
if (!usermsgs_extracted)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)usermsgs_list.size();
|
||||
}
|
||||
|
||||
int BaseProvider::FindUserMessage(const char *name, int *size)
|
||||
{
|
||||
for (size_t i = 0; i < usermsgs_list.size(); i++)
|
||||
{
|
||||
if (usermsgs_list[i].name.compare(name) == 0)
|
||||
{
|
||||
if (size)
|
||||
{
|
||||
*size = usermsgs_list[i].size;
|
||||
}
|
||||
return (int)i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *BaseProvider::GetUserMessage(int index, int *size)
|
||||
{
|
||||
if (!usermsgs_extracted || index < 0 || index >= (int)usermsgs_list.size())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (size)
|
||||
{
|
||||
*size = usermsgs_list[index].size;
|
||||
}
|
||||
|
||||
return usermsgs_list[index].name.c_str();
|
||||
}
|
||||
|
||||
const char *BaseProvider::GetGameDescription()
|
||||
{
|
||||
return server->GetGameDescription();
|
||||
}
|
||||
|
||||
void BaseProvider::SetClientCommandHandler(METAMOD_COMMAND callback)
|
||||
{
|
||||
client_cmd_handler = callback;
|
||||
}
|
||||
|
||||
class GlobCommand : public IMetamodSourceCommandInfo
|
||||
{
|
||||
public:
|
||||
unsigned int GetArgCount()
|
||||
{
|
||||
return engine->Cmd_Argc() - 1;
|
||||
}
|
||||
|
||||
const char *GetArg(unsigned int num)
|
||||
{
|
||||
return engine->Cmd_Argv(num);
|
||||
}
|
||||
|
||||
const char *GetArgString()
|
||||
{
|
||||
return engine->Cmd_Args();
|
||||
}
|
||||
};
|
||||
|
||||
void ClientCommand(edict_t *pEdict)
|
||||
{
|
||||
if (client_cmd_handler)
|
||||
{
|
||||
GlobCommand cmd;
|
||||
bool result;
|
||||
|
||||
if ((result = client_cmd_handler(pEdict, &cmd)) == true)
|
||||
{
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//THERE BE HAX HERE!!!! DON'T TELL ALFRED, BUT GABE WANTED IT THAT WAY. //
|
||||
// (note: you can find the offset by looking for the text //
|
||||
// "Echo text to console", you'll find the callback cmd pushed on the //
|
||||
// stack.) //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define SIGLEN 8
|
||||
#define ENGINE486_SIG "\x55\x89\xE5\x53\x83\xEC\x14\xBB"
|
||||
#define ENGINE486_OFFS 40
|
||||
#define ENGINE686_SIG "\x53\x83\xEC\x08\xBB\x01\x00\x00"
|
||||
#define ENGINE686_OFFS 50
|
||||
#define ENGINEAMD_SIG "\x53\x51\xBB\x01\x00\x00\x00\x51"
|
||||
#define ENGINEAMD_OFFS 47
|
||||
#define ENGINEW32_SIG "\xA1\x2A\x2A\x2A\x2A\x56\xBE\x01"
|
||||
#define ENGINEW32_OFFS 38
|
||||
#define IA32_CALL 0xE8
|
||||
|
||||
bool vcmp(const void *_addr1, const void *_addr2, size_t len)
|
||||
{
|
||||
unsigned char *addr1 = (unsigned char *)_addr1;
|
||||
unsigned char *addr2 = (unsigned char *)_addr2;
|
||||
|
||||
for (size_t i=0; i<len; i++)
|
||||
{
|
||||
if (addr2[i] == '*')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (addr1[i] != addr2[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//Thanks to fysh for the idea of extracting info from "echo" and for
|
||||
// having the original offsets at hand!
|
||||
CONPRINTF_FUNC ExtractRemotePrinter()
|
||||
{
|
||||
ConCommandBase *pBase = icvar->GetCommands();
|
||||
unsigned char *ptr = NULL;
|
||||
FnCommandCallback callback = NULL;
|
||||
int offs = 0;
|
||||
|
||||
while (pBase)
|
||||
{
|
||||
if (strcmp(pBase->GetName(), "echo") == 0)
|
||||
{
|
||||
callback = ((ConCommand *)pBase)->GetCallback();
|
||||
ptr = (unsigned char *)callback;
|
||||
#ifdef OS_LINUX
|
||||
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;
|
||||
}
|
||||
#elif defined OS_WIN32 // Only one Windows engine binary so far...
|
||||
if (vcmp(ptr, ENGINEW32_SIG, SIGLEN))
|
||||
{
|
||||
offs = ENGINEW32_OFFS;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!offs || ptr[offs - 1] != IA32_CALL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
//get the relative offset
|
||||
void *addr = *((void **)(ptr + offs));
|
||||
//add the base offset, to the ip (which is the address+offset + 4 bytes for next instruction)
|
||||
return (CONPRINTF_FUNC)((unsigned long)addr + (unsigned long)(ptr + offs) + 4);
|
||||
}
|
||||
pBase = const_cast<ConCommandBase *>(pBase->GetNext());
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// EVEN MORE HACKS HERE! YOU HAVE BEEN WARNED! //
|
||||
// Signatures necessary in finding the pointer to the CUtlDict that //
|
||||
// stores user message information. //
|
||||
// IServerGameDLL::GetUserMessageInfo() normally crashes with bad //
|
||||
// message indices. This is our answer to it. Yuck! <:-( //
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#ifdef OS_WIN32
|
||||
/* General Windows sig */
|
||||
#define MSGCLASS_SIGLEN 7
|
||||
#define MSGCLASS_SIG "\x8B\x0D\x2A\x2A\x2A\x2A\x56"
|
||||
#define MSGCLASS_OFFS 2
|
||||
|
||||
/* Dystopia Wimdows hack */
|
||||
#define MSGCLASS2_SIGLEN 16
|
||||
#define MSGCLASS2_SIG "\x56\x8B\x74\x24\x2A\x85\xF6\x7C\x2A\x3B\x35\x2A\x2A\x2A\x2A\x7D"
|
||||
#define MSGCLASS2_OFFS 11
|
||||
|
||||
/* Windows frame pointer sig */
|
||||
#define MSGCLASS3_SIGLEN 18
|
||||
#define MSGCLASS3_SIG "\x55\x8B\xEC\x51\x89\x2A\x2A\x8B\x2A\x2A\x50\x8B\x0D\x2A\x2A\x2A\x2A\xE8"
|
||||
#define MSGCLASS3_OFFS 13
|
||||
#elif defined OS_LINUX
|
||||
/* No frame pointer sig */
|
||||
#define MSGCLASS_SIGLEN 14
|
||||
#define MSGCLASS_SIG "\x53\x83\xEC\x2A\x8B\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x89"
|
||||
#define MSGCLASS_OFFS 9
|
||||
|
||||
/* Frame pointer sig */
|
||||
#define MSGCLASS2_SIGLEN 16
|
||||
#define MSGCLASS2_SIG "\x55\x89\xE5\x53\x83\xEC\x2A\x8B\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x89"
|
||||
#define MSGCLASS2_OFFS 11
|
||||
#endif
|
||||
|
||||
struct UserMessage
|
||||
{
|
||||
int size;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
typedef CUtlDict<UserMessage *, int> UserMsgDict;
|
||||
|
||||
/* This is the ugliest function in all of SourceMM */
|
||||
bool CacheUserMessages()
|
||||
{
|
||||
/* Get address of original GetUserMessageInfo() */
|
||||
char *vfunc = NULL;
|
||||
/* :TODO: fix this for v5 (char *)SH_GET_ORIG_VFNPTR_ENTRY(server, &IServerGameDLL::GetUserMessageInfo); */
|
||||
|
||||
/* Oh dear, we have a relative jump on our hands
|
||||
* PVK II on Windows made me do this, but I suppose it doesn't hurt to check this on Linux too...
|
||||
*/
|
||||
if (*vfunc == '\xE9')
|
||||
{
|
||||
/* Get address from displacement...
|
||||
*
|
||||
* Add 5 because it's relative to next instruction:
|
||||
* Opcode <1 byte> + 32-bit displacement <4 bytes>
|
||||
*/
|
||||
vfunc += *reinterpret_cast<int *>(vfunc + 1) + 5;
|
||||
}
|
||||
|
||||
CUtlDict<UserMessage *, int> *dict = NULL;
|
||||
|
||||
if (vcmp(vfunc, MSGCLASS_SIG, MSGCLASS_SIGLEN))
|
||||
{
|
||||
/* Get address of CUserMessages instance */
|
||||
char **userMsgClass = *reinterpret_cast<char ***>(vfunc + MSGCLASS_OFFS);
|
||||
|
||||
/* Get address of CUserMessages::m_UserMessages */
|
||||
dict = reinterpret_cast<UserMsgDict *>(*userMsgClass);
|
||||
}
|
||||
else if (vcmp(vfunc, MSGCLASS2_SIG, MSGCLASS2_SIGLEN))
|
||||
{
|
||||
#ifdef OS_WIN32
|
||||
/* If we get here, the code is possibly inlined like in Dystopia */
|
||||
|
||||
/* Get the address of the CUtlRBTree */
|
||||
char *rbtree = *reinterpret_cast<char **>(vfunc + MSGCLASS2_OFFS);
|
||||
|
||||
/* CUtlDict should be 8 bytes before the CUtlRBTree (hacktacular!) */
|
||||
dict = reinterpret_cast<UserMsgDict *>(rbtree - 8);
|
||||
#elif defined OS_LINUX
|
||||
/* Get address of CUserMessages instance */
|
||||
char **userMsgClass = *reinterpret_cast<char ***>(vfunc + MSGCLASS2_OFFS);
|
||||
|
||||
/* Get address of CUserMessages::m_UserMessages */
|
||||
dict = reinterpret_cast<UserMsgDict *>(*userMsgClass);
|
||||
#endif
|
||||
#ifdef OS_WIN32
|
||||
}
|
||||
else if (vcmp(vfunc, MSGCLASS3_SIG, MSGCLASS3_SIGLEN))
|
||||
{
|
||||
/* Get address of CUserMessages instance */
|
||||
char **userMsgClass = *reinterpret_cast<char ***>(vfunc + MSGCLASS3_OFFS);
|
||||
|
||||
/* Get address of CUserMessages::m_UserMessages */
|
||||
dict = reinterpret_cast<UserMsgDict *>(*userMsgClass);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (dict)
|
||||
{
|
||||
int msg_count = dict->Count();
|
||||
|
||||
/* Ensure that count is within bounds of an unsigned byte, because that's what engine supports */
|
||||
if (msg_count < 0 || msg_count > 255)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
UserMessage *msg;
|
||||
UsrMsgInfo u_msg;
|
||||
|
||||
/* Cache messages in our CUtlDict */
|
||||
for (int i = 0; i < msg_count; i++)
|
||||
{
|
||||
msg = dict->Element(i);
|
||||
u_msg.name = msg->name;
|
||||
u_msg.size = msg->size;
|
||||
usermsgs_list.push_back(u_msg);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1,52 +0,0 @@
|
||||
#ifndef _INCLUDE_METAMOD_SOURCE_BASE_PROVIDER_H_
|
||||
#define _INCLUDE_METAMOD_SOURCE_BASE_PROVIDER_H_
|
||||
|
||||
#include <metamod_provider.h>
|
||||
#include <ISmmAPI.h>
|
||||
#include "oslink.h"
|
||||
|
||||
using namespace SourceMM;
|
||||
using namespace SourceHook;
|
||||
|
||||
class BaseProvider : public IMetamodSourceProvider
|
||||
{
|
||||
public:
|
||||
virtual bool IsSourceEngineBuildCompatible(int build);
|
||||
virtual bool GetHookInfo(ProvidedHooks hook, SourceHook::MemFuncInfo *pInfo);
|
||||
virtual bool LogMessage(const char *buffer);
|
||||
virtual const char *GetCommandLineValue(const char *key, const char *defval);
|
||||
virtual void ConsolePrint(const char *msg);
|
||||
virtual bool IsRemotePrintingAvailable();
|
||||
virtual void ClientConsolePrint(edict_t *client, const char *msg);
|
||||
virtual IServerPluginCallbacks *GetVSPCallbacks(const char *iface);
|
||||
virtual void DisplayError(const char *fmt, ...);
|
||||
virtual void DisplayWarning(const char *fmt, ...);
|
||||
virtual int TryServerGameDLL(const char *iface);
|
||||
virtual void Notify_DLLInit_Pre();
|
||||
virtual void ServerCommand(const char *cmd);
|
||||
virtual ConVar *CreateConVar(const char *name,
|
||||
const char *defval,
|
||||
const char *help,
|
||||
int flags);
|
||||
virtual const char *GetConVarString(ConVar *convar);
|
||||
virtual void CreateCommand(const char *name,
|
||||
METAMOD_COMMAND callback,
|
||||
const char *help);
|
||||
virtual void SetClientCommandHandler(METAMOD_COMMAND callback);
|
||||
virtual const char *GetGameDescription();
|
||||
virtual IConCommandBaseAccessor *GetConCommandBaseAccessor();
|
||||
virtual bool RegisterConCommandBase(ConCommandBase *pCommand);
|
||||
virtual void UnregisterConCommandBase(ConCommandBase *pCommand);
|
||||
virtual bool IsConCommandBaseACommand(ConCommandBase *pCommand);
|
||||
virtual int GetUserMessageCount();
|
||||
virtual int FindUserMessage(const char *name, int *size=NULL);
|
||||
virtual const char *GetUserMessage(int index, int *size=NULL);
|
||||
};
|
||||
|
||||
extern IVEngineServer *engine;
|
||||
extern IServerGameDLL *server;
|
||||
extern IServerGameClients *gameclients;
|
||||
extern ICvar *icvar;
|
||||
|
||||
#endif //_INCLUDE_METAMOD_SOURCE_BASE_PROVIDER_H_
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
#include "provider_util.h"
|
||||
|
||||
size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list params)
|
||||
{
|
||||
size_t len = vsnprintf(buffer, maxlength, fmt, params);
|
||||
|
||||
if (len >= maxlength)
|
||||
{
|
||||
len = maxlength - 1;
|
||||
buffer[len] = '\0';
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
#ifndef _METAMOD_SOURCE_PROVIDER_UTIL_H_
|
||||
#define _METAMOD_SOURCE_PROVIDER_UTIL_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list params);
|
||||
|
||||
#endif //_METAMOD_SOURCE_PROVIDER_UTIL_H_
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,14 @@
|
||||
// 3 - Added "hook loop status variable"
|
||||
// 4 - Reentrant
|
||||
#define SH_IFACE_VERSION 4
|
||||
#define SH_IMPL_VERSION 3
|
||||
|
||||
// Impl versions:
|
||||
// ???
|
||||
// 4 - addition of hook ids and vp hooks (with them, AddHookNew and RemoveHookNew)
|
||||
// This is not a SH_IFACE_VERSION change so that old plugins continue working!
|
||||
// 5 - addition of direct vp hooks (new hook mode; from now on AddHookNew checks for
|
||||
// invalid hookmode -> impl version won't have to change because of things like this)
|
||||
#define SH_IMPL_VERSION 5
|
||||
|
||||
// Hookman version:
|
||||
// 1 - Support for recalls, performance optimisations
|
||||
@ -291,15 +298,12 @@ namespace SourceHook
|
||||
}
|
||||
};
|
||||
|
||||
template<class B> struct CallClass
|
||||
template<class B> struct DeprecatedCallClass
|
||||
{
|
||||
virtual B *GetThisPtr() = 0;
|
||||
virtual void *GetOrigFunc(int vtbloffs, int vtblidx) = 0;
|
||||
};
|
||||
|
||||
typedef CallClass<void> GenericCallClass;
|
||||
typedef CallClass<EmptyClass> ManualCallClass;
|
||||
|
||||
// 09.08.2008 (6 AM, I just woke up, the others are still sleeping so i finally can use this notebook !!)
|
||||
// - Today is an important day.
|
||||
// I'm adding support for functions which return references.
|
||||
@ -401,14 +405,14 @@ namespace SourceHook
|
||||
* @param iface The interface pointer
|
||||
* @param size Size of the class instance
|
||||
*/
|
||||
virtual GenericCallClass *GetCallClass(void *iface, size_t size) = 0;
|
||||
virtual DeprecatedCallClass<void> *GetCallClass(void *iface, size_t size) = 0;
|
||||
|
||||
/**
|
||||
* @brief Release a callclass
|
||||
*
|
||||
* @param ptr Pointer to the callclass
|
||||
*/
|
||||
virtual void ReleaseCallClass(GenericCallClass *ptr) = 0;
|
||||
virtual void ReleaseCallClass(DeprecatedCallClass<void> *ptr) = 0;
|
||||
|
||||
virtual void SetRes(META_RES res) = 0; //!< Sets the meta result
|
||||
virtual META_RES GetPrevRes() = 0; //!< Gets the meta result of the
|
||||
@ -479,7 +483,65 @@ namespace SourceHook
|
||||
virtual void *SetupHookLoop(META_RES *statusPtr, META_RES *prevResPtr, META_RES *curResPtr,
|
||||
void **ifacePtrPtr, const void *origRetPtr, void *overrideRetPtr) = 0;
|
||||
|
||||
//!<
|
||||
/**
|
||||
* @brief Modes for the new AddHook
|
||||
*/
|
||||
enum AddHookMode
|
||||
{
|
||||
Hook_Normal,
|
||||
Hook_VP,
|
||||
Hook_DVP
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Add a (VP) hook.
|
||||
*
|
||||
* @return non-zero hook id on success, 0 otherwise
|
||||
*
|
||||
* @param plug The unique identifier of the plugin that calls this function
|
||||
* @param mode Can be either Hook_Normal or Hook_VP (vtable-wide hook)
|
||||
* @param iface The interface pointer
|
||||
* @param ifacesize The size of the class iface points to
|
||||
* @param myHookMan A hook manager function that should be capable of handling the function
|
||||
* @param handler A pointer to a FastDelegate containing the hook handler
|
||||
* @param post Set to true if you want a post handler
|
||||
*/
|
||||
virtual int AddHookNew(Plugin plug, AddHookMode mode, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan,
|
||||
ISHDelegate *handler, bool post) = 0;
|
||||
|
||||
/**
|
||||
* @brief Remove a VP hook by ID.
|
||||
*
|
||||
* @return true on success, false otherwise
|
||||
*
|
||||
* @param plug The unique identifier of the plugin that calls this function
|
||||
* @param hookid The hook id (returned by AddHookNew)
|
||||
*/
|
||||
virtual bool RemoveHookByID(Plugin plug, int hookid) = 0;
|
||||
|
||||
/**
|
||||
* @brief Makes sure that hooks are going to be ignored on the next call of vfnptr
|
||||
*
|
||||
* @param plug The unique identifier of the plugin that calls this function
|
||||
* @param vfnptr The virtual function pointer of the function in question
|
||||
*/
|
||||
virtual void SetIgnoreHooks(Plugin plug, void *vfnptr) = 0;
|
||||
|
||||
/**
|
||||
* @brief Reverses SetIgnoreHooks' effect
|
||||
*
|
||||
* @param plug The unique identifier of the plugin that calls this function
|
||||
* @param vfnptr The virtual function pointer of the function in question
|
||||
*/
|
||||
virtual void ResetIgnoreHooks(Plugin plug, void *vfnptr) = 0;
|
||||
|
||||
/**
|
||||
* @brief Finds the original entry of a virtual function pointer
|
||||
*
|
||||
* @param vfnptr The virtual function pointer
|
||||
* @return The original entry if the virtual function pointer has been patched; NULL otherwise.
|
||||
*/
|
||||
virtual void *GetOrigVfnPtrEntry(void *vfnptr) = 0;
|
||||
};
|
||||
|
||||
// For META_RESULT_ORIG_RET and META_RESULT_OVERRIDE_RET:
|
||||
@ -510,6 +572,50 @@ namespace SourceHook
|
||||
return &ref;
|
||||
}
|
||||
};
|
||||
|
||||
// For source-level compatibility
|
||||
template <class T> struct CallClass
|
||||
{
|
||||
T *ptr;
|
||||
|
||||
CallClass(T *p) : ptr(p)
|
||||
{
|
||||
}
|
||||
|
||||
operator T*()
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
};
|
||||
|
||||
typedef CallClass<void> GenericCallClass;
|
||||
typedef CallClass<EmptyClass> ManualCallClass;
|
||||
|
||||
template <class T>
|
||||
CallClass<T> *GetCallClass(T *p)
|
||||
{
|
||||
return new CallClass<T>(p);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void ReleaseCallClass(CallClass<T> *p)
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
|
||||
template <class X, class MFP>
|
||||
void *GetOrigVfnPtrEntry(X *pInstance, MFP mfp, ISourceHook *pSH)
|
||||
{
|
||||
SourceHook::MemFuncInfo info = {true, -1, 0, 0};
|
||||
SourceHook::GetFuncInfo(pInstance, mfp, info);
|
||||
|
||||
void *vfnptr = reinterpret_cast<void*>(
|
||||
*reinterpret_cast<void***>(reinterpret_cast<char*>(pInstance) + info.thisptroffs + info.vtbloffs) + info.vtblindex);
|
||||
|
||||
void *origentry = pSH->GetOrigVfnPtrEntry(vfnptr);
|
||||
|
||||
return origentry ? origentry : *reinterpret_cast<void**>(vfnptr);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
@ -614,31 +720,6 @@ namespace SourceHook
|
||||
RETURN_META_VALUE(MRES_SUPERCEDE, (thisptr->*(u.mfp)) newparams); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief Get/generate callclass for an interface pointer
|
||||
*
|
||||
* @param ifaceptr The interface pointer
|
||||
*/
|
||||
template<class ifacetype>
|
||||
inline SourceHook::CallClass<ifacetype> *SH_GET_CALLCLASS_R(SourceHook::ISourceHook *shptr, ifacetype *ptr)
|
||||
{
|
||||
return reinterpret_cast<SourceHook::CallClass<ifacetype>*>(
|
||||
shptr->GetCallClass(reinterpret_cast<void*>(ptr), sizeof(ifacetype)));
|
||||
}
|
||||
|
||||
template<class ifacetype>
|
||||
inline SourceHook::CallClass<ifacetype> *SH_GET_MCALLCLASS_R(SourceHook::ISourceHook *shptr, ifacetype *ptr, int ifacesize)
|
||||
{
|
||||
return reinterpret_cast<SourceHook::CallClass<ifacetype>*>(
|
||||
shptr->GetCallClass(reinterpret_cast<void*>(ptr), ifacesize));
|
||||
}
|
||||
|
||||
template<class ifacetype>
|
||||
inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::CallClass<ifacetype> *ptr)
|
||||
{
|
||||
shptr->ReleaseCallClass(reinterpret_cast<SourceHook::GenericCallClass*>(ptr));
|
||||
}
|
||||
|
||||
#define SH_MANUALHOOK_RECONFIGURE(hookname, pvtblindex, pvtbloffs, pthisptroffs) \
|
||||
do { \
|
||||
SH_GLOB_SHPTR->RemoveHookManager(SH_GLOB_PLUGPTR, SH_MFHCls(hookname)::HookManPubFunc); \
|
||||
@ -647,41 +728,83 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
SH_MFHCls(hookname)::ms_MFI.vtbloffs = pvtbloffs; \
|
||||
} while (0)
|
||||
|
||||
#define SH_GET_CALLCLASS(ptr) SH_GET_CALLCLASS_R(SH_GLOB_SHPTR, ptr)
|
||||
#define SH_GET_MCALLCLASS(ptr, size) SH_GET_MCALLCLASS_R(SH_GLOB_SHPTR, reinterpret_cast<SourceHook::EmptyClass*>(ptr), size)
|
||||
#define SH_RELEASE_CALLCLASS(ptr) SH_RELEASE_CALLCLASS_R(SH_GLOB_SHPTR, ptr)
|
||||
|
||||
#define SH_GET_ORIG_VFNPTR_ENTRY(inst, mfp) (SourceHook::GetOrigVfnPtrEntry(inst, mfp, SH_GLOB_SHPTR))
|
||||
|
||||
// For source-level compatibility
|
||||
|
||||
#define SH_GET_CALLCLASS(ptr) SourceHook::GetCallClass(ptr)
|
||||
#define SH_GET_MCALLCLASS(ptr, size) SourceHook::GetCallClass(reinterpret_cast<SourceHook::EmptyClass*>(ptr))
|
||||
#define SH_RELEASE_CALLCLASS(ptr) SourceHook::ReleaseCallClass(ptr)
|
||||
|
||||
// New ADD / REMOVE macros.
|
||||
#define SH_STATIC(func) fastdelegate::MakeDelegate(func)
|
||||
#define SH_MEMBER(inst, func) fastdelegate::MakeDelegate(inst, func)
|
||||
|
||||
#define SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \
|
||||
__SourceHook_FHAdd##ifacetype##ifacefunc((void*)SourceHook::implicit_cast<ifacetype*>(ifaceptr), \
|
||||
post, handler)
|
||||
#define SH_ADD_HOOK_STATICFUNC(ifacetype, ifacefunc, ifaceptr, handler, post) \
|
||||
SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, fastdelegate::MakeDelegate(handler), post)
|
||||
#define SH_ADD_HOOK_MEMFUNC(ifacetype, ifacefunc, ifaceptr, handler_inst, handler_func, post) \
|
||||
SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, fastdelegate::MakeDelegate(handler_inst, handler_func), post)
|
||||
|
||||
#define SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \
|
||||
__SourceHook_FHRemove##ifacetype##ifacefunc((void*)SourceHook::implicit_cast<ifacetype*>(ifaceptr), \
|
||||
post, handler)
|
||||
#define SH_REMOVE_HOOK_STATICFUNC(ifacetype, ifacefunc, ifaceptr, handler, post) \
|
||||
SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, fastdelegate::MakeDelegate(handler), post)
|
||||
#define SH_REMOVE_HOOK_MEMFUNC(ifacetype, ifacefunc, ifaceptr, handler_inst, handler_func, post) \
|
||||
SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, fastdelegate::MakeDelegate(handler_inst, handler_func), post)
|
||||
|
||||
post, handler)
|
||||
|
||||
#define SH_ADD_MANUALHOOK(hookname, ifaceptr, handler, post) \
|
||||
__SourceHook_FHMAdd##hookname(reinterpret_cast<void*>(ifaceptr), post, handler)
|
||||
#define SH_ADD_MANUALHOOK_STATICFUNC(hookname, ifaceptr, handler, post) \
|
||||
SH_ADD_MANUALHOOK(hookname, ifaceptr, fastdelegate::MakeDelegate(handler), post)
|
||||
#define SH_ADD_MANUALHOOK_MEMFUNC(hookname, ifaceptr, handler_inst, handler_func, post) \
|
||||
SH_ADD_MANUALHOOK(hookname, ifaceptr, fastdelegate::MakeDelegate(handler_inst, handler_func), post)
|
||||
|
||||
#define SH_REMOVE_MANUALHOOK(hookname, ifaceptr, handler, post) \
|
||||
__SourceHook_FHMRemove##hookname(reinterpret_cast<void*>(ifaceptr), post, handler)
|
||||
#define SH_REMOVE_MANUALHOOK_STATICFUNC(hookname, ifaceptr, handler, post) \
|
||||
SH_REMOVE_MANUALHOOK(hookname, ifaceptr, fastdelegate::MakeDelegate(handler), post)
|
||||
#define SH_REMOVE_MANUALHOOK_MEMFUNC(hookname, ifaceptr, handler_inst, handler_func, post) \
|
||||
SH_REMOVE_MANUALHOOK(hookname, ifaceptr, fastdelegate::MakeDelegate(handler_inst, handler_func), post)
|
||||
__SourceHook_FHMRemove##hookname(reinterpret_cast<void*>(ifaceptr), post, handler)
|
||||
|
||||
#define SH_ADD_VPHOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \
|
||||
__SourceHook_FHVPAdd##ifacetype##ifacefunc((void*)SourceHook::implicit_cast<ifacetype*>(ifaceptr), \
|
||||
post, handler, false)
|
||||
|
||||
#define SH_ADD_DVPHOOK(ifacetype, ifacefunc, vtableptr, handler, post) \
|
||||
__SourceHook_FHVPAdd##ifacetype##ifacefunc(reinterpret_cast<void*>(vtableptr), \
|
||||
post, handler, true)
|
||||
|
||||
#define SH_ADD_MANUALVPHOOK(hookname, ifaceptr, handler, post) \
|
||||
__SourceHook_FHMVPAdd##hookname(reinterpret_cast<void*>(ifaceptr), post, handler, false)
|
||||
|
||||
#define SH_ADD_MANUALDVPHOOK(hookname, vtableptr, handler, post) \
|
||||
__SourceHook_FHMVPAdd##hookname(reinterpret_cast<void*>(vtableptr), post, handler, true)
|
||||
|
||||
#define SH_REMOVE_HOOK_ID(hookid) \
|
||||
(SH_GLOB_SHPTR->RemoveHookByID(SH_GLOB_PLUGPTR, hookid))
|
||||
|
||||
// Old macros
|
||||
// !! These are now deprecated. Instead, use one of these:
|
||||
// SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post)
|
||||
// SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(inst, func), post)
|
||||
|
||||
#define SH_ADD_HOOK_STATICFUNC(ifacetype, ifacefunc, ifaceptr, handler, post) \
|
||||
SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post)
|
||||
#define SH_ADD_HOOK_MEMFUNC(ifacetype, ifacefunc, ifaceptr, handler_inst, handler_func, post) \
|
||||
SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(handler_inst, handler_func), post)
|
||||
|
||||
// SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post)
|
||||
// SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(inst, func), post)
|
||||
|
||||
#define SH_REMOVE_HOOK_STATICFUNC(ifacetype, ifacefunc, ifaceptr, handler, post) \
|
||||
SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post)
|
||||
#define SH_REMOVE_HOOK_MEMFUNC(ifacetype, ifacefunc, ifaceptr, handler_inst, handler_func, post) \
|
||||
SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(handler_inst, handler_func), post)
|
||||
|
||||
// SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post)
|
||||
// SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(inst, func), post)
|
||||
|
||||
#define SH_ADD_MANUALHOOK_STATICFUNC(hookname, ifaceptr, handler, post) \
|
||||
SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post)
|
||||
#define SH_ADD_MANUALHOOK_MEMFUNC(hookname, ifaceptr, handler_inst, handler_func, post) \
|
||||
SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(handler_inst, handler_func), post)
|
||||
|
||||
// SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post)
|
||||
// SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(inst, func), post)
|
||||
|
||||
#define SH_REMOVE_MANUALHOOK_STATICFUNC(hookname, ifaceptr, handler, post) \
|
||||
SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post)
|
||||
#define SH_REMOVE_MANUALHOOK_MEMFUNC(hookname, ifaceptr, handler_inst, handler_func, post) \
|
||||
SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(handler_inst, handler_func), post)
|
||||
|
||||
#define SH_NOATTRIB
|
||||
|
||||
@ -716,6 +839,8 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
/* Verify interface version */ \
|
||||
if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \
|
||||
return 1; \
|
||||
if (SH_GLOB_SHPTR->GetImplVersion() < SH_IMPL_VERSION) \
|
||||
return 1; \
|
||||
\
|
||||
if (action == HA_GetInfo) \
|
||||
{ \
|
||||
@ -760,7 +885,7 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
SH_FHCls(ifacetype,ifacefunc,overload) SH_FHCls(ifacetype,ifacefunc,overload)::ms_Inst; \
|
||||
::SourceHook::MemFuncInfo SH_FHCls(ifacetype,ifacefunc,overload)::ms_MFI; \
|
||||
::SourceHook::IHookManagerInfo *SH_FHCls(ifacetype,ifacefunc,overload)::ms_HI; \
|
||||
bool __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, bool post, \
|
||||
int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, bool post, \
|
||||
SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \
|
||||
{ \
|
||||
using namespace ::SourceHook; \
|
||||
@ -769,10 +894,24 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
if (mfi.thisptroffs < 0 || !mfi.isVirtual) \
|
||||
return false; /* No non-virtual functions / virtual inheritance supported */ \
|
||||
\
|
||||
return SH_GLOB_SHPTR->AddHook(SH_GLOB_PLUGPTR, iface, mfi.thisptroffs, \
|
||||
return SH_GLOB_SHPTR->AddHookNew(SH_GLOB_PLUGPTR, ::SourceHook::ISourceHook::Hook_Normal, iface, mfi.thisptroffs, \
|
||||
SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, \
|
||||
new CSHDelegate<SH_FHCls(ifacetype,ifacefunc,overload)::FD>(handler), post); \
|
||||
} \
|
||||
int __SourceHook_FHVPAdd##ifacetype##ifacefunc(void *iface, bool post, \
|
||||
SH_FHCls(ifacetype,ifacefunc,overload)::FD handler, bool direct) \
|
||||
{ \
|
||||
using namespace ::SourceHook; \
|
||||
MemFuncInfo mfi = {true, -1, 0, 0}; \
|
||||
GetFuncInfo(funcptr, mfi); \
|
||||
if (mfi.thisptroffs < 0 || !mfi.isVirtual) \
|
||||
return false; /* No non-virtual functions / virtual inheritance supported */ \
|
||||
\
|
||||
return SH_GLOB_SHPTR->AddHookNew(SH_GLOB_PLUGPTR, \
|
||||
direct ? ::SourceHook::ISourceHook::Hook_DVP : ::SourceHook::ISourceHook::Hook_VP, \
|
||||
iface, mfi.thisptroffs, SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, \
|
||||
new CSHDelegate<SH_FHCls(ifacetype,ifacefunc,overload)::FD>(handler), post); \
|
||||
} \
|
||||
bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \
|
||||
SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \
|
||||
{ \
|
||||
@ -811,6 +950,8 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
/* Verify interface version */ \
|
||||
if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \
|
||||
return 1; \
|
||||
if (SH_GLOB_SHPTR->GetImplVersion() < SH_IMPL_VERSION) \
|
||||
return 1; \
|
||||
\
|
||||
if (action == HA_GetInfo) \
|
||||
{ \
|
||||
@ -843,13 +984,21 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
SH_MFHCls(hookname) SH_MFHCls(hookname)::ms_Inst; \
|
||||
::SourceHook::MemFuncInfo SH_MFHCls(hookname)::ms_MFI; \
|
||||
::SourceHook::IHookManagerInfo *SH_MFHCls(hookname)::ms_HI; \
|
||||
bool __SourceHook_FHMAdd##hookname(void *iface, bool post, \
|
||||
int __SourceHook_FHMAdd##hookname(void *iface, bool post, \
|
||||
SH_MFHCls(hookname)::FD handler) \
|
||||
{ \
|
||||
return SH_GLOB_SHPTR->AddHook(SH_GLOB_PLUGPTR, iface, pthisptroffs, \
|
||||
return SH_GLOB_SHPTR->AddHookNew(SH_GLOB_PLUGPTR, ::SourceHook::ISourceHook::Hook_Normal, iface, pthisptroffs, \
|
||||
SH_MFHCls(hookname)::HookManPubFunc, \
|
||||
new ::SourceHook::CSHDelegate<SH_MFHCls(hookname)::FD>(handler), post); \
|
||||
} \
|
||||
int __SourceHook_FHMVPAdd##hookname(void *iface, bool post, \
|
||||
SH_MFHCls(hookname)::FD handler, bool direct) \
|
||||
{ \
|
||||
return SH_GLOB_SHPTR->AddHookNew(SH_GLOB_PLUGPTR, \
|
||||
direct ? ::SourceHook::ISourceHook::Hook_DVP : ::SourceHook::ISourceHook::Hook_VP, \
|
||||
iface, pthisptroffs, SH_MFHCls(hookname)::HookManPubFunc, \
|
||||
new ::SourceHook::CSHDelegate<SH_MFHCls(hookname)::FD>(handler), post); \
|
||||
} \
|
||||
bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \
|
||||
SH_MFHCls(hookname)::FD handler) \
|
||||
{ \
|
||||
@ -1127,136 +1276,109 @@ inline void SH_RELEASE_CALLCLASS_R(SourceHook::ISourceHook *shptr, SourceHook::C
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SH_CALL
|
||||
|
||||
#if SH_COMP == SH_COMP_MSVC
|
||||
|
||||
# define SH_MAKE_EXECUTABLECLASS_OB(call, prms) \
|
||||
#define SH_MAKE_EXECUTABLECLASS_OB(call, prms) \
|
||||
{ \
|
||||
using namespace ::SourceHook; \
|
||||
MemFuncInfo mfi = {true, -1, 0, 0}; \
|
||||
GetFuncInfo(m_CC->GetThisPtr(), m_MFP, mfi); \
|
||||
void *origfunc = m_CC->GetOrigFunc(mfi.thisptroffs + mfi.vtbloffs, mfi.vtblindex); \
|
||||
if (!origfunc) \
|
||||
return (m_CC->GetThisPtr()->*m_MFP)call; \
|
||||
\
|
||||
/* It's hooked. Call the original function. */ \
|
||||
union \
|
||||
{ \
|
||||
RetType(EmptyClass::*mfpnew)prms; \
|
||||
void *addr; \
|
||||
} u; \
|
||||
u.addr = origfunc; \
|
||||
\
|
||||
void *adjustedthisptr = reinterpret_cast<void*>(reinterpret_cast<char*>(m_CC->GetThisPtr()) + mfi.thisptroffs); \
|
||||
return (reinterpret_cast<EmptyClass*>(adjustedthisptr)->*u.mfpnew)call; \
|
||||
m_pSH->SetIgnoreHooks(m_Plug, m_VfnPtr); \
|
||||
RetType tmpret = (m_ThisPtr->*m_MFP)call; \
|
||||
m_pSH->ResetIgnoreHooks(m_Plug, m_VfnPtr); \
|
||||
return tmpret; \
|
||||
}
|
||||
|
||||
# define SH_MAKE_MEXECUTABLECLASS_OB(call, prms) \
|
||||
#define SH_MAKE_EXECUTABLECLASS_OB_void(call, prms) \
|
||||
{ \
|
||||
using namespace ::SourceHook; \
|
||||
char *adjustedthisptr = reinterpret_cast<char*>(m_CC->GetThisPtr()) + m_ThisPtrOffs; \
|
||||
union \
|
||||
{ \
|
||||
RetType(EmptyClass::*mfpnew)prms; \
|
||||
void *addr; \
|
||||
} u; \
|
||||
u.addr = m_CC->GetOrigFunc(m_ThisPtrOffs + m_VtblOffs, m_VtblIdx); \
|
||||
if (!u.addr) \
|
||||
u.addr = (*reinterpret_cast<void***>(adjustedthisptr + m_VtblOffs))[m_VtblIdx]; \
|
||||
\
|
||||
return (reinterpret_cast<EmptyClass*>(adjustedthisptr)->*u.mfpnew)call; \
|
||||
m_pSH->SetIgnoreHooks(m_Plug, m_VfnPtr); \
|
||||
(m_ThisPtr->*m_MFP)call; \
|
||||
m_pSH->ResetIgnoreHooks(m_Plug, m_VfnPtr); \
|
||||
}
|
||||
|
||||
#elif SH_COMP == SH_COMP_GCC
|
||||
|
||||
# define SH_MAKE_EXECUTABLECLASS_OB(call, prms) \
|
||||
{ \
|
||||
using namespace ::SourceHook; \
|
||||
MemFuncInfo mfi = {true, -1, 0, 0}; \
|
||||
GetFuncInfo(m_CC->GetThisPtr(), m_MFP, mfi); \
|
||||
void *origfunc = m_CC->GetOrigFunc(mfi.thisptroffs + mfi.vtbloffs, mfi.vtblindex); \
|
||||
if (!origfunc) \
|
||||
return (m_CC->GetThisPtr()->*m_MFP)call; \
|
||||
\
|
||||
/* It's hooked. Call the original function. */ \
|
||||
union \
|
||||
{ \
|
||||
RetType(EmptyClass::*mfpnew)prms; \
|
||||
struct \
|
||||
{ \
|
||||
void *addr; \
|
||||
intptr_t adjustor; \
|
||||
} s; \
|
||||
} u; \
|
||||
u.s.addr = origfunc; \
|
||||
u.s.adjustor = mfi.thisptroffs; \
|
||||
\
|
||||
return (reinterpret_cast<EmptyClass*>(m_CC->GetThisPtr())->*u.mfpnew)call; \
|
||||
}
|
||||
|
||||
# define SH_MAKE_MEXECUTABLECLASS_OB(call, prms) \
|
||||
{ \
|
||||
using namespace ::SourceHook; \
|
||||
char *thisptr = reinterpret_cast<char*>(m_CC->GetThisPtr()); \
|
||||
union \
|
||||
{ \
|
||||
RetType(EmptyClass::*mfpnew)prms; \
|
||||
struct { \
|
||||
void *addr; \
|
||||
intptr_t adjustor; \
|
||||
} s; \
|
||||
} u; \
|
||||
u.s.addr = m_CC->GetOrigFunc(m_ThisPtrOffs + m_VtblOffs, m_VtblIdx); \
|
||||
if (!u.s.addr) \
|
||||
u.s.addr = (*reinterpret_cast<void***>(thisptr + m_ThisPtrOffs + m_VtblOffs))[m_VtblIdx]; \
|
||||
\
|
||||
u.s.adjustor = m_ThisPtrOffs; \
|
||||
return (reinterpret_cast<EmptyClass*>(thisptr)->*u.mfpnew)call; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace SourceHook
|
||||
{
|
||||
@[$1,0,$a:
|
||||
// Support for $1 arguments
|
||||
template<class CCType, class MFPType, class RetType@[$2,1,$1:, class Param$2@]> class ExecutableClass$1
|
||||
// Call Class Wrapper!
|
||||
template <class T> struct CCW
|
||||
{
|
||||
CCType *m_CC;
|
||||
MFPType m_MFP;
|
||||
public:
|
||||
ExecutableClass$1(CCType *cc, MFPType mfp) : m_CC(cc), m_MFP(mfp) { }
|
||||
|
||||
RetType operator()(@[$2,1,$1|, :Param$2 p$2@]) const
|
||||
SH_MAKE_EXECUTABLECLASS_OB((@[$2,1,$1|, :p$2@]), (@[$2,1,$1|, :Param$2@]))
|
||||
|
||||
@[$2,$1+1,$a:
|
||||
template <@[$3,$1+1,$2|, :class Param$3@]> RetType operator()(@[$3,1,$2|, :Param$3 p$3@]) const
|
||||
SH_MAKE_EXECUTABLECLASS_OB((@[$3,1,$2|, :p$3@]), (@[$3,1,$2|, :Param$3@]))
|
||||
@]
|
||||
typedef T type;
|
||||
|
||||
// Get Real Pointer!
|
||||
static inline T *GRP(T *p)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
template <class RetType@[$2,1,$1:, class Param$2@]> class MExecutableClass$1
|
||||
template <class T> struct CCW< CallClass<T> >
|
||||
{
|
||||
ManualCallClass *m_CC;
|
||||
int m_ThisPtrOffs;
|
||||
int m_VtblIdx;
|
||||
int m_VtblOffs;
|
||||
typedef T type;
|
||||
|
||||
// Get Real Pointer!
|
||||
static inline T *GRP(CallClass<T> *p)
|
||||
{
|
||||
return p->ptr;
|
||||
}
|
||||
};
|
||||
|
||||
@[$1,0,$a:
|
||||
// Support for $1 arguments
|
||||
template<class ObjType, class MFP, class RetType@[$2,1,$1:, class Param$2@]> class ExecutableClass$1
|
||||
{
|
||||
ObjType *m_ThisPtr;
|
||||
void *m_VfnPtr;
|
||||
MFP m_MFP;
|
||||
ISourceHook *m_pSH;
|
||||
Plugin m_Plug;
|
||||
public:
|
||||
MExecutableClass$1(ManualCallClass *cc, int vtbloffs, int vtblidx, int thisptroffs) : m_CC(cc),
|
||||
m_ThisPtrOffs(thisptroffs), m_VtblIdx(vtblidx), m_VtblOffs(vtbloffs) { }
|
||||
|
||||
ExecutableClass$1(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp),
|
||||
m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { }
|
||||
|
||||
RetType operator()(@[$2,1,$1|, :Param$2 p$2@]) const
|
||||
SH_MAKE_MEXECUTABLECLASS_OB((@[$2,1,$1|, :p$2@]), (@[$2,1,$1|, :Param$2@]))
|
||||
|
||||
SH_MAKE_EXECUTABLECLASS_OB((@[$2,1,$1|, :p$2@]), (@[$2,1,$1|, :Param$2@]))
|
||||
|
||||
@[$2,$1+1,$a:
|
||||
template <@[$3,$1+1,$2|, :class Param$3@]> RetType operator()(@[$3,1,$2|, :Param$3 p$3@]) const
|
||||
SH_MAKE_MEXECUTABLECLASS_OB((@[$3,1,$2|, :p$3@]), (@[$3,1,$2|, :Param$3@]))
|
||||
SH_MAKE_EXECUTABLECLASS_OB((@[$3,1,$2|, :p$3@]), (@[$3,1,$2|, :Param$3@]))
|
||||
@]
|
||||
};
|
||||
|
||||
template<class ObjType, class MFP@[$2,1,$1:, class Param$2@]> class ExecutableClass$1<ObjType, MFP, void@[$2,1,$1:, Param$2@]>
|
||||
{
|
||||
ObjType *m_ThisPtr;
|
||||
void *m_VfnPtr;
|
||||
MFP m_MFP;
|
||||
ISourceHook *m_pSH;
|
||||
Plugin m_Plug;
|
||||
public:
|
||||
ExecutableClass$1(ObjType *tp, MFP mfp, void *vp, ISourceHook *pSH, Plugin plug) : m_ThisPtr(tp),
|
||||
m_VfnPtr(vp), m_MFP(mfp), m_pSH(pSH), m_Plug(plug) { }
|
||||
|
||||
void operator()(@[$2,1,$1|, :Param$2 p$2@]) const
|
||||
SH_MAKE_EXECUTABLECLASS_OB_void((@[$2,1,$1|, :p$2@]), (@[$2,1,$1|, :Param$2@]))
|
||||
|
||||
@[$2,$1+1,$a:
|
||||
template <@[$3,$1+1,$2|, :class Param$3@]> void operator()(@[$3,1,$2|, :Param$3 p$3@]) const
|
||||
SH_MAKE_EXECUTABLECLASS_OB_void((@[$3,1,$2|, :p$3@]), (@[$3,1,$2|, :Param$3@]))
|
||||
@]
|
||||
};
|
||||
@]
|
||||
|
||||
}
|
||||
|
||||
#define SH__CALL_GET_VFNPTR_NORMAL \
|
||||
using namespace ::SourceHook; \
|
||||
MemFuncInfo mfi = {true, -1, 0, 0}; \
|
||||
GetFuncInfo(CCW<Y>::GRP(ptr), mfp, mfi); \
|
||||
void *vfnptr = reinterpret_cast<void*>( \
|
||||
*reinterpret_cast<void***>(reinterpret_cast<char*>(ptr) + mfi.thisptroffs + mfi.vtbloffs) + mfi.vtblindex);
|
||||
|
||||
#define SH__CALL_GET_VFNPTR_MANUAL \
|
||||
using namespace ::SourceHook; \
|
||||
void *vfnptr = reinterpret_cast<void*>( \
|
||||
*reinterpret_cast<void***>( (reinterpret_cast<char*>(CCW<Y>::GRP(ptr)) + thisptroffs + vtbloffs) ) + vtblidx); \
|
||||
/* patch mfp */ \
|
||||
*reinterpret_cast<void**>(&mfp) = *reinterpret_cast<void**>(vfnptr);
|
||||
|
||||
// SH_CALL needs to deduce the return type -> it uses templates and function overloading
|
||||
// That's why SH_CALL takes two parameters: "mfp2" of type RetType(X::*mfp)(params), and "mfp" of type MFP
|
||||
// The only purpose of the mfp2 parameter is to extract the return type
|
||||
@ -1264,24 +1386,30 @@ namespace SourceHook
|
||||
@[$1,0,$a:
|
||||
// Support for $1 arguments
|
||||
template <class X, class Y, class MFP, class RetType@[$2,1,$1:, class Param$2@]>
|
||||
SourceHook::ExecutableClass$1<SourceHook::CallClass<Y>, MFP, RetType@[$2,1,$1:, Param$2@]>
|
||||
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@]))
|
||||
SourceHook::ExecutableClass$1<typename SourceHook::CCW<Y>::type, MFP, RetType@[$2,1,$1:, Param$2@]>
|
||||
SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@]), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug)
|
||||
{
|
||||
return SourceHook::ExecutableClass$1<SourceHook::CallClass<Y>, MFP, RetType@[$2,1,$1:, Param$2@]>(ptr, mfp);
|
||||
SH__CALL_GET_VFNPTR_NORMAL
|
||||
return SourceHook::ExecutableClass$1<typename CCW<Y>::type, MFP, RetType@[$2,1,$1:, Param$2@]>(CCW<Y>::GRP(ptr),
|
||||
mfp, vfnptr, shptr, plug);
|
||||
}
|
||||
|
||||
template <class X, class Y, class MFP, class RetType@[$2,1,$1:, class Param$2@]>
|
||||
SourceHook::ExecutableClass$1<SourceHook::CallClass<Y>, MFP, RetType@[$2,1,$1:, Param$2@]>
|
||||
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@])const)
|
||||
SourceHook::ExecutableClass$1<typename SourceHook::CCW<Y>::type, MFP, RetType@[$2,1,$1:, Param$2@]>
|
||||
SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@])const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug)
|
||||
{
|
||||
return SourceHook::ExecutableClass$1<SourceHook::CallClass<Y>, MFP, RetType@[$2,1,$1:, Param$2@]>(ptr, mfp);
|
||||
SH__CALL_GET_VFNPTR_NORMAL
|
||||
return SourceHook::ExecutableClass$1<typename CCW<Y>::type, MFP, RetType@[$2,1,$1:, Param$2@]>(CCW<Y>::GRP(ptr),
|
||||
mfp, vfnptr, shptr, plug);
|
||||
}
|
||||
|
||||
template <class X, class RetType@[$2,1,$1:, class Param$2@]>
|
||||
SourceHook::MExecutableClass$1<RetType@[$2,1,$1:, Param$2@]>
|
||||
SH_MCALL2(SourceHook::ManualCallClass *ptr, RetType(X::*mfp)(@[$2,1,$1|, :Param$2@]), int vtblidx, int vtbloffs, int thisptroffs)
|
||||
template <class X, class Y, class MFP, class RetType@[$2,1,$1:, class Param$2@]>
|
||||
SourceHook::ExecutableClass$1<SourceHook::EmptyClass, MFP, RetType@[$2,1,$1:, Param$2@]>
|
||||
SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@]), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug)
|
||||
{
|
||||
return SourceHook::MExecutableClass$1<RetType@[$2,1,$1:, Param$2@]>(ptr, vtbloffs, vtblidx, thisptroffs);
|
||||
SH__CALL_GET_VFNPTR_MANUAL
|
||||
return SourceHook::ExecutableClass$1<EmptyClass, MFP, RetType@[$2,1,$1:, Param$2@]>(
|
||||
reinterpret_cast<SourceHook::EmptyClass*>(CCW<Y>::GRP(ptr)), mfp, vfnptr, shptr, plug);
|
||||
}
|
||||
@]
|
||||
|
||||
@ -1291,24 +1419,29 @@ SH_MCALL2(SourceHook::ManualCallClass *ptr, RetType(X::*mfp)(@[$2,1,$1|, :Param$
|
||||
@[$1,0,$a:
|
||||
// Support for $1 arguments
|
||||
template <class X, class Y, class MFP, class RetType@[$2,1,$1:, class Param$2@]>
|
||||
SourceHook::ExecutableClass$1<SourceHook::CallClass<Y>, MFP, RetType@[$2,1,$1:, Param$2@]>
|
||||
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@]@[$1!=0:, @]...))
|
||||
SourceHook::ExecutableClass$1<typename SourceHook::CCW<Y>::type, MFP, RetType@[$2,1,$1:, Param$2@]>
|
||||
SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@]@[$1!=0:, @]...), SourceHook::ISourceHook *shptr, SourceHook::Plugin plug)
|
||||
{
|
||||
return SourceHook::ExecutableClass$1<SourceHook::CallClass<Y>, MFP, RetType@[$2,1,$1:, Param$2@]>(ptr, mfp);
|
||||
SH__CALL_GET_VFNPTR_NORMAL
|
||||
return SourceHook::ExecutableClass$1<typename CCW<Y>::type, MFP, RetType@[$2,1,$1:, Param$2@]>(CCW<Y>::GRP(ptr),
|
||||
mfp, vfnptr, shptr, plug);
|
||||
}
|
||||
|
||||
template <class X, class Y, class MFP, class RetType@[$2,1,$1:, class Param$2@]>
|
||||
SourceHook::ExecutableClass$1<SourceHook::CallClass<Y>, MFP, RetType@[$2,1,$1:, Param$2@]>
|
||||
SH_CALL2(SourceHook::CallClass<Y> *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@]@[$1!=0:, @]...)const)
|
||||
SourceHook::ExecutableClass$1<typename SourceHook::CCW<Y>::type, MFP, RetType@[$2,1,$1:, Param$2@]>
|
||||
SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@]@[$1!=0:, @]...)const, SourceHook::ISourceHook *shptr, SourceHook::Plugin plug)
|
||||
{
|
||||
return SourceHook::ExecutableClass$1<SourceHook::CallClass<Y>, MFP, RetType@[$2,1,$1:, Param$2@]>(ptr, mfp);
|
||||
SH__CALL_GET_VFNPTR_NORMAL
|
||||
return SourceHook::ExecutableClass$1<typename CCW<Y>::type, MFP, RetType@[$2,1,$1:, Param$2@]>(CCW<Y>::GRP(ptr),
|
||||
mfp, vfnptr, shptr, plug);
|
||||
}
|
||||
|
||||
@]
|
||||
|
||||
#endif
|
||||
|
||||
#define SH_CALL(ptr, mfp) SH_CALL2((ptr), (mfp), (mfp))
|
||||
#define SH_CALL(ptr, mfp) SH_CALL2((ptr), (mfp), (mfp), SH_GLOB_SHPTR, SH_GLOB_PLUGPTR)
|
||||
#define SH_MCALL2(ptr, mfp, vtblidx, vtbloffs, thisptroffs) SH_MCALL3((ptr), (mfp), (mfp), (vtblidx), (vtbloffs), (thisptroffs), SH_GLOB_SHPTR, SH_GLOB_PLUGPTR)
|
||||
#define SH_MCALL(ptr, mhookname) SH_MCALL2((ptr), SH_MFHCls(mhookname)::ECMFP(), SH_MFHCls(mhookname)::ms_MFI.vtblindex, \
|
||||
SH_MFHCls(mhookname)::ms_MFI.vtbloffs, SH_MFHCls(mhookname)::ms_MFI.thisptroffs)
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ namespace SourceHook
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
CSourceHookImpl::CSourceHookImpl()
|
||||
CSourceHookImpl::CSourceHookImpl() : m_OneIgnore(NULL), m_IgnoreActive(false)
|
||||
{
|
||||
}
|
||||
CSourceHookImpl::~CSourceHookImpl()
|
||||
@ -277,24 +277,32 @@ namespace SourceHook
|
||||
m_HookMans.clear();
|
||||
}
|
||||
|
||||
|
||||
bool CSourceHookImpl::AddHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post)
|
||||
{
|
||||
void *adjustediface = reinterpret_cast<void*>(reinterpret_cast<char*>(iface) + thisptr_offs);
|
||||
return AddHookNew(plug, Hook_Normal, iface, thisptr_offs, myHookMan, handler, post) != 0 ? true : false;
|
||||
}
|
||||
|
||||
int CSourceHookImpl::AddHookNew(Plugin plug, AddHookMode mode, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan,
|
||||
ISHDelegate *handler, bool post)
|
||||
{
|
||||
void *adjustediface = NULL;
|
||||
void **cur_vtptr = NULL;
|
||||
void *cur_vfnptr = NULL;
|
||||
|
||||
if (mode != Hook_Normal && mode != Hook_VP && mode != Hook_DVP)
|
||||
return 0;
|
||||
|
||||
// 1) Get info about the hook manager
|
||||
CHookManagerInfo tmp;
|
||||
if (myHookMan(HA_GetInfo, &tmp) != 0)
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
tmp.m_Func = myHookMan;
|
||||
tmp.m_Plug = plug;
|
||||
|
||||
CHookManagerContainer::HMCI hmci(tmp.m_Proto, tmp.m_VtblOffs, tmp.m_VtblIdx);
|
||||
|
||||
void **cur_vtptr = *reinterpret_cast<void***>(
|
||||
reinterpret_cast<char*>(adjustediface) + tmp.m_VtblOffs);
|
||||
void *cur_vfnptr = reinterpret_cast<void*>(cur_vtptr + tmp.m_VtblIdx);
|
||||
|
||||
// Add the container if not already added
|
||||
HookManContList::iterator hmcl_iter = m_HookMans.find(hmci);
|
||||
if (hmcl_iter == m_HookMans.end())
|
||||
@ -320,7 +328,7 @@ namespace SourceHook
|
||||
hmil_iter != hmcl_iter2->end(); ++hmil_iter)
|
||||
{
|
||||
if (hmil_iter->m_VfnPtrs.find(cur_vfnptr) != hmil_iter->m_VfnPtrs.end())
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -329,16 +337,37 @@ namespace SourceHook
|
||||
if (hookman->m_VfnPtrs.empty())
|
||||
hookman->m_Func(HA_Register, &(*hookman));
|
||||
|
||||
|
||||
// find vfnptr
|
||||
if (mode == Hook_Normal || mode == Hook_VP)
|
||||
{
|
||||
adjustediface = reinterpret_cast<void*>(reinterpret_cast<char*>(iface) + thisptr_offs);
|
||||
|
||||
cur_vtptr = *reinterpret_cast<void***>(
|
||||
reinterpret_cast<char*>(adjustediface) + tmp.m_VtblOffs);
|
||||
cur_vfnptr = reinterpret_cast<void*>(cur_vtptr + tmp.m_VtblIdx);
|
||||
|
||||
// For Hook_VP, adjustediface will be set to NULL later
|
||||
// because we first have to patch callclasses (callclasses are deprecated but left in for backwards compat)
|
||||
}
|
||||
else if (mode == Hook_DVP)
|
||||
{
|
||||
adjustediface = NULL;
|
||||
|
||||
cur_vtptr = reinterpret_cast<void**>(iface);
|
||||
cur_vfnptr = cur_vtptr + tmp.m_VtblIdx;
|
||||
}
|
||||
|
||||
CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->m_VfnPtrs.find(cur_vfnptr);
|
||||
|
||||
if (vfnptr_iter == hookman->m_VfnPtrs.end())
|
||||
{
|
||||
// Add a new one
|
||||
CVfnPtr vfp(cur_vfnptr);
|
||||
CVfnPtr vfp(cur_vfnptr, &m_OneIgnore);
|
||||
|
||||
// Alter vtable entry
|
||||
if (!SetMemAccess(cur_vtptr, sizeof(void*) * (tmp.m_VtblIdx + 1), SH_MEM_READ | SH_MEM_WRITE))
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
*reinterpret_cast<void**>(cur_vfnptr) = *reinterpret_cast<void**>(hookman->m_HookfuncVfnptr);
|
||||
|
||||
@ -352,6 +381,10 @@ namespace SourceHook
|
||||
ApplyCallClassPatches(adjustediface, tmp.m_VtblOffs, tmp.m_VtblIdx, vfp.m_OrigEntry);
|
||||
}
|
||||
|
||||
// If it's a VP hook, set adjustediface to NULL now ( see the comments at the beginning of sourcehook_impl.h )
|
||||
if (mode == Hook_VP)
|
||||
adjustediface = NULL;
|
||||
|
||||
CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.find(adjustediface);
|
||||
if (iface_iter == vfnptr_iter->m_Ifaces.end())
|
||||
{
|
||||
@ -361,6 +394,34 @@ namespace SourceHook
|
||||
// Make iface_iter point to the new element
|
||||
iface_iter = vfnptr_iter->m_Ifaces.end();
|
||||
--iface_iter;
|
||||
|
||||
// If this is a VP-Hook-NULL interface, go through all other interfaces of this vfnptr and tell them!
|
||||
if (adjustediface == NULL)
|
||||
{
|
||||
for (CVfnPtr::IfaceListIter iface_iter2 = vfnptr_iter->m_Ifaces.begin();
|
||||
iface_iter2 != vfnptr_iter->m_Ifaces.end(); ++iface_iter2)
|
||||
{
|
||||
if (*iface_iter2 != NULL)
|
||||
{
|
||||
iface_iter2->m_PreHooks.SetVPList(&iface_iter->m_PreHooks.m_List);
|
||||
iface_iter2->m_PostHooks.SetVPList(&iface_iter->m_PostHooks.m_List);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If this is a new non-VP-Hook-NULL interface, look for a non-VP-Hook-NULL interface!
|
||||
for (CVfnPtr::IfaceListIter iface_iter2 = vfnptr_iter->m_Ifaces.begin();
|
||||
iface_iter2 != vfnptr_iter->m_Ifaces.end(); ++iface_iter2)
|
||||
{
|
||||
if (*iface_iter2 == NULL)
|
||||
{
|
||||
iface_iter->m_PreHooks.SetVPList(&iface_iter2->m_PreHooks.m_List);
|
||||
iface_iter->m_PostHooks.SetVPList(&iface_iter2->m_PostHooks.m_List);
|
||||
break; // There can only be one!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the hook
|
||||
@ -369,11 +430,136 @@ namespace SourceHook
|
||||
hookinfo.plug = plug;
|
||||
hookinfo.paused = false;
|
||||
hookinfo.thisptr_offs = thisptr_offs;
|
||||
hookinfo.hookid = m_HookIDMan.New(tmp.m_Proto, tmp.m_VtblOffs, tmp.m_VtblIdx, cur_vfnptr,
|
||||
adjustediface, plug, thisptr_offs, handler, post);
|
||||
|
||||
if (post)
|
||||
iface_iter->m_PostHooks.m_List.push_back(hookinfo);
|
||||
else
|
||||
iface_iter->m_PreHooks.m_List.push_back(hookinfo);
|
||||
|
||||
return hookinfo.hookid;
|
||||
}
|
||||
|
||||
bool CSourceHookImpl::RemoveHookByID(Plugin plug, int hookid)
|
||||
{
|
||||
const CHookIDManager::Entry *hentry;
|
||||
|
||||
hentry = m_HookIDMan.QueryHook(hookid);
|
||||
if (!hentry)
|
||||
{
|
||||
// hookid doesn't exist !
|
||||
return false;
|
||||
}
|
||||
|
||||
HookManContList::iterator hmcl_iter = m_HookMans.find(
|
||||
CHookManagerContainer::HMCI(hentry->proto.GetProto(), hentry->vtbl_offs, hentry->vtbl_idx));
|
||||
if (hmcl_iter == m_HookMans.end() || hmcl_iter->empty())
|
||||
return false;
|
||||
CHookManagerContainer::iterator hookman = hmcl_iter->begin();
|
||||
|
||||
// Find vfnptr
|
||||
CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->m_VfnPtrs.find(hentry->vfnptr);
|
||||
if (vfnptr_iter == hookman->m_VfnPtrs.end())
|
||||
return false;
|
||||
|
||||
// Find iface
|
||||
CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.find(hentry->adjustediface);
|
||||
if (iface_iter == vfnptr_iter->m_Ifaces.end())
|
||||
return false;
|
||||
|
||||
// Find hook
|
||||
List<HookInfo> &hooks = hentry->post ? iface_iter->m_PostHooks.m_List : iface_iter->m_PreHooks.m_List;
|
||||
|
||||
List<HookInfo>::iterator hookiter = hooks.find(hookid);
|
||||
if (hookiter == hooks.end())
|
||||
return false;
|
||||
|
||||
hookiter->handler->DeleteThis();
|
||||
|
||||
// Move all iterators pointing at this
|
||||
List<HookInfo>::iterator oldhookiter = hookiter;
|
||||
hookiter = hooks.erase(hookiter);
|
||||
List<HookInfo>::iterator newhookiter = hookiter;
|
||||
--newhookiter; // The hook loop will ++ it then
|
||||
CHookList::CIter *pItIter;
|
||||
|
||||
for (pItIter = iface_iter->m_PreHooks.m_UsedIters; pItIter; pItIter = pItIter->m_pNext)
|
||||
if (pItIter->m_Iter == oldhookiter)
|
||||
pItIter->m_Iter = newhookiter;
|
||||
|
||||
// If this is VP-Hook-NULL interface, also check all other interfaces of this vfnptr
|
||||
if (*iface_iter == NULL)
|
||||
{
|
||||
for (CVfnPtr::IfaceListIter iface_iter2 = vfnptr_iter->m_Ifaces.begin();
|
||||
iface_iter2 != vfnptr_iter->m_Ifaces.end(); ++iface_iter2)
|
||||
{
|
||||
if (*iface_iter2 != NULL)
|
||||
{
|
||||
for (pItIter = iface_iter2->m_PreHooks.m_UsedIters; pItIter; pItIter = pItIter->m_pNext)
|
||||
if (pItIter->m_Iter == oldhookiter)
|
||||
pItIter->m_Iter = newhookiter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (iface_iter->m_PostHooks.m_List.empty() && iface_iter->m_PreHooks.m_List.empty())
|
||||
{
|
||||
// If this is a VP-Hook-NULL interface, go through all other interfaces of this vfnptr and tell them!
|
||||
if (*iface_iter == NULL)
|
||||
{
|
||||
for (CVfnPtr::IfaceListIter iface_iter2 = vfnptr_iter->m_Ifaces.begin();
|
||||
iface_iter2 != vfnptr_iter->m_Ifaces.end(); ++iface_iter2)
|
||||
{
|
||||
if (iface_iter2->m_Ptr != NULL)
|
||||
{
|
||||
iface_iter2->m_PreHooks.ClearVPList();
|
||||
iface_iter2->m_PostHooks.ClearVPList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// There are no hooks on this iface anymore...
|
||||
for (HookLoopInfoStack::iterator hli_iter = m_HLIStack.begin();
|
||||
hli_iter != m_HLIStack.end(); ++hli_iter)
|
||||
{
|
||||
if (hli_iter->pCurIface == static_cast<IIface*>(&(*iface_iter)))
|
||||
hli_iter->shouldContinue = false;
|
||||
}
|
||||
|
||||
iface_iter = vfnptr_iter->m_Ifaces.erase(iface_iter);
|
||||
if (vfnptr_iter->m_Ifaces.empty())
|
||||
{
|
||||
// No ifaces at all -> Deactivate the hook
|
||||
|
||||
// Only patch the vfnptr back if the module is still in memory
|
||||
// If it's not, do not remove stuff like we did before
|
||||
// First off we did it wrong (shutdown the whole hookman, uh..) and secondly applications may be
|
||||
// confused by RemoveHook returning false then (yeah, I know, I made this one up, no one checks for RemoveHook error)
|
||||
if (ModuleInMemory(reinterpret_cast<char*>(vfnptr_iter->m_Ptr), SH_PTRSIZE))
|
||||
{
|
||||
*reinterpret_cast<void**>(vfnptr_iter->m_Ptr) = vfnptr_iter->m_OrigEntry;
|
||||
}
|
||||
|
||||
hookman->m_VfnPtrs.erase(vfnptr_iter);
|
||||
|
||||
// Remove callclass patch
|
||||
for (Impl_CallClassList::iterator cciter = m_CallClasses.begin(); cciter != m_CallClasses.end(); ++cciter)
|
||||
if (cciter->m_Ptr == hentry->adjustediface)
|
||||
cciter->RemoveCallClassPatch(hentry->vtbl_offs, hentry->vtbl_idx);
|
||||
|
||||
if (hookman->m_VfnPtrs.empty())
|
||||
{
|
||||
// Unregister the hook manager
|
||||
hookman->m_Func(HA_Unregister, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Don't forget to remove the hookid from m_HookIDMan
|
||||
m_HookIDMan.Remove(hookid);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -384,113 +570,32 @@ namespace SourceHook
|
||||
|
||||
bool CSourceHookImpl::RemoveHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post)
|
||||
{
|
||||
void *adjustediface = reinterpret_cast<void*>(reinterpret_cast<char*>(iface)+thisptr_offs);
|
||||
// Get info about hook manager and compute adjustediface
|
||||
CHookManagerInfo tmp;
|
||||
if (myHookMan(HA_GetInfo, &tmp) != 0)
|
||||
return false;
|
||||
|
||||
// Find the hook manager and the hook
|
||||
void *adjustediface = reinterpret_cast<void*>(reinterpret_cast<char*>(iface)+thisptr_offs);
|
||||
|
||||
HookManContList::iterator hmcl_iter = m_HookMans.find(
|
||||
CHookManagerContainer::HMCI(tmp.m_Proto, tmp.m_VtblOffs, tmp.m_VtblIdx));
|
||||
if (hmcl_iter == m_HookMans.end() || hmcl_iter->empty())
|
||||
return false;
|
||||
|
||||
CHookManagerContainer::iterator hookman = hmcl_iter->begin();
|
||||
// Loop through all hooks and remove those which match:
|
||||
// hookman, vfnptr, iface, plug, adjusted iface, this ptr offs, handler, post
|
||||
CVector<int> removehooks;
|
||||
m_HookIDMan.FindAllHooks(removehooks, tmp.m_Proto, tmp.m_VtblOffs, tmp.m_VtblIdx, adjustediface, plug, thisptr_offs, handler, post);
|
||||
|
||||
if (!ModuleInMemory(reinterpret_cast<char*>(adjustediface) + tmp.m_VtblOffs,
|
||||
sizeof(void*) * (tmp.m_VtblIdx + 1)))
|
||||
{
|
||||
// The module the vtable was in is already unloaded.
|
||||
hookman->m_VfnPtrs.clear();
|
||||
hookman->m_Func(HA_Unregister, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
void **cur_vtptr = *reinterpret_cast<void***>(
|
||||
reinterpret_cast<char*>(adjustediface) + tmp.m_VtblOffs);
|
||||
void *cur_vfnptr = reinterpret_cast<void*>(cur_vtptr + tmp.m_VtblIdx);
|
||||
|
||||
CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->m_VfnPtrs.find(cur_vfnptr);
|
||||
|
||||
if (vfnptr_iter == hookman->m_VfnPtrs.end())
|
||||
if (removehooks.empty())
|
||||
return false;
|
||||
|
||||
for (CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.begin();
|
||||
iface_iter != vfnptr_iter->m_Ifaces.end();)
|
||||
bool status = false;
|
||||
|
||||
for (CVector<int>::iterator iter = removehooks.begin(); iter != removehooks.end(); ++iter)
|
||||
{
|
||||
if (iface_iter->m_Ptr != adjustediface)
|
||||
{
|
||||
iface_iter++;
|
||||
continue;
|
||||
}
|
||||
List<HookInfo> &hooks =
|
||||
post ? iface_iter->m_PostHooks.m_List : iface_iter->m_PreHooks.m_List;
|
||||
|
||||
bool erase;
|
||||
for (List<HookInfo>::iterator hookiter = hooks.begin();
|
||||
hookiter != hooks.end(); )
|
||||
{
|
||||
erase = hookiter->plug == plug && hookiter->handler->IsEqual(handler) &&
|
||||
hookiter->thisptr_offs == thisptr_offs;
|
||||
if (erase)
|
||||
{
|
||||
hookiter->handler->DeleteThis(); // Make the _plugin_ delete the handler object
|
||||
|
||||
// Move all iterators pointing at this
|
||||
List<HookInfo>::iterator oldhookiter = hookiter;
|
||||
hookiter = hooks.erase(hookiter);
|
||||
List<HookInfo>::iterator newhookiter = hookiter;
|
||||
--newhookiter; // The hook loop will ++ it then
|
||||
CHookList::CIter *pItIter;
|
||||
for (pItIter = iface_iter->m_PreHooks.m_UsedIters; pItIter; pItIter = pItIter->m_pNext)
|
||||
if (pItIter->m_Iter == oldhookiter)
|
||||
pItIter->m_Iter = newhookiter;
|
||||
}
|
||||
else
|
||||
++hookiter;
|
||||
}
|
||||
if (iface_iter->m_PostHooks.m_List.empty() && iface_iter->m_PreHooks.m_List.empty())
|
||||
{
|
||||
// There are no hooks on this iface anymore...
|
||||
for (HookLoopInfoStack::iterator hli_iter = m_HLIStack.begin();
|
||||
hli_iter != m_HLIStack.end(); ++hli_iter)
|
||||
{
|
||||
if (hli_iter->pCurIface == static_cast<IIface*>(&(*iface_iter)))
|
||||
hli_iter->shouldContinue = false;
|
||||
}
|
||||
|
||||
iface_iter = vfnptr_iter->m_Ifaces.erase(iface_iter);
|
||||
if (vfnptr_iter->m_Ifaces.empty())
|
||||
{
|
||||
// No ifaces at all -> Deactivate the hook
|
||||
*reinterpret_cast<void**>(vfnptr_iter->m_Ptr) = vfnptr_iter->m_OrigEntry;
|
||||
|
||||
hookman->m_VfnPtrs.erase(vfnptr_iter);
|
||||
|
||||
// Remove callclass patch
|
||||
for (Impl_CallClassList::iterator cciter = m_CallClasses.begin(); cciter != m_CallClasses.end(); ++cciter)
|
||||
if (cciter->m_Ptr == adjustediface)
|
||||
cciter->RemoveCallClassPatch(tmp.m_VtblOffs, tmp.m_VtblIdx);
|
||||
|
||||
if (hookman->m_VfnPtrs.empty())
|
||||
{
|
||||
// Unregister the hook manager
|
||||
hookman->m_Func(HA_Unregister, NULL);
|
||||
}
|
||||
|
||||
// Don't try to continue looping through ifaces
|
||||
// - the list is already invalid
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
++iface_iter;
|
||||
if (RemoveHookByID(plug, *iter))
|
||||
status = true;
|
||||
}
|
||||
return true;
|
||||
return status;
|
||||
}
|
||||
|
||||
GenericCallClass *CSourceHookImpl::GetCallClass(void *iface, size_t size)
|
||||
DeprecatedCallClass<void> *CSourceHookImpl::GetCallClass(void *iface, size_t size)
|
||||
{
|
||||
for (Impl_CallClassList::iterator cciter = m_CallClasses.begin(); cciter != m_CallClasses.end(); ++cciter)
|
||||
{
|
||||
@ -509,7 +614,7 @@ namespace SourceHook
|
||||
return &m_CallClasses.back();
|
||||
}
|
||||
|
||||
void CSourceHookImpl::ReleaseCallClass(GenericCallClass *ptr)
|
||||
void CSourceHookImpl::ReleaseCallClass(DeprecatedCallClass<void> *ptr)
|
||||
{
|
||||
Impl_CallClassList::iterator iter = m_CallClasses.find(ptr);
|
||||
if (iter == m_CallClasses.end())
|
||||
@ -614,7 +719,7 @@ namespace SourceHook
|
||||
|
||||
void CSourceHookImpl::HookLoopBegin(IIface *pIface)
|
||||
{
|
||||
HookLoopInfo hli;
|
||||
HookLoopInfo hli = {0};
|
||||
hli.pCurIface = pIface;
|
||||
hli.shouldContinue = true;
|
||||
hli.recall = HookLoopInfo::Recall_No;
|
||||
@ -802,6 +907,35 @@ namespace SourceHook
|
||||
}
|
||||
}
|
||||
|
||||
void CSourceHookImpl::SetIgnoreHooks(Plugin plug, void *vfnptr)
|
||||
{
|
||||
m_OneIgnore = vfnptr;
|
||||
}
|
||||
|
||||
void CSourceHookImpl::ResetIgnoreHooks(Plugin plug, void *vfnptr)
|
||||
{
|
||||
m_OneIgnore = NULL;
|
||||
}
|
||||
|
||||
void *CSourceHookImpl::GetOrigVfnPtrEntry(void *vfnptr)
|
||||
{
|
||||
for (HookManContList::iterator hmcl_iter = m_HookMans.begin();
|
||||
hmcl_iter != m_HookMans.end(); ++hmcl_iter)
|
||||
{
|
||||
for (CHookManagerContainer::iterator hookmaniter = hmcl_iter->begin();
|
||||
hookmaniter != hmcl_iter->end(); ++hookmaniter)
|
||||
{
|
||||
for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookmaniter->m_VfnPtrs.begin();
|
||||
vfnptr_iter != hookmaniter->m_VfnPtrs.end(); ++vfnptr_iter)
|
||||
{
|
||||
if (vfnptr_iter->m_Ptr == vfnptr)
|
||||
return vfnptr_iter->m_OrigEntry;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
// CCallClassImpl
|
||||
////////////////////////////
|
||||
@ -897,7 +1031,8 @@ namespace SourceHook
|
||||
|
||||
// If you get a crash here, the ptr passed is invalid
|
||||
// This usually means a SH_DECL_MANUALHOOK* with wrong thisptroffs/vtbloffs/vtblidx
|
||||
CSourceHookImpl::CVfnPtr::CVfnPtr(void *ptr) : m_Ptr(ptr), m_OrigEntry(*reinterpret_cast<void**>(ptr))
|
||||
CSourceHookImpl::CVfnPtr::CVfnPtr(void *ptr, void **pOneIgnore) : m_Ptr(ptr),
|
||||
m_OrigEntry(*reinterpret_cast<void**>(ptr)), m_pOneIgnore(pOneIgnore)
|
||||
{
|
||||
}
|
||||
CSourceHookImpl::CVfnPtr::~CVfnPtr()
|
||||
@ -916,8 +1051,24 @@ namespace SourceHook
|
||||
|
||||
IIface *CSourceHookImpl::CVfnPtr::FindIface(void *ptr)
|
||||
{
|
||||
if (m_Ptr == *m_pOneIgnore)
|
||||
{
|
||||
*m_pOneIgnore = NULL; // Only once!
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IfaceListIter iter = m_Ifaces.find(ptr);
|
||||
return iter == m_Ifaces.end() ? NULL : &(*iter);
|
||||
|
||||
// If nothing is found, check for a NULL-interface (VP hooks only)
|
||||
if (iter == m_Ifaces.end())
|
||||
{
|
||||
iter = m_Ifaces.find((void*)0);
|
||||
return iter == m_Ifaces.end() ? NULL : &(*iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
return &(*iter);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
@ -948,11 +1099,11 @@ namespace SourceHook
|
||||
// CHookList
|
||||
////////////////////////////
|
||||
|
||||
CSourceHookImpl::CHookList::CHookList() : m_FreeIters(NULL), m_UsedIters(NULL),
|
||||
CSourceHookImpl::CHookList::CHookList() : m_VPList(NULL), m_FreeIters(NULL), m_UsedIters(NULL),
|
||||
m_Recall(false)
|
||||
{
|
||||
}
|
||||
CSourceHookImpl::CHookList::CHookList(const CHookList &other) : m_List(other.m_List),
|
||||
CSourceHookImpl::CHookList::CHookList(const CHookList &other) : m_VPList(other.m_VPList), m_List(other.m_List),
|
||||
m_FreeIters(NULL), m_UsedIters(NULL), m_Recall(false)
|
||||
{
|
||||
}
|
||||
@ -1029,9 +1180,36 @@ namespace SourceHook
|
||||
m_Recall = false;
|
||||
}
|
||||
|
||||
CSourceHookImpl::CHookList::CIter::CIter(CHookList *pList) : m_pList(pList), m_pNext(NULL)
|
||||
void CSourceHookImpl::CHookList::SetVPList(List<HookInfo> *newList)
|
||||
{
|
||||
m_VPList = newList;
|
||||
|
||||
// Update cached CIter objects
|
||||
|
||||
CIter *pTmp;
|
||||
pTmp = m_FreeIters;
|
||||
while (pTmp)
|
||||
{
|
||||
pTmp->m_Iter.SetListLeft(m_VPList);
|
||||
pTmp = pTmp->m_pNext;
|
||||
}
|
||||
|
||||
pTmp = m_UsedIters;
|
||||
while (pTmp)
|
||||
{
|
||||
pTmp->m_Iter.SetListLeft(m_VPList);
|
||||
pTmp = pTmp->m_pNext;
|
||||
}
|
||||
}
|
||||
|
||||
void CSourceHookImpl::CHookList::ClearVPList()
|
||||
{
|
||||
SetVPList(NULL);
|
||||
}
|
||||
|
||||
CSourceHookImpl::CHookList::CIter::CIter(CHookList *pList) : m_pList(pList),
|
||||
m_Iter(pList->m_VPList, &m_pList->m_List), m_pNext(NULL)
|
||||
{
|
||||
GoToBegin();
|
||||
}
|
||||
CSourceHookImpl::CHookList::CIter::~CIter()
|
||||
{
|
||||
@ -1044,7 +1222,7 @@ namespace SourceHook
|
||||
|
||||
void CSourceHookImpl::CHookList::CIter::GoToBegin()
|
||||
{
|
||||
m_Iter = m_pList->m_List.begin();
|
||||
m_Iter.GoToBegin();
|
||||
SkipPaused();
|
||||
}
|
||||
|
||||
@ -1052,7 +1230,7 @@ namespace SourceHook
|
||||
{
|
||||
if (!m_pList)
|
||||
return false;
|
||||
return m_Iter == m_pList->m_List.end();
|
||||
return m_Iter.End();;
|
||||
}
|
||||
void CSourceHookImpl::CHookList::CIter::Next()
|
||||
{
|
||||
@ -1067,7 +1245,7 @@ namespace SourceHook
|
||||
}
|
||||
void CSourceHookImpl::CHookList::CIter::SkipPaused()
|
||||
{
|
||||
while (m_Iter != m_pList->m_List.end() && m_Iter->paused)
|
||||
while (!m_Iter.End() && m_Iter->paused)
|
||||
++m_Iter;
|
||||
}
|
||||
|
||||
@ -1085,6 +1263,9 @@ namespace SourceHook
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
char *CSourceHookImpl::CProto::DupProto(const char *p)
|
||||
{
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
char *newproto;
|
||||
if (*p)
|
||||
{
|
||||
@ -1105,6 +1286,9 @@ namespace SourceHook
|
||||
|
||||
void CSourceHookImpl::CProto::FreeProto(char *prot)
|
||||
{
|
||||
if (!prot)
|
||||
return;
|
||||
|
||||
if (*prot)
|
||||
{
|
||||
delete [] prot;
|
||||
@ -1117,6 +1301,9 @@ namespace SourceHook
|
||||
|
||||
bool CSourceHookImpl::CProto::Equal(const char *p1, const char *p2)
|
||||
{
|
||||
if (!p1 || !p2)
|
||||
return false;
|
||||
|
||||
if (*p1 && *p2) // Case1: Both old
|
||||
{
|
||||
// As in old versions
|
||||
@ -1209,4 +1396,68 @@ namespace SourceHook
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CHookIDManager
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CSourceHookImpl::CHookIDManager::CHookIDManager()
|
||||
{
|
||||
}
|
||||
|
||||
int CSourceHookImpl::CHookIDManager::New(const CProto &proto, int vtbl_offs, int vtbl_idx, void *vfnptr,
|
||||
void *adjustediface, Plugin plug, int thisptr_offs, ISHDelegate *handler, bool post)
|
||||
{
|
||||
Entry tmp(proto, vtbl_offs, vtbl_idx, vfnptr, adjustediface, plug, thisptr_offs, handler, post);
|
||||
|
||||
size_t cursize = m_Entries.size();
|
||||
for (size_t i = 0; i < cursize; ++i)
|
||||
{
|
||||
if (m_Entries[i].isfree)
|
||||
{
|
||||
m_Entries[i] = tmp;
|
||||
return static_cast<int>(i) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
m_Entries.push_back(tmp);
|
||||
return static_cast<int>(m_Entries.size()); // return size() because hookid = id+1 anyway
|
||||
}
|
||||
|
||||
bool CSourceHookImpl::CHookIDManager::Remove(int hookid)
|
||||
{
|
||||
int realid = hookid - 1;
|
||||
if (realid < 0 || realid >= static_cast<int>(m_Entries.size()) || m_Entries[realid].isfree)
|
||||
return false;
|
||||
|
||||
m_Entries[realid].isfree = true;
|
||||
|
||||
// :TODO: remove free ids from back sometimes ??
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const CSourceHookImpl::CHookIDManager::Entry * CSourceHookImpl::CHookIDManager::QueryHook(int hookid)
|
||||
{
|
||||
int realid = hookid - 1;
|
||||
if (realid < 0 || realid >= static_cast<int>(m_Entries.size()) || m_Entries[realid].isfree)
|
||||
return NULL;
|
||||
|
||||
return &m_Entries[realid];
|
||||
}
|
||||
|
||||
void CSourceHookImpl::CHookIDManager::FindAllHooks(CVector<int> &output, const CProto &proto, int vtbl_offs,
|
||||
int vtbl_idx, void *adjustediface, Plugin plug, int thisptr_offs, ISHDelegate *handler, bool post)
|
||||
{
|
||||
// oh my god, a lot of parameters...
|
||||
size_t cursize = m_Entries.size();
|
||||
for (size_t i = 0; i < cursize; ++i)
|
||||
{
|
||||
if (!m_Entries[i].isfree && m_Entries[i].proto == proto && m_Entries[i].vtbl_offs == vtbl_offs &&
|
||||
m_Entries[i].vtbl_idx == vtbl_idx && m_Entries[i].adjustediface == adjustediface && m_Entries[i].plug == plug &&
|
||||
m_Entries[i].thisptr_offs == thisptr_offs && m_Entries[i].handler->IsEqual(handler) && m_Entries[i].post == post)
|
||||
{
|
||||
output.push_back(static_cast<int>(i) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,7 @@
|
||||
#include "sh_vector.h"
|
||||
#include "sh_tinyhash.h"
|
||||
#include "sh_stack.h"
|
||||
#include "sh_listcat.h"
|
||||
|
||||
/*
|
||||
|
||||
@ -89,6 +90,9 @@ Hooks
|
||||
|
||||
---------------------------------------
|
||||
Call classes
|
||||
|
||||
!! deprecated !! - see below (new SH_CALL)
|
||||
|
||||
Call classes are identified by a this pointer and an instance size
|
||||
|
||||
We use the instance size because a derived class instance and a base class instance could
|
||||
@ -142,6 +146,28 @@ Return Values in Post Recalls
|
||||
HookLoopEnd we make sure that status is high enough so that the override return will be returned. crazy.
|
||||
|
||||
All this stuff could be much less complicated if I didn't try to preserve binary compatibility :)
|
||||
|
||||
VP Hooks
|
||||
VP hooks are hooks which are called on a vfnptr, regardless of the this pointer with which it was called. They are
|
||||
implemented as a special CIface instance with m_Ptr = NULL. All Hook Lists have a new "ListCatIterator" which
|
||||
virtually concatenates the NULL-interface-hook-list with their normal hook list.
|
||||
|
||||
|
||||
I'm afraid that with the addition of Recalls and VP Hooks, SourceHook is now a pretty complex and hacked-together
|
||||
binary compatible beast which is pretty hard to maintain unless you've written it :)
|
||||
|
||||
New SH_CALL
|
||||
The addition of VP hooks messed up the Call Classes concept (see above) - call classes are bound to an
|
||||
instance pointer; they only work on one of the hooked instances. But VP hooks are called on all instances.
|
||||
|
||||
That's why now, SH_CALL takes an instance pointer instead of a callclass pointer. It basically does this:
|
||||
1) call SH_GLOB_PTR->SetIgnoreHooks(vfnptr)
|
||||
2) call this->*mfp
|
||||
3) call SH_GLOB_PTR->ResetIgnoreHooks(vfnptr)
|
||||
|
||||
SourceHook stroes the "ignored vfnptr" and makes CVfnPtr::FindIface return NULL if the CVfnPtr instance
|
||||
corresponds to the ignored vfnptr. This way the hook manager thinks that the instance isn't hooked, and calls
|
||||
the original function. Everything works fine. This works even for VP hooks.
|
||||
*/
|
||||
|
||||
namespace SourceHook
|
||||
@ -160,6 +186,10 @@ namespace SourceHook
|
||||
char *DupProto(const char *src);
|
||||
void FreeProto(char *prot);
|
||||
public:
|
||||
CProto() : m_Proto(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
CProto(const char *szProto) : m_Proto(DupProto(szProto))
|
||||
{
|
||||
}
|
||||
@ -192,6 +222,11 @@ namespace SourceHook
|
||||
{
|
||||
return Equal(other.m_Proto, m_Proto);
|
||||
}
|
||||
|
||||
const char *GetProto() const
|
||||
{
|
||||
return m_Proto;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -226,17 +261,79 @@ namespace SourceHook
|
||||
HookManagerPubFunc hookman;
|
||||
};
|
||||
|
||||
// Associates hook ids with info about the hooks
|
||||
// Also used to keep track of used hook ids
|
||||
class CHookIDManager
|
||||
{
|
||||
public:
|
||||
struct Entry
|
||||
{
|
||||
bool isfree;
|
||||
|
||||
// hookman info
|
||||
CProto proto;
|
||||
int vtbl_offs;
|
||||
int vtbl_idx;
|
||||
|
||||
// vfnptr
|
||||
void *vfnptr;
|
||||
|
||||
// iface
|
||||
void* adjustediface;
|
||||
|
||||
// hook
|
||||
Plugin plug;
|
||||
int thisptr_offs;
|
||||
ISHDelegate *handler;
|
||||
bool post;
|
||||
|
||||
Entry(const CProto &pprt, int pvo, int pvi, void *pvp, void *pai, Plugin pplug, int pto,
|
||||
ISHDelegate *ph, bool ppost)
|
||||
: isfree(false), proto(pprt), vtbl_offs(pvo), vtbl_idx(pvi), vfnptr(pvp),
|
||||
adjustediface(pai), plug(pplug), thisptr_offs(pto), handler(ph), post(ppost)
|
||||
{
|
||||
}
|
||||
Entry()
|
||||
{
|
||||
}
|
||||
};
|
||||
private:
|
||||
// Internally, hookid 1 is stored as m_Entries[0]
|
||||
|
||||
CVector<Entry> m_Entries;
|
||||
public:
|
||||
CHookIDManager();
|
||||
int New(const CProto &proto, int vtbl_offs, int vtbl_idx, void *vfnptr, void *adjustediface,
|
||||
Plugin plug, int thisptr_offs, ISHDelegate *handler, bool post);
|
||||
bool Remove(int hookid);
|
||||
const Entry * QueryHook(int hookid);
|
||||
|
||||
// Finds all hooks with the given info, and fills the hookids into output.
|
||||
void FindAllHooks(CVector<int> &output, const CProto &proto, int vtbl_offs, int vtbl_idx,
|
||||
void *adjustediface, Plugin plug, int thisptr_offs, ISHDelegate *handler, bool post);
|
||||
|
||||
// Removes all hooks with a specified vfnptr
|
||||
bool RemoveAll(void *vfnptr);
|
||||
};
|
||||
|
||||
struct HookInfo
|
||||
{
|
||||
ISHDelegate *handler; //!< Pointer to the handler
|
||||
bool paused; //!< If true, the hook should not be executed
|
||||
Plugin plug; //!< The owner plugin
|
||||
int thisptr_offs; //!< This pointer offset
|
||||
int hookid; //!< Unique ID given by CHookIDManager
|
||||
|
||||
bool operator==(int otherid)
|
||||
{
|
||||
return hookid == otherid;
|
||||
}
|
||||
};
|
||||
|
||||
class CHookList : public IHookList
|
||||
{
|
||||
public:
|
||||
List<HookInfo> *m_VPList; // left-hand list for ListCatIterator -> for VP hooks
|
||||
List<HookInfo> m_List;
|
||||
|
||||
friend class CIter;
|
||||
@ -250,7 +347,7 @@ namespace SourceHook
|
||||
void SkipPaused();
|
||||
public:
|
||||
|
||||
List<HookInfo>::iterator m_Iter;
|
||||
ListCatIterator<HookInfo> m_Iter;
|
||||
|
||||
CIter(CHookList *pList);
|
||||
|
||||
@ -293,6 +390,9 @@ namespace SourceHook
|
||||
|
||||
IIter *GetIter();
|
||||
void ReleaseIter(IIter *pIter);
|
||||
|
||||
void SetVPList(List<HookInfo> *newList);
|
||||
void ClearVPList();
|
||||
};
|
||||
|
||||
// I know, data hiding... But I'm a lazy bastard!
|
||||
@ -315,6 +415,10 @@ namespace SourceHook
|
||||
{
|
||||
return m_Ptr == ptr;
|
||||
}
|
||||
bool operator!=(void *ptr)
|
||||
{
|
||||
return m_Ptr != ptr;
|
||||
}
|
||||
};
|
||||
|
||||
class CVfnPtr : public IVfnPtr
|
||||
@ -328,8 +432,9 @@ namespace SourceHook
|
||||
|
||||
IfaceList m_Ifaces;
|
||||
|
||||
void **m_pOneIgnore;
|
||||
public:
|
||||
CVfnPtr(void *ptr);
|
||||
CVfnPtr(void *ptr, void **pOneIgnore);
|
||||
virtual ~CVfnPtr();
|
||||
|
||||
void *GetVfnPtr();
|
||||
@ -446,7 +551,7 @@ namespace SourceHook
|
||||
void AddHookManager(Plugin plug, const CHookManagerInfo &hookman);
|
||||
};
|
||||
|
||||
class CCallClassImpl : public GenericCallClass
|
||||
class CCallClassImpl : public DeprecatedCallClass<void>
|
||||
{
|
||||
public:
|
||||
|
||||
@ -520,6 +625,10 @@ namespace SourceHook
|
||||
void SetPluginPaused(Plugin plug, bool paused);
|
||||
|
||||
HookLoopInfoStack m_HLIStack;
|
||||
CHookIDManager m_HookIDMan;
|
||||
|
||||
void *m_OneIgnore; //:TODO:
|
||||
bool m_IgnoreActive;
|
||||
public:
|
||||
CSourceHookImpl();
|
||||
virtual ~CSourceHookImpl();
|
||||
@ -608,14 +717,14 @@ namespace SourceHook
|
||||
* @param iface The interface pointer
|
||||
* @param size Size of the class instance
|
||||
*/
|
||||
GenericCallClass *GetCallClass(void *iface, size_t size);
|
||||
DeprecatedCallClass<void> *GetCallClass(void *iface, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Release a callclass
|
||||
*
|
||||
* @param ptr Pointer to the callclass
|
||||
*/
|
||||
virtual void ReleaseCallClass(GenericCallClass *ptr);
|
||||
virtual void ReleaseCallClass(DeprecatedCallClass<void> *ptr);
|
||||
|
||||
virtual void SetRes(META_RES res); //!< Sets the meta result
|
||||
virtual META_RES GetPrevRes(); //!< Gets the meta result of the previously called handler
|
||||
@ -650,6 +759,58 @@ namespace SourceHook
|
||||
|
||||
virtual void *SetupHookLoop(META_RES *statusPtr, META_RES *prevResPtr, META_RES *curResPtr,
|
||||
void **ifacePtrPtr, const void *origRetPtr, void *overrideRetPtr);
|
||||
|
||||
/**
|
||||
* @brief Add a (VP) hook.
|
||||
*
|
||||
* @return non-zero hook id on success, 0 otherwise
|
||||
*
|
||||
* @param plug The unique identifier of the plugin that calls this function
|
||||
* @param mode Can be either Hook_Normal or Hook_VP (vtable-wide hook)
|
||||
* @param iface The interface pointer
|
||||
* The representative interface pointer for VP hooks
|
||||
* The vtable pointer for direct VP hooks !!!
|
||||
* @param ifacesize The size of the class iface points to
|
||||
* @param myHookMan A hook manager function that should be capable of handling the function
|
||||
* @param handler A pointer to a FastDelegate containing the hook handler
|
||||
* @param post Set to true if you want a post handler
|
||||
*/
|
||||
virtual int AddHookNew(Plugin plug, AddHookMode mode, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan,
|
||||
ISHDelegate *handler, bool post);
|
||||
|
||||
/**
|
||||
* @brief Remove a VP hook by ID.
|
||||
*
|
||||
* @return true on success, false otherwise
|
||||
*
|
||||
* @param plug The unique identifier of the plugin that calls this function
|
||||
* @param hookid The hook id (returned by AddHookNew)
|
||||
*/
|
||||
virtual bool RemoveHookByID(Plugin plug, int hookid);
|
||||
|
||||
/**
|
||||
* @brief Makes sure that hooks are going to be ignored on the next call of vfnptr
|
||||
*
|
||||
* @param plug The unique identifier of the plugin that calls this function
|
||||
* @param vfnptr The virtual function pointer of the function in question
|
||||
*/
|
||||
virtual void SetIgnoreHooks(Plugin plug, void *vfnptr);
|
||||
|
||||
/**
|
||||
* @brief Reverses SetIgnoreHooks' effect
|
||||
*
|
||||
* @param plug The unique identifier of the plugin that calls this function
|
||||
* @param vfnptr The virtual function pointer of the function in question
|
||||
*/
|
||||
virtual void ResetIgnoreHooks(Plugin plug, void *vfnptr);
|
||||
|
||||
/**
|
||||
* @brief Finds the original entry of a virtual function pointer
|
||||
*
|
||||
* @param vfnptr The virtual function pointer
|
||||
* @return The original entry if the virtual function pointer has been patched; NULL otherwise.
|
||||
*/
|
||||
virtual void *GetOrigVfnPtrEntry(void *vfnptr);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -80,6 +80,7 @@ DO_TEST(Recall);
|
||||
DO_TEST(Multi);
|
||||
DO_TEST(Ref);
|
||||
DO_TEST(RefRet);
|
||||
DO_TEST(VPHooks);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
@ -289,6 +289,12 @@
|
||||
<File
|
||||
RelativePath="..\testref.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\testrefret.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\testvphooks.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
@ -296,6 +302,15 @@
|
||||
<File
|
||||
RelativePath="..\..\sh_list.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\sh_listcat.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\sh_memfuncinfo.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\sh_memory.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\sh_stack.h">
|
||||
</File>
|
||||
|
||||
@ -338,6 +338,11 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
// GCC's optimizer is too good. I had to add this in order to make it execute a virtual table lookup!
|
||||
class Whatever : public Test
|
||||
{
|
||||
};
|
||||
|
||||
SH_DECL_HOOK1(Test, F299, SH_NOATTRIB, 0, bool, const char *);
|
||||
SH_DECL_HOOK0_void(Test, F1, SH_NOATTRIB, 0);
|
||||
SH_DECL_HOOK0_void(Test, F2, SH_NOATTRIB, 0);
|
||||
@ -416,52 +421,46 @@ bool TestBasic(std::string &error)
|
||||
g_PLID = 1337;
|
||||
|
||||
HandlersF1 f1_handlers;
|
||||
Test test;
|
||||
Whatever test;
|
||||
Test *pTest = &test;
|
||||
|
||||
// 1) Get a call class and call the member through it and normally
|
||||
SourceHook::CallClass<Test> *cc = SH_GET_CALLCLASS(pTest);
|
||||
// 1) SH_CALL it and call it normally
|
||||
|
||||
ADD_STATE(State_F1_CallClassGenerated);
|
||||
return true;
|
||||
SH_CALL(pTest, &Test::F1)();
|
||||
|
||||
|
||||
SH_CALL(cc, &Test::F1)();
|
||||
pTest->F1();
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_F1_CallClassGenerated,
|
||||
new State_F1_Called,
|
||||
new State_F1_Called,
|
||||
NULL), "Part 1");
|
||||
|
||||
// 2) Request a call class again
|
||||
SourceHook::CallClass<Test> *cc2 = SH_GET_CALLCLASS(pTest);
|
||||
ADD_STATE(State_F1_CallClassGenerated);
|
||||
|
||||
SH_CALL(cc, &Test::F1)();
|
||||
SH_CALL(cc2, &Test::F1)();
|
||||
SH_CALL(pTest, &Test::F1)();
|
||||
SH_CALL(pTest, &Test::F1)();
|
||||
pTest->F1();
|
||||
|
||||
SH_RELEASE_CALLCLASS(cc2);
|
||||
ADD_STATE(State_F1_CallClassReleased);
|
||||
|
||||
SH_CALL(cc, &Test::F1)();
|
||||
SH_CALL(pTest, &Test::F1)();
|
||||
pTest->F1();
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_F1_CallClassGenerated,
|
||||
new State_F1_Called,
|
||||
new State_F1_Called,
|
||||
new State_F1_Called,
|
||||
new State_F1_CallClassReleased,
|
||||
|
||||
new State_F1_Called,
|
||||
new State_F1_Called,
|
||||
NULL), "Part 2");
|
||||
|
||||
// 3) Add a pre hook
|
||||
// (one add memfunc in old format)
|
||||
g_F1Pre_WhatToDo = MRES_SUPERCEDE;
|
||||
ADD_STATE(State_F1_HookAdded(SH_ADD_HOOK_MEMFUNC(Test, F1, pTest, &f1_handlers, &HandlersF1::Pre, false)));
|
||||
ADD_STATE(State_F1_HookAdded(SH_ADD_HOOK_MEMFUNC(Test, F1, pTest, &f1_handlers, &HandlersF1::Pre, false) ? true : false));
|
||||
|
||||
SH_CALL(cc, &Test::F1)();
|
||||
SH_CALL(pTest, &Test::F1)();
|
||||
pTest->F1();
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
@ -470,30 +469,26 @@ bool TestBasic(std::string &error)
|
||||
new State_F1_PreHandler_Called(&f1_handlers),
|
||||
NULL), "Part 3");
|
||||
|
||||
// 4) Rerequest the callclass
|
||||
SH_RELEASE_CALLCLASS(cc);
|
||||
// 4) Test source-level compat with callclasses
|
||||
SourceHook::CallClass<Test> *pCC = SH_GET_CALLCLASS(pTest);
|
||||
|
||||
ADD_STATE(State_F1_CallClassReleased);
|
||||
cc2 = SH_GET_CALLCLASS(pTest);
|
||||
ADD_STATE(State_F1_CallClassGenerated);
|
||||
|
||||
SH_CALL(cc, &Test::F1)();
|
||||
SH_CALL(pCC, &Test::F1)();
|
||||
pTest->F1();
|
||||
|
||||
SH_RELEASE_CALLCLASS(pCC);
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_F1_CallClassReleased,
|
||||
new State_F1_CallClassGenerated,
|
||||
new State_F1_Called,
|
||||
new State_F1_PreHandler_Called(&f1_handlers),
|
||||
NULL), "Part 4");
|
||||
|
||||
// 5) Check ignore / supercede
|
||||
g_F1Pre_WhatToDo = MRES_SUPERCEDE;
|
||||
SH_CALL(cc, &Test::F1)();
|
||||
SH_CALL(pTest, &Test::F1)();
|
||||
pTest->F1();
|
||||
|
||||
g_F1Pre_WhatToDo = MRES_IGNORED;
|
||||
SH_CALL(cc, &Test::F1)();
|
||||
SH_CALL(pTest, &Test::F1)();
|
||||
pTest->F1();
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
@ -505,10 +500,11 @@ bool TestBasic(std::string &error)
|
||||
NULL), "Part 5");
|
||||
|
||||
// 6) remove the hook again
|
||||
// (one remove memfunc in old format)
|
||||
SH_REMOVE_HOOK_MEMFUNC(Test, F1, pTest, &f1_handlers, &HandlersF1::Pre, false);
|
||||
ADD_STATE(State_F1_HookRemoved);
|
||||
|
||||
SH_CALL(cc, &Test::F1)();
|
||||
SH_CALL(pTest, &Test::F1)();
|
||||
pTest->F1();
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
@ -519,9 +515,9 @@ bool TestBasic(std::string &error)
|
||||
|
||||
// 7) add a post hook now
|
||||
g_F1Post_WhatToDo = MRES_IGNORED;
|
||||
ADD_STATE(State_F1_HookAdded(SH_ADD_HOOK_MEMFUNC(Test, F1, pTest, &f1_handlers, &HandlersF1::Post, true)));
|
||||
ADD_STATE(State_F1_HookAdded(SH_ADD_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Post), true) ? true : false));
|
||||
|
||||
SH_CALL(cc, &Test::F1)();
|
||||
SH_CALL(pTest, &Test::F1)();
|
||||
pTest->F1();
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
@ -533,13 +529,13 @@ bool TestBasic(std::string &error)
|
||||
|
||||
// 8) And a pre hook again
|
||||
g_F1Pre_WhatToDo = MRES_IGNORED;
|
||||
ADD_STATE(State_F1_HookAdded(SH_ADD_HOOK_MEMFUNC(Test, F1, pTest, &f1_handlers, &HandlersF1::Pre, false)));
|
||||
ADD_STATE(State_F1_HookAdded(SH_ADD_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false) ? true : false));
|
||||
|
||||
SH_CALL(cc, &Test::F1)();
|
||||
SH_CALL(pTest, &Test::F1)();
|
||||
pTest->F1();
|
||||
|
||||
g_F1Pre_WhatToDo = MRES_SUPERCEDE;
|
||||
SH_CALL(cc, &Test::F1)();
|
||||
SH_CALL(pTest, &Test::F1)();
|
||||
pTest->F1();
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
@ -554,12 +550,12 @@ bool TestBasic(std::string &error)
|
||||
NULL), "Part 8");
|
||||
|
||||
// 9) Remove all hooks
|
||||
SH_REMOVE_HOOK_MEMFUNC(Test, F1, pTest, &f1_handlers, &HandlersF1::Pre, false);
|
||||
SH_REMOVE_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false);
|
||||
ADD_STATE(State_F1_HookRemoved);
|
||||
SH_REMOVE_HOOK_MEMFUNC(Test, F1, pTest, &f1_handlers, &HandlersF1::Post, true);
|
||||
SH_REMOVE_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Post), true);
|
||||
ADD_STATE(State_F1_HookRemoved);
|
||||
|
||||
SH_CALL(cc, &Test::F1)();
|
||||
SH_CALL(pTest, &Test::F1)();
|
||||
pTest->F1();
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
@ -574,7 +570,7 @@ bool TestBasic(std::string &error)
|
||||
g_F299Pre_WhatToRet = false;
|
||||
|
||||
ADD_STATE(State_F299Ret(pTest->F299("hi")));
|
||||
ADD_STATE(State_F299Ret(SH_CALL(cc, &Test::F299)("hi")));
|
||||
ADD_STATE(State_F299Ret(SH_CALL(pTest, &Test::F299)("hi")));
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_F299_Called("hi"),
|
||||
@ -583,9 +579,10 @@ bool TestBasic(std::string &error)
|
||||
new State_F299Ret(true),
|
||||
NULL), "Part 10.1");
|
||||
|
||||
// (one add staticfunc in old format)
|
||||
SH_ADD_HOOK_STATICFUNC(Test, F299, pTest, F299_Pre, false);
|
||||
ADD_STATE(State_F299Ret(pTest->F299("hi")));
|
||||
ADD_STATE(State_F299Ret(SH_CALL(cc, &Test::F299)("hi")));
|
||||
ADD_STATE(State_F299Ret(SH_CALL(pTest, &Test::F299)("hi")));
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_F299_PreHandlerCalled("hi"),
|
||||
@ -595,9 +592,9 @@ bool TestBasic(std::string &error)
|
||||
new State_F299Ret(true),
|
||||
NULL), "Part 10.2");
|
||||
|
||||
SH_ADD_HOOK_STATICFUNC(Test, F299, pTest, F299_Post, true);
|
||||
SH_ADD_HOOK(Test, F299, pTest, SH_STATIC(F299_Post), true);
|
||||
ADD_STATE(State_F299Ret(pTest->F299("hi")));
|
||||
ADD_STATE(State_F299Ret(SH_CALL(cc, &Test::F299)("hi")));
|
||||
ADD_STATE(State_F299Ret(SH_CALL(pTest, &Test::F299)("hi")));
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_F299_PreHandlerCalled("hi"),
|
||||
@ -610,7 +607,7 @@ bool TestBasic(std::string &error)
|
||||
|
||||
g_F299Pre_WhatToDo = MRES_OVERRIDE;
|
||||
ADD_STATE(State_F299Ret(pTest->F299("hi")));
|
||||
ADD_STATE(State_F299Ret(SH_CALL(cc, &Test::F299)("hi")));
|
||||
ADD_STATE(State_F299Ret(SH_CALL(pTest, &Test::F299)("hi")));
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_F299_PreHandlerCalled("hi"),
|
||||
@ -623,7 +620,7 @@ bool TestBasic(std::string &error)
|
||||
|
||||
g_F299Pre_WhatToDo = MRES_SUPERCEDE;
|
||||
ADD_STATE(State_F299Ret(pTest->F299("hi")));
|
||||
ADD_STATE(State_F299Ret(SH_CALL(cc, &Test::F299)("hi")));
|
||||
ADD_STATE(State_F299Ret(SH_CALL(pTest, &Test::F299)("hi")));
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_F299_PreHandlerCalled("hi"),
|
||||
@ -633,9 +630,10 @@ bool TestBasic(std::string &error)
|
||||
new State_F299Ret(true),
|
||||
NULL), "Part 10.5");
|
||||
|
||||
// (one remove staticfunc in old format)
|
||||
SH_REMOVE_HOOK_STATICFUNC(Test, F299, pTest, F299_Pre, false);
|
||||
ADD_STATE(State_F299Ret(pTest->F299("hi")));
|
||||
ADD_STATE(State_F299Ret(SH_CALL(cc, &Test::F299)("hi")));
|
||||
ADD_STATE(State_F299Ret(SH_CALL(pTest, &Test::F299)("hi")));
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_F299_Called("hi"),
|
||||
@ -645,9 +643,9 @@ bool TestBasic(std::string &error)
|
||||
new State_F299Ret(true),
|
||||
NULL), "Part 10.6");
|
||||
|
||||
SH_REMOVE_HOOK_STATICFUNC(Test, F299, pTest, F299_Post, true);
|
||||
SH_REMOVE_HOOK(Test, F299, pTest, SH_STATIC(F299_Post), true);
|
||||
ADD_STATE(State_F299Ret(pTest->F299("hi")));
|
||||
ADD_STATE(State_F299Ret(SH_CALL(cc, &Test::F299)("hi")));
|
||||
ADD_STATE(State_F299Ret(SH_CALL(pTest, &Test::F299)("hi")));
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_F299_Called("hi"),
|
||||
@ -656,39 +654,59 @@ bool TestBasic(std::string &error)
|
||||
new State_F299Ret(true),
|
||||
NULL), "Part 10.7");
|
||||
|
||||
// 11) Release callclass
|
||||
SH_RELEASE_CALLCLASS(cc);
|
||||
ADD_STATE(State_F1_CallClassReleased);
|
||||
|
||||
// 11 1/2) Test removing hook by id
|
||||
|
||||
g_F1Pre_WhatToDo = MRES_IGNORED;
|
||||
|
||||
pTest->F1();
|
||||
int hookPre = SH_ADD_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false);
|
||||
int hookPost = SH_ADD_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Post), true);
|
||||
|
||||
pTest->F1();
|
||||
SH_REMOVE_HOOK_ID(hookPost);
|
||||
pTest->F1();
|
||||
SH_REMOVE_HOOK_ID(hookPre);
|
||||
pTest->F1();
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_F1_CallClassReleased,
|
||||
NULL), "Part 11");
|
||||
new State_F1_Called,
|
||||
|
||||
new State_F1_PreHandler_Called(&f1_handlers),
|
||||
new State_F1_Called,
|
||||
new State_F1_PostHandler_Called(&f1_handlers),
|
||||
|
||||
new State_F1_PreHandler_Called(&f1_handlers),
|
||||
new State_F1_Called,
|
||||
|
||||
new State_F1_Called,
|
||||
|
||||
NULL), "Part 11 1/2");
|
||||
|
||||
// 12) Test? Test.
|
||||
SH_ADD_HOOK_MEMFUNC(Test, F1, pTest, &f1_handlers, &HandlersF1::Pre, true);
|
||||
SH_ADD_HOOK_MEMFUNC(Test, F2, pTest, &f1_handlers, &HandlersF1::Pre, true);
|
||||
SH_ADD_HOOK_MEMFUNC(Test, F3, pTest, &f1_handlers, &HandlersF1::Pre, false);
|
||||
SH_ADD_HOOK_MEMFUNC(Test, F4, pTest, &f1_handlers, &HandlersF1::Pre, true);
|
||||
SH_ADD_HOOK_MEMFUNC(Test, F5, pTest, &f1_handlers, &HandlersF1::Pre, false);
|
||||
SH_ADD_HOOK_MEMFUNC(Test, F6, pTest, &f1_handlers, &HandlersF1::Pre, true);
|
||||
SH_ADD_HOOK_MEMFUNC(Test, F7, pTest, &f1_handlers, &HandlersF1::Pre, false);
|
||||
SH_ADD_HOOK_MEMFUNC(Test, F8, pTest, &f1_handlers, &HandlersF1::Pre, false);
|
||||
SH_ADD_HOOK_MEMFUNC(Test, F9, pTest, &f1_handlers, &HandlersF1::Pre, false);
|
||||
SH_ADD_HOOK_MEMFUNC(Test, F10, pTest, &f1_handlers, &HandlersF1::Pre, false);
|
||||
SH_ADD_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true);
|
||||
SH_ADD_HOOK(Test, F2, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true);
|
||||
SH_ADD_HOOK(Test, F3, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false);
|
||||
SH_ADD_HOOK(Test, F4, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true);
|
||||
SH_ADD_HOOK(Test, F5, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false);
|
||||
SH_ADD_HOOK(Test, F6, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true);
|
||||
SH_ADD_HOOK(Test, F7, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false);
|
||||
SH_ADD_HOOK(Test, F8, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false);
|
||||
SH_ADD_HOOK(Test, F9, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false);
|
||||
SH_ADD_HOOK(Test, F10, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false);
|
||||
|
||||
SH_REMOVE_HOOK_MEMFUNC(Test, F1, pTest, &f1_handlers, &HandlersF1::Pre, true);
|
||||
SH_REMOVE_HOOK_MEMFUNC(Test, F2, pTest, &f1_handlers, &HandlersF1::Pre, true);
|
||||
SH_REMOVE_HOOK_MEMFUNC(Test, F3, pTest, &f1_handlers, &HandlersF1::Pre, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(Test, F4, pTest, &f1_handlers, &HandlersF1::Pre, true);
|
||||
SH_REMOVE_HOOK_MEMFUNC(Test, F5, pTest, &f1_handlers, &HandlersF1::Pre, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(Test, F6, pTest, &f1_handlers, &HandlersF1::Pre, true);
|
||||
SH_REMOVE_HOOK_MEMFUNC(Test, F7, pTest, &f1_handlers, &HandlersF1::Pre, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(Test, F8, pTest, &f1_handlers, &HandlersF1::Pre, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(Test, F9, pTest, &f1_handlers, &HandlersF1::Pre, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(Test, F10, pTest, &f1_handlers, &HandlersF1::Pre, false);
|
||||
SH_REMOVE_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true);
|
||||
SH_REMOVE_HOOK(Test, F2, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true);
|
||||
SH_REMOVE_HOOK(Test, F3, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false);
|
||||
SH_REMOVE_HOOK(Test, F4, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true);
|
||||
SH_REMOVE_HOOK(Test, F5, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false);
|
||||
SH_REMOVE_HOOK(Test, F6, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true);
|
||||
SH_REMOVE_HOOK(Test, F7, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false);
|
||||
SH_REMOVE_HOOK(Test, F8, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false);
|
||||
SH_REMOVE_HOOK(Test, F9, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false);
|
||||
SH_REMOVE_HOOK(Test, F10, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false);
|
||||
|
||||
SH_ADD_HOOK_STATICFUNC(Test, F60, pTest, F60_Pre, false);
|
||||
SH_ADD_HOOK(Test, F60, pTest, SH_STATIC(F60_Pre), false);
|
||||
|
||||
int a = 0;
|
||||
pTest->F60(a);
|
||||
|
||||
@ -50,6 +50,11 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
// GCC's optimizer is too good. I had to add this in order to make it execute a virtual table lookup!
|
||||
class Whatever : public IGaben
|
||||
{
|
||||
};
|
||||
|
||||
SH_DECL_HOOK0_void(IGaben, EatYams, SH_NOATTRIB, 0);
|
||||
SH_DECL_HOOK1(IGaben, EatYams, const, 1, bool, const char *);
|
||||
SH_DECL_HOOK2_void_vafmt(IGaben, Vafmt1, SH_NOATTRIB, 0, bool, int);
|
||||
@ -92,14 +97,12 @@ bool TestVafmtAndOverload(std::string &error)
|
||||
GET_SHPTR(g_SHPtr);
|
||||
g_PLID = 1337;
|
||||
|
||||
IGaben gabgab;
|
||||
Whatever gabgab;
|
||||
IGaben *pGab = &gabgab;
|
||||
|
||||
SourceHook::CallClass<IGaben> *cc = SH_GET_CALLCLASS(pGab);
|
||||
|
||||
// Part 1
|
||||
SH_CALL(cc, static_cast<void (IGaben::*)()>(&IGaben::EatYams))();
|
||||
SH_CALL(cc, static_cast<bool (IGaben::*)(const char *) const>(&IGaben::EatYams))("Here!");
|
||||
SH_CALL(pGab, static_cast<void (IGaben::*)()>(&IGaben::EatYams))();
|
||||
SH_CALL(pGab, static_cast<bool (IGaben::*)(const char *) const>(&IGaben::EatYams))("Here!");
|
||||
|
||||
SH_ADD_HOOK(IGaben, EatYams, pGab, EatYams0_Handler, false);
|
||||
SH_ADD_HOOK(IGaben, EatYams, pGab, EatYams1_Handler, false);
|
||||
@ -121,9 +124,9 @@ bool TestVafmtAndOverload(std::string &error)
|
||||
|
||||
// Part 2
|
||||
pGab->Vafmt1(true, 55, "Hello %s%d%s", "BA", 1, "L");
|
||||
SH_CALL(cc, &IGaben::Vafmt1)(true, 55, "Hello %s%d%s", "BA", 1, "L");
|
||||
SH_CALL(pGab, &IGaben::Vafmt1)(true, 55, "Hello %s%d%s", "BA", 1, "L");
|
||||
pGab->Vafmt2("Hello %s%d%s", "BA", 1, "LOPAN");
|
||||
SH_CALL(cc, &IGaben::Vafmt2)("Hello %s%d%s", "BA", 1, "LOPAN");
|
||||
SH_CALL(pGab, &IGaben::Vafmt2)("Hello %s%d%s", "BA", 1, "LOPAN");
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_Vafmt_Called(1, "Hello BA1L"),
|
||||
@ -165,7 +168,5 @@ bool TestVafmtAndOverload(std::string &error)
|
||||
new State_Vafmt_Called(2, "Hello BA1LOPAN"),
|
||||
NULL), "Part 4");
|
||||
|
||||
SH_RELEASE_CALLCLASS(cc);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -47,6 +47,8 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
class DerivedDerived : public Derived { };
|
||||
|
||||
SH_DECL_HOOK0_void(Derived, Func1, SH_NOATTRIB, 0);
|
||||
SH_DECL_HOOK0_void(Derived, Func2, SH_NOATTRIB, 0);
|
||||
SH_DECL_HOOK0_void(Derived, Func3, SH_NOATTRIB, 0);
|
||||
@ -72,7 +74,7 @@ bool TestThisPtrOffs(std::string &error)
|
||||
GET_SHPTR(g_SHPtr);
|
||||
g_PLID = 1337;
|
||||
|
||||
Derived inst;
|
||||
DerivedDerived inst;
|
||||
Derived *pD = &inst;
|
||||
Base1 *pB1 = pD;
|
||||
Base2 *pB2 = pD;
|
||||
@ -85,11 +87,10 @@ bool TestThisPtrOffs(std::string &error)
|
||||
// Get a callclass for pD
|
||||
// Verify whether the this pointers are correct
|
||||
// Also call them normally to make sure that we aren't messing it up ;)
|
||||
SourceHook::CallClass<Derived> *pD_CC = SH_GET_CALLCLASS(pD);
|
||||
|
||||
SH_CALL(pD_CC, &Derived::Func1)();
|
||||
SH_CALL(pD_CC, &Derived::Func2)();
|
||||
SH_CALL(pD_CC, &Derived::Func3)();
|
||||
SH_CALL(pD, &Derived::Func1)();
|
||||
SH_CALL(pD, &Derived::Func2)();
|
||||
SH_CALL(pD, &Derived::Func3)();
|
||||
pD->Func1();
|
||||
pD->Func2();
|
||||
pD->Func3();
|
||||
@ -103,8 +104,8 @@ bool TestThisPtrOffs(std::string &error)
|
||||
new State_Func3_Called(pD),
|
||||
NULL), "Part 1");
|
||||
|
||||
SH_CALL(pD_CC, &Base1::Func1)();
|
||||
SH_CALL(pD_CC, &Base2::Func2)();
|
||||
SH_CALL(pD, &Base1::Func1)();
|
||||
SH_CALL(pD, &Base2::Func2)();
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_Func1_Called(pB1),
|
||||
@ -114,11 +115,8 @@ bool TestThisPtrOffs(std::string &error)
|
||||
// 2)
|
||||
// Get callclasses for the other ones and verify it as well
|
||||
|
||||
SourceHook::CallClass<Base1> *pB1_CC = SH_GET_CALLCLASS(pB1);
|
||||
SourceHook::CallClass<Base2> *pB2_CC = SH_GET_CALLCLASS(pB2);
|
||||
|
||||
SH_CALL(pB1_CC, &Base1::Func1)();
|
||||
SH_CALL(pB2_CC, &Base2::Func2)();
|
||||
SH_CALL(pB1, &Base1::Func1)();
|
||||
SH_CALL(pB2, &Base2::Func2)();
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_Func1_Called(pB1),
|
||||
@ -129,9 +127,9 @@ bool TestThisPtrOffs(std::string &error)
|
||||
// 3) Add hooks on them (referring to them through pD1 / Derived)
|
||||
// Check whether the hooks are called with the correct this pointer
|
||||
|
||||
SH_ADD_HOOK_STATICFUNC(Derived, Func1, pD, Handler_Func1, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Derived, Func2, pD, Handler_Func2, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Derived, Func3, pD, Handler_Func3, false);
|
||||
SH_ADD_HOOK(Derived, Func1, pD, SH_STATIC(Handler_Func1), false);
|
||||
SH_ADD_HOOK(Derived, Func2, pD, SH_STATIC(Handler_Func2), false);
|
||||
SH_ADD_HOOK(Derived, Func3, pD, SH_STATIC(Handler_Func3), false);
|
||||
|
||||
pD->Func1();
|
||||
pD->Func2();
|
||||
@ -153,17 +151,17 @@ bool TestThisPtrOffs(std::string &error)
|
||||
new State_Func2_Called(pB2),
|
||||
NULL), "Part 3");
|
||||
|
||||
SH_REMOVE_HOOK_STATICFUNC(Derived, Func1, pD, Handler_Func1, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(Derived, Func2, pD, Handler_Func2, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(Derived, Func3, pD, Handler_Func3, false);
|
||||
SH_REMOVE_HOOK(Derived, Func1, pD, SH_STATIC(Handler_Func1), false);
|
||||
SH_REMOVE_HOOK(Derived, Func2, pD, SH_STATIC(Handler_Func2), false);
|
||||
SH_REMOVE_HOOK(Derived, Func3, pD, SH_STATIC(Handler_Func3), false);
|
||||
|
||||
// 4)
|
||||
// Now add the hooks on Base1 and Base2 and check again
|
||||
|
||||
// Note that the new implicit_cast should convert the pD to Base1*/Base2* :)
|
||||
SH_ADD_HOOK_STATICFUNC(Base1, Func1, pD, Handler_Func1, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Base2, Func2, pD, Handler_Func2, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Derived, Func3, pD, Handler_Func3, false);
|
||||
SH_ADD_HOOK(Base1, Func1, pD, SH_STATIC(Handler_Func1), false);
|
||||
SH_ADD_HOOK(Base2, Func2, pD, SH_STATIC(Handler_Func2), false);
|
||||
SH_ADD_HOOK(Derived, Func3, pD, SH_STATIC(Handler_Func3), false);
|
||||
|
||||
pD->Func1();
|
||||
pD->Func2();
|
||||
@ -186,18 +184,18 @@ bool TestThisPtrOffs(std::string &error)
|
||||
new State_Func2_Called(pB2),
|
||||
NULL), "Part 4");
|
||||
|
||||
SH_REMOVE_HOOK_STATICFUNC(Base1, Func1, pD, Handler_Func1, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(Base2, Func2, pD, Handler_Func2, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(Derived, Func3, pD, Handler_Func3, false);
|
||||
SH_REMOVE_HOOK(Base1, Func1, pD, SH_STATIC(Handler_Func1), false);
|
||||
SH_REMOVE_HOOK(Base2, Func2, pD, SH_STATIC(Handler_Func2), false);
|
||||
SH_REMOVE_HOOK(Derived, Func3, pD, SH_STATIC(Handler_Func3), false);
|
||||
|
||||
|
||||
// 5)
|
||||
// Add some hooks, and use callclasses
|
||||
|
||||
// 5.1) First off, add all of them on pD
|
||||
SH_ADD_HOOK_STATICFUNC(Derived, Func1, pD, Handler_Func1, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Derived, Func2, pD, Handler_Func2, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Derived, Func3, pD, Handler_Func3, false);
|
||||
SH_ADD_HOOK(Derived, Func1, pD, SH_STATIC(Handler_Func1), false);
|
||||
SH_ADD_HOOK(Derived, Func2, pD, SH_STATIC(Handler_Func2), false);
|
||||
SH_ADD_HOOK(Derived, Func3, pD, SH_STATIC(Handler_Func3), false);
|
||||
|
||||
pD->Func1();
|
||||
pD->Func2();
|
||||
@ -212,11 +210,11 @@ bool TestThisPtrOffs(std::string &error)
|
||||
new State_Func3_Called(pD),
|
||||
NULL), "Part 5.1");
|
||||
|
||||
SH_CALL(pD_CC, &Derived::Func1)();
|
||||
SH_CALL(pD_CC, &Derived::Func2)();
|
||||
SH_CALL(pD_CC, &Derived::Func3)();
|
||||
SH_CALL(pB1_CC, &Base1::Func1)();
|
||||
SH_CALL(pB2_CC, &Base2::Func2)();
|
||||
SH_CALL(pD, &Derived::Func1)();
|
||||
SH_CALL(pD, &Derived::Func2)();
|
||||
SH_CALL(pD, &Derived::Func3)();
|
||||
SH_CALL(pB1, &Base1::Func1)();
|
||||
SH_CALL(pB2, &Base2::Func2)();
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_Func1_Called(pB1),
|
||||
@ -226,13 +224,9 @@ bool TestThisPtrOffs(std::string &error)
|
||||
new State_Func2_Called(pB2),
|
||||
NULL), "Part 5.2");
|
||||
|
||||
SH_REMOVE_HOOK_STATICFUNC(Derived, Func1, pD, Handler_Func1, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(Derived, Func2, pD, Handler_Func2, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(Derived, Func3, pD, Handler_Func3, false);
|
||||
|
||||
SH_RELEASE_CALLCLASS(pB1_CC);
|
||||
SH_RELEASE_CALLCLASS(pB2_CC);
|
||||
SH_RELEASE_CALLCLASS(pD_CC);
|
||||
SH_REMOVE_HOOK(Derived, Func1, pD, SH_STATIC(Handler_Func1), false);
|
||||
SH_REMOVE_HOOK(Derived, Func2, pD, SH_STATIC(Handler_Func2), false);
|
||||
SH_REMOVE_HOOK(Derived, Func3, pD, SH_STATIC(Handler_Func3), false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -40,6 +40,11 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
// GCC's optimizer is too good. I had to add this in order to make it execute a virtual table lookup!
|
||||
class Whatever : public Test
|
||||
{
|
||||
};
|
||||
|
||||
SH_DECL_HOOK0_void(Test, Func1, SH_NOATTRIB, 0);
|
||||
SH_DECL_HOOK0_void(Test, Func2, SH_NOATTRIB, 0);
|
||||
SH_DECL_HOOK0_void(Test, Func3, SH_NOATTRIB, 0);
|
||||
@ -63,14 +68,14 @@ bool TestPlugSys(std::string &error)
|
||||
GET_SHPTR(g_SHPtr);
|
||||
g_PLID = 1;
|
||||
|
||||
Test inst;
|
||||
Whatever inst;
|
||||
Test *pInst = &inst;
|
||||
|
||||
// 1)
|
||||
// Add hooks, then issue a complete shutdown
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func1, pInst, Handler_Func1, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func2, pInst, Handler_Func2, true);
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func3, pInst, Handler_Func3, false);
|
||||
SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false);
|
||||
SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true);
|
||||
SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false);
|
||||
|
||||
pInst->Func1();
|
||||
pInst->Func2();
|
||||
@ -101,23 +106,23 @@ bool TestPlugSys(std::string &error)
|
||||
// Add hooks from "different plugins", then shutdown the plugins
|
||||
|
||||
g_PLID = 1;
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func1, pInst, Handler_Func1, false);
|
||||
SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false);
|
||||
g_PLID = 2;
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func2, pInst, Handler_Func2, true);
|
||||
SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true);
|
||||
g_PLID = 3;
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func3, pInst, Handler_Func3, false);
|
||||
SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false);
|
||||
|
||||
g_PLID = 1;
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func2, pInst, Handler_Func2, true);
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func3, pInst, Handler_Func3, false);
|
||||
SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true);
|
||||
SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false);
|
||||
|
||||
g_PLID = 2;
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func1, pInst, Handler_Func1, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func3, pInst, Handler_Func3, false);
|
||||
SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false);
|
||||
SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false);
|
||||
|
||||
g_PLID = 3;
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func1, pInst, Handler_Func1, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func2, pInst, Handler_Func2, true);
|
||||
SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false);
|
||||
SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true);
|
||||
|
||||
pInst->Func1();
|
||||
pInst->Func2();
|
||||
@ -237,23 +242,23 @@ bool TestPlugSys(std::string &error)
|
||||
// Add hooks from "different plugins", then pause the plugins
|
||||
|
||||
g_PLID = 1;
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func1, pInst, Handler_Func1, false);
|
||||
SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false);
|
||||
g_PLID = 2;
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func2, pInst, Handler_Func2, true);
|
||||
SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true);
|
||||
g_PLID = 3;
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func3, pInst, Handler_Func3, false);
|
||||
SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false);
|
||||
|
||||
g_PLID = 1;
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func2, pInst, Handler_Func2, true);
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func3, pInst, Handler_Func3, false);
|
||||
SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true);
|
||||
SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false);
|
||||
|
||||
g_PLID = 2;
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func1, pInst, Handler_Func1, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func3, pInst, Handler_Func3, false);
|
||||
SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false);
|
||||
SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false);
|
||||
|
||||
g_PLID = 3;
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func1, pInst, Handler_Func1, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func2, pInst, Handler_Func2, true);
|
||||
SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false);
|
||||
SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true);
|
||||
|
||||
pInst->Func1();
|
||||
pInst->Func2();
|
||||
|
||||
@ -44,7 +44,7 @@ bool TestBail(std::string &error)
|
||||
|
||||
g_Gabgab = new IGaben;
|
||||
|
||||
SH_ADD_HOOK_STATICFUNC(IGaben, EatYams, g_Gabgab, EatYams_Handler1, false);
|
||||
SH_ADD_HOOK(IGaben, EatYams, g_Gabgab, SH_STATIC(EatYams_Handler1), false);
|
||||
|
||||
ADD_STATE(State_EatYams_Return(g_Gabgab->EatYams(0xDEAD)));
|
||||
|
||||
@ -75,7 +75,7 @@ bool TestBail(std::string &error)
|
||||
new State_EatYams_Return(5),
|
||||
NULL), "Part 3");
|
||||
|
||||
SH_REMOVE_HOOK_STATICFUNC(IGaben, EatYams, g_Gabgab, EatYams_Handler1, false);
|
||||
SH_REMOVE_HOOK(IGaben, EatYams, g_Gabgab, SH_STATIC(EatYams_Handler1), false);
|
||||
|
||||
ADD_STATE(State_EatYams_Return(g_Gabgab->EatYams(0xDEAD)));
|
||||
|
||||
@ -97,7 +97,7 @@ bool TestBail(std::string &error)
|
||||
new State_EatYams_Called(0xBEEF),
|
||||
NULL), "Part 5");
|
||||
|
||||
SH_ADD_HOOK_STATICFUNC(IGaben, EatYams, g_Gabgab, EatYams_Handler1, false);
|
||||
SH_ADD_HOOK(IGaben, EatYams, g_Gabgab, SH_STATIC(EatYams_Handler1), false);
|
||||
|
||||
ADD_STATE(State_EatYams_Return(g_Gabgab->EatYams(0xDEAD)));
|
||||
|
||||
|
||||
@ -24,8 +24,8 @@ namespace N_TestBail
|
||||
{
|
||||
g_PLID = 2;
|
||||
|
||||
SH_ADD_HOOK_STATICFUNC(IGaben, EatYams, g_Gabgab, EatYams_Handler2, false);
|
||||
SH_ADD_HOOK_STATICFUNC(IGaben, EatYams, g_Gabgab, EatYams_Handler3, false);
|
||||
SH_ADD_HOOK(IGaben, EatYams, g_Gabgab, SH_STATIC(EatYams_Handler2), false);
|
||||
SH_ADD_HOOK(IGaben, EatYams, g_Gabgab, SH_STATIC(EatYams_Handler3), false);
|
||||
|
||||
int ret = g_Gabgab->EatYams(0xDEAD);
|
||||
|
||||
|
||||
@ -52,6 +52,11 @@ namespace
|
||||
{
|
||||
ADD_STATE(State_Func5_Called(reinterpret_cast<void*>(this)));
|
||||
}
|
||||
|
||||
};
|
||||
// GCC's optimizer is too good. I had to add this in order to make it execute a virtual table lookup!
|
||||
class Whatever : public TheWall
|
||||
{
|
||||
};
|
||||
|
||||
SH_DECL_HOOK0_void(TheWall, Func1, SH_NOATTRIB, 0);
|
||||
@ -106,11 +111,9 @@ bool TestManual(std::string &error)
|
||||
GET_SHPTR(g_SHPtr);
|
||||
g_PLID = 1337;
|
||||
|
||||
TheWall inst;
|
||||
Whatever inst;
|
||||
TheWall *p = &inst;
|
||||
|
||||
SourceHook::ManualCallClass *cc = SH_GET_MCALLCLASS(p, sizeof(void*));
|
||||
|
||||
// 1)
|
||||
// Call each function
|
||||
p->Func1();
|
||||
@ -129,14 +132,14 @@ bool TestManual(std::string &error)
|
||||
|
||||
// 1.1)
|
||||
// Now call each function through the manual call class, using the hook decl and manually
|
||||
SH_MCALL(cc, TheWall_Func1)();
|
||||
SH_MCALL2(cc, MFP_Func1(), 0, 0, 0)();
|
||||
SH_MCALL(cc, TheWall_Func2)(200);
|
||||
SH_MCALL2(cc, MFP_Func2(), 1, 0, 0)(200);
|
||||
ADD_STATE(State_Return(SH_MCALL(cc, TheWall_Func3)()));
|
||||
ADD_STATE(State_Return(SH_MCALL2(cc, MFP_Func3(), 2, 0, 0)()));
|
||||
ADD_STATE(State_Return(SH_MCALL(cc, TheWall_Func4)(400)));
|
||||
ADD_STATE(State_Return(SH_MCALL2(cc, MFP_Func4(), 3, 0, 0)(400)));
|
||||
SH_MCALL(p, TheWall_Func1)();
|
||||
SH_MCALL2(p, MFP_Func1(), 0, 0, 0)();
|
||||
SH_MCALL(p, TheWall_Func2)(200);
|
||||
SH_MCALL2(p, MFP_Func2(), 1, 0, 0)(200);
|
||||
ADD_STATE(State_Return(SH_MCALL(p, TheWall_Func3)()));
|
||||
ADD_STATE(State_Return(SH_MCALL2(p, MFP_Func3(), 2, 0, 0)()));
|
||||
ADD_STATE(State_Return(SH_MCALL(p, TheWall_Func4)(400)));
|
||||
ADD_STATE(State_Return(SH_MCALL2(p, MFP_Func4(), 3, 0, 0)(400)));
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_Func1_Called(p),
|
||||
@ -153,12 +156,23 @@ bool TestManual(std::string &error)
|
||||
new State_Return(4),
|
||||
NULL), "Part 1.1");
|
||||
|
||||
// Compat: really get a manual call class!
|
||||
SourceHook::ManualCallClass *pCC = SH_GET_MCALLCLASS(p, sizeof(void*));
|
||||
SH_MCALL(pCC, TheWall_Func1)();
|
||||
SH_MCALL2(pCC, MFP_Func1(), 0, 0, 0)();
|
||||
CHECK_STATES((&g_States,
|
||||
new State_Func1_Called(p),
|
||||
new State_Func1_Called(p),
|
||||
NULL), "Part 1.2");
|
||||
|
||||
SH_RELEASE_CALLCLASS(pCC);
|
||||
|
||||
// 2)
|
||||
// Hook each function normally, call them
|
||||
SH_ADD_HOOK_STATICFUNC(TheWall, Func1, p, Handler_Func1, false);
|
||||
SH_ADD_HOOK_STATICFUNC(TheWall, Func2, p, Handler_Func2, false);
|
||||
SH_ADD_HOOK_STATICFUNC(TheWall, Func3, p, Handler_Func3, false);
|
||||
SH_ADD_HOOK_STATICFUNC(TheWall, Func4, p, Handler_Func4, false);
|
||||
SH_ADD_HOOK(TheWall, Func1, p, SH_STATIC(Handler_Func1), false);
|
||||
SH_ADD_HOOK(TheWall, Func2, p, SH_STATIC(Handler_Func2), false);
|
||||
SH_ADD_HOOK(TheWall, Func3, p, SH_STATIC(Handler_Func3), false);
|
||||
SH_ADD_HOOK(TheWall, Func4, p, SH_STATIC(Handler_Func4), false);
|
||||
|
||||
p->Func1();
|
||||
p->Func2(200);
|
||||
@ -181,14 +195,14 @@ bool TestManual(std::string &error)
|
||||
// Call them through the mcallclass
|
||||
// 2.1)
|
||||
// Now call each function through the manual call class, using the hook decl and manually
|
||||
SH_MCALL(cc, TheWall_Func1)();
|
||||
SH_MCALL2(cc, MFP_Func1(), 0, 0, 0)();
|
||||
SH_MCALL(cc, TheWall_Func2)(200);
|
||||
SH_MCALL2(cc, MFP_Func2(), 1, 0, 0)(200);
|
||||
ADD_STATE(State_Return(SH_MCALL(cc, TheWall_Func3)()));
|
||||
ADD_STATE(State_Return(SH_MCALL2(cc, MFP_Func3(), 2, 0, 0)()));
|
||||
ADD_STATE(State_Return(SH_MCALL(cc, TheWall_Func4)(400)));
|
||||
ADD_STATE(State_Return(SH_MCALL2(cc, MFP_Func4(), 3, 0, 0)(400)));
|
||||
SH_MCALL(p, TheWall_Func1)();
|
||||
SH_MCALL2(p, MFP_Func1(), 0, 0, 0)();
|
||||
SH_MCALL(p, TheWall_Func2)(200);
|
||||
SH_MCALL2(p, MFP_Func2(), 1, 0, 0)(200);
|
||||
ADD_STATE(State_Return(SH_MCALL(p, TheWall_Func3)()));
|
||||
ADD_STATE(State_Return(SH_MCALL2(p, MFP_Func3(), 2, 0, 0)()));
|
||||
ADD_STATE(State_Return(SH_MCALL(p, TheWall_Func4)(400)));
|
||||
ADD_STATE(State_Return(SH_MCALL2(p, MFP_Func4(), 3, 0, 0)(400)));
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_Func1_Called(p),
|
||||
@ -206,18 +220,18 @@ bool TestManual(std::string &error)
|
||||
NULL), "Part 2.1");
|
||||
|
||||
// Unhook them
|
||||
SH_REMOVE_HOOK_STATICFUNC(TheWall, Func1, p, Handler_Func1, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(TheWall, Func2, p, Handler_Func2, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(TheWall, Func3, p, Handler_Func3, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(TheWall, Func4, p, Handler_Func4, false);
|
||||
SH_REMOVE_HOOK(TheWall, Func1, p, SH_STATIC(Handler_Func1), false);
|
||||
SH_REMOVE_HOOK(TheWall, Func2, p, SH_STATIC(Handler_Func2), false);
|
||||
SH_REMOVE_HOOK(TheWall, Func3, p, SH_STATIC(Handler_Func3), false);
|
||||
SH_REMOVE_HOOK(TheWall, Func4, p, SH_STATIC(Handler_Func4), false);
|
||||
|
||||
// 3)
|
||||
// Hook each function manually, call them
|
||||
|
||||
SH_ADD_MANUALHOOK_STATICFUNC(TheWall_Func1, p, Handler_Func1, false);
|
||||
SH_ADD_MANUALHOOK_STATICFUNC(TheWall_Func2, p, Handler_Func2, false);
|
||||
SH_ADD_MANUALHOOK_STATICFUNC(TheWall_Func3, p, Handler_Func3, false);
|
||||
SH_ADD_MANUALHOOK_STATICFUNC(TheWall_Func4, p, Handler_Func4, false);
|
||||
SH_ADD_MANUALHOOK(TheWall_Func1, p, SH_STATIC(Handler_Func1), false);
|
||||
SH_ADD_MANUALHOOK(TheWall_Func2, p, SH_STATIC(Handler_Func2), false);
|
||||
SH_ADD_MANUALHOOK(TheWall_Func3, p, SH_STATIC(Handler_Func3), false);
|
||||
SH_ADD_MANUALHOOK(TheWall_Func4, p, SH_STATIC(Handler_Func4), false);
|
||||
|
||||
p->Func1();
|
||||
p->Func2(200);
|
||||
@ -242,14 +256,14 @@ bool TestManual(std::string &error)
|
||||
// Call them through the mcallclass
|
||||
// 3.1)
|
||||
// Now call each function through the manual call class, using the hook decl and manually
|
||||
SH_MCALL(cc, TheWall_Func1)();
|
||||
SH_MCALL2(cc, MFP_Func1(), 0, 0, 0)();
|
||||
SH_MCALL(cc, TheWall_Func2)(200);
|
||||
SH_MCALL2(cc, MFP_Func2(), 1, 0, 0)(200);
|
||||
ADD_STATE(State_Return(SH_MCALL(cc, TheWall_Func3)()));
|
||||
ADD_STATE(State_Return(SH_MCALL2(cc, MFP_Func3(), 2, 0, 0)()));
|
||||
ADD_STATE(State_Return(SH_MCALL(cc, TheWall_Func4)(400)));
|
||||
ADD_STATE(State_Return(SH_MCALL2(cc, MFP_Func4(), 3, 0, 0)(400)));
|
||||
SH_MCALL(p, TheWall_Func1)();
|
||||
SH_MCALL2(p, MFP_Func1(), 0, 0, 0)();
|
||||
SH_MCALL(p, TheWall_Func2)(200);
|
||||
SH_MCALL2(p, MFP_Func2(), 1, 0, 0)(200);
|
||||
ADD_STATE(State_Return(SH_MCALL(p, TheWall_Func3)()));
|
||||
ADD_STATE(State_Return(SH_MCALL2(p, MFP_Func3(), 2, 0, 0)()));
|
||||
ADD_STATE(State_Return(SH_MCALL(p, TheWall_Func4)(400)));
|
||||
ADD_STATE(State_Return(SH_MCALL2(p, MFP_Func4(), 3, 0, 0)(400)));
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_Func1_Called(p),
|
||||
@ -267,10 +281,10 @@ bool TestManual(std::string &error)
|
||||
NULL), "Part 3.1");
|
||||
|
||||
// Unhook them
|
||||
SH_REMOVE_MANUALHOOK_STATICFUNC(TheWall_Func1, p, Handler_Func1, false);
|
||||
SH_REMOVE_MANUALHOOK_STATICFUNC(TheWall_Func2, p, Handler_Func2, false);
|
||||
SH_REMOVE_MANUALHOOK_STATICFUNC(TheWall_Func3, p, Handler_Func3, false);
|
||||
SH_REMOVE_MANUALHOOK_STATICFUNC(TheWall_Func4, p, Handler_Func4, false);
|
||||
SH_REMOVE_MANUALHOOK(TheWall_Func1, p, SH_STATIC(Handler_Func1), false);
|
||||
SH_REMOVE_MANUALHOOK(TheWall_Func2, p, SH_STATIC(Handler_Func2), false);
|
||||
SH_REMOVE_MANUALHOOK(TheWall_Func3, p, SH_STATIC(Handler_Func3), false);
|
||||
SH_REMOVE_MANUALHOOK(TheWall_Func4, p, SH_STATIC(Handler_Func4), false);
|
||||
|
||||
// 4)
|
||||
// Hook each function manually, then normally, call, unhook
|
||||
@ -278,7 +292,7 @@ bool TestManual(std::string &error)
|
||||
AnotherBrick handler_inst;
|
||||
|
||||
// Why this?
|
||||
// 1) tests sh_add_manualhook_memfunc
|
||||
// 1) tests sh_add_manualhook
|
||||
// 2) in my tests, the proto of the manual hook was not equal to the proto of the auto hook
|
||||
// (because there are no attribs for manual hooks).
|
||||
// sourcehook.cpp did a !strcmp(..), so it assigned a new hook manager even though there
|
||||
@ -287,15 +301,15 @@ bool TestManual(std::string &error)
|
||||
// The problem with this is that returning MRES_SUPERCEDE (as AnotherBrick::Handler_Func1
|
||||
// does) will supercede the second hook func from being called - thus bypassing the call
|
||||
// of the auto hook here.
|
||||
SH_ADD_MANUALHOOK_MEMFUNC(TheWall_Func1, p, &handler_inst, &AnotherBrick::Handler_Func1, false);
|
||||
SH_ADD_MANUALHOOK_STATICFUNC(TheWall_Func2, p, Handler_Func2, false);
|
||||
SH_ADD_MANUALHOOK_STATICFUNC(TheWall_Func3, p, Handler_Func3, false);
|
||||
SH_ADD_MANUALHOOK_STATICFUNC(TheWall_Func4, p, Handler_Func4, false);
|
||||
SH_ADD_MANUALHOOK(TheWall_Func1, p, SH_MEMBER(&handler_inst, &AnotherBrick::Handler_Func1), false);
|
||||
SH_ADD_MANUALHOOK(TheWall_Func2, p, SH_STATIC(Handler_Func2), false);
|
||||
SH_ADD_MANUALHOOK(TheWall_Func3, p, SH_STATIC(Handler_Func3), false);
|
||||
SH_ADD_MANUALHOOK(TheWall_Func4, p, SH_STATIC(Handler_Func4), false);
|
||||
|
||||
SH_ADD_HOOK_STATICFUNC(TheWall, Func1, p, Handler_Func1, false);
|
||||
SH_ADD_HOOK_STATICFUNC(TheWall, Func2, p, Handler_Func2, false);
|
||||
SH_ADD_HOOK_STATICFUNC(TheWall, Func3, p, Handler_Func3, false);
|
||||
SH_ADD_HOOK_STATICFUNC(TheWall, Func4, p, Handler_Func4, false);
|
||||
SH_ADD_HOOK(TheWall, Func1, p, SH_STATIC(Handler_Func1), false);
|
||||
SH_ADD_HOOK(TheWall, Func2, p, SH_STATIC(Handler_Func2), false);
|
||||
SH_ADD_HOOK(TheWall, Func3, p, SH_STATIC(Handler_Func3), false);
|
||||
SH_ADD_HOOK(TheWall, Func4, p, SH_STATIC(Handler_Func4), false);
|
||||
|
||||
p->Func1();
|
||||
p->Func2(200);
|
||||
@ -319,19 +333,19 @@ bool TestManual(std::string &error)
|
||||
new State_Return(4),
|
||||
NULL), "Part 4");
|
||||
|
||||
SH_REMOVE_MANUALHOOK_MEMFUNC(TheWall_Func1, p, &handler_inst, &AnotherBrick::Handler_Func1, false);
|
||||
SH_REMOVE_MANUALHOOK_STATICFUNC(TheWall_Func2, p, Handler_Func2, false);
|
||||
SH_REMOVE_MANUALHOOK_STATICFUNC(TheWall_Func3, p, Handler_Func3, false);
|
||||
SH_REMOVE_MANUALHOOK_STATICFUNC(TheWall_Func4, p, Handler_Func4, false);
|
||||
SH_REMOVE_MANUALHOOK(TheWall_Func1, p, SH_MEMBER(&handler_inst, &AnotherBrick::Handler_Func1), false);
|
||||
SH_REMOVE_MANUALHOOK(TheWall_Func2, p, SH_STATIC(Handler_Func2), false);
|
||||
SH_REMOVE_MANUALHOOK(TheWall_Func3, p, SH_STATIC(Handler_Func3), false);
|
||||
SH_REMOVE_MANUALHOOK(TheWall_Func4, p, SH_STATIC(Handler_Func4), false);
|
||||
|
||||
SH_REMOVE_HOOK_STATICFUNC(TheWall, Func1, p, Handler_Func1, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(TheWall, Func2, p, Handler_Func2, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(TheWall, Func3, p, Handler_Func3, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(TheWall, Func4, p, Handler_Func4, false);
|
||||
SH_REMOVE_HOOK(TheWall, Func1, p, SH_STATIC(Handler_Func1), false);
|
||||
SH_REMOVE_HOOK(TheWall, Func2, p, SH_STATIC(Handler_Func2), false);
|
||||
SH_REMOVE_HOOK(TheWall, Func3, p, SH_STATIC(Handler_Func3), false);
|
||||
SH_REMOVE_HOOK(TheWall, Func4, p, SH_STATIC(Handler_Func4), false);
|
||||
|
||||
// 5) Reconfigure TheWall_Func1 to actually hook Func5:
|
||||
SH_MANUALHOOK_RECONFIGURE(TheWall_Func1, 4, 0, 0);
|
||||
SH_ADD_MANUALHOOK_STATICFUNC(TheWall_Func1, p, Handler_Func1, false);
|
||||
SH_ADD_MANUALHOOK(TheWall_Func1, p, SH_STATIC(Handler_Func1), false);
|
||||
|
||||
p->Func5();
|
||||
|
||||
|
||||
@ -53,7 +53,7 @@ bool TestMulti(std::string &error)
|
||||
|
||||
|
||||
for (unsigned int i=0; i<10; i++)
|
||||
SH_ADD_HOOK_STATICFUNC(VMultiTest, HookTarget, pv[i], HookFunction, false);
|
||||
SH_ADD_HOOK(VMultiTest, HookTarget, pv[i], SH_STATIC(HookFunction), false);
|
||||
|
||||
pv[0]->HookTarget();
|
||||
|
||||
@ -72,7 +72,7 @@ bool TestMulti(std::string &error)
|
||||
}
|
||||
}
|
||||
|
||||
SH_REMOVE_HOOK_STATICFUNC(VMultiTest, HookTarget, pv[0], HookFunction, false);
|
||||
SH_REMOVE_HOOK(VMultiTest, HookTarget, pv[0], SH_STATIC(HookFunction), false);
|
||||
|
||||
for (unsigned int i=1; i<10; i++)
|
||||
pv[i]->HookTarget();
|
||||
@ -96,7 +96,7 @@ bool TestMulti(std::string &error)
|
||||
|
||||
for (unsigned int i=1; i<10; i++)
|
||||
{
|
||||
SH_REMOVE_HOOK_STATICFUNC(VMultiTest, HookTarget, pv[1], HookFunction, false);
|
||||
SH_REMOVE_HOOK(VMultiTest, HookTarget, pv[1], SH_STATIC(HookFunction), false);
|
||||
delete pv[i];
|
||||
}
|
||||
|
||||
|
||||
@ -48,6 +48,11 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
// GCC's optimizer is too good. I had to add this in order to make it execute a virtual table lookup!
|
||||
struct Whatever : Test
|
||||
{
|
||||
};
|
||||
|
||||
void Handler1_Func1(int a)
|
||||
{
|
||||
ADD_STATE(State_H1_Func1(a));
|
||||
@ -119,12 +124,12 @@ bool TestRecall(std::string &error)
|
||||
GET_SHPTR(g_SHPtr);
|
||||
g_PLID = 1337;
|
||||
|
||||
Test inst;
|
||||
Whatever inst;
|
||||
Test *ptr = &inst;
|
||||
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func1, ptr, Handler1_Func1, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func1, ptr, Handler2_Func1, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func1, ptr, HandlerPost_Func1, true);
|
||||
SH_ADD_HOOK(Test, Func1, ptr, SH_STATIC(Handler1_Func1), false);
|
||||
SH_ADD_HOOK(Test, Func1, ptr, SH_STATIC(Handler2_Func1), false);
|
||||
SH_ADD_HOOK(Test, Func1, ptr, SH_STATIC(HandlerPost_Func1), true);
|
||||
|
||||
ptr->Func1(77);
|
||||
|
||||
@ -135,10 +140,10 @@ bool TestRecall(std::string &error)
|
||||
new State_HP_Func1(0, ptr),
|
||||
NULL), "Part 1");
|
||||
|
||||
SH_REMOVE_HOOK_STATICFUNC(Test, Func1, ptr, Handler1_Func1, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func1, ptr, Handler2_Func1, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func1, ptr, Handler2_Func1, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func1, ptr, Handler2_Func1, false);
|
||||
SH_REMOVE_HOOK(Test, Func1, ptr, SH_STATIC(Handler1_Func1), false);
|
||||
SH_ADD_HOOK(Test, Func1, ptr, SH_STATIC(Handler2_Func1), false);
|
||||
SH_ADD_HOOK(Test, Func1, ptr, SH_STATIC(Handler2_Func1), false);
|
||||
SH_ADD_HOOK(Test, Func1, ptr, SH_STATIC(Handler2_Func1), false);
|
||||
|
||||
ptr->Func1(77);
|
||||
|
||||
@ -151,8 +156,8 @@ bool TestRecall(std::string &error)
|
||||
new State_HP_Func1(57, ptr),
|
||||
NULL), "Part 2");
|
||||
|
||||
SH_REMOVE_HOOK_STATICFUNC(Test, Func1, ptr, Handler2_Func1, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(Test, Func1, ptr, HandlerPost_Func1, true);
|
||||
SH_REMOVE_HOOK(Test, Func1, ptr, SH_STATIC(Handler2_Func1), false);
|
||||
SH_REMOVE_HOOK(Test, Func1, ptr, SH_STATIC(HandlerPost_Func1), true);
|
||||
|
||||
ptr->Func1(77);
|
||||
|
||||
@ -162,8 +167,8 @@ bool TestRecall(std::string &error)
|
||||
|
||||
// Func2
|
||||
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func2, ptr, Handler1_Func2, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func2, ptr, HandlerPost_Func2, true);
|
||||
SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(Handler1_Func2), false);
|
||||
SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost_Func2), true);
|
||||
|
||||
int a = ptr->Func2(77);
|
||||
CHECK_STATES((&g_States,
|
||||
@ -175,8 +180,8 @@ bool TestRecall(std::string &error)
|
||||
CHECK_COND(a == 500, "Part 4.1");
|
||||
|
||||
// Func2, with other handler
|
||||
SH_REMOVE_HOOK_STATICFUNC(Test, Func2, ptr, Handler1_Func2, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func2, ptr, Handler2_Func2, false);
|
||||
SH_REMOVE_HOOK(Test, Func2, ptr, SH_STATIC(Handler1_Func2), false);
|
||||
SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(Handler2_Func2), false);
|
||||
|
||||
a = ptr->Func2(77);
|
||||
CHECK_STATES((&g_States,
|
||||
@ -191,9 +196,9 @@ bool TestRecall(std::string &error)
|
||||
|
||||
// 1) WITH OVERRIDE
|
||||
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func2, ptr, Handler1_Func22, false);
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func2, ptr, HandlerPost1A_Func22, true);
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func2, ptr, HandlerPost2_Func22, true);
|
||||
SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(Handler1_Func22), false);
|
||||
SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost1A_Func22), true);
|
||||
SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost2_Func22), true);
|
||||
|
||||
a = ptr->Func2(10, 11);
|
||||
CHECK_STATES((&g_States,
|
||||
@ -206,11 +211,11 @@ bool TestRecall(std::string &error)
|
||||
CHECK_COND(a == 0, "Part 5.1");
|
||||
|
||||
// 2) WITH IGNORE
|
||||
SH_REMOVE_HOOK_STATICFUNC(Test, Func2, ptr, HandlerPost1A_Func22, true);
|
||||
SH_REMOVE_HOOK_STATICFUNC(Test, Func2, ptr, HandlerPost2_Func22, true);
|
||||
SH_REMOVE_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost1A_Func22), true);
|
||||
SH_REMOVE_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost2_Func22), true);
|
||||
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func2, ptr, HandlerPost1_Func22, true);
|
||||
SH_ADD_HOOK_STATICFUNC(Test, Func2, ptr, HandlerPost2_Func22, true);
|
||||
SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost1_Func22), true);
|
||||
SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost2_Func22), true);
|
||||
|
||||
a = ptr->Func2(10, 11);
|
||||
CHECK_STATES((&g_States,
|
||||
|
||||
@ -82,6 +82,7 @@ namespace
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
struct C2
|
||||
{
|
||||
virtual void F()
|
||||
@ -167,6 +168,15 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
struct C1_Derived : public C1 {};
|
||||
struct C2_Derived : public C2 {};
|
||||
struct C3_Derived : public C3 {};
|
||||
struct C4_Derived : public C4 {};
|
||||
struct C5_Derived : public C5 {};
|
||||
struct C6_Derived : public C6 {};
|
||||
struct C7_Derived : public C7 {};
|
||||
struct C8_Derived : public C8 {};
|
||||
|
||||
SH_DECL_HOOK0_void(C1, F, SH_NOATTRIB, 0);
|
||||
SH_DECL_HOOK0(C1, G, SH_NOATTRIB, 0, int);
|
||||
SH_DECL_HOOK0_void(C2, F, SH_NOATTRIB, 0);
|
||||
@ -258,9 +268,9 @@ namespace
|
||||
void Handler_C7_F()
|
||||
{
|
||||
if (g_TestID == 1 || g_TestID == 2)
|
||||
SH_REMOVE_HOOK_STATICFUNC(C4, G, g_pC4, Handler2_C4_G, false);
|
||||
SH_REMOVE_HOOK(C4, G, g_pC4, SH_STATIC(Handler2_C4_G), false);
|
||||
if (g_TestID == 2)
|
||||
SH_REMOVE_HOOK_STATICFUNC(C4, G, g_pC4, Handler_C4_G, false);
|
||||
SH_REMOVE_HOOK(C4, G, g_pC4, SH_STATIC(Handler_C4_G), false);
|
||||
|
||||
ADD_STATE(State_H_C7_F(META_IFACEPTR(C7)));
|
||||
g_pC7->G();
|
||||
@ -282,14 +292,14 @@ namespace
|
||||
return 8;
|
||||
}
|
||||
|
||||
C1 g_C1;
|
||||
C2 g_C2;
|
||||
C3 g_C3;
|
||||
C4 g_C4;
|
||||
C5 g_C5;
|
||||
C6 g_C6;
|
||||
C7 g_C7;
|
||||
C8 g_C8;
|
||||
C1_Derived g_C1;
|
||||
C2_Derived g_C2;
|
||||
C3_Derived g_C3;
|
||||
C4_Derived g_C4;
|
||||
C5_Derived g_C5;
|
||||
C6_Derived g_C6;
|
||||
C7_Derived g_C7;
|
||||
C8_Derived g_C8;
|
||||
}
|
||||
|
||||
bool TestReentr(std::string &error)
|
||||
@ -306,22 +316,22 @@ bool TestReentr(std::string &error)
|
||||
g_pC7 = &g_C7;
|
||||
g_pC8 = &g_C8;
|
||||
|
||||
SH_ADD_HOOK_STATICFUNC(C1, F, g_pC1, Handler_C1_F, false);
|
||||
SH_ADD_HOOK_STATICFUNC(C1, G, g_pC1, Handler_C1_G, false);
|
||||
SH_ADD_HOOK_STATICFUNC(C2, F, g_pC2, Handler_C2_F, false);
|
||||
SH_ADD_HOOK_STATICFUNC(C2, G, g_pC2, Handler_C2_G, false);
|
||||
SH_ADD_HOOK_STATICFUNC(C3, F, g_pC3, Handler_C3_F, false);
|
||||
SH_ADD_HOOK_STATICFUNC(C3, G, g_pC3, Handler_C3_G, false);
|
||||
SH_ADD_HOOK_STATICFUNC(C4, F, g_pC4, Handler_C4_F, false);
|
||||
SH_ADD_HOOK_STATICFUNC(C4, G, g_pC4, Handler_C4_G, false);
|
||||
SH_ADD_HOOK_STATICFUNC(C5, F, g_pC5, Handler_C5_F, false);
|
||||
SH_ADD_HOOK_STATICFUNC(C5, G, g_pC5, Handler_C5_G, false);
|
||||
SH_ADD_HOOK_STATICFUNC(C6, F, g_pC6, Handler_C6_F, false);
|
||||
SH_ADD_HOOK_STATICFUNC(C6, G, g_pC6, Handler_C6_G, false);
|
||||
SH_ADD_HOOK_STATICFUNC(C7, F, g_pC7, Handler_C7_F, false);
|
||||
SH_ADD_HOOK_STATICFUNC(C7, G, g_pC7, Handler_C7_G, false);
|
||||
SH_ADD_HOOK_STATICFUNC(C8, F, g_pC8, Handler_C8_F, false);
|
||||
SH_ADD_HOOK_STATICFUNC(C8, G, g_pC8, Handler_C8_G, false);
|
||||
SH_ADD_HOOK(C1, F, g_pC1, SH_STATIC(Handler_C1_F), false);
|
||||
SH_ADD_HOOK(C1, G, g_pC1, SH_STATIC(Handler_C1_G), false);
|
||||
SH_ADD_HOOK(C2, F, g_pC2, SH_STATIC(Handler_C2_F), false);
|
||||
SH_ADD_HOOK(C2, G, g_pC2, SH_STATIC(Handler_C2_G), false);
|
||||
SH_ADD_HOOK(C3, F, g_pC3, SH_STATIC(Handler_C3_F), false);
|
||||
SH_ADD_HOOK(C3, G, g_pC3, SH_STATIC(Handler_C3_G), false);
|
||||
SH_ADD_HOOK(C4, F, g_pC4, SH_STATIC(Handler_C4_F), false);
|
||||
SH_ADD_HOOK(C4, G, g_pC4, SH_STATIC(Handler_C4_G), false);
|
||||
SH_ADD_HOOK(C5, F, g_pC5, SH_STATIC(Handler_C5_F), false);
|
||||
SH_ADD_HOOK(C5, G, g_pC5, SH_STATIC(Handler_C5_G), false);
|
||||
SH_ADD_HOOK(C6, F, g_pC6, SH_STATIC(Handler_C6_F), false);
|
||||
SH_ADD_HOOK(C6, G, g_pC6, SH_STATIC(Handler_C6_G), false);
|
||||
SH_ADD_HOOK(C7, F, g_pC7, SH_STATIC(Handler_C7_F), false);
|
||||
SH_ADD_HOOK(C7, G, g_pC7, SH_STATIC(Handler_C7_G), false);
|
||||
SH_ADD_HOOK(C8, F, g_pC8, SH_STATIC(Handler_C8_F), false);
|
||||
SH_ADD_HOOK(C8, G, g_pC8, SH_STATIC(Handler_C8_G), false);
|
||||
|
||||
g_pC1->F();
|
||||
|
||||
@ -361,7 +371,7 @@ bool TestReentr(std::string &error)
|
||||
NULL), "1");
|
||||
|
||||
|
||||
SH_ADD_HOOK_STATICFUNC(C4, G, g_pC4, Handler2_C4_G, false);
|
||||
SH_ADD_HOOK(C4, G, g_pC4, SH_STATIC(Handler2_C4_G), false);
|
||||
|
||||
g_pC1->F();
|
||||
|
||||
@ -517,7 +527,7 @@ bool TestReentr(std::string &error)
|
||||
|
||||
|
||||
|
||||
SH_ADD_HOOK_STATICFUNC(C4, G, g_pC4, Handler2_C4_G, false);
|
||||
SH_ADD_HOOK(C4, G, g_pC4, SH_STATIC(Handler2_C4_G), false);
|
||||
|
||||
g_TestID = 2;
|
||||
|
||||
@ -578,22 +588,22 @@ bool TestReentr(std::string &error)
|
||||
new State_C1_F(g_pC1),
|
||||
NULL), "7");
|
||||
|
||||
SH_REMOVE_HOOK_STATICFUNC(C1, F, g_pC1, Handler_C1_F, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(C1, G, g_pC1, Handler_C1_G, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(C2, F, g_pC2, Handler_C2_F, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(C2, G, g_pC2, Handler_C2_G, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(C3, F, g_pC3, Handler_C3_F, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(C3, G, g_pC3, Handler_C3_G, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(C4, F, g_pC4, Handler_C4_F, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(C4, G, g_pC4, Handler_C4_G, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(C5, F, g_pC5, Handler_C5_F, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(C5, G, g_pC5, Handler_C5_G, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(C6, F, g_pC6, Handler_C6_F, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(C6, G, g_pC6, Handler_C6_G, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(C7, F, g_pC7, Handler_C7_F, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(C7, G, g_pC7, Handler_C7_G, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(C8, F, g_pC8, Handler_C8_F, false);
|
||||
SH_REMOVE_HOOK_STATICFUNC(C8, G, g_pC8, Handler_C8_G, false);
|
||||
SH_REMOVE_HOOK(C1, F, g_pC1, SH_STATIC(Handler_C1_F), false);
|
||||
SH_REMOVE_HOOK(C1, G, g_pC1, SH_STATIC(Handler_C1_G), false);
|
||||
SH_REMOVE_HOOK(C2, F, g_pC2, SH_STATIC(Handler_C2_F), false);
|
||||
SH_REMOVE_HOOK(C2, G, g_pC2, SH_STATIC(Handler_C2_G), false);
|
||||
SH_REMOVE_HOOK(C3, F, g_pC3, SH_STATIC(Handler_C3_F), false);
|
||||
SH_REMOVE_HOOK(C3, G, g_pC3, SH_STATIC(Handler_C3_G), false);
|
||||
SH_REMOVE_HOOK(C4, F, g_pC4, SH_STATIC(Handler_C4_F), false);
|
||||
SH_REMOVE_HOOK(C4, G, g_pC4, SH_STATIC(Handler_C4_G), false);
|
||||
SH_REMOVE_HOOK(C5, F, g_pC5, SH_STATIC(Handler_C5_F), false);
|
||||
SH_REMOVE_HOOK(C5, G, g_pC5, SH_STATIC(Handler_C5_G), false);
|
||||
SH_REMOVE_HOOK(C6, F, g_pC6, SH_STATIC(Handler_C6_F), false);
|
||||
SH_REMOVE_HOOK(C6, G, g_pC6, SH_STATIC(Handler_C6_G), false);
|
||||
SH_REMOVE_HOOK(C7, F, g_pC7, SH_STATIC(Handler_C7_F), false);
|
||||
SH_REMOVE_HOOK(C7, G, g_pC7, SH_STATIC(Handler_C7_G), false);
|
||||
SH_REMOVE_HOOK(C8, F, g_pC8, SH_STATIC(Handler_C8_F), false);
|
||||
SH_REMOVE_HOOK(C8, G, g_pC8, SH_STATIC(Handler_C8_G), false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -76,6 +76,7 @@ namespace
|
||||
return sth.Func();
|
||||
}
|
||||
};
|
||||
class CHelloDerived : public CHello { };
|
||||
|
||||
class CHook
|
||||
{
|
||||
@ -99,12 +100,10 @@ bool TestRef(std::string &error)
|
||||
CDerived der;
|
||||
CDerived2 der2(11);
|
||||
CDerived2 der3(12);
|
||||
CHello hello;
|
||||
CHelloDerived hello;
|
||||
CHello *pHello = &hello;
|
||||
CHook hook;
|
||||
|
||||
SourceHook::CallClass<CHello> *cc = SH_GET_CALLCLASS(&hello);
|
||||
|
||||
ADD_STATE(State_Result(pHello->Func(base)));
|
||||
ADD_STATE(State_Result(pHello->Func(der)));
|
||||
ADD_STATE(State_Result(pHello->Func(der2)));
|
||||
@ -117,10 +116,10 @@ bool TestRef(std::string &error)
|
||||
new State_Result(12),
|
||||
NULL), "Part 1");
|
||||
|
||||
ADD_STATE(State_Result(SH_CALL(cc, &CHello::Func)(base)));
|
||||
ADD_STATE(State_Result(SH_CALL(cc, &CHello::Func)(der)));
|
||||
ADD_STATE(State_Result(SH_CALL(cc, &CHello::Func)(der2)));
|
||||
ADD_STATE(State_Result(SH_CALL(cc, &CHello::Func)(der3)));
|
||||
ADD_STATE(State_Result(SH_CALL(pHello, &CHello::Func)(base)));
|
||||
ADD_STATE(State_Result(SH_CALL(pHello, &CHello::Func)(der)));
|
||||
ADD_STATE(State_Result(SH_CALL(pHello, &CHello::Func)(der2)));
|
||||
ADD_STATE(State_Result(SH_CALL(pHello, &CHello::Func)(der3)));
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_Result(0),
|
||||
@ -129,7 +128,7 @@ bool TestRef(std::string &error)
|
||||
new State_Result(12),
|
||||
NULL), "Part 2");
|
||||
|
||||
SH_ADD_HOOK_MEMFUNC(CHello, Func, &hello, &hook, &CHook::Func, false);
|
||||
SH_ADD_HOOK(CHello, Func, &hello, SH_MEMBER(&hook, &CHook::Func), false);
|
||||
|
||||
ADD_STATE(State_Result(pHello->Func(base)));
|
||||
ADD_STATE(State_Result(pHello->Func(der)));
|
||||
@ -147,10 +146,10 @@ bool TestRef(std::string &error)
|
||||
new State_Result(20),
|
||||
NULL), "Part 3");
|
||||
|
||||
ADD_STATE(State_Result(SH_CALL(cc, &CHello::Func)(base)));
|
||||
ADD_STATE(State_Result(SH_CALL(cc, &CHello::Func)(der)));
|
||||
ADD_STATE(State_Result(SH_CALL(cc, &CHello::Func)(der2)));
|
||||
ADD_STATE(State_Result(SH_CALL(cc, &CHello::Func)(der3)));
|
||||
ADD_STATE(State_Result(SH_CALL(pHello, &CHello::Func)(base)));
|
||||
ADD_STATE(State_Result(SH_CALL(pHello, &CHello::Func)(der)));
|
||||
ADD_STATE(State_Result(SH_CALL(pHello, &CHello::Func)(der2)));
|
||||
ADD_STATE(State_Result(SH_CALL(pHello, &CHello::Func)(der3)));
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
new State_Result(0),
|
||||
|
||||
@ -48,6 +48,10 @@ namespace
|
||||
return m_Var2;
|
||||
}
|
||||
};
|
||||
|
||||
class Whatever : public Test
|
||||
{
|
||||
};
|
||||
|
||||
class CHook
|
||||
{
|
||||
@ -98,7 +102,7 @@ bool TestRefRet(std::string &error)
|
||||
GET_SHPTR(g_SHPtr);
|
||||
g_PLID = 1;
|
||||
|
||||
Test test;
|
||||
Whatever test;
|
||||
Test *pTest = &test;
|
||||
CHook hook;
|
||||
|
||||
@ -111,7 +115,7 @@ bool TestRefRet(std::string &error)
|
||||
NULL), "Part 1");
|
||||
|
||||
// Now add Func1_Pre1, which supercedes and returns hook.m_Var
|
||||
SH_ADD_HOOK_MEMFUNC(Test, Func1, &test, &hook, &CHook::Func1_Pre1, false);
|
||||
SH_ADD_HOOK(Test, Func1, &test, SH_MEMBER(&hook, &CHook::Func1_Pre1), false);
|
||||
|
||||
int &ret2 = pTest->Func1();
|
||||
ADD_STATE(State_Func1_Ret(&ret2));
|
||||
@ -123,7 +127,7 @@ bool TestRefRet(std::string &error)
|
||||
NULL), "Part 2");
|
||||
|
||||
// Now add Func1_Post1, which only reports orig ret and override ret
|
||||
SH_ADD_HOOK_MEMFUNC(Test, Func1, &test, &hook, &CHook::Func1_Post1, true);
|
||||
SH_ADD_HOOK(Test, Func1, &test, SH_MEMBER(&hook, &CHook::Func1_Post1), true);
|
||||
|
||||
int &ret3 = pTest->Func1();
|
||||
ADD_STATE(State_Func1_Ret(&ret3));
|
||||
@ -139,8 +143,8 @@ bool TestRefRet(std::string &error)
|
||||
// Now add Func1_Pre2, which supercedes and returns g_Var (it also sets the override ret from pre1 to 1337)
|
||||
// and add Func1_Post2, which overrides and returns hook.m_Var again.
|
||||
|
||||
SH_ADD_HOOK_MEMFUNC(Test, Func1, &test, &hook, &CHook::Func1_Pre2, false);
|
||||
SH_ADD_HOOK_MEMFUNC(Test, Func1, &test, &hook, &CHook::Func1_Post2, true);
|
||||
SH_ADD_HOOK(Test, Func1, &test, SH_MEMBER(&hook, &CHook::Func1_Pre2), false);
|
||||
SH_ADD_HOOK(Test, Func1, &test, SH_MEMBER(&hook, &CHook::Func1_Post2), true);
|
||||
|
||||
int &ret4 = pTest->Func1();
|
||||
ADD_STATE(State_Func1_Ret(&ret4));
|
||||
@ -160,8 +164,7 @@ bool TestRefRet(std::string &error)
|
||||
CHECK_COND(hook.m_Var == 1337, "Part 4.1");
|
||||
|
||||
// Through a callclass
|
||||
SourceHook::CallClass<Test> *cc1 = SH_GET_CALLCLASS(&test);
|
||||
int &ret5 = SH_CALL(cc1, &Test::Func1)();
|
||||
int &ret5 = SH_CALL(pTest, &Test::Func1)();
|
||||
ADD_STATE(State_Func1_Ret(&ret5));
|
||||
|
||||
CHECK_STATES((&g_States,
|
||||
@ -169,7 +172,6 @@ bool TestRefRet(std::string &error)
|
||||
new State_Func1_Ret(&test.m_Var1),
|
||||
NULL), "Part 5");
|
||||
|
||||
SH_RELEASE_CALLCLASS(cc1);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Func2 tests
|
||||
@ -181,8 +183,8 @@ bool TestRefRet(std::string &error)
|
||||
new State_Func2_Ret(&test.m_Var2),
|
||||
NULL), "Part 6");
|
||||
|
||||
SH_ADD_HOOK_MEMFUNC(Test, Func2, &test, &hook, &CHook::Func2_Pre1, false);
|
||||
SH_ADD_HOOK_MEMFUNC(Test, Func2, &test, &hook, &CHook::Func2_Post1, true);
|
||||
SH_ADD_HOOK(Test, Func2, &test, SH_MEMBER(&hook, &CHook::Func2_Pre1), false);
|
||||
SH_ADD_HOOK(Test, Func2, &test, SH_MEMBER(&hook, &CHook::Func2_Post1), true);
|
||||
|
||||
const int &ret22 = pTest->Func2(500);
|
||||
ADD_STATE(State_Func2_Ret(&ret22));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user