mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2025-12-08 02:48:30 +00:00
Partial fix
--HG-- extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%40122
This commit is contained in:
parent
047c7e0c99
commit
36dda69d9d
@ -341,12 +341,26 @@ namespace SourceHook
|
|||||||
|
|
||||||
bool erase;
|
bool erase;
|
||||||
for (List<HookInfo>::iterator hookiter = hooks.begin();
|
for (List<HookInfo>::iterator hookiter = hooks.begin();
|
||||||
hookiter != hooks.end(); erase ? hookiter = hooks.erase(hookiter) : ++hookiter)
|
hookiter != hooks.end(); )
|
||||||
{
|
{
|
||||||
erase = hookiter->plug == plug && hookiter->handler->IsEqual(handler) &&
|
erase = hookiter->plug == plug && hookiter->handler->IsEqual(handler) &&
|
||||||
hookiter->thisptr_offs == thisptr_offs;
|
hookiter->thisptr_offs == thisptr_offs;
|
||||||
if (erase)
|
if (erase)
|
||||||
|
{
|
||||||
hookiter->handler->DeleteThis(); // Make the _plugin_ delete the handler object
|
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())
|
if (iface_iter->m_PostHooks.m_List.empty() && iface_iter->m_PreHooks.m_List.empty())
|
||||||
{
|
{
|
||||||
@ -701,10 +715,10 @@ namespace SourceHook
|
|||||||
// CHookList
|
// CHookList
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
|
|
||||||
CSourceHookImpl::CHookList::CHookList() : m_FreeIters(NULL)
|
CSourceHookImpl::CHookList::CHookList() : m_FreeIters(NULL), m_UsedIters(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
CSourceHookImpl::CHookList::CHookList(const CHookList &other) : m_List(other.m_List), m_FreeIters(NULL)
|
CSourceHookImpl::CHookList::CHookList(const CHookList &other) : m_List(other.m_List), m_FreeIters(NULL), m_UsedIters(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
CSourceHookImpl::CHookList::~CHookList()
|
CSourceHookImpl::CHookList::~CHookList()
|
||||||
@ -718,19 +732,41 @@ namespace SourceHook
|
|||||||
}
|
}
|
||||||
IHookList::IIter *CSourceHookImpl::CHookList::GetIter()
|
IHookList::IIter *CSourceHookImpl::CHookList::GetIter()
|
||||||
{
|
{
|
||||||
|
CIter *ret;
|
||||||
if (m_FreeIters)
|
if (m_FreeIters)
|
||||||
{
|
{
|
||||||
CIter *ret = m_FreeIters;
|
ret = m_FreeIters;
|
||||||
m_FreeIters = ret->m_pNext;
|
m_FreeIters = ret->m_pNext;
|
||||||
ret->GoToBegin();
|
ret->GoToBegin();
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
return new CIter(this);
|
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)
|
void CSourceHookImpl::CHookList::ReleaseIter(IIter *pIter)
|
||||||
{
|
{
|
||||||
CIter *pIter2 = static_cast<CIter*>(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;
|
||||||
|
|
||||||
|
// Link to m_FreeIters
|
||||||
|
|
||||||
pIter2->m_pNext = m_FreeIters;
|
pIter2->m_pNext = m_FreeIters;
|
||||||
|
|
||||||
m_FreeIters = pIter2;
|
m_FreeIters = pIter2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -750,13 +786,21 @@ namespace SourceHook
|
|||||||
|
|
||||||
bool CSourceHookImpl::CHookList::CIter::End()
|
bool CSourceHookImpl::CHookList::CIter::End()
|
||||||
{
|
{
|
||||||
|
if (!m_pList)
|
||||||
|
return false;
|
||||||
return m_Iter == m_pList->m_List.end();
|
return m_Iter == m_pList->m_List.end();
|
||||||
}
|
}
|
||||||
void CSourceHookImpl::CHookList::CIter::Next()
|
void CSourceHookImpl::CHookList::CIter::Next()
|
||||||
{
|
{
|
||||||
|
if (!m_pList)
|
||||||
|
return;
|
||||||
++m_Iter;
|
++m_Iter;
|
||||||
SkipPaused();
|
SkipPaused();
|
||||||
}
|
}
|
||||||
|
void CSourceHookImpl::CHookList::CIter::Clear()
|
||||||
|
{
|
||||||
|
m_pList = NULL;
|
||||||
|
}
|
||||||
void CSourceHookImpl::CHookList::CIter::SkipPaused()
|
void CSourceHookImpl::CHookList::CIter::SkipPaused()
|
||||||
{
|
{
|
||||||
while (m_Iter != m_pList->m_List.end() && m_Iter->paused)
|
while (m_Iter != m_pList->m_List.end() && m_Iter->paused)
|
||||||
|
|||||||
@ -68,10 +68,12 @@ namespace SourceHook
|
|||||||
friend class CHookList;
|
friend class CHookList;
|
||||||
|
|
||||||
CHookList *m_pList;
|
CHookList *m_pList;
|
||||||
List<HookInfo>::iterator m_Iter;
|
|
||||||
|
|
||||||
void SkipPaused();
|
void SkipPaused();
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
List<HookInfo>::iterator m_Iter;
|
||||||
|
|
||||||
CIter(CHookList *pList);
|
CIter(CHookList *pList);
|
||||||
|
|
||||||
virtual ~CIter();
|
virtual ~CIter();
|
||||||
@ -83,10 +85,14 @@ namespace SourceHook
|
|||||||
ISHDelegate *Handler();
|
ISHDelegate *Handler();
|
||||||
int ThisPtrOffs();
|
int ThisPtrOffs();
|
||||||
|
|
||||||
CIter *m_pNext; // When stored in m_FreeIters
|
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_FreeIters;
|
||||||
|
CIter *m_UsedIters;
|
||||||
|
|
||||||
CHookList();
|
CHookList();
|
||||||
CHookList(const CHookList &other);
|
CHookList(const CHookList &other);
|
||||||
|
|||||||
@ -5,6 +5,28 @@
|
|||||||
|
|
||||||
void *___testbail_gabgab;
|
void *___testbail_gabgab;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class zomg_lolz
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void zomg()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SH_DECL_HOOK0_void(zomg_lolz, zomg, SH_NOATTRIB, 0);
|
||||||
|
void Handler()
|
||||||
|
{
|
||||||
|
printf("H1\n");
|
||||||
|
SH_REMOVE_HOOK_STATICFUNC(zomg_lolz, zomg, reinterpret_cast<zomg_lolz*>(META_IFACEPTR),
|
||||||
|
Handler, false);
|
||||||
|
}
|
||||||
|
void Handler2()
|
||||||
|
{
|
||||||
|
printf("H2\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool TestBail(std::string &error)
|
bool TestBail(std::string &error)
|
||||||
{
|
{
|
||||||
SourceHook::CSourceHookImpl g_SHImpl;
|
SourceHook::CSourceHookImpl g_SHImpl;
|
||||||
@ -32,6 +54,23 @@ bool TestBail(std::string &error)
|
|||||||
|
|
||||||
// If it didn't crash, it's ok
|
// If it didn't crash, it's ok
|
||||||
|
|
||||||
|
// NEW TEST: Remove hook from handler
|
||||||
|
zomg_lolz inst;
|
||||||
|
SH_ADD_HOOK_STATICFUNC(zomg_lolz, zomg, &inst, Handler, false);
|
||||||
|
SH_ADD_HOOK_STATICFUNC(zomg_lolz, zomg, &inst, Handler2, false);
|
||||||
|
|
||||||
|
zomg_lolz *mwah = &inst;
|
||||||
|
mwah->zomg();
|
||||||
|
mwah->zomg();
|
||||||
|
|
||||||
|
SH_ADD_HOOK_STATICFUNC(zomg_lolz, zomg, &inst, Handler, false);
|
||||||
|
SH_REMOVE_HOOK_STATICFUNC(zomg_lolz, zomg, &inst, Handler2, false);
|
||||||
|
|
||||||
|
mwah->zomg();
|
||||||
|
mwah->zomg();
|
||||||
|
|
||||||
|
// Shouldn't crash again...
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user