1.1 --- a/core/systems/HandleSys.cpp Sun Dec 17 02:51:35 2006 +0000
1.2 +++ b/core/systems/HandleSys.cpp Sun Dec 17 09:56:45 2006 +0000
1.3 @@ -1,5 +1,6 @@
1.4 #include "HandleSys.h"
1.5 #include "PluginSys.h"
1.6 +#include <assert.h>
1.7
1.8 HandleSystem g_HandleSys;
1.9
1.10 @@ -56,7 +57,7 @@
1.11 }
1.12 if (parent >= HANDLESYS_TYPEARRAY_SIZE
1.13 || m_Types[parent].dispatch != NULL
1.14 - || m_Types[parent].sec.all.canInherit == false)
1.15 + || m_Types[parent].sec.access[HandleAccess_Inherit] == false)
1.16 {
1.17 return 0;
1.18 }
1.19 @@ -68,12 +69,13 @@
1.20 {
1.21 security = &m_Types[parent].sec;
1.22 } else {
1.23 - static HandleSecurity def_h = {0, HandleAccess() };
1.24 + static HandleSecurity def_h;
1.25 security = &def_h;
1.26 }
1.27 }
1.28
1.29 - if (security->all.canCreate && sm_trie_retrieve(m_TypeLookup, name, NULL))
1.30 + if (security->access[HandleAccess_Create]
1.31 + && sm_trie_retrieve(m_TypeLookup, name, NULL))
1.32 {
1.33 return 0;
1.34 }
1.35 @@ -158,6 +160,54 @@
1.36 return true;
1.37 }
1.38
1.39 +HandleError HandleSystem::MakePrimHandle(HandleType_t type,
1.40 + QHandle **in_pHandle,
1.41 + unsigned int *in_index,
1.42 + Handle_t *in_handle)
1.43 +{
1.44 + unsigned int handle;
1.45 + if (m_FreeHandles == 0)
1.46 + {
1.47 + if (m_HandleTail >= HANDLESYS_MAX_HANDLES)
1.48 + {
1.49 + return HandleError_Limit;;
1.50 + }
1.51 + handle = ++m_HandleTail;
1.52 + } else {
1.53 + handle = m_Handles[m_FreeHandles--].freeID;
1.54 + }
1.55 +
1.56 + QHandle *pHandle = &m_Handles[handle];
1.57 +
1.58 + assert(pHandle->set == false);
1.59 +
1.60 + if (++m_HSerial >= HANDLESYS_MAX_SERIALS)
1.61 + {
1.62 + m_HSerial = 1;
1.63 + }
1.64 +
1.65 + /* Set essential information */
1.66 + pHandle->set = true;
1.67 + pHandle->refcount = 1;
1.68 + pHandle->type = type;
1.69 + pHandle->serial = m_HSerial;
1.70 +
1.71 + /* Create the hash value */
1.72 + Handle_t hash = pHandle->serial;
1.73 + hash <<= 16;
1.74 + hash |= handle;
1.75 +
1.76 + /* Add a reference count to the type */
1.77 + m_Types[type].opened++;
1.78 +
1.79 + /* Output */
1.80 + *in_pHandle = pHandle;
1.81 + *in_index = handle;
1.82 + *in_handle = hash;
1.83 +
1.84 + return HandleError_None;
1.85 +}
1.86 +
1.87 Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityToken_t source, IdentityToken_t ident)
1.88 {
1.89 if (!type
1.90 @@ -169,44 +219,27 @@
1.91
1.92 /* Check the security of this handle */
1.93 QHandleType *pType = &m_Types[type];
1.94 - if (!pType->sec.all.canCreate
1.95 + if (!pType->sec.access[HandleAccess_Create]
1.96 && pType->sec.owner != ident)
1.97 {
1.98 return 0;
1.99 }
1.100
1.101 - unsigned int handle = 0;
1.102 - if (m_FreeHandles == 0)
1.103 + unsigned int index;
1.104 + Handle_t handle;
1.105 + QHandle *pHandle;
1.106 + HandleError err;
1.107 +
1.108 + if ((err=MakePrimHandle(type, &pHandle, &index, &handle)) != HandleError_None)
1.109 {
1.110 - if (m_HandleTail >= HANDLESYS_MAX_HANDLES)
1.111 - {
1.112 - return 0;
1.113 - }
1.114 - handle = ++m_HandleTail;
1.115 - } else {
1.116 - handle = m_Handles[m_FreeHandles--].freeID;
1.117 + return 0;
1.118 }
1.119
1.120 - QHandle *pHandle = &m_Handles[handle];
1.121 -
1.122 - pHandle->type = type;
1.123 pHandle->source = source;
1.124 - pHandle->set = true;
1.125 pHandle->object = object;
1.126 + pHandle->clone = 0;
1.127
1.128 - if (++m_HSerial >= HANDLESYS_MAX_SERIALS)
1.129 - {
1.130 - m_HSerial = 1;
1.131 - }
1.132 - pHandle->serial = m_HSerial;
1.133 -
1.134 - Handle_t hash = pHandle->serial;
1.135 - hash <<= 16;
1.136 - hash |= handle;
1.137 -
1.138 - pType->opened++;
1.139 -
1.140 - return hash;
1.141 + return handle;
1.142 }
1.143
1.144 Handle_t HandleSystem::CreateScriptHandle(HandleType_t type,
1.145 @@ -219,7 +252,11 @@
1.146 return CreateHandle(type, object, pPlugin->GetIdentity(), ident);
1.147 }
1.148
1.149 -HandleError HandleSystem::DestroyHandle(Handle_t handle, IdentityToken_t ident)
1.150 +HandleError HandleSystem::GetHandle(Handle_t handle,
1.151 + IdentityToken_t ident,
1.152 + QHandle **in_pHandle,
1.153 + unsigned int *in_index,
1.154 + HandleAccessRight access)
1.155 {
1.156 unsigned int serial = (handle >> 16);
1.157 unsigned int index = (handle & HANDLESYS_HANDLE_MASK);
1.158 @@ -232,8 +269,8 @@
1.159 QHandle *pHandle = &m_Handles[index];
1.160 QHandleType *pType = &m_Types[pHandle->type];
1.161
1.162 - if (!pType->sec.all.canDelete
1.163 - && pType->sec.owner != ident)
1.164 + if ((access != HandleAccess_TOTAL)
1.165 + && (!pType->sec.access[access] && pType->sec.owner != ident))
1.166 {
1.167 return HandleError_Access;
1.168 }
1.169 @@ -246,10 +283,80 @@
1.170 return HandleError_Changed;
1.171 }
1.172
1.173 - pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
1.174 - pType->opened--;
1.175 - pHandle->set = false;
1.176 - m_Handles[++m_FreeTypes].freeID = index;
1.177 + *in_pHandle = pHandle;
1.178 + *in_index = index;
1.179 +
1.180 + return HandleError_None;
1.181 +}
1.182 +
1.183 +HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *out_newhandle, IdentityToken_t source, IdentityToken_t ident)
1.184 +{
1.185 + HandleError err;
1.186 + QHandle *pHandle;
1.187 + unsigned int index;
1.188 +
1.189 + if ((err=GetHandle(handle, ident, &pHandle, &index, HandleAccess_Clone)) != HandleError_None)
1.190 + {
1.191 + return err;
1.192 + }
1.193 +
1.194 + QHandleType *pType = &m_Types[pHandle->type];
1.195 +
1.196 + /* Get a new Handle ID */
1.197 + unsigned int new_index;
1.198 + QHandle *pNewHandle;
1.199 + Handle_t new_handle;
1.200 +
1.201 + if ((err=MakePrimHandle(pHandle->type, &pNewHandle, &new_index, &new_handle)) != HandleError_None)
1.202 + {
1.203 + return err;
1.204 + }
1.205 +
1.206 + pNewHandle->clone = index;
1.207 + pNewHandle->source = source;
1.208 +
1.209 + if (out_newhandle)
1.210 + {
1.211 + *out_newhandle = new_handle;
1.212 + }
1.213 +
1.214 + return HandleError_None;
1.215 +}
1.216 +
1.217 +HandleError HandleSystem::FreeHandle(Handle_t handle, IdentityToken_t ident)
1.218 +{
1.219 + unsigned int index;
1.220 + QHandle *pHandle;
1.221 + HandleError err;
1.222 +
1.223 + if ((err=GetHandle(handle, ident, &pHandle, &index, HandleAccess_Delete)) != HandleError_None)
1.224 + {
1.225 + return err;
1.226 + }
1.227 +
1.228 + QHandleType *pType = &m_Types[pHandle->type];
1.229 +
1.230 + bool dofree = false;
1.231 + if (pHandle->clone)
1.232 + {
1.233 + /* If we're a clone, there's not a lot to do. */
1.234 + if (FreeHandle(pHandle->clone, ident) != HandleError_None)
1.235 + {
1.236 + assert(false);
1.237 + }
1.238 + dofree = true;
1.239 + } else {
1.240 + if (--pHandle->refcount == 0)
1.241 + {
1.242 + dofree = true;
1.243 + pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
1.244 + }
1.245 + }
1.246 +
1.247 + if (dofree)
1.248 + {
1.249 + ReleasePrimHandle(index);
1.250 + }
1.251
1.252 return HandleError_None;
1.253 }
1.254 @@ -264,24 +371,13 @@
1.255 IdentityToken_t ident,
1.256 void **object)
1.257 {
1.258 - unsigned int serial = (handle >> 16);
1.259 - unsigned int index = (handle & HANDLESYS_HANDLE_MASK);
1.260 -
1.261 - if (index == 0 || index == 0xFFFF)
1.262 - {
1.263 - return HandleError_Index;
1.264 - }
1.265 + unsigned int index;
1.266 + QHandle *pHandle;
1.267 + HandleError err;
1.268
1.269 - QHandle *pHandle = &m_Handles[index];
1.270 -
1.271 - /* Do sanity checks first */
1.272 - if (!pHandle->set)
1.273 + if ((err=GetHandle(handle, ident, &pHandle, &index, HandleAccess_Read)) != HandleError_None)
1.274 {
1.275 - return HandleError_Freed;
1.276 - }
1.277 - if (pHandle->serial != serial)
1.278 - {
1.279 - return HandleError_Changed;
1.280 + return err;
1.281 }
1.282
1.283 /* Check the type inheritance */
1.284 @@ -299,22 +395,28 @@
1.285 }
1.286 }
1.287
1.288 - /* Now do security checks */
1.289 - QHandleType *pType = &m_Types[pHandle->type];
1.290 - if (!pType->sec.all.canRead
1.291 - && pType->sec.owner != ident)
1.292 - {
1.293 - return HandleError_Access;
1.294 - }
1.295 -
1.296 if (object)
1.297 {
1.298 + /* if we're a clone, the rules change - object is ONLY in our reference */
1.299 + if (pHandle->clone)
1.300 + {
1.301 + pHandle = &m_Handles[pHandle->clone];
1.302 + }
1.303 *object = pHandle->object;
1.304 }
1.305
1.306 return HandleError_None;
1.307 }
1.308
1.309 +void HandleSystem::ReleasePrimHandle(unsigned int index)
1.310 +{
1.311 + QHandle *pHandle = &m_Handles[index];
1.312 +
1.313 + pHandle->set = false;
1.314 + m_Types[pHandle->type].opened--;
1.315 + m_Handles[++m_FreeHandles].freeID = index;
1.316 +}
1.317 +
1.318 bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t ident)
1.319 {
1.320 if (type == 0 || type >= HANDLESYS_TYPEARRAY_SIZE)
1.321 @@ -358,17 +460,37 @@
1.322 if (pType->opened)
1.323 {
1.324 QHandle *pHandle;
1.325 - for (unsigned int i=1; i<=HANDLESYS_MAX_HANDLES; i++)
1.326 + for (unsigned int i=1; i<m_HandleTail; i++)
1.327 {
1.328 pHandle = &m_Handles[i];
1.329 if (!pHandle->set || pHandle->type != type)
1.330 {
1.331 continue;
1.332 }
1.333 - dispatch->OnHandleDestroy(type, pHandle->object);
1.334 - pHandle->set = false;
1.335 - m_Handles[++m_FreeHandles].freeID = i;
1.336 - if (--pType->opened == 0)
1.337 + if (pHandle->clone)
1.338 + {
1.339 + /* Get parent */
1.340 + QHandle *pOther = &m_Handles[pHandle->clone];
1.341 + if (--pOther->refcount == 0)
1.342 + {
1.343 + /* Free! */
1.344 + dispatch->OnHandleDestroy(type, pOther->object);
1.345 + ReleasePrimHandle(pHandle->clone);
1.346 + }
1.347 + /* Unlink ourselves since we don't have a reference count */
1.348 + ReleasePrimHandle(i);
1.349 + } else {
1.350 + /* If it's not a clone, we still have to check the reference count.
1.351 + * Either way, we'll be destroyed eventually because the handle types do not change.
1.352 + */
1.353 + if (--pHandle->refcount == 0)
1.354 + {
1.355 + /* Free! */
1.356 + dispatch->OnHandleDestroy(type, pHandle->object);
1.357 + ReleasePrimHandle(i);
1.358 + }
1.359 + }
1.360 + if (pType->opened == 0)
1.361 {
1.362 break;
1.363 }