core/systems/HandleSys.cpp
changeset 259 ca9b124a2544
parent 252 ce166c465bad
child 262 de0e374ffa47
     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  	}