mirror of
https://github.com/dhewm/dhewm3-sdk.git
synced 2024-11-29 07:42:01 +00:00
Remove SourceHook, use new common->SetCallback() instead
This commit is contained in:
parent
1bd4b7a590
commit
ef3b057ebd
15 changed files with 27 additions and 10597 deletions
|
@ -22,7 +22,6 @@ set(src_game_mod
|
|||
game/PlayerCursor.cpp
|
||||
game/tracer.cpp
|
||||
game/TrailGenerator.cpp
|
||||
sourcehook/sourcehook.cpp
|
||||
)
|
||||
|
||||
set(src_d3xp_mod
|
||||
|
|
|
@ -57,19 +57,6 @@ const int CINEMATIC_SKIP_DELAY = SEC2MS( 2.0f );
|
|||
|
||||
#ifdef GAME_DLL
|
||||
|
||||
#ifdef _DENTONMOD
|
||||
#include "../sourcehook/sourcehook_impl.h"
|
||||
//============================================================================
|
||||
// Source hook related: Defining these vars here so that can be used globally
|
||||
// anywhere by just declaring following vars as "extern"
|
||||
//============================================================================
|
||||
SourceHook::CSourceHookImpl g_SourceHook;
|
||||
SourceHook::ISourceHook *g_SHPtr = static_cast<SourceHook::ISourceHook*>(&g_SourceHook);
|
||||
int g_PLID = 0;
|
||||
|
||||
//============================================================================
|
||||
#endif // _DENTONMOD
|
||||
|
||||
idSys * sys = NULL;
|
||||
idCommon * common = NULL;
|
||||
idCmdSystem * cmdSystem = NULL;
|
||||
|
|
|
@ -36,16 +36,6 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "PlayerView.h"
|
||||
|
||||
#ifdef _DENTONMOD
|
||||
#include "../sourcehook/sourcehook.h"
|
||||
|
||||
extern SourceHook::ISourceHook *g_SHPtr;
|
||||
extern int g_PLID;
|
||||
|
||||
SH_DECL_HOOK2_void( idCmdSystem, BufferCommandText, SH_NOATTRIB, 0, cmdExecution_t, const char * );
|
||||
|
||||
#endif
|
||||
|
||||
static int MakePowerOfTwo( int num ) {
|
||||
int pot;
|
||||
for (pot = 1 ; pot < num ; pot<<=1) {
|
||||
|
@ -848,38 +838,37 @@ idPlayerView::dnPostProcessManager::dnPostProcessManager():
|
|||
|
||||
m_iScreenHeight = m_iScreenWidth = 0;
|
||||
m_iScreenHeightPow2 = m_iScreenWidthPow2 = 0;
|
||||
m_fShiftScale_x = m_fShiftScale_y = 0;
|
||||
m_bForceUpdateOnCookedData = false;
|
||||
m_nFramesSinceLumUpdate = 0;
|
||||
m_nFramesToUpdateCookedData = 0;
|
||||
|
||||
// Initialize once this object is created.
|
||||
this->Initialize();
|
||||
|
||||
SH_ADD_HOOK_MEMFUNC(idCmdSystem, BufferCommandText, cmdSystem, this, &idPlayerView::dnPostProcessManager::Hook_BufferCommandText, false );
|
||||
|
||||
if(!common->SetCallback(idCommon::CB_ReloadImages, (idCommon::FunctionPointer)ReloadImagesCallback, this))
|
||||
{
|
||||
gameLocal.Warning("Couldn't set ReloadImages Callback from Ruiner game DLL! This could lead to errors on vid_restart and similar!\n");
|
||||
}
|
||||
}
|
||||
|
||||
idPlayerView::dnPostProcessManager::~dnPostProcessManager()
|
||||
{
|
||||
// Remove Source Hook before closing.
|
||||
SH_REMOVE_HOOK_MEMFUNC(idCmdSystem, BufferCommandText, cmdSystem, this, &idPlayerView::dnPostProcessManager::Hook_BufferCommandText, false );
|
||||
}
|
||||
idPlayerView::dnPostProcessManager::~dnPostProcessManager()
|
||||
{
|
||||
// remove callback because this object is destroyed (and this was passed as userArg)
|
||||
common->SetCallback(idCommon::CB_ReloadImages, NULL, NULL);
|
||||
}
|
||||
|
||||
void idPlayerView::dnPostProcessManager::Hook_BufferCommandText( cmdExecution_t a_eType, const char *a_pcText )
|
||||
{
|
||||
// Using idStr::FindText to make sure that we account for trailing white spaces. However, even an invalid command
|
||||
// e.g. like "reloadImagesADEAW" would update the cooked data, but that should not be a problem.
|
||||
if( NULL != a_pcText &&
|
||||
( 0 == idStr::FindText( a_pcText, "reloadimages", false ) || 0 == idStr::FindText(a_pcText, "vid_restart", false ) )
|
||||
)
|
||||
{
|
||||
m_nFramesToUpdateCookedData = 1;
|
||||
// this is called by the engine whenever vid_restart or reloadImages is executed
|
||||
// (replaces old SourceHook hack)
|
||||
/* static */ void idPlayerView::dnPostProcessManager::ReloadImagesCallback(void* arg, const idCmdArgs& cmdArgs)
|
||||
{
|
||||
idPlayerView::dnPostProcessManager* self = (idPlayerView::dnPostProcessManager*)arg;
|
||||
self->m_nFramesToUpdateCookedData = 1;
|
||||
if( r_HDR_postProcess.GetBool() )
|
||||
gameLocal.Printf("Cooked Data will be updated after %d frames...\n", m_nFramesToUpdateCookedData );
|
||||
gameLocal.Printf("Cooked Data will be updated after %d frames...\n", self->m_nFramesToUpdateCookedData );
|
||||
else
|
||||
gameLocal.Printf("Cooked Data will be updated after %d frames immediately after r_HDR_postProcess is enabled.\n", m_nFramesToUpdateCookedData );
|
||||
}
|
||||
|
||||
RETURN_META(MRES_IGNORED );
|
||||
}
|
||||
gameLocal.Printf("Cooked Data will be updated after %d frames immediately after r_HDR_postProcess is enabled.\n", self->m_nFramesToUpdateCookedData );
|
||||
}
|
||||
|
||||
void idPlayerView::dnPostProcessManager::Initialize()
|
||||
{
|
||||
|
|
|
@ -198,7 +198,10 @@ private:
|
|||
void RenderDebugTextures ();
|
||||
void UpdateCookedData ();
|
||||
void UpdateInteractionShader (); // Chooses between the various VFP files according to the CVAR settings. Only call this if settings got changed.
|
||||
void Hook_BufferCommandText( cmdExecution_t a_eType, const char *a_pcText ); // Source Hook for idCmdSystem::BufferCommandText - JC.
|
||||
|
||||
// will be called whenever vid_restart or reloadImages is executed
|
||||
// (set via common->SetCallback())
|
||||
static void ReloadImagesCallback(void* arg, const idCmdArgs& cmdArgs);
|
||||
};
|
||||
|
||||
dnPostProcessManager m_postProcessManager;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,276 +0,0 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* PROJECT: The Dark Mod
|
||||
* $Revision: 1435 $
|
||||
* $Date: 2007-10-16 22:23:28 +0530 (Tue, 16 Oct 2007) $
|
||||
* $Author: greebo $
|
||||
*
|
||||
***************************************************************************/
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 Metamod:Source Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): David "BAILOPAN" Anderson
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SMM_LIST_H
|
||||
#define _INCLUDE_SMM_LIST_H
|
||||
|
||||
#include <new>
|
||||
#include <malloc.h>
|
||||
|
||||
namespace SourceHook
|
||||
{
|
||||
//This class is from CSDM for AMX Mod X
|
||||
template <class T>
|
||||
class List
|
||||
{
|
||||
public:
|
||||
class iterator;
|
||||
friend class iterator;
|
||||
class ListNode
|
||||
{
|
||||
public:
|
||||
ListNode(const T & o) : obj(o) { };
|
||||
ListNode() { };
|
||||
T obj;
|
||||
ListNode *next;
|
||||
ListNode *prev;
|
||||
};
|
||||
private:
|
||||
ListNode *_Initialize()
|
||||
{
|
||||
ListNode *n = (ListNode *)malloc(sizeof(ListNode));
|
||||
n->next = NULL;
|
||||
n->prev = NULL;
|
||||
return n;
|
||||
}
|
||||
public:
|
||||
List() : m_Head(_Initialize()), m_Size(0)
|
||||
{
|
||||
}
|
||||
List(const List &src) : m_Head(_Initialize()), m_Size(0)
|
||||
{
|
||||
iterator iter;
|
||||
for (iter=src.begin(); iter!=src.end(); iter++)
|
||||
push_back( (*iter) );
|
||||
}
|
||||
~List()
|
||||
{
|
||||
clear();
|
||||
if (m_Head)
|
||||
{
|
||||
free(m_Head);
|
||||
m_Head = NULL;
|
||||
}
|
||||
}
|
||||
void push_back(const T &obj)
|
||||
{
|
||||
ListNode *node = new ListNode(obj);
|
||||
|
||||
if (!m_Head->prev)
|
||||
{
|
||||
//link in the node as the first item
|
||||
node->next = m_Head;
|
||||
node->prev = m_Head;
|
||||
m_Head->prev = node;
|
||||
m_Head->next = node;
|
||||
} else {
|
||||
node->prev = m_Head->prev;
|
||||
node->next = m_Head;
|
||||
m_Head->prev->next = node;
|
||||
m_Head->prev = node;
|
||||
}
|
||||
m_Size++;
|
||||
}
|
||||
size_t size()
|
||||
{
|
||||
return m_Size;
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
ListNode *node = m_Head->next;
|
||||
ListNode *temp;
|
||||
m_Head->next = NULL;
|
||||
m_Head->prev = NULL;
|
||||
while (node && node != m_Head)
|
||||
{
|
||||
temp = node->next;
|
||||
delete node;
|
||||
node = temp;
|
||||
}
|
||||
m_Size = 0;
|
||||
}
|
||||
bool empty()
|
||||
{
|
||||
return (m_Head->next == NULL);
|
||||
}
|
||||
T & back()
|
||||
{
|
||||
return m_Head->prev->obj;
|
||||
}
|
||||
private:
|
||||
ListNode *m_Head;
|
||||
size_t m_Size;
|
||||
public:
|
||||
class iterator
|
||||
{
|
||||
friend class List;
|
||||
public:
|
||||
iterator()
|
||||
{
|
||||
m_This = NULL;
|
||||
}
|
||||
iterator(const List &src)
|
||||
{
|
||||
m_This = src.m_Head;
|
||||
}
|
||||
iterator(ListNode *n) : m_This(n)
|
||||
{
|
||||
}
|
||||
iterator(const iterator &where)
|
||||
{
|
||||
m_This = where.m_This;
|
||||
}
|
||||
//pre decrement
|
||||
iterator & operator--()
|
||||
{
|
||||
if (m_This)
|
||||
m_This = m_This->prev;
|
||||
return *this;
|
||||
}
|
||||
//post decrement
|
||||
iterator operator--(int)
|
||||
{
|
||||
iterator old(*this);
|
||||
if (m_This)
|
||||
m_This = m_This->prev;
|
||||
return old;
|
||||
}
|
||||
|
||||
//pre increment
|
||||
iterator & operator++()
|
||||
{
|
||||
if (m_This)
|
||||
m_This = m_This->next;
|
||||
return *this;
|
||||
}
|
||||
//post increment
|
||||
iterator operator++(int)
|
||||
{
|
||||
iterator old(*this);
|
||||
if (m_This)
|
||||
m_This = m_This->next;
|
||||
return old;
|
||||
}
|
||||
|
||||
const T & operator * () const
|
||||
{
|
||||
return m_This->obj;
|
||||
}
|
||||
T & operator * ()
|
||||
{
|
||||
return m_This->obj;
|
||||
}
|
||||
|
||||
T * operator -> ()
|
||||
{
|
||||
return &(m_This->obj);
|
||||
}
|
||||
const T * operator -> () const
|
||||
{
|
||||
return &(m_This->obj);
|
||||
}
|
||||
|
||||
bool operator != (const iterator &where) const
|
||||
{
|
||||
return (m_This != where.m_This);
|
||||
}
|
||||
bool operator ==(const iterator &where) const
|
||||
{
|
||||
return (m_This == where.m_This);
|
||||
}
|
||||
private:
|
||||
ListNode *m_This;
|
||||
};
|
||||
public:
|
||||
iterator begin() const
|
||||
{
|
||||
if (m_Size)
|
||||
return iterator(m_Head->next);
|
||||
else
|
||||
return iterator(m_Head);
|
||||
}
|
||||
iterator end() const
|
||||
{
|
||||
return iterator(m_Head);
|
||||
}
|
||||
iterator erase(iterator &where)
|
||||
{
|
||||
ListNode *pNode = where.m_This;
|
||||
iterator iter(where);
|
||||
iter++;
|
||||
|
||||
//If we are both the head and tail...
|
||||
if (m_Head->next == pNode && m_Head->prev == pNode)
|
||||
{
|
||||
m_Head->next = NULL;
|
||||
m_Head->prev = NULL;
|
||||
} else if (m_Head->next == pNode) {
|
||||
//we are only the first
|
||||
pNode->next->prev = m_Head;
|
||||
m_Head->next = pNode->next;
|
||||
} else if (m_Head->prev == pNode) {
|
||||
//we are the tail
|
||||
pNode->prev->next = m_Head;
|
||||
m_Head->prev = pNode->prev;
|
||||
} else {
|
||||
//middle unlink
|
||||
pNode->prev->next = pNode->next;
|
||||
pNode->next->prev = pNode->prev;
|
||||
}
|
||||
|
||||
delete pNode;
|
||||
m_Size--;
|
||||
|
||||
return iter;
|
||||
}
|
||||
public:
|
||||
void remove(const T & obj)
|
||||
{
|
||||
iterator b;
|
||||
for (b=begin(); b!=end(); b++)
|
||||
{
|
||||
if ( (*b) == obj )
|
||||
{
|
||||
erase( b );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
template <typename U>
|
||||
iterator find(const U & equ)
|
||||
{
|
||||
iterator iter;
|
||||
for (iter=begin(); iter!=end(); iter++)
|
||||
{
|
||||
if ( (*iter) == equ )
|
||||
return iter;
|
||||
}
|
||||
return end();
|
||||
}
|
||||
List & operator =(List &src)
|
||||
{
|
||||
clear();
|
||||
iterator iter;
|
||||
for (iter=src.begin(); iter!=src.end(); iter++)
|
||||
push_back( (*iter) );
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
}; //NAMESPACE
|
||||
|
||||
#endif //_INCLUDE_CSDM_LIST_H
|
|
@ -1,899 +0,0 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* PROJECT: The Dark Mod
|
||||
* $Revision: 1435 $
|
||||
* $Date: 2007-10-16 22:23:28 +0530 (Tue, 16 Oct 2007) $
|
||||
* $Author: greebo $
|
||||
*
|
||||
***************************************************************************/
|
||||
/* ======== SourceHook ========
|
||||
* Copyright (C) 2004-2005 Metamod:Source Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): Pavol "PM OnoTo" Marko
|
||||
* ============================
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This file provides a way for getting information about a member function.
|
||||
* @file sh_memfuncinfo.h
|
||||
*/
|
||||
|
||||
#ifndef __SHINT_MEMFUNC_INFO_H__
|
||||
#define __SHINT_MEMFUNC_INFO_H__
|
||||
|
||||
namespace SourceHook
|
||||
{
|
||||
|
||||
// Don Clugston:
|
||||
// implicit_cast< >
|
||||
// I believe this was originally going to be in the C++ standard but
|
||||
// was left out by accident. It's even milder than static_cast.
|
||||
// I use it instead of static_cast<> to emphasize that I'm not doing
|
||||
// anything nasty.
|
||||
// Usage is identical to static_cast<>
|
||||
template <class OutputClass, class InputClass>
|
||||
inline OutputClass implicit_cast(InputClass input){
|
||||
return input;
|
||||
}
|
||||
|
||||
|
||||
struct MemFuncInfo
|
||||
{
|
||||
bool isVirtual; // Is the function virtual?
|
||||
int thisptroffs; // The this pointer the function expects to be called with
|
||||
// If -1, you need to call the GetFuncInfo_GetThisPtr function
|
||||
int vtblindex; // The function's index in the vtable (0-based, 1=second entry, 2=third entry, ...)
|
||||
int vtbloffs; // The vtable pointer
|
||||
};
|
||||
|
||||
// Ideas by Don Clugston.
|
||||
// Check out his excellent paper: http://www.codeproject.com/cpp/FastDelegate.asp
|
||||
|
||||
template<int N> struct MFI_Impl
|
||||
{
|
||||
template<class MFP> static inline void GetFuncInfo(MFP *mfp, MemFuncInfo &out)
|
||||
{
|
||||
static char weird_memfunc_pointer_exclamation_mark_arrow_error[N-1000];
|
||||
}
|
||||
};
|
||||
|
||||
# if SH_COMP == SH_COMP_GCC
|
||||
|
||||
template<> struct MFI_Impl<2*SH_PTRSIZE> // All of these have size==8/16
|
||||
{
|
||||
struct GCC_MemFunPtr
|
||||
{
|
||||
union
|
||||
{
|
||||
void *funcadr; // always even
|
||||
intptr_t vtable_index_plus1; // = vindex+1, always odd
|
||||
};
|
||||
intptr_t delta;
|
||||
};
|
||||
template<class MFP> static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out)
|
||||
{
|
||||
GCC_MemFunPtr *mfp_detail = (GCC_MemFunPtr*)&mfp;
|
||||
out.thisptroffs = mfp_detail->delta;
|
||||
if (mfp_detail->vtable_index_plus1 & 1)
|
||||
{
|
||||
out.vtblindex = (mfp_detail->vtable_index_plus1 - 1) / SH_PTRSIZE;
|
||||
out.vtbloffs = 0;
|
||||
out.isVirtual = true;
|
||||
}
|
||||
else
|
||||
out.isVirtual = false;
|
||||
}
|
||||
};
|
||||
|
||||
# elif SH_COMP == SH_COMP_MSVC
|
||||
|
||||
namespace
|
||||
{
|
||||
int MFI_GetVtblOffset(void *mfp)
|
||||
{
|
||||
unsigned char *addr = (unsigned char*)mfp;
|
||||
if (*addr == 0xE9) // Jmp
|
||||
{
|
||||
// May or may not be!
|
||||
// Check where it'd jump
|
||||
addr += 5 /*size of the instruction*/ + *(unsigned long*)(addr + 1);
|
||||
}
|
||||
|
||||
// Check whether it's a virtual function call
|
||||
// They look like this:
|
||||
// 004125A0 8B 01 mov eax,dword ptr [ecx]
|
||||
// 004125A2 FF 60 04 jmp dword ptr [eax+4]
|
||||
// ==OR==
|
||||
// 00411B80 8B 01 mov eax,dword ptr [ecx]
|
||||
// 00411B82 FF A0 18 03 00 00 jmp dword ptr [eax+318h]
|
||||
|
||||
// However, for vararg functions, they look like this:
|
||||
// 0048F0B0 8B 44 24 04 mov eax,dword ptr [esp+4]
|
||||
// 0048F0B4 8B 00 mov eax,dword ptr [eax]
|
||||
// 0048F0B6 FF 60 08 jmp dword ptr [eax+8]
|
||||
// ==OR==
|
||||
// 0048F0B0 8B 44 24 04 mov eax,dword ptr [esp+4]
|
||||
// 0048F0B4 8B 00 mov eax,dword ptr [eax]
|
||||
// 00411B82 FF A0 18 03 00 00 jmp dword ptr [eax+318h]
|
||||
|
||||
// With varargs, the this pointer is passed as if it was the first argument
|
||||
|
||||
bool ok = false;
|
||||
if (addr[0] == 0x8B && addr[1] == 0x44 && addr[2] == 0x24 && addr[3] == 0x04 &&
|
||||
addr[4] == 0x8B && addr[5] == 0x00)
|
||||
{
|
||||
addr += 6;
|
||||
ok = true;
|
||||
}
|
||||
else if (addr[0] == 0x8B && addr[1] == 0x01)
|
||||
{
|
||||
addr += 2;
|
||||
ok = true;
|
||||
}
|
||||
if (!ok)
|
||||
return -1;
|
||||
|
||||
if (*addr++ == 0xFF)
|
||||
{
|
||||
if (*addr == 0x60)
|
||||
{
|
||||
return *++addr / 4;
|
||||
}
|
||||
else if (*addr == 0xA0)
|
||||
{
|
||||
return *((unsigned int*)++addr) / 4;
|
||||
}
|
||||
else if (*addr == 0x20)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
template<> struct MFI_Impl<1*SH_PTRSIZE> // simple ones
|
||||
{
|
||||
template<class MFP> static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out)
|
||||
{
|
||||
out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp);
|
||||
out.isVirtual = out.vtblindex >= 0 ? true : false;
|
||||
out.thisptroffs = 0;
|
||||
out.vtbloffs = 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct MFI_Impl<2*SH_PTRSIZE> // more complicated ones!
|
||||
{
|
||||
struct MSVC_MemFunPtr2
|
||||
{
|
||||
void *funcadr;
|
||||
int delta;
|
||||
};
|
||||
template<class MFP> static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out)
|
||||
{
|
||||
out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp);
|
||||
out.isVirtual = out.vtblindex >= 0 ? true : false;
|
||||
out.thisptroffs = reinterpret_cast<MSVC_MemFunPtr2*>(&mfp)->delta;
|
||||
out.vtbloffs = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// By Don Clugston, adapted
|
||||
template<> struct MFI_Impl<3*SH_PTRSIZE> // WOW IT"S GETTING BIGGER OMGOMOGMG
|
||||
{
|
||||
class __single_inheritance GenericClass;
|
||||
class GenericClass {};
|
||||
|
||||
struct MicrosoftVirtualMFP {
|
||||
void (GenericClass::*codeptr)(); // points to the actual member function
|
||||
int delta; // #bytes to be added to the 'this' pointer
|
||||
int vtable_index; // or 0 if no virtual inheritance
|
||||
};
|
||||
|
||||
struct GenericVirtualClass : virtual public GenericClass
|
||||
{
|
||||
typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)();
|
||||
GenericVirtualClass * GetThis() { return this; }
|
||||
};
|
||||
|
||||
template<class MFP> static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out)
|
||||
{
|
||||
out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp);
|
||||
out.isVirtual = out.vtblindex >= 0 ? true : false;
|
||||
// This pointer
|
||||
/*
|
||||
union {
|
||||
MFP func;
|
||||
GenericClass* (T::*ProbeFunc)();
|
||||
MicrosoftVirtualMFP s;
|
||||
} u;
|
||||
u.func = mfp;
|
||||
union {
|
||||
GenericVirtualClass::ProbePtrType virtfunc;
|
||||
MicrosoftVirtualMFP s;
|
||||
} u2;
|
||||
|
||||
// Check that the horrible_cast<>s will work
|
||||
typedef int ERROR_CantUsehorrible_cast[sizeof(mfp)==sizeof(u.s)
|
||||
&& sizeof(mfp)==sizeof(u.ProbeFunc)
|
||||
&& sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1];
|
||||
// Unfortunately, taking the address of a MF prevents it from being inlined, so
|
||||
// this next line can't be completely optimised away by the compiler.
|
||||
u2.virtfunc = &GenericVirtualClass::GetThis;
|
||||
u.s.codeptr = u2.s.codeptr;
|
||||
out.thisptroffs = (reinterpret_cast<T*>(NULL)->*u.ProbeFunc)();
|
||||
*/
|
||||
out.thisptroffs = -1;
|
||||
out.vtbloffs = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Don: Nasty hack for Microsoft and Intel (IA32 and Itanium)
|
||||
// unknown_inheritance classes go here
|
||||
// This is probably the ugliest bit of code I've ever written. Look at the casts!
|
||||
// There is a compiler bug in MSVC6 which prevents it from using this code.
|
||||
template<> struct MFI_Impl<4*SH_PTRSIZE> // THE BIGGEST ONE!!!1GABEN
|
||||
{
|
||||
template<class MFP> static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out)
|
||||
{
|
||||
out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp);
|
||||
out.isVirtual = out.vtblindex >= 0 ? true : false;
|
||||
|
||||
// The member function pointer is 16 bytes long. We can't use a normal cast, but
|
||||
// we can use a union to do the conversion.
|
||||
union {
|
||||
MFP func;
|
||||
// In VC++ and ICL, an unknown_inheritance member pointer
|
||||
// is internally defined as:
|
||||
struct {
|
||||
void *m_funcaddress; // points to the actual member function
|
||||
int delta; // #bytes to be added to the 'this' pointer
|
||||
int vtordisp; // #bytes to add to 'this' to find the vtable
|
||||
int vtable_index; // or 0 if no virtual inheritance
|
||||
} s;
|
||||
} u;
|
||||
// Check that the horrible_cast will work
|
||||
typedef int ERROR_CantUsehorrible_cast[sizeof(u.func)==sizeof(u.s)? 1 : -1];
|
||||
u.func = mfp;
|
||||
int virtual_delta = 0;
|
||||
if (u.s.vtable_index) { // Virtual inheritance is used
|
||||
/*
|
||||
// First, get to the vtable.
|
||||
// It is 'vtordisp' bytes from the start of the class.
|
||||
int * vtable = *reinterpret_cast<int **>(
|
||||
reinterpret_cast<char *>(thisptr) + u.s.vtordisp );
|
||||
|
||||
// 'vtable_index' tells us where in the table we should be looking.
|
||||
virtual_delta = u.s.vtordisp + *reinterpret_cast<const int *>(
|
||||
reinterpret_cast<const char *>(vtable) + u.s.vtable_index);
|
||||
// The int at 'virtual_delta' gives us the amount to add to 'this'.
|
||||
// Finally we can add the three components together. Phew!
|
||||
out.thisptr = reinterpret_cast<void *>(
|
||||
reinterpret_cast<char *>(thisptr) + u.s.delta + virtual_delta);
|
||||
*/
|
||||
out.vtbloffs = u.s.vtordisp;
|
||||
out.thisptroffs = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
out.vtbloffs = out.vtblindex < 0 ? 0 : u.s.delta;
|
||||
out.thisptroffs = u.s.delta;
|
||||
}
|
||||
};
|
||||
};
|
||||
# else
|
||||
# error Unsupported compiler
|
||||
# endif
|
||||
|
||||
// This version does not take a this pointer
|
||||
// Useful for hookdecls, as they ensure that mfp is correct through a static_cast
|
||||
template<class X> inline void GetFuncInfo(X mfp, MemFuncInfo &out)
|
||||
{
|
||||
MFI_Impl<sizeof(mfp)>::GetFuncInfo(mfp, out);
|
||||
}
|
||||
|
||||
// Versions which do take a this
|
||||
template<class X, class Y, class RetType>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)() = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)() const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)() const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19, class Param20>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19, class Param20>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
|
||||
// GCC & MSVC 7.1 need this, MSVC 7.0 doesn't like it
|
||||
#if SH_COMP != SH_COMP_MSVC || _MSC_VER > 1300
|
||||
|
||||
template<class X, class Y, class RetType>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19, class Param20>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...), MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...) = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
template<class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class Param9, class Param10, class Param11, class Param12, class Param13, class Param14, class Param15, class Param16, class Param17, class Param18, class Param19, class Param20>
|
||||
inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...) const, MemFuncInfo &out)
|
||||
{
|
||||
RetType(Y::*mfp2)(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15, Param16, Param17, Param18, Param19, Param20, ...) const = mfp;
|
||||
MFI_Impl<sizeof(mfp2)>::GetFuncInfo(mfp2, out);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,197 +0,0 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* PROJECT: The Dark Mod
|
||||
* $Revision: 1435 $
|
||||
* $Date: 2007-10-16 22:23:28 +0530 (Tue, 16 Oct 2007) $
|
||||
* $Author: greebo $
|
||||
*
|
||||
***************************************************************************/
|
||||
/* ======== SourceHook ========
|
||||
* Copyright (C) 2004-2005 Metamod:Source Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): Pavol "PM OnoTo" Marko, Scott "Damaged Soul" Ehlert
|
||||
* Contributors: lancevorgin, XAD, theqizmo
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#ifndef __SHINT_MEMORY_H__
|
||||
#define __SHINT_MEMORY_H__
|
||||
|
||||
// Feb 17 / 2005:
|
||||
// Unprotect now sets to readwrite
|
||||
// The vtable doesn't need to be executable anyway
|
||||
|
||||
# if /********/ defined _WIN32
|
||||
# include <windows.h>
|
||||
# define SH_MEM_READ 1
|
||||
# define SH_MEM_WRITE 2
|
||||
# define SH_MEM_EXEC 4
|
||||
# elif /******/ defined __linux__
|
||||
# include <sys/mman.h>
|
||||
# include <stdio.h>
|
||||
# include <signal.h>
|
||||
# include <setjmp.h>
|
||||
// http://www.die.net/doc/linux/man/man2/mprotect.2.html
|
||||
# include <limits.h>
|
||||
# ifndef PAGESIZE
|
||||
# define PAGESIZE 4096
|
||||
# endif
|
||||
# define SH_MEM_READ PROT_READ
|
||||
# define SH_MEM_WRITE PROT_WRITE
|
||||
# define SH_MEM_EXEC PROT_EXEC
|
||||
|
||||
// We need to align addr down to pagesize on linux
|
||||
// We assume PAGESIZE is a power of two
|
||||
# define SH_LALIGN(x) (void*)((intptr_t)(x) & ~(PAGESIZE-1))
|
||||
# define SH_LALDIF(x) ((intptr_t)(x) & (PAGESIZE-1))
|
||||
# else
|
||||
# error Unsupported OS/Compiler
|
||||
# endif
|
||||
|
||||
|
||||
namespace SourceHook
|
||||
{
|
||||
inline bool SetMemAccess(void *addr, size_t len, int access)
|
||||
{
|
||||
# ifdef __linux__
|
||||
return mprotect(SH_LALIGN(addr), len + SH_LALDIF(addr), access)==0 ? true : false;
|
||||
# else
|
||||
DWORD tmp;
|
||||
DWORD prot;
|
||||
switch (access)
|
||||
{
|
||||
case SH_MEM_READ:
|
||||
prot = PAGE_READONLY; break;
|
||||
case SH_MEM_READ | SH_MEM_WRITE:
|
||||
prot = PAGE_READWRITE; break;
|
||||
case SH_MEM_READ | SH_MEM_EXEC:
|
||||
prot = PAGE_EXECUTE_READ; break;
|
||||
default:
|
||||
case SH_MEM_READ | SH_MEM_WRITE | SH_MEM_EXEC:
|
||||
prot = PAGE_EXECUTE_READWRITE; break;
|
||||
}
|
||||
return VirtualProtect(addr, len, prot, &tmp) ? true : false;
|
||||
# endif
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
namespace
|
||||
{
|
||||
bool g_BadReadCalled;
|
||||
jmp_buf g_BadReadJmpBuf;
|
||||
|
||||
static void BadReadHandler(int sig)
|
||||
{
|
||||
if (g_BadReadCalled)
|
||||
longjmp(g_BadReadJmpBuf, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Checks whether the specified memory region is (still) accessible
|
||||
*
|
||||
* @param addr The lower boundary
|
||||
* @param len Length of the region to be checked
|
||||
*/
|
||||
namespace
|
||||
{
|
||||
bool ModuleInMemory(char *addr, size_t len)
|
||||
{
|
||||
#ifdef __linux__
|
||||
// On linux, first check /proc/self/maps
|
||||
long lower = reinterpret_cast<long>(addr);
|
||||
long upper = lower + len;
|
||||
|
||||
FILE *pF = fopen("/proc/self/maps", "r");
|
||||
if (pF)
|
||||
{
|
||||
// Linux /proc/self/maps -> parse
|
||||
// Format:
|
||||
// lower upper prot stuff path
|
||||
// 08048000-0804c000 r-xp 00000000 03:03 1010107 /bin/cat
|
||||
long rlower, rupper;
|
||||
while (fscanf(pF, "%lx-%lx", &rlower, &rupper) != EOF)
|
||||
{
|
||||
// Check whether we're IN THERE!
|
||||
if (lower >= rlower && upper <= rupper)
|
||||
{
|
||||
fclose(pF);
|
||||
return true;
|
||||
}
|
||||
// Read to end of line
|
||||
int c;
|
||||
while ((c = fgetc(pF)) != '\n')
|
||||
{
|
||||
if (c == EOF)
|
||||
break;
|
||||
}
|
||||
if (c == EOF)
|
||||
break;
|
||||
}
|
||||
fclose(pF);
|
||||
return false;
|
||||
}
|
||||
pF = fopen("/proc/curproc/map", "r");
|
||||
if (pF)
|
||||
{
|
||||
// FreeBSD /proc/curproc/map -> parse
|
||||
// 0x804800 0x805500 13 15 0xc6e18960 r-x 21 0x0 COW NC vnode
|
||||
long rlower, rupper;
|
||||
while (fscanf(pF, "0x%lx 0x%lx", &rlower, &rupper) != EOF)
|
||||
{
|
||||
// Check whether we're IN THERE!
|
||||
if (lower >= rlower && upper <= rupper)
|
||||
{
|
||||
fclose(pF);
|
||||
return true;
|
||||
}
|
||||
// Read to end of line
|
||||
int c;
|
||||
while ((c = fgetc(pF)) != '\n')
|
||||
{
|
||||
if (c == EOF)
|
||||
break;
|
||||
}
|
||||
if (c == EOF)
|
||||
break;
|
||||
}
|
||||
fclose(pF);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Both of the above failed, try to actually read and trap sigsegv (implemented by Damaged Soul)
|
||||
void(*prevHandler)(int sig);
|
||||
g_BadReadCalled = true;
|
||||
|
||||
if (setjmp(g_BadReadJmpBuf))
|
||||
return true;
|
||||
|
||||
prevHandler = signal(SIGSEGV, BadReadHandler);
|
||||
|
||||
volatile const char *p = reinterpret_cast<const char*>(addr);
|
||||
char dummy;
|
||||
|
||||
for (size_t i = 0; i < len; i++)
|
||||
dummy = p[i];
|
||||
|
||||
(void)dummy;
|
||||
|
||||
g_BadReadCalled = false;
|
||||
|
||||
signal(SIGSEGV, prevHandler);
|
||||
|
||||
return false;
|
||||
#else
|
||||
// On Win32, simply use IsBadReadPtr
|
||||
return !IsBadReadPtr(addr, len);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,227 +0,0 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* PROJECT: The Dark Mod
|
||||
* $Revision: 1435 $
|
||||
* $Date: 2007-10-16 22:23:28 +0530 (Tue, 16 Oct 2007) $
|
||||
* $Author: greebo $
|
||||
*
|
||||
***************************************************************************/
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 Metamod:Source Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): Pavol "PM OnoTo" Marko
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#ifndef __SH_STACK_H__
|
||||
#define __SH_STACK_H__
|
||||
|
||||
#define SH_STACK_DEFAULT_SIZE 4
|
||||
|
||||
namespace SourceHook
|
||||
{
|
||||
// Vector
|
||||
template <class T> class CStack
|
||||
{
|
||||
T *m_Elements;
|
||||
size_t m_AllocatedSize;
|
||||
size_t m_UsedSize;
|
||||
public:
|
||||
friend class iterator;
|
||||
class iterator
|
||||
{
|
||||
CStack<T> *m_pParent;
|
||||
size_t m_Index;
|
||||
public:
|
||||
iterator(CStack<T> *pParent, size_t id) : m_pParent(pParent), m_Index(id)
|
||||
{
|
||||
}
|
||||
|
||||
iterator(CStack<T> *pParent) : m_pParent(pParent), m_Index(0)
|
||||
{
|
||||
}
|
||||
|
||||
iterator() : m_pParent(NULL), m_Index(0)
|
||||
{
|
||||
}
|
||||
|
||||
T &operator *()
|
||||
{
|
||||
return m_pParent->m_Elements[m_Index];
|
||||
}
|
||||
const T &operator *() const
|
||||
{
|
||||
return m_pParent->m_Elements[m_Index];
|
||||
}
|
||||
|
||||
T * operator->()
|
||||
{
|
||||
return m_pParent->m_Elements + m_Index;
|
||||
}
|
||||
|
||||
const T * operator->() const
|
||||
{
|
||||
return m_pParent->m_Elements + m_Index;
|
||||
}
|
||||
|
||||
iterator & operator++() // preincrement
|
||||
{
|
||||
++m_Index;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
iterator operator++(int) // postincrement
|
||||
{
|
||||
iterator tmp = *this;
|
||||
++m_Index;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
iterator & operator--() // predecrement
|
||||
{
|
||||
--m_Index;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
iterator operator--(int) // postdecrememnt
|
||||
{
|
||||
iterator tmp = *this;
|
||||
--m_Index;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const iterator & right) const
|
||||
{
|
||||
return (m_pParent == right.m_pParent && m_Index == right.m_Index);
|
||||
}
|
||||
|
||||
bool operator!=(const iterator & right) const
|
||||
{
|
||||
return !(*this == right);
|
||||
}
|
||||
};
|
||||
CStack() : m_Elements(new T[SH_STACK_DEFAULT_SIZE]),
|
||||
m_AllocatedSize(SH_STACK_DEFAULT_SIZE),
|
||||
m_UsedSize(0)
|
||||
{
|
||||
}
|
||||
CStack(size_t size) : m_Elements(new T[size]),
|
||||
m_AllocatedSize(size),
|
||||
m_UsedSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
CStack(const CStack &other) : m_Elements(NULL),
|
||||
m_AllocatedSize(0),
|
||||
m_UsedSize(0)
|
||||
{
|
||||
reserve(other.m_AllocatedSize);
|
||||
m_UsedSize = other.m_UsedSize;
|
||||
for (size_t i = 0; i < m_UsedSize; ++i)
|
||||
m_Elements[i] = other.m_Elements[i];
|
||||
}
|
||||
|
||||
~CStack()
|
||||
{
|
||||
if (m_Elements)
|
||||
delete [] m_Elements;
|
||||
}
|
||||
|
||||
void operator=(const CStack &other)
|
||||
{
|
||||
if (m_AllocatedSize < other.m_AllocatedSize)
|
||||
{
|
||||
if (m_Elements)
|
||||
delete [] m_Elements;
|
||||
m_Elements = new T[other.m_AllocatedSize];
|
||||
m_AllocatedSize = other.m_AllocatedSize;
|
||||
}
|
||||
m_UsedSize = other.m_UsedSize;
|
||||
for (size_t i = 0; i < m_UsedSize; ++i)
|
||||
m_Elements[i] = other.m_Elements[i];
|
||||
}
|
||||
|
||||
bool push(const T &val)
|
||||
{
|
||||
if (m_UsedSize + 1 == m_AllocatedSize)
|
||||
{
|
||||
// zOHNOES! REALLOCATE!
|
||||
m_AllocatedSize *= 2;
|
||||
T *newElements = new T[m_AllocatedSize];
|
||||
if (!newElements)
|
||||
{
|
||||
m_AllocatedSize /= 2;
|
||||
return false;
|
||||
}
|
||||
if (m_Elements)
|
||||
{
|
||||
for (size_t i = 0; i < m_UsedSize; ++i)
|
||||
newElements[i] = m_Elements[i];
|
||||
delete [] m_Elements;
|
||||
}
|
||||
m_Elements = newElements;
|
||||
}
|
||||
m_Elements[m_UsedSize++] = val;
|
||||
return true;
|
||||
}
|
||||
void pop()
|
||||
{
|
||||
--m_UsedSize;
|
||||
}
|
||||
|
||||
T &front()
|
||||
{
|
||||
return m_Elements[m_UsedSize - 1];
|
||||
}
|
||||
|
||||
const T &front() const
|
||||
{
|
||||
return m_Elements[m_UsedSize - 1];
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(this, 0);
|
||||
}
|
||||
iterator end()
|
||||
{
|
||||
return iterator(this, m_UsedSize);
|
||||
}
|
||||
|
||||
size_t size()
|
||||
{
|
||||
return m_UsedSize;
|
||||
}
|
||||
size_t capacity()
|
||||
{
|
||||
return m_AllocatedSize;
|
||||
}
|
||||
bool empty()
|
||||
{
|
||||
return m_UsedSize == 0 ? true : false;
|
||||
}
|
||||
bool reserve(size_t size)
|
||||
{
|
||||
if (size > m_AllocatedSize)
|
||||
{
|
||||
T *newElements = new T[size];
|
||||
if (!newElements)
|
||||
return false;
|
||||
if (m_Elements)
|
||||
{
|
||||
for (size_t i = 0; i < m_UsedSize; ++i)
|
||||
newElements[i] = m_Elements[i];
|
||||
delete [] m_Elements;
|
||||
}
|
||||
m_Elements = newElements;
|
||||
m_AllocatedSize = size;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}; //namespace SourceHook
|
||||
|
||||
#endif
|
|
@ -1,375 +0,0 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* PROJECT: The Dark Mod
|
||||
* $Revision: 1435 $
|
||||
* $Date: 2007-10-16 22:23:28 +0530 (Tue, 16 Oct 2007) $
|
||||
* $Author: greebo $
|
||||
*
|
||||
***************************************************************************/
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 Metamod:Source Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): David "BAILOPAN" Anderson
|
||||
* ============================
|
||||
*/
|
||||
|
||||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_CSTRING_H
|
||||
#define _INCLUDE_CSTRING_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace SourceHook
|
||||
{
|
||||
class String
|
||||
{
|
||||
public:
|
||||
String()
|
||||
{
|
||||
v = NULL;
|
||||
a_size = 0;
|
||||
//assign("");
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
if (v)
|
||||
delete [] v;
|
||||
}
|
||||
|
||||
String(const char *src)
|
||||
{
|
||||
v = NULL;
|
||||
a_size = 0;
|
||||
assign(src);
|
||||
}
|
||||
|
||||
String(const String &src)
|
||||
{
|
||||
v = NULL;
|
||||
a_size = 0;
|
||||
assign(src.c_str());
|
||||
}
|
||||
|
||||
const char *c_str() { return v?v:""; }
|
||||
|
||||
const char *c_str() const { return v?v:""; }
|
||||
|
||||
void append(const char *t)
|
||||
{
|
||||
Grow(size() + strlen(t) + 1);
|
||||
strcat(v, t);
|
||||
}
|
||||
|
||||
void append(const char c)
|
||||
{
|
||||
size_t len = size();
|
||||
Grow(len + 2);
|
||||
v[len] = c;
|
||||
v[len + 1] = '\0';
|
||||
}
|
||||
|
||||
void append(String &d)
|
||||
{
|
||||
append(d.c_str());
|
||||
}
|
||||
|
||||
void assign(const String &src)
|
||||
{
|
||||
assign(src.c_str());
|
||||
}
|
||||
|
||||
void assign(const char *d)
|
||||
{
|
||||
if (!d)
|
||||
{
|
||||
clear();
|
||||
} else {
|
||||
Grow(strlen(d) + 1, false);
|
||||
strcpy(v, d);
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
if (v)
|
||||
v[0] = '\0';
|
||||
}
|
||||
|
||||
int compare (const char *d)
|
||||
{
|
||||
if (!v)
|
||||
return strcmp("", d);
|
||||
else
|
||||
return strcmp(v, d);
|
||||
}
|
||||
|
||||
//Added this for amxx inclusion
|
||||
bool empty()
|
||||
{
|
||||
if (!v)
|
||||
return true;
|
||||
|
||||
if (v[0] == '\0')
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t size()
|
||||
{
|
||||
if (v)
|
||||
return strlen(v);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int find(const char c, int index = 0)
|
||||
{
|
||||
int len = static_cast<int>(size());
|
||||
if (len < 1)
|
||||
return npos;
|
||||
if (index >= len || index < 0)
|
||||
return npos;
|
||||
int i = 0;
|
||||
for (i=index; i<len; i++)
|
||||
{
|
||||
if (v[i] == c)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
bool is_space(int c)
|
||||
{
|
||||
if (c == '\f' || c == '\n' ||
|
||||
c == '\t' || c == '\r' ||
|
||||
c == '\v' || c == ' ')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void trim()
|
||||
{
|
||||
if (!v)
|
||||
return;
|
||||
|
||||
unsigned int i = 0;
|
||||
unsigned int j = 0;
|
||||
size_t len = strlen(v);
|
||||
|
||||
if (len == 1)
|
||||
{
|
||||
if (is_space(v[i]))
|
||||
{
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char c0 = v[0];
|
||||
|
||||
if (is_space(c0))
|
||||
{
|
||||
for (i=0; i<len; i++)
|
||||
{
|
||||
if (!is_space(v[i]) || (is_space(v[i]) && ((unsigned char)i==len-1)))
|
||||
{
|
||||
erase(0, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
len = strlen(v);
|
||||
|
||||
if (len < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_space(v[len-1]))
|
||||
{
|
||||
for (i=len-1; i>=0; i--)
|
||||
{
|
||||
if (!is_space(v[i])
|
||||
|| (is_space(v[i]) && i==0))
|
||||
{
|
||||
erase(i+1, j);
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
if (len == 1)
|
||||
{
|
||||
if (is_space(v[0]))
|
||||
{
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void erase(unsigned int start, int num = npos)
|
||||
{
|
||||
if (!v)
|
||||
return;
|
||||
unsigned int i = 0;
|
||||
size_t len = size();
|
||||
//check for bounds
|
||||
if (num == npos || start+num > len-num+1)
|
||||
num = len - start;
|
||||
//do the erasing
|
||||
bool copyflag = false;
|
||||
for (i=0; i<len; i++)
|
||||
{
|
||||
if (i>=start && i<start+num)
|
||||
{
|
||||
if (i+num < len)
|
||||
{
|
||||
v[i] = v[i+num];
|
||||
} else {
|
||||
v[i] = 0;
|
||||
}
|
||||
copyflag = true;
|
||||
} else if (copyflag) {
|
||||
if (i+num < len)
|
||||
{
|
||||
v[i] = v[i+num];
|
||||
} else {
|
||||
v[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
len -= num;
|
||||
v[len] = 0;
|
||||
}
|
||||
|
||||
String substr(unsigned int index, int num = npos)
|
||||
{
|
||||
if (!v)
|
||||
{
|
||||
String b("");
|
||||
return b;
|
||||
}
|
||||
|
||||
String ns;
|
||||
|
||||
size_t len = size();
|
||||
|
||||
if (index >= len || !v)
|
||||
return ns;
|
||||
|
||||
if (num == npos)
|
||||
{
|
||||
num = len - index;
|
||||
} else if (index+num >= len) {
|
||||
num = len - index;
|
||||
}
|
||||
|
||||
unsigned int i = 0;
|
||||
unsigned int nslen = num + 2;
|
||||
|
||||
ns.Grow(nslen);
|
||||
|
||||
for (i=index; i<index+num; i++)
|
||||
ns.append(v[i]);
|
||||
|
||||
return ns;
|
||||
}
|
||||
|
||||
void toLower()
|
||||
{
|
||||
if (!v)
|
||||
return;
|
||||
unsigned int i = 0;
|
||||
size_t len = strlen(v);
|
||||
for (i=0; i<len; i++)
|
||||
{
|
||||
if (v[i] >= 65 && v[i] <= 90)
|
||||
v[i] &= ~(1<<5);
|
||||
}
|
||||
}
|
||||
|
||||
String & operator = (const String &src)
|
||||
{
|
||||
assign(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String & operator = (const char *src)
|
||||
{
|
||||
assign(src);
|
||||
return *this;
|
||||
|
||||
}
|
||||
|
||||
char operator [] (unsigned int index)
|
||||
{
|
||||
if (index > size() || !v)
|
||||
{
|
||||
return -1;
|
||||
} else {
|
||||
return v[index];
|
||||
}
|
||||
}
|
||||
|
||||
int at(int a)
|
||||
{
|
||||
if (a < 0 || a >= (int)size() || !v)
|
||||
return -1;
|
||||
|
||||
return v[a];
|
||||
}
|
||||
|
||||
bool at(int at, char c)
|
||||
{
|
||||
if (at < 0 || at >= (int)size() || !v)
|
||||
return false;
|
||||
|
||||
v[at] = c;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
void Grow(unsigned int d, bool copy=true)
|
||||
{
|
||||
if (d <= a_size)
|
||||
return;
|
||||
char *n = new char[d + 1];
|
||||
if (copy && v)
|
||||
strcpy(n, v);
|
||||
if (v)
|
||||
delete [] v;
|
||||
else
|
||||
strcpy(n, "");
|
||||
v = n;
|
||||
a_size = d + 1;
|
||||
}
|
||||
|
||||
char *v;
|
||||
unsigned int a_size;
|
||||
public:
|
||||
static const int npos = -1;
|
||||
};
|
||||
|
||||
}; //NAMESPACE
|
||||
|
||||
#endif //_INCLUDE_CSTRING_H
|
|
@ -1,474 +0,0 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* PROJECT: The Dark Mod
|
||||
* $Revision: 1435 $
|
||||
* $Date: 2007-10-16 22:23:28 +0530 (Tue, 16 Oct 2007) $
|
||||
* $Author: greebo $
|
||||
*
|
||||
***************************************************************************/
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 Metamod:Source Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): David "BAILOPAN" Anderson
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SH_TINYHASH_H_
|
||||
#define _INCLUDE_SH_TINYHASH_H_
|
||||
|
||||
#include "sh_list.h"
|
||||
|
||||
#define _T_INIT_HASH_SIZE 32
|
||||
|
||||
namespace SourceHook
|
||||
{
|
||||
template <class K>
|
||||
int HashFunction(const K & k);
|
||||
|
||||
template <class K>
|
||||
int Compare(const K & k1, const K & k2);
|
||||
|
||||
/**
|
||||
* This is a tiny, growable hash class.
|
||||
* Meant for quick and dirty dictionaries only!
|
||||
*/
|
||||
template <class K, class V>
|
||||
class THash
|
||||
{
|
||||
public:
|
||||
struct THashNode
|
||||
{
|
||||
THashNode(const K & k, const V & v) :
|
||||
key(k), val(v)
|
||||
{
|
||||
};
|
||||
K key;
|
||||
V val;
|
||||
};
|
||||
typedef List<THashNode *> * NodePtr;
|
||||
public:
|
||||
THash() : m_Buckets(NULL), m_numBuckets(0), m_percentUsed(0.0f)
|
||||
{
|
||||
_Refactor();
|
||||
}
|
||||
THash(const THash &other) : m_Buckets(new NodePtr[other.m_numBuckets]),
|
||||
m_numBuckets(other.m_numBuckets), m_percentUsed(other.m_percentUsed)
|
||||
{
|
||||
for (size_t i=0; i<m_numBuckets; i++)
|
||||
m_Buckets[i] = NULL;
|
||||
for (const_iterator iter = other.begin(); iter != other.end(); ++iter)
|
||||
_FindOrInsert(iter->key)->val = iter->val;
|
||||
}
|
||||
void operator=(const THash &other)
|
||||
{
|
||||
clear();
|
||||
for (const_iterator iter = other.begin(); iter != other.end(); ++iter)
|
||||
_FindOrInsert(iter->key)->val = iter->val;
|
||||
}
|
||||
|
||||
~THash()
|
||||
{
|
||||
_Clear();
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
_Clear();
|
||||
_Refactor();
|
||||
}
|
||||
size_t GetBuckets()
|
||||
{
|
||||
return m_numBuckets;
|
||||
}
|
||||
float PercentUsed()
|
||||
{
|
||||
return m_percentUsed;
|
||||
}
|
||||
V & operator [](const K & key)
|
||||
{
|
||||
THashNode *pNode = _FindOrInsert(key);
|
||||
return pNode->val;
|
||||
}
|
||||
private:
|
||||
void _Clear()
|
||||
{
|
||||
for (size_t i=0; i<m_numBuckets; i++)
|
||||
{
|
||||
if (m_Buckets[i])
|
||||
{
|
||||
delete m_Buckets[i];
|
||||
m_Buckets[i] = NULL;
|
||||
}
|
||||
}
|
||||
if (m_Buckets)
|
||||
delete [] m_Buckets;
|
||||
m_Buckets = NULL;
|
||||
m_numBuckets = 0;
|
||||
}
|
||||
THashNode *_FindOrInsert(const K & key)
|
||||
{
|
||||
size_t place = HashFunction(key) % m_numBuckets;
|
||||
THashNode *pNode = NULL;
|
||||
if (!m_Buckets[place])
|
||||
{
|
||||
m_Buckets[place] = new List<THashNode *>;
|
||||
pNode = new THashNode(key, V());
|
||||
m_Buckets[place]->push_back(pNode);
|
||||
m_percentUsed += (1.0f / (float)m_numBuckets);
|
||||
} else {
|
||||
typename List<THashNode *>::iterator iter;
|
||||
for (iter=m_Buckets[place]->begin(); iter!=m_Buckets[place]->end(); iter++)
|
||||
{
|
||||
if (Compare((*iter)->key, key) == 0)
|
||||
return (*iter);
|
||||
}
|
||||
//node does not exist
|
||||
pNode = new THashNode(key, V());
|
||||
m_Buckets[place]->push_back(pNode);
|
||||
}
|
||||
if (PercentUsed() > 0.75f)
|
||||
_Refactor();
|
||||
return pNode;
|
||||
}
|
||||
void _Refactor()
|
||||
{
|
||||
m_percentUsed = 0.0f;
|
||||
if (!m_numBuckets)
|
||||
{
|
||||
m_numBuckets = _T_INIT_HASH_SIZE;
|
||||
m_Buckets = new NodePtr[m_numBuckets];
|
||||
for (size_t i=0; i<m_numBuckets; i++)
|
||||
m_Buckets[i] = NULL;
|
||||
} else {
|
||||
size_t oldSize = m_numBuckets;
|
||||
m_numBuckets *= 2;
|
||||
typename List<THashNode *>::iterator iter;
|
||||
size_t place;
|
||||
THashNode *pHashNode;
|
||||
NodePtr *temp = new NodePtr[m_numBuckets];
|
||||
for (size_t i=0; i<m_numBuckets; i++)
|
||||
temp[i] = NULL;
|
||||
//look in old hash table
|
||||
for (size_t i=0; i<oldSize; i++)
|
||||
{
|
||||
//does a bucket have anything?
|
||||
if (m_Buckets[i])
|
||||
{
|
||||
//go through the list of items
|
||||
for (iter = m_Buckets[i]->begin(); iter != m_Buckets[i]->end(); iter++)
|
||||
{
|
||||
pHashNode = (*iter);
|
||||
//rehash it with the new bucket filter
|
||||
place = HashFunction(pHashNode->key) % m_numBuckets;
|
||||
//add it to the new hash table
|
||||
if (!temp[place])
|
||||
{
|
||||
temp[place] = new List<THashNode *>;
|
||||
m_percentUsed += (1.0f / (float)m_numBuckets);
|
||||
}
|
||||
temp[place]->push_back(pHashNode);
|
||||
}
|
||||
//delete that bucket!
|
||||
delete m_Buckets[i];
|
||||
m_Buckets[i] = NULL;
|
||||
}
|
||||
}
|
||||
//reassign bucket table
|
||||
delete [] m_Buckets;
|
||||
m_Buckets = temp;
|
||||
}
|
||||
}
|
||||
public:
|
||||
friend class iterator;
|
||||
friend class const_iterator;
|
||||
class iterator
|
||||
{
|
||||
friend class THash;
|
||||
public:
|
||||
iterator() : curbucket(-1), hash(NULL), end(true)
|
||||
{
|
||||
};
|
||||
iterator(THash *h) : curbucket(-1), hash(h), end(false)
|
||||
{
|
||||
if (!h->m_Buckets)
|
||||
end = true;
|
||||
else
|
||||
_Inc();
|
||||
};
|
||||
//pre increment
|
||||
iterator & operator++()
|
||||
{
|
||||
_Inc();
|
||||
return *this;
|
||||
}
|
||||
//post increment
|
||||
iterator operator++(int)
|
||||
{
|
||||
iterator old(*this);
|
||||
_Inc();
|
||||
return old;
|
||||
}
|
||||
const THashNode & operator * () const
|
||||
{
|
||||
return *(*iter);
|
||||
}
|
||||
THashNode & operator * ()
|
||||
{
|
||||
return *(*iter);
|
||||
}
|
||||
const THashNode * operator ->() const
|
||||
{
|
||||
return (*iter);
|
||||
}
|
||||
THashNode * operator ->()
|
||||
{
|
||||
return (*iter);
|
||||
}
|
||||
bool operator ==(const iterator &where) const
|
||||
{
|
||||
if (where.hash == this->hash
|
||||
&& where.end == this->end
|
||||
&&
|
||||
(this->end ||
|
||||
((where.curbucket == this->curbucket)
|
||||
&& (where.iter == iter))
|
||||
))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool operator !=(const iterator &where) const
|
||||
{
|
||||
return !( (*this) == where );
|
||||
}
|
||||
|
||||
void erase()
|
||||
{
|
||||
if (end || !hash || curbucket < 0 || curbucket >= static_cast<int>(hash->m_numBuckets))
|
||||
return;
|
||||
|
||||
// Remove this element and move to the next one
|
||||
iterator tmp = *this;
|
||||
++tmp;
|
||||
hash->m_Buckets[curbucket]->erase(iter);
|
||||
*this = tmp;
|
||||
|
||||
// :TODO: Maybe refactor to a lower size if required
|
||||
}
|
||||
private:
|
||||
void _Inc()
|
||||
{
|
||||
if (end || !hash || curbucket >= static_cast<int>(hash->m_numBuckets))
|
||||
return;
|
||||
if (curbucket < 0)
|
||||
{
|
||||
for (int i=0; i<(int)hash->m_numBuckets; i++)
|
||||
{
|
||||
if (hash->m_Buckets[i])
|
||||
{
|
||||
iter = hash->m_Buckets[i]->begin();
|
||||
if (iter == hash->m_Buckets[i]->end())
|
||||
continue;
|
||||
curbucket = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (curbucket < 0)
|
||||
end = true;
|
||||
} else {
|
||||
if (iter != hash->m_Buckets[curbucket]->end())
|
||||
iter++;
|
||||
if (iter == hash->m_Buckets[curbucket]->end())
|
||||
{
|
||||
int oldbucket = curbucket;
|
||||
for (int i=curbucket+1; i<(int)hash->m_numBuckets; i++)
|
||||
{
|
||||
if (hash->m_Buckets[i])
|
||||
{
|
||||
iter = hash->m_Buckets[i]->begin();
|
||||
if (iter == hash->m_Buckets[i]->end())
|
||||
continue;
|
||||
curbucket = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (curbucket == oldbucket)
|
||||
end = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
int curbucket;
|
||||
typename SourceHook::List<THashNode *>::iterator iter;
|
||||
THash *hash;
|
||||
bool end;
|
||||
};
|
||||
class const_iterator
|
||||
{
|
||||
friend class THash;
|
||||
public:
|
||||
const_iterator() : curbucket(-1), hash(NULL), end(true)
|
||||
{
|
||||
};
|
||||
const_iterator(const THash *h) : curbucket(-1), hash(h), end(false)
|
||||
{
|
||||
if (!h->m_Buckets)
|
||||
end = true;
|
||||
else
|
||||
_Inc();
|
||||
};
|
||||
//pre increment
|
||||
const_iterator & operator++()
|
||||
{
|
||||
_Inc();
|
||||
return *this;
|
||||
}
|
||||
//post increment
|
||||
const_iterator operator++(int)
|
||||
{
|
||||
iterator old(*this);
|
||||
_Inc();
|
||||
return old;
|
||||
}
|
||||
const THashNode & operator * () const
|
||||
{
|
||||
return *(*iter);
|
||||
}
|
||||
const THashNode * operator ->() const
|
||||
{
|
||||
return (*iter);
|
||||
}
|
||||
bool operator ==(const const_iterator &where) const
|
||||
{
|
||||
if (where.hash == this->hash
|
||||
&& where.end == this->end
|
||||
&&
|
||||
(this->end ||
|
||||
((where.curbucket == this->curbucket)
|
||||
&& (where.iter == iter))
|
||||
))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool operator !=(const const_iterator &where) const
|
||||
{
|
||||
return !( (*this) == where );
|
||||
}
|
||||
private:
|
||||
void _Inc()
|
||||
{
|
||||
if (end || !hash || curbucket >= static_cast<int>(hash->m_numBuckets))
|
||||
return;
|
||||
if (curbucket < 0)
|
||||
{
|
||||
for (int i=0; i<(int)hash->m_numBuckets; i++)
|
||||
{
|
||||
if (hash->m_Buckets[i])
|
||||
{
|
||||
iter = hash->m_Buckets[i]->begin();
|
||||
if (iter == hash->m_Buckets[i]->end())
|
||||
continue;
|
||||
curbucket = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (curbucket < 0)
|
||||
end = true;
|
||||
} else {
|
||||
if (iter != hash->m_Buckets[curbucket]->end())
|
||||
iter++;
|
||||
if (iter == hash->m_Buckets[curbucket]->end())
|
||||
{
|
||||
int oldbucket = curbucket;
|
||||
for (int i=curbucket+1; i<(int)hash->m_numBuckets; i++)
|
||||
{
|
||||
if (hash->m_Buckets[i])
|
||||
{
|
||||
iter = hash->m_Buckets[i]->begin();
|
||||
if (iter == hash->m_Buckets[i]->end())
|
||||
continue;
|
||||
curbucket = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (curbucket == oldbucket)
|
||||
end = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
int curbucket;
|
||||
typename SourceHook::List<THashNode *>::iterator iter;
|
||||
const THash *hash;
|
||||
bool end;
|
||||
};
|
||||
public:
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(this);
|
||||
}
|
||||
iterator end()
|
||||
{
|
||||
iterator iter;
|
||||
iter.hash = this;
|
||||
return iter;
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(this);
|
||||
}
|
||||
const_iterator end() const
|
||||
{
|
||||
const_iterator iter;
|
||||
iter.hash = this;
|
||||
return iter;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
iterator find(const U & u) const
|
||||
{
|
||||
iterator b = begin();
|
||||
iterator e = end();
|
||||
for (iterator iter = b; iter != e; iter++)
|
||||
{
|
||||
if ( (*iter).key == u )
|
||||
return iter;
|
||||
}
|
||||
return end();
|
||||
}
|
||||
template <typename U>
|
||||
iterator find(const U & u)
|
||||
{
|
||||
iterator b = begin();
|
||||
iterator e = end();
|
||||
for (iterator iter = b; iter != e; iter++)
|
||||
{
|
||||
if ( (*iter).key == u )
|
||||
return iter;
|
||||
}
|
||||
return end();
|
||||
}
|
||||
|
||||
iterator erase(iterator where)
|
||||
{
|
||||
where.erase();
|
||||
return where;
|
||||
}
|
||||
template <typename U>
|
||||
void erase(const U & u)
|
||||
{
|
||||
iterator iter = find(u);
|
||||
if (iter == end())
|
||||
return;
|
||||
iter.erase();
|
||||
}
|
||||
private:
|
||||
NodePtr *m_Buckets;
|
||||
size_t m_numBuckets;
|
||||
float m_percentUsed;
|
||||
};
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SH_TINYHASH_H_
|
|
@ -1,482 +0,0 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* PROJECT: The Dark Mod
|
||||
* $Revision: 1435 $
|
||||
* $Date: 2007-10-16 22:23:28 +0530 (Tue, 16 Oct 2007) $
|
||||
* $Author: greebo $
|
||||
*
|
||||
***************************************************************************/
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 Metamod:Source Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): Pavol "PM OnoTo" Marko
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#ifndef __CVECTOR_H__
|
||||
#define __CVECTOR_H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
//This file originally from AMX Mod X
|
||||
namespace SourceHook
|
||||
{
|
||||
// Vector
|
||||
template <class T> class CVector
|
||||
{
|
||||
bool Grow()
|
||||
{
|
||||
// automatic grow
|
||||
size_t newSize = m_Size * 2;
|
||||
if (newSize == 0)
|
||||
newSize = 8; // a good init value
|
||||
T *newData = new T[newSize];
|
||||
if (!newData)
|
||||
return false;
|
||||
if (m_Data)
|
||||
{
|
||||
for (size_t i=0; i<m_CurrentUsedSize; i++)
|
||||
newData[i] = m_Data[i];
|
||||
delete [] m_Data;
|
||||
}
|
||||
m_Data = newData;
|
||||
m_Size = newSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrowIfNeeded()
|
||||
{
|
||||
if (m_CurrentUsedSize >= m_Size)
|
||||
return Grow();
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChangeSize(size_t size)
|
||||
{
|
||||
// change size
|
||||
if (size == m_Size)
|
||||
return true;
|
||||
|
||||
if (!size)
|
||||
{
|
||||
if (m_Data)
|
||||
{
|
||||
delete [] m_Data;
|
||||
m_Data = NULL;
|
||||
m_Size = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
T *newData = new T[size];
|
||||
if (!newData)
|
||||
return false;
|
||||
if (m_Data)
|
||||
{
|
||||
size_t end = (m_CurrentUsedSize < size) ? (m_CurrentUsedSize) : size;
|
||||
for (size_t i=0; i<end; i++)
|
||||
newData[i] = m_Data[i];
|
||||
delete [] m_Data;
|
||||
}
|
||||
m_Data = newData;
|
||||
m_Size = size;
|
||||
if (m_CurrentUsedSize > m_Size)
|
||||
m_CurrentUsedSize = m_Size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FreeMemIfPossible()
|
||||
{
|
||||
if (!m_Data)
|
||||
return;
|
||||
|
||||
if (!m_CurrentUsedSize)
|
||||
{
|
||||
ChangeSize(0);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t newSize = m_Size;
|
||||
while (m_CurrentUsedSize <= newSize / 2)
|
||||
newSize /= 2;
|
||||
|
||||
if (newSize != m_Size)
|
||||
ChangeSize(newSize);
|
||||
}
|
||||
protected:
|
||||
T *m_Data;
|
||||
size_t m_Size;
|
||||
size_t m_CurrentUsedSize;
|
||||
public:
|
||||
class iterator
|
||||
{
|
||||
protected:
|
||||
T *m_Ptr;
|
||||
public:
|
||||
// constructors / destructors
|
||||
iterator()
|
||||
{
|
||||
m_Ptr = NULL;
|
||||
}
|
||||
|
||||
iterator(T * ptr)
|
||||
{
|
||||
m_Ptr = ptr;
|
||||
}
|
||||
|
||||
// member functions
|
||||
T * base()
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
const T * base() const
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
// operators
|
||||
T & operator*()
|
||||
{
|
||||
return *m_Ptr;
|
||||
}
|
||||
|
||||
T * operator->()
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
iterator & operator++() // preincrement
|
||||
{
|
||||
++m_Ptr;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
iterator operator++(int) // postincrement
|
||||
{
|
||||
iterator tmp = *this;
|
||||
++m_Ptr;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
iterator & operator--() // predecrement
|
||||
{
|
||||
--m_Ptr;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
iterator operator--(int) // postdecrememnt
|
||||
{
|
||||
iterator tmp = *this;
|
||||
--m_Ptr;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(T * right) const
|
||||
{
|
||||
return (m_Ptr == right);
|
||||
}
|
||||
|
||||
bool operator==(const iterator & right) const
|
||||
{
|
||||
return (m_Ptr == right.m_Ptr);
|
||||
}
|
||||
|
||||
bool operator!=(T * right) const
|
||||
{
|
||||
return (m_Ptr != right);
|
||||
}
|
||||
|
||||
bool operator!=(const iterator & right) const
|
||||
{
|
||||
return (m_Ptr != right.m_Ptr);
|
||||
}
|
||||
|
||||
iterator & operator+=(size_t offset)
|
||||
{
|
||||
m_Ptr += offset;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
iterator & operator-=(size_t offset)
|
||||
{
|
||||
m_Ptr -= offset;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
iterator operator+(size_t offset) const
|
||||
{
|
||||
iterator tmp(*this);
|
||||
tmp.m_Ptr += offset;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
iterator operator-(size_t offset) const
|
||||
{
|
||||
iterator tmp(*this);
|
||||
tmp.m_Ptr -= offset;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
T & operator[](size_t offset)
|
||||
{
|
||||
return (*(*this + offset));
|
||||
}
|
||||
|
||||
const T & operator[](size_t offset) const
|
||||
{
|
||||
return (*(*this + offset));
|
||||
}
|
||||
|
||||
bool operator<(const iterator & right) const
|
||||
{
|
||||
return m_Ptr < right.m_Ptr;
|
||||
}
|
||||
|
||||
bool operator>(const iterator & right) const
|
||||
{
|
||||
return m_Ptr > right.m_Ptr;
|
||||
}
|
||||
|
||||
bool operator<=(const iterator & right) const
|
||||
{
|
||||
return m_Ptr <= right.m_Ptr;
|
||||
}
|
||||
|
||||
bool operator>=(const iterator & right) const
|
||||
{
|
||||
return m_Ptr >= right.m_Ptr;
|
||||
}
|
||||
|
||||
size_t operator-(const iterator & right) const
|
||||
{
|
||||
return m_Ptr - right.m_Ptr;
|
||||
}
|
||||
};
|
||||
|
||||
// constructors / destructors
|
||||
CVector<T>()
|
||||
{
|
||||
m_Size = 0;
|
||||
m_CurrentUsedSize = 0;
|
||||
m_Data = NULL;
|
||||
}
|
||||
|
||||
CVector<T>(const CVector<T> & other)
|
||||
{
|
||||
// copy data
|
||||
m_Data = new T [other.m_CurrentUsedSize];
|
||||
m_Size = other.m_CurrentUsedSize;
|
||||
m_CurrentUsedSize = other.m_CurrentUsedSize;
|
||||
for (size_t i=0; i<other.m_CurrentUsedSize; i++)
|
||||
m_Data[i] = other.m_Data[i];
|
||||
}
|
||||
|
||||
~CVector<T>()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
// interface
|
||||
size_t size() const
|
||||
{
|
||||
return m_CurrentUsedSize;
|
||||
}
|
||||
|
||||
size_t capacity() const
|
||||
{
|
||||
return m_Size;
|
||||
}
|
||||
|
||||
iterator begin() const
|
||||
{
|
||||
return iterator(m_Data);
|
||||
}
|
||||
|
||||
iterator end() const
|
||||
{
|
||||
return iterator(m_Data + m_CurrentUsedSize);
|
||||
}
|
||||
|
||||
iterator iterAt(size_t pos)
|
||||
{
|
||||
if (pos > m_CurrentUsedSize)
|
||||
assert(0);
|
||||
return iterator(m_Data + pos);
|
||||
}
|
||||
|
||||
bool reserve(size_t newSize)
|
||||
{
|
||||
if (newSize > m_Size)
|
||||
return ChangeSize(newSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool push_back(const T & elem)
|
||||
{
|
||||
++m_CurrentUsedSize;
|
||||
if (!GrowIfNeeded())
|
||||
{
|
||||
--m_CurrentUsedSize;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Data[m_CurrentUsedSize - 1] = elem;
|
||||
return true;
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
--m_CurrentUsedSize;
|
||||
if (m_CurrentUsedSize < 0)
|
||||
m_CurrentUsedSize = 0;
|
||||
|
||||
FreeMemIfPossible();
|
||||
}
|
||||
|
||||
bool resize(size_t newSize)
|
||||
{
|
||||
if (!ChangeSize(newSize))
|
||||
return false;
|
||||
m_CurrentUsedSize = newSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return (m_CurrentUsedSize == 0);
|
||||
}
|
||||
|
||||
T & at(size_t pos)
|
||||
{
|
||||
if (pos > m_CurrentUsedSize)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return m_Data[pos];
|
||||
}
|
||||
|
||||
const T & at(size_t pos) const
|
||||
{
|
||||
if (pos > m_CurrentUsedSize)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return m_Data[pos];
|
||||
}
|
||||
|
||||
T & operator[](size_t pos)
|
||||
{
|
||||
return at(pos);
|
||||
}
|
||||
|
||||
const T & operator[](size_t pos) const
|
||||
{
|
||||
return at(pos);
|
||||
}
|
||||
|
||||
T & front()
|
||||
{
|
||||
if (m_CurrentUsedSize < 1)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return m_Data[0];
|
||||
}
|
||||
|
||||
const T & front() const
|
||||
{
|
||||
if (m_CurrentUsedSize < 1)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return m_Data[0];
|
||||
}
|
||||
|
||||
T & back()
|
||||
{
|
||||
if (m_CurrentUsedSize < 1)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return m_Data[m_CurrentUsedSize - 1];
|
||||
}
|
||||
|
||||
const T & back() const
|
||||
{
|
||||
if (m_CurrentUsedSize < 1)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return m_Data[m_CurrentUsedSize - 1];
|
||||
}
|
||||
|
||||
iterator insert(iterator where, const T & value)
|
||||
{
|
||||
// validate iter
|
||||
if (where < m_Data || where > (m_Data + m_CurrentUsedSize))
|
||||
return iterator(0);
|
||||
|
||||
size_t ofs = where - begin();
|
||||
|
||||
++m_CurrentUsedSize;
|
||||
if (!GrowIfNeeded())
|
||||
{
|
||||
--m_CurrentUsedSize;
|
||||
return false;
|
||||
}
|
||||
|
||||
where = begin() + ofs;
|
||||
|
||||
// Move subsequent entries
|
||||
for (T *ptr = m_Data + m_CurrentUsedSize - 2; ptr >= where.base(); --ptr)
|
||||
*(ptr + 1) = *ptr;
|
||||
|
||||
*where.base() = value;
|
||||
|
||||
return where;
|
||||
}
|
||||
|
||||
iterator erase(iterator where)
|
||||
{
|
||||
// validate iter
|
||||
if (where < m_Data || where >= (m_Data + m_CurrentUsedSize))
|
||||
return iterator(0);
|
||||
|
||||
size_t ofs = where - begin();
|
||||
|
||||
if (m_CurrentUsedSize > 1)
|
||||
{
|
||||
// move
|
||||
T *theend = m_Data + m_CurrentUsedSize;
|
||||
for (T *ptr = where.base() + 1; ptr < theend; ++ptr)
|
||||
*(ptr - 1) = *ptr;
|
||||
}
|
||||
|
||||
--m_CurrentUsedSize;
|
||||
|
||||
FreeMemIfPossible();
|
||||
|
||||
return begin() + ofs;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_Size = 0;
|
||||
m_CurrentUsedSize = 0;
|
||||
if (m_Data)
|
||||
{
|
||||
delete [] m_Data;
|
||||
m_Data = NULL;
|
||||
}
|
||||
}
|
||||
};
|
||||
}; //namespace SourceHook
|
||||
|
||||
#endif // __CVECTOR_H__
|
||||
|
|
@ -1,844 +0,0 @@
|
|||
/* ======== SourceHook ========
|
||||
* Copyright (C) 2004-2005 Metamod:Source Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): Pavol "PM OnoTo" Marko
|
||||
* Contributors: Scott "Damaged Soul" Ehlert
|
||||
* ============================
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sourcehook.cpp
|
||||
* @brief Contains the implementation of the SourceHook API
|
||||
*/
|
||||
|
||||
#if defined __GNUC__
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "sourcehook_impl.h"
|
||||
#include "sh_memory.h"
|
||||
|
||||
namespace SourceHook
|
||||
{
|
||||
template<>
|
||||
int HashFunction<int>(const int & k)
|
||||
{
|
||||
return k;
|
||||
}
|
||||
|
||||
template<>
|
||||
int Compare<int>(const int & k1, const int & k2)
|
||||
{
|
||||
if (k1 == k2)
|
||||
return 0;
|
||||
if (k1 > k2)
|
||||
return 1;
|
||||
if (k1 < k2)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
CSourceHookImpl::CSourceHookImpl()
|
||||
{
|
||||
}
|
||||
CSourceHookImpl::~CSourceHookImpl()
|
||||
{
|
||||
}
|
||||
|
||||
int CSourceHookImpl::GetIfaceVersion()
|
||||
{
|
||||
return SH_IFACE_VERSION;
|
||||
}
|
||||
|
||||
int CSourceHookImpl::GetImplVersion()
|
||||
{
|
||||
return SH_IMPL_VERSION;
|
||||
}
|
||||
|
||||
bool CSourceHookImpl::IsPluginInUse(Plugin plug)
|
||||
{
|
||||
// Iterate through all hook managers which are in this plugin
|
||||
// Iterate through their vfnptrs, ifaces, hooks
|
||||
// If a hook from an other plugin is found, return true
|
||||
// Return false otherwise
|
||||
#define TMP_CHECK_LIST(name) \
|
||||
for (hook_iter = iface_iter->name.m_List.begin(); hook_iter != iface_iter->name.m_List.end(); ++hook_iter) \
|
||||
if (hook_iter->plug == plug) \
|
||||
return true;
|
||||
|
||||
for (HookManInfoList::iterator hmil_iter = m_HookMans.begin(); hmil_iter != m_HookMans.end(); ++hmil_iter)
|
||||
{
|
||||
if (hmil_iter->m_Plug != plug)
|
||||
continue;
|
||||
for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hmil_iter->m_VfnPtrs.begin();
|
||||
vfnptr_iter != hmil_iter->m_VfnPtrs.end(); ++vfnptr_iter)
|
||||
{
|
||||
for (CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.begin();
|
||||
iface_iter != vfnptr_iter->m_Ifaces.end(); ++iface_iter)
|
||||
{
|
||||
List<HookInfo>::iterator hook_iter;
|
||||
TMP_CHECK_LIST(m_PreHooks);
|
||||
TMP_CHECK_LIST(m_PostHooks);
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef TMP_CHECK_LIST
|
||||
return false;
|
||||
}
|
||||
|
||||
void CSourceHookImpl::UnloadPlugin(Plugin plug)
|
||||
{
|
||||
// 1) Manually remove all hooks by this plugin
|
||||
List<RemoveHookInfo> hookstoremove;
|
||||
HookManInfoList::iterator hmil_iter;
|
||||
|
||||
#define TMP_CHECK_LIST(name, ispost) \
|
||||
for (hook_iter = iface_iter->name.m_List.begin(); hook_iter != iface_iter->name.m_List.end(); ++hook_iter) \
|
||||
if (hook_iter->plug == plug) \
|
||||
hookstoremove.push_back(RemoveHookInfo(hook_iter->plug, iface_iter->m_Ptr, \
|
||||
hook_iter->thisptr_offs, hmil_iter->m_Func, hook_iter->handler, ispost))
|
||||
|
||||
for (hmil_iter = m_HookMans.begin(); hmil_iter != m_HookMans.end(); ++hmil_iter)
|
||||
{
|
||||
for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hmil_iter->m_VfnPtrs.begin();
|
||||
vfnptr_iter != hmil_iter->m_VfnPtrs.end(); ++vfnptr_iter)
|
||||
{
|
||||
for (CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.begin();
|
||||
iface_iter != vfnptr_iter->m_Ifaces.end(); ++iface_iter)
|
||||
{
|
||||
List<HookInfo>::iterator hook_iter;
|
||||
TMP_CHECK_LIST(m_PreHooks, false);
|
||||
TMP_CHECK_LIST(m_PostHooks, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef TMP_CHECK_LIST
|
||||
|
||||
for (List<RemoveHookInfo>::iterator rmiter = hookstoremove.begin(); rmiter != hookstoremove.end(); ++rmiter)
|
||||
RemoveHook(*rmiter);
|
||||
|
||||
// 2) Other plugins may use hook managers in this plugin.
|
||||
// Get a list of hook managers that are in this plugin and are used by other plugins
|
||||
// Delete all hook managers that are in this plugin
|
||||
|
||||
HookManInfoList tmphookmans;
|
||||
bool erase = false;
|
||||
for (hmil_iter = m_HookMans.begin(); hmil_iter != m_HookMans.end();
|
||||
erase ? hmil_iter=m_HookMans.erase(hmil_iter) : ++hmil_iter)
|
||||
{
|
||||
if (hmil_iter->m_Plug == plug)
|
||||
{
|
||||
if (!hmil_iter->m_VfnPtrs.empty())
|
||||
{
|
||||
// All hooks by this plugin are already removed
|
||||
// So if there is a vfnptr, it has to be used by an other plugin
|
||||
tmphookmans.push_back(*hmil_iter);
|
||||
}
|
||||
erase = true;
|
||||
}
|
||||
else
|
||||
erase = false;
|
||||
}
|
||||
|
||||
// For each hook manager that is used in an other plugin:
|
||||
for (hmil_iter = tmphookmans.begin(); hmil_iter != tmphookmans.end(); ++hmil_iter)
|
||||
{
|
||||
// Find a suitable hook manager in an other plugin
|
||||
HookManInfoList::iterator newHookMan = FindHookMan(m_HookMans.begin(), m_HookMans.end(),
|
||||
hmil_iter->m_Proto, hmil_iter->m_VtblOffs, hmil_iter->m_VtblIdx);
|
||||
|
||||
// This should _never_ happen.
|
||||
// If there is a hook from an other plugin, the plugin must have provided a hook manager as well.
|
||||
SH_ASSERT(newHookMan != m_HookMans.end(),
|
||||
("Could not find a suitable hook manager in an other plugin!"));
|
||||
|
||||
// AddHook should make sure that every plugin only has _one_ hook manager for _one_ proto/vi/vo
|
||||
SH_ASSERT(newHookMan->m_Plug != plug, ("New hook manager from same plugin!"));
|
||||
|
||||
// The first hook manager should be always used - so the new hook manager has to be empty
|
||||
SH_ASSERT(newHookMan->m_VfnPtrs.empty(), ("New hook manager not empty!"));
|
||||
|
||||
// Move the vfnptrs from the old hook manager to the new one
|
||||
newHookMan->m_VfnPtrs = hmil_iter->m_VfnPtrs;
|
||||
|
||||
// Unregister the old one, register the new one
|
||||
hmil_iter->m_Func(HA_Unregister, NULL);
|
||||
newHookMan->m_Func(HA_Register, &(*newHookMan));
|
||||
|
||||
// zOMG BAIL, here is part of what you wanted:
|
||||
|
||||
// Go through all vfnptrs in this hookman and patch them to point to the new manager's handler!
|
||||
// or whatever
|
||||
for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = newHookMan->m_VfnPtrs.begin();
|
||||
vfnptr_iter != newHookMan->m_VfnPtrs.end(); ++vfnptr_iter)
|
||||
{
|
||||
// And DEREFERENCE newHookMan->m_HookfuncVfnptr!
|
||||
// otherwise it will be executing the vtable... had to find out the hard way
|
||||
*reinterpret_cast<void**>(vfnptr_iter->m_Ptr) = *reinterpret_cast<void**>(newHookMan->m_HookfuncVfnptr);
|
||||
}
|
||||
|
||||
// That should fix it, bail!
|
||||
}
|
||||
}
|
||||
|
||||
void CSourceHookImpl::CompleteShutdown()
|
||||
{
|
||||
List<RemoveHookInfo> hookstoremove;
|
||||
#define TMP_CHECK_LIST(name, ispost) \
|
||||
for (hook_iter = iface_iter->name.m_List.begin(); hook_iter != iface_iter->name.m_List.end(); ++hook_iter) \
|
||||
hookstoremove.push_back(RemoveHookInfo(hook_iter->plug, iface_iter->m_Ptr, \
|
||||
hook_iter->thisptr_offs, hmil_iter->m_Func, hook_iter->handler, ispost))
|
||||
for (HookManInfoList::iterator hmil_iter = m_HookMans.begin(); hmil_iter != m_HookMans.end(); ++hmil_iter)
|
||||
{
|
||||
for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hmil_iter->m_VfnPtrs.begin();
|
||||
vfnptr_iter != hmil_iter->m_VfnPtrs.end(); ++vfnptr_iter)
|
||||
{
|
||||
for (CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.begin();
|
||||
iface_iter != vfnptr_iter->m_Ifaces.end(); ++iface_iter)
|
||||
{
|
||||
List<HookInfo>::iterator hook_iter;
|
||||
TMP_CHECK_LIST(m_PreHooks, false);
|
||||
TMP_CHECK_LIST(m_PostHooks, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef TMP_CHECK_LIST
|
||||
|
||||
for (List<RemoveHookInfo>::iterator rmiter = hookstoremove.begin(); rmiter != hookstoremove.end(); ++rmiter)
|
||||
RemoveHook(*rmiter);
|
||||
|
||||
m_HookMans.clear();
|
||||
}
|
||||
|
||||
bool CSourceHookImpl::AddHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post)
|
||||
{
|
||||
void *adjustediface = reinterpret_cast<void*>(reinterpret_cast<char*>(iface) + thisptr_offs);
|
||||
// 1) Get info about the hook manager
|
||||
CHookManagerInfo tmp;
|
||||
if (myHookMan(HA_GetInfo, &tmp) != 0)
|
||||
return false;
|
||||
|
||||
// Add the proposed hook manager to the _end_ of the list if the plugin doesn't have a hook manager
|
||||
// with this proto/vo/vi registered
|
||||
HookManInfoList::iterator hkmi_iter;
|
||||
for (hkmi_iter = m_HookMans.begin(); hkmi_iter != m_HookMans.end(); ++hkmi_iter)
|
||||
{
|
||||
if (hkmi_iter->m_Plug == plug && strcmp(hkmi_iter->m_Proto, tmp.m_Proto) == 0 &&
|
||||
hkmi_iter->m_VtblOffs == tmp.m_VtblOffs && hkmi_iter->m_VtblIdx == tmp.m_VtblIdx)
|
||||
break;
|
||||
}
|
||||
if (hkmi_iter == m_HookMans.end())
|
||||
{
|
||||
// No such hook manager from this plugin yet, add it!
|
||||
tmp.m_Func = myHookMan;
|
||||
tmp.m_Plug = plug;
|
||||
m_HookMans.push_back(tmp);
|
||||
}
|
||||
|
||||
// Then, search for a suitable hook manager (from the beginning)
|
||||
HookManInfoList::iterator hookman = FindHookMan(m_HookMans.begin(), m_HookMans.end(), tmp.m_Proto,
|
||||
tmp.m_VtblOffs, tmp.m_VtblIdx);
|
||||
SH_ASSERT(hookman != m_HookMans.end(), ("No hookman found - but if there was none, we've just added one!"));
|
||||
|
||||
// Tell it to store the pointer if it's not already active
|
||||
if (hookman->m_VfnPtrs.empty())
|
||||
hookman->m_Func(HA_Register, &(*hookman));
|
||||
|
||||
void **cur_vtptr = *reinterpret_cast<void***>(
|
||||
reinterpret_cast<char*>(adjustediface) + tmp.m_VtblOffs);
|
||||
void *cur_vfnptr = reinterpret_cast<void*>(cur_vtptr + tmp.m_VtblIdx);
|
||||
|
||||
CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->m_VfnPtrs.find(cur_vfnptr);
|
||||
|
||||
if (vfnptr_iter == hookman->m_VfnPtrs.end())
|
||||
{
|
||||
// Add a new one
|
||||
CVfnPtr vfp(cur_vfnptr);
|
||||
|
||||
// Alter vtable entry
|
||||
if (!SetMemAccess(cur_vtptr, sizeof(void*) * (tmp.m_VtblIdx + 1), SH_MEM_READ | SH_MEM_WRITE))
|
||||
return false;
|
||||
|
||||
*reinterpret_cast<void**>(cur_vfnptr) = *reinterpret_cast<void**>(hookman->m_HookfuncVfnptr);
|
||||
|
||||
hookman->m_VfnPtrs.push_back(vfp);
|
||||
|
||||
// Make vfnptr_iter point to the new element
|
||||
vfnptr_iter = hookman->m_VfnPtrs.end();
|
||||
--vfnptr_iter;
|
||||
|
||||
// Now that it is done, check whether we have to update any callclasses
|
||||
ApplyCallClassPatches(adjustediface, tmp.m_VtblOffs, tmp.m_VtblIdx, vfp.m_OrigEntry);
|
||||
}
|
||||
|
||||
CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.find(adjustediface);
|
||||
if (iface_iter == vfnptr_iter->m_Ifaces.end())
|
||||
{
|
||||
// Add a new one
|
||||
vfnptr_iter->m_Ifaces.push_back(CIface(adjustediface));
|
||||
|
||||
// Make iface_iter point to the new element
|
||||
iface_iter = vfnptr_iter->m_Ifaces.end();
|
||||
--iface_iter;
|
||||
}
|
||||
|
||||
// Add the hook
|
||||
HookInfo hookinfo;
|
||||
hookinfo.handler = handler;
|
||||
hookinfo.plug = plug;
|
||||
hookinfo.paused = false;
|
||||
hookinfo.thisptr_offs = thisptr_offs;
|
||||
if (post)
|
||||
iface_iter->m_PostHooks.m_List.push_back(hookinfo);
|
||||
else
|
||||
iface_iter->m_PreHooks.m_List.push_back(hookinfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSourceHookImpl::RemoveHook(RemoveHookInfo info)
|
||||
{
|
||||
return RemoveHook(info.plug, info.iface, info.thisptr_offs, info.hookman, info.handler, info.post);
|
||||
}
|
||||
|
||||
bool CSourceHookImpl::RemoveHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post)
|
||||
{
|
||||
void *adjustediface = reinterpret_cast<void*>(reinterpret_cast<char*>(iface)+thisptr_offs);
|
||||
CHookManagerInfo tmp;
|
||||
if (myHookMan(HA_GetInfo, &tmp) != 0)
|
||||
return false;
|
||||
|
||||
// Find the hook manager and the hook
|
||||
HookManInfoList::iterator hookman = FindHookMan(m_HookMans.begin(), m_HookMans.end(),
|
||||
tmp.m_Proto, tmp.m_VtblOffs, tmp.m_VtblIdx);
|
||||
if (hookman == m_HookMans.end())
|
||||
return false;
|
||||
|
||||
if (!ModuleInMemory(reinterpret_cast<char*>(adjustediface) + tmp.m_VtblOffs,
|
||||
sizeof(void*) * (tmp.m_VtblIdx + 1)))
|
||||
{
|
||||
// The module the vtable was in is already unloaded.
|
||||
hookman->m_VfnPtrs.clear();
|
||||
hookman->m_Func(HA_Unregister, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
void **cur_vtptr = *reinterpret_cast<void***>(
|
||||
reinterpret_cast<char*>(adjustediface) + tmp.m_VtblOffs);
|
||||
void *cur_vfnptr = reinterpret_cast<void*>(cur_vtptr + tmp.m_VtblIdx);
|
||||
|
||||
CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->m_VfnPtrs.find(cur_vfnptr);
|
||||
|
||||
if (vfnptr_iter == hookman->m_VfnPtrs.end())
|
||||
return false;
|
||||
|
||||
for (CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.begin();
|
||||
iface_iter != vfnptr_iter->m_Ifaces.end();)
|
||||
{
|
||||
List<HookInfo> &hooks =
|
||||
post ? iface_iter->m_PostHooks.m_List : iface_iter->m_PreHooks.m_List;
|
||||
|
||||
bool erase;
|
||||
for (List<HookInfo>::iterator hookiter = hooks.begin();
|
||||
hookiter != hooks.end(); )
|
||||
{
|
||||
erase = hookiter->plug == plug && hookiter->handler->IsEqual(handler) &&
|
||||
hookiter->thisptr_offs == thisptr_offs;
|
||||
if (erase)
|
||||
{
|
||||
hookiter->handler->DeleteThis(); // Make the _plugin_ delete the handler object
|
||||
|
||||
// Move all iterators pointing at this
|
||||
List<HookInfo>::iterator oldhookiter = hookiter;
|
||||
hookiter = hooks.erase(hookiter);
|
||||
List<HookInfo>::iterator newhookiter = hookiter;
|
||||
--newhookiter; // The hook loop will ++ it then
|
||||
CHookList::CIter *pItIter;
|
||||
for (pItIter = iface_iter->m_PreHooks.m_UsedIters; pItIter; pItIter = pItIter->m_pNext)
|
||||
if (pItIter->m_Iter == oldhookiter)
|
||||
pItIter->m_Iter = newhookiter;
|
||||
}
|
||||
else
|
||||
++hookiter;
|
||||
}
|
||||
if (iface_iter->m_PostHooks.m_List.empty() && iface_iter->m_PreHooks.m_List.empty())
|
||||
{
|
||||
// There are no hooks on this iface anymore...
|
||||
for (HookLoopInfoStack::iterator hli_iter = m_HLIStack.begin();
|
||||
hli_iter != m_HLIStack.end(); ++hli_iter)
|
||||
{
|
||||
if (hli_iter->pCurIface == static_cast<IIface*>(&(*iface_iter)))
|
||||
hli_iter->shouldContinue = false;
|
||||
}
|
||||
|
||||
iface_iter = vfnptr_iter->m_Ifaces.erase(iface_iter);
|
||||
if (vfnptr_iter->m_Ifaces.empty())
|
||||
{
|
||||
// No ifaces at all -> Deactivate the hook
|
||||
*reinterpret_cast<void**>(vfnptr_iter->m_Ptr) = vfnptr_iter->m_OrigEntry;
|
||||
|
||||
hookman->m_VfnPtrs.erase(vfnptr_iter);
|
||||
|
||||
// Remove callclass patch
|
||||
for (Impl_CallClassList::iterator cciter = m_CallClasses.begin(); cciter != m_CallClasses.end(); ++cciter)
|
||||
if (cciter->m_Ptr == adjustediface)
|
||||
cciter->RemoveCallClassPatch(tmp.m_VtblOffs, tmp.m_VtblIdx);
|
||||
|
||||
if (hookman->m_VfnPtrs.empty())
|
||||
{
|
||||
// Unregister the hook manager
|
||||
hookman->m_Func(HA_Unregister, NULL);
|
||||
}
|
||||
|
||||
// Don't try to continue looping through ifaces
|
||||
// - the list is already invalid
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
++iface_iter;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
GenericCallClass *CSourceHookImpl::GetCallClass(void *iface, size_t size)
|
||||
{
|
||||
for (Impl_CallClassList::iterator cciter = m_CallClasses.begin(); cciter != m_CallClasses.end(); ++cciter)
|
||||
{
|
||||
if (cciter->m_Ptr == iface && cciter->m_ObjSize == size)
|
||||
{
|
||||
++cciter->m_RefCounter;
|
||||
return &(*cciter);
|
||||
}
|
||||
}
|
||||
|
||||
// Make a new one
|
||||
|
||||
CCallClassImpl tmp(iface, size);
|
||||
ApplyCallClassPatches(tmp);
|
||||
m_CallClasses.push_back(tmp);
|
||||
return &m_CallClasses.back();
|
||||
}
|
||||
|
||||
void CSourceHookImpl::ReleaseCallClass(GenericCallClass *ptr)
|
||||
{
|
||||
Impl_CallClassList::iterator iter = m_CallClasses.find(ptr);
|
||||
if (iter == m_CallClasses.end())
|
||||
return;
|
||||
--iter->m_RefCounter;
|
||||
if (iter->m_RefCounter < 1)
|
||||
m_CallClasses.erase(iter);
|
||||
}
|
||||
|
||||
void CSourceHookImpl::ApplyCallClassPatches(CCallClassImpl &cc)
|
||||
{
|
||||
for (HookManInfoList::iterator hookman = m_HookMans.begin(); hookman != m_HookMans.end(); ++hookman)
|
||||
{
|
||||
for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookman->m_VfnPtrs.begin();
|
||||
vfnptr_iter != hookman->m_VfnPtrs.end(); ++vfnptr_iter)
|
||||
{
|
||||
for (CVfnPtr::IfaceListIter iface_iter = vfnptr_iter->m_Ifaces.begin();
|
||||
iface_iter != vfnptr_iter->m_Ifaces.end(); ++iface_iter)
|
||||
{
|
||||
if (iface_iter->m_Ptr >= cc.m_Ptr &&
|
||||
iface_iter->m_Ptr < (reinterpret_cast<char*>(cc.m_Ptr) + cc.m_ObjSize))
|
||||
{
|
||||
cc.ApplyCallClassPatch(static_cast<int>(reinterpret_cast<char*>(iface_iter->m_Ptr) -
|
||||
reinterpret_cast<char*>(cc.m_Ptr)) + hookman->m_VtblOffs,
|
||||
hookman->m_VtblIdx, vfnptr_iter->m_OrigEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSourceHookImpl::ApplyCallClassPatches(void *ifaceptr, int vtbl_offs, int vtbl_idx, void *orig_entry)
|
||||
{
|
||||
for (Impl_CallClassList::iterator cc_iter = m_CallClasses.begin(); cc_iter != m_CallClasses.end();
|
||||
++cc_iter)
|
||||
{
|
||||
if (ifaceptr >= cc_iter->m_Ptr &&
|
||||
ifaceptr < (reinterpret_cast<char*>(cc_iter->m_Ptr) + cc_iter->m_ObjSize))
|
||||
{
|
||||
cc_iter->ApplyCallClassPatch(static_cast<int>(reinterpret_cast<char*>(ifaceptr) -
|
||||
reinterpret_cast<char*>(cc_iter->m_Ptr)) + vtbl_offs, vtbl_idx, orig_entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSourceHookImpl::RemoveCallClassPatches(void *ifaceptr, int vtbl_offs, int vtbl_idx)
|
||||
{
|
||||
for (Impl_CallClassList::iterator cc_iter = m_CallClasses.begin(); cc_iter != m_CallClasses.end();
|
||||
++cc_iter)
|
||||
{
|
||||
if (ifaceptr >= cc_iter->m_Ptr &&
|
||||
ifaceptr < (reinterpret_cast<char*>(cc_iter->m_Ptr) + cc_iter->m_ObjSize))
|
||||
{
|
||||
cc_iter->RemoveCallClassPatch(vtbl_offs, vtbl_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CSourceHookImpl::HookManInfoList::iterator CSourceHookImpl::FindHookMan(HookManInfoList::iterator begin,
|
||||
HookManInfoList::iterator end, const char *proto, int vtblofs, int vtblidx)
|
||||
{
|
||||
HookManInfoList::iterator hookmaniter;
|
||||
for (hookmaniter = m_HookMans.begin(); hookmaniter != m_HookMans.end(); ++hookmaniter)
|
||||
{
|
||||
if (strcmp(hookmaniter->m_Proto, proto) == 0 && hookmaniter->m_VtblOffs == vtblofs &&
|
||||
hookmaniter->m_VtblIdx == vtblidx)
|
||||
break;
|
||||
}
|
||||
return hookmaniter;
|
||||
}
|
||||
|
||||
void CSourceHookImpl::SetPluginPaused(Plugin plug, bool paused)
|
||||
{
|
||||
// Go through all hook managers, all interfaces, and set the status of all hooks of this plugin to paused
|
||||
for (HookManInfoList::iterator hookmaniter = m_HookMans.begin(); hookmaniter != m_HookMans.end(); ++hookmaniter)
|
||||
for (CHookManagerInfo::VfnPtrListIter vfnptr_iter = hookmaniter->m_VfnPtrs.begin();
|
||||
vfnptr_iter != hookmaniter->m_VfnPtrs.end(); ++vfnptr_iter)
|
||||
for (CVfnPtr::IfaceListIter ifaceiter = vfnptr_iter->m_Ifaces.begin();
|
||||
ifaceiter != vfnptr_iter->m_Ifaces.end(); ++ifaceiter)
|
||||
{
|
||||
for (List<HookInfo>::iterator hookiter = ifaceiter->m_PreHooks.m_List.begin();
|
||||
hookiter != ifaceiter->m_PreHooks.m_List.end(); ++hookiter)
|
||||
if (plug == hookiter->plug)
|
||||
hookiter->paused = paused;
|
||||
|
||||
for (List<HookInfo>::iterator hookiter = ifaceiter->m_PostHooks.m_List.begin();
|
||||
hookiter != ifaceiter->m_PostHooks.m_List.end(); ++hookiter)
|
||||
if (plug == hookiter->plug)
|
||||
hookiter->paused = paused;
|
||||
}
|
||||
}
|
||||
void CSourceHookImpl::PausePlugin(Plugin plug)
|
||||
{
|
||||
SetPluginPaused(plug, true);
|
||||
}
|
||||
|
||||
void CSourceHookImpl::UnpausePlugin(Plugin plug)
|
||||
{
|
||||
SetPluginPaused(plug, false);
|
||||
}
|
||||
|
||||
void CSourceHookImpl::HookLoopBegin(IIface *pIface)
|
||||
{
|
||||
HookLoopInfo hli;
|
||||
hli.pCurIface = pIface;
|
||||
hli.shouldContinue = true;
|
||||
m_HLIStack.push(hli);
|
||||
}
|
||||
|
||||
void CSourceHookImpl::HookLoopEnd()
|
||||
{
|
||||
m_HLIStack.pop();
|
||||
}
|
||||
|
||||
void CSourceHookImpl::SetRes(META_RES res)
|
||||
{
|
||||
*m_HLIStack.front().pCurRes = res;
|
||||
}
|
||||
|
||||
META_RES CSourceHookImpl::GetPrevRes()
|
||||
{
|
||||
return *m_HLIStack.front().pPrevRes;
|
||||
}
|
||||
|
||||
META_RES CSourceHookImpl::GetStatus()
|
||||
{
|
||||
return *m_HLIStack.front().pStatus;
|
||||
}
|
||||
|
||||
const void *CSourceHookImpl::GetOrigRet()
|
||||
{
|
||||
return m_HLIStack.front().pOrigRet;
|
||||
}
|
||||
|
||||
const void *CSourceHookImpl::GetOverrideRet()
|
||||
{
|
||||
return m_HLIStack.front().pOverrideRet;
|
||||
}
|
||||
|
||||
void *CSourceHookImpl::GetIfacePtr()
|
||||
{
|
||||
return *m_HLIStack.front().pIfacePtrPtr;
|
||||
}
|
||||
|
||||
void CSourceHookImpl::SetCurResPtr(META_RES *mres)
|
||||
{
|
||||
m_HLIStack.front().pCurRes = mres;
|
||||
}
|
||||
|
||||
void CSourceHookImpl::SetPrevResPtr(META_RES *mres)
|
||||
{
|
||||
m_HLIStack.front().pPrevRes = mres;
|
||||
}
|
||||
|
||||
void CSourceHookImpl::SetStatusPtr(META_RES *mres)
|
||||
{
|
||||
m_HLIStack.front().pStatus = mres;
|
||||
}
|
||||
|
||||
void CSourceHookImpl::SetIfacePtrPtr(void **pp)
|
||||
{
|
||||
m_HLIStack.front().pIfacePtrPtr = pp;
|
||||
}
|
||||
|
||||
void CSourceHookImpl::SetOrigRetPtr(const void *ptr)
|
||||
{
|
||||
m_HLIStack.front().pOrigRet = ptr;
|
||||
}
|
||||
void CSourceHookImpl::SetOverrideRetPtr(const void *ptr)
|
||||
{
|
||||
m_HLIStack.front().pOverrideRet = ptr;
|
||||
}
|
||||
bool CSourceHookImpl::ShouldContinue()
|
||||
{
|
||||
return m_HLIStack.front().shouldContinue;
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
// CCallClassImpl
|
||||
////////////////////////////
|
||||
CSourceHookImpl::CCallClassImpl::CCallClassImpl(void *ptr, size_t size)
|
||||
: m_Ptr(ptr), m_ObjSize(size), m_RefCounter(1)
|
||||
{
|
||||
}
|
||||
CSourceHookImpl::CCallClassImpl::~CCallClassImpl()
|
||||
{
|
||||
}
|
||||
|
||||
void *CSourceHookImpl::CCallClassImpl::GetThisPtr()
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
void *CSourceHookImpl::CCallClassImpl::GetOrigFunc(int vtbloffs, int vtblidx)
|
||||
{
|
||||
OrigVTables::iterator iter = m_VT.find(vtbloffs);
|
||||
if (iter != m_VT.end() && iter->val.size() > (size_t)vtblidx)
|
||||
{
|
||||
return iter->val[vtblidx];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CSourceHookImpl::CCallClassImpl::ApplyCallClassPatch(int vtbl_offs, int vtbl_idx, void *orig_entry)
|
||||
{
|
||||
OrigFuncs &tmpvec = m_VT[vtbl_offs];
|
||||
if (tmpvec.size() <= (size_t)vtbl_idx)
|
||||
tmpvec.resize(vtbl_idx+1);
|
||||
tmpvec[vtbl_idx] = orig_entry;
|
||||
}
|
||||
void CSourceHookImpl::CCallClassImpl::RemoveCallClassPatch(int vtbl_offs, int vtbl_idx)
|
||||
{
|
||||
OrigVTables::iterator iter = m_VT.find(vtbl_offs);
|
||||
if (iter != m_VT.end())
|
||||
{
|
||||
if (iter->val.size() > (size_t)vtbl_idx)
|
||||
{
|
||||
iter->val[vtbl_idx] = 0;
|
||||
|
||||
OrigFuncs &of = iter->val;
|
||||
OrigFuncs::iterator lastused = of.end();
|
||||
for (OrigFuncs::iterator viter = of.begin(); viter != of.end(); ++viter)
|
||||
{
|
||||
if (*viter)
|
||||
lastused = viter;
|
||||
}
|
||||
if (lastused == of.end())
|
||||
{
|
||||
// No used element => Remove the whole vector
|
||||
m_VT.erase(iter);
|
||||
return;
|
||||
}
|
||||
of.resize(lastused - of.begin() + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
// CHookManagerInfo
|
||||
////////////////////////////
|
||||
CSourceHookImpl::CHookManagerInfo::~CHookManagerInfo()
|
||||
{
|
||||
}
|
||||
|
||||
IVfnPtr *CSourceHookImpl::CHookManagerInfo::FindVfnPtr(void *vfnptr)
|
||||
{
|
||||
VfnPtrListIter iter = m_VfnPtrs.find(vfnptr);
|
||||
return iter == m_VfnPtrs.end() ? NULL : &(*iter);
|
||||
}
|
||||
void CSourceHookImpl::CHookManagerInfo::SetInfo(int vtbl_offs, int vtbl_idx, const char *proto)
|
||||
{
|
||||
m_VtblOffs = vtbl_offs;
|
||||
m_VtblIdx = vtbl_idx;
|
||||
m_Proto = proto;
|
||||
}
|
||||
void CSourceHookImpl::CHookManagerInfo::SetHookfuncVfnptr(void *hookfunc_vfnptr)
|
||||
{
|
||||
m_HookfuncVfnptr = hookfunc_vfnptr;
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
// CVfnPtr
|
||||
////////////////////////////
|
||||
|
||||
|
||||
CSourceHookImpl::CVfnPtr::CVfnPtr(void *ptr) : m_Ptr(ptr), m_OrigEntry(*reinterpret_cast<void**>(ptr))
|
||||
{
|
||||
}
|
||||
CSourceHookImpl::CVfnPtr::~CVfnPtr()
|
||||
{
|
||||
}
|
||||
|
||||
void *CSourceHookImpl::CVfnPtr::GetVfnPtr()
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
void *CSourceHookImpl::CVfnPtr::GetOrigEntry()
|
||||
{
|
||||
return m_OrigEntry;
|
||||
}
|
||||
|
||||
IIface *CSourceHookImpl::CVfnPtr::FindIface(void *ptr)
|
||||
{
|
||||
IfaceListIter iter = m_Ifaces.find(ptr);
|
||||
return iter == m_Ifaces.end() ? NULL : &(*iter);
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
// CIface
|
||||
////////////////////////////
|
||||
CSourceHookImpl::CIface::CIface(void *ptr) : m_Ptr(ptr)
|
||||
{
|
||||
}
|
||||
CSourceHookImpl::CIface::~CIface()
|
||||
{
|
||||
}
|
||||
|
||||
void *CSourceHookImpl::CIface::GetPtr()
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
IHookList *CSourceHookImpl::CIface::GetPreHooks()
|
||||
{
|
||||
return &m_PreHooks;
|
||||
}
|
||||
IHookList *CSourceHookImpl::CIface::GetPostHooks()
|
||||
{
|
||||
return &m_PostHooks;
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
// CHookList
|
||||
////////////////////////////
|
||||
|
||||
CSourceHookImpl::CHookList::CHookList() : m_FreeIters(NULL), m_UsedIters(NULL)
|
||||
{
|
||||
}
|
||||
CSourceHookImpl::CHookList::CHookList(const CHookList &other) : m_List(other.m_List), m_FreeIters(NULL), m_UsedIters(NULL)
|
||||
{
|
||||
}
|
||||
CSourceHookImpl::CHookList::~CHookList()
|
||||
{
|
||||
while (m_FreeIters)
|
||||
{
|
||||
CIter *iter = m_FreeIters->m_pNext;
|
||||
delete m_FreeIters;
|
||||
m_FreeIters = iter;
|
||||
}
|
||||
}
|
||||
IHookList::IIter *CSourceHookImpl::CHookList::GetIter()
|
||||
{
|
||||
CIter *ret;
|
||||
if (m_FreeIters)
|
||||
{
|
||||
ret = m_FreeIters;
|
||||
m_FreeIters = ret->m_pNext;
|
||||
ret->GoToBegin();
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = new CIter(this);
|
||||
}
|
||||
|
||||
ret->m_pNext = m_UsedIters;
|
||||
ret->m_pPrev = NULL;
|
||||
if (m_UsedIters)
|
||||
m_UsedIters->m_pPrev = ret;
|
||||
m_UsedIters = ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
void CSourceHookImpl::CHookList::ReleaseIter(IIter *pIter)
|
||||
{
|
||||
CIter *pIter2 = static_cast<CIter*>(pIter);
|
||||
|
||||
// Unlink from m_UsedIters
|
||||
|
||||
if (pIter2->m_pNext)
|
||||
pIter2->m_pNext->m_pPrev = pIter2->m_pPrev;
|
||||
if (pIter2->m_pPrev)
|
||||
pIter2->m_pPrev->m_pNext = pIter2->m_pNext;
|
||||
if (pIter2 == m_UsedIters)
|
||||
m_UsedIters = NULL;
|
||||
|
||||
// Link to m_FreeIters
|
||||
|
||||
pIter2->m_pNext = m_FreeIters;
|
||||
|
||||
m_FreeIters = pIter2;
|
||||
}
|
||||
|
||||
CSourceHookImpl::CHookList::CIter::CIter(CHookList *pList) : m_pList(pList), m_pNext(NULL)
|
||||
{
|
||||
GoToBegin();
|
||||
}
|
||||
CSourceHookImpl::CHookList::CIter::~CIter()
|
||||
{
|
||||
}
|
||||
|
||||
void CSourceHookImpl::CHookList::CIter::GoToBegin()
|
||||
{
|
||||
m_Iter = m_pList->m_List.begin();
|
||||
SkipPaused();
|
||||
}
|
||||
|
||||
bool CSourceHookImpl::CHookList::CIter::End()
|
||||
{
|
||||
if (!m_pList)
|
||||
return false;
|
||||
return m_Iter == m_pList->m_List.end();
|
||||
}
|
||||
void CSourceHookImpl::CHookList::CIter::Next()
|
||||
{
|
||||
if (!m_pList)
|
||||
return;
|
||||
++m_Iter;
|
||||
SkipPaused();
|
||||
}
|
||||
void CSourceHookImpl::CHookList::CIter::Clear()
|
||||
{
|
||||
m_pList = NULL;
|
||||
}
|
||||
void CSourceHookImpl::CHookList::CIter::SkipPaused()
|
||||
{
|
||||
while (m_Iter != m_pList->m_List.end() && m_Iter->paused)
|
||||
++m_Iter;
|
||||
}
|
||||
|
||||
ISHDelegate *CSourceHookImpl::CHookList::CIter::Handler()
|
||||
{
|
||||
return m_Iter->handler;
|
||||
}
|
||||
int CSourceHookImpl::CHookList::CIter::ThisPtrOffs()
|
||||
{
|
||||
return m_Iter->thisptr_offs;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,372 +0,0 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* PROJECT: The Dark Mod
|
||||
* $Revision: 1435 $
|
||||
* $Date: 2007-10-16 22:23:28 +0530 (Tue, 16 Oct 2007) $
|
||||
* $Author: greebo $
|
||||
*
|
||||
***************************************************************************/
|
||||
/* ======== SourceHook ========
|
||||
* Copyright (C) 2004-2005 Metamod:Source Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): Pavol "PM OnoTo" Marko
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#ifndef __SOURCEHOOK_IMPL_H__
|
||||
#define __SOURCEHOOK_IMPL_H__
|
||||
|
||||
#include "sourcehook.h"
|
||||
#include "sh_list.h"
|
||||
#include "sh_vector.h"
|
||||
#include "sh_tinyhash.h"
|
||||
#include "sh_stack.h"
|
||||
|
||||
namespace SourceHook
|
||||
{
|
||||
/**
|
||||
* @brief The SourceHook implementation class
|
||||
*/
|
||||
class CSourceHookImpl : public ISourceHook
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* @brief A hook can be removed if you have this information
|
||||
*/
|
||||
struct RemoveHookInfo
|
||||
{
|
||||
RemoveHookInfo(Plugin pplug, void *piface, int tpo, HookManagerPubFunc phookman,
|
||||
ISHDelegate *phandler, bool ppost)
|
||||
: plug(pplug), iface(piface), thisptr_offs(tpo),
|
||||
hookman(phookman), handler(phandler), post(ppost)
|
||||
{
|
||||
}
|
||||
|
||||
Plugin plug;
|
||||
void *iface;
|
||||
int thisptr_offs;
|
||||
HookManagerPubFunc hookman;
|
||||
ISHDelegate *handler;
|
||||
bool post;
|
||||
};
|
||||
|
||||
struct HookInfo
|
||||
{
|
||||
ISHDelegate *handler; //!< Pointer to the handler
|
||||
bool paused; //!< If true, the hook should not be executed
|
||||
Plugin plug; //!< The owner plugin
|
||||
int thisptr_offs; //!< This pointer offset
|
||||
};
|
||||
|
||||
class CHookList : public IHookList
|
||||
{
|
||||
public:
|
||||
List<HookInfo> m_List;
|
||||
|
||||
friend class CIter;
|
||||
|
||||
class CIter : public IHookList::IIter
|
||||
{
|
||||
friend class CHookList;
|
||||
|
||||
CHookList *m_pList;
|
||||
|
||||
void SkipPaused();
|
||||
public:
|
||||
|
||||
List<HookInfo>::iterator m_Iter;
|
||||
|
||||
CIter(CHookList *pList);
|
||||
|
||||
virtual ~CIter();
|
||||
|
||||
void GoToBegin();
|
||||
|
||||
bool End();
|
||||
void Next();
|
||||
ISHDelegate *Handler();
|
||||
int ThisPtrOffs();
|
||||
|
||||
void Clear();
|
||||
|
||||
CIter *m_pNext; // When stored in m_FreeIters and m_UsedIters
|
||||
CIter *m_pPrev; // Only used when stored in m_UsedIters
|
||||
};
|
||||
|
||||
CIter *m_FreeIters;
|
||||
CIter *m_UsedIters;
|
||||
|
||||
CHookList();
|
||||
CHookList(const CHookList &other);
|
||||
virtual ~CHookList();
|
||||
|
||||
void operator=(const CHookList &other);
|
||||
|
||||
IIter *GetIter();
|
||||
void ReleaseIter(IIter *pIter);
|
||||
};
|
||||
|
||||
// I know, data hiding... But I'm a lazy bastard!
|
||||
|
||||
class CIface : public IIface
|
||||
{
|
||||
public:
|
||||
void *m_Ptr;
|
||||
CHookList m_PreHooks;
|
||||
CHookList m_PostHooks;
|
||||
public:
|
||||
CIface(void *ptr);
|
||||
virtual ~CIface();
|
||||
|
||||
void *GetPtr();
|
||||
IHookList *GetPreHooks();
|
||||
IHookList *GetPostHooks();
|
||||
|
||||
bool operator==(void *ptr)
|
||||
{
|
||||
return m_Ptr == ptr;
|
||||
}
|
||||
};
|
||||
|
||||
class CVfnPtr : public IVfnPtr
|
||||
{
|
||||
public:
|
||||
typedef List<CIface> IfaceList;
|
||||
typedef IfaceList::iterator IfaceListIter;
|
||||
|
||||
void *m_Ptr;
|
||||
void *m_OrigEntry;
|
||||
|
||||
IfaceList m_Ifaces;
|
||||
|
||||
public:
|
||||
CVfnPtr(void *ptr);
|
||||
virtual ~CVfnPtr();
|
||||
|
||||
void *GetVfnPtr();
|
||||
void *GetOrigEntry();
|
||||
|
||||
virtual IIface *FindIface(void *ptr);
|
||||
|
||||
bool operator==(void *ptr)
|
||||
{
|
||||
return m_Ptr == ptr;
|
||||
}
|
||||
};
|
||||
|
||||
class CHookManagerInfo : public IHookManagerInfo
|
||||
{
|
||||
public:
|
||||
typedef List<CVfnPtr> VfnPtrList;
|
||||
typedef VfnPtrList::iterator VfnPtrListIter;
|
||||
|
||||
Plugin m_Plug;
|
||||
HookManagerPubFunc m_Func;
|
||||
|
||||
int m_VtblOffs;
|
||||
int m_VtblIdx;
|
||||
const char *m_Proto;
|
||||
void *m_HookfuncVfnptr;
|
||||
|
||||
VfnPtrList m_VfnPtrs;
|
||||
|
||||
public:
|
||||
virtual ~CHookManagerInfo();
|
||||
|
||||
IVfnPtr *FindVfnPtr(void *vfnptr);
|
||||
|
||||
void SetInfo(int vtbl_offs, int vtbl_idx, const char *proto);
|
||||
void SetHookfuncVfnptr(void *hookfunc_vfnptr);
|
||||
};
|
||||
/**
|
||||
* @brief A list of CHookManagerInfo classes
|
||||
*/
|
||||
typedef List<CHookManagerInfo> HookManInfoList;
|
||||
|
||||
class CCallClassImpl : public GenericCallClass
|
||||
{
|
||||
public:
|
||||
|
||||
typedef SourceHook::CVector<void*> OrigFuncs;
|
||||
typedef SourceHook::THash<int, OrigFuncs> OrigVTables;
|
||||
|
||||
void *m_Ptr; //!< Pointer to the actual object
|
||||
size_t m_ObjSize; //!< Size of the instance
|
||||
OrigVTables m_VT; //!< Info about vtables & functions
|
||||
|
||||
int m_RefCounter;
|
||||
|
||||
CCallClassImpl(void *ptr, size_t size);
|
||||
virtual ~CCallClassImpl();
|
||||
|
||||
bool operator==(void *other)
|
||||
{
|
||||
return m_Ptr == other;
|
||||
}
|
||||
|
||||
void *GetThisPtr();
|
||||
void *GetOrigFunc(int vtbloffs, int vtblidx);
|
||||
|
||||
void ApplyCallClassPatch(int vtbl_offs, int vtbl_idx, void *orig_entry);
|
||||
void RemoveCallClassPatch(int vtbl_offs, int vtbl_idx);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A list of CallClass structures
|
||||
*/
|
||||
typedef List<CCallClassImpl> Impl_CallClassList;
|
||||
|
||||
Impl_CallClassList m_CallClasses; //!< A list of already generated callclasses
|
||||
HookManInfoList m_HookMans; //!< A list of hook managers
|
||||
|
||||
struct HookLoopInfo
|
||||
{
|
||||
META_RES *pStatus;
|
||||
META_RES *pPrevRes;
|
||||
META_RES *pCurRes;
|
||||
|
||||
bool shouldContinue;
|
||||
|
||||
IIface *pCurIface;
|
||||
const void *pOrigRet;
|
||||
const void *pOverrideRet;
|
||||
void **pIfacePtrPtr;
|
||||
};
|
||||
typedef CStack<HookLoopInfo> HookLoopInfoStack;
|
||||
|
||||
/**
|
||||
* @brief Finds a hook manager for a function based on a text-prototype, a vtable offset and a vtable index
|
||||
*/
|
||||
HookManInfoList::iterator FindHookMan(HookManInfoList::iterator begin, HookManInfoList::iterator end,
|
||||
const char *proto, int vtblofs, int vtblidx);
|
||||
|
||||
void ApplyCallClassPatches(CCallClassImpl &cc);
|
||||
void ApplyCallClassPatches(void *ifaceptr, int vtbl_offs, int vtbl_idx, void *orig_entry);
|
||||
void RemoveCallClassPatches(void *ifaceptr, int vtbl_offs, int vtbl_idx);
|
||||
|
||||
void SetPluginPaused(Plugin plug, bool paused);
|
||||
|
||||
HookLoopInfoStack m_HLIStack;
|
||||
public:
|
||||
CSourceHookImpl();
|
||||
virtual ~CSourceHookImpl();
|
||||
|
||||
/**
|
||||
* @brief Returns the interface version
|
||||
*/
|
||||
int GetIfaceVersion();
|
||||
|
||||
/**
|
||||
* @brief Returns the implemnetation version
|
||||
*/
|
||||
int GetImplVersion();
|
||||
|
||||
/**
|
||||
* @brief Make sure that a plugin is not used by any other plugins anymore, and unregister all its hook managers
|
||||
*/
|
||||
void UnloadPlugin(Plugin plug);
|
||||
|
||||
/**
|
||||
* @brief Shut down the whole system, unregister all hook managers
|
||||
*/
|
||||
void CompleteShutdown();
|
||||
|
||||
/**
|
||||
* @brief Add a hook.
|
||||
*
|
||||
* @return True if the function succeeded, false otherwise
|
||||
*
|
||||
* @param plug The unique identifier of the plugin that calls this function
|
||||
* @param iface The interface pointer
|
||||
* @param ifacesize The size of the class iface points to
|
||||
* @param myHookMan A hook manager function that should be capable of handling the function
|
||||
* @param handler A pointer to a FastDelegate containing the hook handler
|
||||
* @param post Set to true if you want a post handler
|
||||
*/
|
||||
bool AddHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post);
|
||||
|
||||
/**
|
||||
* @brief Removes a hook.
|
||||
*
|
||||
* @return True if the function succeeded, false otherwise
|
||||
*
|
||||
* @param plug The unique identifier of the plugin that calls this function
|
||||
* @param iface The interface pointer
|
||||
* @param thisptr_offs This pointer adjuster
|
||||
* @param myHookMan A hook manager function that should be capable of handling the function
|
||||
* @param handler A pointer to a FastDelegate containing the hook handler
|
||||
* @param post Set to true if you want a post handler
|
||||
*/
|
||||
bool RemoveHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, ISHDelegate *handler, bool post);
|
||||
|
||||
/**
|
||||
* @brief Removes a hook.
|
||||
*
|
||||
* @ return True if the function succeeded, false otherwise
|
||||
*
|
||||
* @param info A RemoveHookInfo structure, describing the hook
|
||||
*/
|
||||
bool RemoveHook(RemoveHookInfo info);
|
||||
|
||||
/**
|
||||
* @brief Checks whether a plugin has (a) hook manager(s) that is/are currently used by other plugins
|
||||
*
|
||||
* @param plug The unique identifier of the plugin in question
|
||||
*/
|
||||
bool IsPluginInUse(Plugin plug);
|
||||
|
||||
/**
|
||||
* @brief Pauses all hooks of a plugin
|
||||
*
|
||||
* @param plug The unique identifier of the plugin
|
||||
*/
|
||||
void PausePlugin(Plugin plug);
|
||||
|
||||
/**
|
||||
* @brief Unpauses all hooks of a plugin
|
||||
*
|
||||
* @param plug The unique identifier of the plugin
|
||||
*/
|
||||
void UnpausePlugin(Plugin plug);
|
||||
|
||||
/**
|
||||
* @brief Return a pointer to a callclass. Generate a new one if required.
|
||||
*
|
||||
* @param iface The interface pointer
|
||||
* @param size Size of the class instance
|
||||
*/
|
||||
GenericCallClass *GetCallClass(void *iface, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Release a callclass
|
||||
*
|
||||
* @param ptr Pointer to the callclass
|
||||
*/
|
||||
virtual void ReleaseCallClass(GenericCallClass *ptr);
|
||||
|
||||
virtual void SetRes(META_RES res); //!< Sets the meta result
|
||||
virtual META_RES GetPrevRes(); //!< Gets the meta result of the previously called handler
|
||||
virtual META_RES GetStatus(); //!< Gets the highest meta result
|
||||
virtual const void *GetOrigRet(); //!< Gets the original result. If not in post function, undefined
|
||||
virtual const void *GetOverrideRet(); //!< Gets the override result. If none is specified, NULL
|
||||
virtual void *GetIfacePtr(); //!< Gets the interface pointer
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// For hook managers
|
||||
void HookLoopBegin(IIface *pIface); //!< Should be called when a hook loop begins
|
||||
void HookLoopEnd(); //!< Should be called when a hook loop exits
|
||||
void SetCurResPtr(META_RES *mres); //!< Sets pointer to the current meta result
|
||||
void SetPrevResPtr(META_RES *mres); //!< Sets pointer to previous meta result
|
||||
void SetStatusPtr(META_RES *mres); //!< Sets pointer to the status variable
|
||||
void SetIfacePtrPtr(void **pp); //!< Sets pointer to the interface this pointer
|
||||
void SetOrigRetPtr(const void *ptr); //!< Sets the original return pointer
|
||||
void SetOverrideRetPtr(const void *ptr); //!< Sets the override result pointer
|
||||
bool ShouldContinue(); //!< Returns false if the hook loop should exit
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in a new issue