core/systems/HandleSys.cpp
author Borja Ferrer <faluco@alliedmods.net>
Sun Jan 07 01:30:28 2007 +0000 (2007-01-07)
changeset 274 959c85596341
parent 262 de0e374ffa47
child 283 c3d54680969a
permissions -rw-r--r--
Added a bunch of new file natives.
Fixed possible corruption in snprintf when input buffer was bigger than output buffer and relaying on its retval.
Fixed all cases when the above situation happened.
Fixed _PrintToHL2Log not taking va_list in.
dvander@218
     1
#include "HandleSys.h"
dvander@229
     2
#include "ShareSys.h"
dvander@218
     3
#include "PluginSys.h"
dvander@222
     4
#include <assert.h>
dvander@218
     5
dvander@218
     6
HandleSystem g_HandleSys;
dvander@218
     7
dvander@229
     8
QHandle *ignore_handle;
dvander@229
     9
dvander@229
    10
inline HandleType_t TypeParent(HandleType_t type)
dvander@229
    11
{
dvander@229
    12
	return (type & ~HANDLESYS_SUBTYPE_MASK);
dvander@229
    13
}
dvander@229
    14
dvander@229
    15
inline HandleError IdentityHandle(IdentityToken_t *token, unsigned int *index)
dvander@229
    16
{
dvander@262
    17
	return g_HandleSys.GetHandle(token->ident, g_ShareSys.GetIdentRoot(), &ignore_handle, index);
dvander@229
    18
}
dvander@229
    19
dvander@218
    20
HandleSystem::HandleSystem()
dvander@218
    21
{
dvander@218
    22
	m_Handles = new QHandle[HANDLESYS_MAX_HANDLES + 1];
dvander@218
    23
	memset(m_Handles, 0, sizeof(QHandle) * (HANDLESYS_MAX_HANDLES + 1));
dvander@218
    24
dvander@218
    25
	m_Types = new QHandleType[HANDLESYS_TYPEARRAY_SIZE];
dvander@218
    26
	memset(m_Types, 0, sizeof(QHandleType) * HANDLESYS_TYPEARRAY_SIZE);
dvander@218
    27
dvander@218
    28
	m_TypeLookup = sm_trie_create();
dvander@218
    29
	m_strtab = new BaseStringTable(512);
dvander@218
    30
dvander@218
    31
	m_TypeTail = 0;
dvander@218
    32
}
dvander@218
    33
dvander@218
    34
HandleSystem::~HandleSystem()
dvander@218
    35
{
dvander@218
    36
	delete [] m_Handles;
dvander@218
    37
	delete [] m_Types;
dvander@218
    38
	sm_trie_destroy(m_TypeLookup);
dvander@218
    39
	delete m_strtab;
dvander@218
    40
}
dvander@218
    41
dvander@218
    42
dvander@262
    43
HandleType_t HandleSystem::CreateType(const char *name, 
dvander@262
    44
									  IHandleTypeDispatch *dispatch, 
dvander@262
    45
									  HandleType_t parent, 
dvander@262
    46
									  const TypeAccess *typeAccess, 
dvander@262
    47
									  const HandleAccess *hndlAccess, 
dvander@262
    48
									  IdentityToken_t *ident,
dvander@262
    49
									  HandleError *err)
dvander@218
    50
{
dvander@218
    51
	if (!dispatch)
dvander@218
    52
	{
dvander@262
    53
		if (err)
dvander@262
    54
		{
dvander@262
    55
			*err = HandleError_Parameter;
dvander@262
    56
		}
dvander@262
    57
		return 0;
dvander@262
    58
	}
dvander@262
    59
dvander@262
    60
	if (typeAccess && typeAccess->hsVersion > SMINTERFACE_HANDLESYSTEM_VERSION)
dvander@262
    61
	{
dvander@262
    62
		if (err)
dvander@262
    63
		{
dvander@262
    64
			*err = HandleError_Version;
dvander@262
    65
		}
dvander@262
    66
		return 0;
dvander@262
    67
	}
dvander@262
    68
dvander@262
    69
	if (hndlAccess && hndlAccess->hsVersion > SMINTERFACE_HANDLESYSTEM_VERSION)
dvander@262
    70
	{
dvander@262
    71
		if (err)
dvander@262
    72
		{
dvander@262
    73
			*err = HandleError_Version;
dvander@262
    74
		}
dvander@218
    75
		return 0;
dvander@218
    76
	}
dvander@218
    77
dvander@218
    78
	bool isChild = false;
dvander@218
    79
dvander@218
    80
	if (parent != 0)
dvander@218
    81
	{
dvander@218
    82
		isChild = true;
dvander@218
    83
		if (parent & HANDLESYS_SUBTYPE_MASK)
dvander@218
    84
		{
dvander@262
    85
			if (err)
dvander@262
    86
			{
dvander@262
    87
				*err = HandleError_NoInherit;
dvander@262
    88
			}
dvander@218
    89
			return 0;
dvander@218
    90
		}
dvander@218
    91
		if (parent >= HANDLESYS_TYPEARRAY_SIZE
dvander@262
    92
			|| m_Types[parent].dispatch == NULL)
dvander@218
    93
		{
dvander@262
    94
			if (err)
dvander@262
    95
			{
dvander@262
    96
				*err = HandleError_Parameter;
dvander@262
    97
			}
dvander@262
    98
			return 0;
dvander@262
    99
		}
dvander@262
   100
		if (m_Types[parent].typeSec.access[HTypeAccess_Inherit] == false
dvander@262
   101
			&& (m_Types[parent].typeSec.ident != ident))
dvander@262
   102
		{
dvander@262
   103
			if (err)
dvander@262
   104
			{
dvander@262
   105
				*err = HandleError_Access;
dvander@262
   106
			}
dvander@218
   107
			return 0;
dvander@218
   108
		}
dvander@218
   109
	}
dvander@218
   110
dvander@262
   111
	if (name && name[0] != '\0')
dvander@218
   112
	{
dvander@262
   113
		if (sm_trie_retrieve(m_TypeLookup, name, NULL))
dvander@218
   114
		{
dvander@262
   115
			if (err)
dvander@262
   116
			{
dvander@262
   117
				*err = HandleError_Parameter;
dvander@262
   118
			}
dvander@262
   119
			return 0;
dvander@218
   120
		}
dvander@218
   121
	}
dvander@218
   122
dvander@218
   123
	unsigned int index;
dvander@218
   124
dvander@218
   125
	if (isChild)
dvander@218
   126
	{
dvander@218
   127
		QHandleType *pParent = &m_Types[parent];
dvander@218
   128
		if (pParent->children >= HANDLESYS_MAX_SUBTYPES)
dvander@218
   129
		{
dvander@262
   130
			if (err)
dvander@262
   131
			{
dvander@262
   132
				*err = HandleError_Limit;
dvander@262
   133
			}
dvander@218
   134
			return 0;
dvander@218
   135
		}
dvander@218
   136
		index = 0;
dvander@218
   137
		for (unsigned int i=1; i<=HANDLESYS_MAX_SUBTYPES; i++)
dvander@218
   138
		{
dvander@218
   139
			if (m_Types[parent + i].dispatch == NULL)
dvander@218
   140
			{
dvander@218
   141
				index = parent + i;
dvander@218
   142
				break;
dvander@218
   143
			}
dvander@218
   144
		}
dvander@218
   145
		if (!index)
dvander@218
   146
		{
dvander@262
   147
			if (err)
dvander@262
   148
			{
dvander@262
   149
				*err = HandleError_Limit;
dvander@262
   150
			}
dvander@218
   151
			return 0;
dvander@218
   152
		}
dvander@218
   153
		pParent->children++;
dvander@218
   154
	} else {
dvander@218
   155
		if (m_FreeTypes == 0)
dvander@218
   156
		{
dvander@218
   157
			/* Reserve another index */
dvander@218
   158
			if (m_TypeTail >= HANDLESYS_TYPEARRAY_SIZE)
dvander@218
   159
			{
dvander@262
   160
				if (err)
dvander@262
   161
				{
dvander@262
   162
					*err = HandleError_Limit;
dvander@262
   163
				}
dvander@218
   164
				return 0;
dvander@218
   165
			} else {
dvander@218
   166
				m_TypeTail += (HANDLESYS_MAX_SUBTYPES + 1);
dvander@218
   167
				index = m_TypeTail;
dvander@218
   168
			}
dvander@218
   169
		} else {
dvander@218
   170
			/* The "free array" is compacted into the normal array for easiness */
dvander@218
   171
			index = m_Types[m_FreeTypes--].freeID;
dvander@218
   172
		}
dvander@218
   173
	}
dvander@218
   174
dvander@218
   175
	QHandleType *pType = &m_Types[index];
dvander@218
   176
	
dvander@218
   177
	pType->dispatch = dispatch;
dvander@218
   178
	if (name && name[0] != '\0')
dvander@218
   179
	{
dvander@218
   180
		pType->nameIdx = m_strtab->AddString(name);
dvander@218
   181
		sm_trie_insert(m_TypeLookup, name, (void *)pType);
dvander@218
   182
	} else {
dvander@218
   183
		pType->nameIdx = -1;
dvander@218
   184
	}
dvander@262
   185
dvander@218
   186
	pType->opened = 0;
dvander@218
   187
dvander@262
   188
	if (typeAccess)
dvander@262
   189
	{
dvander@262
   190
		pType->typeSec = *typeAccess;
dvander@262
   191
	} else {
dvander@262
   192
		InitAccessDefaults(&pType->typeSec, NULL);
dvander@262
   193
		pType->typeSec.ident = ident;
dvander@262
   194
	}
dvander@262
   195
dvander@262
   196
	if (hndlAccess)
dvander@262
   197
	{
dvander@262
   198
		pType->hndlSec = *hndlAccess;
dvander@262
   199
	} else {
dvander@262
   200
		InitAccessDefaults(NULL, &pType->hndlSec);
dvander@262
   201
	}
dvander@262
   202
dvander@218
   203
	if (!isChild)
dvander@218
   204
	{
dvander@218
   205
		pType->children = 0;
dvander@218
   206
	}
dvander@218
   207
dvander@218
   208
	return index;
dvander@218
   209
}
dvander@218
   210
dvander@218
   211
bool HandleSystem::FindHandleType(const char *name, HandleType_t *type)
dvander@218
   212
{
dvander@218
   213
	QHandleType *_type;
dvander@218
   214
dvander@218
   215
	if (!sm_trie_retrieve(m_TypeLookup, name, (void **)&_type))
dvander@218
   216
	{
dvander@218
   217
		return false;
dvander@218
   218
	}
dvander@218
   219
dvander@218
   220
	unsigned int offset = _type - m_Types;
dvander@218
   221
dvander@218
   222
	if (type)
dvander@218
   223
	{
dvander@218
   224
		*type = offset;
dvander@218
   225
	}
dvander@218
   226
dvander@218
   227
	return true;
dvander@218
   228
}
dvander@218
   229
dvander@222
   230
HandleError HandleSystem::MakePrimHandle(HandleType_t type, 
dvander@222
   231
						   QHandle **in_pHandle, 
dvander@222
   232
						   unsigned int *in_index, 
dvander@229
   233
						   Handle_t *in_handle,
dvander@229
   234
						   IdentityToken_t *owner)
dvander@222
   235
{
dvander@229
   236
	unsigned int owner_index = 0;
dvander@229
   237
dvander@229
   238
	if (owner && (IdentityHandle(owner, &owner_index) != HandleError_None))
dvander@229
   239
	{
dvander@229
   240
		return HandleError_Identity;
dvander@229
   241
	}
dvander@229
   242
dvander@222
   243
	unsigned int handle;
dvander@222
   244
	if (m_FreeHandles == 0)
dvander@222
   245
	{
dvander@222
   246
		if (m_HandleTail >= HANDLESYS_MAX_HANDLES)
dvander@222
   247
		{
dvander@222
   248
			return HandleError_Limit;;
dvander@222
   249
		}
dvander@222
   250
		handle = ++m_HandleTail;
dvander@222
   251
	} else {
dvander@222
   252
		handle = m_Handles[m_FreeHandles--].freeID;
dvander@222
   253
	}
dvander@222
   254
dvander@222
   255
	QHandle *pHandle = &m_Handles[handle];
dvander@222
   256
	
dvander@222
   257
	assert(pHandle->set == false);
dvander@222
   258
dvander@222
   259
	if (++m_HSerial >= HANDLESYS_MAX_SERIALS)
dvander@222
   260
	{
dvander@222
   261
		m_HSerial = 1;
dvander@222
   262
	}
dvander@222
   263
dvander@222
   264
	/* Set essential information */
dvander@229
   265
	pHandle->set = HandleSet_Used;;
dvander@222
   266
	pHandle->refcount = 1;
dvander@222
   267
	pHandle->type = type;
dvander@222
   268
	pHandle->serial = m_HSerial;
dvander@229
   269
	pHandle->owner = owner;
dvander@229
   270
	pHandle->ch_next = 0;
dvander@222
   271
dvander@222
   272
	/* Create the hash value */
dvander@222
   273
	Handle_t hash = pHandle->serial;
dvander@222
   274
	hash <<= 16;
dvander@222
   275
	hash |= handle;
dvander@222
   276
dvander@222
   277
	/* Add a reference count to the type */
dvander@222
   278
	m_Types[type].opened++;
dvander@222
   279
dvander@222
   280
	/* Output */
dvander@222
   281
	*in_pHandle = pHandle;
dvander@222
   282
	*in_index = handle;
dvander@222
   283
	*in_handle = hash;
dvander@222
   284
dvander@229
   285
	/* Decode the identity token */
dvander@229
   286
	if (owner)
dvander@229
   287
	{
dvander@229
   288
		QHandle *pIdentity = &m_Handles[owner_index];
dvander@229
   289
		if (pIdentity->ch_prev == 0)
dvander@229
   290
		{
dvander@229
   291
			pIdentity->ch_prev = handle;
dvander@229
   292
			pIdentity->ch_next = handle;
dvander@229
   293
			pHandle->ch_prev = 0;
dvander@229
   294
		} else {
dvander@229
   295
			/* Link previous node to us (forward) */
dvander@229
   296
			m_Handles[pIdentity->ch_next].ch_next = handle;
dvander@229
   297
			/* Link us to previous node (backwards) */
dvander@229
   298
			pHandle->ch_prev = pIdentity->ch_next;
dvander@229
   299
			/* Set new tail */
dvander@229
   300
			pIdentity->ch_next = handle;
dvander@229
   301
		}
dvander@229
   302
		pIdentity->refcount++;
dvander@229
   303
	} else {
dvander@229
   304
		pHandle->ch_prev = 0;
dvander@229
   305
	}
dvander@229
   306
dvander@222
   307
	return HandleError_None;
dvander@222
   308
}
dvander@222
   309
dvander@229
   310
void HandleSystem::SetTypeSecurityOwner(HandleType_t type, IdentityToken_t *pToken)
dvander@229
   311
{
dvander@229
   312
	if (!type
dvander@229
   313
		|| type >= HANDLESYS_TYPEARRAY_SIZE
dvander@229
   314
		|| m_Types[type].dispatch == NULL)
dvander@229
   315
	{
dvander@229
   316
		return;
dvander@229
   317
	}
dvander@229
   318
dvander@262
   319
	m_Types[type].typeSec.ident = pToken;
dvander@229
   320
}
dvander@229
   321
dvander@262
   322
Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityToken_t *owner, IdentityToken_t *ident, HandleError *err)
dvander@218
   323
{
dvander@218
   324
	if (!type 
dvander@218
   325
		|| type >= HANDLESYS_TYPEARRAY_SIZE
dvander@218
   326
		|| m_Types[type].dispatch == NULL)
dvander@218
   327
	{
dvander@262
   328
		if (err)
dvander@262
   329
		{
dvander@262
   330
			*err = HandleError_Parameter;
dvander@262
   331
		}
dvander@218
   332
		return 0;
dvander@218
   333
	}
dvander@218
   334
dvander@262
   335
	/* Check to see if we're allowed to create this handle type */
dvander@218
   336
	QHandleType *pType = &m_Types[type];
dvander@262
   337
	if (!pType->typeSec.access[HTypeAccess_Create]
dvander@262
   338
		&& (!pType->typeSec.ident
dvander@262
   339
			|| pType->typeSec.ident != ident))
dvander@218
   340
	{
dvander@262
   341
		if (err)
dvander@262
   342
		{
dvander@262
   343
			*err = HandleError_Access;
dvander@262
   344
		}
dvander@218
   345
		return 0;
dvander@218
   346
	}
dvander@218
   347
dvander@222
   348
	unsigned int index;
dvander@222
   349
	Handle_t handle;
dvander@222
   350
	QHandle *pHandle;
dvander@262
   351
	HandleError _err;
dvander@222
   352
dvander@262
   353
	if ((_err=MakePrimHandle(type, &pHandle, &index, &handle, owner)) != HandleError_None)
dvander@218
   354
	{
dvander@262
   355
		if (err)
dvander@262
   356
		{
dvander@262
   357
			*err = _err;
dvander@262
   358
		}
dvander@222
   359
		return 0;
dvander@218
   360
	}
dvander@218
   361
dvander@218
   362
	pHandle->object = object;
dvander@222
   363
	pHandle->clone = 0;
dvander@218
   364
dvander@222
   365
	return handle;
dvander@218
   366
}
dvander@218
   367
dvander@229
   368
bool HandleSystem::TypeCheck(HandleType_t intype, HandleType_t outtype)
dvander@229
   369
{
dvander@229
   370
	/* Check the type inheritance */
dvander@229
   371
	if (intype & HANDLESYS_SUBTYPE_MASK)
dvander@229
   372
	{
dvander@229
   373
		if (intype != outtype
dvander@229
   374
			&& (TypeParent(intype) != TypeParent(outtype)))
dvander@229
   375
		{
dvander@229
   376
			return false;
dvander@229
   377
		}
dvander@229
   378
	} else {
dvander@229
   379
		if (intype != outtype)
dvander@229
   380
		{
dvander@229
   381
			return false;
dvander@229
   382
		}
dvander@229
   383
	}
dvander@229
   384
dvander@229
   385
	return true;
dvander@229
   386
}
dvander@229
   387
dvander@222
   388
HandleError HandleSystem::GetHandle(Handle_t handle,
dvander@229
   389
									IdentityToken_t *ident, 
dvander@222
   390
									QHandle **in_pHandle, 
dvander@222
   391
									unsigned int *in_index,
dvander@259
   392
									bool ignoreFree)
dvander@218
   393
{
dvander@218
   394
	unsigned int serial = (handle >> 16);
dvander@218
   395
	unsigned int index = (handle & HANDLESYS_HANDLE_MASK);
dvander@218
   396
dvander@218
   397
	if (index == 0 || index == 0xFFFF)
dvander@218
   398
	{
dvander@218
   399
		return HandleError_Index;
dvander@218
   400
	}
dvander@218
   401
dvander@218
   402
	QHandle *pHandle = &m_Handles[index];
dvander@218
   403
	QHandleType *pType = &m_Types[pHandle->type];
dvander@218
   404
dvander@259
   405
	if (!pHandle->set
dvander@259
   406
		|| (pHandle->set == HandleSet_Freed && !ignoreFree))
dvander@218
   407
	{
dvander@218
   408
		return HandleError_Freed;
dvander@229
   409
	} else if (pHandle->set == HandleSet_Identity
dvander@229
   410
			   && ident != g_ShareSys.GetIdentRoot())
dvander@229
   411
	{
dvander@229
   412
		/* Only IdentityHandle() can read this! */
dvander@229
   413
		return HandleError_Identity;
dvander@218
   414
	}
dvander@218
   415
	if (pHandle->serial != serial)
dvander@218
   416
	{
dvander@218
   417
		return HandleError_Changed;
dvander@218
   418
	}
dvander@218
   419
dvander@222
   420
	*in_pHandle = pHandle;
dvander@222
   421
	*in_index = index;
dvander@222
   422
dvander@222
   423
	return HandleError_None;
dvander@222
   424
}
dvander@222
   425
dvander@262
   426
bool HandleSystem::CheckAccess(QHandle *pHandle, HandleAccessRight right, const HandleSecurity *pSecurity)
dvander@262
   427
{
dvander@262
   428
	QHandleType *pType = &m_Types[pHandle->type];
dvander@262
   429
	unsigned int access = pType->hndlSec.access[right];
dvander@262
   430
dvander@262
   431
	/* Check if the type's identity matches */
dvander@262
   432
	if (access & HANDLE_RESTRICT_IDENTITY)
dvander@262
   433
	{
dvander@262
   434
		IdentityToken_t *owner = pType->typeSec.ident;
dvander@262
   435
		if (!owner
dvander@262
   436
			|| (!pSecurity || pSecurity->pIdentity != owner))
dvander@262
   437
		{
dvander@262
   438
			return false;
dvander@262
   439
		}
dvander@262
   440
	}
dvander@262
   441
dvander@262
   442
	/* Check if the owner is allowed */
dvander@262
   443
	if (access & HANDLE_RESTRICT_OWNER)
dvander@262
   444
	{
dvander@262
   445
		IdentityToken_t *owner = pHandle->owner;
dvander@262
   446
		if (owner
dvander@262
   447
			&& (!pSecurity || pSecurity->pOwner != owner))
dvander@262
   448
		{
dvander@262
   449
			return false;
dvander@262
   450
		}
dvander@262
   451
	}
dvander@262
   452
dvander@262
   453
	return true;
dvander@262
   454
}
dvander@262
   455
dvander@262
   456
HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *newhandle, IdentityToken_t *newOwner, const HandleSecurity *pSecurity)
dvander@222
   457
{
dvander@222
   458
	HandleError err;
dvander@222
   459
	QHandle *pHandle;
dvander@222
   460
	unsigned int index;
dvander@262
   461
	IdentityToken_t *ident = pSecurity ? pSecurity->pIdentity : NULL;
dvander@222
   462
dvander@262
   463
	if ((err=GetHandle(handle, ident, &pHandle, &index)) != HandleError_None)
dvander@222
   464
	{
dvander@222
   465
		return err;
dvander@222
   466
	}
dvander@222
   467
dvander@259
   468
	/* Identities cannot be cloned */
dvander@259
   469
	if (pHandle->set == HandleSet_Identity)
dvander@259
   470
	{
dvander@259
   471
		return HandleError_Identity;
dvander@259
   472
	}
dvander@259
   473
dvander@262
   474
	/* Check if the handle can be cloned */
dvander@262
   475
	if (!CheckAccess(pHandle, HandleAccess_Clone, pSecurity))
dvander@262
   476
	{
dvander@262
   477
		return HandleError_Access;
dvander@262
   478
	}
dvander@222
   479
dvander@222
   480
	/* Get a new Handle ID */
dvander@222
   481
	unsigned int new_index;
dvander@222
   482
	QHandle *pNewHandle;
dvander@222
   483
	Handle_t new_handle;
dvander@222
   484
dvander@262
   485
	if ((err=MakePrimHandle(pHandle->type, &pNewHandle, &new_index, &new_handle, newOwner)) != HandleError_None)
dvander@222
   486
	{
dvander@222
   487
		return err;
dvander@222
   488
	}
dvander@222
   489
dvander@262
   490
	pNewHandle->clone = index;
dvander@259
   491
	pHandle->refcount++;
dvander@222
   492
dvander@262
   493
	*newhandle = new_handle;
dvander@222
   494
dvander@222
   495
	return HandleError_None;
dvander@222
   496
}
dvander@222
   497
dvander@262
   498
HandleError HandleSystem::FreeHandle(Handle_t handle, const HandleSecurity *pSecurity)
dvander@222
   499
{
dvander@222
   500
	unsigned int index;
dvander@222
   501
	QHandle *pHandle;
dvander@222
   502
	HandleError err;
dvander@262
   503
	IdentityToken_t *ident = pSecurity ? pSecurity->pIdentity : NULL;
dvander@222
   504
dvander@262
   505
	if ((err=GetHandle(handle, ident, &pHandle, &index)) != HandleError_None)
dvander@222
   506
	{
dvander@222
   507
		return err;
dvander@222
   508
	}
dvander@222
   509
dvander@262
   510
	if (!CheckAccess(pHandle, HandleAccess_Delete, pSecurity))
dvander@259
   511
	{
dvander@259
   512
		return HandleError_Access;
dvander@259
   513
	}
dvander@259
   514
dvander@262
   515
	QHandleType *pType = &m_Types[pHandle->type];
dvander@262
   516
dvander@222
   517
	bool dofree = false;
dvander@222
   518
	if (pHandle->clone)
dvander@222
   519
	{
dvander@259
   520
		/* If we're a clone, decrease the parent reference count */
dvander@259
   521
		QHandle *pMaster;
dvander@259
   522
		unsigned int master;
dvander@259
   523
dvander@262
   524
		/* Note that if we ever have per-handle security, we would need to re-check
dvander@262
   525
		 * the access on this Handle. */
dvander@262
   526
		master = pHandle->clone;
dvander@262
   527
		pMaster = &m_Handles[master];
dvander@259
   528
dvander@259
   529
		/* Release the clone now */
dvander@259
   530
		ReleasePrimHandle(index);
dvander@259
   531
dvander@259
   532
		/* Decrement the master's reference count */
dvander@259
   533
		if (--pMaster->refcount == 0)
dvander@222
   534
		{
dvander@259
   535
			/* Type should be the same but do this anyway... */
dvander@259
   536
			pType = &m_Types[pMaster->type];
dvander@259
   537
			pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object);
dvander@259
   538
			ReleasePrimHandle(master);
dvander@222
   539
		}
dvander@222
   540
	} else {
dvander@259
   541
		/* Decrement, free if necessary */
dvander@222
   542
		if (--pHandle->refcount == 0)
dvander@222
   543
		{
dvander@222
   544
			pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
dvander@259
   545
			ReleasePrimHandle(index);
dvander@259
   546
		} else {
dvander@259
   547
			/* We must be cloned, so mark ourselves as freed */
dvander@259
   548
			pHandle->set = HandleSet_Freed;
dvander@222
   549
		}
dvander@222
   550
	}
dvander@222
   551
dvander@218
   552
	return HandleError_None;
dvander@218
   553
}
dvander@218
   554
dvander@262
   555
HandleError HandleSystem::ReadHandle(Handle_t handle, HandleType_t type, const HandleSecurity *pSecurity, void **object)
dvander@218
   556
{
dvander@222
   557
	unsigned int index;
dvander@222
   558
	QHandle *pHandle;
dvander@222
   559
	HandleError err;
dvander@262
   560
	IdentityToken_t *ident = pSecurity ? pSecurity->pIdentity : NULL;
dvander@218
   561
dvander@262
   562
	if ((err=GetHandle(handle, ident, &pHandle, &index)) != HandleError_None)
dvander@218
   563
	{
dvander@222
   564
		return err;
dvander@218
   565
	}
dvander@218
   566
dvander@262
   567
	if (!CheckAccess(pHandle, HandleAccess_Read, pSecurity))
dvander@262
   568
	{
dvander@262
   569
		return HandleError_Access;
dvander@262
   570
	}
dvander@262
   571
dvander@218
   572
	/* Check the type inheritance */
dvander@218
   573
	if (pHandle->type & HANDLESYS_SUBTYPE_MASK)
dvander@218
   574
	{
dvander@218
   575
		if (pHandle->type != type
dvander@218
   576
			&& (TypeParent(pHandle->type) != TypeParent(type)))
dvander@218
   577
		{
dvander@218
   578
			return HandleError_Type;
dvander@218
   579
		}
dvander@247
   580
	} else if (type) {
dvander@218
   581
		if (pHandle->type != type)
dvander@218
   582
		{
dvander@218
   583
			return HandleError_Type;
dvander@218
   584
		}
dvander@218
   585
	}
dvander@218
   586
dvander@218
   587
	if (object)
dvander@218
   588
	{
dvander@222
   589
		/* if we're a clone, the rules change - object is ONLY in our reference */
dvander@222
   590
		if (pHandle->clone)
dvander@222
   591
		{
dvander@262
   592
			pHandle = &m_Handles[pHandle->clone];
dvander@222
   593
		}
dvander@218
   594
		*object = pHandle->object;
dvander@218
   595
	}
dvander@218
   596
dvander@218
   597
	return HandleError_None;
dvander@218
   598
}
dvander@218
   599
dvander@222
   600
void HandleSystem::ReleasePrimHandle(unsigned int index)
dvander@222
   601
{
dvander@222
   602
	QHandle *pHandle = &m_Handles[index];
dvander@222
   603
	
dvander@229
   604
	pHandle->set = HandleSet_None;
dvander@222
   605
	m_Types[pHandle->type].opened--;
dvander@222
   606
	m_Handles[++m_FreeHandles].freeID = index;
dvander@229
   607
dvander@229
   608
	/* Unlink us if necessary */
dvander@229
   609
	if (pHandle->owner)
dvander@229
   610
	{
dvander@229
   611
		unsigned int ident_index;
dvander@229
   612
		if (IdentityHandle(pHandle->owner, &ident_index) != HandleError_None)
dvander@229
   613
		{
dvander@229
   614
			/* Uh-oh! */
dvander@229
   615
			assert(pHandle->owner == 0);
dvander@229
   616
			return;
dvander@229
   617
		}
dvander@229
   618
		/* Note that since 0 is an invalid handle, if any of these links are 0,
dvander@229
   619
		 * the data can still be set.
dvander@229
   620
		 */
dvander@229
   621
		QHandle *pIdentity = &m_Handles[ident_index];
dvander@229
   622
dvander@229
   623
		/* Unlink case: We're the head AND tail node */
dvander@229
   624
		if (index == pIdentity->ch_prev && index == pIdentity->ch_next)
dvander@229
   625
		{
dvander@229
   626
			pIdentity->ch_prev = 0;
dvander@229
   627
			pIdentity->ch_next = 0;
dvander@229
   628
		}
dvander@229
   629
		/* Unlink case: We're the head node */
dvander@229
   630
		else if (index == pIdentity->ch_prev) {
dvander@229
   631
			/* Link us to the next in the chain */
dvander@229
   632
			pIdentity->ch_prev = pHandle->ch_next;
dvander@229
   633
			/* Patch up the previous link */
dvander@229
   634
			m_Handles[pHandle->ch_next].ch_prev = 0;
dvander@229
   635
		}
dvander@229
   636
		/* Unlink case: We're the tail node */
dvander@229
   637
		else if (index == pIdentity->ch_next) {
dvander@229
   638
			/* Link us to the previous in the chain */
dvander@229
   639
			pIdentity->ch_next = pHandle->ch_prev;
dvander@229
   640
			/* Patch up the next link */
dvander@229
   641
			m_Handles[pHandle->ch_prev].ch_next = 0;
dvander@229
   642
		}
dvander@229
   643
		/* Unlink case: We're in the middle! */
dvander@229
   644
		else {
dvander@229
   645
			/* Patch the forward reference */
dvander@229
   646
			m_Handles[pHandle->ch_next].ch_prev = pHandle->ch_prev;
dvander@229
   647
			/* Patch the backward reference */
dvander@229
   648
			m_Handles[pHandle->ch_prev].ch_next = pHandle->ch_next;
dvander@229
   649
		}
dvander@229
   650
dvander@229
   651
		/* Lastly, decrease the reference count */
dvander@229
   652
		pIdentity->refcount--;
dvander@229
   653
	}
dvander@222
   654
}
dvander@222
   655
dvander@229
   656
bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t *ident)
dvander@218
   657
{
dvander@218
   658
	if (type == 0 || type >= HANDLESYS_TYPEARRAY_SIZE)
dvander@218
   659
	{
dvander@218
   660
		return false;
dvander@218
   661
	}
dvander@218
   662
dvander@218
   663
	QHandleType *pType = &m_Types[type];
dvander@218
   664
dvander@262
   665
	if (pType->typeSec.ident
dvander@262
   666
		&& pType->typeSec.ident != ident)
dvander@218
   667
	{
dvander@218
   668
		return false;
dvander@218
   669
	}
dvander@218
   670
dvander@218
   671
	if (pType->dispatch == NULL)
dvander@218
   672
	{
dvander@218
   673
		return false;
dvander@218
   674
	}
dvander@218
   675
dvander@218
   676
	/* Remove children if we have to */
dvander@218
   677
	if (!(type & HANDLESYS_SUBTYPE_MASK))
dvander@218
   678
	{
dvander@218
   679
		QHandleType *childType;
dvander@218
   680
		for (unsigned int i=1; i<=HANDLESYS_MAX_SUBTYPES; i++)
dvander@218
   681
		{
dvander@218
   682
			childType = &m_Types[type + i];
dvander@218
   683
			if (childType->dispatch)
dvander@218
   684
			{
dvander@262
   685
				RemoveType(type + i, childType->typeSec.ident);
dvander@218
   686
			}
dvander@218
   687
		}
dvander@218
   688
		/* Link us into the free chain */
dvander@218
   689
		m_Types[++m_FreeTypes].freeID = type;
dvander@218
   690
	}
dvander@218
   691
dvander@218
   692
	/* Invalidate the type now */
dvander@218
   693
	IHandleTypeDispatch *dispatch = pType->dispatch;
dvander@218
   694
	pType->dispatch = NULL;
dvander@218
   695
dvander@218
   696
	/* Make sure nothing is using this type. */
dvander@218
   697
	if (pType->opened)
dvander@218
   698
	{
dvander@218
   699
		QHandle *pHandle;
dvander@222
   700
		for (unsigned int i=1; i<m_HandleTail; i++)
dvander@218
   701
		{
dvander@218
   702
			pHandle = &m_Handles[i];
dvander@218
   703
			if (!pHandle->set || pHandle->type != type)
dvander@218
   704
			{
dvander@218
   705
				continue;
dvander@218
   706
			}
dvander@222
   707
			if (pHandle->clone)
dvander@222
   708
			{
dvander@222
   709
				/* Get parent */
dvander@222
   710
				QHandle *pOther = &m_Handles[pHandle->clone];
dvander@222
   711
				if (--pOther->refcount == 0)
dvander@222
   712
				{
dvander@222
   713
					/* Free! */
dvander@222
   714
					dispatch->OnHandleDestroy(type, pOther->object);
dvander@222
   715
					ReleasePrimHandle(pHandle->clone);
dvander@222
   716
				}
dvander@222
   717
				/* Unlink ourselves since we don't have a reference count */
dvander@222
   718
				ReleasePrimHandle(i);
dvander@222
   719
			} else {
dvander@222
   720
				/* If it's not a clone, we still have to check the reference count.
dvander@222
   721
				 * Either way, we'll be destroyed eventually because the handle types do not change.
dvander@222
   722
				 */
dvander@222
   723
				if (--pHandle->refcount == 0)
dvander@222
   724
				{
dvander@222
   725
					/* Free! */
dvander@222
   726
					dispatch->OnHandleDestroy(type, pHandle->object);
dvander@222
   727
					ReleasePrimHandle(i);
dvander@222
   728
				}
dvander@222
   729
			}
dvander@222
   730
			if (pType->opened == 0)
dvander@218
   731
			{
dvander@218
   732
				break;
dvander@218
   733
			}
dvander@218
   734
		}
dvander@218
   735
	}
dvander@218
   736
dvander@218
   737
	return true;
dvander@218
   738
}
dvander@229
   739
dvander@229
   740
void HandleSystem::MarkHandleAsIdentity(Handle_t handle)
dvander@229
   741
{
dvander@229
   742
	QHandle *pHandle;
dvander@229
   743
	unsigned int index;
dvander@229
   744
dvander@262
   745
	if (GetHandle(handle, g_ShareSys.GetIdentRoot(), &pHandle, &index) != HandleError_None)
dvander@229
   746
	{
dvander@229
   747
		return;
dvander@229
   748
	}
dvander@229
   749
dvander@229
   750
	pHandle->set = HandleSet_Identity;
dvander@229
   751
}
dvander@262
   752
dvander@262
   753
bool HandleSystem::InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess)
dvander@262
   754
{
dvander@262
   755
	if (pTypeAccess)
dvander@262
   756
	{
dvander@262
   757
		if (pTypeAccess->hsVersion > SMINTERFACE_HANDLESYSTEM_VERSION)
dvander@262
   758
		{
dvander@262
   759
			return false;
dvander@262
   760
		}
dvander@262
   761
		pTypeAccess->access[HTypeAccess_Create] = false;
dvander@262
   762
		pTypeAccess->access[HTypeAccess_Inherit] = false;
dvander@262
   763
		pTypeAccess->ident = NULL;
dvander@262
   764
	}
dvander@262
   765
dvander@262
   766
	if (pHandleAccess)
dvander@262
   767
	{
dvander@262
   768
		if (pHandleAccess->hsVersion > SMINTERFACE_HANDLESYSTEM_VERSION)
dvander@262
   769
		{
dvander@262
   770
			return false;
dvander@262
   771
		}
dvander@262
   772
dvander@262
   773
		pHandleAccess->access[HandleAccess_Clone] = 0;
dvander@262
   774
		pHandleAccess->access[HandleAccess_Delete] = HANDLE_RESTRICT_OWNER;
dvander@262
   775
		pHandleAccess->access[HandleAccess_Read] = HANDLE_RESTRICT_IDENTITY;
dvander@262
   776
	}
dvander@262
   777
dvander@262
   778
	return true;
dvander@262
   779
}