mirror of
https://github.com/rehlds/reapi.git
synced 2024-12-29 08:05:36 +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
|
majorVersion=5
|
||||||
minorVersion=15
|
minorVersion=16
|
||||||
maintenanceVersion=0
|
maintenanceVersion=0
|
||||||
|
@ -192,6 +192,16 @@ native any:GetHookChainReturn(AType:type, any:...);
|
|||||||
*/
|
*/
|
||||||
native SetHookChainArg(number, 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.
|
* Compares the entity to a specified classname.
|
||||||
* @note This native also checks the validity of an entity.
|
* @note This native also checks the validity of an entity.
|
||||||
|
@ -144,12 +144,14 @@ struct hookctx_t
|
|||||||
extern hookctx_t* g_hookCtx;
|
extern hookctx_t* g_hookCtx;
|
||||||
|
|
||||||
template <typename original_t, typename ...f_args>
|
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;
|
auto hookCtx = g_hookCtx;
|
||||||
hookCtx->reset();
|
hookCtx->reset();
|
||||||
int hc_state = HC_CONTINUE;
|
int hc_state = HC_CONTINUE;
|
||||||
|
|
||||||
|
hook->wasCalled = false;
|
||||||
|
|
||||||
for (auto fwd : hook->pre)
|
for (auto fwd : hook->pre)
|
||||||
{
|
{
|
||||||
if (likely(fwd->GetState() == FSTATE_ENABLED))
|
if (likely(fwd->GetState() == FSTATE_ENABLED))
|
||||||
@ -169,16 +171,21 @@ NOINLINE void DLLEXPORT _callVoidForward(const hook_t* hook, original_t original
|
|||||||
g_hookCtx = nullptr;
|
g_hookCtx = nullptr;
|
||||||
original(std::forward<f_args &&>(args)...);
|
original(std::forward<f_args &&>(args)...);
|
||||||
g_hookCtx = hookCtx;
|
g_hookCtx = hookCtx;
|
||||||
|
hook->wasCalled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto fwd : hook->post) {
|
for (auto fwd : hook->post)
|
||||||
if (likely(fwd->GetState() == FSTATE_ENABLED)) {
|
{
|
||||||
|
if (likely(fwd->GetState() == FSTATE_ENABLED))
|
||||||
|
{
|
||||||
auto ret = g_amxxapi.ExecuteForward(fwd->GetIndex(), std::forward<f_args &&>(args)...);
|
auto ret = g_amxxapi.ExecuteForward(fwd->GetIndex(), std::forward<f_args &&>(args)...);
|
||||||
|
|
||||||
if (unlikely(ret == HC_BREAK))
|
if (unlikely(ret == HC_BREAK))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hook->wasCalled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename original_t, typename ...f_args>
|
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>
|
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;
|
auto hookCtx = g_hookCtx;
|
||||||
hookCtx->reset(getApiType(R()));
|
hookCtx->reset(getApiType(R()));
|
||||||
|
|
||||||
int hc_state = HC_CONTINUE;
|
int hc_state = HC_CONTINUE;
|
||||||
|
|
||||||
|
hook->wasCalled = false;
|
||||||
|
|
||||||
for (auto fwd : hook->pre)
|
for (auto fwd : hook->pre)
|
||||||
{
|
{
|
||||||
if (likely(fwd->GetState() == FSTATE_ENABLED))
|
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;
|
g_hookCtx = nullptr;
|
||||||
auto retVal = original(std::forward<f_args &&>(args)...);
|
auto retVal = original(std::forward<f_args &&>(args)...);
|
||||||
g_hookCtx = hookCtx;
|
g_hookCtx = hookCtx;
|
||||||
|
hook->wasCalled = true;
|
||||||
|
|
||||||
if (unlikely(!hookCtx->retVal.set)) {
|
if (unlikely(!hookCtx->retVal.set)) {
|
||||||
switch (sizeof retVal) {
|
switch (sizeof retVal) {
|
||||||
@ -250,8 +260,10 @@ NOINLINE R DLLEXPORT _callForward(const hook_t* hook, original_t original, f_arg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto fwd : hook->post) {
|
for (auto fwd : hook->post)
|
||||||
if (likely(fwd->GetState() == FSTATE_ENABLED)) {
|
{
|
||||||
|
if (likely(fwd->GetState() == FSTATE_ENABLED))
|
||||||
|
{
|
||||||
auto ret = g_amxxapi.ExecuteForward(fwd->GetIndex(), std::forward<f_args &&>(args)...);
|
auto ret = g_amxxapi.ExecuteForward(fwd->GetIndex(), std::forward<f_args &&>(args)...);
|
||||||
|
|
||||||
if (unlikely(ret == HC_BREAK))
|
if (unlikely(ret == HC_BREAK))
|
||||||
@ -259,6 +271,8 @@ NOINLINE R DLLEXPORT _callForward(const hook_t* hook, original_t original, f_arg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hook->wasCalled = false;
|
||||||
|
|
||||||
return *(R *)&hookCtx->retVal._integer;
|
return *(R *)&hookCtx->retVal._integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ struct regfunc
|
|||||||
|
|
||||||
int regfunc::current_cell = 1;
|
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[] = {
|
hook_t hooklist_engine[] = {
|
||||||
ENG(SV_StartSound),
|
ENG(SV_StartSound),
|
||||||
ENG(SV_DropClient),
|
ENG(SV_DropClient),
|
||||||
@ -80,7 +80,7 @@ hook_t hooklist_engine[] = {
|
|||||||
ENG(SV_WriteFullClientUpdate, _AMXX)
|
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[] = {
|
hook_t hooklist_gamedll[] = {
|
||||||
DLL(GetForceCamera),
|
DLL(GetForceCamera),
|
||||||
DLL(PlayerBlind),
|
DLL(PlayerBlind),
|
||||||
@ -213,7 +213,7 @@ hook_t hooklist_gib[] = {
|
|||||||
DLL(CGib_WaitTillLand),
|
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[] = {
|
hook_t hooklist_rechecker[] = {
|
||||||
RCHECK(FileConsistencyProcess, _AMXX),
|
RCHECK(FileConsistencyProcess, _AMXX),
|
||||||
RCHECK(FileConsistencyFinal),
|
RCHECK(FileConsistencyFinal),
|
||||||
|
@ -23,6 +23,8 @@ struct hook_t
|
|||||||
regchain_t unregisterHookchain; // unregister re* API hook
|
regchain_t unregisterHookchain; // unregister re* API hook
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
bool wasCalled;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern hook_t hooklist_engine[];
|
extern hook_t hooklist_engine[];
|
||||||
|
@ -314,6 +314,38 @@ cell AMX_NATIVE_CALL SetHookChainArg(AMX *amx, cell *params)
|
|||||||
return TRUE;
|
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[] =
|
AMX_NATIVE_INFO HookChain_Natives[] =
|
||||||
{
|
{
|
||||||
{ "RegisterHookChain", RegisterHookChain },
|
{ "RegisterHookChain", RegisterHookChain },
|
||||||
@ -326,6 +358,8 @@ AMX_NATIVE_INFO HookChain_Natives[] =
|
|||||||
|
|
||||||
{ "SetHookChainArg", SetHookChainArg },
|
{ "SetHookChainArg", SetHookChainArg },
|
||||||
|
|
||||||
|
{ "IsReapiHookOriginalWasCalled", IsReapiHookOriginalWasCalled },
|
||||||
|
|
||||||
{ nullptr, nullptr }
|
{ nullptr, nullptr }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user