3 * ===============================================================
4 * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
5 * ===============================================================
7 * This file is not open source and may not be copied without explicit
8 * written permission of AlliedModders LLC. This file may not be redistributed
9 * in whole or significant part.
10 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
15 #ifndef _INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
16 #define _INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
18 #include <IHandleSys.h>
20 #include "sm_globals.h"
22 #include "sourcemod.h"
23 #include "sm_memtable.h"
25 #define HANDLESYS_MAX_HANDLES (1<<14)
26 #define HANDLESYS_MAX_TYPES (1<<9)
27 #define HANDLESYS_MAX_SUBTYPES 0xF
28 #define HANDLESYS_SUBTYPE_MASK 0xF
29 #define HANDLESYS_TYPEARRAY_SIZE (HANDLESYS_MAX_TYPES * (HANDLESYS_MAX_SUBTYPES + 1))
30 #define HANDLESYS_MAX_SERIALS 0xFFFF
31 #define HANDLESYS_SERIAL_MASK 0xFFFF0000
32 #define HANDLESYS_HANDLE_MASK 0x0000FFFF
35 * The QHandle is a nasty structure that compacts the handle system into a big vector.
36 * The members of the vector each encapsulate one Handle, however, they also act as nodes
37 * in an inlined linked list and an inlined vector.
39 * The first of these lists is the 'freeID' list. Each node from 1 to N (where N
40 * is the number of free nodes) has a 'freeID' that specifies a free Handle ID. This
41 * is a quick hack to get around allocating a second base vector.
43 * The second vector is the identity linked list. An identity has its own handle, so
44 * these handles are used as sentinel nodes for index linking. They point to the first and last
45 * index into the handle array. Each subsequent Handle who is owned by that identity is mapped into
46 * that list. This lets owning identities be unloaded in O(n) time.
48 * Eventually, there may be a third list for type chains.
54 HandleSet_Used, /* The Handle is in use */
55 HandleSet_Freed, /* The "master" Handle of a clone chain is freed */
56 HandleSet_Identity, /* The Handle is a special identity */
61 HandleType_t type; /* Handle type */
62 void *object; /* Unmaintained object pointer */
63 IdentityToken_t *owner; /* Identity of object which owns this */
64 unsigned int serial; /* Serial no. for sanity checking */
65 unsigned int refcount; /* Reference count for safe destruction */
66 unsigned int clone; /* If non-zero, this is our cloned parent index */
67 HandleSet set; /* Information about the handle's state */
68 bool access_special; /* Whether or not access rules are special or type-derived */
69 bool is_destroying; /* Whether or not the handle is being destroyed */
70 HandleAccess sec; /* Security rules */
71 /* The following variables are unrelated to the Handle array, and used
72 * as an inlined chain of information */
73 unsigned int freeID; /* ID of a free handle in the free handle chain */
74 /* Indexes into the handle array for owner membership.
75 * For identity roots, these are treated as the head/tail. */
76 unsigned int ch_prev; /* chained previous handle */
77 unsigned int ch_next; /* chained next handle */
82 IHandleTypeDispatch *dispatch;
84 unsigned int children;
94 friend HandleError IdentityHandle(IdentityToken_t *token, unsigned int *index);
95 friend class ShareSystem;
99 public: //IHandleSystem
101 HandleType_t CreateType(const char *name,
102 IHandleTypeDispatch *dispatch,
104 const TypeAccess *typeAccess,
105 const HandleAccess *hndlAccess,
106 IdentityToken_t *ident,
109 bool RemoveType(HandleType_t type, IdentityToken_t *ident);
111 bool FindHandleType(const char *name, HandleType_t *type);
113 Handle_t CreateHandle(HandleType_t type,
115 IdentityToken_t *owner,
116 IdentityToken_t *ident,
119 HandleError FreeHandle(Handle_t handle, const HandleSecurity *pSecurity);
121 HandleError CloneHandle(Handle_t handle,
123 IdentityToken_t *newOwner,
124 const HandleSecurity *pSecurity);
126 HandleError ReadHandle(Handle_t handle,
128 const HandleSecurity *pSecurity,
131 bool InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess);
133 bool TypeCheck(HandleType_t intype, HandleType_t outtype);
135 virtual Handle_t CreateHandleEx(HandleType_t type,
137 const HandleSecurity *pSec,
138 const HandleAccess *pAccess,
144 * Decodes a handle with sanity and security checking.
146 HandleError GetHandle(Handle_t handle,
147 IdentityToken_t *ident,
150 bool ignoreFree=false);
153 * Creates a basic handle and sets its reference count to 1.
154 * Does not do any type or security checking.
156 HandleError MakePrimHandle(HandleType_t type,
159 HandleType_t *handle,
160 IdentityToken_t *owner,
161 bool identity=false);
164 * Frees a primitive handle. Does no object freeing, only reference count, bookkeeping,
165 * and linked list maintenance.
166 * If used on an Identity handle, destroys all Handles under that identity.
168 void ReleasePrimHandle(unsigned int index);
171 * Sets the security owner of a type.
173 void SetTypeSecurityOwner(HandleType_t type, IdentityToken_t *pToken);
176 * Helper function to check access rights.
178 bool CheckAccess(QHandle *pHandle, HandleAccessRight right, const HandleSecurity *pSecurity);
181 * Some wrappers for internal functions, so we can pass indexes instead of encoded handles.
183 HandleError FreeHandle(QHandle *pHandle, unsigned int index);
184 void UnlinkHandleFromOwner(QHandle *pHandle, unsigned int index);
185 HandleError CloneHandle(QHandle *pHandle, unsigned int index, Handle_t *newhandle, IdentityToken_t *newOwner);
186 Handle_t CreateHandleInt(HandleType_t type, void *object, const HandleSecurity *pSec, HandleError *err, const HandleAccess *pAccess, bool identity);
189 QHandleType *m_Types;
191 unsigned int m_TypeTail;
192 unsigned int m_FreeTypes;
193 unsigned int m_HandleTail;
194 unsigned int m_FreeHandles;
195 unsigned int m_HSerial;
196 BaseStringTable *m_strtab;
199 extern HandleSystem g_HandleSys;
201 #endif //_INCLUDE_SOURCEMOD_HANDLESYSTEM_H_