1.1 --- a/core/systems/HandleSys.cpp Thu Jan 11 01:13:34 2007 +0000
1.2 +++ b/core/systems/HandleSys.cpp Thu Jan 11 07:29:09 2007 +0000
1.3 @@ -231,7 +231,8 @@
1.4 QHandle **in_pHandle,
1.5 unsigned int *in_index,
1.6 Handle_t *in_handle,
1.7 - IdentityToken_t *owner)
1.8 + IdentityToken_t *owner,
1.9 + bool identity)
1.10 {
1.11 unsigned int owner_index = 0;
1.12
1.13 @@ -262,7 +263,7 @@
1.14 }
1.15
1.16 /* Set essential information */
1.17 - pHandle->set = HandleSet_Used;;
1.18 + pHandle->set = identity ? HandleSet_Identity : HandleSet_Used;
1.19 pHandle->refcount = 1;
1.20 pHandle->type = type;
1.21 pHandle->serial = m_HSerial;
1.22 @@ -282,8 +283,10 @@
1.23 *in_index = handle;
1.24 *in_handle = hash;
1.25
1.26 - /* Decode the identity token */
1.27 - if (owner)
1.28 + /* Decode the identity token
1.29 + * For now, we don't allow nested ownership
1.30 + */
1.31 + if (owner && !identity)
1.32 {
1.33 QHandle *pIdentity = &m_Handles[owner_index];
1.34 if (pIdentity->ch_prev == 0)
1.35 @@ -319,7 +322,7 @@
1.36 m_Types[type].typeSec.ident = pToken;
1.37 }
1.38
1.39 -Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityToken_t *owner, IdentityToken_t *ident, HandleError *err)
1.40 +Handle_t HandleSystem::CreateHandleEx(HandleType_t type, void *object, IdentityToken_t *owner, IdentityToken_t *ident, HandleError *err, bool identity)
1.41 {
1.42 if (!type
1.43 || type >= HANDLESYS_TYPEARRAY_SIZE
1.44 @@ -335,8 +338,8 @@
1.45 /* Check to see if we're allowed to create this handle type */
1.46 QHandleType *pType = &m_Types[type];
1.47 if (!pType->typeSec.access[HTypeAccess_Create]
1.48 - && (!pType->typeSec.ident
1.49 - || pType->typeSec.ident != ident))
1.50 + && (!pType->typeSec.ident
1.51 + || pType->typeSec.ident != ident))
1.52 {
1.53 if (err)
1.54 {
1.55 @@ -350,7 +353,7 @@
1.56 QHandle *pHandle;
1.57 HandleError _err;
1.58
1.59 - if ((_err=MakePrimHandle(type, &pHandle, &index, &handle, owner)) != HandleError_None)
1.60 + if ((_err=MakePrimHandle(type, &pHandle, &index, &handle, owner, identity)) != HandleError_None)
1.61 {
1.62 if (err)
1.63 {
1.64 @@ -365,6 +368,11 @@
1.65 return handle;
1.66 }
1.67
1.68 +Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityToken_t *owner, IdentityToken_t *ident, HandleError *err)
1.69 +{
1.70 + return CreateHandleEx(type, object, owner, ident, err, false);
1.71 +}
1.72 +
1.73 bool HandleSystem::TypeCheck(HandleType_t intype, HandleType_t outtype)
1.74 {
1.75 /* Check the type inheritance */
1.76 @@ -453,6 +461,27 @@
1.77 return true;
1.78 }
1.79
1.80 +HandleError HandleSystem::CloneHandle(QHandle *pHandle, unsigned int index, Handle_t *newhandle, IdentityToken_t *newOwner)
1.81 +{
1.82 + /* Get a new Handle ID */
1.83 + unsigned int new_index;
1.84 + QHandle *pNewHandle;
1.85 + Handle_t new_handle;
1.86 + HandleError err;
1.87 +
1.88 + if ((err=MakePrimHandle(pHandle->type, &pNewHandle, &new_index, &new_handle, newOwner)) != HandleError_None)
1.89 + {
1.90 + return err;
1.91 + }
1.92 +
1.93 + pNewHandle->clone = index;
1.94 + pHandle->refcount++;
1.95 +
1.96 + *newhandle = new_handle;
1.97 +
1.98 + return HandleError_None;
1.99 +}
1.100 +
1.101 HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *newhandle, IdentityToken_t *newOwner, const HandleSecurity *pSecurity)
1.102 {
1.103 HandleError err;
1.104 @@ -477,20 +506,63 @@
1.105 return HandleError_Access;
1.106 }
1.107
1.108 - /* Get a new Handle ID */
1.109 - unsigned int new_index;
1.110 - QHandle *pNewHandle;
1.111 - Handle_t new_handle;
1.112 -
1.113 - if ((err=MakePrimHandle(pHandle->type, &pNewHandle, &new_index, &new_handle, newOwner)) != HandleError_None)
1.114 + /* Make sure we're not cloning a clone */
1.115 + if (pHandle->clone)
1.116 {
1.117 - return err;
1.118 + QHandle *pParent = &m_Handles[pHandle->clone];
1.119 + return CloneHandle(pParent, pHandle->clone, newhandle, newOwner);
1.120 }
1.121
1.122 - pNewHandle->clone = index;
1.123 - pHandle->refcount++;
1.124 + return CloneHandle(pHandle, index, newhandle, newOwner);
1.125 +}
1.126 +
1.127 +HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
1.128 +{
1.129 + QHandleType *pType = &m_Types[pHandle->type];
1.130 +
1.131 + if (pHandle->clone)
1.132 + {
1.133 + /* If we're a clone, decrease the parent reference count */
1.134 + QHandle *pMaster;
1.135 + unsigned int master;
1.136 +
1.137 + /* Note that if we ever have per-handle security, we would need to re-check
1.138 + * the access on this Handle. */
1.139 + master = pHandle->clone;
1.140 + pMaster = &m_Handles[master];
1.141 +
1.142 + /* Release the clone now */
1.143 + ReleasePrimHandle(index);
1.144
1.145 - *newhandle = new_handle;
1.146 + /* Decrement the master's reference count */
1.147 + if (--pMaster->refcount == 0)
1.148 + {
1.149 + /* Type should be the same but do this anyway... */
1.150 + pType = &m_Types[pMaster->type];
1.151 + pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object);
1.152 + ReleasePrimHandle(master);
1.153 + }
1.154 + } else if (pHandle->set == HandleSet_Identity) {
1.155 + /* If we're an identity, skip all this stuff!
1.156 + * NOTE: SHARESYS DOES NOT CARE ABOUT THE DESTRUCTOR
1.157 + */
1.158 + ReleasePrimHandle(index);
1.159 + } else {
1.160 + /* Decrement, free if necessary */
1.161 + if (--pHandle->refcount == 0)
1.162 + {
1.163 + pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
1.164 + ReleasePrimHandle(index);
1.165 + } else {
1.166 + /* We must be cloned, so mark ourselves as freed */
1.167 + pHandle->set = HandleSet_Freed;
1.168 + /* Now, unlink us, so we're not being tracked by the owner */
1.169 + if (pHandle->owner)
1.170 + {
1.171 + UnlinkHandleFromOwner(pHandle, index);
1.172 + }
1.173 + }
1.174 + }
1.175
1.176 return HandleError_None;
1.177 }
1.178 @@ -512,44 +584,7 @@
1.179 return HandleError_Access;
1.180 }
1.181
1.182 - QHandleType *pType = &m_Types[pHandle->type];
1.183 -
1.184 - bool dofree = false;
1.185 - if (pHandle->clone)
1.186 - {
1.187 - /* If we're a clone, decrease the parent reference count */
1.188 - QHandle *pMaster;
1.189 - unsigned int master;
1.190 -
1.191 - /* Note that if we ever have per-handle security, we would need to re-check
1.192 - * the access on this Handle. */
1.193 - master = pHandle->clone;
1.194 - pMaster = &m_Handles[master];
1.195 -
1.196 - /* Release the clone now */
1.197 - ReleasePrimHandle(index);
1.198 -
1.199 - /* Decrement the master's reference count */
1.200 - if (--pMaster->refcount == 0)
1.201 - {
1.202 - /* Type should be the same but do this anyway... */
1.203 - pType = &m_Types[pMaster->type];
1.204 - pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object);
1.205 - ReleasePrimHandle(master);
1.206 - }
1.207 - } else {
1.208 - /* Decrement, free if necessary */
1.209 - if (--pHandle->refcount == 0)
1.210 - {
1.211 - pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
1.212 - ReleasePrimHandle(index);
1.213 - } else {
1.214 - /* We must be cloned, so mark ourselves as freed */
1.215 - pHandle->set = HandleSet_Freed;
1.216 - }
1.217 - }
1.218 -
1.219 - return HandleError_None;
1.220 + return FreeHandle(pHandle, index);
1.221 }
1.222
1.223 HandleError HandleSystem::ReadHandle(Handle_t handle, HandleType_t type, const HandleSecurity *pSecurity, void **object)
1.224 @@ -597,60 +632,84 @@
1.225 return HandleError_None;
1.226 }
1.227
1.228 +void HandleSystem::UnlinkHandleFromOwner(QHandle *pHandle, unsigned int index)
1.229 +{
1.230 + /* Unlink us if necessary */
1.231 + unsigned int ident_index;
1.232 + if (IdentityHandle(pHandle->owner, &ident_index) != HandleError_None)
1.233 + {
1.234 + /* Uh-oh! */
1.235 + assert(pHandle->owner == 0);
1.236 + return;
1.237 + }
1.238 + /* Note that since 0 is an invalid handle, if any of these links are 0,
1.239 + * the data can still be set.
1.240 + */
1.241 + QHandle *pIdentity = &m_Handles[ident_index];
1.242 +
1.243 + /* Unlink case: We're the head AND tail node */
1.244 + if (index == pIdentity->ch_prev && index == pIdentity->ch_next)
1.245 + {
1.246 + pIdentity->ch_prev = 0;
1.247 + pIdentity->ch_next = 0;
1.248 + }
1.249 + /* Unlink case: We're the head node */
1.250 + else if (index == pIdentity->ch_prev) {
1.251 + /* Link us to the next in the chain */
1.252 + pIdentity->ch_prev = pHandle->ch_next;
1.253 + /* Patch up the previous link */
1.254 + m_Handles[pHandle->ch_next].ch_prev = 0;
1.255 + }
1.256 + /* Unlink case: We're the tail node */
1.257 + else if (index == pIdentity->ch_next) {
1.258 + /* Link us to the previous in the chain */
1.259 + pIdentity->ch_next = pHandle->ch_prev;
1.260 + /* Patch up the next link */
1.261 + m_Handles[pHandle->ch_prev].ch_next = 0;
1.262 + }
1.263 + /* Unlink case: We're in the middle! */
1.264 + else {
1.265 + /* Patch the forward reference */
1.266 + m_Handles[pHandle->ch_next].ch_prev = pHandle->ch_prev;
1.267 + /* Patch the backward reference */
1.268 + m_Handles[pHandle->ch_prev].ch_next = pHandle->ch_next;
1.269 + }
1.270 +
1.271 + /* Lastly, decrease the reference count */
1.272 + pIdentity->refcount--;
1.273 +}
1.274 +
1.275 void HandleSystem::ReleasePrimHandle(unsigned int index)
1.276 {
1.277 QHandle *pHandle = &m_Handles[index];
1.278 -
1.279 + HandleSet set = pHandle->set;
1.280 +
1.281 + if (pHandle->owner && (set != HandleSet_Identity))
1.282 + {
1.283 + UnlinkHandleFromOwner(pHandle, index);
1.284 + }
1.285 +
1.286 + /* Were we an identity ourself? */
1.287 + QHandle *pLocal;
1.288 + if (set == HandleSet_Identity)
1.289 + {
1.290 + /* Extra work to do. We need to find everything connected to this identity and release it. */
1.291 + unsigned int ch_index, old_index = 0;
1.292 + while ((ch_index = pHandle->ch_next) != 0)
1.293 + {
1.294 + pLocal = &m_Handles[ch_index];
1.295 +#if defined _DEBUG
1.296 + assert(old_index != ch_index);
1.297 + assert(pLocal->set == HandleSet_Used);
1.298 + old_index = ch_index;
1.299 +#endif
1.300 + FreeHandle(pLocal, ch_index);
1.301 + }
1.302 + }
1.303 +
1.304 pHandle->set = HandleSet_None;
1.305 m_Types[pHandle->type].opened--;
1.306 m_Handles[++m_FreeHandles].freeID = index;
1.307 -
1.308 - /* Unlink us if necessary */
1.309 - if (pHandle->owner)
1.310 - {
1.311 - unsigned int ident_index;
1.312 - if (IdentityHandle(pHandle->owner, &ident_index) != HandleError_None)
1.313 - {
1.314 - /* Uh-oh! */
1.315 - assert(pHandle->owner == 0);
1.316 - return;
1.317 - }
1.318 - /* Note that since 0 is an invalid handle, if any of these links are 0,
1.319 - * the data can still be set.
1.320 - */
1.321 - QHandle *pIdentity = &m_Handles[ident_index];
1.322 -
1.323 - /* Unlink case: We're the head AND tail node */
1.324 - if (index == pIdentity->ch_prev && index == pIdentity->ch_next)
1.325 - {
1.326 - pIdentity->ch_prev = 0;
1.327 - pIdentity->ch_next = 0;
1.328 - }
1.329 - /* Unlink case: We're the head node */
1.330 - else if (index == pIdentity->ch_prev) {
1.331 - /* Link us to the next in the chain */
1.332 - pIdentity->ch_prev = pHandle->ch_next;
1.333 - /* Patch up the previous link */
1.334 - m_Handles[pHandle->ch_next].ch_prev = 0;
1.335 - }
1.336 - /* Unlink case: We're the tail node */
1.337 - else if (index == pIdentity->ch_next) {
1.338 - /* Link us to the previous in the chain */
1.339 - pIdentity->ch_next = pHandle->ch_prev;
1.340 - /* Patch up the next link */
1.341 - m_Handles[pHandle->ch_prev].ch_next = 0;
1.342 - }
1.343 - /* Unlink case: We're in the middle! */
1.344 - else {
1.345 - /* Patch the forward reference */
1.346 - m_Handles[pHandle->ch_next].ch_prev = pHandle->ch_prev;
1.347 - /* Patch the backward reference */
1.348 - m_Handles[pHandle->ch_prev].ch_next = pHandle->ch_next;
1.349 - }
1.350 -
1.351 - /* Lastly, decrease the reference count */
1.352 - pIdentity->refcount--;
1.353 - }
1.354 }
1.355
1.356 bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t *ident)
1.357 @@ -737,19 +796,6 @@
1.358 return true;
1.359 }
1.360
1.361 -void HandleSystem::MarkHandleAsIdentity(Handle_t handle)
1.362 -{
1.363 - QHandle *pHandle;
1.364 - unsigned int index;
1.365 -
1.366 - if (GetHandle(handle, g_ShareSys.GetIdentRoot(), &pHandle, &index) != HandleError_None)
1.367 - {
1.368 - return;
1.369 - }
1.370 -
1.371 - pHandle->set = HandleSet_Identity;
1.372 -}
1.373 -
1.374 bool HandleSystem::InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess)
1.375 {
1.376 if (pTypeAccess)