|
dvander@372
|
1 |
/** |
|
dvander@375
|
2 |
* vim: set ts=4 : |
|
dvander@372
|
3 |
* =============================================================== |
|
dvander@376
|
4 |
* SourceMod, Copyright (C) 2004-2007 AlliedModders LLC. |
|
dvander@376
|
5 |
* All rights reserved. |
|
dvander@372
|
6 |
* =============================================================== |
|
dvander@372
|
7 |
* |
|
dvander@379
|
8 |
* This file is part of the SourceMod/SourcePawn SDK. This file may only be |
|
dvander@379
|
9 |
* used or modified under the Terms and Conditions of its License Agreement, |
|
dvander@379
|
10 |
* which is found in public/licenses/LICENSE.txt. As of this notice, derivative |
|
dvander@379
|
11 |
* works must be licensed under the GNU General Public License (version 2 or |
|
dvander@379
|
12 |
* greater). A copy of the GPL is included under public/licenses/GPL.txt. |
|
dvander@379
|
13 |
* |
|
dvander@379
|
14 |
* To view the latest information, see: http://www.sourcemod.net/license.php |
|
dvander@372
|
15 |
* |
|
dvander@372
|
16 |
* Version: $Id$ |
|
dvander@372
|
17 |
*/ |
|
dvander@372
|
18 |
|
|
dvander@324
|
19 |
#ifndef _INCLUDE_SOURCEMOD_HANDLESYSTEM_INTERFACE_H_ |
|
dvander@324
|
20 |
#define _INCLUDE_SOURCEMOD_HANDLESYSTEM_INTERFACE_H_ |
|
dvander@324
|
21 |
|
|
dvander@372
|
22 |
/** |
|
dvander@372
|
23 |
* @file IHandleSys.h |
|
dvander@372
|
24 |
* @brief Defines the interface for creating, reading, and removing Handles. |
|
dvander@372
|
25 |
* |
|
dvander@372
|
26 |
* The Handle system abstracts generic pointers into typed objects represented by |
|
dvander@372
|
27 |
* 32bit codes. This is extremely useful for verifying data integrity and cross-platform |
|
dvander@372
|
28 |
* support in SourcePawn scripts. When a Plugin unloads, all its Handles are freed, ensuring |
|
dvander@372
|
29 |
* that no memory leaks are present, They have reference counts and thus can be duplicated, |
|
dvander@372
|
30 |
* or cloned, and are safe to pass between Plugins even if one is unloaded. |
|
dvander@372
|
31 |
* |
|
dvander@372
|
32 |
* Handles are created with a given type (custom types may be created). They can have |
|
dvander@372
|
33 |
* per-Identity permissions for deletion, reading, and cloning. They also support generic |
|
dvander@372
|
34 |
* operations. For example, deleting a Handle will call that type's destructor on the generic |
|
dvander@372
|
35 |
* pointer, making cleanup easier for users and eliminating memory leaks. |
|
dvander@372
|
36 |
*/ |
|
dvander@372
|
37 |
|
|
dvander@324
|
38 |
#include <IShareSys.h> |
|
dvander@324
|
39 |
#include <sp_vm_types.h> |
|
dvander@324
|
40 |
|
|
dvander@324
|
41 |
#define SMINTERFACE_HANDLESYSTEM_NAME "IHandleSys" |
|
dvander@528
|
42 |
#define SMINTERFACE_HANDLESYSTEM_VERSION 2 |
|
dvander@324
|
43 |
|
|
dvander@372
|
44 |
/** Specifies no Identity */ |
|
dvander@324
|
45 |
#define DEFAULT_IDENTITY NULL |
|
dvander@372
|
46 |
/** Specifies no Type. This is invalid for everything but reading a Handle. */ |
|
dvander@372
|
47 |
#define NO_HANDLE_TYPE 0 |
|
dvander@372
|
48 |
/** Specifies an invalid/NULL Handle */ |
|
dvander@372
|
49 |
#define BAD_HANDLE 0 |
|
dvander@324
|
50 |
|
|
dvander@324
|
51 |
namespace SourceMod |
|
dvander@324
|
52 |
{ |
|
dvander@324
|
53 |
/** |
|
dvander@372
|
54 |
* @brief Represents a Handle Type ID. |
|
dvander@324
|
55 |
*/ |
|
dvander@324
|
56 |
typedef unsigned int HandleType_t; |
|
dvander@372
|
57 |
|
|
dvander@372
|
58 |
/** |
|
dvander@372
|
59 |
* @brief Represents a Handle ID. |
|
dvander@372
|
60 |
*/ |
|
dvander@324
|
61 |
typedef unsigned int Handle_t; |
|
dvander@324
|
62 |
|
|
dvander@324
|
63 |
|
|
dvander@372
|
64 |
/* |
|
dvander@324
|
65 |
* About type checking: |
|
dvander@324
|
66 |
* Types can be inherited - a Parent type ("Supertype") can have child types. |
|
dvander@324
|
67 |
* When accessing handles, type checking is done. This table shows how this is resolved: |
|
dvander@324
|
68 |
* |
|
dvander@324
|
69 |
* HANDLE CHECK -> RESULT |
|
dvander@324
|
70 |
* ------ ----- ------ |
|
dvander@324
|
71 |
* Parent Parent Success |
|
dvander@324
|
72 |
* Parent Child Fail |
|
dvander@324
|
73 |
* Child Parent Success |
|
dvander@324
|
74 |
* Child Child Success |
|
dvander@324
|
75 |
*/ |
|
dvander@324
|
76 |
|
|
dvander@372
|
77 |
/** |
|
dvander@372
|
78 |
* @brief Lists the possible handle error codes. |
|
dvander@372
|
79 |
*/ |
|
dvander@324
|
80 |
enum HandleError |
|
dvander@324
|
81 |
{ |
|
dvander@372
|
82 |
HandleError_None = 0, /**< No error */ |
|
dvander@372
|
83 |
HandleError_Changed, /**< The handle has been freed and reassigned */ |
|
dvander@372
|
84 |
HandleError_Type, /**< The handle has a different type registered */ |
|
dvander@372
|
85 |
HandleError_Freed, /**< The handle has been freed */ |
|
dvander@372
|
86 |
HandleError_Index, /**< generic internal indexing error */ |
|
dvander@372
|
87 |
HandleError_Access, /**< No access permitted to free this handle */ |
|
dvander@372
|
88 |
HandleError_Limit, /**< The limited number of handles has been reached */ |
|
dvander@372
|
89 |
HandleError_Identity, /**< The identity token was not usable */ |
|
dvander@372
|
90 |
HandleError_Owner, /**< Owners do not match for this operation */ |
|
dvander@372
|
91 |
HandleError_Version, /**< Unrecognized security structure version */ |
|
dvander@372
|
92 |
HandleError_Parameter, /**< An invalid parameter was passed */ |
|
dvander@372
|
93 |
HandleError_NoInherit, /**< This type cannot be inherited */ |
|
dvander@324
|
94 |
}; |
|
dvander@324
|
95 |
|
|
dvander@324
|
96 |
/** |
|
dvander@372
|
97 |
* @brief Lists access rights specific to a type. |
|
dvander@324
|
98 |
*/ |
|
dvander@324
|
99 |
enum HTypeAccessRight |
|
dvander@324
|
100 |
{ |
|
dvander@372
|
101 |
HTypeAccess_Create = 0, /**< Handles of this type can be created (DEFAULT=false) */ |
|
dvander@372
|
102 |
HTypeAccess_Inherit, /**< Sub-types can inherit this type (DEFAULT=false) */ |
|
dvander@324
|
103 |
/* -------------- */ |
|
dvander@372
|
104 |
HTypeAccess_TOTAL, /**< Total number of type access rights */ |
|
dvander@324
|
105 |
}; |
|
dvander@324
|
106 |
|
|
dvander@324
|
107 |
/** |
|
dvander@372
|
108 |
* @brief Lists access rights specific to a Handle. |
|
dvander@372
|
109 |
* |
|
dvander@372
|
110 |
* These rights are exclusive. For example, you do not need "read" access to delete or clone. |
|
dvander@324
|
111 |
*/ |
|
dvander@324
|
112 |
enum HandleAccessRight |
|
dvander@324
|
113 |
{ |
|
dvander@372
|
114 |
HandleAccess_Read, /**< Can be read (DEFAULT=ident only) */ |
|
dvander@372
|
115 |
HandleAccess_Delete, /**< Can be deleted (DEFAULT=owner only) */ |
|
dvander@372
|
116 |
HandleAccess_Clone, /**< Can be cloned (DEFAULT=any) */ |
|
dvander@324
|
117 |
/* ------------- */ |
|
dvander@372
|
118 |
HandleAccess_TOTAL, /**< Total number of access rights */ |
|
dvander@324
|
119 |
}; |
|
dvander@324
|
120 |
|
|
dvander@372
|
121 |
/** Access is restricted to the identity */ |
|
dvander@372
|
122 |
#define HANDLE_RESTRICT_IDENTITY (1<<0) |
|
dvander@372
|
123 |
/** Access is restricted to the owner */ |
|
dvander@372
|
124 |
#define HANDLE_RESTRICT_OWNER (1<<1) |
|
dvander@324
|
125 |
|
|
dvander@324
|
126 |
/** |
|
dvander@372
|
127 |
* @brief This is used to define per-type access rights. |
|
dvander@324
|
128 |
*/ |
|
dvander@324
|
129 |
struct TypeAccess |
|
dvander@324
|
130 |
{ |
|
dvander@372
|
131 |
/** Constructor */ |
|
dvander@324
|
132 |
TypeAccess() |
|
dvander@324
|
133 |
{ |
|
dvander@324
|
134 |
hsVersion = SMINTERFACE_HANDLESYSTEM_VERSION; |
|
dvander@324
|
135 |
} |
|
dvander@372
|
136 |
unsigned int hsVersion; /**< Handle API version */ |
|
dvander@372
|
137 |
IdentityToken_t *ident; /**< Identity owning this type */ |
|
dvander@372
|
138 |
bool access[HTypeAccess_TOTAL]; /**< Access array */ |
|
dvander@324
|
139 |
}; |
|
dvander@324
|
140 |
|
|
dvander@324
|
141 |
/** |
|
dvander@372
|
142 |
* @brief This is used to define per-Handle access rights. |
|
dvander@324
|
143 |
*/ |
|
dvander@324
|
144 |
struct HandleAccess |
|
dvander@324
|
145 |
{ |
|
dvander@372
|
146 |
/** Constructor */ |
|
dvander@324
|
147 |
HandleAccess() |
|
dvander@324
|
148 |
{ |
|
dvander@324
|
149 |
hsVersion = SMINTERFACE_HANDLESYSTEM_VERSION; |
|
dvander@324
|
150 |
} |
|
dvander@372
|
151 |
unsigned int hsVersion; /**< Handle API version */ |
|
dvander@372
|
152 |
unsigned int access[HandleAccess_TOTAL]; /**< Access array */ |
|
dvander@324
|
153 |
}; |
|
dvander@324
|
154 |
|
|
dvander@324
|
155 |
/** |
|
dvander@372
|
156 |
* @brief This pair of tokens is used for identification. |
|
dvander@324
|
157 |
*/ |
|
dvander@324
|
158 |
struct HandleSecurity |
|
dvander@324
|
159 |
{ |
|
dvander@372
|
160 |
IdentityToken_t *pOwner; /**< Owner of the Handle */ |
|
dvander@372
|
161 |
IdentityToken_t *pIdentity; /**< Owner of the Type */ |
|
dvander@324
|
162 |
}; |
|
dvander@324
|
163 |
|
|
dvander@372
|
164 |
/** |
|
dvander@372
|
165 |
* @brief Hooks type-specific Handle operations. |
|
dvander@372
|
166 |
*/ |
|
dvander@324
|
167 |
class IHandleTypeDispatch |
|
dvander@324
|
168 |
{ |
|
dvander@324
|
169 |
public: |
|
dvander@372
|
170 |
/** Returns the Handle API version */ |
|
dvander@324
|
171 |
virtual unsigned int GetDispatchVersion() |
|
dvander@324
|
172 |
{ |
|
dvander@324
|
173 |
return SMINTERFACE_HANDLESYSTEM_VERSION; |
|
dvander@324
|
174 |
} |
|
dvander@324
|
175 |
public: |
|
dvander@324
|
176 |
/** |
|
dvander@324
|
177 |
* @brief Called when destroying a handle. Must be implemented. |
|
dvander@324
|
178 |
*/ |
|
dvander@324
|
179 |
virtual void OnHandleDestroy(HandleType_t type, void *object) =0; |
|
dvander@324
|
180 |
}; |
|
dvander@324
|
181 |
|
|
dvander@372
|
182 |
/** |
|
dvander@372
|
183 |
* @brief Provides functions for managing Handles. |
|
dvander@372
|
184 |
*/ |
|
dvander@324
|
185 |
class IHandleSys : public SMInterface |
|
dvander@324
|
186 |
{ |
|
dvander@324
|
187 |
public: |
|
dvander@324
|
188 |
virtual unsigned int GetInterfaceVersion() |
|
dvander@324
|
189 |
{ |
|
dvander@324
|
190 |
return SMINTERFACE_HANDLESYSTEM_VERSION; |
|
dvander@324
|
191 |
} |
|
dvander@324
|
192 |
virtual const char *GetInterfaceName() |
|
dvander@324
|
193 |
{ |
|
dvander@324
|
194 |
return SMINTERFACE_HANDLESYSTEM_NAME; |
|
dvander@324
|
195 |
} |
|
dvander@324
|
196 |
public: |
|
dvander@324
|
197 |
/** |
|
dvander@324
|
198 |
* @brief Creates a new Handle type. |
|
dvander@324
|
199 |
* NOTE: Currently, a child type may not have its own children. |
|
dvander@324
|
200 |
* NOTE: Handle names must be unique if not private. |
|
dvander@324
|
201 |
* |
|
dvander@324
|
202 |
* @param name Name of handle type (NULL or "" to be anonymous) |
|
dvander@324
|
203 |
* @param dispatch Pointer to a valid IHandleTypeDispatch object. |
|
dvander@324
|
204 |
* @param parent Parent handle to inherit from, 0 for none. |
|
dvander@324
|
205 |
* @param typeAccess Pointer to a TypeAccess object, NULL to use default |
|
dvander@324
|
206 |
* or inherited permissions. Pointer can be temporary. |
|
dvander@324
|
207 |
* @param hndlAccess Pointer to a HandleAccess object to define default |
|
dvander@324
|
208 |
* default permissions on each Handle. NULL to use default |
|
dvander@324
|
209 |
* permissions. |
|
dvander@324
|
210 |
* @param ident Security token for any permissions. If typeAccess is NULL, this |
|
dvander@324
|
211 |
* becomes the owning identity. |
|
dvander@324
|
212 |
* @param err Optional pointer to store an error code. |
|
dvander@324
|
213 |
* @return A new HandleType_t unique ID, or 0 on failure. |
|
dvander@324
|
214 |
*/ |
|
dvander@324
|
215 |
virtual HandleType_t CreateType(const char *name, |
|
dvander@324
|
216 |
IHandleTypeDispatch *dispatch, |
|
dvander@324
|
217 |
HandleType_t parent, |
|
dvander@324
|
218 |
const TypeAccess *typeAccess, |
|
dvander@324
|
219 |
const HandleAccess *hndlAccess, |
|
dvander@324
|
220 |
IdentityToken_t *ident, |
|
dvander@324
|
221 |
HandleError *err) =0; |
|
dvander@324
|
222 |
|
|
dvander@324
|
223 |
/** |
|
dvander@324
|
224 |
* @brief Removes a handle type. |
|
dvander@324
|
225 |
* NOTE: This removes all child types. |
|
dvander@324
|
226 |
* |
|
dvander@324
|
227 |
* @param type Type chain to remove. |
|
dvander@324
|
228 |
* @param ident Identity token. Removal fails if the token does not match. |
|
dvander@324
|
229 |
* @return True on success, false on failure. |
|
dvander@324
|
230 |
*/ |
|
dvander@324
|
231 |
virtual bool RemoveType(HandleType_t type, IdentityToken_t *ident) =0; |
|
dvander@324
|
232 |
|
|
dvander@324
|
233 |
/** |
|
dvander@324
|
234 |
* @brief Finds a handle type by name. |
|
dvander@324
|
235 |
* |
|
dvander@324
|
236 |
* @param name Name of handle type to find (anonymous not allowed). |
|
dvander@324
|
237 |
* @param type Address to store found handle in (if not found, undefined). |
|
dvander@324
|
238 |
* @return True if found, false otherwise. |
|
dvander@324
|
239 |
*/ |
|
dvander@324
|
240 |
virtual bool FindHandleType(const char *name, HandleType_t *type) =0; |
|
dvander@324
|
241 |
|
|
dvander@324
|
242 |
/** |
|
dvander@324
|
243 |
* @brief Creates a new handle. |
|
dvander@324
|
244 |
* |
|
dvander@324
|
245 |
* @param type Type to use on the handle. |
|
dvander@324
|
246 |
* @param object Object to bind to the handle. |
|
dvander@324
|
247 |
* @param owner Owner of the new Handle (may be NULL). |
|
dvander@324
|
248 |
* @param ident Identity for type access if needed (may be NULL). |
|
dvander@324
|
249 |
* @param err Optional pointer to store an error code. |
|
dvander@324
|
250 |
* @return A new Handle_t, or 0 on failure. |
|
dvander@324
|
251 |
*/ |
|
dvander@324
|
252 |
virtual Handle_t CreateHandle(HandleType_t type, |
|
dvander@324
|
253 |
void *object, |
|
dvander@324
|
254 |
IdentityToken_t *owner, |
|
dvander@324
|
255 |
IdentityToken_t *ident, |
|
dvander@324
|
256 |
HandleError *err) =0; |
|
dvander@324
|
257 |
|
|
dvander@324
|
258 |
/** |
|
dvander@324
|
259 |
* @brief Frees the memory associated with a handle and calls any destructors. |
|
dvander@324
|
260 |
* NOTE: This function will decrement the internal reference counter. It will |
|
dvander@324
|
261 |
* only perform any further action if the counter hits 0. |
|
dvander@324
|
262 |
* |
|
dvander@372
|
263 |
* @param handle Handle_t identifier to destroy. |
|
dvander@324
|
264 |
* @param pSecurity Security information struct (may be NULL). |
|
dvander@324
|
265 |
* @return A HandleError error code. |
|
dvander@324
|
266 |
*/ |
|
dvander@324
|
267 |
virtual HandleError FreeHandle(Handle_t handle, const HandleSecurity *pSecurity) =0; |
|
dvander@324
|
268 |
|
|
dvander@324
|
269 |
/** |
|
dvander@324
|
270 |
* @brief Clones a handle by adding to its internal reference count. Its data, |
|
dvander@324
|
271 |
* type, and security permissions remain the same. |
|
dvander@324
|
272 |
* |
|
dvander@324
|
273 |
* @param handle Handle to duplicate. Any non-free handle target is valid. |
|
dvander@324
|
274 |
* @param newhandle Stores the duplicated handle in the pointer (must not be NULL). |
|
dvander@324
|
275 |
* @param newOwner New owner of cloned handle. |
|
dvander@324
|
276 |
* @param pSecurity Security information struct (may be NULL). |
|
dvander@324
|
277 |
* @return A HandleError error code. |
|
dvander@324
|
278 |
*/ |
|
dvander@324
|
279 |
virtual HandleError CloneHandle(Handle_t handle, |
|
dvander@324
|
280 |
Handle_t *newhandle, |
|
dvander@324
|
281 |
IdentityToken_t *newOwner, |
|
dvander@324
|
282 |
const HandleSecurity *pSecurity) =0; |
|
dvander@324
|
283 |
|
|
dvander@324
|
284 |
/** |
|
dvander@324
|
285 |
* @brief Retrieves the contents of a handle. |
|
dvander@324
|
286 |
* |
|
dvander@324
|
287 |
* @param handle Handle_t from which to retrieve contents. |
|
dvander@324
|
288 |
* @param type Expected type to read as. 0 ignores typing rules. |
|
dvander@324
|
289 |
* @param pSecurity Security information struct (may be NULL). |
|
dvander@324
|
290 |
* @param object Optional address to store object in. |
|
dvander@324
|
291 |
* @return HandleError error code. |
|
dvander@324
|
292 |
*/ |
|
dvander@324
|
293 |
virtual HandleError ReadHandle(Handle_t handle, |
|
dvander@324
|
294 |
HandleType_t type, |
|
dvander@324
|
295 |
const HandleSecurity *pSecurity, |
|
dvander@324
|
296 |
void **object) =0; |
|
dvander@324
|
297 |
|
|
dvander@324
|
298 |
/** |
|
dvander@324
|
299 |
* @brief Sets access permissions on one or more structures. |
|
dvander@324
|
300 |
* |
|
dvander@324
|
301 |
* @param pTypeAccess Optional TypeAccess buffer to initialize with the default values. |
|
dvander@324
|
302 |
* @param pHandleAccess Optional HandleAccess buffer to initialize with the default values. |
|
dvander@335
|
303 |
* @return True on success, false if version is unsupported. |
|
dvander@324
|
304 |
*/ |
|
dvander@324
|
305 |
virtual bool InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess) =0; |
|
dvander@528
|
306 |
|
|
dvander@528
|
307 |
/** |
|
dvander@528
|
308 |
* @brief Creates a new handle. |
|
dvander@528
|
309 |
* |
|
dvander@528
|
310 |
* @param type Type to use on the handle. |
|
dvander@528
|
311 |
* @param object Object to bind to the handle. |
|
dvander@528
|
312 |
* @param pSec Security pointer; pOwner is written as the owner, |
|
dvander@528
|
313 |
* pIdent is used as the parent identity for authorization. |
|
dvander@528
|
314 |
* @param pAccess Access right descriptor for the Handle; NULL for type defaults. |
|
dvander@528
|
315 |
* @param err Optional pointer to store an error code. |
|
dvander@528
|
316 |
* @return A new Handle_t, or 0 on failure. |
|
dvander@528
|
317 |
*/ |
|
dvander@528
|
318 |
virtual Handle_t CreateHandleEx(HandleType_t type, |
|
dvander@528
|
319 |
void *object, |
|
dvander@528
|
320 |
const HandleSecurity *pSec, |
|
dvander@528
|
321 |
const HandleAccess *pAccess, |
|
dvander@528
|
322 |
HandleError *err) =0; |
|
dvander@324
|
323 |
}; |
|
ds@432
|
324 |
} |
|
dvander@324
|
325 |
|
|
dvander@324
|
326 |
#endif //_INCLUDE_SOURCEMOD_HANDLESYSTEM_INTERFACE_H_ |