1.1 --- a/core/systems/HandleSys.cpp Mon Jan 01 23:14:20 2007 +0000
1.2 +++ b/core/systems/HandleSys.cpp Tue Jan 02 01:44:46 2007 +0000
1.3 @@ -334,7 +334,8 @@
1.4 IdentityToken_t *ident,
1.5 QHandle **in_pHandle,
1.6 unsigned int *in_index,
1.7 - HandleAccessRight access)
1.8 + HandleAccessRight access,
1.9 + bool ignoreFree)
1.10 {
1.11 unsigned int serial = (handle >> 16);
1.12 unsigned int index = (handle & HANDLESYS_HANDLE_MASK);
1.13 @@ -352,7 +353,8 @@
1.14 {
1.15 return HandleError_Access;
1.16 }
1.17 - if (!pHandle->set)
1.18 + if (!pHandle->set
1.19 + || (pHandle->set == HandleSet_Freed && !ignoreFree))
1.20 {
1.21 return HandleError_Freed;
1.22 } else if (pHandle->set == HandleSet_Identity
1.23 @@ -383,6 +385,12 @@
1.24 return err;
1.25 }
1.26
1.27 + /* Identities cannot be cloned */
1.28 + if (pHandle->set == HandleSet_Identity)
1.29 + {
1.30 + return HandleError_Identity;
1.31 + }
1.32 +
1.33 QHandleType *pType = &m_Types[pHandle->type];
1.34
1.35 /* Get a new Handle ID */
1.36 @@ -395,7 +403,8 @@
1.37 return err;
1.38 }
1.39
1.40 - pNewHandle->clone = index;
1.41 + pNewHandle->clone = handle;
1.42 + pHandle->refcount++;
1.43
1.44 if (out_newhandle)
1.45 {
1.46 @@ -405,41 +414,60 @@
1.47 return HandleError_None;
1.48 }
1.49
1.50 -HandleError HandleSystem::FreeHandle(Handle_t handle, IdentityToken_t *ident)
1.51 +HandleError HandleSystem::FreeHandle(Handle_t handle, IdentityToken_t *pOwner, IdentityToken_t *ident)
1.52 {
1.53 unsigned int index;
1.54 QHandle *pHandle;
1.55 HandleError err;
1.56
1.57 - if ((err=GetHandle(handle, ident, &pHandle, &index, HandleAccess_Delete)) != HandleError_None)
1.58 + if ((err=GetHandle(handle, ident, &pHandle, &index, HandleAccess_IdentDelete)) != HandleError_None)
1.59 {
1.60 return err;
1.61 }
1.62
1.63 QHandleType *pType = &m_Types[pHandle->type];
1.64
1.65 + if (pType->sec.access[HandleAccess_OwnerDelete] == false
1.66 + && pHandle->owner
1.67 + && pHandle->owner != pOwner)
1.68 + {
1.69 + return HandleError_Access;
1.70 + }
1.71 +
1.72 bool dofree = false;
1.73 if (pHandle->clone)
1.74 {
1.75 - /* If we're a clone, there's not a lot to do. */
1.76 - if (FreeHandle(pHandle->clone, ident) != HandleError_None)
1.77 + /* If we're a clone, decrease the parent reference count */
1.78 + QHandle *pMaster;
1.79 + unsigned int master;
1.80 +
1.81 + /* This call should not return an error, it'd be a corruption sign */
1.82 + err = GetHandle(pHandle->clone, ident, &pMaster, &master, HandleAccess_IdentDelete, true);
1.83 + assert(err == HandleError_None);
1.84 +
1.85 + /* Release the clone now */
1.86 + ReleasePrimHandle(index);
1.87 +
1.88 + /* Decrement the master's reference count */
1.89 + if (--pMaster->refcount == 0)
1.90 {
1.91 - assert(false);
1.92 + /* Type should be the same but do this anyway... */
1.93 + pType = &m_Types[pMaster->type];
1.94 + pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object);
1.95 + ReleasePrimHandle(master);
1.96 }
1.97 - dofree = true;
1.98 } else {
1.99 + /* Decrement, free if necessary */
1.100 if (--pHandle->refcount == 0)
1.101 {
1.102 - dofree = true;
1.103 pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
1.104 + ReleasePrimHandle(index);
1.105 + } else {
1.106 + /* We must be cloned, so mark ourselves as freed */
1.107 + pHandle->set = HandleSet_Freed;
1.108 }
1.109 }
1.110
1.111 - if (dofree)
1.112 - {
1.113 - ReleasePrimHandle(index);
1.114 - }
1.115 -
1.116 return HandleError_None;
1.117 }
1.118
1.119 @@ -477,7 +505,8 @@
1.120 /* if we're a clone, the rules change - object is ONLY in our reference */
1.121 if (pHandle->clone)
1.122 {
1.123 - pHandle = &m_Handles[pHandle->clone];
1.124 + /* :TODO: optimize this */
1.125 + return ReadHandle(pHandle->clone, pHandle->type, ident, object);
1.126 }
1.127 *object = pHandle->object;
1.128 }