2 * ===============================================================
3 * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
4 * ===============================================================
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
14 #ifndef _INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
15 #define _INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
17 #include <IHandleSys.h>
18 #include "sm_globals.h"
20 #include "sourcemod.h"
21 #include "sm_memtable.h"
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
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.
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.
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.
46 * Eventually, there may be a third list for type chains.
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 */
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 */
79 IHandleTypeDispatch *dispatch;
81 unsigned int children;
91 friend HandleError IdentityHandle(IdentityToken_t *token, unsigned int *index);
92 friend class ShareSystem;
96 public: //IHandleSystem
98 HandleType_t CreateType(const char *name,
99 IHandleTypeDispatch *dispatch,
101 const TypeAccess *typeAccess,
102 const HandleAccess *hndlAccess,
103 IdentityToken_t *ident,
106 bool RemoveType(HandleType_t type, IdentityToken_t *ident);
108 bool FindHandleType(const char *name, HandleType_t *type);
110 Handle_t CreateHandle(HandleType_t type,
112 IdentityToken_t *owner,
113 IdentityToken_t *ident,
116 HandleError FreeHandle(Handle_t handle, const HandleSecurity *pSecurity);
118 HandleError CloneHandle(Handle_t handle,
120 IdentityToken_t *newOwner,
121 const HandleSecurity *pSecurity);
123 HandleError ReadHandle(Handle_t handle,
125 const HandleSecurity *pSecurity,
128 bool InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess);
130 bool TypeCheck(HandleType_t intype, HandleType_t outtype);
132 virtual Handle_t CreateHandleEx(HandleType_t type,
134 const HandleSecurity *pSec,
135 const HandleAccess *pAccess,
139 * Decodes a handle with sanity and security checking.
141 HandleError GetHandle(Handle_t handle,
142 IdentityToken_t *ident,
145 bool ignoreFree=false);
148 * Creates a basic handle and sets its reference count to 1.
149 * Does not do any type or security checking.
151 HandleError MakePrimHandle(HandleType_t type,
154 HandleType_t *handle,
155 IdentityToken_t *owner,
156 bool identity=false);
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.
163 void ReleasePrimHandle(unsigned int index);
166 * Sets the security owner of a type.
168 void SetTypeSecurityOwner(HandleType_t type, IdentityToken_t *pToken);
171 * Helper function to check access rights.
173 bool CheckAccess(QHandle *pHandle, HandleAccessRight right, const HandleSecurity *pSecurity);
176 * Some wrappers for internal functions, so we can pass indexes instead of encoded handles.
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);
184 QHandleType *m_Types;
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;
194 extern HandleSystem g_HandleSys;
196 #endif //_INCLUDE_SOURCEMOD_HANDLESYSTEM_H_