Skip to content

Commit 1e9bf7a

Browse files
committed
fix: revert sourcehook changes
1 parent 6d56678 commit 1e9bf7a

File tree

1 file changed

+161
-3
lines changed

1 file changed

+161
-3
lines changed

src/mm_plugin.cpp

Lines changed: 161 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,20 @@ using namespace SourceHook::Impl;
4444

4545
SourceHook::ISourceHook* g_SHPtr = nullptr;
4646

47+
struct CSourceHookImplFriend {
48+
typedef HookContextStack CSourceHookImpl::* type;
49+
friend type get(CSourceHookImplFriend);
50+
};
51+
52+
template<typename Tag, typename Tag::type M>
53+
struct CSourceHookImplAccessor {
54+
friend typename Tag::type get(Tag) {
55+
return M;
56+
}
57+
};
58+
59+
template struct CSourceHookImplAccessor<CSourceHookImplFriend, &CSourceHookImpl::m_ContextStack>;
60+
4761
namespace mm {
4862
PlugifyPlugin g_Plugin;
4963
PLUGIN_EXPOSE(PlugifyPlugin, g_Plugin);
@@ -531,6 +545,143 @@ namespace mm {
531545
}
532546
static ConCommand plg_command("plg", plugify_callback, "Plugify control options", 0);
533547

548+
using FindOriginalAddrFn = void* (*) (void* pClass, void* pAddr);
549+
FindOriginalAddrFn _FindOriginalAddr;
550+
bool FindOriginalAddr() {
551+
if (_FindOriginalAddr == nullptr) {
552+
Assembly polyhook("polyhook", LoadFlag::Lazy | LoadFlag::Now);
553+
if (polyhook) {
554+
_FindOriginalAddr = polyhook.GetFunctionByName("FindOriginalAddr").CCast<FindOriginalAddrFn>();
555+
}
556+
else
557+
{
558+
throw std::runtime_error("PolyHook not found, therefore SourceHook could not be patched.\n");
559+
}
560+
}
561+
return _FindOriginalAddr != nullptr;
562+
}
563+
564+
using SetupHookLoopFn = IHookContext* (*) (CSourceHookImpl* sh, CHookManager* hi, void* vfnptr, void* thisptr, void** origCallAddr, META_RES* statusPtr, META_RES* prevResPtr, META_RES* curResPtr, const void* origRetPtr, void* overrideRetPtr);
565+
[[maybe_unused]] SetupHookLoopFn _SetupHookLoop;
566+
IHookContext* SetupHookLoop(CSourceHookImpl* sh, CHookManager* hi, void* vfnptr, void* thisptr, void** origCallAddr, META_RES* statusPtr, META_RES* prevResPtr, META_RES* curResPtr, const void* origRetPtr, void* overrideRetPtr) {
567+
HookContextStack& contextStack = sh->*get(CSourceHookImplFriend());
568+
CHookContext* pCtx = NULL;
569+
CHookContext* oldctx = contextStack.empty() ? NULL : &contextStack.front();
570+
if (oldctx) {
571+
// SH_CALL
572+
if (oldctx->m_State == CHookContext::State_Ignore) {
573+
*statusPtr = MRES_IGNORED;
574+
oldctx->m_CallOrig = true;
575+
oldctx->m_State = CHookContext::State_Dead;
576+
577+
List<CVfnPtr*>& vfnptr_list = hi->GetVfnPtrList();
578+
List<CVfnPtr*>::iterator vfnptr_iter;
579+
for (vfnptr_iter = vfnptr_list.begin();
580+
vfnptr_iter != vfnptr_list.end(); ++vfnptr_iter) {
581+
if (**vfnptr_iter == vfnptr)
582+
break;
583+
}
584+
585+
// Workaround for overhooking
586+
if (vfnptr_iter == vfnptr_list.end() && FindOriginalAddr()) {
587+
void* origPtr = _FindOriginalAddr(thisptr, *(void**) vfnptr);
588+
if (origPtr != nullptr) {
589+
for (vfnptr_iter = vfnptr_list.begin();
590+
vfnptr_iter != vfnptr_list.end(); ++vfnptr_iter) {
591+
void** ptr = (void**) (*vfnptr_iter)->GetPtr();
592+
if (*ptr == origPtr)
593+
{
594+
break;
595+
}
596+
}
597+
}
598+
}
599+
600+
if (vfnptr_iter == vfnptr_list.end()) {
601+
// ASSERT
602+
std::puts("Could not find original address");
603+
std::terminate();
604+
} else {
605+
*origCallAddr = (*vfnptr_iter)->GetOrigCallAddr();
606+
oldctx->pVfnPtr = *vfnptr_iter;
607+
}
608+
609+
oldctx->pOrigRet = origRetPtr;
610+
611+
return oldctx;
612+
}
613+
// Recall
614+
if (oldctx->m_State >= CHookContext::State_Recall_Pre && oldctx->m_State <= CHookContext::State_Recall_PostVP) {
615+
pCtx = oldctx;
616+
617+
*statusPtr = *(oldctx->pStatus);
618+
*prevResPtr = *(oldctx->pPrevRes);
619+
620+
pCtx->m_Iter = oldctx->m_Iter;
621+
622+
// Only have possibility of calling the orig func in pre recall mode
623+
pCtx->m_CallOrig = (oldctx->m_State == CHookContext::State_Recall_Pre || oldctx->m_State == CHookContext::State_Recall_PreVP);
624+
625+
overrideRetPtr = pCtx->pOverrideRet;
626+
627+
// When the status is low so there's no override return value and we're in a post recall,
628+
// give it the orig return value as override return value.
629+
if (pCtx->m_State == CHookContext::State_Recall_Post || pCtx->m_State == CHookContext::State_Recall_PostVP) {
630+
origRetPtr = oldctx->pOrigRet;
631+
if (*statusPtr < MRES_OVERRIDE)
632+
overrideRetPtr = const_cast<void*>(pCtx->pOrigRet);
633+
}
634+
}
635+
}
636+
if (!pCtx) {
637+
pCtx = contextStack.make_next();
638+
pCtx->m_State = CHookContext::State_Born;
639+
pCtx->m_CallOrig = true;
640+
}
641+
642+
pCtx->pIface = NULL;
643+
644+
List<CVfnPtr*>& vfnptr_list = hi->GetVfnPtrList();
645+
List<CVfnPtr*>::iterator vfnptr_iter;
646+
for (vfnptr_iter = vfnptr_list.begin();
647+
vfnptr_iter != vfnptr_list.end(); ++vfnptr_iter) {
648+
if (**vfnptr_iter == vfnptr)
649+
break;
650+
}
651+
652+
// Workaround for overhooking
653+
if (vfnptr_iter == vfnptr_list.end() && FindOriginalAddr()) {
654+
void* origPtr = _FindOriginalAddr(thisptr, *(void**) vfnptr);
655+
if (origPtr != nullptr) {
656+
for (vfnptr_iter = vfnptr_list.begin();
657+
vfnptr_iter != vfnptr_list.end(); ++vfnptr_iter) {
658+
void** ptr = (void**) (*vfnptr_iter)->GetPtr();
659+
if (*ptr == origPtr)
660+
{
661+
break;
662+
}
663+
}
664+
}
665+
}
666+
667+
if (vfnptr_iter == vfnptr_list.end()) {
668+
pCtx->m_State = CHookContext::State_Dead;
669+
} else {
670+
pCtx->pVfnPtr = *vfnptr_iter;
671+
*origCallAddr = pCtx->pVfnPtr->GetOrigCallAddr();
672+
pCtx->pIface = pCtx->pVfnPtr->FindIface(thisptr);
673+
}
674+
675+
pCtx->pStatus = statusPtr;
676+
pCtx->pPrevRes = prevResPtr;
677+
pCtx->pCurRes = curResPtr;
678+
pCtx->pThisPtr = thisptr;
679+
pCtx->pOverrideRet = overrideRetPtr;
680+
pCtx->pOrigRet = origRetPtr;
681+
682+
return pCtx;
683+
}
684+
534685
using ServerGamePostSimulateFn = void (*)(IGameSystem*, const EventServerGamePostSimulate_t&);
535686
ServerGamePostSimulateFn _ServerGamePostSimulate;
536687
void ServerGamePostSimulate(IGameSystem* pThis, const EventServerGamePostSimulate_t& msg) {
@@ -559,6 +710,7 @@ namespace mm {
559710

560711
pluginManager->Terminate();
561712
CONPRINT("Plugin manager was unloaded.\n");
713+
_FindOriginalAddr = nullptr;
562714

563715
if (auto packageManager = g_Plugin.m_context->GetPackageManager().lock()) {
564716
packageManager->Reload();
@@ -573,6 +725,7 @@ namespace mm {
573725
}
574726

575727
pluginManager->Terminate();
728+
_FindOriginalAddr = nullptr;
576729

577730
if (auto packageManager = g_Plugin.m_context->GetPackageManager().lock()) {
578731
packageManager->Reload();
@@ -611,6 +764,11 @@ namespace mm {
611764
_ServerGamePostSimulate = HookMethod(&table, &ServerGamePostSimulate, offset);
612765
}
613766

767+
if (g_SHPtr != nullptr) {
768+
int offset = GetVirtualTableIndex(&ISourceHook::SetupHookLoop);
769+
_SetupHookLoop = HookMethod(g_SHPtr, &SetupHookLoop, offset);
770+
}
771+
614772
m_context = MakePlugify();
615773

616774
m_logger = std::make_shared<MMLogger>("plugify");
@@ -711,7 +869,7 @@ SMM_API PluginId Plugify_Id() {
711869
SMM_API SourceHook::ISourceHook* Plugify_SourceHook() {
712870
return mm::g_SHPtr;
713871
}
714-
872+
/*
715873
struct CSourceHookFriend {
716874
typedef CHookIDManager CSourceHookImpl::* type;
717875
friend type get(CSourceHookFriend);
@@ -743,10 +901,10 @@ SMM_API bool Plugify_SourceHooked(void* vfnptr) {
743901
const CHookIDManager& hookIdManager = sh.*get(CSourceHookFriend());
744902
for (const CHookIDManager::Entry& entry : hookIdManager.*get(CHookIDManagerFriend())) {
745903
if (entry.vfnptr == vfnptr) {
746-
CONPRINT(std::format("Sourcehooked **vfnptr** was pathed: {}\n", vfnptr).c_str());
904+
//CONPRINT(std::format("Sourcehooked **vfnptr** was pathed: {}\n", vfnptr).c_str());
747905
return true;
748906
}
749907
}
750908
//CONPRINTE(std::format("**vfnptr** was not pathed!!!\n", vfnptr).c_str());
751909
return false;
752-
}
910+
}*/

0 commit comments

Comments
 (0)