2
0
mirror of https://github.com/s1lentq/reapi.git synced 2024-10-16 15:27:06 +03:00

Callbacks refactoring

Implemented hookchain arguments changing
This commit is contained in:
asmodai 2016-04-13 19:55:25 +03:00
parent 219071fb50
commit 59be98fb6a
10 changed files with 154 additions and 91 deletions

View File

@ -45,7 +45,7 @@ void setupToolchain(NativeBinarySpec b) {
pchHeader: 'precompiled.h',
pchSourceSet: 'reapi_pch'
)
cfg.compilerOptions.args '/Ob2', '/Oi', '/GF', '/GR-'
cfg.compilerOptions.args '/Ob2', '/Oi', '/GF', '/GR-', '/GS-'
cfg.singleDefines('_CRT_SECURE_NO_WARNINGS')
cfg.extraLibs 'ws2_32.lib'
} else if (cfg instanceof GccToolchainConfig) {
@ -61,7 +61,7 @@ void setupToolchain(NativeBinarySpec b) {
'_snprintf': 'snprintf'
])
cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp', '-msse2', '-fp-model fast', '-fomit-frame-pointer', '-fvisibility-inlines-hidden', '-fno-rtti', '-g0', '-s'
cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp', '-msse2', '-fp-model fast=2', '-fomit-frame-pointer', '-inline-forceinline', '-fvisibility-inlines-hidden', '-fno-rtti', '-g0', '-s'
}
ToolchainConfigUtils.apply(project, cfg, b)

View File

@ -361,6 +361,7 @@
<StringPooling>true</StringPooling>
<ExceptionHandling>Sync</ExceptionHandling>
<OmitFramePointers>true</OmitFramePointers>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>

View File

@ -494,7 +494,7 @@ extern amxxapi_t g_amxxapi;
void MF_Log(const char *fmt, ...);
void MF_LogError(AMX *amx, int err, const char *fmt, ...);
char* getAmxStringTemp(cell* src, char* dest, size_t max, size_t* len);
char* getAmxStringTemp(cell* src, char* dest, size_t max, size_t* len = nullptr);
void setAmxString(cell* dest, const char* string, size_t max);
inline cell* getAmxAddr(AMX *amx, cell amx_addr)
@ -504,11 +504,16 @@ inline cell* getAmxAddr(AMX *amx, cell amx_addr)
struct getAmxString
{
getAmxString(cell* src, size_t* len)
getAmxString(cell* src, size_t* len = nullptr)
{
getAmxStringTemp(src, temp, sizeof temp - 1, len);
}
getAmxString(AMX* amx, cell addr, size_t* len = nullptr)
{
getAmxString(getAmxAddr(amx, addr), len);
}
operator char *()
{
return temp;

View File

@ -246,6 +246,7 @@ void CBasePlayer_ImpulseCommands(IReGameHook_CBasePlayer_ImpulseCommands *chain,
{
chain->callNext();
};
callVoidForward(RH_CBasePlayer_ImpulseCommands, original, pthis->entindex());
}

View File

@ -39,18 +39,17 @@ inline AType getApiType(float) { return ATYPE_FLOAT; }
inline AType getApiType(const char *) { return ATYPE_STRING; }
inline AType getApiType(CBaseEntity *) { return ATYPE_CLASSPTR; }
#define MAX_ARGS 12u
template<size_t current>
void setupArgTypes(AType args_type[])
void setupArgTypes(AType args_type[MAX_ARGS])
{
}
#define MAX_ARGS 10u
template<size_t current = 0, typename T, typename ...t_args>
void setupArgTypes(AType args_type[MAX_ARGS], T arg, t_args... args)
{
args_type[current] = getApiType(arg);
args_type[current] = getApiType(T());
if (sizeof...(args) && current + 1 < MAX_ARGS)
setupArgTypes<current + 1>(args_type, args...);
}
@ -58,13 +57,19 @@ void setupArgTypes(AType args_type[MAX_ARGS], T arg, t_args... args)
struct hookctx_t
{
template<typename ...t_args>
hookctx_t(size_t count, size_t ptr, t_args... args)
hookctx_t(size_t arg_count, t_args... args) : args_ptr()
{
args_count = min(count, MAX_ARGS);
args_ptr = ptr;
args_count = min(arg_count, MAX_ARGS);
setupArgTypes(args_type, args...);
}
void reset(size_t arg_ptr, AType ret_type = ATYPE_INTEGER)
{
retVal.set = false;
retVal.type = ret_type;
args_ptr = arg_ptr;
}
retval_t retVal;
size_t args_count;
size_t args_ptr;
@ -73,15 +78,26 @@ struct hookctx_t
extern hookctx_t* g_hookCtx;
template <typename original_t, typename ...f_args>
void callVoidForward(int func, original_t original, f_args... args)
{
hookctx_t hookCtx(sizeof...(args), size_t(&original) + sizeof(original), args...);
hookCtx.retVal.set = false;
g_hookCtx = &hookCtx;
#pragma optimize("ts", on)
template <typename original_t, typename ...f_args>
void callVoidForward(size_t func, original_t original, f_args... args)
{
#ifndef _WIN32
static
#endif
hookctx_t hookCtx(sizeof...(args), args...);
g_hookCtx = &hookCtx;
_callVoidForward(g_hookManager.getHook(func), original, args...);
g_hookCtx = nullptr;
}
template <typename original_t, typename ...f_args>
NOINLINE void DLLEXPORT _callVoidForward(const hook_t* hook, original_t original, volatile f_args... args)
{
g_hookCtx->reset(size_t(&original) + sizeof(original));
int hc_state = HC_CONTINUE;
auto hook = g_hookManager.getHook(func);
for (auto& fwd : hook->pre)
{
@ -90,7 +106,6 @@ void callVoidForward(int func, original_t original, f_args... args)
auto ret = g_amxxapi.ExecuteForward(fwd->m_forward, args...);
if (ret == HC_BREAK) {
g_hookCtx = nullptr;
return;
}
@ -112,20 +127,29 @@ void callVoidForward(int func, original_t original, f_args... args)
break;
}
}
g_hookCtx = nullptr;
}
template <typename R, typename original_t, typename ...f_args>
R callForward(int func, original_t original, f_args... args)
R callForward(size_t func, original_t original, f_args... args)
{
hookctx_t hookCtx(sizeof...(args), size_t(&original) + sizeof(original), args...);
hookCtx.retVal.set = false;
hookCtx.retVal.type = getApiType(R());
g_hookCtx = &hookCtx;
#ifndef _WIN32
static
#endif
hookctx_t hookCtx(sizeof...(args), args...);
g_hookCtx = &hookCtx;
auto ret = _callForward<R>(g_hookManager.getHook(func), original, args...);
g_hookCtx = nullptr;
return ret;
}
template <typename R, typename original_t, typename ...f_args>
NOINLINE R DLLEXPORT _callForward(const hook_t* hook, original_t original, volatile f_args... args)
{
auto& hookCtx = *g_hookCtx;
hookCtx.reset(size_t(&original) + sizeof(original), getApiType(R()));
int hc_state = HC_CONTINUE;
auto hook = g_hookManager.getHook(func);
for (auto& fwd : hook->pre)
{
@ -136,15 +160,13 @@ R callForward(int func, original_t original, f_args... args)
if (ret == HC_CONTINUE)
continue;
if (!hookCtx.retVal.set)
{
if (!hookCtx.retVal.set) {
g_amxxapi.LogError(fwd->GetAmx(), AMX_ERR_CALLBACK, "%s", "can't suppress original function call without new return value set");
continue;
}
if (ret == HC_BREAK) {
g_hookCtx = nullptr;
return (R)hookCtx.retVal._interger;
return *(R *)&hookCtx.retVal._interger;
}
if (ret > hc_state)
@ -169,10 +191,11 @@ R callForward(int func, original_t original, f_args... args)
}
}
g_hookCtx = nullptr;
return (R)hookCtx.retVal._interger;
return *(R *)&hookCtx.retVal._interger;
}
#pragma optimize("", on)
// rehlds functions
void SV_StartSound(IRehldsHook_SV_StartSound *chain, int recipients, edict_t *entity, int channel, const char *sample, int volume, float attenuation, int fFlags, int pitch);
void SV_DropClient(IRehldsHook_SV_DropClient *chain, IGameClient *cl, bool crash, const char *fmt);

View File

@ -41,7 +41,7 @@ hook_t hooklist_player[] = {
DLL(CBasePlayer_Observer_IsValidTarget),
};
hook_t *hooklist_t::operator[](size_t hook) const
/*hook_t *hooklist_t::getHook(size_t hook)
{
#define CASE(h) case ht_##h: if (index < arraysize(hooklist_##h)) return &hooklist_##h[index]; else break;
@ -55,4 +55,8 @@ hook_t *hooklist_t::operator[](size_t hook) const
}
return nullptr;
}
}*/
const size_t hooklist_engine_size = arraysize(hooklist_engine);
const size_t hooklist_gamedll_size = arraysize(hooklist_gamedll);
const size_t hooklist_player_size = arraysize(hooklist_player);

View File

@ -101,9 +101,42 @@ struct hook_t
regchain_t unregisterHookchain; // unregister re* API hook
};
extern hook_t hooklist_engine[];
extern hook_t hooklist_gamedll[];
extern hook_t hooklist_player[];
extern const size_t hooklist_engine_size;
extern const size_t hooklist_gamedll_size;
extern const size_t hooklist_player_size;
struct hooklist_t
{
hook_t *operator[](size_t hook) const;
hook_t *operator[](size_t hook) const
{
#define CASE(h) case ht_##h: if (index < hooklist_##h##_size) return &hooklist_##h[index]; else break;
const auto table = hooks_tables_e(hook / MAX_REGION_RANGE);
const auto index = hook & (MAX_REGION_RANGE - 1);
switch (table) {
CASE(engine)
CASE(gamedll)
CASE(player)
}
return nullptr;
/*const auto table = hooks_tables_e(hook / MAX_REGION_RANGE);
const auto index = hook & (MAX_REGION_RANGE - 1);
switch (table) {
case ht_engine: return &hooklist_engine[index];
case ht_gamedll: return &hooklist_gamedll[index];
case ht_player: return &hooklist_player[index];
}
return nullptr;*/
}
//static hook_t *getHook(size_t hook);
enum hooks_tables_e
{
@ -197,6 +230,3 @@ enum GamedllFunc_CBasePlayer
// [...]
RH_CBasePlayer_End
};
extern hook_t hooklist_engine[];
extern hook_t hooklist_player[];

View File

@ -3,7 +3,7 @@
struct regmember
{
template<typename T>
regmember(T &type, size_t maxsize, size_t offset, enum_membertypes member_type)
regmember(T& type, size_t maxsize, size_t offset, enum_membertypes member_type)
{
member.size = sizeof(T);
member.max_size = sizeof(T);

View File

@ -32,8 +32,8 @@ static cell AMX_NATIVE_CALL RegisterHookChain(AMX *amx, cell *params)
return 0;
}
int funcid, len;
const char *funcname = g_amxxapi.GetAmxString(amx, params[arg_handler], 0, &len);
int funcid;
const char *funcname = getAmxString(amx, params[arg_handler]);
if (g_amxxapi.amx_FindPublic(amx, funcname, &funcid) != AMX_ERR_NONE)
{
MF_LogError(amx, AMX_ERR_NATIVE, "RegisterHookChain: public function \"%s\" not found.", funcname);
@ -69,11 +69,11 @@ static cell AMX_NATIVE_CALL EnableHookChain(AMX *amx, cell *params)
if (hook == nullptr)
{
MF_LogError(amx, AMX_ERR_NATIVE, "EnableHookChain: invalid HookChain handle.");
return 0;
return FALSE;
}
hook->m_state = FSTATE_ENABLED;
return 1;
return TRUE;
}
/*
@ -94,11 +94,11 @@ static cell AMX_NATIVE_CALL DisableHookChain(AMX *amx, cell *params)
if (hook == nullptr)
{
MF_LogError(amx, AMX_ERR_NATIVE, "DisableHookChain: invalid HookChain handle.");
return 0;
return FALSE;
}
hook->m_state = FSTATE_STOPPED;
return 1;
return TRUE;
}
/*
@ -116,7 +116,7 @@ static cell AMX_NATIVE_CALL SetHookChainReturn(AMX *amx, cell *params)
if (!g_hookCtx)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Trying to set return value without active hook.");
return 0;
return FALSE;
}
enum args_e { arg_count, arg_type, arg_value };
@ -125,7 +125,7 @@ static cell AMX_NATIVE_CALL SetHookChainReturn(AMX *amx, cell *params)
if (params[arg_type] != retVal.type)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Trying to set incompatible return type.");
return 0;
return FALSE;
}
cell* srcAddr = getAmxAddr(amx, params[arg_value]);
@ -151,11 +151,11 @@ static cell AMX_NATIVE_CALL SetHookChainReturn(AMX *amx, cell *params)
retVal._classptr = CBaseEntity::Instance(INDEXENT(*srcAddr));
break;
default:
return 0;
return FALSE;
}
retVal.set = true;
return 1;
return TRUE;
}
/*
@ -174,7 +174,7 @@ static cell AMX_NATIVE_CALL GetHookChainReturn(AMX *amx, cell *params)
if (!g_hookCtx)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Trying to get return value without active hook.");
return 0;
return FALSE;
}
enum args_e { arg_count, arg_value, arg_maxlen };
@ -191,7 +191,7 @@ static cell AMX_NATIVE_CALL GetHookChainReturn(AMX *amx, cell *params)
case ATYPE_STRING:
{
if (params[arg_count] != 2)
return 0;
return FALSE;
setAmxString(dstAddr, retVal._string, params[arg_maxlen]);
break;
@ -200,10 +200,10 @@ static cell AMX_NATIVE_CALL GetHookChainReturn(AMX *amx, cell *params)
*dstAddr = retVal._classptr->entindex();
break;
default:
return 0;
return FALSE;
}
return 1;
return TRUE;
}
/*
@ -223,17 +223,16 @@ static cell AMX_NATIVE_CALL SetHookChainArg(AMX *amx, cell *params)
if (!g_hookCtx)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Trying to get return value without active hook.");
return 0;
return FALSE;
}
enum args_e { arg_count, arg_number, arg_type, arg_value };
size_t number = params[arg_number] - 1;
if (number >= g_hookCtx->args_count)
{
MF_LogError(amx, AMX_ERR_NATIVE, "SetHookChainArg: can't set argument %i of hookchain with %i args.", params[arg_number], g_hookCtx->args_count);
return 0;
return FALSE;
}
AType type = g_hookCtx->args_type[number];
@ -241,7 +240,7 @@ static cell AMX_NATIVE_CALL SetHookChainArg(AMX *amx, cell *params)
if (params[arg_type] != type)
{
MF_LogError(amx, AMX_ERR_NATIVE, "SetHookChainArg: invalid argument type provided.");
return 0;
return FALSE;
}
static char temp_strings[MAX_ARGS][1024];
@ -256,14 +255,14 @@ static cell AMX_NATIVE_CALL SetHookChainArg(AMX *amx, cell *params)
*(cell *)destAddr = *srcAddr;
break;
case ATYPE_STRING:
*(char **)destAddr = getAmxStringTemp(srcAddr, temp_strings[number], 1023, nullptr);
*(char **)destAddr = getAmxStringTemp(srcAddr, temp_strings[number], 1023);
break;
case ATYPE_CLASSPTR:
*(CBaseEntity **)destAddr = CBaseEntity::Instance(INDEXENT(*srcAddr));
break;
}
return 1;
return TRUE;
}
AMX_NATIVE_INFO Func_Natives[] =

View File

@ -8,13 +8,13 @@ static cell AMX_NATIVE_CALL set_member(AMX *amx, cell *params)
if (member == nullptr) {
MF_LogError(amx, AMX_ERR_NATIVE, "set_member: unknown member id %i", params[arg_member]);
return 0;
return FALSE;
}
edict_t *pEdict = INDEXENT(params[arg_index]);
if (pEdict == nullptr || pEdict->pvPrivateData == nullptr) {
MF_LogError(amx, AMX_ERR_NATIVE, "set_member: invalid or uninitialized entity", params[arg_member]);
return 0;
return FALSE;
}
cell* value = getAmxAddr(amx, params[arg_value]);
@ -23,7 +23,7 @@ static cell AMX_NATIVE_CALL set_member(AMX *amx, cell *params)
switch (member->type)
{
case MEMBER_ENTITY:
return -1;
return FALSE;
case MEMBER_CLASSPTR:
{
// native set_member(_index, any:_member, _value, _elem);
@ -34,7 +34,7 @@ static cell AMX_NATIVE_CALL set_member(AMX *amx, cell *params)
pEntity = CBaseEntity::Instance(pEdictValue);
}
set_member<CBaseEntity *>(pEdict, member->offset, pEntity, element);
return 1;
return TRUE;
}
case MEMBER_EHANDLE:
{
@ -42,23 +42,23 @@ static cell AMX_NATIVE_CALL set_member(AMX *amx, cell *params)
EHANDLE& ehandle = get_member<EHANDLE>(pEdict, member->offset, element);
edict_t *pEdictValue = INDEXENT(*value);
ehandle.Set(pEdictValue);
return 1;
return TRUE;
}
case MEMBER_EVARS:
return -1;
return FALSE;
case MEMBER_EDICT:
{
// native set_member(_index, any:_member, _value, _elem);
edict_t *pEdictValue = INDEXENT(*value);
set_member<edict_t *>(pEdict, member->offset, pEdictValue, element);
return 1;
return TRUE;
}
case MEMBER_VECTOR:
{
// native set_member(_index, any:_member, Float:_value[3], _elem);
Vector *pSource = (Vector *)getAmxAddr(amx, params[arg_value]);
set_member<Vector>(pEdict, member->offset, *pSource, element);
return 1;
return TRUE;
}
case MEMBER_CHAR_ARRAY:
{
@ -68,7 +68,7 @@ static cell AMX_NATIVE_CALL set_member(AMX *amx, cell *params)
char *dest = get_member_direct<char *>(pEdict, member->offset);
strncpy(dest, source, member->max_size - 1);
dest[member->max_size - 1] = '\0';
return 1;
return TRUE;
}
case MEMBER_CHAR_POINTER:
{
@ -85,51 +85,51 @@ static cell AMX_NATIVE_CALL set_member(AMX *amx, cell *params)
strcpy(dest, source);
set_member<char *>(pEdict, member->offset, dest);
return 1;
return TRUE;
}
case MEMBER_FLOAT:
case MEMBER_INTEGER:
{
// native set_member(_index, any:_member, any:_value, _elem);
set_member<int>(pEdict, member->offset, *value, element);
return 1;
return TRUE;
}
case MEMBER_SHORT:
{
// native set_member(_index, any:_member, _value, _elem);
set_member<short>(pEdict, member->offset, *value, element);
return 1;
return TRUE;
}
case MEMBER_BYTE:
{
// native set_member(_index, any:_member, _value, _elem);
set_member<byte>(pEdict, member->offset, *value, element);
return 1;
return TRUE;
}
case MEMBER_BOOL:
{
// native set_member(_index, any:_member, bool:_value, _elem);
set_member<bool>(pEdict, member->offset, *value != 0, element);
return 1;
return TRUE;
}
case MEMBER_SIGNALS:
{
// native set_member(_index, any:_member, _value);
CUnifiedSignals& signal = get_member<CUnifiedSignals>(pEdict, member->offset, element);
signal.Signal(*value);
return 1;
return TRUE;
}
case MEMBER_DOUBLE:
{
// native set_member(_index, any:_member, any:_value, _elem);
set_member<double>(pEdict, member->offset, *(float *)value, element);
return 1;
return TRUE;
}
case MEBMER_REBUYSTRUCT:
return -1;
return FALSE;
}
return 0;
return FALSE;
}
// native any:get_member(_index = 0, any:_member, any:...);
@ -140,13 +140,13 @@ static cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params)
if (member == nullptr) {
MF_LogError(amx, AMX_ERR_NATIVE, "Member (%d) is unknown", params[arg_member]);
return 0;
return FALSE;
}
edict_t *pEdict = INDEXENT(params[arg_index]);
if (pEdict == nullptr || pEdict->pvPrivateData == nullptr) {
return 0;
return FALSE;
}
size_t element = *g_amxxapi.GetAmxAddr(amx, params[arg_elem]);
@ -154,7 +154,7 @@ static cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params)
switch (member->type)
{
case MEMBER_ENTITY:
return -1;
return FALSE;
case MEMBER_CLASSPTR:
// native any:get_member(_index, any:_member, element);
return get_member<CBaseEntity *>(pEdict, member->offset, element)->entindex();
@ -166,7 +166,7 @@ static cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params)
if (pEntity != nullptr) {
return ((CBaseEntity *)ehandle)->entindex();
}
return 0;
return FALSE;
}
case MEMBER_EVARS:
return -1;
@ -178,7 +178,7 @@ static cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params)
return indexOfEdict(pEntity);
}
return 0;
return FALSE;
}
case MEMBER_VECTOR:
{
@ -207,7 +207,7 @@ static cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params)
g_amxxapi.SetAmxString(amx, params[3], dest, *g_amxxapi.GetAmxAddr(amx, params[4]));
return 1;
}
return 0;
return FALSE;
}
case MEMBER_FLOAT:
case MEMBER_INTEGER:
@ -244,7 +244,7 @@ static cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params)
return -1;
}
return 0;
return FALSE;
}
// native set_member_game(any:_member, any:...);
@ -255,7 +255,7 @@ static cell AMX_NATIVE_CALL set_member_game(AMX *amx, cell *params)
if (member == nullptr) {
MF_LogError(amx, AMX_ERR_NATIVE, "Member (%d) is unknown", params[arg_member]);
return 0;
return FALSE;
}
size_t value = *g_amxxapi.GetAmxAddr(amx, params[arg_value]);
@ -273,7 +273,7 @@ static cell AMX_NATIVE_CALL set_member_game(AMX *amx, cell *params)
case MEMBER_BYTE:
case MEMBER_SIGNALS:
case MEBMER_REBUYSTRUCT:
return -1;
return FALSE;
case MEMBER_CLASSPTR:
{
// native set_member_game(any:_member, _value, _elem);
@ -313,7 +313,7 @@ static cell AMX_NATIVE_CALL set_member_game(AMX *amx, cell *params)
}
}
return 0;
return FALSE;
}
// native get_member_game(any:_member, any:...);
@ -324,7 +324,7 @@ static cell AMX_NATIVE_CALL get_member_game(AMX *amx, cell *params)
if (member == nullptr) {
MF_LogError(amx, AMX_ERR_NATIVE, "Member (%d) is unknown", params[arg_member]);
return 0;
return FALSE;
}
size_t element = *g_amxxapi.GetAmxAddr(amx, params[arg_elem]);
@ -370,7 +370,7 @@ static cell AMX_NATIVE_CALL get_member_game(AMX *amx, cell *params)
}
}
return 0;
return FALSE;
}
AMX_NATIVE_INFO Member_Natives[] =