2
0
mirror of https://github.com/rehlds/reapi.git synced 2024-12-27 23:25:30 +03:00

Implemented IsReapiHookOriginalWasCalled which determine whether original function was called or not (#172)

This commit is contained in:
shel 2020-10-02 18:43:07 +04:00 committed by GitHub
parent 8647cd083d
commit fb5ec01319
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 70 additions and 10 deletions

View File

@ -1,3 +1,3 @@
majorVersion=5
minorVersion=15
minorVersion=16
maintenanceVersion=0

View File

@ -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.

View File

@ -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))
@ -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>
@ -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))
@ -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) {
@ -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;
}

View File

@ -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),
@ -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),
@ -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),

View File

@ -23,6 +23,8 @@ struct hook_t
regchain_t unregisterHookchain; // unregister re* API hook
void clear();
bool wasCalled;
};
extern hook_t hooklist_engine[];

View File

@ -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 },
@ -326,6 +358,8 @@ AMX_NATIVE_INFO HookChain_Natives[] =
{ "SetHookChainArg", SetHookChainArg },
{ "IsReapiHookOriginalWasCalled", IsReapiHookOriginalWasCalled },
{ nullptr, nullptr }
};