From a36fa76d21fcdb3178def00343f421e04ee85b8e Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 27 Apr 2010 21:03:20 -0700 Subject: [PATCH] Root menu handles in callbacks (bug 4353, r=fyren). --- core/HandleSys.cpp | 37 +++++++++++++++++++++++++++++++++++++ core/HandleSys.h | 29 +++++++++++++++++++++++++++++ core/MenuStyle_Base.cpp | 3 +++ 3 files changed, 69 insertions(+) diff --git a/core/HandleSys.cpp b/core/HandleSys.cpp index 5b91a838..d139c1c5 100644 --- a/core/HandleSys.cpp +++ b/core/HandleSys.cpp @@ -620,6 +620,43 @@ HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *newhandle, Iden return CloneHandle(pHandle, index, newhandle, newOwner); } +Handle_t HandleSystem::FastCloneHandle(QHandle *pHandle, unsigned int index) +{ + if (pHandle->clone) + return FastCloneHandle(&m_Handles[pHandle->clone], pHandle->clone); + + Handle_t hndl; + if (CloneHandle(pHandle, index, &hndl, g_pCoreIdent) != HandleError_None) + return BAD_HANDLE; + + return hndl; +} + +Handle_t HandleSystem::FastCloneHandle(Handle_t hndl) +{ + QHandle *pHandle; + unsigned int index; + + GetHandleUnchecked(hndl, pHandle, index); + + return FastCloneHandle(pHandle, index); +} + +void HandleSystem::GetHandleUnchecked(Handle_t hndl, QHandle *& pHandle, unsigned int &index) +{ +#ifndef NDEBUG + unsigned int serial = (hndl >> 16); +#endif + index = (hndl & HANDLESYS_HANDLE_MASK); + + assert(index != 0 && index <= m_HandleTail && index < HANDLESYS_MAX_HANDLES); + + pHandle = &m_Handles[index]; + + assert(pHandle->set && pHandle->set != HandleSet_Freed); + assert(pHandle->serial == serial); +} + HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index) { QHandleType *pType = &m_Types[pHandle->type]; diff --git a/core/HandleSys.h b/core/HandleSys.h index 8fb0e879..5a554aae 100644 --- a/core/HandleSys.h +++ b/core/HandleSys.h @@ -160,6 +160,9 @@ public: //IHandleSystem HandleError *err); void Dump(HANDLE_REPORTER rep); + + /* Bypasses security checks. */ + Handle_t FastCloneHandle(Handle_t hndl); protected: /** * Decodes a handle with sanity and security checking. @@ -170,6 +173,9 @@ protected: unsigned int *index, bool ignoreFree=false); + Handle_t FastCloneHandle(QHandle *pHandle, unsigned int index); + void GetHandleUnchecked(Handle_t hndl, QHandle *& pHandle, unsigned int &index); + /** * Creates a basic handle and sets its reference count to 1. * Does not do any type or security checking. @@ -222,4 +228,27 @@ private: extern HandleSystem g_HandleSys; +struct AutoHandleRooter +{ +public: + AutoHandleRooter(Handle_t hndl) + { + if (hndl != BAD_HANDLE) + this->hndl = g_HandleSys.FastCloneHandle(hndl); + else + this->hndl = BAD_HANDLE; + } + + ~AutoHandleRooter() + { + if (hndl != BAD_HANDLE) + { + HandleSecurity sec(g_pCoreIdent, g_pCoreIdent); + g_HandleSys.FreeHandle(hndl, &sec); + } + } +private: + Handle_t hndl; +}; + #endif //_INCLUDE_SOURCEMOD_HANDLESYSTEM_H_ diff --git a/core/MenuStyle_Base.cpp b/core/MenuStyle_Base.cpp index 786cc86a..89eeb534 100644 --- a/core/MenuStyle_Base.cpp +++ b/core/MenuStyle_Base.cpp @@ -377,6 +377,9 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press) RemoveClientFromWatch(client); } + Handle_t hndl = menu->GetHandle(); + AutoHandleRooter ahr(hndl); + if (cancel) { mh->OnMenuCancel(menu, client, reason);