faluco@739: /**
faluco@739: * vim: set ts=4 :
ds@1330: * =============================================================================
dvander@1226: * SourceMod BinTools Extension
ds@1947: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
ds@1330: * =============================================================================
faluco@739: *
ds@1330: * This program is free software; you can redistribute it and/or modify it under
ds@1330: * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330: * Free Software Foundation.
faluco@739: *
ds@1330: * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
ds@1330: * details.
dvander@1226: *
ds@1330: * You should have received a copy of the GNU General Public License along with
ds@1330: * this program. If not, see .
dvander@1226: *
ds@1330: * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330: * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330: * by the Valve Corporation. You must obey the GNU General Public License in
ds@1330: * all respects for all other code used. Additionally, AlliedModders LLC grants
ds@1330: * this exception to all derivative works. AlliedModders LLC defines further
ds@1330: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330: * or .
faluco@739: *
faluco@739: * Version: $Id$
faluco@739: */
faluco@739:
faluco@739: #ifndef _INCLUDE_SMEXT_BINTOOLS_H_
faluco@739: #define _INCLUDE_SMEXT_BINTOOLS_H_
faluco@739:
faluco@739: #include
faluco@739:
pred@2504:
faluco@739: #define SMINTERFACE_BINTOOLS_NAME "IBinTools"
pred@2504: #define SMINTERFACE_BINTOOLS_VERSION 3
pred@2504:
pred@2504: #if defined HOOKING_ENABLED
pred@2504: #include
pred@2504:
pred@2504: #define SMINTERFACE_BINTOOLS2_NAME "IBinTools2"
pred@2504: #define SMINTERFACE_BINTOOLS2_VERSION 1
pred@2504: #endif
faluco@739:
faluco@739: /**
faluco@739: * @brief Function calling encoding utilities
faluco@739: * @file IBinTools.h
faluco@739: */
faluco@739:
faluco@739: namespace SourceMod
faluco@739: {
faluco@739: /**
faluco@739: * @brief Supported calling conventions
faluco@739: */
faluco@739: enum CallConvention
faluco@739: {
faluco@739: CallConv_ThisCall, /**< This call (object pointer required) */
faluco@739: CallConv_Cdecl, /**< Standard C call */
faluco@739: };
faluco@739:
faluco@739: /**
faluco@739: * @brief Describes how a parameter should be passed
faluco@739: */
faluco@739: enum PassType
faluco@739: {
faluco@739: PassType_Basic, /**< Plain old register data (pointers, integers) */
faluco@739: PassType_Float, /**< Floating point data */
faluco@739: PassType_Object, /**< Object or structure */
faluco@739: };
faluco@739:
faluco@739: #define PASSFLAG_BYVAL (1<<0) /**< Passing by value */
faluco@739: #define PASSFLAG_BYREF (1<<1) /**< Passing by reference */
faluco@739: #define PASSFLAG_ODTOR (1<<2) /**< Object has a destructor */
faluco@739: #define PASSFLAG_OCTOR (1<<3) /**< Object has a constructor */
faluco@739: #define PASSFLAG_OASSIGNOP (1<<4) /**< Object has an assignment operator */
faluco@739:
faluco@739: /**
faluco@739: * @brief Parameter passing information
faluco@739: */
faluco@739: struct PassInfo
faluco@739: {
faluco@739: PassType type; /**< PassType value */
faluco@739: unsigned int flags; /**< Pass/return flags */
faluco@739: size_t size; /**< Size of the data being passed */
faluco@739: };
faluco@739:
faluco@739: /**
faluco@739: * @brief Parameter encoding information
faluco@739: */
faluco@739: struct PassEncode
faluco@739: {
faluco@739: PassInfo info; /**< Parameter information */
faluco@739: size_t offset; /**< Offset into the virtual stack */
faluco@739: };
faluco@739:
faluco@739: /**
faluco@739: * @brief Wraps a C/C++ call.
faluco@739: */
faluco@739: class ICallWrapper
faluco@739: {
faluco@739: public:
faluco@739: /**
faluco@739: * @brief Returns the calling convention.
faluco@739: *
faluco@739: * @return CallConvention value.
faluco@739: */
faluco@739: virtual CallConvention GetCallConvention() =0;
faluco@739:
faluco@739: /**
faluco@739: * @brief Returns parameter info.
faluco@739: *
faluco@739: * @param num Parameter number to get (starting from 0).
faluco@739: * @return A PassInfo pointer.
faluco@739: */
faluco@739: virtual const PassEncode *GetParamInfo(unsigned int num) =0;
faluco@739:
faluco@739: /**
faluco@739: * @brief Returns return type info.
faluco@739: *
faluco@739: * @return A PassInfo pointer.
faluco@739: */
faluco@739: virtual const PassInfo *GetReturnInfo() =0;
faluco@739:
faluco@739: /**
faluco@739: * @brief Returns the number of parameters.
dvander@942: *
dvander@942: * @return Number of parameters.
faluco@739: */
faluco@739: virtual unsigned int GetParamCount() =0;
faluco@739:
faluco@739: /**
faluco@739: * @brief Execute the contained function.
dvander@942: *
dvander@942: * @param vParamStack A blob of memory containing stack data.
dvander@942: * @param retBuffer Buffer to store return value.
faluco@739: */
faluco@739: virtual void Execute(void *vParamStack, void *retBuffer) =0;
dvander@942:
dvander@942: /**
dvander@942: * @brief Destroys all resources used by this object.
dvander@942: */
dvander@942: virtual void Destroy() =0;
pred@2504:
pred@2504: #if defined HOOKING_ENABLED
pred@2504:
pred@2504: /**
pred@2504: * @brief Gets the Return type info.
pred@2504: *
pred@2504: * @return A PassInfo pointer.
pred@2504: */
pred@2504: virtual const SourceHook::PassInfo *GetSHReturnInfo() =0;
pred@2504:
pred@2504: /**
pred@2504: * @brief Returns the calling convention.
pred@2504: *
pred@2504: * @return CallConvention value.
pred@2504: */
pred@2504: virtual SourceHook::ProtoInfo::CallConvention GetSHCallConvention() =0;
pred@2504:
pred@2504: /**
pred@2504: * @brief Returns parameter info.
pred@2504: *
pred@2504: * @param num Parameter number to get (starting from 0).
pred@2504: * @return A PassInfo pointer.
pred@2504: */
pred@2504: virtual const SourceHook::PassInfo *GetSHParamInfo(unsigned int num) =0;
pred@2504:
pred@2504: /**
pred@2504: * @brief Returns the offset of a given param.
pred@2504: *
pred@2504: * @param num Parameter number to get (starting from 0).
pred@2504: * @return Parameter offset.
pred@2504: */
pred@2504: virtual unsigned int GetParamOffset(unsigned int num) =0;
pred@2504:
pred@2504: #endif
faluco@739: };
faluco@739:
pred@2504: #if defined HOOKING_ENABLED
pred@2504:
pred@2504: /**
pred@2504: * @brief Delegate object that intermediates between SourceHook and the callback function.
pred@2504: */
pred@2504: class ISMDelegate : public SourceHook::ISHDelegate
pred@2504: {
pred@2504: private:
pred@2504: /**
pred@2504: * @brief Internally used callback function - Do not call!
pred@2504: */
pred@2504: virtual void Call() =0; /**< Do not call */
pred@2504: public:
pred@2504: /**
pred@2504: * @brief Retrieves the User data buffer.
pred@2504: *
pred@2504: * @return User data pointer.
pred@2504: */
pred@2504: virtual void *GetUserData() =0;
pred@2504: };
pred@2504:
pred@2504: /**
pred@2504: * @brief Wrapper around a virtual hook.
pred@2504: */
pred@2504: class IHookWrapper
pred@2504: {
pred@2504: public:
pred@2504: /**
pred@2504: * @brief Creates a hook delegate to pass to SourceHook.
pred@2504: *
pred@2504: * @param data User data pointer.
pred@2504: * @return A new ISMDelegate for the hook.
pred@2504: */
pred@2504: virtual ISMDelegate *CreateDelegate(void *data) =0;
pred@2504:
pred@2504: /**
pred@2504: * @brief Gets the number of params in the hooked function.
pred@2504: *
pred@2504: * @return Number of params.
pred@2504: */
pred@2504: virtual unsigned int GetParamCount() =0;
pred@2504:
pred@2504: /**
pred@2504: * @brief Returns the offset of a given param.
pred@2504: *
pred@2504: * @param argnum Parameter number from 0 to GetParamCount-1.
pred@2504: * @param size Optional buffer to store the size of the param.
pred@2504: * @return Parameter offset or -1 on error.
pred@2504: */
pred@2504: virtual unsigned int GetParamOffset(unsigned int argnum, unsigned int *size) =0;
pred@2504:
pred@2504: /**
pred@2504: * @brief Initiates a recall on the function.
pred@2504: *
pred@2504: * @param params Parameter buffer.
pred@2504: * @param retval Buffer to store the return value in.
pred@2504: */
pred@2504: virtual void PerformRecall(void *params, void *retval) =0;
pred@2504:
pred@2504: /**
pred@2504: * @brief Destroys this HookWrapper.
pred@2504: */
pred@2504: virtual void Destroy() =0;
pred@2504: };
pred@2504:
pred@2504: #endif
pred@2504:
faluco@739: /**
faluco@739: * @brief Binary tools interface.
faluco@739: */
faluco@739: class IBinTools : public SMInterface
faluco@739: {
faluco@739: public:
faluco@739: virtual const char *GetInterfaceName()
faluco@739: {
faluco@739: return SMINTERFACE_BINTOOLS_NAME;
faluco@739: }
faluco@739: virtual unsigned int GetInterfaceVersion()
faluco@739: {
faluco@739: return SMINTERFACE_BINTOOLS_VERSION;
faluco@739: }
faluco@739: public:
faluco@739: /**
faluco@739: * @brief Creates a call decoder.
faluco@739: *
faluco@739: * Note: CallConv_ThisCall requires an implicit first parameter
faluco@739: * of PassType_Basic / PASSFLAG_BYVAL / sizeof(void *). However,
faluco@739: * this should only be given to the Execute() function, and never
faluco@739: * listed in the paramInfo array.
faluco@739: *
faluco@739: * @param address Address to use as a call.
faluco@739: * @param cv Calling convention.
faluco@739: * @param retInfo Return type information, or NULL for void.
faluco@739: * @param paramInfo Array of parameters.
faluco@739: * @param numParams Number of parameters in the array.
faluco@739: * @return A new ICallWrapper function.
faluco@739: */
faluco@739: virtual ICallWrapper *CreateCall(void *address,
faluco@739: CallConvention cv,
faluco@739: const PassInfo *retInfo,
faluco@739: const PassInfo paramInfo[],
faluco@739: unsigned int numParams) =0;
faluco@739:
faluco@739: /**
faluco@739: * @brief Creates a vtable call decoder.
faluco@739: *
faluco@739: * Note: CallConv_ThisCall requires an implicit first parameter
faluco@739: * of PassType_Basic / PASSFLAG_BYVAL / sizeof(void *). However,
faluco@739: * this should only be given to the Execute() function, and never
faluco@739: * listed in the paramInfo array.
faluco@739: *
faluco@739: * @param vtblIdx Index into the virtual table.
faluco@739: * @param vtblOffs Offset of the virtual table.
faluco@739: * @param thisOffs Offset of the this pointer of the virtual table.
faluco@739: * @param retInfo Return type information, or NULL for void.
faluco@739: * @param paramInfo Array of parameters.
faluco@739: * @param numParams Number of parameters in the array.
faluco@739: * @return A new ICallWrapper function.
faluco@739: */
faluco@739: virtual ICallWrapper *CreateVCall(unsigned int vtblIdx,
faluco@739: unsigned int vtblOffs,
faluco@739: unsigned int thisOffs,
faluco@739: const PassInfo *retInfo,
faluco@739: const PassInfo paramInfo[],
faluco@739: unsigned int numParams) =0;
faluco@739: };
pred@2504:
pred@2504: #if defined HOOKING_ENABLED
pred@2504:
pred@2504: /**
pred@2504: * @brief Binary tools interface.
pred@2504: */
pred@2504: class IBinTools2 : public SMInterface
pred@2504: {
pred@2504: public:
pred@2504: virtual const char *GetInterfaceName()
pred@2504: {
pred@2504: return SMINTERFACE_BINTOOLS2_NAME;
pred@2504: }
pred@2504: virtual unsigned int GetInterfaceVersion()
pred@2504: {
pred@2504: return SMINTERFACE_BINTOOLS2_VERSION;
pred@2504: }
pred@2504: public:
pred@2504:
pred@2504: /**
pred@2504: * @brief Creates a call decoder.
pred@2504: *
pred@2504: * Note: CallConv_ThisCall requires an implicit first parameter
pred@2504: * of PassType_Basic / PASSFLAG_BYVAL / sizeof(void *). However,
pred@2504: * this should only be given to the Execute() function, and never
pred@2504: * listed in the paramInfo array.
pred@2504: *
pred@2504: * @param address Address to use as a call.
pred@2504: * @param protoInfo Parameter type information.
pred@2504: * @return A new ICallWrapper function.
pred@2504: */
pred@2504: virtual ICallWrapper *CreateCall(void *address,
pred@2504: const SourceHook::ProtoInfo *protoInfo) =0;
pred@2504:
pred@2504: /**
pred@2504: * @brief Creates a vtable call decoder.
pred@2504: *
pred@2504: * Note: CallConv_ThisCall requires an implicit first parameter
pred@2504: * of PassType_Basic / PASSFLAG_BYVAL / sizeof(void *). However,
pred@2504: * this should only be given to the Execute() function, and never
pred@2504: * listed in the paramInfo array.
pred@2504: *
pred@2504: * @param protoInfo Parameter type information.
pred@2504: * @param info Function offset information.
pred@2504: * @return A new ICallWrapper function.
pred@2504: */
pred@2504: virtual ICallWrapper *CreateVirtualCall(const SourceHook::ProtoInfo *protoInfo,
pred@2504: const SourceHook::MemFuncInfo *info) =0;
pred@2504:
pred@2504:
pred@2504: /**
pred@2504: * @brief Callback function pointer for Virtual Hooks.
pred@2504: *
pred@2504: * @param wrapper Call wrapper for this hook.
pred@2504: * @param deleg Delegate for this call.
pred@2504: * @param params Array of parameters.
pred@2504: * @param ret Storage buffer for the return value.
pred@2504: */
pred@2504: typedef void (*VIRTUAL_HOOK_PROTO)(IHookWrapper *wrapper, ISMDelegate *deleg, void *params, void *ret);
pred@2504:
pred@2504: /**
pred@2504: * @brief Creates a hook on a virtual function.
pred@2504: *
pred@2504: * @param pSH Global SourceHook pointer.
pred@2504: * @param protoInfo Parameter type information.
pred@2504: * @param info Function offset information.
pred@2504: * @param f Callback function pointer.
pred@2504: */
pred@2504: virtual IHookWrapper *CreateVirtualHook(SourceHook::ISourceHook *pSH,
pred@2504: const SourceHook::ProtoInfo *protoInfo,
pred@2504: const SourceHook::MemFuncInfo *info,
pred@2504: VIRTUAL_HOOK_PROTO f) =0;
pred@2504: };
pred@2504:
pred@2504: #endif
pred@2504:
faluco@739: }
faluco@739:
faluco@739: #endif //_INCLUDE_SMEXT_BINTOOLS_H_