initial import of sharesystem (unfinished)
final revision of handle system (I hope!) initial import of plugin handles --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40234
This commit is contained in:
		
							parent
							
								
									5b331ca858
								
							
						
					
					
						commit
						f068587ecc
					
				| @ -7,6 +7,8 @@ | ||||
| #define SMINTERFACE_HANDLESYSTEM_NAME			"IHandleSys" | ||||
| #define SMINTERFACE_HANDLESYSTEM_VERSION		1 | ||||
| 
 | ||||
| #define DEFAULT_IDENTITY			NULL | ||||
| 
 | ||||
| namespace SourceMod | ||||
| { | ||||
| 	/**
 | ||||
| @ -37,6 +39,7 @@ namespace SourceMod | ||||
| 		HandleError_Index,			/* generic internal indexing error */ | ||||
| 		HandleError_Access,			/* No access permitted to free this handle */ | ||||
| 		HandleError_Limit,			/* The limited number of handles has been reached */ | ||||
| 		HandleError_Identity,		/* The identity token was not usable */ | ||||
| 	}; | ||||
| 
 | ||||
| 	enum HandleAccessRight | ||||
| @ -54,14 +57,14 @@ namespace SourceMod | ||||
| 	{ | ||||
| 		HandleSecurity() | ||||
| 		{ | ||||
| 			owner = 0; | ||||
| 			owner = NULL; | ||||
| 			access[HandleAccess_Create] = true; | ||||
| 			access[HandleAccess_Read] = true; | ||||
| 			access[HandleAccess_Delete] = true; | ||||
| 			access[HandleAccess_Inherit] = true; | ||||
| 			access[HandleAccess_Clone] = true; | ||||
| 		} | ||||
| 		IdentityToken_t owner;				/* Owner of the handle */ | ||||
| 		IdentityToken_t *owner;				/* Owner of the handle */ | ||||
| 		bool access[HandleAccess_TOTAL];	/* World access rights */ | ||||
| 	}; | ||||
| 
 | ||||
| @ -112,12 +115,14 @@ namespace SourceMod | ||||
| 		 * @param parent	Parent handle to inherit from, 0 for none. | ||||
| 		 * @param security	Pointer to a temporary HandleSecurity object, NULL to use default  | ||||
| 		 *					or inherited permissions. | ||||
| 		 * @param ident		Security token for any permissions. | ||||
| 		 * @return			A new HandleType_t unique ID. | ||||
| 		 */ | ||||
| 		virtual HandleType_t CreateTypeEx(const char *name, | ||||
| 										  IHandleTypeDispatch *dispatch, | ||||
| 										  HandleType_t parent, | ||||
| 										  const HandleSecurity *security) =0; | ||||
| 										  const HandleSecurity *security, | ||||
| 										  IdentityToken_t *ident) =0; | ||||
| 
 | ||||
| 
 | ||||
| 		/**
 | ||||
| @ -143,7 +148,7 @@ namespace SourceMod | ||||
| 		 * @param type		Type chain to remove. | ||||
| 		 * @return			True on success, false on failure. | ||||
| 		 */ | ||||
| 		virtual bool RemoveType(HandleType_t type, IdentityToken_t ident) =0; | ||||
| 		virtual bool RemoveType(HandleType_t type, IdentityToken_t *ident) =0; | ||||
| 
 | ||||
| 		/**
 | ||||
| 		 * @brief Finds a handle type by name. | ||||
| @ -159,14 +164,14 @@ namespace SourceMod | ||||
| 		 *  | ||||
| 		 * @param type		Type to use on the handle. | ||||
| 		 * @param object	Object to bind to the handle. | ||||
| 		 * @param source	Identity token for object using this handle (for example, a script). | ||||
| 		 * @param owner		Owner for the handle. | ||||
| 		 * @param ident		Identity token if any security rights are needed. | ||||
| 		 * @return			A new Handle_t, or 0 on failure. | ||||
| 		 */ | ||||
| 		virtual Handle_t CreateHandle(HandleType_t type,  | ||||
| 										void *object,  | ||||
| 										IdentityToken_t source,  | ||||
| 										IdentityToken_t ident) =0; | ||||
| 										IdentityToken_t *owner,  | ||||
| 										IdentityToken_t *ident) =0; | ||||
| 
 | ||||
| 		/**
 | ||||
| 		 * @brief Creates a new handle. | ||||
| @ -181,7 +186,7 @@ namespace SourceMod | ||||
| 		virtual Handle_t CreateScriptHandle(HandleType_t type,  | ||||
| 											void *object,  | ||||
| 											sp_context_t *ctx, | ||||
| 											IdentityToken_t ident) =0; | ||||
| 											IdentityToken_t *ident) =0; | ||||
| 
 | ||||
| 		/**
 | ||||
| 		 * @brief Frees the memory associated with a handle and calls any destructors. | ||||
| @ -192,7 +197,7 @@ namespace SourceMod | ||||
| 		 * @param ident		Identity token, for destroying secure handles (0 for none). | ||||
| 		 * @return			A HandleError error code. | ||||
| 		 */ | ||||
| 		virtual HandleError FreeHandle(Handle_t handle, IdentityToken_t ident) =0; | ||||
| 		virtual HandleError FreeHandle(Handle_t handle, IdentityToken_t *ident) =0; | ||||
| 
 | ||||
| 		/**
 | ||||
| 		 * @brief Clones a handle by adding to its internal reference count.  Its data, | ||||
| @ -200,11 +205,11 @@ namespace SourceMod | ||||
| 		 * | ||||
| 		 * @param handle	Handle to duplicate.  Any non-free handle target is valid. | ||||
| 		 * @param newhandle	If non-NULL, stores the duplicated handle in the pointer. | ||||
| 		 * @param source	New source of cloned handle. | ||||
| 		 * @param owner		New owner of cloned handle. | ||||
| 		 * @param ident		Security token, if needed. | ||||
| 		 * @return			A HandleError error code. | ||||
| 		 */ | ||||
| 		virtual HandleError CloneHandle(Handle_t handle, Handle_t *newhandle, IdentityToken_t source, IdentityToken_t ident) =0; | ||||
| 		virtual HandleError CloneHandle(Handle_t handle, Handle_t *newhandle, IdentityToken_t *owner, IdentityToken_t *ident) =0; | ||||
| 
 | ||||
| 		/**
 | ||||
| 		 * @brief Retrieves the contents of a handle. | ||||
| @ -215,7 +220,7 @@ namespace SourceMod | ||||
| 		 * @param object	Address to store object in. | ||||
| 		 * @return			HandleError error code. | ||||
| 		 */ | ||||
| 		virtual HandleError ReadHandle(Handle_t handle, HandleType_t type, IdentityToken_t ident, void **object) =0; | ||||
| 		virtual HandleError ReadHandle(Handle_t handle, HandleType_t type, IdentityToken_t *ident, void **object) =0; | ||||
| 	}; | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -147,7 +147,7 @@ namespace SourceMod | ||||
| 		/**
 | ||||
| 		 * @brief Returns a plugin's identity token. | ||||
| 		 */ | ||||
| 		virtual IdentityToken_t GetIdentity() =0; | ||||
| 		virtual IdentityToken_t *GetIdentity() =0; | ||||
| 	}; | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -3,11 +3,13 @@ | ||||
| 
 | ||||
| #include <sp_vm_types.h> | ||||
| 
 | ||||
| #define	DEFAULT_IDENTITY		0 | ||||
| #define	NO_IDENTITY		0 | ||||
| 
 | ||||
| namespace SourceMod | ||||
| { | ||||
| 	typedef unsigned int		IdentityToken_t; | ||||
| 	struct IdentityToken_t; | ||||
| 	typedef unsigned int		HandleType_t; | ||||
| 	typedef HandleType_t		IdentityType_t; | ||||
| 	/**
 | ||||
| 	 * @brief Defines the base functionality required by a shared interface. | ||||
| 	 */ | ||||
| @ -49,12 +51,13 @@ namespace SourceMod | ||||
| 	{ | ||||
| 	public: | ||||
| 		/**
 | ||||
| 		 * @brief Adds an interface to the global interface system | ||||
| 		 * @brief Adds an interface to the global interface system. | ||||
| 		 * | ||||
| 		 * @param iface			Interface pointer (must be unique). | ||||
| 		 * @param token			Parent token of the module/interface. | ||||
| 		 * @return				True on success, false otherwise. | ||||
| 		 */ | ||||
| 		virtual bool AddInterface(SMInterface *iface, IdentityToken_t token) =0; | ||||
| 		virtual bool AddInterface(SMInterface *iface, IdentityToken_t *token) =0; | ||||
| 
 | ||||
| 		/**
 | ||||
| 		 * @brief Requests an interface from the global interface system. | ||||
| @ -67,8 +70,8 @@ namespace SourceMod | ||||
| 		 */ | ||||
| 		virtual bool RequestInterface(const char *iface_name,  | ||||
| 										unsigned int iface_vers, | ||||
| 										IdentityToken_t token, | ||||
| 										void **pIface) =0; | ||||
| 										IdentityToken_t *token, | ||||
| 										SMInterface **pIface) =0; | ||||
| 
 | ||||
| 		/**
 | ||||
| 		 * @brief Adds a list of natives to the global native pool. | ||||
| @ -76,7 +79,54 @@ namespace SourceMod | ||||
| 		 * @param token			Identity token of parent object. | ||||
| 		 * @param natives		Array of natives to add, NULL terminated. | ||||
| 		 */ | ||||
| 		virtual void AddNatives(IdentityToken_t token, const sp_nativeinfo_t *natives[]) =0; | ||||
| 		virtual void AddNatives(IdentityToken_t *token, const sp_nativeinfo_t *natives[]) =0; | ||||
| 
 | ||||
| 		/**
 | ||||
| 		 * @brief Creates a new identity type. | ||||
| 		 * NOTE: Module authors should never need to use this.  Due to the current implementation, | ||||
| 		 * there is a hardcoded limit of 15 types.  Core uses up a few, so think carefully! | ||||
| 		 * | ||||
| 		 * @param name			String containing type name.  Must not be empty or NULL. | ||||
| 		 * @return				A new HandleType_t identifier, or 0 on failure. | ||||
| 		 */ | ||||
| 		virtual IdentityType_t CreateIdentType(const char *name) =0; | ||||
| 
 | ||||
| 		/**
 | ||||
| 		 * @brief Finds an identity type by name. | ||||
| 		 * DEFAULT IDENTITY TYPES: | ||||
| 		 *  "PLUGIN"	- An IPlugin object. | ||||
| 		 *  "MODULE"	- An IModule object. | ||||
| 		 *  "CORE"		- An SMGlobalClass or other singleton. | ||||
| 		 *  | ||||
| 		 * @param name			String containing type name to search for. | ||||
| 		 * @return				A HandleType_t identifier if found, 0 otherwise. | ||||
| 		 */ | ||||
| 		virtual IdentityType_t FindIdentType(const char *name) =0; | ||||
| 
 | ||||
| 		/**
 | ||||
| 		 * @brief Creates a new identity token.  This token is guaranteed to be unique | ||||
| 		 * amongst all other open identities. | ||||
| 		 * | ||||
| 		 * @param type			Identity type. | ||||
| 		 * @return				A new IdentityToken_t identifier. | ||||
| 		 */ | ||||
| 		virtual IdentityToken_t *CreateIdentity(IdentityType_t type) =0; | ||||
| 
 | ||||
| 		/** 
 | ||||
| 		 * @brief Destroys an identity type.  Note that this will delete any identities | ||||
| 		 * that are under this type.   | ||||
| 		 * | ||||
| 		 * @param type			Identity type. | ||||
| 		 */ | ||||
| 		virtual void DestroyIdentType(IdentityType_t type) =0; | ||||
| 
 | ||||
| 		/**
 | ||||
| 		 * @brief Destroys an identity token.  Any handles being owned by this token, or | ||||
| 		 * any handles being  | ||||
| 		 * | ||||
| 		 * @param identity		Identity to remove. | ||||
| 		 */ | ||||
| 		virtual void DestroyIdentity(IdentityToken_t *identity) =0; | ||||
| 	}; | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -13,6 +13,40 @@ | ||||
| using namespace SourcePawn; | ||||
| using namespace SourceMod; | ||||
| 
 | ||||
| /** 
 | ||||
|  * @brief Any class deriving from this will be automatically initiated/shutdown by SourceMod | ||||
|  */ | ||||
| class SMGlobalClass | ||||
| { | ||||
| 	friend class SourceModBase; | ||||
| public: | ||||
| 	SMGlobalClass(); | ||||
| public: | ||||
| 	/**
 | ||||
| 	 * @brief Called when SourceMod is initially loading | ||||
| 	 */ | ||||
| 	virtual void OnSourceModStartup(bool late) | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * @brief Called after all global classes have initialized | ||||
| 	 */ | ||||
| 	virtual void OnSourceModAllInitialized() | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * @brief Called when SourceMod is shutting down | ||||
| 	 */ | ||||
| 	virtual void OnSourceModShutdown() | ||||
| 	{ | ||||
| 	} | ||||
| private: | ||||
| 	SMGlobalClass *m_pGlobalClassNext; | ||||
| 	static SMGlobalClass *head; | ||||
| }; | ||||
| 
 | ||||
| extern ISourcePawnEngine *g_pSourcePawn; | ||||
| extern IVirtualMachine *g_pVM; | ||||
| 
 | ||||
|  | ||||
| @ -52,40 +52,6 @@ private: | ||||
| 	bool m_IsLateLoadInMap; | ||||
| }; | ||||
| 
 | ||||
| /** 
 | ||||
|  * @brief Any class deriving from this will be automatically initiated/shutdown by SourceMod | ||||
|  */ | ||||
| class SMGlobalClass | ||||
| { | ||||
| 	friend class SourceModBase; | ||||
| public: | ||||
| 	SMGlobalClass(); | ||||
| public: | ||||
| 	/**
 | ||||
| 	 * @brief Called when SourceMod is initially loading | ||||
| 	 */ | ||||
| 	virtual void OnSourceModStartup(bool late) | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * @brief Called after all global classes have initialized | ||||
| 	 */ | ||||
| 	virtual void OnSourceModAllInitialized() | ||||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * @brief Called when SourceMod is shutting down | ||||
| 	 */ | ||||
| 	virtual void OnSourceModShutdown() | ||||
| 	{ | ||||
| 	} | ||||
| private: | ||||
| 	SMGlobalClass *m_pGlobalClassNext; | ||||
| 	static SMGlobalClass *head; | ||||
| }; | ||||
| 
 | ||||
| extern SourceModBase g_SourceMod; | ||||
| 
 | ||||
| #endif //_INCLUDE_SOURCEMOD_GLOBALHEADER_H_
 | ||||
|  | ||||
| @ -1,9 +1,22 @@ | ||||
| #include "HandleSys.h" | ||||
| #include "ShareSys.h" | ||||
| #include "PluginSys.h" | ||||
| #include <assert.h> | ||||
| 
 | ||||
| HandleSystem g_HandleSys; | ||||
| 
 | ||||
| QHandle *ignore_handle; | ||||
| 
 | ||||
| inline HandleType_t TypeParent(HandleType_t type) | ||||
| { | ||||
| 	return (type & ~HANDLESYS_SUBTYPE_MASK); | ||||
| } | ||||
| 
 | ||||
| inline HandleError IdentityHandle(IdentityToken_t *token, unsigned int *index) | ||||
| { | ||||
| 	return g_HandleSys.GetHandle(token->ident, g_ShareSys.GetIdentRoot(), &ignore_handle, index, HandleAccess_Read); | ||||
| } | ||||
| 
 | ||||
| HandleSystem::HandleSystem() | ||||
| { | ||||
| 	m_Handles = new QHandle[HANDLESYS_MAX_HANDLES + 1]; | ||||
| @ -28,18 +41,19 @@ HandleSystem::~HandleSystem() | ||||
| 
 | ||||
| HandleType_t HandleSystem::CreateType(const char *name, IHandleTypeDispatch *dispatch) | ||||
| { | ||||
| 	return CreateTypeEx(name, dispatch, 0, NULL); | ||||
| 	return CreateTypeEx(name, dispatch, 0, NULL, NULL); | ||||
| } | ||||
| 
 | ||||
| HandleType_t HandleSystem::CreateChildType(const char *name, HandleType_t parent, IHandleTypeDispatch *dispatch) | ||||
| { | ||||
| 	return CreateTypeEx(name, dispatch, parent, NULL); | ||||
| 	return CreateTypeEx(name, dispatch, parent, NULL, NULL); | ||||
| } | ||||
| 
 | ||||
| HandleType_t HandleSystem::CreateTypeEx(const char *name,  | ||||
| 										IHandleTypeDispatch *dispatch,  | ||||
| 										HandleType_t parent,  | ||||
| 										const HandleSecurity *security) | ||||
| 										const HandleSecurity *security, | ||||
| 										IdentityToken_t *ident) | ||||
| { | ||||
| 	if (!dispatch) | ||||
| 	{ | ||||
| @ -56,8 +70,9 @@ HandleType_t HandleSystem::CreateTypeEx(const char *name, | ||||
| 			return 0; | ||||
| 		} | ||||
| 		if (parent >= HANDLESYS_TYPEARRAY_SIZE | ||||
| 			|| m_Types[parent].dispatch != NULL | ||||
| 			|| m_Types[parent].sec.access[HandleAccess_Inherit] == false) | ||||
| 			|| m_Types[parent].dispatch == NULL | ||||
| 			|| (m_Types[parent].sec.access[HandleAccess_Inherit] == false | ||||
| 				&& m_Types[parent].sec.owner != ident)) | ||||
| 		{ | ||||
| 			return 0; | ||||
| 		} | ||||
| @ -163,8 +178,16 @@ bool HandleSystem::FindHandleType(const char *name, HandleType_t *type) | ||||
| HandleError HandleSystem::MakePrimHandle(HandleType_t type,  | ||||
| 						   QHandle **in_pHandle,  | ||||
| 						   unsigned int *in_index,  | ||||
| 						   Handle_t *in_handle) | ||||
| 						   Handle_t *in_handle, | ||||
| 						   IdentityToken_t *owner) | ||||
| { | ||||
| 	unsigned int owner_index = 0; | ||||
| 
 | ||||
| 	if (owner && (IdentityHandle(owner, &owner_index) != HandleError_None)) | ||||
| 	{ | ||||
| 		return HandleError_Identity; | ||||
| 	} | ||||
| 
 | ||||
| 	unsigned int handle; | ||||
| 	if (m_FreeHandles == 0) | ||||
| 	{ | ||||
| @ -187,10 +210,12 @@ HandleError HandleSystem::MakePrimHandle(HandleType_t type, | ||||
| 	} | ||||
| 
 | ||||
| 	/* Set essential information */ | ||||
| 	pHandle->set = true; | ||||
| 	pHandle->set = HandleSet_Used;; | ||||
| 	pHandle->refcount = 1; | ||||
| 	pHandle->type = type; | ||||
| 	pHandle->serial = m_HSerial; | ||||
| 	pHandle->owner = owner; | ||||
| 	pHandle->ch_next = 0; | ||||
| 
 | ||||
| 	/* Create the hash value */ | ||||
| 	Handle_t hash = pHandle->serial; | ||||
| @ -205,10 +230,44 @@ HandleError HandleSystem::MakePrimHandle(HandleType_t type, | ||||
| 	*in_index = handle; | ||||
| 	*in_handle = hash; | ||||
| 
 | ||||
| 	/* Decode the identity token */ | ||||
| 	if (owner) | ||||
| 	{ | ||||
| 		QHandle *pIdentity = &m_Handles[owner_index]; | ||||
| 		if (pIdentity->ch_prev == 0) | ||||
| 		{ | ||||
| 			pIdentity->ch_prev = handle; | ||||
| 			pIdentity->ch_next = handle; | ||||
| 			pHandle->ch_prev = 0; | ||||
| 		} else { | ||||
| 			/* Link previous node to us (forward) */ | ||||
| 			m_Handles[pIdentity->ch_next].ch_next = handle; | ||||
| 			/* Link us to previous node (backwards) */ | ||||
| 			pHandle->ch_prev = pIdentity->ch_next; | ||||
| 			/* Set new tail */ | ||||
| 			pIdentity->ch_next = handle; | ||||
| 		} | ||||
| 		pIdentity->refcount++; | ||||
| 	} else { | ||||
| 		pHandle->ch_prev = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	return HandleError_None; | ||||
| } | ||||
| 
 | ||||
| Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityToken_t source, IdentityToken_t ident) | ||||
| void HandleSystem::SetTypeSecurityOwner(HandleType_t type, IdentityToken_t *pToken) | ||||
| { | ||||
| 	if (!type | ||||
| 		|| type >= HANDLESYS_TYPEARRAY_SIZE | ||||
| 		|| m_Types[type].dispatch == NULL) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	m_Types[type].sec.owner = pToken; | ||||
| } | ||||
| 
 | ||||
| Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityToken_t *source, IdentityToken_t *ident) | ||||
| { | ||||
| 	if (!type  | ||||
| 		|| type >= HANDLESYS_TYPEARRAY_SIZE | ||||
| @ -230,12 +289,11 @@ Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityTok | ||||
| 	QHandle *pHandle; | ||||
| 	HandleError err; | ||||
| 
 | ||||
| 	if ((err=MakePrimHandle(type, &pHandle, &index, &handle)) != HandleError_None) | ||||
| 	if ((err=MakePrimHandle(type, &pHandle, &index, &handle, source)) != HandleError_None) | ||||
| 	{ | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	pHandle->source = source; | ||||
| 	pHandle->object = object; | ||||
| 	pHandle->clone = 0; | ||||
| 
 | ||||
| @ -245,15 +303,35 @@ Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityTok | ||||
| Handle_t HandleSystem::CreateScriptHandle(HandleType_t type,  | ||||
| 										  void *object,  | ||||
| 										  sp_context_t *ctx,  | ||||
| 										  IdentityToken_t ident) | ||||
| 										  IdentityToken_t *ident) | ||||
| { | ||||
| 	IPlugin *pPlugin = g_PluginSys.FindPluginByContext(ctx); | ||||
| 
 | ||||
| 	return CreateHandle(type, object, pPlugin->GetIdentity(), ident); | ||||
| } | ||||
| 
 | ||||
| bool HandleSystem::TypeCheck(HandleType_t intype, HandleType_t outtype) | ||||
| { | ||||
| 	/* Check the type inheritance */ | ||||
| 	if (intype & HANDLESYS_SUBTYPE_MASK) | ||||
| 	{ | ||||
| 		if (intype != outtype | ||||
| 			&& (TypeParent(intype) != TypeParent(outtype))) | ||||
| 		{ | ||||
| 			return false; | ||||
| 		} | ||||
| 	} else { | ||||
| 		if (intype != outtype) | ||||
| 		{ | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| HandleError HandleSystem::GetHandle(Handle_t handle, | ||||
| 									IdentityToken_t ident,  | ||||
| 									IdentityToken_t *ident,  | ||||
| 									QHandle **in_pHandle,  | ||||
| 									unsigned int *in_index, | ||||
| 									HandleAccessRight access) | ||||
| @ -277,6 +355,11 @@ HandleError HandleSystem::GetHandle(Handle_t handle, | ||||
| 	if (!pHandle->set) | ||||
| 	{ | ||||
| 		return HandleError_Freed; | ||||
| 	} else if (pHandle->set == HandleSet_Identity | ||||
| 			   && ident != g_ShareSys.GetIdentRoot()) | ||||
| 	{ | ||||
| 		/* Only IdentityHandle() can read this! */ | ||||
| 		return HandleError_Identity; | ||||
| 	} | ||||
| 	if (pHandle->serial != serial) | ||||
| 	{ | ||||
| @ -289,7 +372,7 @@ HandleError HandleSystem::GetHandle(Handle_t handle, | ||||
| 	return HandleError_None; | ||||
| } | ||||
| 
 | ||||
| HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *out_newhandle, IdentityToken_t source, IdentityToken_t ident) | ||||
| HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *out_newhandle, IdentityToken_t *source, IdentityToken_t *ident) | ||||
| { | ||||
| 	HandleError err; | ||||
| 	QHandle *pHandle; | ||||
| @ -307,13 +390,12 @@ HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *out_newhandle, | ||||
| 	QHandle *pNewHandle; | ||||
| 	Handle_t new_handle; | ||||
| 
 | ||||
| 	if ((err=MakePrimHandle(pHandle->type, &pNewHandle, &new_index, &new_handle)) != HandleError_None) | ||||
| 	if ((err=MakePrimHandle(pHandle->type, &pNewHandle, &new_index, &new_handle, source)) != HandleError_None) | ||||
| 	{ | ||||
| 		return err; | ||||
| 	} | ||||
| 
 | ||||
| 	pNewHandle->clone = index; | ||||
| 	pNewHandle->source = source; | ||||
| 
 | ||||
| 	if (out_newhandle) | ||||
| 	{ | ||||
| @ -323,7 +405,7 @@ HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *out_newhandle, | ||||
| 	return HandleError_None; | ||||
| } | ||||
| 
 | ||||
| HandleError HandleSystem::FreeHandle(Handle_t handle, IdentityToken_t ident) | ||||
| HandleError HandleSystem::FreeHandle(Handle_t handle, IdentityToken_t *ident) | ||||
| { | ||||
| 	unsigned int index; | ||||
| 	QHandle *pHandle; | ||||
| @ -361,14 +443,9 @@ HandleError HandleSystem::FreeHandle(Handle_t handle, IdentityToken_t ident) | ||||
| 	return HandleError_None; | ||||
| } | ||||
| 
 | ||||
| inline HandleType_t TypeParent(HandleType_t type) | ||||
| { | ||||
| 	return (type & ~HANDLESYS_SUBTYPE_MASK); | ||||
| } | ||||
| 
 | ||||
| HandleError HandleSystem::ReadHandle(Handle_t handle,  | ||||
| 									 HandleType_t type,  | ||||
| 									 IdentityToken_t ident,  | ||||
| 									 IdentityToken_t *ident,  | ||||
| 									 void **object) | ||||
| { | ||||
| 	unsigned int index; | ||||
| @ -412,12 +489,59 @@ void HandleSystem::ReleasePrimHandle(unsigned int index) | ||||
| { | ||||
| 	QHandle *pHandle = &m_Handles[index]; | ||||
| 	 | ||||
| 	pHandle->set = false; | ||||
| 	pHandle->set = HandleSet_None; | ||||
| 	m_Types[pHandle->type].opened--; | ||||
| 	m_Handles[++m_FreeHandles].freeID = index; | ||||
| 
 | ||||
| 	/* Unlink us if necessary */ | ||||
| 	if (pHandle->owner) | ||||
| 	{ | ||||
| 		unsigned int ident_index; | ||||
| 		if (IdentityHandle(pHandle->owner, &ident_index) != HandleError_None) | ||||
| 		{ | ||||
| 			/* Uh-oh! */ | ||||
| 			assert(pHandle->owner == 0); | ||||
| 			return; | ||||
| 		} | ||||
| 		/* Note that since 0 is an invalid handle, if any of these links are 0,
 | ||||
| 		 * the data can still be set. | ||||
| 		 */ | ||||
| 		QHandle *pIdentity = &m_Handles[ident_index]; | ||||
| 
 | ||||
| 		/* Unlink case: We're the head AND tail node */ | ||||
| 		if (index == pIdentity->ch_prev && index == pIdentity->ch_next) | ||||
| 		{ | ||||
| 			pIdentity->ch_prev = 0; | ||||
| 			pIdentity->ch_next = 0; | ||||
| 		} | ||||
| 		/* Unlink case: We're the head node */ | ||||
| 		else if (index == pIdentity->ch_prev) { | ||||
| 			/* Link us to the next in the chain */ | ||||
| 			pIdentity->ch_prev = pHandle->ch_next; | ||||
| 			/* Patch up the previous link */ | ||||
| 			m_Handles[pHandle->ch_next].ch_prev = 0; | ||||
| 		} | ||||
| 		/* Unlink case: We're the tail node */ | ||||
| 		else if (index == pIdentity->ch_next) { | ||||
| 			/* Link us to the previous in the chain */ | ||||
| 			pIdentity->ch_next = pHandle->ch_prev; | ||||
| 			/* Patch up the next link */ | ||||
| 			m_Handles[pHandle->ch_prev].ch_next = 0; | ||||
| 		} | ||||
| 		/* Unlink case: We're in the middle! */ | ||||
| 		else { | ||||
| 			/* Patch the forward reference */ | ||||
| 			m_Handles[pHandle->ch_next].ch_prev = pHandle->ch_prev; | ||||
| 			/* Patch the backward reference */ | ||||
| 			m_Handles[pHandle->ch_prev].ch_next = pHandle->ch_next; | ||||
| 		} | ||||
| 
 | ||||
| 		/* Lastly, decrease the reference count */ | ||||
| 		pIdentity->refcount--; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t ident) | ||||
| bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t *ident) | ||||
| { | ||||
| 	if (type == 0 || type >= HANDLESYS_TYPEARRAY_SIZE) | ||||
| 	{ | ||||
| @ -499,3 +623,16 @@ bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t ident) | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| void HandleSystem::MarkHandleAsIdentity(Handle_t handle) | ||||
| { | ||||
| 	QHandle *pHandle; | ||||
| 	unsigned int index; | ||||
| 
 | ||||
| 	if (GetHandle(handle, g_ShareSys.GetIdentRoot(), &pHandle, &index, HandleAccess_Read) != HandleError_None) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	pHandle->set = HandleSet_Identity; | ||||
| } | ||||
|  | ||||
| @ -16,16 +16,46 @@ | ||||
| #define HANDLESYS_SERIAL_MASK		0xFFFF0000 | ||||
| #define HANDLESYS_HANDLE_MASK		0x0000FFFF | ||||
| 
 | ||||
| /**
 | ||||
|  *   The QHandle is a nasty structure that compacts the handle system into a big vector. | ||||
|  * The members of the vector each encapsulate one Handle, however, they also act as nodes | ||||
|  * in an inlined linked list and an inlined vector. | ||||
|  * | ||||
|  *   The first of these lists is the 'freeID' list.  Each node from 1 to N (where N | ||||
|  * is the number of free nodes) has a 'freeID' that specifies a free Handle ID.  This | ||||
|  * is a quick hack to get around allocating a second base vector. | ||||
|  * | ||||
|  *   The second vector is the identity linked list.  An identity has its own handle, so | ||||
|  * these handles are used as sentinel nodes for index linking.  They point to the first and last | ||||
|  * index into the handle array.  Each subsequent Handle who is owned by that indentity is mapped into | ||||
|  * that list.  This lets owning identities be unloaded in O(n) time. | ||||
|  * | ||||
|  *   Eventually, there may be a third list for type chains. | ||||
|  */ | ||||
| 
 | ||||
| enum HandleSet | ||||
| { | ||||
| 	HandleSet_None = 0, | ||||
| 	HandleSet_Used, | ||||
| 	HandleSet_Identity | ||||
| }; | ||||
| 
 | ||||
| struct QHandle | ||||
| { | ||||
| 	HandleType_t type;			/* Handle type */ | ||||
| 	void *object;				/* Unmaintained object pointer */ | ||||
| 	unsigned int freeID;		/* ID of a free handle in the free handle chain */ | ||||
| 	IdentityToken_t source;		/* Identity of object which owns this */ | ||||
| 	IdentityToken_t *owner;		/* Identity of object which owns this */ | ||||
| 	unsigned int serial;		/* Serial no. for sanity checking */ | ||||
| 	unsigned int refcount;		/* Reference count for safe destruction */ | ||||
| 	Handle_t clone;				/* If non-zero, this is our cloned parent */ | ||||
| 	bool set;					/* Whether or not this handle is set */ | ||||
| 	HandleSet set;				/* Information about the handle's state */ | ||||
| 	/* The following variables are unrelated to the Handle array, and used 
 | ||||
| 	 * as an inlined chain of information */ | ||||
| 	unsigned int freeID;		/* ID of a free handle in the free handle chain */ | ||||
| 	/* Indexes into the handle array for owner membership.
 | ||||
| 	 * For identity roots, these are treated as the head/tail. */ | ||||
| 	unsigned int ch_prev;		/* chained previous handle or HEAD */ | ||||
| 	unsigned int ch_next;		/* chained next handle or TAIL */ | ||||
| }; | ||||
| 
 | ||||
| struct QHandleType | ||||
| @ -41,6 +71,8 @@ struct QHandleType | ||||
| class HandleSystem :  | ||||
| 	public IHandleSys | ||||
| { | ||||
| 	friend HandleError IdentityHandle(IdentityToken_t *token, unsigned int *index); | ||||
| 	friend class ShareSystem; | ||||
| public: | ||||
| 	HandleSystem(); | ||||
| 	~HandleSystem(); | ||||
| @ -49,24 +81,26 @@ public: //IHandleSystem | ||||
| 	HandleType_t CreateTypeEx(const char *name,	 | ||||
| 							  IHandleTypeDispatch *dispatch,  | ||||
| 							  HandleType_t parent,  | ||||
| 							  const HandleSecurity *security); | ||||
| 							  const HandleSecurity *security, | ||||
| 							  IdentityToken_t *ident); | ||||
| 	HandleType_t CreateChildType(const char *name, HandleType_t parent, IHandleTypeDispatch *dispatch); | ||||
| 	bool RemoveType(HandleType_t type, IdentityToken_t ident); | ||||
| 	bool RemoveType(HandleType_t type, IdentityToken_t *ident); | ||||
| 	bool FindHandleType(const char *name, HandleType_t *type); | ||||
| 	Handle_t CreateHandle(HandleType_t type,  | ||||
| 							void *object,  | ||||
| 							IdentityToken_t source,  | ||||
| 							IdentityToken_t ident); | ||||
| 	Handle_t CreateScriptHandle(HandleType_t type, void *object, sp_context_t *ctx, IdentityToken_t ident); | ||||
| 	HandleError FreeHandle(Handle_t handle, IdentityToken_t ident); | ||||
| 	HandleError CloneHandle(Handle_t handle, Handle_t *newhandle, IdentityToken_t source, IdentityToken_t ident); | ||||
| 	HandleError ReadHandle(Handle_t handle, HandleType_t type, IdentityToken_t ident, void **object); | ||||
| private: | ||||
| 							IdentityToken_t *source,  | ||||
| 							IdentityToken_t *ident); | ||||
| 	Handle_t CreateScriptHandle(HandleType_t type, void *object, sp_context_t *ctx, IdentityToken_t *ident); | ||||
| 	HandleError FreeHandle(Handle_t handle, IdentityToken_t *ident); | ||||
| 	HandleError CloneHandle(Handle_t handle, Handle_t *newhandle, IdentityToken_t *source, IdentityToken_t *ident); | ||||
| 	HandleError ReadHandle(Handle_t handle, HandleType_t type, IdentityToken_t *ident, void **object); | ||||
| 	bool TypeCheck(HandleType_t intype, HandleType_t outtype); | ||||
| protected: | ||||
| 	/**
 | ||||
| 	 * Decodes a handle with sanity and security checking. | ||||
| 	 */ | ||||
| 	HandleError GetHandle(Handle_t handle,  | ||||
| 						  IdentityToken_t ident,  | ||||
| 						  IdentityToken_t *ident,  | ||||
| 						  QHandle **pHandle,  | ||||
| 						  unsigned int *index, | ||||
| 						  HandleAccessRight access); | ||||
| @ -75,12 +109,28 @@ private: | ||||
| 	 * Creates a basic handle and sets its reference count to 1. | ||||
| 	 * Does not do any type or security checking. | ||||
| 	 */ | ||||
| 	HandleError MakePrimHandle(HandleType_t type, QHandle **pHandle, unsigned int *index, HandleType_t *handle); | ||||
| 	HandleError MakePrimHandle(HandleType_t type,  | ||||
| 							   QHandle **pHandle,  | ||||
| 							   unsigned int *index,  | ||||
| 							   HandleType_t *handle, | ||||
| 							   IdentityToken_t *owner); | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * Frees a primitive handle.  Does no object freeing, only reference count and bookkeepping. | ||||
| 	 * Frees a primitive handle.  Does no object freeing, only reference count, bookkeepping,  | ||||
| 	 * and linked list maintenance. | ||||
| 	 */ | ||||
| 	void ReleasePrimHandle(unsigned int index); | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * Sets the security owner of a type | ||||
| 	 */ | ||||
| 	void SetTypeSecurityOwner(HandleType_t type, IdentityToken_t *pToken); | ||||
| 
 | ||||
| 	/** 
 | ||||
| 	 * Marks a handle as an identity. | ||||
| 	 * This prevents it from being tampered with by outside stuff | ||||
| 	 */ | ||||
| 	void MarkHandleAsIdentity(Handle_t handle); | ||||
| private: | ||||
| 	QHandle *m_Handles; | ||||
| 	QHandleType *m_Types; | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| #include <stdio.h> | ||||
| #include "PluginSys.h" | ||||
| #include "ShareSys.h" | ||||
| #include "LibrarySys.h" | ||||
| #include "HandleSys.h" | ||||
| #include "sourcemm_api.h" | ||||
| @ -8,6 +9,7 @@ | ||||
| 
 | ||||
| CPluginManager g_PluginSys; | ||||
| HandleType_t g_PluginType = 0; | ||||
| IdentityType_t g_PluginIdent = 0; | ||||
| 
 | ||||
| CPlugin::CPlugin(const char *file) | ||||
| { | ||||
| @ -22,8 +24,8 @@ CPlugin::CPlugin(const char *file) | ||||
| 	m_pub_funcs = NULL; | ||||
| 	m_errormsg[256] = '\0'; | ||||
| 	snprintf(m_filename, sizeof(m_filename), "%s", file); | ||||
| 	/* :TODO: ShareSys token */ | ||||
| 	m_handle = g_HandleSys.CreateHandle(g_PluginType, this, DEFAULT_IDENTITY, 1); | ||||
| 	m_handle = 0; | ||||
| 	m_ident = NULL; | ||||
| } | ||||
| 
 | ||||
| CPlugin::~CPlugin() | ||||
| @ -70,7 +72,20 @@ CPlugin::~CPlugin() | ||||
| 		m_plugin = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	g_HandleSys.FreeHandle(m_handle, g_PluginType); | ||||
| 	if (m_handle) | ||||
| 	{ | ||||
| 		g_HandleSys.FreeHandle(m_handle, g_PluginSys.GetIdentity()); | ||||
| 		g_ShareSys.DestroyIdentity(m_ident); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void CPlugin::InitIdentity() | ||||
| { | ||||
| 	if (!m_handle) | ||||
| 	{ | ||||
| 		m_ident = g_ShareSys.CreateIdentity(g_PluginIdent); | ||||
| 		m_handle = g_HandleSys.CreateHandle(g_PluginType, this, g_PluginSys.GetIdentity(), g_PluginSys.GetIdentity()); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| CPlugin *CPlugin::CreatePlugin(const char *file, char *error, size_t maxlength) | ||||
| @ -447,9 +462,9 @@ bool CPlugin::SetPauseState(bool paused) | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| IdentityToken_t CPlugin::GetIdentity() | ||||
| IdentityToken_t *CPlugin::GetIdentity() | ||||
| { | ||||
| 	return 0; | ||||
| 	return m_ident; | ||||
| } | ||||
| 
 | ||||
| /*******************
 | ||||
| @ -499,6 +514,7 @@ CPluginManager::CPluginManager() | ||||
| { | ||||
| 	m_LoadLookup = sm_trie_create(); | ||||
| 	m_AllPluginsLoaded = false; | ||||
| 	m_MyIdent = NULL; | ||||
| } | ||||
| 
 | ||||
| CPluginManager::~CPluginManager() | ||||
| @ -661,6 +677,7 @@ void CPluginManager::LoadAutoPlugin(const char *file) | ||||
| 	if (pPlugin->GetStatus() == Plugin_Created) | ||||
| 	{ | ||||
| 		AddCoreNativesToPlugin(pPlugin); | ||||
| 		pPlugin->InitIdentity(); | ||||
| 		pPlugin->Call_AskPluginLoad(NULL, 0); | ||||
| 	} | ||||
| 
 | ||||
| @ -712,6 +729,8 @@ IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType typ | ||||
| 
 | ||||
| 	AddCoreNativesToPlugin(pPlugin); | ||||
| 
 | ||||
| 	pPlugin->InitIdentity(); | ||||
| 
 | ||||
| 	/* Finally, ask the plugin if it wants to be loaded */ | ||||
| 	if (!pPlugin->Call_AskPluginLoad(error, err_max)) | ||||
| 	{ | ||||
| @ -1092,20 +1111,25 @@ bool CPluginManager::IsLateLoadTime() | ||||
| 
 | ||||
| void CPluginManager::OnSourceModAllInitialized() | ||||
| { | ||||
| 	m_MyIdent = g_ShareSys.CreateCoreIdentity(); | ||||
| 
 | ||||
| 	HandleSecurity sec; | ||||
| 
 | ||||
| 	sec.owner = 1;	/* :TODO: implement ShareSys */ | ||||
| 	sec.owner = m_MyIdent;	/* :TODO: implement ShareSys */ | ||||
| 	sec.access[HandleAccess_Create] = false; | ||||
| 	sec.access[HandleAccess_Delete] = false; | ||||
| 	sec.access[HandleAccess_Inherit] = false; | ||||
| 	sec.access[HandleAccess_Clone] = false; | ||||
| 	 | ||||
| 	g_PluginType = g_HandleSys.CreateTypeEx("IPlugin", this, 0, &sec); | ||||
| 	g_PluginType = g_HandleSys.CreateTypeEx("IPlugin", this, 0, &sec, NULL); | ||||
| 	g_PluginIdent = g_ShareSys.CreateIdentType("PLUGIN"); | ||||
| } | ||||
| 
 | ||||
| void CPluginManager::OnSourceModShutdown() | ||||
| { | ||||
| 	g_HandleSys.RemoveType(g_PluginType, 1); | ||||
| 	g_HandleSys.RemoveType(g_PluginType, m_MyIdent); | ||||
| 	g_ShareSys.DestroyIdentType(g_PluginIdent); | ||||
| 	g_ShareSys.DestroyIdentity(m_MyIdent); | ||||
| } | ||||
| 
 | ||||
| void CPluginManager::OnHandleDestroy(HandleType_t type, void *object) | ||||
|  | ||||
| @ -93,7 +93,7 @@ public: | ||||
| 	virtual const sp_plugin_t *GetPluginStructure() const; | ||||
| 	virtual IPluginFunction *GetFunctionByName(const char *public_name); | ||||
| 	virtual IPluginFunction *GetFunctionById(funcid_t func_id); | ||||
| 	virtual IdentityToken_t GetIdentity(); | ||||
| 	virtual IdentityToken_t *GetIdentity(); | ||||
| public: | ||||
| 	/**
 | ||||
| 	 * Creates a plugin object with default values. | ||||
| @ -114,11 +114,17 @@ public: | ||||
| 	 */ | ||||
| 	bool FinishMyCompile(char *error, size_t maxlength); | ||||
| 	void CancelMyCompile(); | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * Sets an error state on the plugin | ||||
| 	 */ | ||||
| 	void SetErrorState(PluginStatus status, const char *error_fmt, ...); | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * Initializes the plugin's identity information | ||||
| 	 */ | ||||
| 	void InitIdentity(); | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * Calls the OnPluginLoad function, and sets any failed states if necessary. | ||||
| 	 * NOTE: Valid pre-states are: Plugin_Created | ||||
| @ -151,6 +157,7 @@ private: | ||||
| 	CFunction **m_pub_funcs; | ||||
| 	char m_errormsg[256]; | ||||
| 	time_t m_LastAccess; | ||||
| 	IdentityToken_t *m_ident; | ||||
| 	Handle_t m_handle; | ||||
| }; | ||||
| 
 | ||||
| @ -262,6 +269,10 @@ protected: | ||||
| 	void ReleaseIterator(CPluginIterator *iter); | ||||
| 	CFunction *GetFunctionFromPool(funcid_t f, CPlugin *plugin); | ||||
| 	void ReleaseFunctionToPool(CFunction *func); | ||||
| 	inline IdentityToken_t *GetIdentity() | ||||
| 	{ | ||||
| 		return m_MyIdent; | ||||
| 	} | ||||
| private: | ||||
| 	List<IPluginsListener *> m_listeners; | ||||
| 	List<CPlugin *> m_plugins; | ||||
| @ -271,6 +282,7 @@ private: | ||||
| 	CPluginInfoDatabase m_PluginInfo; | ||||
| 	Trie *m_LoadLookup; | ||||
| 	bool m_AllPluginsLoaded; | ||||
| 	IdentityToken_t *m_MyIdent; | ||||
| }; | ||||
| 
 | ||||
| extern CPluginManager g_PluginSys; | ||||
|  | ||||
							
								
								
									
										195
									
								
								core/systems/ShareSys.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								core/systems/ShareSys.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,195 @@ | ||||
| #include "ShareSys.h" | ||||
| #include "HandleSys.h" | ||||
| 
 | ||||
| ShareSystem g_ShareSys; | ||||
| 
 | ||||
| ShareSystem::ShareSystem() | ||||
| { | ||||
| 	m_IdentRoot.ident = 0; | ||||
| 	m_TypeRoot = 0; | ||||
| 	m_IfaceType = 0; | ||||
| 	m_CoreType = 0; | ||||
| } | ||||
| 
 | ||||
| IdentityToken_t *ShareSystem::CreateCoreIdentity() | ||||
| { | ||||
| 	if (!m_CoreType) | ||||
| 	{ | ||||
| 		m_CoreType = CreateIdentType("CORE"); | ||||
| 	} | ||||
| 
 | ||||
| 	return CreateIdentity(m_CoreType); | ||||
| } | ||||
| 
 | ||||
| void ShareSystem::OnSourceModStartup(bool late) | ||||
| { | ||||
| 	HandleSecurity sec; | ||||
| 
 | ||||
| 	sec.owner = GetIdentRoot(); | ||||
| 	sec.access[HandleAccess_Inherit] = false; | ||||
| 	sec.access[HandleAccess_Delete] = false; | ||||
| 	 | ||||
| 	m_TypeRoot = g_HandleSys.CreateTypeEx("Identity", this, 0, &sec, NULL); | ||||
| 	m_IfaceType = g_HandleSys.CreateTypeEx("Interface", this, 0, &sec, NULL); | ||||
| 
 | ||||
| 	/* Initialize our static identity handle */ | ||||
| 	m_IdentRoot.ident = g_HandleSys.CreateHandle(m_TypeRoot, NULL, NULL, NULL); | ||||
| } | ||||
| 
 | ||||
| void ShareSystem::OnSourceModShutdown() | ||||
| { | ||||
| 	if (m_CoreType) | ||||
| 	{ | ||||
| 		g_HandleSys.RemoveType(m_CoreType, GetIdentRoot()); | ||||
| 	} | ||||
| 
 | ||||
| 	g_HandleSys.RemoveType(m_IfaceType, GetIdentRoot()); | ||||
| 	g_HandleSys.RemoveType(m_TypeRoot, GetIdentRoot()); | ||||
| } | ||||
| 
 | ||||
| IdentityType_t ShareSystem::FindIdentType(const char *name) | ||||
| { | ||||
| 	HandleType_t type; | ||||
| 
 | ||||
| 	if (g_HandleSys.FindHandleType(name, &type)) | ||||
| 	{ | ||||
| 		if (g_HandleSys.TypeCheck(type, m_TypeRoot)) | ||||
| 		{ | ||||
| 			return type; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| IdentityType_t ShareSystem::CreateIdentType(const char *name) | ||||
| { | ||||
| 	if (!m_TypeRoot) | ||||
| 	{ | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	return g_HandleSys.CreateTypeEx(name, this, m_TypeRoot, NULL, GetIdentRoot()); | ||||
| } | ||||
| 
 | ||||
| void ShareSystem::OnHandleDestroy(HandleType_t type, void *object) | ||||
| { | ||||
| 	/* We don't care here */ | ||||
| } | ||||
| 
 | ||||
| IdentityToken_t *ShareSystem::CreateIdentity(IdentityType_t type) | ||||
| { | ||||
| 	if (!m_TypeRoot) | ||||
| 	{ | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	/* :TODO: Cache? */ | ||||
| 	IdentityToken_t *pToken = new IdentityToken_t; | ||||
| 	pToken->ident = g_HandleSys.CreateHandle(type, NULL, NULL, GetIdentRoot()); | ||||
| 
 | ||||
| 	return pToken; | ||||
| } | ||||
| 
 | ||||
| bool ShareSystem::AddInterface(SMInterface *iface, IdentityToken_t *token) | ||||
| { | ||||
| 	if (!iface) | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	IfaceInfo info; | ||||
| 
 | ||||
| 	info.iface = iface; | ||||
| 	info.token = token; | ||||
| 	 | ||||
| 	if (token) | ||||
| 	{ | ||||
| 		/* If we're an external object, we have to do this */ | ||||
| 		info.handle = g_HandleSys.CreateHandle(m_IfaceType, iface, token, GetIdentRoot()); | ||||
| 	} else { | ||||
| 		info.handle = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	m_Interfaces.push_back(info); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| bool ShareSystem::RequestInterface(const char *iface_name,  | ||||
| 								   unsigned int iface_vers,  | ||||
| 								   IdentityToken_t *token,  | ||||
| 								   SMInterface **pIface) | ||||
| { | ||||
| 	/* If Some yahoo.... SOME HOOLIGAN... some NO GOOD DIRTY 
 | ||||
| 	 * HORRIBLE PERSON passed in a token that we don't recognize.... | ||||
| 	 * <b>Punish them.</b> | ||||
| 	 */ | ||||
| 	if (!g_HandleSys.ReadHandle(token->ident, m_TypeRoot, GetIdentRoot(), NULL)) | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	/* See if the interface exists */ | ||||
| 	List<IfaceInfo>::iterator iter; | ||||
| 	SMInterface *iface; | ||||
| 	IdentityToken_t *iface_owner; | ||||
| 	Handle_t iface_handle; | ||||
| 	bool found = false; | ||||
| 	for (iter=m_Interfaces.begin(); iter!=m_Interfaces.end(); iter++) | ||||
| 	{ | ||||
| 		IfaceInfo &info = (*iter); | ||||
| 		iface = info.iface; | ||||
| 		if (strcmp(iface->GetInterfaceName(), iface_name) == 0) | ||||
| 		{ | ||||
| 			if (iface->GetInterfaceVersion() == iface_vers | ||||
| 				|| iface->IsVersionCompatible(iface_vers)) | ||||
| 			{ | ||||
| 				iface_owner = info.token; | ||||
| 				iface_handle = info.handle; | ||||
| 				found = true; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (!found) | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	/* If something external owns this, we need to track it. */ | ||||
| 	if (iface_owner) | ||||
| 	{ | ||||
| 		Handle_t newhandle; | ||||
| 		if (g_HandleSys.CloneHandle(iface_handle, &newhandle, token, GetIdentRoot()) | ||||
| 			!= HandleError_None) | ||||
| 		{ | ||||
| 			return false; | ||||
| 		} | ||||
| 		/** 
 | ||||
| 		 * Now we can deny module loads based on dependencies. | ||||
| 		 */ | ||||
| 	} | ||||
| 
 | ||||
| 	/* :TODO: finish */ | ||||
| 
 | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| void ShareSystem::AddNatives(IdentityToken_t *token, const sp_nativeinfo_t *natives[]) | ||||
| { | ||||
| 	/* :TODO: implement */ | ||||
| } | ||||
| 
 | ||||
| void ShareSystem::DestroyIdentity(IdentityToken_t *identity) | ||||
| { | ||||
| 	g_HandleSys.FreeHandle(identity->ident, GetIdentRoot()); | ||||
| 	delete identity; | ||||
| } | ||||
| 
 | ||||
| void ShareSystem::DestroyIdentType(IdentityType_t type) | ||||
| { | ||||
| 	g_HandleSys.RemoveType(type, GetIdentRoot()); | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										69
									
								
								core/systems/ShareSys.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								core/systems/ShareSys.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,69 @@ | ||||
| #ifndef _INCLUDE_SOURCEMOD_SHARESYSTEM_H_ | ||||
| #define _INCLUDE_SOURCEMOD_SHARESYSTEM_H_ | ||||
| 
 | ||||
| #include <IShareSys.h> | ||||
| #include <IHandleSys.h> | ||||
| #include <sh_list.h> | ||||
| #include "sm_globals.h" | ||||
| #include "sourcemod.h" | ||||
| 
 | ||||
| using namespace SourceHook; | ||||
| 
 | ||||
| namespace SourceMod | ||||
| { | ||||
| 	struct IdentityToken_t | ||||
| 	{ | ||||
| 		Handle_t ident; | ||||
| 	}; | ||||
| }; | ||||
| 
 | ||||
| struct IfaceInfo | ||||
| { | ||||
| 	SMInterface *iface; | ||||
| 	IdentityToken_t *token; | ||||
| 	Handle_t handle; | ||||
| }; | ||||
| 
 | ||||
| class ShareSystem :  | ||||
| 	public IShareSys, | ||||
| 	public SMGlobalClass, | ||||
| 	public IHandleTypeDispatch | ||||
| { | ||||
| public: | ||||
| 	ShareSystem(); | ||||
| public: //IShareSys
 | ||||
| 	bool AddInterface(SMInterface *iface, IdentityToken_t *token); | ||||
| 	bool RequestInterface(const char *iface_name,  | ||||
| 		unsigned int iface_vers, | ||||
| 		IdentityToken_t *token, | ||||
| 		SMInterface **pIface); | ||||
| 	void AddNatives(IdentityToken_t *token, const sp_nativeinfo_t *natives[]); | ||||
| 	IdentityType_t CreateIdentType(const char *name); | ||||
| 	IdentityType_t FindIdentType(const char *name); | ||||
| 	IdentityToken_t *CreateIdentity(IdentityType_t type); | ||||
| 	void DestroyIdentType(IdentityType_t type); | ||||
| 	void DestroyIdentity(IdentityToken_t *identity); | ||||
| public: //SMGlobalClass
 | ||||
| 	/* Pre-empt in case anything tries to register idents early */ | ||||
| 	void OnSourceModStartup(bool late); | ||||
| 	void OnSourceModShutdown(); | ||||
| public: //IHandleTypeDispatch
 | ||||
| 	void OnHandleDestroy(HandleType_t type, void *object); | ||||
| public: | ||||
| 	IdentityToken_t *CreateCoreIdentity(); | ||||
| public: | ||||
| 	inline IdentityToken_t *GetIdentRoot() | ||||
| 	{ | ||||
| 		return &m_IdentRoot; | ||||
| 	} | ||||
| private: | ||||
| 	List<IfaceInfo> m_Interfaces; | ||||
| 	HandleType_t m_TypeRoot; | ||||
| 	IdentityToken_t m_IdentRoot; | ||||
| 	HandleType_t m_IfaceType; | ||||
| 	IdentityType_t m_CoreType; | ||||
| }; | ||||
| 
 | ||||
| extern ShareSystem g_ShareSys; | ||||
| 
 | ||||
| #endif //_INCLUDE_SOURCEMOD_SHARESYSTEM_H_
 | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user