core/systems/HandleSys.h
author David Anderson <dvander@alliedmods.net>
Mon Feb 26 02:47:03 2007 +0000 (2007-02-26)
changeset 528 ea61550036b5
parent 487 3410298035cb
child 653 ef60870067ff
permissions -rw-r--r--
added per-handle security (untested)
     1 /**
     2  * ===============================================================
     3  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     4  * ===============================================================
     5  *
     6  * This file is not open source and may not be copied without explicit
     7  * written permission of AlliedModders LLC.  This file may not be redistributed 
     8  * in whole or significant part.
     9  * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
    10  *
    11  * Version: $Id$
    12  */
    13 
    14 #ifndef _INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
    15 #define _INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
    16 
    17 #include <IHandleSys.h>
    18 #include "sm_globals.h"
    19 #include "sm_trie.h"
    20 #include "sourcemod.h"
    21 #include "sm_memtable.h"
    22 
    23 #define HANDLESYS_MAX_HANDLES		(1<<14)
    24 #define HANDLESYS_MAX_TYPES			(1<<9)
    25 #define HANDLESYS_MAX_SUBTYPES		0xF
    26 #define HANDLESYS_SUBTYPE_MASK		0xF
    27 #define HANDLESYS_TYPEARRAY_SIZE	(HANDLESYS_MAX_TYPES * (HANDLESYS_MAX_SUBTYPES + 1))
    28 #define HANDLESYS_MAX_SERIALS		0xFFFF
    29 #define HANDLESYS_SERIAL_MASK		0xFFFF0000
    30 #define HANDLESYS_HANDLE_MASK		0x0000FFFF
    31 
    32 /**
    33  *   The QHandle is a nasty structure that compacts the handle system into a big vector.
    34  * The members of the vector each encapsulate one Handle, however, they also act as nodes
    35  * in an inlined linked list and an inlined vector.
    36  *
    37  *   The first of these lists is the 'freeID' list.  Each node from 1 to N (where N
    38  * is the number of free nodes) has a 'freeID' that specifies a free Handle ID.  This
    39  * is a quick hack to get around allocating a second base vector.
    40  *
    41  *   The second vector is the identity linked list.  An identity has its own handle, so
    42  * these handles are used as sentinel nodes for index linking.  They point to the first and last
    43  * index into the handle array.  Each subsequent Handle who is owned by that identity is mapped into
    44  * that list.  This lets owning identities be unloaded in O(n) time.
    45  *
    46  *   Eventually, there may be a third list for type chains.
    47  */
    48 
    49 enum HandleSet
    50 {
    51 	HandleSet_None = 0,
    52 	HandleSet_Used,			/* The Handle is in use */
    53 	HandleSet_Freed,		/* The "master" Handle of a clone chain is freed */
    54 	HandleSet_Identity,		/* The Handle is a special identity */
    55 };
    56 
    57 struct QHandle
    58 {
    59 	HandleType_t type;			/* Handle type */
    60 	void *object;				/* Unmaintained object pointer */
    61 	IdentityToken_t *owner;		/* Identity of object which owns this */
    62 	unsigned int serial;		/* Serial no. for sanity checking */
    63 	unsigned int refcount;		/* Reference count for safe destruction */
    64 	unsigned int clone;			/* If non-zero, this is our cloned parent index */
    65 	HandleSet set;				/* Information about the handle's state */
    66 	bool access_special;		/* Whether or not access rules are special or type-derived */
    67 	HandleAccess sec;			/* Security rules */
    68 	/* The following variables are unrelated to the Handle array, and used 
    69 	 * as an inlined chain of information */
    70 	unsigned int freeID;		/* ID of a free handle in the free handle chain */
    71 	/* Indexes into the handle array for owner membership.
    72 	 * For identity roots, these are treated as the head/tail. */
    73 	unsigned int ch_prev;		/* chained previous handle */
    74 	unsigned int ch_next;		/* chained next handle */
    75 };
    76 
    77 struct QHandleType
    78 {
    79 	IHandleTypeDispatch *dispatch;
    80 	unsigned int freeID;
    81 	unsigned int children;
    82 	TypeAccess typeSec;
    83 	HandleAccess hndlSec;
    84 	unsigned int opened;
    85 	int nameIdx;
    86 };
    87 
    88 class HandleSystem : 
    89 	public IHandleSys
    90 {
    91 	friend HandleError IdentityHandle(IdentityToken_t *token, unsigned int *index);
    92 	friend class ShareSystem;
    93 public:
    94 	HandleSystem();
    95 	~HandleSystem();
    96 public: //IHandleSystem
    97 
    98 	HandleType_t CreateType(const char *name,
    99 		IHandleTypeDispatch *dispatch,
   100 		HandleType_t parent,
   101 		const TypeAccess *typeAccess,
   102 		const HandleAccess *hndlAccess,
   103 		IdentityToken_t *ident,
   104 		HandleError *err);
   105 
   106 	bool RemoveType(HandleType_t type, IdentityToken_t *ident);
   107 
   108 	bool FindHandleType(const char *name, HandleType_t *type);
   109 
   110 	Handle_t CreateHandle(HandleType_t type, 
   111 		void *object,
   112 		IdentityToken_t *owner,
   113 		IdentityToken_t *ident,
   114 		HandleError *err);
   115 
   116 	HandleError FreeHandle(Handle_t handle, const HandleSecurity *pSecurity);
   117 
   118 	HandleError CloneHandle(Handle_t handle, 
   119 		Handle_t *newhandle, 
   120 		IdentityToken_t *newOwner,
   121 		const HandleSecurity *pSecurity);
   122 
   123 	HandleError ReadHandle(Handle_t handle, 
   124 		HandleType_t type, 
   125 		const HandleSecurity *pSecurity,
   126 		void **object);
   127 
   128 	bool InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess);
   129 
   130 	bool TypeCheck(HandleType_t intype, HandleType_t outtype);
   131 
   132 	virtual Handle_t CreateHandleEx(HandleType_t type, 
   133 		void *object,
   134 		const HandleSecurity *pSec,
   135 		const HandleAccess *pAccess,
   136 		HandleError *err);
   137 protected:
   138 	/**
   139 	 * Decodes a handle with sanity and security checking.
   140 	 */
   141 	HandleError GetHandle(Handle_t handle, 
   142 						  IdentityToken_t *ident, 
   143 						  QHandle **pHandle, 
   144 						  unsigned int *index,
   145 						  bool ignoreFree=false);
   146 
   147 	/**
   148 	 * Creates a basic handle and sets its reference count to 1.
   149 	 * Does not do any type or security checking.
   150 	 */
   151 	HandleError MakePrimHandle(HandleType_t type, 
   152 							   QHandle **pHandle, 
   153 							   unsigned int *index, 
   154 							   HandleType_t *handle,
   155 							   IdentityToken_t *owner,
   156 							   bool identity=false);
   157 
   158 	/**
   159 	 * Frees a primitive handle.  Does no object freeing, only reference count, bookkeepping, 
   160 	 * and linked list maintenance.
   161 	 * If used on an Identity handle, destroys all Handles under that identity.
   162 	 */
   163 	void ReleasePrimHandle(unsigned int index);
   164 
   165 	/**
   166 	 * Sets the security owner of a type.
   167 	 */
   168 	void SetTypeSecurityOwner(HandleType_t type, IdentityToken_t *pToken);
   169 
   170 	/**
   171 	 * Helper function to check access rights.
   172 	 */
   173 	bool CheckAccess(QHandle *pHandle, HandleAccessRight right, const HandleSecurity *pSecurity);
   174 
   175 	/** 
   176 	 * Some wrappers for internal functions, so we can pass indexes instead of encoded handles.
   177 	 */
   178 	HandleError FreeHandle(QHandle *pHandle, unsigned int index);
   179 	void UnlinkHandleFromOwner(QHandle *pHandle, unsigned int index);
   180 	HandleError CloneHandle(QHandle *pHandle, unsigned int index, Handle_t *newhandle, IdentityToken_t *newOwner);
   181 	Handle_t CreateHandleInt(HandleType_t type, void *object, const HandleSecurity *pSec, HandleError *err, const HandleAccess *pAccess, bool identity);
   182 private:
   183 	QHandle *m_Handles;
   184 	QHandleType *m_Types;
   185 	Trie *m_TypeLookup;
   186 	unsigned int m_TypeTail;
   187 	unsigned int m_FreeTypes;
   188 	unsigned int m_HandleTail;
   189 	unsigned int m_FreeHandles;
   190 	unsigned int m_HSerial;
   191 	BaseStringTable *m_strtab;
   192 };
   193 
   194 extern HandleSystem g_HandleSys;
   195 
   196 #endif //_INCLUDE_SOURCEMOD_HANDLESYSTEM_H_