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:
parent
8647cd083d
commit
fb5ec01319
@ -1,3 +1,3 @@
|
||||
majorVersion=5
|
||||
minorVersion=15
|
||||
minorVersion=16
|
||||
maintenanceVersion=0
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -23,6 +23,8 @@ struct hook_t
|
||||
regchain_t unregisterHookchain; // unregister re* API hook
|
||||
|
||||
void clear();
|
||||
|
||||
bool wasCalled;
|
||||
};
|
||||
|
||||
extern hook_t hooklist_engine[];
|
||||
|
@ -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 }
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user