mirror of
https://github.com/WPMGPRoSToTeMa/SafeNameAndChat.git
synced 2025-01-13 04:37:55 +03:00
258 lines
7.5 KiB
C++
258 lines
7.5 KiB
C++
|
|
// vi: set ts=4 sw=4 :
|
|
// vim: set tw=75 :
|
|
|
|
// engineinfo.h - info about HL engine, like file used and
|
|
// text segment range
|
|
//
|
|
|
|
#ifndef MM_ENGINEINFO_H
|
|
#define MM_ENGINEINFO_H
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
typedef void* MemAddr;
|
|
#else
|
|
# include <link.h> // ElfW(Addr/Phdr) macros
|
|
typedef void* MemAddr;
|
|
#endif /* _WIN32 */
|
|
|
|
#include "extdll.h" // eiface.h: enginefuncs_t
|
|
|
|
#include "comp_dep.h"
|
|
#include "osdep.h" //unlikely, OPEN_ARGS
|
|
#include "new_baseclass.h"
|
|
|
|
|
|
// What we return in is_valid_code_pointer() when the EngineInfo object is
|
|
// in an INVALID state, i.e. no code address range could be determined.
|
|
static const bool c_DefaultReturnOnInvalidState = true;
|
|
|
|
static const int c_EngineInfo__typeLen = 10;
|
|
|
|
|
|
class EngineInfo : public class_metamod_new
|
|
{
|
|
private:
|
|
// data :
|
|
|
|
MemAddr m_codeStart;
|
|
MemAddr m_codeEnd;
|
|
|
|
// State is either NULL when not yet initialised,
|
|
// VALID if a code range could be determined
|
|
// or INVALID when no valid range for code addresses
|
|
// could be determined.
|
|
char m_state;
|
|
|
|
// Type of engine dso/dll used.
|
|
// For Linux this specifies the architecture, i.e. 'i486', 'i686',
|
|
// 'amd', 'amd64' etc.
|
|
// For Windows this is either 'sw' or 'hw' or 'swds' depending on
|
|
// the server type.
|
|
char m_type[c_EngineInfo__typeLen];
|
|
|
|
// functions :
|
|
|
|
|
|
// Check if string is valid name of engine dso/dll.
|
|
bool DLLINTERNAL check_for_engine_module( const char* pName );
|
|
|
|
#ifdef _WIN32
|
|
|
|
// Set info using the PE header found by module name.
|
|
// Returns 0 on success, error code on failure.
|
|
int DLLINTERNAL nthdr_module_name( void );
|
|
|
|
int DLLINTERNAL vac_pe_approx( enginefuncs_t* pFuncs );
|
|
|
|
// Set code segment start and end from PEheader. The base
|
|
// address, that relative addresses are based on, is passed in
|
|
// pBase.
|
|
void DLLINTERNAL set_code_range( unsigned char* pBase, PIMAGE_NT_HEADERS pNThdr );
|
|
|
|
#else
|
|
|
|
// Set info using the Programheader found via r_debug struct.
|
|
// Returns 0 on success, error code on failure.
|
|
int DLLINTERNAL phdr_r_debug( void );
|
|
// Set info using the Programheader found with reference address
|
|
// via dladdr(). Returns 0 on success, error code on failure.
|
|
int DLLINTERNAL phdr_dladdr( void* pMem );
|
|
// Set info using the Programheader found via ELF header passed as
|
|
// pElfHdr. Return 0 on success, error code on failure.
|
|
int DLLINTERNAL phdr_elfhdr( void* pElfHdr );
|
|
// Set code segment start and end from Programheader. The base
|
|
// address, that relative addresses are based on, is passed in
|
|
// pBase.
|
|
void DLLINTERNAL set_code_range( void* pBase, ElfW(Phdr)* pPhdr );
|
|
|
|
#endif /* _WIN32 */
|
|
|
|
public:
|
|
// codes :
|
|
|
|
enum {
|
|
STATE_NULL = 0,
|
|
STATE_VALID,
|
|
STATE_INVALID,
|
|
|
|
MODULE_NAME_NOTFOUND = 5,
|
|
INVALID_DOS_SIGN,
|
|
INVALID_NT_SIGN,
|
|
INVALID_ARG,
|
|
HEADER_NOTFOUND,
|
|
NOTFOUND
|
|
};
|
|
|
|
|
|
// functions :
|
|
|
|
EngineInfo() DLLINTERNAL;
|
|
EngineInfo& operator=( const EngineInfo& ) DLLINTERNAL;
|
|
EngineInfo( const EngineInfo& ) DLLINTERNAL;
|
|
|
|
const char* DLLINTERNAL type( void );
|
|
|
|
// Initilaise object, determining the bounds of the code segment of
|
|
// the HL engine shared object.
|
|
int DLLINTERNAL initialise( enginefuncs_t* pFuncs = NULL );
|
|
|
|
// Test if pMem is within bounds of the code segment.
|
|
bool DLLINTERNAL is_valid_code_pointer( void* pMem );
|
|
|
|
// Overloaded versions of above test to keep the ugly pointer
|
|
// conversion stuff in here.
|
|
bool DLLINTERNAL is_valid_code_pointer( const char* (*fp) (edict_t*) );
|
|
bool DLLINTERNAL is_valid_code_pointer( sequenceEntry_s* (*fp) (const char*, const char*) );
|
|
bool DLLINTERNAL is_valid_code_pointer( sentenceEntry_s* (*fp) (const char*, int, int*) );
|
|
bool DLLINTERNAL is_valid_code_pointer( int (*fp) (char*) );
|
|
bool DLLINTERNAL is_valid_code_pointer( unsigned int (*fp) (const char*) );
|
|
bool DLLINTERNAL is_valid_code_pointer( int (*fp) (void) );
|
|
bool DLLINTERNAL is_valid_code_pointer( int (*fp) (const char*) );
|
|
bool DLLINTERNAL is_valid_code_pointer( void (*fp) (int) );
|
|
bool DLLINTERNAL is_valid_code_pointer( int (*fp) (int) );
|
|
bool DLLINTERNAL is_valid_code_pointer( void (*fp) (int*, int) );
|
|
bool DLLINTERNAL is_valid_code_pointer( void (*fp) (void) );
|
|
bool DLLINTERNAL is_valid_code_pointer( void (*fp) (const edict_t*, const char*) );
|
|
bool DLLINTERNAL is_valid_code_pointer( void (*fp) (const edict_t*, const char*, int) );
|
|
};
|
|
|
|
|
|
|
|
// We probably should run an initialisation here without a reference
|
|
// pointer so that the object has valid info in any case.
|
|
inline EngineInfo::EngineInfo() :
|
|
m_codeStart(NULL),
|
|
m_codeEnd(NULL),
|
|
m_state(STATE_NULL)
|
|
{
|
|
m_type[0] = '\0';
|
|
}
|
|
|
|
|
|
inline EngineInfo::EngineInfo( const EngineInfo& _rhs) :
|
|
m_codeStart(_rhs.m_codeStart),
|
|
m_codeEnd(_rhs.m_codeEnd),
|
|
m_state(STATE_NULL)
|
|
{
|
|
memcpy( m_type, _rhs.m_type, c_EngineInfo__typeLen );
|
|
}
|
|
|
|
|
|
inline EngineInfo& EngineInfo::operator=( const EngineInfo& _rhs)
|
|
{
|
|
m_state = _rhs.m_state;
|
|
m_codeStart = _rhs.m_codeStart;
|
|
m_codeEnd = _rhs.m_codeEnd;
|
|
memcpy( m_type, _rhs.m_type, c_EngineInfo__typeLen );
|
|
return *this;
|
|
}
|
|
|
|
|
|
inline const char* EngineInfo::type( void )
|
|
{
|
|
return m_type;
|
|
}
|
|
|
|
inline bool EngineInfo::is_valid_code_pointer( void* _pMem )
|
|
{
|
|
if ( STATE_INVALID == m_state ) {
|
|
return c_DefaultReturnOnInvalidState;
|
|
}
|
|
if ( NULL != _pMem && m_codeStart <= _pMem && _pMem <= m_codeEnd ) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
inline bool EngineInfo::is_valid_code_pointer( const char* (*_fp) (edict_t*) )
|
|
{
|
|
return is_valid_code_pointer( (void*)_fp );
|
|
}
|
|
|
|
inline bool EngineInfo::is_valid_code_pointer( sequenceEntry_s* (*_fp) (const char*, const char*) )
|
|
{
|
|
return is_valid_code_pointer( (void*)_fp );
|
|
}
|
|
|
|
inline bool EngineInfo::is_valid_code_pointer( sentenceEntry_s* (*_fp) (const char*, int, int*) )
|
|
{
|
|
return is_valid_code_pointer( (void*)_fp );
|
|
}
|
|
|
|
inline bool EngineInfo::is_valid_code_pointer( int (*_fp) (char*) )
|
|
{
|
|
return is_valid_code_pointer( (void*)_fp );
|
|
}
|
|
|
|
inline bool EngineInfo::is_valid_code_pointer( unsigned int (*_fp) (const char*) )
|
|
{
|
|
return is_valid_code_pointer( (void*)_fp );
|
|
}
|
|
|
|
inline bool EngineInfo::is_valid_code_pointer( int (*_fp) (void) )
|
|
{
|
|
return is_valid_code_pointer( (void*)_fp );
|
|
}
|
|
|
|
inline bool EngineInfo::is_valid_code_pointer( int (*_fp) (const char*) )
|
|
{
|
|
return is_valid_code_pointer( (void*)_fp );
|
|
}
|
|
|
|
inline bool EngineInfo::is_valid_code_pointer( void (*_fp) (int) )
|
|
{
|
|
return is_valid_code_pointer( (void*)_fp );
|
|
}
|
|
|
|
inline bool EngineInfo::is_valid_code_pointer( int (*_fp) (int) )
|
|
{
|
|
return is_valid_code_pointer( (void*)_fp );
|
|
}
|
|
|
|
inline bool EngineInfo::is_valid_code_pointer( void (*_fp) (int*, int) )
|
|
{
|
|
return is_valid_code_pointer( (void*)_fp );
|
|
}
|
|
|
|
inline bool EngineInfo::is_valid_code_pointer( void (*_fp) (void) )
|
|
{
|
|
return is_valid_code_pointer( (void*)_fp );
|
|
}
|
|
|
|
inline bool EngineInfo::is_valid_code_pointer( void (*_fp) (const edict_t*, const char*) )
|
|
{
|
|
return is_valid_code_pointer( (void*)_fp );
|
|
}
|
|
|
|
inline bool EngineInfo::is_valid_code_pointer( void (*_fp) (const edict_t*, const char*, int) )
|
|
{
|
|
return is_valid_code_pointer( (void*)_fp );
|
|
}
|
|
|
|
#endif /* MM_ENGINEINFO_H */
|
|
|