From f747acdc7c6ca38f08859c37f3bf4d1104cd282a Mon Sep 17 00:00:00 2001 From: Steve Dudenhoeffer Date: Tue, 8 May 2007 17:26:51 +0000 Subject: [PATCH] Added return type modification / retrieval. Added HAM_{IGNORED,HANDLED,OVERRIDE,SUPERCEDE} to include file. Added the ability to disable and re-enable hooks. --- dlls/hamsandwich/CString.h | 4 +- dlls/hamsandwich/DataHandler.cpp | 183 +++++++++++++++++ dlls/hamsandwich/DataHandler.h | 238 ++++++++++++++++++++++ dlls/hamsandwich/Makefile | 2 +- dlls/hamsandwich/amxx_api.cpp | 2 + dlls/hamsandwich/hook_callbacks.cpp | 194 ++++++++++++++---- dlls/hamsandwich/hook_native.cpp | 42 +++- dlls/hamsandwich/include/hamsandwich.inc | 50 ++++- dlls/hamsandwich/msvc8/hamsandwich.vcproj | 20 ++ dlls/hamsandwich/sh_stack.h | 219 ++++++++++++++++++++ dlls/hamsandwich/srvcmd.cpp | 10 +- 11 files changed, 906 insertions(+), 58 deletions(-) create mode 100644 dlls/hamsandwich/DataHandler.cpp create mode 100644 dlls/hamsandwich/DataHandler.h create mode 100644 dlls/hamsandwich/sh_stack.h diff --git a/dlls/hamsandwich/CString.h b/dlls/hamsandwich/CString.h index 1c77cfac..3bdc3605 100644 --- a/dlls/hamsandwich/CString.h +++ b/dlls/hamsandwich/CString.h @@ -129,7 +129,7 @@ public: } //Added this for amxx inclusion - bool empty() + bool empty() const { if (!v) return true; @@ -140,7 +140,7 @@ public: return false; } - size_t size() + size_t size() const { if (v) return strlen(v); diff --git a/dlls/hamsandwich/DataHandler.cpp b/dlls/hamsandwich/DataHandler.cpp new file mode 100644 index 00000000..554c2493 --- /dev/null +++ b/dlls/hamsandwich/DataHandler.cpp @@ -0,0 +1,183 @@ +#include "sdk/amxxmodule.h" + +#include "CVector.h" +#include "CString.h" +#include "sh_stack.h" +#include "DataHandler.h" + +#include "ham_const.h" +#include "ham_utils.h" +#include "NEW_Util.h" + +CStack< Data * > ReturnStack; +CStack< Data * > OrigReturnStack; +CStack< CVector< Data * > * > ParamStack; + +#define CHECK_STACK(__STACK__) \ + if ( ( __STACK__ ).size() <= 0) \ + { \ + MF_LogError(amx, AMX_ERR_NATIVE, "%s is empty!", #__STACK__); \ + return 0; \ + } + +#define PARSE_RETURN() \ + if (ret==-2) \ + { \ + MF_LogError(amx, AMX_ERR_NATIVE, "Data pointer is NULL!"); \ + } \ + else if (ret==-1) \ + { \ + MF_LogError(amx, AMX_ERR_NATIVE, "Wrong data type (data is of type %s)", returntypes[dat->GetType()]); \ + } \ + return ret + +static const char *returntypes[] = +{ + "void", + "integer", + "float", + "vector", + "string", + "cbase", +}; + +static cell AMX_NATIVE_CALL GetHamReturnInteger(AMX *amx, cell *params) +{ + CHECK_STACK(ReturnStack); + Data *dat=ReturnStack.front(); + + int ret=dat->GetInt(MF_GetAmxAddr(amx, params[1])); + PARSE_RETURN(); +} +static cell AMX_NATIVE_CALL GetOrigHamReturnInteger(AMX *amx, cell *params) +{ + CHECK_STACK(OrigReturnStack); + Data *dat=OrigReturnStack.front(); + + int ret=dat->GetInt(MF_GetAmxAddr(amx, params[1])); + PARSE_RETURN(); +} +static cell AMX_NATIVE_CALL GetHamReturnFloat(AMX *amx, cell *params) +{ + CHECK_STACK(ReturnStack); + Data *dat=ReturnStack.front(); + + int ret=dat->GetFloat(MF_GetAmxAddr(amx, params[1])); + PARSE_RETURN(); +} +static cell AMX_NATIVE_CALL GetOrigHamReturnFloat(AMX *amx, cell *params) +{ + CHECK_STACK(OrigReturnStack); + Data *dat=OrigReturnStack.front(); + + int ret=dat->GetFloat(MF_GetAmxAddr(amx, params[1])); + PARSE_RETURN(); +} +static cell AMX_NATIVE_CALL GetHamReturnVector(AMX *amx, cell *params) +{ + CHECK_STACK(ReturnStack); + Data *dat=ReturnStack.front(); + + int ret=dat->GetVector(MF_GetAmxAddr(amx, params[1])); + PARSE_RETURN(); +} +static cell AMX_NATIVE_CALL GetOrigHamReturnVector(AMX *amx, cell *params) +{ + CHECK_STACK(OrigReturnStack); + Data *dat=OrigReturnStack.front(); + + int ret=dat->GetVector(MF_GetAmxAddr(amx, params[1])); + PARSE_RETURN(); +} +static cell AMX_NATIVE_CALL GetHamReturnCbase(AMX *amx, cell *params) +{ + CHECK_STACK(ReturnStack); + Data *dat=ReturnStack.front(); + + int ret=dat->GetCbase(MF_GetAmxAddr(amx, params[1])); + PARSE_RETURN(); +} +static cell AMX_NATIVE_CALL GetOrigHamReturnCbase(AMX *amx, cell *params) +{ + CHECK_STACK(OrigReturnStack); + Data *dat=OrigReturnStack.front(); + + int ret=dat->GetCbase(MF_GetAmxAddr(amx, params[1])); + PARSE_RETURN(); +} +static cell AMX_NATIVE_CALL GetHamReturnString(AMX *amx, cell *params) +{ + CHECK_STACK(ReturnStack); + Data *dat=ReturnStack.front(); + + int ret=dat->GetString(MF_GetAmxAddr(amx, params[1]), params[2]); + PARSE_RETURN(); +} +static cell AMX_NATIVE_CALL GetOrigHamReturnString(AMX *amx, cell *params) +{ + CHECK_STACK(OrigReturnStack); + Data *dat=OrigReturnStack.front(); + + int ret=dat->GetString(MF_GetAmxAddr(amx, params[1]), params[2]); + PARSE_RETURN(); +} +static cell AMX_NATIVE_CALL SetHamReturnInteger(AMX *amx, cell *params) +{ + CHECK_STACK(ReturnStack); + Data *dat=ReturnStack.front(); + + int ret=dat->SetInt(¶ms[1]); + PARSE_RETURN(); +} +static cell AMX_NATIVE_CALL SetHamReturnFloat(AMX *amx, cell *params) +{ + CHECK_STACK(ReturnStack); + Data *dat=ReturnStack.front(); + + int ret=dat->SetFloat(¶ms[1]); + PARSE_RETURN(); +} +static cell AMX_NATIVE_CALL SetHamReturnVector(AMX *amx, cell *params) +{ + CHECK_STACK(ReturnStack); + Data *dat=ReturnStack.front(); + + int ret=dat->SetVector(MF_GetAmxAddr(amx, params[1])); + PARSE_RETURN(); +} +static cell AMX_NATIVE_CALL SetHamReturnCbase(AMX *amx, cell *params) +{ + CHECK_STACK(ReturnStack); + Data *dat=ReturnStack.front(); + + int ret=dat->SetCbase(¶ms[1]); + PARSE_RETURN(); +} +static cell AMX_NATIVE_CALL SetHamReturnString(AMX *amx, cell *params) +{ + CHECK_STACK(ReturnStack); + Data *dat=ReturnStack.front(); + + int ret=dat->SetString(MF_GetAmxAddr(amx, params[1])); + PARSE_RETURN(); +} + +AMX_NATIVE_INFO ReturnNatives[] = +{ + { "GetHamReturnInteger", GetHamReturnInteger }, + { "GetHamReturnFloat", GetHamReturnFloat }, + { "GetHamReturnVector", GetHamReturnVector }, + { "GetHamReturnCbase", GetHamReturnCbase }, + { "GetHamReturnString", GetHamReturnString }, + { "GetOrigHamReturnInteger", GetOrigHamReturnInteger }, + { "GetOrigHamReturnFloat", GetOrigHamReturnFloat }, + { "GetOrigHamReturnVector", GetOrigHamReturnVector }, + { "GetOrigHamReturnCbase", GetOrigHamReturnCbase }, + { "GetOrigHamReturnString", GetOrigHamReturnString }, + { "SetHamReturnInteger", SetHamReturnInteger }, + { "SetHamReturnFloat", SetHamReturnFloat }, + { "SetHamReturnVector", SetHamReturnVector }, + { "SetHamReturnCbase", SetHamReturnCbase }, + { "SetHamReturnString", SetHamReturnString }, + { NULL, NULL }, +}; diff --git a/dlls/hamsandwich/DataHandler.h b/dlls/hamsandwich/DataHandler.h new file mode 100644 index 00000000..2a4bb109 --- /dev/null +++ b/dlls/hamsandwich/DataHandler.h @@ -0,0 +1,238 @@ +#ifndef RETURNHANDLER_H +#define RETURNHANDLER_H + +#include "ham_utils.h" +#include "CVector.h" +#include "CString.h" +#include "sh_stack.h" + +enum +{ + RET_VOID, + RET_INTEGER, + RET_FLOAT, + RET_VECTOR, + RET_STRING, + RET_CBASE +}; +// Container for return and parameter data. +// Contains a void pointer, and a flag telling what it contains. +class Data +{ +private: + void *m_data; + int m_type; + + bool IsSet(void) + { + return (m_type != RET_VOID && + m_data != NULL); + }; + bool IsType(const int type) + { + return (m_type == type); + }; + +public: + Data() : m_data(NULL), m_type(RET_VOID) + { /* nothing */ }; + + Data(int type, void *ptr) : m_data(ptr), m_type(type) + { /* nothing */ }; + + ~Data() + { /* nothing */ }; + + int GetType() + { + return m_type; + }; + + // All Get/Set value natives return < 0 on failure. + // -1: Wrong type + // -2: Bad data pointer (void, etc). + int SetInt(cell *data) + { + if (!IsSet()) + { + return -2; + } + if (!IsType(RET_INTEGER)) + { + return -1; + } + *(reinterpret_cast(m_data))=*data; + + return 0; + }; + + int SetFloat(cell *data) + { + if (!IsSet()) + { + return -2; + } + if (!IsType(RET_FLOAT)) + { + return -1; + } + *(reinterpret_cast(m_data))=amx_ctof2(*data); + + return 0; + }; + int SetVector(cell *data) + { + if (!IsSet()) + { + return -2; + } + if (!IsType(RET_VECTOR)) + { + return -1; + } + Vector *vec=reinterpret_cast(m_data); + + vec->x=amx_ctof2(data[0]); + vec->y=amx_ctof2(data[1]); + vec->z=amx_ctof2(data[2]); + + return 0; + }; + int SetString(cell *data) + { + if (!IsSet()) + { + return -2; + } + if (!IsType(RET_STRING)) + { + return -1; + } + + String *str=reinterpret_cast(m_data); + + cell *i=data; + size_t len=0; + + while (*i!=0) + { + i++; + len++; + }; + char *temp=new char[len+1]; + i=data; + char *j=temp; + + while ((*j++=*i++)!=0) + { + /* nothing */ + } + + str->assign(temp); + + delete[] temp; + + return 0; + }; + + int SetCbase(cell *data) + { + if (!IsSet()) + { + return -2; + } + if (!IsType(RET_CBASE)) + { + return -1; + } + + *(reinterpret_cast(m_data))=IndexToPrivate(*data); + + return 0; + }; + + int GetInt(cell *data) + { + if (!IsSet()) + { + return -2; + } + if (!IsType(RET_INTEGER)) + { + return -1; + } + *data=*(reinterpret_cast(m_data)); + + return 0; + }; + int GetFloat(cell *data) + { + if (!IsSet()) + { + return -2; + } + if (!IsType(RET_FLOAT)) + { + return -1; + } + *data=amx_ftoc2(*(reinterpret_cast(m_data))); + + return 0; + }; + int GetVector(cell *data) + { + if (!IsSet()) + { + return -2; + } + if (!IsType(RET_VECTOR)) + { + return -1; + } + Vector *vec=reinterpret_cast(m_data); + data[0]=amx_ftoc2(vec->x); + data[1]=amx_ftoc2(vec->y); + data[2]=amx_ftoc2(vec->z); + + return 0; + }; + int GetString(cell *data, int len) + { + if (!IsSet()) + { + return -2; + } + if (!IsType(RET_STRING)) + { + return -1; + } + const char *i=(reinterpret_cast(m_data)->c_str()); + + while (len-- && + (*data++=*i++)!='\0') + { + /* nothing */ + }; + return 0; + }; + int GetCbase(cell *data) + { + if (!IsSet()) + { + return -2; + } + if (!IsType(RET_CBASE)) + { + return -1; + } + *data=PrivateToIndex(m_data); + + return 0; + } +}; + +extern CStack< Data * > ReturnStack; +extern CStack< Data * > OrigReturnStack; +extern CStack< CVector< Data * > * > ParamStack; + +#endif diff --git a/dlls/hamsandwich/Makefile b/dlls/hamsandwich/Makefile index 3442baf2..08a9fd90 100644 --- a/dlls/hamsandwich/Makefile +++ b/dlls/hamsandwich/Makefile @@ -25,7 +25,7 @@ BIN_SUFFIX = amxx_i386.so OBJECTS = sdk/amxxmodule.cpp amxx_api.cpp config_parser.cpp \ hook_callbacks.cpp hook_native.cpp srvcmd.cpp \ -call_funcs.cpp hook_create.cpp +call_funcs.cpp hook_create.cpp DataHandler.cpp LINK = diff --git a/dlls/hamsandwich/amxx_api.cpp b/dlls/hamsandwich/amxx_api.cpp index c557d9d2..2188c647 100644 --- a/dlls/hamsandwich/amxx_api.cpp +++ b/dlls/hamsandwich/amxx_api.cpp @@ -13,6 +13,7 @@ bool NEW_Initialized; extern CVector hooks[HAM_LAST_ENTRY_DONT_USE_ME_LOL]; extern AMX_NATIVE_INFO RegisterNatives[]; +extern AMX_NATIVE_INFO ReturnNatives[]; int ReadConfig(void); @@ -21,6 +22,7 @@ void OnAmxxAttach(void) if (ReadConfig() > 0) { MF_AddNatives(RegisterNatives); + MF_AddNatives(ReturnNatives); } } diff --git a/dlls/hamsandwich/hook_callbacks.cpp b/dlls/hamsandwich/hook_callbacks.cpp index e660425e..2314cb4d 100644 --- a/dlls/hamsandwich/hook_callbacks.cpp +++ b/dlls/hamsandwich/hook_callbacks.cpp @@ -9,6 +9,8 @@ #include "CVector.h" +#include "CString.h" +#include "sh_stack.h" #include "hook.h" #include "forward.h" @@ -16,10 +18,21 @@ #include "ham_const.h" #include "ham_utils.h" +#include "DataHandler.h" + extern bool gDoForwards; +#define PUSH_VOID() ReturnStack.push(new Data(RET_VOID, NULL)); OrigReturnStack.push(new Data(RET_VOID, NULL)); +#define PUSH_INT() ReturnStack.push(new Data(RET_INTEGER, (void *)&ret)); OrigReturnStack.push(new Data(RET_INTEGER, (void *)&origret)); +#define PUSH_FLOAT() ReturnStack.push(new Data(RET_FLOAT, (void *)&ret)); OrigReturnStack.push(new Data(RET_FLOAT, (void *)&origret)); +#define PUSH_VECTOR() ReturnStack.push(new Data(RET_VECTOR, (void *)&ret)); OrigReturnStack.push(new Data(RET_VECTOR, (void *)&origret)); +#define PUSH_CBASE() ReturnStack.push(new Data(RET_CBASE, (void *)&ret)); OrigReturnStack.push(new Data(RET_CBASE, (void *)&origret)); +#define PUSH_STRING() ReturnStack.push(new Data(RET_STRING, (void *)&ret)); OrigReturnStack.push(new Data(RET_STRING, (void *)&origret)); + +#define POP() delete ReturnStack.front(); ReturnStack.pop(); delete OrigReturnStack.front(); OrigReturnStack.pop(); + #define PRE_START() \ bool DoForwards=gDoForwards; \ gDoForwards=true; \ @@ -65,8 +78,22 @@ extern bool gDoForwards; } +#define CHECK_RETURN() \ + if (thisresult < HAM_OVERRIDE) \ + { \ + return origret; \ + } + +#define CHECK_RETURN_STR() \ + if (thisresult < HAM_OVERRIDE) \ + { \ + return origret.c_str(); \ + } + + void Hook_Void_Void(Hook *hook, void *pthis) { + PUSH_VOID() PRE_START() PRE_END() @@ -78,29 +105,35 @@ void Hook_Void_Void(Hook *hook, void *pthis) POST_START() POST_END() + POP() } int Hook_Int_Void(Hook *hook, void *pthis) { - int ireturn=0; + int ret=0; + int origret=0; + PUSH_INT() PRE_START() PRE_END() #if defined _WIN32 - ireturn=reinterpret_cast(hook->func)(pthis,0); + origret=reinterpret_cast(hook->func)(pthis,0); #elif defined __linux__ - ireturn=reinterpret_cast(hook->func)(pthis); + origret=reinterpret_cast(hook->func)(pthis); #endif POST_START() POST_END() - return ireturn; + POP() + CHECK_RETURN() + return ret; } void Hook_Void_Entvar(Hook *hook, void *pthis, entvars_t *entvar) { + PUSH_VOID() int iOther=EntvarToIndex(entvar); PRE_START() @@ -117,10 +150,13 @@ void Hook_Void_Entvar(Hook *hook, void *pthis, entvars_t *entvar) , iOther POST_END() + POP() + } void Hook_Void_Cbase(Hook *hook, void *pthis, void *other) { + PUSH_VOID() int iOther=PrivateToIndex(other); PRE_START() @@ -137,31 +173,36 @@ void Hook_Void_Cbase(Hook *hook, void *pthis, void *other) , iOther POST_END() - + POP() } int Hook_Int_Float_Int(Hook *hook, void *pthis, float f1, int i1) { - int ireturn=0; + int ret=0; + int origret=0; + PUSH_INT() PRE_START() , f1, i1 PRE_END() #if defined _WIN32 - ireturn=reinterpret_cast(hook->func)(pthis, 0, f1, i1); + origret=reinterpret_cast(hook->func)(pthis, 0, f1, i1); #elif defined __linux__ - ireturn=reinterpret_cast(hook->func)(pthis, f1, i1); + origret=reinterpret_cast(hook->func)(pthis, f1, i1); #endif POST_START() , f1, i1 POST_END() - return ireturn; + POP(); + CHECK_RETURN(); + return ret; } void Hook_Void_Entvar_Int(Hook *hook, void *pthis, entvars_t *ev1, int i1) { + PUSH_VOID() int iOther=EntvarToIndex(ev1); PRE_START() @@ -177,30 +218,38 @@ void Hook_Void_Entvar_Int(Hook *hook, void *pthis, entvars_t *ev1, int i1) POST_START() , iOther, i1 POST_END() + POP() } int Hook_Int_Cbase(Hook *hook, void *pthis, void *cb1) { + int ret=0; + int origret=0; + + PUSH_INT() + int iOther=PrivateToIndex(cb1); - int ireturn=0; PRE_START() , iOther PRE_END() #if defined _WIN32 - ireturn=reinterpret_cast(hook->func)(pthis, 0, cb1); + origret=reinterpret_cast(hook->func)(pthis, 0, cb1); #elif defined __linux__ - ireturn=reinterpret_cast(hook->func)(pthis, cb1); + origret=reinterpret_cast(hook->func)(pthis, cb1); #endif POST_START() , iOther POST_END() - return ireturn; + POP() + CHECK_RETURN() + return ret; } void Hook_Void_Int_Int(Hook *hook, void *pthis, int i1, int i2) { + PUSH_VOID() PRE_START() ,i1, i2 PRE_END() @@ -213,51 +262,63 @@ void Hook_Void_Int_Int(Hook *hook, void *pthis, int i1, int i2) POST_START() ,i1, i2 POST_END() + POP() } int Hook_Int_Int_Str_Int(Hook *hook, void *pthis, int i1, const char *sz1, int i2) { - int ireturn=0; + int ret=0; + int origret=0; + PUSH_INT() PRE_START() ,i1, sz1, i2 PRE_END() #if defined _WIN32 - ireturn=reinterpret_cast(hook->func)(pthis, 0, i1, sz1, i2); + origret=reinterpret_cast(hook->func)(pthis, 0, i1, sz1, i2); #elif defined __linux__ - ireturn=reinterpret_cast(hook->func)(pthis, i1, sz1, i2); + origret=reinterpret_cast(hook->func)(pthis, i1, sz1, i2); #endif POST_START() ,i1, sz1, i2 POST_END() - return ireturn; + POP() + CHECK_RETURN() + return ret; } int Hook_Int_Int(Hook *hook, void *pthis, int i1) { - int ireturn=0; + int ret=0; + int origret=0; + PUSH_INT() PRE_START() ,i1 PRE_END() #if defined _WIN32 - ireturn=reinterpret_cast(hook->func)(pthis, 0, i1); + origret=reinterpret_cast(hook->func)(pthis, 0, i1); #elif defined __linux__ - ireturn=reinterpret_cast(hook->func)(pthis, i1); + origret=reinterpret_cast(hook->func)(pthis, i1); #endif POST_START() ,i1 POST_END() - return ireturn; + POP() + CHECK_RETURN() + return ret; } int Hook_Int_Entvar(Hook *hook, void *pthis, entvars_t *ev1) { - int ireturn=0; + int ret=0; + int origret=0; + + PUSH_INT() int iOther=EntvarToIndex(ev1); PRE_START() @@ -265,16 +326,18 @@ int Hook_Int_Entvar(Hook *hook, void *pthis, entvars_t *ev1) PRE_END() #if defined _WIN32 - ireturn=reinterpret_cast(hook->func)(pthis, 0, ev1); + origret=reinterpret_cast(hook->func)(pthis, 0, ev1); #elif defined __linux__ - ireturn=reinterpret_cast(hook->func)(pthis, ev1); + origret=reinterpret_cast(hook->func)(pthis, ev1); #endif POST_START() , iOther POST_END() - return ireturn; + POP() + CHECK_RETURN() + return ret; } @@ -282,7 +345,9 @@ int Hook_Int_Entvar(Hook *hook, void *pthis, entvars_t *ev1) // Takedamage int Hook_Int_Entvar_Entvar_Float_Int(Hook *hook, void *pthis, entvars_t *inflictor, entvars_t *attacker, float damage, int damagebits) { - int ireturn=0; + int ret=0; + int origret=0; + PUSH_INT() int iInflictor=EntvarToIndex(inflictor); int iAttacker=EntvarToIndex(attacker); @@ -293,20 +358,23 @@ int Hook_Int_Entvar_Entvar_Float_Int(Hook *hook, void *pthis, entvars_t *inflict #if defined _WIN32 - ireturn=reinterpret_cast(hook->func)(pthis, 0, inflictor, attacker, damage, damagebits); + origret=reinterpret_cast(hook->func)(pthis, 0, inflictor, attacker, damage, damagebits); #elif defined __linux__ - ireturn=reinterpret_cast(hook->func)(pthis, inflictor, attacker, damage, damagebits); + origret=reinterpret_cast(hook->func)(pthis, inflictor, attacker, damage, damagebits); #endif POST_START() ,iInflictor, iAttacker, damage, damagebits POST_END() - return ireturn; + POP() + CHECK_RETURN() + return ret; } void Hook_Void_Int(Hook *hook, void *pthis, int i1) { + PUSH_VOID() PRE_START() , i1 PRE_END() @@ -321,10 +389,12 @@ void Hook_Void_Int(Hook *hook, void *pthis, int i1) ,i1 POST_END() + POP() } void Hook_Void_Cbase_Cbase_Int_Float(Hook *hook, void *pthis, void *cb1, void *cb2, int i1, float f1) { + PUSH_VOID() int iCaller=PrivateToIndex(cb1); int iActivator=PrivateToIndex(cb2); @@ -344,10 +414,12 @@ void Hook_Void_Cbase_Cbase_Int_Float(Hook *hook, void *pthis, void *cb1, void *c ,iCaller, iActivator, i1, f1 POST_END() + POP() } void Hook_Void_Entvar_Float_Vector_Trace_Int(Hook *hook, void *pthis, entvars_t *ev1, float f1, Vector v1, TraceResult *tr1, int i1) { + PUSH_VOID() int iev1=EntvarToIndex(ev1); cell cvec[3]; cvec[0]=amx_ftoc2(v1.x); @@ -367,10 +439,13 @@ void Hook_Void_Entvar_Float_Vector_Trace_Int(Hook *hook, void *pthis, entvars_t POST_START() , iev1, f1, MF_PrepareCellArrayA(cvec, 3, false), tr1, i1 POST_END() + + POP() } void Hook_Void_Float_Vector_TraceResult_Int(Hook *hook, void *pthis, float f1, Vector v1, TraceResult *tr1, int i1) { + PUSH_VOID() cell cvec[3]; cvec[0]=amx_ftoc2(v1.x); cvec[1]=amx_ftoc2(v1.y); @@ -389,41 +464,50 @@ void Hook_Void_Float_Vector_TraceResult_Int(Hook *hook, void *pthis, float f1, V POST_START() , f1, MF_PrepareCellArrayA(cvec, 3, false), tr1, i1 POST_END() + POP() } const char *Hook_Str_Void(Hook *hook, void *pthis) { - const char *ret=NULL; + String ret; + String origret; + PUSH_STRING() PRE_START() PRE_END() #if defined _WIN32 - ret=reinterpret_cast(hook->func)(pthis, 0); + origret.assign(reinterpret_cast(hook->func)(pthis, 0)); #elif defined __linux__ - ret=reinterpret_cast(hook->func)(pthis); + origret.assign(reinterpret_cast(hook->func)(pthis)); #endif POST_START() POST_END() - return ret; + POP() + CHECK_RETURN_STR(); + return ret.c_str(); } void *Hook_Cbase_Void(Hook *hook, void *pthis) { void *ret=NULL; + void *origret=NULL; + PUSH_CBASE() PRE_START() PRE_END() #if defined _WIN32 - ret=reinterpret_cast(hook->func)(pthis, 0); + origret=reinterpret_cast(hook->func)(pthis, 0); #elif defined __linux__ - ret=reinterpret_cast(hook->func)(pthis); + origret=reinterpret_cast(hook->func)(pthis); #endif POST_START() POST_END() + POP() + CHECK_RETURN() return ret; } @@ -432,21 +516,27 @@ void *Hook_Cbase_Void(Hook *hook, void *pthis) Vector Hook_Vector_Void(Hook *hook, void *pthis) { Vector ret; + Vector origret; + + PUSH_VECTOR() memset(&ret, 0x0, sizeof(Vector)); + memset(&origret, 0x0, sizeof(Vector)); PRE_START() PRE_END() #if defined _WIN32 - ret=reinterpret_cast(hook->func)(pthis, 0); + origret=reinterpret_cast(hook->func)(pthis, 0); #elif defined __linux__ - ret=reinterpret_cast(hook->func)(pthis); + origret=reinterpret_cast(hook->func)(pthis); #endif POST_START() POST_END() + POP() + CHECK_RETURN() return ret; } @@ -454,8 +544,12 @@ Vector Hook_Vector_Void(Hook *hook, void *pthis) Vector Hook_Vector_pVector(Hook *hook, void *pthis, Vector *v1) { Vector ret; + Vector origret; + + PUSH_VECTOR() memset(&ret, 0x0, sizeof(Vector)); + memset(&origret, 0x0, sizeof(Vector)); cell cv1[3]; cv1[0]=amx_ftoc2(v1->x); @@ -467,15 +561,17 @@ Vector Hook_Vector_pVector(Hook *hook, void *pthis, Vector *v1) PRE_END() #if defined _WIN32 - ret=reinterpret_cast(hook->func)(pthis, 0, v1); + origret=reinterpret_cast(hook->func)(pthis, 0, v1); #elif defined __linux__ - ret=reinterpret_cast(hook->func)(pthis, v1); + origret=reinterpret_cast(hook->func)(pthis, v1); #endif POST_START() , MF_PrepareCellArrayA(cv1, 3, false) POST_END() + POP() + CHECK_RETURN() return ret; } @@ -483,6 +579,8 @@ Vector Hook_Vector_pVector(Hook *hook, void *pthis, Vector *v1) int Hook_Int_pVector(Hook *hook, void *pthis, Vector *v1) { int ret=0; + int origret=0; + PUSH_INT() cell cv1[3]; @@ -495,21 +593,24 @@ int Hook_Int_pVector(Hook *hook, void *pthis, Vector *v1) PRE_END() #if defined _WIN32 - ret=reinterpret_cast(hook->func)(pthis, 0, v1); + origret=reinterpret_cast(hook->func)(pthis, 0, v1); #elif defined __linux__ - ret=reinterpret_cast(hook->func)(pthis, v1); + origret=reinterpret_cast(hook->func)(pthis, v1); #endif POST_START() , MF_PrepareCellArrayA(cv1, 3, false) POST_END() + POP() + CHECK_RETURN() return ret; } void Hook_Void_Entvar_Float_Float(Hook *hook, void *pthis, entvars_t *ev1, float f1, float f2) { + PUSH_VOID() cell cev1=EntvarToIndex(ev1); PRE_START() @@ -526,11 +627,14 @@ void Hook_Void_Entvar_Float_Float(Hook *hook, void *pthis, entvars_t *ev1, float , cev1, f1, f2 POST_END() + POP() } int Hook_Int_pFloat_pFloat(Hook *hook, void *pthis, float *f1, float *f2) { int ret=0; + int origret=0; + PUSH_INT() cell cf1=amx_ftoc2(f1 == NULL ? 0.0 : *f1); cell cf2=amx_ftoc2(f2 == NULL ? 0.0 : *f2); @@ -540,20 +644,23 @@ int Hook_Int_pFloat_pFloat(Hook *hook, void *pthis, float *f1, float *f2) PRE_END() #if defined _WIN32 - ret=reinterpret_cast(hook->func)(pthis, 0, f1, f2); + origret=reinterpret_cast(hook->func)(pthis, 0, f1, f2); #elif defined __linux__ - ret=reinterpret_cast(hook->func)(pthis, f1, f2); + origret=reinterpret_cast(hook->func)(pthis, f1, f2); #endif POST_START() , cf1, cf2 POST_END() + POP() + CHECK_RETURN() return ret; } void Hook_Void_Entvar_Float(Hook *hook, void *pthis, entvars_t *ev1, float f1) { + PUSH_VOID() cell cev1=EntvarToIndex(ev1); PRE_START() @@ -569,5 +676,6 @@ void Hook_Void_Entvar_Float(Hook *hook, void *pthis, entvars_t *ev1, float f1) POST_START() , cev1, f1 POST_END() + POP() } diff --git a/dlls/hamsandwich/hook_native.cpp b/dlls/hamsandwich/hook_native.cpp index 7965bf95..ce6bf139 100644 --- a/dlls/hamsandwich/hook_native.cpp +++ b/dlls/hamsandwich/hook_native.cpp @@ -198,15 +198,16 @@ static cell AMX_NATIVE_CALL RegisterHam(AMX *amx, cell *params) if ((*i)->tramp == vfunction) { // Yes, this function is hooked + Forward *pfwd=new Forward(fwd); if (post) { - (*i)->post.push_back(new Forward(fwd)); + (*i)->post.push_back(pfwd); } else { - (*i)->pre.push_back(new Forward(fwd)); + (*i)->pre.push_back(pfwd); } - return 1; + return reinterpret_cast(pfwd); } } @@ -214,16 +215,17 @@ static cell AMX_NATIVE_CALL RegisterHam(AMX *amx, cell *params) Hook *hook=new Hook(vtable, hooklist[func].vtid, hooklist[func].targetfunc, hooklist[func].isvoid, hooklist[func].paramcount, classname); hooks[func].push_back(hook); + Forward *pfwd=new Forward(fwd); if (post) { - hook->post.push_back(new Forward(fwd)); + hook->post.push_back(pfwd); } else { - hook->pre.push_back(new Forward(fwd)); + hook->pre.push_back(pfwd); } - return 1; + return reinterpret_cast(pfwd); } static cell AMX_NATIVE_CALL ExecuteHam(AMX *amx, cell *params) { @@ -258,12 +260,40 @@ static cell AMX_NATIVE_CALL IsHamValid(AMX *amx, cell *params) return 0; } +static cell AMX_NATIVE_CALL DisableHamForward(AMX *amx, cell *params) +{ + Forward *fwd=reinterpret_cast(params[1]); + + if (fwd == 0) + { + MF_LogError(amx, AMX_ERR_NATIVE, "Invalid HamHook handle."); + return -1; + } + + fwd->state=FSTATE_STOP; + return 0; +} +static cell AMX_NATIVE_CALL EnableHamForward(AMX *amx, cell *params) +{ + Forward *fwd=reinterpret_cast(params[1]); + + if (fwd == 0) + { + MF_LogError(amx, AMX_ERR_NATIVE, "Invalid HamHook handle."); + return -1; + } + + fwd->state=FSTATE_OK; + return 0; +} AMX_NATIVE_INFO RegisterNatives[] = { { "RegisterHam", RegisterHam }, { "ExecuteHam", ExecuteHam }, { "ExecuteHamB", ExecuteHamB }, { "IsHamValid", IsHamValid }, + { "DisableHamForward", DisableHamForward }, + { "EnableHamForward", EnableHamForward }, { NULL, NULL } }; diff --git a/dlls/hamsandwich/include/hamsandwich.inc b/dlls/hamsandwich/include/hamsandwich.inc index 69cd3f32..4498ef24 100644 --- a/dlls/hamsandwich/include/hamsandwich.inc +++ b/dlls/hamsandwich/include/hamsandwich.inc @@ -455,6 +455,18 @@ enum Ham }; +/** + * Ham return types. + * - + * Return these from hooks to disable calling the target function. + * Numbers match up with fakemeta's FMRES_* for clarity. They are interchangable. + * 0 (or no return) is also interpretted as HAM_IGNORED. + */ +#define HAM_IGNORED 1 /**< Calls target function, returns normal value */ +#define HAM_HANDLED 2 /**< Tells the module you did something, still calls target function and returns normal value */ +#define HAM_OVERRIDE 3 /**< Still calls the target function, but returns whatever is set with SetHamReturn*() */ +#define HAM_SUPERCEDE 4 /**< Block the target call, and use your return value (if applicable) (Set with SetHamReturn*()) */ + /** * Hooks the virtual table for the specified entity class. * An example would be: RegisterHam(Ham_TakeDamage, "player_hurt", "player"); @@ -464,8 +476,27 @@ enum Ham * @param callback The forward to call. * @param entity The entity classname to hook. * @param post Whether or not to forward this in post. + * @return Returns a handle to the forward. Use EnableHamForward/DisableHamForward to toggle the forward on or off. */ -native RegisterHam(Ham:function, const callback[], const entity[], post=0); +native HamHook:RegisterHam(Ham:function, const callback[], const entity[], post=0); + +/** + * Stops a ham forward from triggering. + * Use the return value from RegisterHam as the parameter here! + * + * @param fwd The forward to stop. + */ +native DisableHamForward(HamHook:fwd); + +/** + * Starts a ham forward back up. + * Use the return value from RegisterHam as the parameter here! + * + * @param fwd The forward to re-enable. + */ +native EnableHamForward(HamHook:fwd); + + /** * Executes the virtual function on the entity. @@ -487,6 +518,23 @@ native ExecuteHam(Ham:function, this, any:...); native ExecuteHamB(Ham:function, this, any:...); +native GetHamReturnInteger(&output); +native GetHamReturnFloat(&Float:output); +native GetHamReturnVector(Float:output[3]); +native GetHamReturnCbase(&output); +native GetHamReturnString(output[], size); +native GetOrigHamReturnInteger(&output); +native GetOrigHamReturnFloat(&Float:output); +native GetOrigHamReturnVector(Float:output[3]); +native GetOrigHamReturnCbase(&output); +native GetOrigHamReturnString(output[], size); +native SetHamReturnInteger(output); +native SetHamReturnFloat(Float:output); +native SetHamReturnVector(const Float:output[3]); +native SetHamReturnCbase(output); +native SetHamReturnString(const output[]); + + /** * Returns whether or not the function for the specified Ham is valid. * Things that would make it invalid would be bounds (an older module version diff --git a/dlls/hamsandwich/msvc8/hamsandwich.vcproj b/dlls/hamsandwich/msvc8/hamsandwich.vcproj index e9614d3d..51dde9be 100644 --- a/dlls/hamsandwich/msvc8/hamsandwich.vcproj +++ b/dlls/hamsandwich/msvc8/hamsandwich.vcproj @@ -260,6 +260,26 @@ > + + + + + + + + + + diff --git a/dlls/hamsandwich/sh_stack.h b/dlls/hamsandwich/sh_stack.h new file mode 100644 index 00000000..c01021f7 --- /dev/null +++ b/dlls/hamsandwich/sh_stack.h @@ -0,0 +1,219 @@ +/* ======== SourceMM ======== +* Copyright (C) 2004-2005 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* ============================ +*/ + +#ifndef __SH_STACK_H__ +#define __SH_STACK_H__ + +#define SH_STACK_DEFAULT_SIZE 4 + +//namespace SourceHook +//{/ + // Vector + template class CStack + { + T *m_Elements; + size_t m_AllocatedSize; + size_t m_UsedSize; + public: + friend class iterator; + class iterator + { + CStack *m_pParent; + size_t m_Index; + public: + iterator(CStack *pParent, size_t id) : m_pParent(pParent), m_Index(id) + { + } + + iterator(CStack *pParent) : m_pParent(pParent), m_Index(0) + { + } + + iterator() : m_pParent(NULL), m_Index(0) + { + } + + T &operator *() + { + return m_pParent->m_Elements[m_Index]; + } + const T &operator *() const + { + return m_pParent->m_Elements[m_Index]; + } + + T * operator->() + { + return m_pParent->m_Elements + m_Index; + } + + const T * operator->() const + { + return m_pParent->m_Elements + m_Index; + } + + iterator & operator++() // preincrement + { + ++m_Index; + return (*this); + } + + iterator operator++(int) // postincrement + { + iterator tmp = *this; + ++m_Index; + return tmp; + } + + iterator & operator--() // predecrement + { + --m_Index; + return (*this); + } + + iterator operator--(int) // postdecrememnt + { + iterator tmp = *this; + --m_Index; + return tmp; + } + + bool operator==(const iterator & right) const + { + return (m_pParent == right.m_pParent && m_Index == right.m_Index); + } + + bool operator!=(const iterator & right) const + { + return !(*this == right); + } + }; + CStack() : m_Elements(new T[SH_STACK_DEFAULT_SIZE]), + m_AllocatedSize(SH_STACK_DEFAULT_SIZE), + m_UsedSize(0) + { + } + CStack(size_t size) : m_Elements(new T[size]), + m_AllocatedSize(size), + m_UsedSize(0) + { + } + + CStack(const CStack &other) : m_Elements(NULL), + m_AllocatedSize(0), + m_UsedSize(0) + { + reserve(other.m_AllocatedSize); + m_UsedSize = other.m_UsedSize; + for (size_t i = 0; i < m_UsedSize; ++i) + m_Elements[i] = other.m_Elements[i]; + } + + ~CStack() + { + if (m_Elements) + delete [] m_Elements; + } + + void operator=(const CStack &other) + { + if (m_AllocatedSize < other.m_AllocatedSize) + { + if (m_Elements) + delete [] m_Elements; + m_Elements = new T[other.m_AllocatedSize]; + m_AllocatedSize = other.m_AllocatedSize; + } + m_UsedSize = other.m_UsedSize; + for (size_t i = 0; i < m_UsedSize; ++i) + m_Elements[i] = other.m_Elements[i]; + } + + bool push(const T &val) + { + if (m_UsedSize + 1 == m_AllocatedSize) + { + // zOHNOES! REALLOCATE! + m_AllocatedSize *= 2; + T *newElements = new T[m_AllocatedSize]; + if (!newElements) + { + m_AllocatedSize /= 2; + return false; + } + if (m_Elements) + { + for (size_t i = 0; i < m_UsedSize; ++i) + newElements[i] = m_Elements[i]; + delete [] m_Elements; + } + m_Elements = newElements; + } + m_Elements[m_UsedSize++] = val; + return true; + } + void pop() + { + --m_UsedSize; + } + + T &front() + { + return m_Elements[m_UsedSize - 1]; + } + + const T &front() const + { + return m_Elements[m_UsedSize - 1]; + } + + iterator begin() + { + return iterator(this, 0); + } + iterator end() + { + return iterator(this, m_UsedSize); + } + + size_t size() + { + return m_UsedSize; + } + size_t capacity() + { + return m_AllocatedSize; + } + bool empty() + { + return m_UsedSize == 0 ? true : false; + } + bool reserve(size_t size) + { + if (size > m_AllocatedSize) + { + T *newElements = new T[size]; + if (!newElements) + return false; + if (m_Elements) + { + for (size_t i = 0; i < m_UsedSize; ++i) + newElements[i] = m_Elements[i]; + delete [] m_Elements; + } + m_Elements = newElements; + m_AllocatedSize = size; + } + return true; + } + }; +//}; //namespace SourceHook + +#endif diff --git a/dlls/hamsandwich/srvcmd.cpp b/dlls/hamsandwich/srvcmd.cpp index ba4a21d5..3efc3f7d 100644 --- a/dlls/hamsandwich/srvcmd.cpp +++ b/dlls/hamsandwich/srvcmd.cpp @@ -74,8 +74,8 @@ void HamCommand(void) } else if (strcmp(cmd, "hooks")==0) { - print_srvconsole("%-24s | %-32s | %10s | %10s\n", "Key", "Classname", "Pre", "Post"); - print_srvconsole("-------------------------------------------------------------------------------------\n"); + print_srvconsole("%-24s | %-27s | %10s | %10s\n", "Key", "Classname", "Pre", "Post"); + print_srvconsole("--------------------------------------------------------------------------------\n"); unsigned int ForwardCount=0; unsigned int HookCount=0; int count = 0; @@ -90,14 +90,14 @@ void HamCommand(void) HookCount++; ForwardCount+=(*j)->pre.size() + (*j)->post.size(); - print_srvconsole("%-24s | %-32s | %10d | %10d\n",hooklist[i].name, (*j)->ent, (*j)->pre.size(), (*j)->post.size()); + print_srvconsole("%-24s | %-27s | %10d | %10d\n",hooklist[i].name, (*j)->ent, (*j)->pre.size(), (*j)->post.size()); if (count >= 5) { - print_srvconsole("-------------------------------------------------------------------------------------\n"); + print_srvconsole("--------------------------------------------------------------------------------\n"); } } } - print_srvconsole("\n%u active hooks, %u active forwards.\n\n", HookCount, ForwardCount); + print_srvconsole("\n%u hooks, %u forwards.\n\n", HookCount, ForwardCount); return; }