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_