More linux fixes.

This commit is contained in:
Dr!fter 2013-08-29 15:18:43 -04:00
parent b2288d7333
commit c3fcdbb7db
4 changed files with 280 additions and 9 deletions

View File

@ -42,6 +42,7 @@ bool GetHandleIfValidOrError(HandleType_t type, void **object, IPluginContext *p
return true;
}
#ifndef __linux__
intptr_t GetObjectAddr(HookParamType type, void **params, int index)
{
if(type == HookParamType_Object)
@ -51,6 +52,12 @@ intptr_t GetObjectAddr(HookParamType type, void **params, int index)
return 0;
}
#else
intptr_t GetObjectAddr(HookParamType type, void **params, int index)
{
return (intptr_t)params[index];
}
#endif
//native Handle:DHookCreate(offset, HookType:hooktype, ReturnType:returntype, ThisPointerType:thistype, DHookCallback:callback);
cell_t Native_CreateHook(IPluginContext *pContext, const cell_t *params)
@ -495,8 +502,6 @@ cell_t Native_SetParamVector(IPluginContext *pContext, const cell_t *params)
}
return pContext->ThrowNativeError("Invalid param type to set. Param is not a vector.");
}
/*cell_t Native_GetReturnVector(IPluginContext *pContext, const cell_t *params);
cell_t Native_SetReturnVector(IPluginContext *pContext, const cell_t *params);*/
// native DHookGetParamString(Handle:hParams, num, String:buffer[], size)
cell_t Native_GetParamString(IPluginContext *pContext, const cell_t *params)
@ -526,6 +531,7 @@ cell_t Native_GetParamString(IPluginContext *pContext, const cell_t *params)
return 1;
}
// native DHookGetReturnString(Handle:hReturn, String:buffer[], size)
cell_t Native_GetReturnString(IPluginContext *pContext, const cell_t *params)
{

View File

@ -110,6 +110,7 @@ T CallVFunction(DHooksCallback *dg, HookParamsStruct *paramStruct, void *iface)
}
T ret = 0;
if(dg->returnType == ReturnType_Void)
{
pCall = g_pBinTools->CreateVCall(dg->offset, 0, 0, NULL, paramInfo, dg->params.Count());
@ -132,4 +133,93 @@ T CallVFunction(DHooksCallback *dg, HookParamsStruct *paramStruct, void *iface)
return ret;
}
#ifdef __linux__
template <>
string_t CallVFunction<string_t>(DHooksCallback *dg, HookParamsStruct *paramStruct, void *iface)
{
SourceMod::PassInfo *paramInfo = NULL;
SourceMod::PassInfo returnInfo;
if(dg->returnType != ReturnType_Void)
{
returnInfo.flags = dg->returnFlag;
returnInfo.size = sizeof(string_t);
returnInfo.type = PassType_Object;
}
ICallWrapper *pCall;
size_t size = GetStackArgsSize(dg);
unsigned char *vstk = (unsigned char *)malloc(sizeof(void *) + size);
unsigned char *vptr = vstk;
*(void **)vptr = iface;
if(paramStruct)
{
vptr += sizeof(void *);
paramInfo = (SourceMod::PassInfo *)malloc(sizeof(SourceMod::PassInfo) * dg->params.Count());
for(int i = 0; i < dg->params.Count(); i++)
{
switch(dg->params.Element(i).type)
{
case HookParamType_Int:
PARAMINFO_SWITCH(PassType_Basic);
VSTK_PARAM_SWITCH(int);
case HookParamType_Bool:
PARAMINFO_SWITCH(PassType_Basic);
VSTK_PARAM_SWITCH(cell_t);
case HookParamType_Float:
PARAMINFO_SWITCH(PassType_Float);
VSTK_PARAM_SWITCH_FLOAT();
case HookParamType_String:
PARAMINFO_SWITCH(PassType_Object);
VSTK_PARAM_SWITCH(int);
case HookParamType_StringPtr:
PARAMINFO_SWITCH(PassType_Basic);
VSTK_PARAM_SWITCH(string_t *);
case HookParamType_CharPtr:
PARAMINFO_SWITCH(PassType_Basic);
VSTK_PARAM_SWITCH(char *);
case HookParamType_VectorPtr:
PARAMINFO_SWITCH(PassType_Basic);
VSTK_PARAM_SWITCH(Vector *);
case HookParamType_CBaseEntity:
PARAMINFO_SWITCH(PassType_Basic);
VSTK_PARAM_SWITCH(CBaseEntity *);
case HookParamType_Edict:
PARAMINFO_SWITCH(PassType_Basic);
VSTK_PARAM_SWITCH(edict_t *);
default:
PARAMINFO_SWITCH(PassType_Basic);
VSTK_PARAM_SWITCH(void *);
}
}
}
string_t ret = NULL_STRING;
if(dg->returnType == ReturnType_Void)
{
pCall = g_pBinTools->CreateVCall(dg->offset, 0, 0, NULL, paramInfo, dg->params.Count());
pCall->Execute(vstk, NULL);
}
else
{
pCall = g_pBinTools->CreateVCall(dg->offset, 0, 0, &returnInfo, paramInfo, dg->params.Count());
pCall->Execute(vstk, &ret);
}
pCall->Destroy();
free(vstk);
if(paramInfo != NULL)
{
free(paramInfo);
}
return ret;
}
#endif
#endif

166
vhook.cpp
View File

@ -7,6 +7,11 @@ CUtlVector<DHooksManager *> g_pHooks;
using namespace SourceHook;
#ifndef __linux__
#define OBJECT_OFFSET sizeof(void *)
#else
#define OBJECT_OFFSET (sizeof(void *)*2)
#endif
DHooksManager::DHooksManager(HookSetup *setup, void *iface, IPluginFunction *remove_callback, bool post)
{
this->callback = MakeHandler(setup->returnType);
@ -110,9 +115,13 @@ size_t GetStackArgsSize(DHooksCallback *dg)
res += dg->params.Element(i).size;
}
#ifndef __linux__
if(dg->returnType == ReturnType_Vector)//Account for result vector ptr.
#else
if(dg->returnType == ReturnType_Vector || dg->returnType == ReturnType_String)
#endif
{
res += sizeof(void *);
res += OBJECT_OFFSET;
}
return res;
}
@ -120,15 +129,19 @@ HookParamsStruct *GetParamStruct(DHooksCallback *dg, void **argStack, size_t arg
{
HookParamsStruct *params = new HookParamsStruct();
params->dg = dg;
#ifndef __linux__
if(dg->returnType != ReturnType_Vector)
#else
if(dg->returnType != ReturnType_Vector && dg->returnType != ReturnType_String)
#endif
{
params->orgParams = (void **)malloc(argStackSize);
memcpy(params->orgParams, argStack, argStackSize);
}
else //Offset result ptr
{
params->orgParams = (void **)malloc(argStackSize-sizeof(void *));
memcpy(params->orgParams, argStack+sizeof(void *), argStackSize);
params->orgParams = (void **)malloc(argStackSize-OBJECT_OFFSET);
memcpy(params->orgParams, argStack+OBJECT_OFFSET, argStackSize-OBJECT_OFFSET);
}
params->newParams = (void **)malloc(dg->params.Count() * sizeof(void *));
params->isChanged = (bool *)malloc(dg->params.Count() * sizeof(bool));
@ -681,3 +694,150 @@ Vector *Callback_vector(DHooksCallback *dg, void **argStack)
}
return vec_result;
}
#ifdef __linux__
string_t *Callback_stringt(DHooksCallback *dg, void **argStack)
{
string_t *string_result = (string_t *)argStack[0]; // Save the result
HookReturnStruct *returnStruct = NULL;
HookParamsStruct *paramStruct = NULL;
Handle_t rHndl;
Handle_t pHndl;
size_t argsize = GetStackArgsSize(dg);
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
{
dg->plugin_callback->PushCell(GetThisPtr(g_SHPtr->GetIfacePtr(), dg->thisType));
}
returnStruct = GetReturnStruct(dg);
rHndl = handlesys->CreateHandle(g_HookReturnHandle, returnStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL);
if(!rHndl)
{
dg->plugin_callback->Cancel();
if(returnStruct)
{
delete returnStruct;
}
g_SHPtr->SetRes(MRES_IGNORED);
return NULL;
}
dg->plugin_callback->PushCell(rHndl);
if(argsize > 0)
{
paramStruct = GetParamStruct(dg, argStack, argsize);
pHndl = handlesys->CreateHandle(g_HookParamsHandle, paramStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL);
if(!pHndl)
{
dg->plugin_callback->Cancel();
if(returnStruct)
{
delete returnStruct;
}
if(paramStruct)
{
delete paramStruct;
}
g_SHPtr->SetRes(MRES_IGNORED);
return NULL;
}
dg->plugin_callback->PushCell(pHndl);
}
cell_t result = (cell_t)MRES_Ignored;
META_RES mres = MRES_IGNORED;
dg->plugin_callback->Execute(&result);
void *ret = g_SHPtr->GetOverrideRetPtr();
ret = string_result;
switch((MRESReturn)result)
{
case MRES_Handled:
case MRES_ChangedHandled:
g_SHPtr->DoRecall();
g_SHPtr->SetRes(MRES_SUPERCEDE);
mres = MRES_SUPERCEDE;
*string_result = CallVFunction<string_t>(dg, paramStruct, g_SHPtr->GetIfacePtr());
break;
case MRES_ChangedOverride:
if(dg->returnType != ReturnType_Void)
{
if(returnStruct->isChanged)
{
*string_result = *(string_t *)returnStruct->newResult;
}
else //Throw an error if no override was set
{
g_SHPtr->SetRes(MRES_IGNORED);
mres = MRES_IGNORED;
dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->ThrowNativeError("Tried to override return value without return value being set");
break;
}
}
g_SHPtr->DoRecall();
g_SHPtr->SetRes(MRES_SUPERCEDE);
mres = MRES_SUPERCEDE;
CallVFunction<Vector>(dg, paramStruct, g_SHPtr->GetIfacePtr());
break;
case MRES_Override:
if(dg->returnType != ReturnType_Void)
{
if(returnStruct->isChanged)
{
g_SHPtr->SetRes(MRES_OVERRIDE);
mres = MRES_OVERRIDE;
*string_result = *(string_t *)returnStruct->newResult;
}
else //Throw an error if no override was set
{
g_SHPtr->SetRes(MRES_IGNORED);
mres = MRES_IGNORED;
dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->ThrowNativeError("Tried to override return value without return value being set");
}
}
break;
case MRES_Supercede:
if(dg->returnType != ReturnType_Void)
{
if(returnStruct->isChanged)
{
g_SHPtr->SetRes(MRES_SUPERCEDE);
mres = MRES_SUPERCEDE;
*string_result = *(string_t *)returnStruct->newResult;
}
else //Throw an error if no override was set
{
g_SHPtr->SetRes(MRES_IGNORED);
mres = MRES_IGNORED;
dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->ThrowNativeError("Tried to override return value without return value being set");
}
}
break;
default:
g_SHPtr->SetRes(MRES_IGNORED);
mres = MRES_IGNORED;
break;
}
HandleSecurity sec(dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity());
if(returnStruct)
{
handlesys->FreeHandle(rHndl, &sec);
}
if(paramStruct)
{
handlesys->FreeHandle(pHndl, &sec);
}
if(dg->returnType == ReturnType_Void || mres <= MRES_HANDLED)
{
*string_result = NULL_STRING;
return string_result;
}
return string_result;
}
#endif

19
vhook.h
View File

@ -166,6 +166,7 @@ Vector *Callback_vector(DHooksCallback *dg, void **stack, size_t *argsizep);
void *Callback(DHooksCallback *dg, void **stack);
float Callback_float(DHooksCallback *dg, void **stack);
Vector *Callback_vector(DHooksCallback *dg, void **stack);
string_t *Callback_stringt(DHooksCallback *dg, void **stack);
#endif
bool SetupHookManager(ISmmAPI *ismm);
void CleanupHooks(IPluginContext *pContext);
@ -182,10 +183,20 @@ static void *GenerateThunk(ReturnType type)
masm.push(ebp);
masm.movl(ebp, esp);
masm.subl(esp, kReserve);
if(type != ReturnType_String && type != ReturnType_Vector)
{
masm.lea(eax, Operand(ebp, 12)); // grab the incoming caller argument vector
masm.movl(Operand(esp, 1 * 4), eax); // set that as the 2nd argument
masm.lea(eax, Operand(ebp, 8)); // grab the |this|
masm.movl(Operand(esp, 0 * 4), eax); // set |this| as the 1st argument
masm.movl(eax, Operand(ebp, 8)); // grab the |this|
masm.movl(Operand(esp, 0 * 4), eax); // set |this| as the 1st argument*/
}
else
{
masm.lea(eax, Operand(ebp, 8)); // grab the incoming caller argument vector
masm.movl(Operand(esp, 1 * 4), eax); // set that as the 2nd argument
masm.movl(eax, Operand(ebp, 12)); // grab the |this|
masm.movl(Operand(esp, 0 * 4), eax); // set |this| as the 1st argument*/
}
if(type == ReturnType_Float)
{
masm.call(ExternalAddress((void *)Callback_float));
@ -194,6 +205,10 @@ static void *GenerateThunk(ReturnType type)
{
masm.call(ExternalAddress((void *)Callback_vector));
}
else if(type == ReturnType_String)
{
masm.call(ExternalAddress((void *)Callback_stringt));
}
else
{
masm.call(ExternalAddress((void *)Callback));