Skip to content

Commit

Permalink
Implemented IsReapiHookOriginalWasCalled which determine whether orig…
Browse files Browse the repository at this point in the history
…inal function was called or not (#172)
  • Loading branch information
afwn90cj93201nixr2e1re authored Oct 2, 2020
1 parent 8647cd0 commit fb5ec01
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 10 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
majorVersion=5
minorVersion=15
minorVersion=16
maintenanceVersion=0
10 changes: 10 additions & 0 deletions reapi/extra/amxmodx/scripting/include/reapi.inc
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,16 @@ native any:GetHookChainReturn(AType:type, any:...);
*/
native SetHookChainArg(number, AType:type, any:...);

/*
* Return call state of original API function (that are available into enum).
* Look at the enums for parameter lists.
*
* @param func The function to get state
*
* @return Returns true if the original function was called, otherwise false
*/
native bool:IsReapiHookOriginalWasCalled({EngineFunc, GamedllFunc, GamedllFunc_CBaseAnimating, GamedllFunc_CBasePlayer, GamedllFunc_CSGameRules, GamedllFunc_CGrenade, GamedllFunc_CWeaponBox, ReCheckerFunc, GamedllFunc_CBasePlayerWeapon, GamedllFunc_CGib}:function_id);

/*
* Compares the entity to a specified classname.
* @note This native also checks the validity of an entity.
Expand Down
26 changes: 20 additions & 6 deletions reapi/src/hook_callback.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,14 @@ struct hookctx_t
extern hookctx_t* g_hookCtx;

template <typename original_t, typename ...f_args>
NOINLINE void DLLEXPORT _callVoidForward(const hook_t* hook, original_t original, f_args&&... args)
NOINLINE void DLLEXPORT _callVoidForward(hook_t* hook, original_t original, f_args&&... args)
{
auto hookCtx = g_hookCtx;
hookCtx->reset();
int hc_state = HC_CONTINUE;

hook->wasCalled = false;

for (auto fwd : hook->pre)
{
if (likely(fwd->GetState() == FSTATE_ENABLED))
Expand All @@ -169,16 +171,21 @@ NOINLINE void DLLEXPORT _callVoidForward(const hook_t* hook, original_t original
g_hookCtx = nullptr;
original(std::forward<f_args &&>(args)...);
g_hookCtx = hookCtx;
hook->wasCalled = true;
}

for (auto fwd : hook->post) {
if (likely(fwd->GetState() == FSTATE_ENABLED)) {
for (auto fwd : hook->post)
{
if (likely(fwd->GetState() == FSTATE_ENABLED))
{
auto ret = g_amxxapi.ExecuteForward(fwd->GetIndex(), std::forward<f_args &&>(args)...);

if (unlikely(ret == HC_BREAK))
break;
}
}

hook->wasCalled = false;
}

template <typename original_t, typename ...f_args>
Expand All @@ -197,13 +204,15 @@ void callVoidForward(size_t func, original_t original, f_args&&... args)
}

template <typename R, typename original_t, typename ...f_args>
NOINLINE R DLLEXPORT _callForward(const hook_t* hook, original_t original, f_args&&... args)
NOINLINE R DLLEXPORT _callForward(hook_t* hook, original_t original, f_args&&... args)
{
auto hookCtx = g_hookCtx;
hookCtx->reset(getApiType(R()));

int hc_state = HC_CONTINUE;

hook->wasCalled = false;

for (auto fwd : hook->pre)
{
if (likely(fwd->GetState() == FSTATE_ENABLED))
Expand Down Expand Up @@ -233,6 +242,7 @@ NOINLINE R DLLEXPORT _callForward(const hook_t* hook, original_t original, f_arg
g_hookCtx = nullptr;
auto retVal = original(std::forward<f_args &&>(args)...);
g_hookCtx = hookCtx;
hook->wasCalled = true;

if (unlikely(!hookCtx->retVal.set)) {
switch (sizeof retVal) {
Expand All @@ -250,14 +260,18 @@ NOINLINE R DLLEXPORT _callForward(const hook_t* hook, original_t original, f_arg
}
}

for (auto fwd : hook->post) {
if (likely(fwd->GetState() == FSTATE_ENABLED)) {
for (auto fwd : hook->post)
{
if (likely(fwd->GetState() == FSTATE_ENABLED))
{
auto ret = g_amxxapi.ExecuteForward(fwd->GetIndex(), std::forward<f_args &&>(args)...);

if (unlikely(ret == HC_BREAK))
break;
}
}

hook->wasCalled = false;

return *(R *)&hookCtx->retVal._integer;
}
Expand Down
6 changes: 3 additions & 3 deletions reapi/src/hook_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ struct regfunc

int regfunc::current_cell = 1;

#define ENG(h,...) { {}, {}, #h, "ReHLDS", [](){ return api_cfg.hasReHLDS(); }, ((!(RH_##h & (MAX_REGION_RANGE - 1)) ? regfunc::current_cell = 1, true : false) || (RH_##h & (MAX_REGION_RANGE - 1)) == regfunc::current_cell++) ? regfunc(h##__VA_ARGS__) : regfunc(#h#__VA_ARGS__), [](){ g_RehldsHookchains->h()->registerHook(&h); }, [](){ g_RehldsHookchains->h()->unregisterHook(&h); }}
#define ENG(h,...) { {}, {}, #h, "ReHLDS", [](){ return api_cfg.hasReHLDS(); }, ((!(RH_##h & (MAX_REGION_RANGE - 1)) ? regfunc::current_cell = 1, true : false) || (RH_##h & (MAX_REGION_RANGE - 1)) == regfunc::current_cell++) ? regfunc(h##__VA_ARGS__) : regfunc(#h#__VA_ARGS__), [](){ g_RehldsHookchains->h()->registerHook(&h); }, [](){ g_RehldsHookchains->h()->unregisterHook(&h); }, false}
hook_t hooklist_engine[] = {
ENG(SV_StartSound),
ENG(SV_DropClient),
Expand All @@ -80,7 +80,7 @@ hook_t hooklist_engine[] = {
ENG(SV_WriteFullClientUpdate, _AMXX)
};

#define DLL(h,...) { {}, {}, #h, "ReGameDLL", [](){ return api_cfg.hasReGameDLL(); }, ((!(RG_##h & (MAX_REGION_RANGE - 1)) ? regfunc::current_cell = 1, true : false) || (RG_##h & (MAX_REGION_RANGE - 1)) == regfunc::current_cell++) ? regfunc(h##__VA_ARGS__) : regfunc(#h#__VA_ARGS__), [](){ g_ReGameHookchains->h()->registerHook(&h); }, [](){ g_ReGameHookchains->h()->unregisterHook(&h); }}
#define DLL(h,...) { {}, {}, #h, "ReGameDLL", [](){ return api_cfg.hasReGameDLL(); }, ((!(RG_##h & (MAX_REGION_RANGE - 1)) ? regfunc::current_cell = 1, true : false) || (RG_##h & (MAX_REGION_RANGE - 1)) == regfunc::current_cell++) ? regfunc(h##__VA_ARGS__) : regfunc(#h#__VA_ARGS__), [](){ g_ReGameHookchains->h()->registerHook(&h); }, [](){ g_ReGameHookchains->h()->unregisterHook(&h); }, false}
hook_t hooklist_gamedll[] = {
DLL(GetForceCamera),
DLL(PlayerBlind),
Expand Down Expand Up @@ -213,7 +213,7 @@ hook_t hooklist_gib[] = {
DLL(CGib_WaitTillLand),
};

#define RCHECK(h,...) { {}, {}, #h, "ReChecker", [](){ return api_cfg.hasRechecker(); }, ((!(RC_##h & (MAX_REGION_RANGE - 1)) ? regfunc::current_cell = 1, true : false) || (RC_##h & (MAX_REGION_RANGE - 1)) == regfunc::current_cell++) ? regfunc(h##__VA_ARGS__) : regfunc(#h#__VA_ARGS__), [](){ g_RecheckerHookchains->h()->registerHook(&h); }, [](){ g_RecheckerHookchains->h()->unregisterHook(&h); }}
#define RCHECK(h,...) { {}, {}, #h, "ReChecker", [](){ return api_cfg.hasRechecker(); }, ((!(RC_##h & (MAX_REGION_RANGE - 1)) ? regfunc::current_cell = 1, true : false) || (RC_##h & (MAX_REGION_RANGE - 1)) == regfunc::current_cell++) ? regfunc(h##__VA_ARGS__) : regfunc(#h#__VA_ARGS__), [](){ g_RecheckerHookchains->h()->registerHook(&h); }, [](){ g_RecheckerHookchains->h()->unregisterHook(&h); }, false}
hook_t hooklist_rechecker[] = {
RCHECK(FileConsistencyProcess, _AMXX),
RCHECK(FileConsistencyFinal),
Expand Down
2 changes: 2 additions & 0 deletions reapi/src/hook_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ struct hook_t
regchain_t unregisterHookchain; // unregister re* API hook

void clear();

bool wasCalled;
};

extern hook_t hooklist_engine[];
Expand Down
34 changes: 34 additions & 0 deletions reapi/src/natives/natives_hookchains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,38 @@ cell AMX_NATIVE_CALL SetHookChainArg(AMX *amx, cell *params)
return TRUE;
}

/*
* Return call state of original API function (that are available into enum).
* Look at the enums for parameter lists.
*
* @param func The function to get state
*
* @return Returns true if the API original function was called, otherwise false
*
* native bool:IsReapiHookOriginalWasCalled(any:function_id);
*/
cell AMX_NATIVE_CALL IsReapiHookOriginalWasCalled(AMX* amx, cell* params)
{
enum args_e { arg_count, arg_func };

int func = params[arg_func];
auto hook = g_hookManager.getHook(func);

if (unlikely(hook == nullptr))
{
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: function with id (%d) doesn't exist in current API version.", __FUNCTION__, func);
return INVALID_HOOKCHAIN;
}

if (unlikely(!hook->checkRequirements()))
{
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: function (%s) is not available, %s required.", __FUNCTION__, hook->func_name, hook->depend_name);
return INVALID_HOOKCHAIN;
}

return hook->wasCalled ? TRUE : FALSE;
}

AMX_NATIVE_INFO HookChain_Natives[] =
{
{ "RegisterHookChain", RegisterHookChain },
Expand All @@ -326,6 +358,8 @@ AMX_NATIVE_INFO HookChain_Natives[] =

{ "SetHookChainArg", SetHookChainArg },

{ "IsReapiHookOriginalWasCalled", IsReapiHookOriginalWasCalled },

{ nullptr, nullptr }
};

Expand Down

0 comments on commit fb5ec01

Please sign in to comment.