restructure of HandleSys admin permissions and interface

removal of HandleSys helper functions
removed useless BaseContext stuff from Engine
put SourceMod specific stuff in BaseContext
cleaned up broken Handle code

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40267
This commit is contained in:
David Anderson 2007-01-04 02:08:27 +00:00
parent 15beb5afb0
commit 4bd40d69e1
13 changed files with 436 additions and 240 deletions

View File

@ -43,34 +43,72 @@ namespace SourceMod
HandleError_Limit, /* The limited number of handles has been reached */ HandleError_Limit, /* The limited number of handles has been reached */
HandleError_Identity, /* The identity token was not usable */ HandleError_Identity, /* The identity token was not usable */
HandleError_Owner, /* Owners do not match for this operation */ HandleError_Owner, /* Owners do not match for this operation */
HandleError_Version, /* Unrecognized security structure version */
HandleError_Parameter, /* An invalid parameter was passed */
HandleError_NoInherit, /* This type cannot be inherited */
}; };
/**
* Access rights specific to a type
*/
enum HTypeAccessRight
{
HTypeAccess_Create = 0, /* Handles of this type can be created (DEFAULT=false) */
HTypeAccess_Inherit, /* Sub-types can inherit this type (DEFAULT=false) */
/* -------------- */
HTypeAccess_TOTAL, /* Total number of type access rights */
};
/**
* Access rights specific to a Handle. These rights are exclusive.
* For example, you do not need "read" access to delete or clone.
*/
enum HandleAccessRight enum HandleAccessRight
{ {
HandleAccess_Create, /* TYPE: Instances can be created by other objects (this makes it searchable) */ HandleAccess_Read, /* Can be read (DEFAULT=ident only) */
HandleAccess_Read, /* HANDLES: Can be read by other objects */ HandleAccess_Delete, /* Can be deleted (DEFAULT=owner only) */
HandleAccess_IdentDelete, /* HANDLES: Can be deleted by other identities */ HandleAccess_Clone, /* Can be cloned (DEFAULT=any) */
HandleAccess_OwnerDelete, /* HANDLES: Can be deleted by other owners */
HandleAccess_Inherit, /* TYPE: Can be inherited by new types */
HandleAccess_Clone, /* HANDLES: Can be cloned */
/* ------------- */ /* ------------- */
HandleAccess_TOTAL, /* Total number of access rights */ HandleAccess_TOTAL, /* Total number of access rights */
}; };
#define HANDLE_RESTRICT_IDENTITY (1<<0) /* Access is restricted to the identity */
#define HANDLE_RESTRICT_OWNER (1<<1) /* Access is restricted to the owner */
/**
* This is used to define per-type access rights.
*/
struct TypeAccess
{
TypeAccess()
{
hsVersion = SMINTERFACE_HANDLESYSTEM_VERSION;
}
unsigned int hsVersion;
IdentityToken_t *ident;
bool access[HTypeAccess_TOTAL];
};
/**
* This is used to define per-Handle access rights.
*/
struct HandleAccess
{
HandleAccess()
{
hsVersion = SMINTERFACE_HANDLESYSTEM_VERSION;
}
unsigned int hsVersion;
unsigned int access[HandleAccess_TOTAL];
};
/**
* This pair of tokens is used for identification.
*/
struct HandleSecurity struct HandleSecurity
{ {
HandleSecurity() IdentityToken_t *pOwner; /* Owner of the Handle */
{ IdentityToken_t *pIdentity; /* Owner of the Type */
owner = NULL;
access[HandleAccess_Create] = true;
access[HandleAccess_Read] = true;
access[HandleAccess_IdentDelete] = true;
access[HandleAccess_Inherit] = true;
access[HandleAccess_Clone] = true;
access[HandleAccess_OwnerDelete] = false;
}
IdentityToken_t *owner; /* Owner of the handle */
bool access[HandleAccess_TOTAL]; /* World access rights */
}; };
class IHandleTypeDispatch class IHandleTypeDispatch
@ -99,17 +137,6 @@ namespace SourceMod
return SMINTERFACE_HANDLESYSTEM_NAME; return SMINTERFACE_HANDLESYSTEM_NAME;
} }
public: public:
/**
* @brief Creates a new Handle type.
* NOTE: Handle names must be unique if not private.
*
* @param name Name of handle type (NULL or "" to be anonymous)
* @param dispatch Pointer to a valid IHandleTypeDispatch object.
* @return A new HandleType_t unique ID, or 0 on failure.
*/
virtual HandleType_t CreateType(const char *name,
IHandleTypeDispatch *dispatch) =0;
/** /**
* @brief Creates a new Handle type. * @brief Creates a new Handle type.
* NOTE: Currently, a child type may not have its own children. * NOTE: Currently, a child type may not have its own children.
@ -118,39 +145,30 @@ namespace SourceMod
* @param name Name of handle type (NULL or "" to be anonymous) * @param name Name of handle type (NULL or "" to be anonymous)
* @param dispatch Pointer to a valid IHandleTypeDispatch object. * @param dispatch Pointer to a valid IHandleTypeDispatch object.
* @param parent Parent handle to inherit from, 0 for none. * @param parent Parent handle to inherit from, 0 for none.
* @param security Pointer to a temporary HandleSecurity object, NULL to use default * @param typeAccess Pointer to a TypeAccess object, NULL to use default
* or inherited permissions. * or inherited permissions. Pointer can be temporary.
* @param ident Security token for any permissions. * @param hndlAccess Pointer to a HandleAccess object to define default
* default permissions on each Handle. NULL to use default
* permissions.
* @param ident Security token for any permissions. If typeAccess is NULL, this
* becomes the owning identity.
* @param err Optional pointer to store an error code.
* @return A new HandleType_t unique ID, or 0 on failure. * @return A new HandleType_t unique ID, or 0 on failure.
*/ */
virtual HandleType_t CreateTypeEx(const char *name, virtual HandleType_t CreateType(const char *name,
IHandleTypeDispatch *dispatch, IHandleTypeDispatch *dispatch,
HandleType_t parent, HandleType_t parent,
const HandleSecurity *security, const TypeAccess *typeAccess,
IdentityToken_t *ident) =0; const HandleAccess *hndlAccess,
IdentityToken_t *ident,
HandleError *err) =0;
/**
* @brief Creates a sub-type for a Handle.
* NOTE: Currently, a child type may not have its own children.
* NOTE: Handle names must be unique if not private.
* NOTE: This is a wrapper around the above.
*
* @param name Name of a handle.
* @param parent Parent handle type.
* @param dispatch Pointer to a valid IHandleTypeDispatch object.
* @return A new HandleType_t unique ID.
*/
virtual HandleType_t CreateChildType(const char *name,
HandleType_t parent,
IHandleTypeDispatch *dispatch) =0;
/** /**
* @brief Removes a handle type. * @brief Removes a handle type.
* NOTE: This removes all child types. * NOTE: This removes all child types.
* *
* @param token Identity token. Removal fails if the token does not match.
* @param type Type chain to remove. * @param type Type chain to remove.
* @param ident Identity token. Removal fails if the token does not match.
* @return True on success, false on failure. * @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;
@ -169,29 +187,16 @@ namespace SourceMod
* *
* @param type Type to use on the handle. * @param type Type to use on the handle.
* @param object Object to bind to the handle. * @param object Object to bind to the handle.
* @param owner Owner for the handle. NULL means anonymous (no owner). * @param owner Owner of the new Handle (may be NULL).
* @param ident Identity token if any security rights are needed. * @param ident Identity for type access if needed (may be NULL).
* @param err Optional pointer to store an error code.
* @return A new Handle_t, or 0 on failure. * @return A new Handle_t, or 0 on failure.
*/ */
virtual Handle_t CreateHandle(HandleType_t type, virtual Handle_t CreateHandle(HandleType_t type,
void *object, void *object,
IdentityToken_t *owner, IdentityToken_t *owner,
IdentityToken_t *ident) =0; IdentityToken_t *ident,
HandleError *err) =0;
/**
* @brief Creates a new handle.
* NOTE: This is a wrapper around the above function.
*
* @param type Type to use on the handle.
* @param object Object to bind to the handle.
* @param pOwner Plugin context that will own this handle. NULL for none.
* @param ident Identity token if any security rights are needed.
* @return A new Handle_t.
*/
virtual Handle_t CreateScriptHandle(HandleType_t type,
void *object,
SourcePawn::IPluginContext *pOwner,
IdentityToken_t *ident) =0;
/** /**
* @brief Frees the memory associated with a handle and calls any destructors. * @brief Frees the memory associated with a handle and calls any destructors.
@ -199,34 +204,48 @@ namespace SourceMod
* only perform any further action if the counter hits 0. * only perform any further action if the counter hits 0.
* *
* @param type Handle_t identifier to destroy. * @param type Handle_t identifier to destroy.
* @param owner Owner of handle (NULL for none). * @param pSecurity Security information struct (may be NULL).
* @param ident Identity token, for destroying secure handles (NULL for none).
* @return A HandleError error code. * @return A HandleError error code.
*/ */
virtual HandleError FreeHandle(Handle_t handle, IdentityToken_t *owner, IdentityToken_t *ident) =0; virtual HandleError FreeHandle(Handle_t handle, const HandleSecurity *pSecurity) =0;
/** /**
* @brief Clones a handle by adding to its internal reference count. Its data, * @brief Clones a handle by adding to its internal reference count. Its data,
* type, and security permissions remain the same. * type, and security permissions remain the same.
* *
* @param handle Handle to duplicate. Any non-free handle target is valid. * @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 newhandle Stores the duplicated handle in the pointer (must not be NULL).
* @param owner New owner of cloned handle. * @param newOwner New owner of cloned handle.
* @param ident Security token, if needed. * @param pSecurity Security information struct (may be NULL).
* @return A HandleError error code. * @return A HandleError error code.
*/ */
virtual HandleError CloneHandle(Handle_t handle, Handle_t *newhandle, IdentityToken_t *owner, IdentityToken_t *ident) =0; virtual HandleError CloneHandle(Handle_t handle,
Handle_t *newhandle,
IdentityToken_t *newOwner,
const HandleSecurity *pSecurity) =0;
/** /**
* @brief Retrieves the contents of a handle. * @brief Retrieves the contents of a handle.
* *
* @param handle Handle_t from which to retrieve contents. * @param handle Handle_t from which to retrieve contents.
* @param type Expected type to read as. 0 ignores typing rules. * @param type Expected type to read as. 0 ignores typing rules.
* @param ident Identity token to validate as. * @param pSecurity Security information struct (may be NULL).
* @param object Optional address to store object in. * @param object Optional address to store object in.
* @return HandleError error code. * @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,
const HandleSecurity *pSecurity,
void **object) =0;
/**
* @brief Sets access permissions on one or more structures.
*
* @param pTypeAccess Optional TypeAccess buffer to initialize with the default values.
* @param pHandleAccess Optional HandleAccess buffer to initialize with the default values.
* @return True on success, false if version is unsupported.
*/
virtual bool InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess) =0;
}; };
}; };

View File

@ -41,7 +41,7 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories="..\interfaces;..\;..\systems;..\..\sourcepawn\include" AdditionalIncludeDirectories="..\interfaces;..\;..\systems;..\..\sourcepawn\include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMOD_MM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMOD_MM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;SOURCEMOD_BUILD"
MinimalRebuild="true" MinimalRebuild="true"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
RuntimeLibrary="1" RuntimeLibrary="1"

View File

@ -12,13 +12,8 @@ class FileNatives :
public: public:
virtual void OnSourceModAllInitialized() virtual void OnSourceModAllInitialized()
{ {
HandleSecurity sec; g_FileType = g_HandleSys.CreateType("File", this, 0, NULL, NULL, g_pCoreIdent, NULL);
sec.owner = g_pCoreIdent; g_DirType = g_HandleSys.CreateType("Directory", this, 0, NULL, NULL, g_pCoreIdent, NULL);
sec.access[HandleAccess_Inherit] = false;
sec.access[HandleAccess_Create] = false;
g_FileType = g_HandleSys.CreateTypeEx("File", this, 0, &sec, NULL);
g_DirType = g_HandleSys.CreateTypeEx("Directory", this, 0, &sec, NULL);
} }
virtual void OnSourceModShutdown() virtual void OnSourceModShutdown()
{ {
@ -60,17 +55,21 @@ cell_t sm_OpenDirectory(IPluginContext *pContext, const cell_t *params)
return 0; return 0;
} }
return g_HandleSys.CreateScriptHandle(g_DirType, pDir, pContext, g_pCoreIdent); return g_HandleSys.CreateHandle(g_DirType, pDir, pContext->GetIdentity(), g_pCoreIdent, NULL);
} }
cell_t sm_ReadDirEntry(IPluginContext *pContext, const cell_t *params) cell_t sm_ReadDirEntry(IPluginContext *pContext, const cell_t *params)
{ {
Handle_t hndl = static_cast<Handle_t>(params[1]); Handle_t hndl = static_cast<Handle_t>(params[1]);
IDirectory *pDir; IDirectory *pDir;
HandleError herr; HandleError herr;
HandleSecurity sec;
int err; int err;
if ((herr=g_HandleSys.ReadHandle(hndl, g_DirType, g_pCoreIdent, (void **)&pDir))
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_DirType, &sec, (void **)&pDir))
!= HandleError_None) != HandleError_None)
{ {
return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);

View File

@ -24,7 +24,12 @@ static cell_t sm_CloseHandle(IPluginContext *pContext, const cell_t *params)
/* :TODO: make this a little bit cleaner, eh? */ /* :TODO: make this a little bit cleaner, eh? */
IPlugin *pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext()); IPlugin *pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
HandleError err = g_HandleSys.FreeHandle(hndl, pPlugin->GetIdentity(), NULL); HandleSecurity sec;
sec.pIdentity = NULL;
sec.pOwner = pContext->GetIdentity();
HandleError err = g_HandleSys.FreeHandle(hndl, &sec);
if (err == HandleError_None) if (err == HandleError_None)
{ {

View File

@ -14,7 +14,7 @@ inline HandleType_t TypeParent(HandleType_t type)
inline HandleError IdentityHandle(IdentityToken_t *token, unsigned int *index) inline HandleError IdentityHandle(IdentityToken_t *token, unsigned int *index)
{ {
return g_HandleSys.GetHandle(token->ident, g_ShareSys.GetIdentRoot(), &ignore_handle, index, HandleAccess_Read); return g_HandleSys.GetHandle(token->ident, g_ShareSys.GetIdentRoot(), &ignore_handle, index);
} }
HandleSystem::HandleSystem() HandleSystem::HandleSystem()
@ -39,24 +39,39 @@ HandleSystem::~HandleSystem()
delete m_strtab; delete m_strtab;
} }
HandleType_t HandleSystem::CreateType(const char *name, IHandleTypeDispatch *dispatch)
{
return CreateTypeEx(name, dispatch, 0, NULL, NULL);
}
HandleType_t HandleSystem::CreateChildType(const char *name, HandleType_t parent, IHandleTypeDispatch *dispatch) HandleType_t HandleSystem::CreateType(const char *name,
{ IHandleTypeDispatch *dispatch,
return CreateTypeEx(name, dispatch, parent, NULL, NULL); HandleType_t parent,
} const TypeAccess *typeAccess,
const HandleAccess *hndlAccess,
HandleType_t HandleSystem::CreateTypeEx(const char *name, IdentityToken_t *ident,
IHandleTypeDispatch *dispatch, HandleError *err)
HandleType_t parent,
const HandleSecurity *security,
IdentityToken_t *ident)
{ {
if (!dispatch) if (!dispatch)
{ {
if (err)
{
*err = HandleError_Parameter;
}
return 0;
}
if (typeAccess && typeAccess->hsVersion > SMINTERFACE_HANDLESYSTEM_VERSION)
{
if (err)
{
*err = HandleError_Version;
}
return 0;
}
if (hndlAccess && hndlAccess->hsVersion > SMINTERFACE_HANDLESYSTEM_VERSION)
{
if (err)
{
*err = HandleError_Version;
}
return 0; return 0;
} }
@ -67,34 +82,44 @@ HandleType_t HandleSystem::CreateTypeEx(const char *name,
isChild = true; isChild = true;
if (parent & HANDLESYS_SUBTYPE_MASK) if (parent & HANDLESYS_SUBTYPE_MASK)
{ {
if (err)
{
*err = HandleError_NoInherit;
}
return 0; return 0;
} }
if (parent >= HANDLESYS_TYPEARRAY_SIZE if (parent >= HANDLESYS_TYPEARRAY_SIZE
|| m_Types[parent].dispatch == NULL || m_Types[parent].dispatch == NULL)
|| (m_Types[parent].sec.access[HandleAccess_Inherit] == false
&& m_Types[parent].sec.owner != ident))
{ {
if (err)
{
*err = HandleError_Parameter;
}
return 0;
}
if (m_Types[parent].typeSec.access[HTypeAccess_Inherit] == false
&& (m_Types[parent].typeSec.ident != ident))
{
if (err)
{
*err = HandleError_Access;
}
return 0; return 0;
} }
} }
if (!security) if (name && name[0] != '\0')
{ {
if (isChild) if (sm_trie_retrieve(m_TypeLookup, name, NULL))
{ {
security = &m_Types[parent].sec; if (err)
} else { {
static HandleSecurity def_h; *err = HandleError_Parameter;
security = &def_h; }
return 0;
} }
} }
if (security->access[HandleAccess_Create]
&& sm_trie_retrieve(m_TypeLookup, name, NULL))
{
return 0;
}
unsigned int index; unsigned int index;
if (isChild) if (isChild)
@ -102,6 +127,10 @@ HandleType_t HandleSystem::CreateTypeEx(const char *name,
QHandleType *pParent = &m_Types[parent]; QHandleType *pParent = &m_Types[parent];
if (pParent->children >= HANDLESYS_MAX_SUBTYPES) if (pParent->children >= HANDLESYS_MAX_SUBTYPES)
{ {
if (err)
{
*err = HandleError_Limit;
}
return 0; return 0;
} }
index = 0; index = 0;
@ -115,6 +144,10 @@ HandleType_t HandleSystem::CreateTypeEx(const char *name,
} }
if (!index) if (!index)
{ {
if (err)
{
*err = HandleError_Limit;
}
return 0; return 0;
} }
pParent->children++; pParent->children++;
@ -124,6 +157,10 @@ HandleType_t HandleSystem::CreateTypeEx(const char *name,
/* Reserve another index */ /* Reserve another index */
if (m_TypeTail >= HANDLESYS_TYPEARRAY_SIZE) if (m_TypeTail >= HANDLESYS_TYPEARRAY_SIZE)
{ {
if (err)
{
*err = HandleError_Limit;
}
return 0; return 0;
} else { } else {
m_TypeTail += (HANDLESYS_MAX_SUBTYPES + 1); m_TypeTail += (HANDLESYS_MAX_SUBTYPES + 1);
@ -145,9 +182,24 @@ HandleType_t HandleSystem::CreateTypeEx(const char *name,
} else { } else {
pType->nameIdx = -1; pType->nameIdx = -1;
} }
pType->sec = *security;
pType->opened = 0; pType->opened = 0;
if (typeAccess)
{
pType->typeSec = *typeAccess;
} else {
InitAccessDefaults(&pType->typeSec, NULL);
pType->typeSec.ident = ident;
}
if (hndlAccess)
{
pType->hndlSec = *hndlAccess;
} else {
InitAccessDefaults(NULL, &pType->hndlSec);
}
if (!isChild) if (!isChild)
{ {
pType->children = 0; pType->children = 0;
@ -264,33 +316,46 @@ void HandleSystem::SetTypeSecurityOwner(HandleType_t type, IdentityToken_t *pTok
return; return;
} }
m_Types[type].sec.owner = pToken; m_Types[type].typeSec.ident = pToken;
} }
Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityToken_t *source, IdentityToken_t *ident) Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityToken_t *owner, IdentityToken_t *ident, HandleError *err)
{ {
if (!type if (!type
|| type >= HANDLESYS_TYPEARRAY_SIZE || type >= HANDLESYS_TYPEARRAY_SIZE
|| m_Types[type].dispatch == NULL) || m_Types[type].dispatch == NULL)
{ {
if (err)
{
*err = HandleError_Parameter;
}
return 0; return 0;
} }
/* Check the security of this handle */ /* Check to see if we're allowed to create this handle type */
QHandleType *pType = &m_Types[type]; QHandleType *pType = &m_Types[type];
if (!pType->sec.access[HandleAccess_Create] if (!pType->typeSec.access[HTypeAccess_Create]
&& pType->sec.owner != ident) && (!pType->typeSec.ident
|| pType->typeSec.ident != ident))
{ {
if (err)
{
*err = HandleError_Access;
}
return 0; return 0;
} }
unsigned int index; unsigned int index;
Handle_t handle; Handle_t handle;
QHandle *pHandle; QHandle *pHandle;
HandleError err; HandleError _err;
if ((err=MakePrimHandle(type, &pHandle, &index, &handle, source)) != HandleError_None) if ((_err=MakePrimHandle(type, &pHandle, &index, &handle, owner)) != HandleError_None)
{ {
if (err)
{
*err = _err;
}
return 0; return 0;
} }
@ -300,16 +365,6 @@ Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityTok
return handle; return handle;
} }
Handle_t HandleSystem::CreateScriptHandle(HandleType_t type,
void *object,
IPluginContext *pContext,
IdentityToken_t *ident)
{
IPlugin *pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
return CreateHandle(type, object, pPlugin->GetIdentity(), ident);
}
bool HandleSystem::TypeCheck(HandleType_t intype, HandleType_t outtype) bool HandleSystem::TypeCheck(HandleType_t intype, HandleType_t outtype)
{ {
/* Check the type inheritance */ /* Check the type inheritance */
@ -334,7 +389,6 @@ HandleError HandleSystem::GetHandle(Handle_t handle,
IdentityToken_t *ident, IdentityToken_t *ident,
QHandle **in_pHandle, QHandle **in_pHandle,
unsigned int *in_index, unsigned int *in_index,
HandleAccessRight access,
bool ignoreFree) bool ignoreFree)
{ {
unsigned int serial = (handle >> 16); unsigned int serial = (handle >> 16);
@ -348,11 +402,6 @@ HandleError HandleSystem::GetHandle(Handle_t handle,
QHandle *pHandle = &m_Handles[index]; QHandle *pHandle = &m_Handles[index];
QHandleType *pType = &m_Types[pHandle->type]; QHandleType *pType = &m_Types[pHandle->type];
if ((access != HandleAccess_TOTAL)
&& (!pType->sec.access[access] && pType->sec.owner != ident))
{
return HandleError_Access;
}
if (!pHandle->set if (!pHandle->set
|| (pHandle->set == HandleSet_Freed && !ignoreFree)) || (pHandle->set == HandleSet_Freed && !ignoreFree))
{ {
@ -374,13 +423,44 @@ HandleError HandleSystem::GetHandle(Handle_t handle,
return HandleError_None; return HandleError_None;
} }
HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *out_newhandle, IdentityToken_t *source, IdentityToken_t *ident) bool HandleSystem::CheckAccess(QHandle *pHandle, HandleAccessRight right, const HandleSecurity *pSecurity)
{
QHandleType *pType = &m_Types[pHandle->type];
unsigned int access = pType->hndlSec.access[right];
/* Check if the type's identity matches */
if (access & HANDLE_RESTRICT_IDENTITY)
{
IdentityToken_t *owner = pType->typeSec.ident;
if (!owner
|| (!pSecurity || pSecurity->pIdentity != owner))
{
return false;
}
}
/* Check if the owner is allowed */
if (access & HANDLE_RESTRICT_OWNER)
{
IdentityToken_t *owner = pHandle->owner;
if (owner
&& (!pSecurity || pSecurity->pOwner != owner))
{
return false;
}
}
return true;
}
HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *newhandle, IdentityToken_t *newOwner, const HandleSecurity *pSecurity)
{ {
HandleError err; HandleError err;
QHandle *pHandle; QHandle *pHandle;
unsigned int index; unsigned int index;
IdentityToken_t *ident = pSecurity ? pSecurity->pIdentity : NULL;
if ((err=GetHandle(handle, ident, &pHandle, &index, HandleAccess_Clone)) != HandleError_None) if ((err=GetHandle(handle, ident, &pHandle, &index)) != HandleError_None)
{ {
return err; return err;
} }
@ -391,49 +471,49 @@ HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *out_newhandle,
return HandleError_Identity; return HandleError_Identity;
} }
QHandleType *pType = &m_Types[pHandle->type]; /* Check if the handle can be cloned */
if (!CheckAccess(pHandle, HandleAccess_Clone, pSecurity))
{
return HandleError_Access;
}
/* Get a new Handle ID */ /* Get a new Handle ID */
unsigned int new_index; unsigned int new_index;
QHandle *pNewHandle; QHandle *pNewHandle;
Handle_t new_handle; Handle_t new_handle;
if ((err=MakePrimHandle(pHandle->type, &pNewHandle, &new_index, &new_handle, source)) != HandleError_None) if ((err=MakePrimHandle(pHandle->type, &pNewHandle, &new_index, &new_handle, newOwner)) != HandleError_None)
{ {
return err; return err;
} }
pNewHandle->clone = handle; pNewHandle->clone = index;
pHandle->refcount++; pHandle->refcount++;
if (out_newhandle) *newhandle = new_handle;
{
*out_newhandle = new_handle;
}
return HandleError_None; return HandleError_None;
} }
HandleError HandleSystem::FreeHandle(Handle_t handle, IdentityToken_t *pOwner, IdentityToken_t *ident) HandleError HandleSystem::FreeHandle(Handle_t handle, const HandleSecurity *pSecurity)
{ {
unsigned int index; unsigned int index;
QHandle *pHandle; QHandle *pHandle;
HandleError err; HandleError err;
IdentityToken_t *ident = pSecurity ? pSecurity->pIdentity : NULL;
if ((err=GetHandle(handle, ident, &pHandle, &index, HandleAccess_IdentDelete)) != HandleError_None) if ((err=GetHandle(handle, ident, &pHandle, &index)) != HandleError_None)
{ {
return err; return err;
} }
QHandleType *pType = &m_Types[pHandle->type]; if (!CheckAccess(pHandle, HandleAccess_Delete, pSecurity))
if (pType->sec.access[HandleAccess_OwnerDelete] == false
&& pHandle->owner
&& pHandle->owner != pOwner)
{ {
return HandleError_Access; return HandleError_Access;
} }
QHandleType *pType = &m_Types[pHandle->type];
bool dofree = false; bool dofree = false;
if (pHandle->clone) if (pHandle->clone)
{ {
@ -441,9 +521,10 @@ HandleError HandleSystem::FreeHandle(Handle_t handle, IdentityToken_t *pOwner, I
QHandle *pMaster; QHandle *pMaster;
unsigned int master; unsigned int master;
/* This call should not return an error, it'd be a corruption sign */ /* Note that if we ever have per-handle security, we would need to re-check
err = GetHandle(pHandle->clone, ident, &pMaster, &master, HandleAccess_IdentDelete, true); * the access on this Handle. */
assert(err == HandleError_None); master = pHandle->clone;
pMaster = &m_Handles[master];
/* Release the clone now */ /* Release the clone now */
ReleasePrimHandle(index); ReleasePrimHandle(index);
@ -471,20 +552,23 @@ HandleError HandleSystem::FreeHandle(Handle_t handle, IdentityToken_t *pOwner, I
return HandleError_None; return HandleError_None;
} }
HandleError HandleSystem::ReadHandle(Handle_t handle, HandleError HandleSystem::ReadHandle(Handle_t handle, HandleType_t type, const HandleSecurity *pSecurity, void **object)
HandleType_t type,
IdentityToken_t *ident,
void **object)
{ {
unsigned int index; unsigned int index;
QHandle *pHandle; QHandle *pHandle;
HandleError err; HandleError err;
IdentityToken_t *ident = pSecurity ? pSecurity->pIdentity : NULL;
if ((err=GetHandle(handle, ident, &pHandle, &index, HandleAccess_Read)) != HandleError_None) if ((err=GetHandle(handle, ident, &pHandle, &index)) != HandleError_None)
{ {
return err; return err;
} }
if (!CheckAccess(pHandle, HandleAccess_Read, pSecurity))
{
return HandleError_Access;
}
/* Check the type inheritance */ /* Check the type inheritance */
if (pHandle->type & HANDLESYS_SUBTYPE_MASK) if (pHandle->type & HANDLESYS_SUBTYPE_MASK)
{ {
@ -505,8 +589,7 @@ HandleError HandleSystem::ReadHandle(Handle_t handle,
/* if we're a clone, the rules change - object is ONLY in our reference */ /* if we're a clone, the rules change - object is ONLY in our reference */
if (pHandle->clone) if (pHandle->clone)
{ {
/* :TODO: optimize this */ pHandle = &m_Handles[pHandle->clone];
return ReadHandle(pHandle->clone, pHandle->type, ident, object);
} }
*object = pHandle->object; *object = pHandle->object;
} }
@ -579,7 +662,8 @@ bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t *ident)
QHandleType *pType = &m_Types[type]; QHandleType *pType = &m_Types[type];
if (pType->sec.owner && pType->sec.owner != ident) if (pType->typeSec.ident
&& pType->typeSec.ident != ident)
{ {
return false; return false;
} }
@ -598,7 +682,7 @@ bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t *ident)
childType = &m_Types[type + i]; childType = &m_Types[type + i];
if (childType->dispatch) if (childType->dispatch)
{ {
RemoveType(type + i, childType->sec.owner); RemoveType(type + i, childType->typeSec.ident);
} }
} }
/* Link us into the free chain */ /* Link us into the free chain */
@ -658,10 +742,38 @@ void HandleSystem::MarkHandleAsIdentity(Handle_t handle)
QHandle *pHandle; QHandle *pHandle;
unsigned int index; unsigned int index;
if (GetHandle(handle, g_ShareSys.GetIdentRoot(), &pHandle, &index, HandleAccess_Read) != HandleError_None) if (GetHandle(handle, g_ShareSys.GetIdentRoot(), &pHandle, &index) != HandleError_None)
{ {
return; return;
} }
pHandle->set = HandleSet_Identity; pHandle->set = HandleSet_Identity;
} }
bool HandleSystem::InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess)
{
if (pTypeAccess)
{
if (pTypeAccess->hsVersion > SMINTERFACE_HANDLESYSTEM_VERSION)
{
return false;
}
pTypeAccess->access[HTypeAccess_Create] = false;
pTypeAccess->access[HTypeAccess_Inherit] = false;
pTypeAccess->ident = NULL;
}
if (pHandleAccess)
{
if (pHandleAccess->hsVersion > SMINTERFACE_HANDLESYSTEM_VERSION)
{
return false;
}
pHandleAccess->access[HandleAccess_Clone] = 0;
pHandleAccess->access[HandleAccess_Delete] = HANDLE_RESTRICT_OWNER;
pHandleAccess->access[HandleAccess_Read] = HANDLE_RESTRICT_IDENTITY;
}
return true;
}

View File

@ -48,7 +48,7 @@ struct QHandle
IdentityToken_t *owner; /* 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 serial; /* Serial no. for sanity checking */
unsigned int refcount; /* Reference count for safe destruction */ unsigned int refcount; /* Reference count for safe destruction */
Handle_t clone; /* If non-zero, this is our cloned parent */ unsigned int clone; /* If non-zero, this is our cloned parent index */
HandleSet set; /* Information about the handle's state */ HandleSet set; /* Information about the handle's state */
/* The following variables are unrelated to the Handle array, and used /* The following variables are unrelated to the Handle array, and used
* as an inlined chain of information */ * as an inlined chain of information */
@ -64,7 +64,8 @@ struct QHandleType
IHandleTypeDispatch *dispatch; IHandleTypeDispatch *dispatch;
unsigned int freeID; unsigned int freeID;
unsigned int children; unsigned int children;
HandleSecurity sec; TypeAccess typeSec;
HandleAccess hndlSec;
unsigned int opened; unsigned int opened;
int nameIdx; int nameIdx;
}; };
@ -78,23 +79,38 @@ public:
HandleSystem(); HandleSystem();
~HandleSystem(); ~HandleSystem();
public: //IHandleSystem public: //IHandleSystem
HandleType_t CreateType(const char *name, IHandleTypeDispatch *dispatch);
HandleType_t CreateTypeEx(const char *name, HandleType_t CreateType(const char *name,
IHandleTypeDispatch *dispatch, IHandleTypeDispatch *dispatch,
HandleType_t parent, HandleType_t parent,
const HandleSecurity *security, const TypeAccess *typeAccess,
IdentityToken_t *ident); const HandleAccess *hndlAccess,
HandleType_t CreateChildType(const char *name, HandleType_t parent, IHandleTypeDispatch *dispatch); IdentityToken_t *ident,
HandleError *err);
bool RemoveType(HandleType_t type, IdentityToken_t *ident); bool RemoveType(HandleType_t type, IdentityToken_t *ident);
bool FindHandleType(const char *name, HandleType_t *type); bool FindHandleType(const char *name, HandleType_t *type);
Handle_t CreateHandle(HandleType_t type, Handle_t CreateHandle(HandleType_t type,
void *object, void *object,
IdentityToken_t *source, IdentityToken_t *owner,
IdentityToken_t *ident); IdentityToken_t *ident,
Handle_t CreateScriptHandle(HandleType_t type, void *object, IPluginContext *pContext, IdentityToken_t *ident); HandleError *err);
HandleError FreeHandle(Handle_t handle, IdentityToken_t *owner, IdentityToken_t *ident); HandleError FreeHandle(Handle_t handle, const HandleSecurity *pSecurity);
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); HandleError CloneHandle(Handle_t handle,
Handle_t *newhandle,
IdentityToken_t *newOwner,
const HandleSecurity *pSecurity);
HandleError ReadHandle(Handle_t handle,
HandleType_t type,
const HandleSecurity *pSecurity,
void **object);
bool InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess);
bool TypeCheck(HandleType_t intype, HandleType_t outtype); bool TypeCheck(HandleType_t intype, HandleType_t outtype);
protected: protected:
/** /**
@ -104,7 +120,6 @@ protected:
IdentityToken_t *ident, IdentityToken_t *ident,
QHandle **pHandle, QHandle **pHandle,
unsigned int *index, unsigned int *index,
HandleAccessRight access,
bool ignoreFree=false); bool ignoreFree=false);
/** /**
@ -133,6 +148,8 @@ protected:
* This prevents it from being tampered with by outside stuff * This prevents it from being tampered with by outside stuff
*/ */
void MarkHandleAsIdentity(Handle_t handle); void MarkHandleAsIdentity(Handle_t handle);
bool CheckAccess(QHandle *pHandle, HandleAccessRight right, const HandleSecurity *pSecurity);
private: private:
QHandle *m_Handles; QHandle *m_Handles;
QHandleType *m_Types; QHandleType *m_Types;

View File

@ -32,7 +32,7 @@ CPlugin::~CPlugin()
{ {
if (m_ctx.base) if (m_ctx.base)
{ {
g_pSourcePawn->FreeBaseContext(m_ctx.base); delete m_ctx.base;
m_ctx.base = NULL; m_ctx.base = NULL;
} }
if (m_ctx.ctx) if (m_ctx.ctx)
@ -74,7 +74,11 @@ CPlugin::~CPlugin()
if (m_handle) if (m_handle)
{ {
g_HandleSys.FreeHandle(m_handle, g_PluginSys.GetIdentity(), g_PluginSys.GetIdentity()); HandleSecurity sec;
sec.pOwner = g_PluginSys.GetIdentity();
sec.pIdentity = sec.pOwner;
g_HandleSys.FreeHandle(m_handle, &sec);
g_ShareSys.DestroyIdentity(m_ident); g_ShareSys.DestroyIdentity(m_ident);
} }
} }
@ -84,7 +88,8 @@ void CPlugin::InitIdentity()
if (!m_handle) if (!m_handle)
{ {
m_ident = g_ShareSys.CreateIdentity(g_PluginIdent); m_ident = g_ShareSys.CreateIdentity(g_PluginIdent);
m_handle = g_HandleSys.CreateHandle(g_PluginType, this, g_PluginSys.GetIdentity(), g_PluginSys.GetIdentity()); m_handle = g_HandleSys.CreateHandle(g_PluginType, this, g_PluginSys.GetIdentity(), g_PluginSys.GetIdentity(), NULL);
m_ctx.base->SetIdentity(m_ident);
} }
} }
@ -188,7 +193,7 @@ bool CPlugin::FinishMyCompile(char *error, size_t maxlength)
return false; return false;
} }
m_ctx.base = g_pSourcePawn->CreateBaseContext(m_ctx.ctx); m_ctx.base = new BaseContext(m_ctx.ctx);
m_ctx.ctx->user[SM_CONTEXTVAR_MYSELF] = (void *)this; m_ctx.ctx->user[SM_CONTEXTVAR_MYSELF] = (void *)this;
m_funcsnum = m_ctx.vm->FunctionCount(m_ctx.ctx); m_funcsnum = m_ctx.vm->FunctionCount(m_ctx.ctx);
@ -1113,15 +1118,13 @@ void CPluginManager::OnSourceModAllInitialized()
{ {
m_MyIdent = g_ShareSys.CreateCoreIdentity(); m_MyIdent = g_ShareSys.CreateCoreIdentity();
HandleSecurity sec; HandleAccess sec;
g_HandleSys.InitAccessDefaults(NULL, &sec);
sec.owner = m_MyIdent; /* :TODO: implement ShareSys */ sec.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY;
sec.access[HandleAccess_Create] = false; sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY;
sec.access[HandleAccess_IdentDelete] = false;
sec.access[HandleAccess_Inherit] = false;
sec.access[HandleAccess_Clone] = false;
g_PluginType = g_HandleSys.CreateTypeEx("IPlugin", this, 0, &sec, NULL); g_PluginType = g_HandleSys.CreateType("Plugin", this, 0, NULL, &sec, m_MyIdent, NULL);
g_PluginIdent = g_ShareSys.CreateIdentType("PLUGIN"); g_PluginIdent = g_ShareSys.CreateIdentType("PLUGIN");
} }
@ -1147,7 +1150,12 @@ IPlugin *CPluginManager::PluginFromHandle(Handle_t handle, HandleError *err)
IPlugin *pPlugin; IPlugin *pPlugin;
HandleError _err; HandleError _err;
if ((_err=g_HandleSys.ReadHandle(handle, g_PluginType, m_MyIdent, (void **)&pPlugin)) != HandleError_None) HandleSecurity sec;
sec.pOwner = NULL;
sec.pIdentity = m_MyIdent;
if ((_err=g_HandleSys.ReadHandle(handle, g_PluginType, &sec, (void **)&pPlugin)) != HandleError_None)
{ {
pPlugin = NULL; pPlugin = NULL;
} }

View File

@ -7,6 +7,7 @@
#include <sh_list.h> #include <sh_list.h>
#include <sh_stack.h> #include <sh_stack.h>
#include "sm_globals.h" #include "sm_globals.h"
#include "vm/sp_vm_basecontext.h"
#include "CFunction.h" #include "CFunction.h"
#include "PluginInfoDatabase.h" #include "PluginInfoDatabase.h"
#include "sm_trie.h" #include "sm_trie.h"
@ -67,7 +68,7 @@ struct ContextPair
ContextPair() : base(NULL), ctx(NULL), co(NULL) ContextPair() : base(NULL), ctx(NULL), co(NULL)
{ {
}; };
IPluginContext *base; BaseContext *base;
sp_context_t *ctx; sp_context_t *ctx;
ICompilation *co; ICompilation *co;
IVirtualMachine *vm; IVirtualMachine *vm;

View File

@ -23,17 +23,16 @@ IdentityToken_t *ShareSystem::CreateCoreIdentity()
void ShareSystem::OnSourceModStartup(bool late) void ShareSystem::OnSourceModStartup(bool late)
{ {
HandleSecurity sec; TypeAccess sec;
sec.owner = GetIdentRoot(); g_HandleSys.InitAccessDefaults(&sec, NULL);
sec.access[HandleAccess_Inherit] = false; sec.ident = GetIdentRoot();
sec.access[HandleAccess_IdentDelete] = false;
m_TypeRoot = g_HandleSys.CreateTypeEx("Identity", this, 0, &sec, NULL); m_TypeRoot = g_HandleSys.CreateType("Identity", this, 0, &sec, NULL, NULL, NULL);
m_IfaceType = g_HandleSys.CreateTypeEx("Interface", this, 0, &sec, NULL); m_IfaceType = g_HandleSys.CreateType("Interface", this, 0, NULL, NULL, GetIdentRoot(), NULL);
/* Initialize our static identity handle */ /* Initialize our static identity handle */
m_IdentRoot.ident = g_HandleSys.CreateHandle(m_TypeRoot, NULL, NULL, NULL); m_IdentRoot.ident = g_HandleSys.CreateHandle(m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL);
} }
void ShareSystem::OnSourceModShutdown() void ShareSystem::OnSourceModShutdown()
@ -69,7 +68,7 @@ IdentityType_t ShareSystem::CreateIdentType(const char *name)
return 0; return 0;
} }
return g_HandleSys.CreateTypeEx(name, this, m_TypeRoot, NULL, GetIdentRoot()); return g_HandleSys.CreateType(name, this, m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL);
} }
void ShareSystem::OnHandleDestroy(HandleType_t type, void *object) void ShareSystem::OnHandleDestroy(HandleType_t type, void *object)
@ -86,7 +85,7 @@ IdentityToken_t *ShareSystem::CreateIdentity(IdentityType_t type)
/* :TODO: Cache? */ /* :TODO: Cache? */
IdentityToken_t *pToken = new IdentityToken_t; IdentityToken_t *pToken = new IdentityToken_t;
pToken->ident = g_HandleSys.CreateHandle(type, NULL, NULL, GetIdentRoot()); pToken->ident = g_HandleSys.CreateHandle(type, NULL, GetIdentRoot(), GetIdentRoot(), NULL);
return pToken; return pToken;
} }
@ -106,7 +105,7 @@ bool ShareSystem::AddInterface(SMInterface *iface, IdentityToken_t *token)
if (token) if (token)
{ {
/* If we're an external object, we have to do this */ /* If we're an external object, we have to do this */
info.handle = g_HandleSys.CreateHandle(m_IfaceType, iface, token, GetIdentRoot()); info.handle = g_HandleSys.CreateHandle(m_IfaceType, iface, token, GetIdentRoot(), NULL);
} else { } else {
info.handle = 0; info.handle = 0;
} }
@ -125,7 +124,12 @@ bool ShareSystem::RequestInterface(const char *iface_name,
* HORRIBLE PERSON passed in a token that we don't recognize.... * HORRIBLE PERSON passed in a token that we don't recognize....
* <b>Punish them.</b> * <b>Punish them.</b>
*/ */
if (!g_HandleSys.ReadHandle(token->ident, m_TypeRoot, GetIdentRoot(), NULL)) HandleSecurity sec;
sec.pIdentity = GetIdentRoot();
sec.pOwner = NULL;
if (!g_HandleSys.ReadHandle(token->ident, m_TypeRoot, &sec, NULL))
{ {
return false; return false;
} }
@ -162,7 +166,7 @@ bool ShareSystem::RequestInterface(const char *iface_name,
if (iface_owner) if (iface_owner)
{ {
Handle_t newhandle; Handle_t newhandle;
if (g_HandleSys.CloneHandle(iface_handle, &newhandle, token, GetIdentRoot()) if (g_HandleSys.CloneHandle(iface_handle, &newhandle, token, &sec)
!= HandleError_None) != HandleError_None)
{ {
return false; return false;
@ -184,7 +188,12 @@ void ShareSystem::AddNatives(IdentityToken_t *token, const sp_nativeinfo_t *nati
void ShareSystem::DestroyIdentity(IdentityToken_t *identity) void ShareSystem::DestroyIdentity(IdentityToken_t *identity)
{ {
g_HandleSys.FreeHandle(identity->ident, NULL, GetIdentRoot()); HandleSecurity sec;
sec.pOwner = GetIdentRoot();
sec.pIdentity = GetIdentRoot();
g_HandleSys.FreeHandle(identity->ident, &sec);
delete identity; delete identity;
} }

View File

@ -252,11 +252,9 @@ int BaseContext::HeapRelease(cell_t local_addr)
int BaseContext::FindNativeByName(const char *name, uint32_t *index) int BaseContext::FindNativeByName(const char *name, uint32_t *index)
{ {
int diff, high, low; int high;
uint32_t mid;
high = ctx->plugin->info.natives_num - 1; high = ctx->plugin->info.natives_num - 1;
low = 0;
#if 0 #if 0
while (low <= high) while (low <= high)
@ -786,3 +784,15 @@ int BaseContext::LookupLine(ucell_t addr, uint32_t *line)
return SP_ERROR_NONE; return SP_ERROR_NONE;
} }
#if defined SOURCEMOD_BUILD
SourceMod::IdentityToken_t *BaseContext::GetIdentity()
{
return m_pToken;
}
void BaseContext::SetIdentity(SourceMod::IdentityToken_t *token)
{
m_pToken = token;
}
#endif

View File

@ -44,6 +44,10 @@ namespace SourcePawn
virtual int Execute(funcid_t funcid, cell_t *result); virtual int Execute(funcid_t funcid, cell_t *result);
virtual void ThrowNativeErrorEx(int error, const char *msg, ...); virtual void ThrowNativeErrorEx(int error, const char *msg, ...);
virtual cell_t ThrowNativeError(const char *msg, ...); virtual cell_t ThrowNativeError(const char *msg, ...);
#if defined SOURCEMOD_BUILD
virtual SourceMod::IdentityToken_t *GetIdentity();
void SetIdentity(SourceMod::IdentityToken_t *token);
#endif
public: //IPluginDebugInfo public: //IPluginDebugInfo
virtual int LookupFile(ucell_t addr, const char **filename); virtual int LookupFile(ucell_t addr, const char **filename);
virtual int LookupFunction(ucell_t addr, const char **name); virtual int LookupFunction(ucell_t addr, const char **name);
@ -52,6 +56,9 @@ namespace SourcePawn
void SetErrorMessage(const char *msg, va_list ap); void SetErrorMessage(const char *msg, va_list ap);
private: private:
sp_context_t *ctx; sp_context_t *ctx;
#if defined SOURCEMOD_BUILD
SourceMod::IdentityToken_t *m_pToken;
#endif
char m_MsgCache[1024]; char m_MsgCache[1024];
bool m_CustomMsg; bool m_CustomMsg;
bool m_InExec; bool m_InExec;

View File

@ -12,7 +12,7 @@ public Plugin:myinfo =
native PrintStuff(const String:buffer[]); native PrintStuff(const String:buffer[]);
public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) DoItAll()
{ {
new String:buffer[PLATFORM_MAX_PATH]; new String:buffer[PLATFORM_MAX_PATH];
new FileType:type; new FileType:type;
@ -24,7 +24,14 @@ public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max)
Format(stuff, sizeof(stuff), "Type: %d Dir: %s", _:type, buffer) Format(stuff, sizeof(stuff), "Type: %d Dir: %s", _:type, buffer)
PrintStuff(stuff); PrintStuff(stuff);
} }
new Handle:copy = CloneHandle(dir);
CloseHandle(copy);
CloseHandle(dir); CloseHandle(dir);
}
public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max)
{
DoItAll();
return true; return true;
} }

View File

@ -6,6 +6,13 @@
#define SOURCEPAWN_VM_API_VERSION 1 #define SOURCEPAWN_VM_API_VERSION 1
#if defined SOURCEMOD_BUILD
namespace SourceMod
{
struct IdentityToken_t;
};
#endif
namespace SourcePawn namespace SourcePawn
{ {
class IVirtualMachine; class IVirtualMachine;
@ -331,6 +338,16 @@ namespace SourcePawn
* @return 0 for convenience. * @return 0 for convenience.
*/ */
virtual cell_t ThrowNativeError(const char *msg, ...) =0; virtual cell_t ThrowNativeError(const char *msg, ...) =0;
#if defined SOURCEMOD_BUILD
/**
* @brief Returns the identity token for this context.
* Note: This is a helper function for native calls and the Handle System.
*
* @return Identity token.
*/
virtual SourceMod::IdentityToken_t *GetIdentity() =0;
#endif
}; };
@ -448,21 +465,6 @@ namespace SourcePawn
*/ */
virtual int FreeFromMemory(sp_plugin_t *plugin) =0; virtual int FreeFromMemory(sp_plugin_t *plugin) =0;
/**
* @brief Creates a new IContext from a context handle.
*
* @param ctx Context to use as a basis for the IPluginContext.
* @return New IPluginContext handle.
*/
virtual IPluginContext *CreateBaseContext(sp_context_t *ctx) =0;
/**
* @brief Frees a base context. Does not free the sp_context_t it holds.
*
* @param ctx Context pointer to free.
*/
virtual void FreeBaseContext(IPluginContext *ctx) =0;
/** /**
* @brief Allocates large blocks of temporary memory. * @brief Allocates large blocks of temporary memory.
* *