<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.alliedmods.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Nefarius</id>
	<title>AlliedModders Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.alliedmods.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Nefarius"/>
	<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/Special:Contributions/Nefarius"/>
	<updated>2026-05-08T18:13:38Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.6</generator>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Handle_API_(SourceMod)&amp;diff=9593</id>
		<title>Handle API (SourceMod)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Handle_API_(SourceMod)&amp;diff=9593"/>
		<updated>2014-06-09T19:25:25Z</updated>

		<summary type="html">&lt;p&gt;Nefarius: /* Implementing the Native */ Corrected misspelled variable names&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The SourceMod [[Handles (SourceMod Scripting)|Handle System]] marshals pointers into typed, unique, 32-bit integers.  This makes coding in SourceMod more cross-platform compatible, type safe, and mistake safe than its predecessor, [[AMX Mod X]].  It also allows for safe object sharing and reference count based object destruction.&lt;br /&gt;
&lt;br /&gt;
The fundamental aspect of Handles is that they encapsulate a single pointer.  This pointer is private data, and can only be read by the Handle's creator.  When the Handle is freed, the pointer is automatically freed (via a special interface), thus ensuring that memory is not leaked.&lt;br /&gt;
&lt;br /&gt;
Handles also provide a simple &amp;quot;security&amp;quot; system for restricting which areas of SourceMod are allowed to directly call certain functions on Handles under a given type.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Basic Types=&lt;br /&gt;
==Handle_t==&lt;br /&gt;
The &amp;lt;tt&amp;gt;Handle_t&amp;lt;/tt&amp;gt; type is a 32bit integer.  Currently, it is composed of two 16-bit integers, a serial number and a handle index.  The serial number is private and used for integrity checking.  The index is the internal ID of the Handle, which is tied to the encapsulated pointer and security information.&lt;br /&gt;
&lt;br /&gt;
Each &amp;lt;tt&amp;gt;Handle_t&amp;lt;/tt&amp;gt; is a unique Handle, however, there are ''cloned'' Handles which are copies of another Handle.  They have their own unique signatures, but they refer to another Handle internally.  Each Handle is also associated with a ''type'', explained below.&lt;br /&gt;
&lt;br /&gt;
==HandleType_t==&lt;br /&gt;
The &amp;lt;tt&amp;gt;HandleType_t&amp;lt;/tt&amp;gt; describes a type under which Handles can be created.  Types can have up to 15 sub-types; sub-types can also have their own sub-types, called child types.  When Handles are being read, they are &amp;quot;type checked,&amp;quot; to make sure they are being read under a given type.  When a type is destroyed, all Handles under the type are destroyed.  If the type has child types, each child type is also destroyed. &lt;br /&gt;
&lt;br /&gt;
Handle types also allow overloading of various Handle operations.  Currently, the only overloaded action is for overloading when a Handle is destroyed.  This allows the encapsulated pointer to be safely destroyed by the type interface.  The interface which overloads type operations is called &amp;lt;tt&amp;gt;IHandleTypeDispatch&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Lastly, types provide a &amp;quot;default security&amp;quot; system which lets programmers restrict which functions can be accessed by other areas in SourceMod.  This is explained later.&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
'''Note:''' Type defaults can be set via &amp;lt;tt&amp;gt;IHandleSys::InitAccessDefaults()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Type Security==&lt;br /&gt;
Often, extensions may want to share HandleType_t values with each other, so they can create Handles of external types.  However, the owner of the handle type may not want other extensions to perform certain actions.  Thus, types can be ''secured'' by an &amp;lt;tt&amp;gt;IdentityToken_t&amp;lt;/tt&amp;gt; when created.  Unless the same &amp;lt;tt&amp;gt;IdentityToken&amp;lt;/tt&amp;gt; is provided, a function may fail if restricted.&lt;br /&gt;
&lt;br /&gt;
Type permissions are declared in a &amp;lt;tt&amp;gt;TypeAccess&amp;lt;/tt&amp;gt; struct, which has the following user-set members:&lt;br /&gt;
*&amp;lt;tt&amp;gt;ident&amp;lt;/tt&amp;gt;: The &amp;lt;tt&amp;gt;IdentityToken_t&amp;lt;/tt&amp;gt; owner of this type.&lt;br /&gt;
*&amp;lt;tt&amp;gt;access&amp;lt;/tt&amp;gt;: An array where each index is a &amp;lt;tt&amp;gt;HTypeAccessRight&amp;lt;/tt&amp;gt; enumeration member.  If an index is set to false, functions requiring that right will fail unless the correct &amp;lt;tt&amp;gt;IdentityToken_t&amp;lt;/tt&amp;gt; is passed in.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;HTypeAccessRight&amp;lt;/tt&amp;gt; enumeration has the following values:&lt;br /&gt;
*&amp;lt;tt&amp;gt;HTypeAccess_Create&amp;lt;/tt&amp;gt;: Handle creation using this type; default is false.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HTypeAccess_Inherit&amp;lt;/tt&amp;gt;: Inheriting this type for child types; default is false.&lt;br /&gt;
&lt;br /&gt;
Below is a list of each Handle System function that requires type permissions, and which permissions may be required:&lt;br /&gt;
*&amp;lt;tt&amp;gt;CreateType&amp;lt;/tt&amp;gt;: &amp;lt;i&amp;gt;&amp;lt;tt&amp;gt;HTypeAccess_Inherit&amp;lt;/tt&amp;gt; if a parent is specified&amp;lt;/i&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;RemoveType&amp;lt;/tt&amp;gt;: &amp;lt;i&amp;gt;(none, always secured)&amp;lt;/i&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;CreateHandle&amp;lt;/tt&amp;gt;: &amp;lt;i&amp;gt;&amp;lt;tt&amp;gt;HTypeAccess_Create&amp;lt;/tt&amp;gt;&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Handle Security==&lt;br /&gt;
Handle security permissions inherit from their parent type unless given an alternate set of permissions.  Handles are &amp;quot;secured&amp;quot; by two properties, unlike Handles, which just have one.  When verifying your identity with a secured Handle function, you must use the &amp;lt;tt&amp;gt;HandleSecurity&amp;lt;/tt&amp;gt; struct, which has two properties:&lt;br /&gt;
*&amp;lt;tt&amp;gt;pOwner&amp;lt;/tt&amp;gt;: The owner of the Handle, which is usually a plugin &amp;lt;tt&amp;gt;IdentityToken_t&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;pIdentity&amp;lt;/tt&amp;gt;: The owner of the Handle's type, or the &amp;lt;tt&amp;gt;IdentityToken_t&amp;lt;/tt&amp;gt; securing its type.&lt;br /&gt;
&lt;br /&gt;
Handle permissions are specified via the &amp;lt;tt&amp;gt;HandleAccess&amp;lt;/tt&amp;gt; struct.  It is passed either through &amp;lt;tt&amp;gt;CreateType&amp;lt;/tt&amp;gt; for default settings in a given type, or through &amp;lt;tt&amp;gt;CreateHandleEx&amp;lt;/tt&amp;gt; for explicit per-Handle permissions.  This struct has the following members:&lt;br /&gt;
*&amp;lt;tt&amp;gt;access&amp;lt;/tt&amp;gt;: An array where each index is a &amp;lt;tt&amp;gt;HandleAccessRight&amp;lt;/tt&amp;gt; enumeration member.  If set to 0, an access right is allowed without a &amp;lt;tt&amp;gt;HandleSecurity&amp;lt;/tt&amp;gt; instance.  Otherwise, the following bitwise flags are checked:&lt;br /&gt;
**&amp;lt;tt&amp;gt;HANDLE_RESTRICT_IDENTITY&amp;lt;/tt&amp;gt;: If flagged, this access right is only granted if the &amp;lt;tt&amp;gt;pIdentity&amp;lt;/tt&amp;gt; member of the &amp;lt;tt&amp;gt;HandleSecurity&amp;lt;/tt&amp;gt; struct matches the Handle's '''type's''' owner.&lt;br /&gt;
**&amp;lt;tt&amp;gt;HANDLE_RESTRICT_OWNER&amp;lt;/tt&amp;gt;: If flagged, this access right is onyl granted if the &amp;lt;tt&amp;gt;pOwner&amp;lt;/tt&amp;gt; member of the &amp;lt;tt&amp;gt;Handlesecurity&amp;lt;/tt&amp;gt; struct matches the Handle's owner.&lt;br /&gt;
&lt;br /&gt;
The following access rights exist for Handles:&lt;br /&gt;
*&amp;lt;tt&amp;gt;HandleAccess_Read&amp;lt;/tt&amp;gt;: This Handle's encapsulated pointer can be retrieved.  Defaults to &amp;lt;tt&amp;gt;HANDLE_RESTRICT_IDENTITY&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HandleAccess_Delete&amp;lt;/tt&amp;gt;: This Handle can be removed or freed.  Defaults to &amp;lt;tt&amp;gt;HANDLE_RESTRICT_OWNER&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HandleAccess_Clone&amp;lt;/tt&amp;gt;: This Handle can be cloned.  Defaults to 0.&lt;br /&gt;
&lt;br /&gt;
Below is a list of each Handle system function that requires permissions, and which permissions may be required:&lt;br /&gt;
*&amp;lt;tt&amp;gt;FreeHandle&amp;lt;/tt&amp;gt;: &amp;lt;i&amp;gt;&amp;lt;tt&amp;gt;HandleAccess_Delete&amp;lt;/tt&amp;gt;&amp;lt;/i&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;CloneHandle/CloneHandleEx&amp;lt;/tt&amp;gt;: &amp;lt;i&amp;gt;&amp;lt;tt&amp;gt;HandleAccess_Clone&amp;lt;/tt&amp;gt;&amp;lt;/i&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;ReadHandle&amp;lt;/tt&amp;gt;: &amp;lt;i&amp;gt;&amp;lt;tt&amp;gt;HandleAccess_Read&amp;lt;/tt&amp;gt;&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
SourceMod's generic native wrappers assume follow these rules, however, they assume certain access rights, and will return &amp;lt;tt&amp;gt;INVALID_HANDLE&amp;lt;/tt&amp;gt; or 0 if these rights are denied.  Thus, you should make sure your permissions are compatible, unless you explicitly want to deny usage of these functions.&lt;br /&gt;
*&amp;lt;tt&amp;gt;CloneHandle()&amp;lt;/tt&amp;gt;: Passes &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;HandleSecurity&amp;lt;/tt&amp;gt;, meaning &amp;lt;tt&amp;gt;HandleAccess_Clone&amp;lt;/tt&amp;gt; must be 0.&lt;br /&gt;
*&amp;lt;tt&amp;gt;CloseHandle()&amp;lt;/tt&amp;gt;: Passes &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;HandleSecurity::pIdentity&amp;lt;/tt&amp;gt;, and the plugin's &amp;lt;tt&amp;gt;IdentityToken_t&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;HandleSecurity::pOwner&amp;lt;/tt/&amp;gt;.  This means that at most, the only restriction can be &amp;lt;tt&amp;gt;HANDLE_RESTRICT_OWNER&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;HandleAccess_Delete&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Usage Examples=&lt;br /&gt;
Here are some examples of Handle usages.&lt;br /&gt;
&lt;br /&gt;
==Basic Handles==&lt;br /&gt;
The most basic use of Handles is to encapsulate a data structure and allow &amp;lt;tt&amp;gt;CloseHandle&amp;lt;/tt&amp;gt; to universally destroy it.  Let's say we want to implement two natives - &amp;lt;tt&amp;gt;CreateFile&amp;lt;/tt&amp;gt; for creating an empty file, and &amp;lt;tt&amp;gt;WriteLine&amp;lt;/tt&amp;gt; for writing a line to this file.  How could we implement this using the Handle system?&lt;br /&gt;
&lt;br /&gt;
After reading this, it is tempting to think, &amp;quot;Why can't we just return the &amp;lt;tt&amp;gt;FILE&amp;lt;/tt&amp;gt; pointer as a &amp;lt;tt&amp;gt;cell_t&amp;lt;/tt&amp;gt;?&amp;quot;  The reason is that a &amp;lt;tt&amp;gt;cell_t&amp;lt;/tt&amp;gt; is guaranteed to be a 32bit integer.  There is no guarantee that a pointer will always be this size, however, and thus casting on future platforms could break.  This problem happened in [[AMX Mod X]] and greatly restricted flexibility.  &lt;br /&gt;
&lt;br /&gt;
===Creating the type===&lt;br /&gt;
First, we have to create the type and its Dispatch interface.&lt;br /&gt;
&amp;lt;cpp&amp;gt;HandleType_t g_FileType = 0;	/* Holds the HandleType ID */&lt;br /&gt;
&lt;br /&gt;
class FileTypeHandler : public IHandleTypeDispatch&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
	void OnHandleDestroy(HandleType_t type, void *object)&lt;br /&gt;
	{&lt;br /&gt;
		/* :TODO: implement this */&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* Create an instance of the handler */&lt;br /&gt;
FileTypeHandler g_FileTypeHandler;&lt;br /&gt;
&lt;br /&gt;
Initialize()&lt;br /&gt;
{&lt;br /&gt;
	/* Register the type with default security permissions */&lt;br /&gt;
	g_FileType = g_pHandleSys-&amp;gt;CreateType(&amp;quot;File&amp;quot;, &lt;br /&gt;
		&amp;amp;g_FileTypeHandler, &lt;br /&gt;
		0, &lt;br /&gt;
		NULL, &lt;br /&gt;
		NULL, &lt;br /&gt;
		myself-&amp;gt;GetIdentity(), &lt;br /&gt;
		NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Shutdown()&lt;br /&gt;
{&lt;br /&gt;
	/* Remove the type on shutdown */&lt;br /&gt;
	g_pHandleSys-&amp;gt;RemoveType(g_FileType, myself-&amp;gt;GetIdentity());&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creating Handles===&lt;br /&gt;
Creating the Handles is fairly easy once we have a valid pointer to stuff in it.&lt;br /&gt;
&amp;lt;cpp&amp;gt;/* native CreateFile(const String:file[]) */&lt;br /&gt;
static cell_t sm_CreateFile(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	char path[PLATFORM_MAX_PATH];&lt;br /&gt;
	char *filename;&lt;br /&gt;
&lt;br /&gt;
	/* Get the filename */&lt;br /&gt;
	pContext-&amp;gt;LocalToString(params[1], &amp;amp;filename);&lt;br /&gt;
	/* Build a full path */&lt;br /&gt;
	g_pSM-&amp;gt;BuildPath(Path_SM, path, sizeof(path), &amp;quot;%s&amp;quot;, filename);&lt;br /&gt;
	&lt;br /&gt;
	/* Open for writing */&lt;br /&gt;
	FILE *fp = fopen(path, &amp;quot;wt&amp;quot;);&lt;br /&gt;
	if (!fp)&lt;br /&gt;
	{&lt;br /&gt;
		return BAD_HANDLE;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Create the Handle with our type, the FILE pointer, the plugin's identity, and our identity */&lt;br /&gt;
	return g_pHandleSys-&amp;gt;CreateHandle(g_FileType, &lt;br /&gt;
		fp, &lt;br /&gt;
		pContext-&amp;gt;GetIdentity(), &lt;br /&gt;
		myself-&amp;gt;GetIdentity(), &lt;br /&gt;
		NULL);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Reading/Checking Handles===&lt;br /&gt;
Handles aren't very useful unless you have natives to use them.  Let's say we want to write lines of text to our File type.&lt;br /&gt;
&amp;lt;cpp&amp;gt;/* native WriteLine(Handle:hndl, const String:line[]); */&lt;br /&gt;
static cell_t sm_WriteLine(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	Handle_t hndl = static_cast&amp;lt;Handle_t&amp;gt;(params[1]);&lt;br /&gt;
	HandleError err;&lt;br /&gt;
	HandleSecurity sec;&lt;br /&gt;
&lt;br /&gt;
	/* Build our security descriptor */&lt;br /&gt;
	sec.pOwner = NULL;	/* Not needed, owner access is not checked */&lt;br /&gt;
	sec.pIdentity = myself-&amp;gt;GetIdentity();	/* But only this extension can read */&lt;br /&gt;
&lt;br /&gt;
	/* Attempt to read the given handle as our type, using our security info.&lt;br /&gt;
	 * Note that we read the pointer directly in with a little cast.&lt;br /&gt;
	 * This type of cast is safe since sizeof(void **) == sizeof(void *) == sizeof(T *) in almost all cases.&lt;br /&gt;
	 */&lt;br /&gt;
	FILE *fp;&lt;br /&gt;
	if ((err = g_pHandleSys-&amp;gt;ReadHandle(hndl, g_FileType, &amp;amp;sec, (void **)&amp;amp;fp))&lt;br /&gt;
	     != HandleError_None)&lt;br /&gt;
	{&lt;br /&gt;
		return pContext-&amp;gt;ThrowNativeError(&amp;quot;Invalid file handle %x (error %d)&amp;quot;, hndl, err);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get the text */&lt;br /&gt;
	char *text;&lt;br /&gt;
	pContext-&amp;gt;LocalToString(params[2], &amp;amp;text);&lt;br /&gt;
&lt;br /&gt;
	/* Write it */&lt;br /&gt;
	fputs(text, fp);&lt;br /&gt;
&lt;br /&gt;
	return 1;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===CloseHandle Support===&lt;br /&gt;
Lastly, we need to make it so &amp;lt;tt&amp;gt;CloseHandle()&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FreeHandle()&amp;lt;/tt&amp;gt; will close our file pointer when removing the Handle, which we skipped before.&lt;br /&gt;
&amp;lt;cpp&amp;gt;class FileTypeHandler : public IHandleTypeDispatch&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
	void OnHandleDestroy(HandleType_t type, void *object)&lt;br /&gt;
	{&lt;br /&gt;
		fclose( (FILE *)object );&lt;br /&gt;
	}&lt;br /&gt;
};&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Restricting CloseHandle==&lt;br /&gt;
Let's say that, for various reasons, you don't want users to be able to call CloseHandle().  An example of this might be a data type that is non-temporary, or is being called from a forward, and thus should not be touched.  Or, you might have a special deconstructor that takes extra parameters, and thus you need a separate destroy function.&lt;br /&gt;
&lt;br /&gt;
For example, let's create a separate function called &amp;lt;tt&amp;gt;CloseFile&amp;lt;/tt&amp;gt;.  It doesn't do anything particularly special, but we are going to force its usage over CloseHandle().&lt;br /&gt;
&lt;br /&gt;
===New Security Rules===&lt;br /&gt;
&amp;lt;cpp&amp;gt;Initialize()&lt;br /&gt;
{&lt;br /&gt;
	/* Create default access rights */&lt;br /&gt;
	HandleAccess rules;&lt;br /&gt;
	g_pHandleSys-&amp;gt;InitAccessDefaults(NULL, &amp;amp;rules);&lt;br /&gt;
&lt;br /&gt;
	/* Restrict delete to only our identity */&lt;br /&gt;
	rules.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY;&lt;br /&gt;
&lt;br /&gt;
	/* Register the type with our security permissions */&lt;br /&gt;
	g_FileType = g_pHandleSys-&amp;gt;CreateType(&amp;quot;File&amp;quot;, &lt;br /&gt;
			&amp;amp;g_FileTypeHandler, &lt;br /&gt;
			0, &lt;br /&gt;
			NULL, &lt;br /&gt;
			&amp;amp;rules, &lt;br /&gt;
			myself-&amp;gt;GetIdentity(), &lt;br /&gt;
			NULL);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementing the Native===&lt;br /&gt;
&amp;lt;cpp&amp;gt;/* native Closefile(Handle:hndl); */&lt;br /&gt;
static cell_t sm_CloseFile(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	Handle_t hndl = static_cast&amp;lt;Handle_t&amp;gt;(params[1]);&lt;br /&gt;
	HandleError err;&lt;br /&gt;
	HandleSecurity sec;&lt;br /&gt;
&lt;br /&gt;
	/* Build our security descriptor */&lt;br /&gt;
	sec.pOwner = pContext-&amp;gt;GetIdentity();	/* Needed, HANDLE_RESTRICT_OWNER is default */&lt;br /&gt;
	sec.pIdentity = myself-&amp;gt;GetIdentity();	/* But only this extension can read */&lt;br /&gt;
&lt;br /&gt;
	/* Attempt to read the given handle as our type, using our security info.&lt;br /&gt;
	 * Note that we read the pointer directly in with a little cast.&lt;br /&gt;
	 * This type of cast is safe since sizeof(void **) == sizeof(void *) == sizeof(T *) in almost all cases.&lt;br /&gt;
	 */&lt;br /&gt;
	FILE *fp;&lt;br /&gt;
	if ((err = g_pHandleSys-&amp;gt;FreeHandle(hndl, &amp;amp;sec))&lt;br /&gt;
	     != HandleError_None)&lt;br /&gt;
	{&lt;br /&gt;
		return pContext-&amp;gt;ThrowNativeError(&amp;quot;Invalid file handle %x (error %d)&amp;quot;, hndl, err);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 1;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Restricting CloseHandle Per-Handle==&lt;br /&gt;
Taking our above example, it is possible that we might want some Handles to be closed via CloseHandle(), but others not.  Again, this is useful if you wish to pass a Handle as read-only to a plugin, commonly done when using non-temporary structures or Handles used in Forwards.&lt;br /&gt;
&lt;br /&gt;
In this example, we'll create a global instance of our file type, and this instance will be denied access to CloseHandle(), whereas files returned by OpenFile() will not.&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
&amp;lt;cpp&amp;gt;Handle_t g_GlobalFile;&lt;br /&gt;
&lt;br /&gt;
Initialize()&lt;br /&gt;
{&lt;br /&gt;
	/* Register the type with default security permissions */&lt;br /&gt;
	g_FileType = g_pHandleSys-&amp;gt;CreateType(&amp;quot;File&amp;quot;, &lt;br /&gt;
			&amp;amp;g_FileTypeHandler, &lt;br /&gt;
			0, &lt;br /&gt;
			NULL, &lt;br /&gt;
			NULL, &lt;br /&gt;
			myself-&amp;gt;GetIdentity(), &lt;br /&gt;
			NULL);&lt;br /&gt;
&lt;br /&gt;
	/* Create our 'global' file */&lt;br /&gt;
	FILE *fp = tmpfile();&lt;br /&gt;
&lt;br /&gt;
	/* Set up the security descriptor */&lt;br /&gt;
	HandleSecurity sec;&lt;br /&gt;
	sec.pOwner = NULL;		/* No owner for this Handle */&lt;br /&gt;
	sec.pIdentity = myself-&amp;gt;GetIdentity();	/* Only this identity will be allowed */&lt;br /&gt;
&lt;br /&gt;
	/* Set up the access permissions */&lt;br /&gt;
	HandleAccess rules;&lt;br /&gt;
	g_pHandleSys-&amp;gt;InitAccessDefaults(NULL, &amp;amp;rules);&lt;br /&gt;
	rules.access[HandleAccess_Delete] |= HANDLE_RESTRICT_IDENTITY;&lt;br /&gt;
&lt;br /&gt;
	/* Finally, create the Handle with our rules */&lt;br /&gt;
	g_GlobalFile = g_pHandleSys-&amp;gt;CreateHandleEx(g_FileType, fp, &amp;amp;sec, &amp;amp;rules, NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Shutdown()&lt;br /&gt;
{&lt;br /&gt;
	/* Remove our global Handle (not needed, but we do it for clarity */&lt;br /&gt;
	HandleSecurity sec;&lt;br /&gt;
	sec.pOwner = NULL;&lt;br /&gt;
	sec.pIdentity = myself-&amp;gt;GetIdentity();&lt;br /&gt;
&lt;br /&gt;
	g_pHandleSys-&amp;gt;FreeHandle(g_GlobalFile, &amp;amp;sec);&lt;br /&gt;
&lt;br /&gt;
	/* Remove the type on shutdown */&lt;br /&gt;
	g_pHandleSys-&amp;gt;RemoveType(g_FileType, myself-&amp;gt;GetIdentity());&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Development]]&lt;/div&gt;</summary>
		<author><name>Nefarius</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Protobuf&amp;diff=9591</id>
		<title>Protobuf</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Protobuf&amp;diff=9591"/>
		<updated>2014-06-05T12:55:24Z</updated>

		<summary type="html">&lt;p&gt;Nefarius: Changed link to protobuf.inc to new Github location&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Intro==&lt;br /&gt;
Unlike the serial bitbuffer-backed usermessages in older games, newer games such as CS:GO (and DOTA 2) now use Google's [https://code.google.com/p/protobuf/ Protocol Buffers] or &amp;quot;protobuf&amp;quot; to back net messages and usermessages.&lt;br /&gt;
&lt;br /&gt;
==Differences==&lt;br /&gt;
Instead of having to be read or written in order, the protobuf usermessages use defined fields, accessible by name, in any order.&lt;br /&gt;
&lt;br /&gt;
Starting, ending, and hooking usermessages remains unchanged. Reading and writing values to/from them is done using the Pb* set of natives in protobuf.inc instead of the Bf* natives in bitbuffer.inc.&lt;br /&gt;
&lt;br /&gt;
You can tell which usermessage system is in use for the current game by checking GetUserMessageType(). Possible returns are UM_BitBuf and UM_Protobuf.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Basic fields (&amp;quot;optional&amp;quot; or &amp;quot;required&amp;quot;) are single values and use the PbRead*/PbSet* natives.&lt;br /&gt;
&lt;br /&gt;
Repeated fields are arrays of values, accessible by their 0-based index with the PbReadRepeated* natives or added with the PbAdd* natives. You can get the count of values in a repeated field with PbGetRepeatedFieldCount.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For message and field names, see the [https://hg.alliedmods.net/hl2sdks/hl2sdk-csgo/file/tip/public/game/shared/csgo/protobuf/cstrike15_usermessages.proto#l130 CS:GO Usermessages] as defined in protobuf's proto format, the [[Counter-Strike: Global Offensive UserMessages]] page, or the [[DOTA 2 UserMessages]] page.&lt;br /&gt;
&lt;br /&gt;
==Protobuf natives==&lt;br /&gt;
See [https://github.com/alliedmodders/sourcemod/blob/master/plugins/include/protobuf.inc protobuf.inc]&lt;br /&gt;
&lt;br /&gt;
==Multi-game usermessages example==&lt;br /&gt;
From funcommands' drug.sp, using the [http://hg.alliedmods.net/hl2sdks/hl2sdk-csgo/file/9a3c7f5049b6/public/game/shared/csgo/protobuf/cstrike15_usermessages.proto#l204 Fade] usermessage:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
	new clients[2];&lt;br /&gt;
	clients[0] = client;	&lt;br /&gt;
	&lt;br /&gt;
	new duration = 255;&lt;br /&gt;
	new holdtime = 255;&lt;br /&gt;
	new flags = 0x0002;&lt;br /&gt;
	new color[4] = { 0, 0, 0, 128 };&lt;br /&gt;
	color[0] = GetRandomInt(0,255);&lt;br /&gt;
	color[1] = GetRandomInt(0,255);&lt;br /&gt;
	color[2] = GetRandomInt(0,255);&lt;br /&gt;
&lt;br /&gt;
	new Handle:message = StartMessageEx(g_FadeUserMsgId, clients, 1);&lt;br /&gt;
	&lt;br /&gt;
	if (GetUserMessageType() == UM_Protobuf)&lt;br /&gt;
	{&lt;br /&gt;
		PbSetInt(message, &amp;quot;duration&amp;quot;, duration);&lt;br /&gt;
		PbSetInt(message, &amp;quot;hold_time&amp;quot;, holdtime);&lt;br /&gt;
		PbSetInt(message, &amp;quot;flags&amp;quot;, flags);&lt;br /&gt;
		PbSetColor(message, &amp;quot;clr&amp;quot;, color);&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		BfWriteShort(message, duration);&lt;br /&gt;
		BfWriteShort(message, holdtime);&lt;br /&gt;
		BfWriteShort(message, flags);&lt;br /&gt;
		BfWriteByte(message, color[0]);&lt;br /&gt;
		BfWriteByte(message, color[1]);&lt;br /&gt;
		BfWriteByte(message, color[2]);&lt;br /&gt;
		BfWriteByte(message, color[3]);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	EndMessage();&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Embedded message example==&lt;br /&gt;
&lt;br /&gt;
This example sends a VGUIMenu usermessage, adding values to a repeated field &amp;quot;subkeys&amp;quot; that uses the [http://hg.alliedmods.net/hl2sdks/hl2sdk-csgo/file/tip/public/game/shared/csgo/protobuf/cstrike15_usermessages.proto#l137 Subkey message type] defined in the [http://hg.alliedmods.net/hl2sdks/hl2sdk-csgo/file/tip/public/game/shared/csgo/protobuf/cstrike15_usermessages.proto#l132 VGUIMenu message].&lt;br /&gt;
&lt;br /&gt;
Once an embedded message handle is retrieved with ReadMessage, you can read or write to its fields with the normal PbRead/Set natives. GetRepeatedMessage or AddMessage will retrieve the handle for reading or writing respectively if it is a repeated field.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;SendSourceModMOTD(client)&lt;br /&gt;
{	&lt;br /&gt;
	new Handle:pb = StartMessageOne(&amp;quot;VGUIMenu&amp;quot;, client);&lt;br /&gt;
	&lt;br /&gt;
	PbSetString(pb, &amp;quot;name&amp;quot;, &amp;quot;info&amp;quot;);&lt;br /&gt;
	PbSetBool(pb, &amp;quot;show&amp;quot;, true);&lt;br /&gt;
	&lt;br /&gt;
	new Handle:subkey;&lt;br /&gt;
	&lt;br /&gt;
	subkey = PbAddMessage(pb, &amp;quot;subkeys&amp;quot;);&lt;br /&gt;
	PbSetString(subkey, &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot;);&lt;br /&gt;
	PbSetString(subkey, &amp;quot;str&amp;quot;, &amp;quot;2&amp;quot;); // MOTDPANEL_TYPE_URL&lt;br /&gt;
	&lt;br /&gt;
	subkey = PbAddMessage(pb, &amp;quot;subkeys&amp;quot;);&lt;br /&gt;
	PbSetString(subkey, &amp;quot;name&amp;quot;, &amp;quot;title&amp;quot;);&lt;br /&gt;
	PbSetString(subkey, &amp;quot;str&amp;quot;, &amp;quot;TESTING&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	subkey = PbAddMessage(pb, &amp;quot;subkeys&amp;quot;);&lt;br /&gt;
	PbSetString(subkey, &amp;quot;name&amp;quot;, &amp;quot;msg&amp;quot;);&lt;br /&gt;
	PbSetString(subkey, &amp;quot;str&amp;quot;, &amp;quot;http://www.sourcemod.net&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	EndMessage();&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;/div&gt;</summary>
		<author><name>Nefarius</name></author>
		
	</entry>
</feed>