Root menu handles in callbacks (bug 4353, r=fyren).
Root menu handles in callbacks (
bug 4353, r=fyren).
1.1 --- a/core/HandleSys.cpp Sat Apr 24 21:10:23 2010 -0400
1.2 +++ b/core/HandleSys.cpp Tue Apr 27 21:03:20 2010 -0700
1.3 @@ -620,6 +620,43 @@
1.4 return CloneHandle(pHandle, index, newhandle, newOwner);
1.5 }
1.6
1.7 +Handle_t HandleSystem::FastCloneHandle(QHandle *pHandle, unsigned int index)
1.8 +{
1.9 + if (pHandle->clone)
1.10 + return FastCloneHandle(&m_Handles[pHandle->clone], pHandle->clone);
1.11 +
1.12 + Handle_t hndl;
1.13 + if (CloneHandle(pHandle, index, &hndl, g_pCoreIdent) != HandleError_None)
1.14 + return BAD_HANDLE;
1.15 +
1.16 + return hndl;
1.17 +}
1.18 +
1.19 +Handle_t HandleSystem::FastCloneHandle(Handle_t hndl)
1.20 +{
1.21 + QHandle *pHandle;
1.22 + unsigned int index;
1.23 +
1.24 + GetHandleUnchecked(hndl, pHandle, index);
1.25 +
1.26 + return FastCloneHandle(pHandle, index);
1.27 +}
1.28 +
1.29 +void HandleSystem::GetHandleUnchecked(Handle_t hndl, QHandle *& pHandle, unsigned int &index)
1.30 +{
1.31 +#ifndef NDEBUG
1.32 + unsigned int serial = (hndl >> 16);
1.33 +#endif
1.34 + index = (hndl & HANDLESYS_HANDLE_MASK);
1.35 +
1.36 + assert(index != 0 && index <= m_HandleTail && index < HANDLESYS_MAX_HANDLES);
1.37 +
1.38 + pHandle = &m_Handles[index];
1.39 +
1.40 + assert(pHandle->set && pHandle->set != HandleSet_Freed);
1.41 + assert(pHandle->serial == serial);
1.42 +}
1.43 +
1.44 HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
1.45 {
1.46 QHandleType *pType = &m_Types[pHandle->type];
2.1 --- a/core/HandleSys.h Sat Apr 24 21:10:23 2010 -0400
2.2 +++ b/core/HandleSys.h Tue Apr 27 21:03:20 2010 -0700
2.3 @@ -160,6 +160,9 @@
2.4 HandleError *err);
2.5
2.6 void Dump(HANDLE_REPORTER rep);
2.7 +
2.8 + /* Bypasses security checks. */
2.9 + Handle_t FastCloneHandle(Handle_t hndl);
2.10 protected:
2.11 /**
2.12 * Decodes a handle with sanity and security checking.
2.13 @@ -170,6 +173,9 @@
2.14 unsigned int *index,
2.15 bool ignoreFree=false);
2.16
2.17 + Handle_t FastCloneHandle(QHandle *pHandle, unsigned int index);
2.18 + void GetHandleUnchecked(Handle_t hndl, QHandle *& pHandle, unsigned int &index);
2.19 +
2.20 /**
2.21 * Creates a basic handle and sets its reference count to 1.
2.22 * Does not do any type or security checking.
2.23 @@ -222,4 +228,27 @@
2.24
2.25 extern HandleSystem g_HandleSys;
2.26
2.27 +struct AutoHandleRooter
2.28 +{
2.29 +public:
2.30 + AutoHandleRooter(Handle_t hndl)
2.31 + {
2.32 + if (hndl != BAD_HANDLE)
2.33 + this->hndl = g_HandleSys.FastCloneHandle(hndl);
2.34 + else
2.35 + this->hndl = BAD_HANDLE;
2.36 + }
2.37 +
2.38 + ~AutoHandleRooter()
2.39 + {
2.40 + if (hndl != BAD_HANDLE)
2.41 + {
2.42 + HandleSecurity sec(g_pCoreIdent, g_pCoreIdent);
2.43 + g_HandleSys.FreeHandle(hndl, &sec);
2.44 + }
2.45 + }
2.46 +private:
2.47 + Handle_t hndl;
2.48 +};
2.49 +
2.50 #endif //_INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
3.1 --- a/core/MenuStyle_Base.cpp Sat Apr 24 21:10:23 2010 -0400
3.2 +++ b/core/MenuStyle_Base.cpp Tue Apr 27 21:03:20 2010 -0700
3.3 @@ -377,6 +377,9 @@
3.4 RemoveClientFromWatch(client);
3.5 }
3.6
3.7 + Handle_t hndl = menu->GetHandle();
3.8 + AutoHandleRooter ahr(hndl);
3.9 +
3.10 if (cancel)
3.11 {
3.12 mh->OnMenuCancel(menu, client, reason);