194 lines
4.2 KiB
C++
194 lines
4.2 KiB
C++
#include "sdk/amxxmodule.h"
|
|
|
|
#include "hamsandwich.h"
|
|
|
|
#include "VTableManager.h"
|
|
#include "VTableEntries.h"
|
|
|
|
#include "NEW_Util.h"
|
|
|
|
VTableManager VTMan;
|
|
|
|
NATIVEFUNC VTableManager::RegisterNatives[HAM_END_DONT_USE_ME];
|
|
NATIVEFUNC VTableManager::RegisterIDNatives[HAM_END_DONT_USE_ME];
|
|
const char *VTableManager::RegisterNames[HAM_END_DONT_USE_ME];
|
|
|
|
void RegisterThisRegister(int index,NATIVEFUNC byname, NATIVEFUNC byid)
|
|
{
|
|
VTableManager::RegisterNatives[index]=byname;
|
|
VTableManager::RegisterIDNatives[index]=byid;
|
|
}
|
|
void RegisterThisRegisterName(int index, const char *name)
|
|
{
|
|
VTableManager::RegisterNames[index]=name;
|
|
}
|
|
|
|
static AMX_NATIVE_INFO registernatives[] = {
|
|
{ "ham_register", VTableManager::Register },
|
|
{ "ham_registerid", VTableManager::RegisterID },
|
|
|
|
{ NULL, NULL }
|
|
};
|
|
void RegisterRegisterNatives(void)
|
|
{
|
|
MF_AddNatives(registernatives);
|
|
}
|
|
cell VTableManager::Register(AMX *amx, cell *params)
|
|
{
|
|
int id=params[1];
|
|
|
|
if (id<0 || id>=HAM_END_DONT_USE_ME || RegisterIDNatives[id]==NULL)
|
|
{
|
|
// this register is not found, fail the plugin
|
|
int fwd=MF_RegisterSPForwardByName(amx,"__fatal_ham_error",FP_STRING,FP_DONE);
|
|
char error[256];
|
|
|
|
snprintf(&error[0],sizeof(error)-1,"Requested to ham_registerid a function ID that is not registered in configs/hamdata.ini, cannot continue. (Requested: %d)",id);
|
|
|
|
MF_ExecuteForward(fwd,&error[0]);
|
|
|
|
MF_UnregisterSPForward(fwd);
|
|
return 0;
|
|
|
|
}
|
|
|
|
cell tempparams[4];
|
|
|
|
// remove one parameter from this param count
|
|
tempparams[0]=(params[0]-(sizeof(cell)));
|
|
tempparams[1]=params[2];
|
|
tempparams[2]=params[3];
|
|
tempparams[3]=params[4];
|
|
|
|
return RegisterNatives[id](amx,&tempparams[0]);
|
|
}
|
|
cell VTableManager::RegisterID(AMX *amx, cell *params)
|
|
{
|
|
int id=params[1];
|
|
|
|
if (id<0 || id>=HAM_END_DONT_USE_ME || RegisterNatives[id]==NULL)
|
|
{
|
|
// this register is not found, fail the plugin
|
|
int fwd=MF_RegisterSPForwardByName(amx,"__fatal_ham_error",FP_STRING,FP_DONE);
|
|
|
|
char error[256];
|
|
|
|
snprintf(&error[0],sizeof(error)-1,"Requested to ham_register a function ID that is not registered in configs/hamdata.ini, cannot continue. (Requested: %d)",id);
|
|
|
|
MF_ExecuteForward(fwd,&error[0]);
|
|
|
|
MF_UnregisterSPForward(fwd);
|
|
return 0;
|
|
|
|
}
|
|
|
|
cell tempparams[4];
|
|
|
|
// remove one parameter from this param count
|
|
tempparams[0]=(params[0]-(sizeof(cell)));
|
|
tempparams[1]=params[2];
|
|
tempparams[2]=params[3];
|
|
tempparams[3]=params[4];
|
|
|
|
return RegisterIDNatives[id](amx,&tempparams[0]);
|
|
}
|
|
|
|
|
|
void *VTableManager::InsertIntoVTable(void **vtable, int index, void *trampoline)
|
|
{
|
|
void *func;
|
|
#if defined _WIN32
|
|
DWORD OldFlags;
|
|
VirtualProtect(&vtable[index],sizeof(int*),PAGE_READWRITE,&OldFlags);
|
|
#elif defined __linux__
|
|
mprotect(&vtable[index],sizeof(int*),PROT_READ|PROT_WRITE);
|
|
#endif
|
|
func=vtable[index];
|
|
vtable[index]=trampoline;
|
|
|
|
return func;
|
|
};
|
|
|
|
|
|
#define CLEAR_ENTRIES(Container) \
|
|
i=Container.size(); \
|
|
while (i--) \
|
|
{ \
|
|
Container[i]->Destroy(); \
|
|
delete Container[i]; \
|
|
} \
|
|
Container.clear()
|
|
|
|
|
|
void VTableManager::Cleanup(void)
|
|
{
|
|
int i;
|
|
|
|
CLEAR_ENTRIES(UseEntries);
|
|
CLEAR_ENTRIES(TakeDamageEntries);
|
|
};
|
|
|
|
|
|
|
|
void VTableEntryBase::CreateGenericTrampoline(VTableManager *manager, void **vtable, int vtid, int id, void **outtrampoline, void **origfunc, void *callee, int paramcount, int voidcall, int thiscall)
|
|
{
|
|
Trampolines::TrampolineMaker tramp;
|
|
|
|
if (voidcall)
|
|
{
|
|
if (thiscall)
|
|
{
|
|
tramp.ThisVoidPrologue();
|
|
}
|
|
else
|
|
{
|
|
tramp.VoidPrologue();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (thiscall)
|
|
{
|
|
tramp.ThisReturnPrologue();
|
|
}
|
|
else
|
|
{
|
|
tramp.ReturnPrologue();
|
|
}
|
|
}
|
|
|
|
while (paramcount)
|
|
{
|
|
tramp.PushParam(paramcount--);
|
|
}
|
|
if (thiscall)
|
|
{
|
|
tramp.PushThis();
|
|
}
|
|
tramp.PushNum(id);
|
|
tramp.Call(callee);
|
|
tramp.FreeTargetStack();
|
|
if (voidcall)
|
|
{
|
|
#if defined _WIN32
|
|
tramp.VoidEpilogueAndFree();
|
|
#elif defined __linux__
|
|
tramp.VoidEpilogue();
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#if defined _WIN32
|
|
tramp.ReturnEpilogueAndFree();
|
|
#elif defined __linux__
|
|
tramp.ReturnEpilogue();
|
|
#endif
|
|
}
|
|
|
|
void *trampoline=tramp.Finish(NULL);
|
|
|
|
*outtrampoline=trampoline;
|
|
|
|
*origfunc=manager->InsertIntoVTable(vtable,vtid,trampoline);
|
|
};
|