Fix extension rejecting valid auth tickets (#24)
* Fix extension rejecting valid auth tickets * don't get origin val twice * Review changes --------- Co-authored-by: Kenzzer <kenzzer@users.noreply.github.com>
This commit is contained in:
parent
b563b80bae
commit
51fe0dbac6
@ -81,14 +81,6 @@
|
|||||||
"windows" "\x55\x8B\xEC\x8B\x55\x08\x8B\x02\x89\x41\x59\x8B\x42\x04"
|
"windows" "\x55\x8B\xEC\x8B\x55\x08\x8B\x02\x89\x41\x59\x8B\x42\x04"
|
||||||
}
|
}
|
||||||
|
|
||||||
"CBaseServer__CheckChallengeType"
|
|
||||||
{
|
|
||||||
"library" "engine"
|
|
||||||
"linux" "@_ZN11CBaseServer18CheckChallengeTypeEP11CBaseClientiR8netadr_siPKcii"
|
|
||||||
"mac" "@_ZN11CBaseServer18CheckChallengeTypeEP11CBaseClientiR8netadr_siPKcii"
|
|
||||||
"windows" "\x55\x8B\xEC\x83\xEC\x14\x56\x57\x8B\x7D\x2A\x8B\xF1"
|
|
||||||
}
|
|
||||||
|
|
||||||
"CBaseServer__CheckMasterServerRequestRestart"
|
"CBaseServer__CheckMasterServerRequestRestart"
|
||||||
{
|
{
|
||||||
"library" "engine"
|
"library" "engine"
|
||||||
@ -106,6 +98,22 @@
|
|||||||
|
|
||||||
"Offsets"
|
"Offsets"
|
||||||
{
|
{
|
||||||
|
"ISteamGameServer__BeginAuthSession"
|
||||||
|
{
|
||||||
|
"linux" "26"
|
||||||
|
"linux64" "26"
|
||||||
|
"windows" "26"
|
||||||
|
"windows64" "26"
|
||||||
|
}
|
||||||
|
|
||||||
|
"ISteamGameServer__EndAuthSession"
|
||||||
|
{
|
||||||
|
"linux" "27"
|
||||||
|
"linux64" "27"
|
||||||
|
"windows" "27"
|
||||||
|
"windows64" "27"
|
||||||
|
}
|
||||||
|
|
||||||
"CheckMasterServerRequestRestart_Steam3ServerFuncOffset"
|
"CheckMasterServerRequestRestart_Steam3ServerFuncOffset"
|
||||||
{
|
{
|
||||||
"windows" "240"
|
"windows" "240"
|
||||||
@ -138,14 +146,6 @@
|
|||||||
"windows" "\x55\x8B\xEC\x56\x8B\xF1\x57\x8B\x7D\x08\x8D\x4E\x04"
|
"windows" "\x55\x8B\xEC\x56\x8B\xF1\x57\x8B\x7D\x08\x8D\x4E\x04"
|
||||||
}
|
}
|
||||||
|
|
||||||
"CBaseServer__CheckChallengeType"
|
|
||||||
{
|
|
||||||
"library" "engine"
|
|
||||||
"linux" "@_ZN11CBaseServer18CheckChallengeTypeEP11CBaseClientiR8netadr_siPKcii"
|
|
||||||
"linux64" "@_ZN11CBaseServer18CheckChallengeTypeEP11CBaseClientiR8netadr_siPKcii"
|
|
||||||
"windows" "\x55\x8B\xEC\x83\xEC\x14\x53\x8B\x5D\x14"
|
|
||||||
}
|
|
||||||
|
|
||||||
"CBaseServer__CheckMasterServerRequestRestart"
|
"CBaseServer__CheckMasterServerRequestRestart"
|
||||||
{
|
{
|
||||||
"library" "engine"
|
"library" "engine"
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
#include "CDetour/detours.h"
|
#include "CDetour/detours.h"
|
||||||
|
|
||||||
#include "steam/steamclientpublic.h"
|
#include "steam/steamclientpublic.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
Connect g_connect;
|
Connect g_connect;
|
||||||
|
|
||||||
@ -114,6 +115,17 @@ typedef void (*SetSteamIDFunc)(CBaseClient *, const CSteamID &steamID);
|
|||||||
typedef void (__fastcall *SetSteamIDFunc)(CBaseClient *, void *, const CSteamID &steamID);
|
typedef void (__fastcall *SetSteamIDFunc)(CBaseClient *, void *, const CSteamID &steamID);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
CDetour* detourCBaseServer__ConnectClient = nullptr;
|
||||||
|
CDetour* detourCBaseServer__RejectConnection = nullptr;
|
||||||
|
|
||||||
|
bool g_bEndAuthSessionOnRejectConnection = false;
|
||||||
|
bool g_bSuppressBeginAuthSession = false;
|
||||||
|
CSteamID g_lastClientSteamID;
|
||||||
|
const void* g_lastAuthTicket;
|
||||||
|
int g_lastcbAuthTicket;
|
||||||
|
|
||||||
|
char passwordBuffer[255];
|
||||||
|
|
||||||
Steam3ServerFunc g_pSteam3ServerFunc = NULL;
|
Steam3ServerFunc g_pSteam3ServerFunc = NULL;
|
||||||
RejectConnectionFunc g_pRejectConnectionFunc = NULL;
|
RejectConnectionFunc g_pRejectConnectionFunc = NULL;
|
||||||
SetSteamIDFunc g_pSetSteamIDFunc = NULL;
|
SetSteamIDFunc g_pSetSteamIDFunc = NULL;
|
||||||
@ -155,89 +167,61 @@ class VFuncEmptyClass{};
|
|||||||
int g_nBeginAuthSessionOffset = 0;
|
int g_nBeginAuthSessionOffset = 0;
|
||||||
int g_nEndAuthSessionOffset = 0;
|
int g_nEndAuthSessionOffset = 0;
|
||||||
|
|
||||||
|
SH_DECL_MANUALHOOK3(MHook_BeginAuthSession, 0, 0, 0, EBeginAuthSessionResult, const void *, int, CSteamID);
|
||||||
|
int g_nHookIdBeginAuthSession = -1;
|
||||||
|
|
||||||
|
EBeginAuthSessionResult Hook_BeginAuthSession(const void *pAuthTicket, int cbAuthTicket, CSteamID steamID)
|
||||||
|
{
|
||||||
|
if (!g_bSuppressBeginAuthSession)
|
||||||
|
{
|
||||||
|
RETURN_META_VALUE(MRES_IGNORED, k_EBeginAuthSessionResultOK);
|
||||||
|
}
|
||||||
|
g_bSuppressBeginAuthSession = false;
|
||||||
|
|
||||||
|
if (strcmp(steamID.Render(), g_lastClientSteamID.Render()) == 0
|
||||||
|
&& g_lastAuthTicket == pAuthTicket
|
||||||
|
&& g_lastcbAuthTicket == cbAuthTicket)
|
||||||
|
{
|
||||||
|
// Let the server know everything is fine
|
||||||
|
// g_pSM->LogMessage(myself, "You alright ;)");
|
||||||
|
RETURN_META_VALUE(MRES_SUPERCEDE, k_EBeginAuthSessionResultOK);
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_META_VALUE(MRES_IGNORED, k_EBeginAuthSessionResultDuplicateRequest);
|
||||||
|
}
|
||||||
|
|
||||||
EBeginAuthSessionResult BeginAuthSession(const void *pAuthTicket, int cbAuthTicket, CSteamID steamID)
|
EBeginAuthSessionResult BeginAuthSession(const void *pAuthTicket, int cbAuthTicket, CSteamID steamID)
|
||||||
{
|
{
|
||||||
if (!g_pSteam3Server || !g_pSteam3Server->m_pSteamGameServer || g_nBeginAuthSessionOffset == 0)
|
if (g_nBeginAuthSessionOffset == 0)
|
||||||
return k_EBeginAuthSessionResultOK;
|
return k_EBeginAuthSessionResultInvalidTicket;
|
||||||
|
|
||||||
void **this_ptr = *(void ***)&g_pSteam3Server->m_pSteamGameServer;
|
void *func = (*(void ***)g_pSteam3Server->m_pSteamGameServer)[g_nBeginAuthSessionOffset];
|
||||||
void **vtable = *(void ***)g_pSteam3Server->m_pSteamGameServer;
|
|
||||||
void *func = vtable[g_nBeginAuthSessionOffset];
|
|
||||||
|
|
||||||
union {
|
union {
|
||||||
EBeginAuthSessionResult (VFuncEmptyClass::*mfpnew)(const void *, int, CSteamID);
|
EBeginAuthSessionResult (VFuncEmptyClass::*mfpnew)(const void *, int, CSteamID);
|
||||||
|
mfpDetails mfp;
|
||||||
#ifndef WIN32
|
|
||||||
struct {
|
|
||||||
void *addr;
|
|
||||||
intptr_t adjustor;
|
|
||||||
} s;
|
|
||||||
} u;
|
} u;
|
||||||
|
u.mfp.Init(func);
|
||||||
|
|
||||||
u.s.addr = func;
|
return (EBeginAuthSessionResult)(reinterpret_cast<VFuncEmptyClass*>(g_pSteam3Server->m_pSteamGameServer)->*u.mfpnew)(pAuthTicket, cbAuthTicket, steamID);
|
||||||
u.s.adjustor = 0;
|
|
||||||
#else
|
|
||||||
void *addr;
|
|
||||||
} u;
|
|
||||||
|
|
||||||
u.addr = func;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return (EBeginAuthSessionResult)(reinterpret_cast<VFuncEmptyClass*>(this_ptr)->*u.mfpnew)(pAuthTicket, cbAuthTicket, steamID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EndAuthSession(CSteamID steamID)
|
void EndAuthSession(CSteamID steamID)
|
||||||
{
|
{
|
||||||
if (!g_pSteam3Server || !g_pSteam3Server->m_pSteamGameServer || g_nEndAuthSessionOffset == 0)
|
if (g_nEndAuthSessionOffset == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
void **this_ptr = *(void ***)&g_pSteam3Server->m_pSteamGameServer;
|
void *func = (*(void ***)g_pSteam3Server->m_pSteamGameServer)[g_nEndAuthSessionOffset];
|
||||||
void **vtable = *(void ***)g_pSteam3Server->m_pSteamGameServer;
|
|
||||||
void *func = vtable[g_nEndAuthSessionOffset];
|
|
||||||
|
|
||||||
union {
|
union {
|
||||||
void (VFuncEmptyClass::*mfpnew)(CSteamID);
|
void (VFuncEmptyClass::*mfpnew)(CSteamID);
|
||||||
|
mfpDetails mfp;
|
||||||
#ifndef WIN32
|
|
||||||
struct {
|
|
||||||
void *addr;
|
|
||||||
intptr_t adjustor;
|
|
||||||
} s;
|
|
||||||
} u;
|
} u;
|
||||||
|
u.mfp.Init(func);
|
||||||
|
|
||||||
u.s.addr = func;
|
return (void)(reinterpret_cast<VFuncEmptyClass*>(g_pSteam3Server->m_pSteamGameServer)->*u.mfpnew)(steamID);
|
||||||
u.s.adjustor = 0;
|
|
||||||
#else
|
|
||||||
void *addr;
|
|
||||||
} u;
|
|
||||||
|
|
||||||
u.addr = func;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return (void)(reinterpret_cast<VFuncEmptyClass*>(this_ptr)->*u.mfpnew)(steamID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CDetour* detourCBaseServer__ConnectClient = nullptr;
|
|
||||||
CDetour* detourCBaseServer__RejectConnection = nullptr;
|
|
||||||
CDetour* detourCBaseServer__CheckChallengeType = nullptr;
|
|
||||||
|
|
||||||
bool g_bEndAuthSessionOnRejectConnection = false;
|
|
||||||
CSteamID g_lastClientSteamID;
|
|
||||||
|
|
||||||
bool g_bSuppressCheckChallengeType = false;
|
|
||||||
|
|
||||||
char passwordBuffer[255];
|
|
||||||
|
|
||||||
#define DETOUR_DECL_MEMBER9(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name, p8type, p8name, p9type, p9name) \
|
|
||||||
class name##Class \
|
|
||||||
{ \
|
|
||||||
public: \
|
|
||||||
ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name, p9type p9name); \
|
|
||||||
static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type, p9type); \
|
|
||||||
}; \
|
|
||||||
ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type, p9type) = NULL; \
|
|
||||||
ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name, p9type p9name)
|
|
||||||
|
|
||||||
DETOUR_DECL_MEMBER9(CBaseServer__ConnectClient, IClient*, netadr_t&, address, int, nProtocol, int, iChallenge, int, iClientChallenge, int, nAuthProtocol, const char *, pchName, const char *, pchPassword, const char *, pCookie, int, cbCookie)
|
DETOUR_DECL_MEMBER9(CBaseServer__ConnectClient, IClient*, netadr_t&, address, int, nProtocol, int, iChallenge, int, iClientChallenge, int, nAuthProtocol, const char *, pchName, const char *, pchPassword, const char *, pCookie, int, cbCookie)
|
||||||
{
|
{
|
||||||
if (nAuthProtocol != k_EAuthProtocolSteam)
|
if (nAuthProtocol != k_EAuthProtocolSteam)
|
||||||
@ -264,7 +248,10 @@ DETOUR_DECL_MEMBER9(CBaseServer__ConnectClient, IClient*, netadr_t&, address, in
|
|||||||
|
|
||||||
g_bEndAuthSessionOnRejectConnection = true;
|
g_bEndAuthSessionOnRejectConnection = true;
|
||||||
g_lastClientSteamID = CSteamID(ullSteamID);
|
g_lastClientSteamID = CSteamID(ullSteamID);
|
||||||
|
g_lastcbAuthTicket = cbTicket;
|
||||||
|
g_lastAuthTicket = pvTicket;
|
||||||
|
|
||||||
|
// Validate steam ticket
|
||||||
EBeginAuthSessionResult result = BeginAuthSession(pvTicket, cbTicket, g_lastClientSteamID);
|
EBeginAuthSessionResult result = BeginAuthSession(pvTicket, cbTicket, g_lastClientSteamID);
|
||||||
if (result != k_EBeginAuthSessionResultOK)
|
if (result != k_EBeginAuthSessionResultOK)
|
||||||
{
|
{
|
||||||
@ -291,8 +278,10 @@ DETOUR_DECL_MEMBER9(CBaseServer__ConnectClient, IClient*, netadr_t&, address, in
|
|||||||
|
|
||||||
pchPassword = passwordBuffer;
|
pchPassword = passwordBuffer;
|
||||||
|
|
||||||
g_bSuppressCheckChallengeType = true;
|
g_bSuppressBeginAuthSession = true;
|
||||||
return DETOUR_MEMBER_CALL(CBaseServer__ConnectClient)(address, nProtocol, iChallenge, iClientChallenge, nAuthProtocol, pchName, pchPassword, pCookie, cbCookie);
|
auto client = DETOUR_MEMBER_CALL(CBaseServer__ConnectClient)(address, nProtocol, iChallenge, iClientChallenge, nAuthProtocol, pchName, pchPassword, pCookie, cbCookie);
|
||||||
|
g_bSuppressBeginAuthSession = false;
|
||||||
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
DETOUR_DECL_MEMBER3(CBaseServer__RejectConnection, void, netadr_t &, address, int, iClientChallenge, const char *, pchReason)
|
DETOUR_DECL_MEMBER3(CBaseServer__RejectConnection, void, netadr_t &, address, int, iClientChallenge, const char *, pchReason)
|
||||||
@ -306,21 +295,6 @@ DETOUR_DECL_MEMBER3(CBaseServer__RejectConnection, void, netadr_t &, address, in
|
|||||||
return DETOUR_MEMBER_CALL(CBaseServer__RejectConnection)(address, iClientChallenge, pchReason);
|
return DETOUR_MEMBER_CALL(CBaseServer__RejectConnection)(address, iClientChallenge, pchReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
DETOUR_DECL_MEMBER7(CBaseServer__CheckChallengeType, bool, CBaseClient *, pClient, int, nUserID, netadr_t &, address, int, nAuthProtocol, const char *, pCookie, int, cbCookie, int, iClientChallenge)
|
|
||||||
{
|
|
||||||
if (g_bSuppressCheckChallengeType)
|
|
||||||
{
|
|
||||||
g_bEndAuthSessionOnRejectConnection = false;
|
|
||||||
|
|
||||||
SetSteamID(pClient, g_lastClientSteamID);
|
|
||||||
|
|
||||||
g_bSuppressCheckChallengeType = false;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return DETOUR_MEMBER_CALL(CBaseServer__CheckChallengeType)(pClient, nUserID, address, nAuthProtocol, pCookie, cbCookie, iClientChallenge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Connect::SDK_OnLoad(char *error, size_t maxlen, bool late)
|
bool Connect::SDK_OnLoad(char *error, size_t maxlen, bool late)
|
||||||
{
|
{
|
||||||
char conf_error[255] = "";
|
char conf_error[255] = "";
|
||||||
@ -381,6 +355,12 @@ bool Connect::SDK_OnLoad(char *error, size_t maxlen, bool late)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!g_pSteam3Server->m_pSteamGameServer)
|
||||||
|
{
|
||||||
|
snprintf(error, maxlen, "Unable to get Steam Game Server.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
META_CONPRINTF("ISteamGameServer: %p\n", g_pSteam3Server->m_pSteamGameServer);
|
META_CONPRINTF("ISteamGameServer: %p\n", g_pSteam3Server->m_pSteamGameServer);
|
||||||
META_CONPRINTF("ISteamUtils: %p\n", g_pSteam3Server->m_pSteamGameServerUtils);
|
META_CONPRINTF("ISteamUtils: %p\n", g_pSteam3Server->m_pSteamGameServerUtils);
|
||||||
@ -394,6 +374,12 @@ bool Connect::SDK_OnLoad(char *error, size_t maxlen, bool late)
|
|||||||
snprintf(error, maxlen, "Failed to find ISteamGameServer__BeginAuthSession offset.\n");
|
snprintf(error, maxlen, "Failed to find ISteamGameServer__BeginAuthSession offset.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
SH_MANUALHOOK_RECONFIGURE(MHook_BeginAuthSession, g_nBeginAuthSessionOffset, 0, 0);
|
||||||
|
if (SH_ADD_MANUALHOOK(MHook_BeginAuthSession, g_pSteam3Server->m_pSteamGameServer, SH_STATIC(Hook_BeginAuthSession), true) == 0)
|
||||||
|
{
|
||||||
|
snprintf(error, maxlen, "Failed to setup ISteamGameServer__BeginAuthSession hook.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!g_pGameConf->GetOffset("ISteamGameServer__EndAuthSession", &g_nEndAuthSessionOffset) || g_nEndAuthSessionOffset == 0)
|
if (!g_pGameConf->GetOffset("ISteamGameServer__EndAuthSession", &g_nEndAuthSessionOffset) || g_nEndAuthSessionOffset == 0)
|
||||||
{
|
{
|
||||||
@ -404,8 +390,20 @@ bool Connect::SDK_OnLoad(char *error, size_t maxlen, bool late)
|
|||||||
CDetourManager::Init(g_pSM->GetScriptingEngine(), g_pGameConf);
|
CDetourManager::Init(g_pSM->GetScriptingEngine(), g_pGameConf);
|
||||||
|
|
||||||
detourCBaseServer__ConnectClient = DETOUR_CREATE_MEMBER(CBaseServer__ConnectClient, "CBaseServer__ConnectClient");
|
detourCBaseServer__ConnectClient = DETOUR_CREATE_MEMBER(CBaseServer__ConnectClient, "CBaseServer__ConnectClient");
|
||||||
|
if (detourCBaseServer__ConnectClient == nullptr)
|
||||||
|
{
|
||||||
|
snprintf(error, maxlen, "Failed to create CBaseServer__ConnectClient detour.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
detourCBaseServer__ConnectClient->EnableDetour();
|
||||||
|
|
||||||
detourCBaseServer__RejectConnection = DETOUR_CREATE_MEMBER(CBaseServer__RejectConnection, "CBaseServer__RejectConnection");
|
detourCBaseServer__RejectConnection = DETOUR_CREATE_MEMBER(CBaseServer__RejectConnection, "CBaseServer__RejectConnection");
|
||||||
detourCBaseServer__CheckChallengeType = DETOUR_CREATE_MEMBER(CBaseServer__CheckChallengeType, "CBaseServer__CheckChallengeType");
|
if (detourCBaseServer__RejectConnection == nullptr)
|
||||||
|
{
|
||||||
|
snprintf(error, maxlen, "Failed to create CBaseServer__RejectConnection detour.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
detourCBaseServer__RejectConnection->EnableDetour();
|
||||||
|
|
||||||
g_pConnectForward = g_pForwards->CreateForward("OnClientPreConnectEx", ET_LowEvent, 5, NULL, Param_String, Param_String, Param_String, Param_String, Param_String);
|
g_pConnectForward = g_pForwards->CreateForward("OnClientPreConnectEx", ET_LowEvent, 5, NULL, Param_String, Param_String, Param_String, Param_String, Param_String);
|
||||||
|
|
||||||
@ -435,16 +433,12 @@ bool Connect::SDK_OnMetamodUnload(char *error, size_t maxlen)
|
|||||||
detourCBaseServer__ConnectClient->DisableDetour();
|
detourCBaseServer__ConnectClient->DisableDetour();
|
||||||
delete detourCBaseServer__ConnectClient;
|
delete detourCBaseServer__ConnectClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (detourCBaseServer__RejectConnection)
|
if (detourCBaseServer__RejectConnection)
|
||||||
{
|
{
|
||||||
detourCBaseServer__RejectConnection->DisableDetour();
|
detourCBaseServer__RejectConnection->DisableDetour();
|
||||||
delete detourCBaseServer__RejectConnection;
|
delete detourCBaseServer__RejectConnection;
|
||||||
}
|
}
|
||||||
if (detourCBaseServer__CheckChallengeType)
|
|
||||||
{
|
|
||||||
detourCBaseServer__CheckChallengeType->DisableDetour();
|
|
||||||
delete detourCBaseServer__CheckChallengeType;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -100,4 +100,24 @@ public: //IConCommandBaseAccessor
|
|||||||
bool RegisterConCommandBase(ConCommandBase *pCommand);
|
bool RegisterConCommandBase(ConCommandBase *pCommand);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define DETOUR_DECL_MEMBER9(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name, p8type, p8name, p9type, p9name) \
|
||||||
|
class name##Class \
|
||||||
|
{ \
|
||||||
|
public: \
|
||||||
|
ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name, p9type p9name); \
|
||||||
|
static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type, p9type); \
|
||||||
|
}; \
|
||||||
|
ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type, p9type) = NULL; \
|
||||||
|
ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name, p9type p9name)
|
||||||
|
|
||||||
|
struct mfpDetails {
|
||||||
|
void *addr;
|
||||||
|
intptr_t adjustor;
|
||||||
|
|
||||||
|
void Init(void* addr, intptr_t adj = 0) {
|
||||||
|
this->addr = addr;
|
||||||
|
this->adjustor = adj;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user