Added extension loading/unloading
authorDavid Anderson <dvander@alliedmods.net>
Wed Jan 17 03:01:38 2007 +0000 (2007-01-17)
changeset 304fa485d2f25ed
parent 303 7e4acfe72046
child 305 59ef1afbe958
Added extension loading/unloading
Extended SDK for interface sharing
Completed Metamod extension support
core/interfaces/IExtensionSys.h
core/interfaces/IShareSys.h
core/sourcemm_api.cpp
core/sourcemm_api.h
core/systems/ExtensionSys.cpp
core/systems/ExtensionSys.h
core/systems/ShareSys.cpp
core/systems/ShareSys.h
extensions/sdk/sdk.vcproj
extensions/sdk/smsdk_ext.cpp
extensions/sdk/smsdk_ext.h
     1.1 --- a/core/interfaces/IExtensionSys.h	Tue Jan 16 20:45:13 2007 +0000
     1.2 +++ b/core/interfaces/IExtensionSys.h	Wed Jan 17 03:01:38 2007 +0000
     1.3 @@ -7,6 +7,7 @@
     1.4  namespace SourceMod
     1.5  {
     1.6  	class IExtensionInterface;
     1.7 +	typedef void *		ITERATOR;
     1.8  
     1.9  	/** 
    1.10  	 * @brief Encapsulates an IExtension.
    1.11 @@ -40,6 +41,32 @@
    1.12  		 * @return			An IdentityToken_t pointer.
    1.13  		 */
    1.14  		virtual IdentityToken_t *GetIdentity() =0;
    1.15 +
    1.16 +		/**
    1.17 +		 * @brief Retrieves the extension dependency list for this extension.
    1.18 +		 *
    1.19 +		 * @param pOwner		Optional pointer to store the first interface's owner.
    1.20 +		 * @param pInterface	Optional pointer to store the first interface.
    1.21 +		 * @return				An ITERATOR pointer for the results, or NULL if no results at all.
    1.22 +		 */
    1.23 +		virtual ITERATOR *FindFirstDependency(IExtension **pOwner, SMInterface **pInterface) =0;
    1.24 +
    1.25 +		/**
    1.26 +		 * @brief Finds the next dependency in the dependency list.
    1.27 +		 *
    1.28 +		 * @param iter			Pointer to iterator from FindFirstDependency.
    1.29 +		 * @param pOwner		Optional pointer to store the interface's owner.
    1.30 +		 * @param pInterface	Optional pointer to store the interface.
    1.31 +		 * @return				True if there are more results after this, false otherwise.
    1.32 +		 */
    1.33 +		virtual bool FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface) =0;
    1.34 +
    1.35 +		/**
    1.36 +		 * @brief Frees an ITERATOR handle from FindFirstDependency.
    1.37 +		 *
    1.38 +		 * @param iter			Pointer to iterator to free.
    1.39 +		 */
    1.40 +		virtual void FreeDependencyIterator(ITERATOR *iter) =0;
    1.41  	};
    1.42  
    1.43  	#define SMINTERFACE_EXTENSIONAPI_VERSION	1
    1.44 @@ -50,6 +77,11 @@
    1.45  	class IExtensionInterface
    1.46  	{
    1.47  	public:
    1.48 +		virtual unsigned int GetExtensionVersion()
    1.49 +		{
    1.50 +			return SMINTERFACE_EXTENSIONAPI_VERSION;
    1.51 +		}
    1.52 +	public:
    1.53  		/**
    1.54  		 * @brief Called when the extension is loaded.
    1.55  		 * 
    1.56 @@ -84,16 +116,29 @@
    1.57  		 */
    1.58  		virtual void OnExtensionPauseChange(bool pause) =0;
    1.59  
    1.60 -		virtual unsigned int GetExtensionVersion()
    1.61 +		/**
    1.62 +		 * @brief Asks the extension whether it's safe to remove an external interface it's using.
    1.63 +		 * If it's not safe, return false, and the extension will be unloaded afterwards.
    1.64 +		 * NOTE: It is important to also hook NotifyInterfaceDrop() in order to clean up resources.
    1.65 +		 *
    1.66 +		 * @param pInterface		Pointer to interface being dropped.
    1.67 +		 * @return					True to continue, false to unload this extension afterwards.
    1.68 +		 */
    1.69 +		virtual bool QueryInterfaceDrop(SMInterface *pInterface)
    1.70  		{
    1.71 -			return SMINTERFACE_EXTENSIONAPI_VERSION;
    1.72 +			return true;
    1.73  		}
    1.74  
    1.75  		/**
    1.76 -		 * @brief Returns true if the extension is Metamod-dependent.
    1.77 +		 * @brief Notifies the extension that an external interface it uses is being removed.
    1.78 +		 *
    1.79 +		 * @param pInterface		Pointer to interface being dropped.
    1.80  		 */
    1.81 +		virtual void NotifyInterfaceDrop(SMInterface *pInterface)
    1.82 +		{
    1.83 +		}
    1.84 +	public:
    1.85  		virtual bool IsMetamodExtension() =0;
    1.86 -	public:
    1.87  		virtual const char *GetExtensionName() =0;
    1.88  		virtual const char *GetExtensionURL() =0;
    1.89  		virtual const char *GetExtensionTag() =0;
    1.90 @@ -139,25 +184,6 @@
    1.91  									size_t err_max) =0;
    1.92  
    1.93  		/**
    1.94 -		 * @brief Returns the number of plugins that will be unloaded when this
    1.95 -		 * module is unloaded.
    1.96 -		 *
    1.97 -		 * @param pExt		IExtension pointer.
    1.98 -		 * @param optional	Optional pointer to be filled with # of plugins that 
    1.99 -		 *					are dependent, but will continue safely.  NOT YET USED.
   1.100 -		 * @return			Total number of dependent plugins.
   1.101 -		 */
   1.102 -		virtual unsigned int NumberOfPluginDependents(IExtension *pExt, unsigned int *optional) =0;
   1.103 -
   1.104 -		/**
   1.105 -		 * @brief Returns whether or not the extension can be unloaded.
   1.106 -		 *
   1.107 -		 * @param pExt		IExtension pointer.
   1.108 -		 * @return			True if unloading is possible, false otherwise.
   1.109 -		 */
   1.110 -		virtual bool IsExtensionUnloadable(IExtension *pExtension) =0;
   1.111 -
   1.112 -		/**
   1.113  		 * @brief Attempts to unload a module.
   1.114  		 *
   1.115  		 * @param pExt		IExtension pointer.
     2.1 --- a/core/interfaces/IShareSys.h	Tue Jan 16 20:45:13 2007 +0000
     2.2 +++ b/core/interfaces/IShareSys.h	Wed Jan 17 03:01:38 2007 +0000
     2.3 @@ -7,6 +7,7 @@
     2.4  
     2.5  namespace SourceMod
     2.6  {
     2.7 +	class IExtension;
     2.8  	struct IdentityToken_t;
     2.9  	typedef unsigned int		HandleType_t;
    2.10  	typedef HandleType_t		IdentityType_t;
    2.11 @@ -53,11 +54,11 @@
    2.12  		/**
    2.13  		 * @brief Adds an interface to the global interface system.
    2.14  		 *
    2.15 +		 * @param myself		Object adding this interface, in order to track dependencies.
    2.16  		 * @param iface			Interface pointer (must be unique).
    2.17 -		 * @param token			Parent token of the module/interface.
    2.18  		 * @return				True on success, false otherwise.
    2.19  		 */
    2.20 -		virtual bool AddInterface(SMInterface *iface, IdentityToken_t *token) =0;
    2.21 +		virtual bool AddInterface(IExtension *myself, SMInterface *iface) =0;
    2.22  
    2.23  		/**
    2.24  		 * @brief Requests an interface from the global interface system.
    2.25 @@ -65,12 +66,12 @@
    2.26  		 *
    2.27  		 * @param iface_name	Interface name.
    2.28  		 * @param iface_vers	Interface version to attempt to match.
    2.29 -		 * @param token			Object requesting this interface, in order to track dependencies.
    2.30 +		 * @param myself		Object requesting this interface, in order to track dependencies.
    2.31  		 * @param pIface		Pointer to store the return value in.
    2.32  		 */
    2.33  		virtual bool RequestInterface(const char *iface_name, 
    2.34  										unsigned int iface_vers,
    2.35 -										IdentityToken_t *token,
    2.36 +										IExtension *myself,
    2.37  										SMInterface **pIface) =0;
    2.38  
    2.39  		/**
     3.1 --- a/core/sourcemm_api.cpp	Tue Jan 16 20:45:13 2007 +0000
     3.2 +++ b/core/sourcemm_api.cpp	Wed Jan 17 03:01:38 2007 +0000
     3.3 @@ -7,6 +7,7 @@
     3.4  IVEngineServer *engine = NULL;
     3.5  IServerGameDLL *gamedll = NULL;
     3.6  IServerGameClients *serverClients = NULL;
     3.7 +ISmmPluginManager *g_pMMPlugins = NULL;
     3.8  
     3.9  PLUGIN_EXPOSE(SourceMod, g_SourceMod_Core);
    3.10  
    3.11 @@ -18,6 +19,15 @@
    3.12  	GET_V_IFACE_CURRENT(engineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER);
    3.13  	GET_V_IFACE_CURRENT(serverFactory, serverClients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS);
    3.14  
    3.15 +	if ((g_pMMPlugins = (ISmmPluginManager *)g_SMAPI->MetaFactory(MMIFACE_PLMANAGER, NULL, NULL)) == NULL)
    3.16 +	{
    3.17 +		if (error)
    3.18 +		{
    3.19 +			snprintf(error, maxlen, "Unable to find interface %s", MMIFACE_PLMANAGER);
    3.20 +		}
    3.21 +		return false;
    3.22 +	}
    3.23 +
    3.24  	return g_SourceMod.InitializeSourceMod(error, maxlen, late);
    3.25  }
    3.26  
     4.1 --- a/core/sourcemm_api.h	Tue Jan 16 20:45:13 2007 +0000
     4.2 +++ b/core/sourcemm_api.h	Wed Jan 17 03:01:38 2007 +0000
     4.3 @@ -31,6 +31,7 @@
     4.4  extern IVEngineServer *engine;
     4.5  extern IServerGameDLL *gamedll;
     4.6  extern IServerGameClients *serverClients;
     4.7 +extern ISmmPluginManager *g_pMMPlugins;
     4.8  
     4.9  PLUGIN_GLOBALVARS();
    4.10  
     5.1 --- a/core/systems/ExtensionSys.cpp	Tue Jan 16 20:45:13 2007 +0000
     5.2 +++ b/core/systems/ExtensionSys.cpp	Wed Jan 17 03:01:38 2007 +0000
     5.3 @@ -2,6 +2,7 @@
     5.4  #include "LibrarySys.h"
     5.5  #include "ShareSys.h"
     5.6  #include "CLogger.h"
     5.7 +#include "sourcemm_api.h"
     5.8  
     5.9  CExtensionManager g_Extensions;
    5.10  IdentityType_t g_ExtType;
    5.11 @@ -11,6 +12,7 @@
    5.12  	m_File.assign(filename);
    5.13  	m_pAPI = NULL;
    5.14  	m_pIdentToken = NULL;
    5.15 +	m_PlId = 0;
    5.16  
    5.17  	char path[PLATFORM_MAX_PATH+1];
    5.18  	g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s/extensions/%s", g_SourceMod.GetSMBaseDir(), filename);
    5.19 @@ -44,7 +46,8 @@
    5.20  
    5.21  	if (m_pAPI->IsMetamodExtension())
    5.22  	{
    5.23 -		/* :TODO: STUFF */
    5.24 +		bool already;
    5.25 +		m_PlId = g_pMMPlugins->Load(path, g_PLID, already, error, err_max);
    5.26  	}
    5.27  
    5.28  	m_pIdentToken = g_ShareSys.CreateIdentity(g_ExtType);
    5.29 @@ -53,7 +56,12 @@
    5.30  	{
    5.31  		if (m_pAPI->IsMetamodExtension())
    5.32  		{
    5.33 -			/* :TODO: stuff */
    5.34 +			if (m_PlId)
    5.35 +			{
    5.36 +				char dummy[255];
    5.37 +				g_pMMPlugins->Unload(m_PlId, true, dummy, sizeof(dummy));
    5.38 +				m_PlId = 0;
    5.39 +			}
    5.40  		}
    5.41  		m_pAPI = NULL;
    5.42  		m_pLib->CloseLibrary();
    5.43 @@ -69,6 +77,10 @@
    5.44  	if (m_pAPI)
    5.45  	{
    5.46  		m_pAPI->OnExtensionUnload();
    5.47 +		if (m_PlId)
    5.48 +		{
    5.49 +			g_pMMPlugins->Unload(m_PlId, true, NULL, 0);
    5.50 +		}
    5.51  	}
    5.52  
    5.53  	if (m_pIdentToken)
    5.54 @@ -107,6 +119,81 @@
    5.55  	return (m_pLib != NULL);
    5.56  }
    5.57  
    5.58 +void CExtension::AddDependency(IfaceInfo *pInfo)
    5.59 +{
    5.60 +	m_Deps.push_back(*pInfo);
    5.61 +}
    5.62 +
    5.63 +ITERATOR *CExtension::FindFirstDependency(IExtension **pOwner, SMInterface **pInterface)
    5.64 +{
    5.65 +	List<IfaceInfo>::iterator iter = m_Deps.begin();
    5.66 +
    5.67 +	if (iter == m_Deps.end())
    5.68 +	{
    5.69 +		return NULL;
    5.70 +	}
    5.71 +
    5.72 +	if (pOwner)
    5.73 +	{
    5.74 +		*pOwner = (*iter).owner;
    5.75 +	}
    5.76 +	if (pInterface)
    5.77 +	{
    5.78 +		*pInterface = (*iter).iface;
    5.79 +	}
    5.80 +
    5.81 +	List<IfaceInfo>::iterator *pIter = new List<IfaceInfo>::iterator(iter);
    5.82 +
    5.83 +	return (ITERATOR *)pIter;
    5.84 +}
    5.85 +
    5.86 +bool CExtension::FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface)
    5.87 +{
    5.88 +	List<IfaceInfo>::iterator *pIter = (List<IfaceInfo>::iterator *)iter;
    5.89 +	List<IfaceInfo>::iterator _iter;
    5.90 +
    5.91 +	if (_iter == m_Deps.end())
    5.92 +	{
    5.93 +		return false;
    5.94 +	}
    5.95 +
    5.96 +	_iter++;
    5.97 +
    5.98 +	if (pOwner)
    5.99 +	{
   5.100 +		*pOwner = (*_iter).owner;
   5.101 +	}
   5.102 +	if (pInterface)
   5.103 +	{
   5.104 +		*pInterface = (*_iter).iface;
   5.105 +	}
   5.106 +
   5.107 +	*pIter = _iter;
   5.108 +
   5.109 +	if (_iter == m_Deps.end())
   5.110 +	{
   5.111 +		return false;
   5.112 +	}
   5.113 +
   5.114 +	return true;
   5.115 +}
   5.116 +
   5.117 +void CExtension::FreeDependencyIterator(ITERATOR *iter)
   5.118 +{
   5.119 +	List<IfaceInfo>::iterator *pIter = (List<IfaceInfo>::iterator *)iter;
   5.120 +
   5.121 +	delete pIter;
   5.122 +}
   5.123 +
   5.124 +void CExtension::AddInterface(SMInterface *pInterface)
   5.125 +{
   5.126 +	m_Interfaces.push_back(pInterface);
   5.127 +}
   5.128 +
   5.129 +/*********************
   5.130 + * EXTENSION MANAGER *
   5.131 + *********************/
   5.132 +
   5.133  void CExtensionManager::OnSourceModAllInitialized()
   5.134  {
   5.135  	g_ExtType = g_ShareSys.CreateIdentType("EXTENSION");
   5.136 @@ -119,6 +206,12 @@
   5.137  
   5.138  IExtension *CExtensionManager::LoadAutoExtension(const char *path)
   5.139  {
   5.140 +	IExtension *pAlready;
   5.141 +	if ((pAlready=FindExtensionByFile(path)) != NULL)
   5.142 +	{
   5.143 +		return pAlready;
   5.144 +	}
   5.145 +
   5.146  	char error[256];
   5.147  	CExtension *p = new CExtension(path, error, sizeof(error));
   5.148  
   5.149 @@ -188,6 +281,12 @@
   5.150  
   5.151  IExtension *CExtensionManager::LoadExtension(const char *file, ExtensionLifetime lifetime, char *error, size_t err_max)
   5.152  {
   5.153 +	IExtension *pAlready;
   5.154 +	if ((pAlready=FindExtensionByFile(file)) != NULL)
   5.155 +	{
   5.156 +		return pAlready;
   5.157 +	}
   5.158 +
   5.159  	CExtension *pExt = new CExtension(file, error, err_max);
   5.160  
   5.161  	/* :NOTE: lifetime is currently ignored */
   5.162 @@ -203,20 +302,80 @@
   5.163  	return pExt;
   5.164  }
   5.165  
   5.166 -bool CExtensionManager::UnloadExtension(IExtension *pExt)
   5.167 +void CExtensionManager::BindDependency(IExtension *pOwner, IfaceInfo *pInfo)
   5.168  {
   5.169 -	/* :TODO: implement */
   5.170 -	return true;
   5.171 +	CExtension *pExt = (CExtension *)pOwner;
   5.172 +
   5.173 +	pExt->AddDependency(pInfo);
   5.174 +}
   5.175 +
   5.176 +void CExtensionManager::AddInterface(IExtension *pOwner, SMInterface *pInterface)
   5.177 +{
   5.178 +	CExtension *pExt = (CExtension *)pOwner;
   5.179 +
   5.180 +	pExt->AddInterface(pInterface);
   5.181  }
   5.182  
   5.183 -unsigned int CExtensionManager::NumberOfPluginDependents(IExtension *pExt, unsigned int *optional)
   5.184 +bool CExtensionManager::UnloadExtension(IExtension *_pExt)
   5.185  {
   5.186 -	/* :TODO: implement */
   5.187 -	return 0;
   5.188 -}
   5.189 +	if (!_pExt)
   5.190 +	{
   5.191 +		return false;
   5.192 +	}
   5.193 +
   5.194 +	CExtension *pExt = (CExtension *)_pExt;
   5.195 +
   5.196 +	if (m_Libs.find(pExt) == m_Libs.end())
   5.197 +	{
   5.198 +		return false;
   5.199 +	}
   5.200 +
   5.201 +	/* First remove us from internal lists */
   5.202 +	g_ShareSys.RemoveInterfaces(_pExt);
   5.203 +	m_Libs.remove(pExt);
   5.204 +
   5.205 +	List<CExtension *> UnloadQueue;
   5.206  
   5.207 -bool CExtensionManager::IsExtensionUnloadable(IExtension *pExtension)
   5.208 -{
   5.209 -	/* :TODO: implement */
   5.210 +	/* Handle dependencies */
   5.211 +	if (pExt->IsLoaded())
   5.212 +	{
   5.213 +		/* Notify and/or unload all dependencies */
   5.214 +		List<CExtension *>::iterator c_iter;
   5.215 +		CExtension *pDep;
   5.216 +		IExtensionInterface *pAPI;
   5.217 +		for (c_iter = m_Libs.begin(); c_iter != m_Libs.end(); c_iter++)
   5.218 +		{
   5.219 +			pDep = (*c_iter);
   5.220 +			if ((pAPI=pDep->GetAPI()) == NULL)
   5.221 +			{
   5.222 +				continue;
   5.223 +			}
   5.224 +			/* Now, get its dependency list */
   5.225 +			bool dropped = false;
   5.226 +			List<IfaceInfo>::iterator i_iter = pDep->m_Deps.begin();
   5.227 +			while (i_iter != pDep->m_Deps.end())
   5.228 +			{
   5.229 +				if ((*i_iter).owner == _pExt)
   5.230 +				{
   5.231 +					if (!dropped && !pAPI->QueryInterfaceDrop((*i_iter).iface))
   5.232 +					{
   5.233 +						dropped = true;
   5.234 +					}
   5.235 +					pAPI->NotifyInterfaceDrop((*i_iter).iface);
   5.236 +					i_iter = pDep->m_Deps.erase(i_iter);
   5.237 +				} else {
   5.238 +					i_iter++;
   5.239 +				}
   5.240 +			}
   5.241 +		}
   5.242 +	}
   5.243 +
   5.244 +	List<CExtension *>::iterator iter;
   5.245 +	for (iter=UnloadQueue.begin(); iter!=UnloadQueue.end(); iter++)
   5.246 +	{
   5.247 +		/* NOTE: This is safe because the unload function backs out of anything not present */
   5.248 +		UnloadExtension((*iter));
   5.249 +	}
   5.250 +
   5.251  	return true;
   5.252  }
     6.1 --- a/core/systems/ExtensionSys.h	Tue Jan 16 20:45:13 2007 +0000
     6.2 +++ b/core/systems/ExtensionSys.h	Wed Jan 17 03:01:38 2007 +0000
     6.3 @@ -6,12 +6,15 @@
     6.4  #include <sh_list.h>
     6.5  #include <sh_string.h>
     6.6  #include "sm_globals.h"
     6.7 +#include "ShareSys.h"
     6.8 +#include <ISmmAPI.h>
     6.9  
    6.10  using namespace SourceMod;
    6.11  using namespace SourceHook;
    6.12  
    6.13  class CExtension : public IExtension
    6.14  {
    6.15 +	friend class CExtensionManager;
    6.16  public:
    6.17  	CExtension(const char *filename, char *error, size_t maxlen);
    6.18  	~CExtension();
    6.19 @@ -20,14 +23,22 @@
    6.20  	const char *GetFilename();
    6.21  	IdentityToken_t *GetIdentity();
    6.22  	bool IsLoaded();
    6.23 +	ITERATOR *FindFirstDependency(IExtension **pOwner, SMInterface **pInterface);
    6.24 +	bool FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface);
    6.25 +	void FreeDependencyIterator(ITERATOR *iter);
    6.26  public:
    6.27  	void SetError(const char *error);
    6.28 +	void AddDependency(IfaceInfo *pInfo);
    6.29 +	void AddInterface(SMInterface *pInterface);
    6.30  private:
    6.31  	IdentityToken_t *m_pIdentToken;
    6.32  	IExtensionInterface *m_pAPI;
    6.33  	String m_File;
    6.34  	ILibrary *m_pLib;
    6.35  	String m_Error;
    6.36 +	List<IfaceInfo> m_Deps;
    6.37 +	List<SMInterface *> m_Interfaces;
    6.38 +	PluginId m_PlId;
    6.39  };
    6.40  
    6.41  class CExtensionManager : 
    6.42 @@ -42,13 +53,13 @@
    6.43  		ExtensionLifetime lifetime, 
    6.44  		char *error,
    6.45  		size_t err_max);
    6.46 -	unsigned int NumberOfPluginDependents(IExtension *pExt, unsigned int *optional);
    6.47 -	bool IsExtensionUnloadable(IExtension *pExtension);
    6.48  	bool UnloadExtension(IExtension *pExt);
    6.49  	IExtension *FindExtensionByFile(const char *file);
    6.50  	IExtension *FindExtensionByName(const char *ext);
    6.51  public:
    6.52  	IExtension *LoadAutoExtension(const char *path);
    6.53 +	void BindDependency(IExtension *pOwner, IfaceInfo *pInfo);
    6.54 +	void AddInterface(IExtension *pOwner, SMInterface *pInterface);
    6.55  private:
    6.56  	List<CExtension *> m_Libs;
    6.57  };
     7.1 --- a/core/systems/ShareSys.cpp	Tue Jan 16 20:45:13 2007 +0000
     7.2 +++ b/core/systems/ShareSys.cpp	Wed Jan 17 03:01:38 2007 +0000
     7.3 @@ -1,5 +1,6 @@
     7.4  #include "ShareSys.h"
     7.5  #include "HandleSys.h"
     7.6 +#include "ExtensionSys.h"
     7.7  
     7.8  ShareSystem g_ShareSys;
     7.9  
    7.10 @@ -90,7 +91,7 @@
    7.11  	return pToken;
    7.12  }
    7.13  
    7.14 -bool ShareSystem::AddInterface(SMInterface *iface, IdentityToken_t *token)
    7.15 +bool ShareSystem::AddInterface(IExtension *myself, SMInterface *iface)
    7.16  {
    7.17  	if (!iface)
    7.18  	{
    7.19 @@ -99,17 +100,9 @@
    7.20  
    7.21  	IfaceInfo info;
    7.22  
    7.23 +	info.owner = myself;
    7.24  	info.iface = iface;
    7.25 -	info.token = token;
    7.26  	
    7.27 -	if (token)
    7.28 -	{
    7.29 -		/* If we're an external object, we have to do this */
    7.30 -		info.handle = g_HandleSys.CreateHandle(m_IfaceType, iface, token, GetIdentRoot(), NULL);
    7.31 -	} else {
    7.32 -		info.handle = 0;
    7.33 -	}
    7.34 -
    7.35  	m_Interfaces.push_back(info);
    7.36  
    7.37  	return true;
    7.38 @@ -117,28 +110,13 @@
    7.39  
    7.40  bool ShareSystem::RequestInterface(const char *iface_name, 
    7.41  								   unsigned int iface_vers, 
    7.42 -								   IdentityToken_t *token, 
    7.43 +								   IExtension *mysql, 
    7.44  								   SMInterface **pIface)
    7.45  {
    7.46 -	/* If Some yahoo.... SOME HOOLIGAN... some NO GOOD DIRTY 
    7.47 -	 * HORRIBLE PERSON passed in a token that we don't recognize....
    7.48 -	 * <b>Punish them.</b>
    7.49 -	 */
    7.50 -	HandleSecurity sec;
    7.51 -
    7.52 -	sec.pIdentity = GetIdentRoot();
    7.53 -	sec.pOwner = NULL;
    7.54 -
    7.55 -	if (!g_HandleSys.ReadHandle(token->ident, m_TypeRoot, &sec, NULL))
    7.56 -	{
    7.57 -		return false;
    7.58 -	}
    7.59 -
    7.60  	/* See if the interface exists */
    7.61  	List<IfaceInfo>::iterator iter;
    7.62  	SMInterface *iface;
    7.63 -	IdentityToken_t *iface_owner;
    7.64 -	Handle_t iface_handle;
    7.65 +	IExtension *iface_owner;
    7.66  	bool found = false;
    7.67  	for (iter=m_Interfaces.begin(); iter!=m_Interfaces.end(); iter++)
    7.68  	{
    7.69 @@ -149,8 +127,7 @@
    7.70  			if (iface->GetInterfaceVersion() == iface_vers
    7.71  				|| iface->IsVersionCompatible(iface_vers))
    7.72  			{
    7.73 -				iface_owner = info.token;
    7.74 -				iface_handle = info.handle;
    7.75 +				iface_owner = info.owner;
    7.76  				found = true;
    7.77  				break;
    7.78  			}
    7.79 @@ -162,23 +139,21 @@
    7.80  		return false;
    7.81  	}
    7.82  
    7.83 -	/* If something external owns this, we need to track it. */
    7.84 +	/* Add a dependency node */
    7.85  	if (iface_owner)
    7.86  	{
    7.87 -		Handle_t newhandle;
    7.88 -		if (g_HandleSys.CloneHandle(iface_handle, &newhandle, token, &sec)
    7.89 -			!= HandleError_None)
    7.90 -		{
    7.91 -			return false;
    7.92 -		}
    7.93 -		/** 
    7.94 -		 * Now we can deny module loads based on dependencies.
    7.95 -		 */
    7.96 +		IfaceInfo info;
    7.97 +		info.iface = iface;
    7.98 +		info.owner = iface_owner;
    7.99 +		g_Extensions.BindDependency(iface_owner, &info);
   7.100  	}
   7.101  
   7.102 -	/* :TODO: finish */
   7.103 +	if (pIface)
   7.104 +	{
   7.105 +		*pIface = iface;
   7.106 +	}
   7.107  
   7.108 -	return NULL;
   7.109 +	return true;
   7.110  }
   7.111  
   7.112  void ShareSystem::AddNatives(IdentityToken_t *token, const sp_nativeinfo_t *natives[])
   7.113 @@ -202,3 +177,17 @@
   7.114  	g_HandleSys.RemoveType(type, GetIdentRoot());
   7.115  }
   7.116  
   7.117 +void ShareSystem::RemoveInterfaces(IExtension *pExtension)
   7.118 +{
   7.119 +	List<IfaceInfo>::iterator iter = m_Interfaces.begin();
   7.120 +
   7.121 +	while (iter != m_Interfaces.end())
   7.122 +	{
   7.123 +		if ((*iter).owner == pExtension)
   7.124 +		{
   7.125 +			iter = m_Interfaces.erase(iter);
   7.126 +		} else {
   7.127 +			iter++;
   7.128 +		}
   7.129 +	}
   7.130 +}
     8.1 --- a/core/systems/ShareSys.h	Tue Jan 16 20:45:13 2007 +0000
     8.2 +++ b/core/systems/ShareSys.h	Wed Jan 17 03:01:38 2007 +0000
     8.3 @@ -20,8 +20,7 @@
     8.4  struct IfaceInfo
     8.5  {
     8.6  	SMInterface *iface;
     8.7 -	IdentityToken_t *token;
     8.8 -	Handle_t handle;
     8.9 +	IExtension *owner;
    8.10  };
    8.11  
    8.12  class ShareSystem : 
    8.13 @@ -32,10 +31,10 @@
    8.14  public:
    8.15  	ShareSystem();
    8.16  public: //IShareSys
    8.17 -	bool AddInterface(SMInterface *iface, IdentityToken_t *token);
    8.18 +	bool AddInterface(IExtension *myself, SMInterface *pIface);
    8.19  	bool RequestInterface(const char *iface_name, 
    8.20  		unsigned int iface_vers,
    8.21 -		IdentityToken_t *token,
    8.22 +		IExtension *mysql,
    8.23  		SMInterface **pIface);
    8.24  	void AddNatives(IdentityToken_t *token, const sp_nativeinfo_t *natives[]);
    8.25  	IdentityType_t CreateIdentType(const char *name);
    8.26 @@ -51,6 +50,7 @@
    8.27  	void OnHandleDestroy(HandleType_t type, void *object);
    8.28  public:
    8.29  	IdentityToken_t *CreateCoreIdentity();
    8.30 +	void RemoveInterfaces(IExtension *pExtension);
    8.31  public:
    8.32  	inline IdentityToken_t *GetIdentRoot()
    8.33  	{
     9.1 --- a/extensions/sdk/sdk.vcproj	Tue Jan 16 20:45:13 2007 +0000
     9.2 +++ b/extensions/sdk/sdk.vcproj	Wed Jan 17 03:01:38 2007 +0000
     9.3 @@ -43,7 +43,7 @@
     9.4  				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
     9.5  				MinimalRebuild="true"
     9.6  				BasicRuntimeChecks="3"
     9.7 -				RuntimeLibrary="3"
     9.8 +				RuntimeLibrary="1"
     9.9  				UsePrecompiledHeader="0"
    9.10  				WarningLevel="3"
    9.11  				Detect64BitPortabilityProblems="true"
    9.12 @@ -60,6 +60,7 @@
    9.13  			/>
    9.14  			<Tool
    9.15  				Name="VCLinkerTool"
    9.16 +				OutputFile="$(OutDir)\sample.ext.dll"
    9.17  				LinkIncremental="2"
    9.18  				GenerateDebugInformation="true"
    9.19  				SubSystem="2"
    9.20 @@ -116,7 +117,7 @@
    9.21  			<Tool
    9.22  				Name="VCCLCompilerTool"
    9.23  				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
    9.24 -				RuntimeLibrary="2"
    9.25 +				RuntimeLibrary="0"
    9.26  				UsePrecompiledHeader="0"
    9.27  				WarningLevel="3"
    9.28  				Detect64BitPortabilityProblems="true"
    9.29 @@ -133,6 +134,7 @@
    9.30  			/>
    9.31  			<Tool
    9.32  				Name="VCLinkerTool"
    9.33 +				OutputFile="$(OutDir)\sample.ext.dll"
    9.34  				LinkIncremental="1"
    9.35  				GenerateDebugInformation="true"
    9.36  				SubSystem="2"
    9.37 @@ -193,7 +195,7 @@
    9.38  				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SMEXT_CONF_METAMOD"
    9.39  				MinimalRebuild="true"
    9.40  				BasicRuntimeChecks="3"
    9.41 -				RuntimeLibrary="3"
    9.42 +				RuntimeLibrary="1"
    9.43  				UsePrecompiledHeader="0"
    9.44  				WarningLevel="3"
    9.45  				Detect64BitPortabilityProblems="true"
    9.46 @@ -211,6 +213,7 @@
    9.47  			<Tool
    9.48  				Name="VCLinkerTool"
    9.49  				AdditionalDependencies="tier0.lib"
    9.50 +				OutputFile="$(OutDir)\sample.ext.dll"
    9.51  				LinkIncremental="2"
    9.52  				GenerateDebugInformation="true"
    9.53  				SubSystem="2"
    9.54 @@ -267,7 +270,7 @@
    9.55  			<Tool
    9.56  				Name="VCCLCompilerTool"
    9.57  				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SMEXT_CONF_METAMOD"
    9.58 -				RuntimeLibrary="2"
    9.59 +				RuntimeLibrary="0"
    9.60  				UsePrecompiledHeader="0"
    9.61  				WarningLevel="3"
    9.62  				Detect64BitPortabilityProblems="true"
    9.63 @@ -284,6 +287,7 @@
    9.64  			/>
    9.65  			<Tool
    9.66  				Name="VCLinkerTool"
    9.67 +				OutputFile="$(OutDir)\sample.ext.dll"
    9.68  				LinkIncremental="1"
    9.69  				GenerateDebugInformation="true"
    9.70  				SubSystem="2"
    10.1 --- a/extensions/sdk/smsdk_ext.cpp	Tue Jan 16 20:45:13 2007 +0000
    10.2 +++ b/extensions/sdk/smsdk_ext.cpp	Wed Jan 17 03:01:38 2007 +0000
    10.3 @@ -2,7 +2,7 @@
    10.4  #include "smsdk_ext.h"
    10.5  
    10.6  IShareSys *g_pShareSys = NULL;
    10.7 -IdentityToken_t *myself = NULL;
    10.8 +IExtension *myself = NULL;
    10.9  IHandleSys *g_pHandleSys = NULL;
   10.10  
   10.11  PLATFORM_EXTERN_C IExtensionInterface *GetSMExtAPI()
   10.12 @@ -22,7 +22,9 @@
   10.13  bool SDKExtension::OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t err_max, bool late)
   10.14  {
   10.15  	g_pShareSys = sys;
   10.16 -	myself = me->GetIdentity();
   10.17 +	myself = me;
   10.18 +
   10.19 +	m_WeAreUnloaded = true;
   10.20  
   10.21  #if defined SMEXT_CONF_METAMOD
   10.22  	if (!m_SourceMMLoaded)
   10.23 @@ -37,7 +39,13 @@
   10.24  
   10.25  	SM_GET_IFACE(HANDLESYSTEM, g_pHandleSys);
   10.26  
   10.27 -	return SDK_OnLoad(error, err_max, late);
   10.28 +	if (SDK_OnLoad(error, err_max, late))
   10.29 +	{
   10.30 +		m_WeAreUnloaded = true;
   10.31 +		return true;
   10.32 +	}
   10.33 +
   10.34 +	return false;
   10.35  }
   10.36  
   10.37  bool SDKExtension::IsMetamodExtension()
   10.38 @@ -51,7 +59,9 @@
   10.39  
   10.40  void SDKExtension::OnExtensionPauseChange(bool state)
   10.41  {
   10.42 +#if defined SMEXT_CONF_METAMOD
   10.43  	m_WeGotPauseChange = true;
   10.44 +#endif
   10.45  	SDK_OnPauseChange(state);
   10.46  }
   10.47  
   10.48 @@ -62,7 +72,9 @@
   10.49  
   10.50  void SDKExtension::OnExtensionUnload()
   10.51  {
   10.52 +#if defined SMEXT_CONF_METAMOD
   10.53  	m_WeAreUnloaded = true;
   10.54 +#endif
   10.55  	SDK_OnUnload();
   10.56  }
   10.57  
    11.1 --- a/extensions/sdk/smsdk_ext.h	Tue Jan 16 20:45:13 2007 +0000
    11.2 +++ b/extensions/sdk/smsdk_ext.h	Wed Jan 17 03:01:38 2007 +0000
    11.3 @@ -118,7 +118,7 @@
    11.4  extern SDKExtension *g_pExtensionIface;
    11.5  
    11.6  extern IShareSys *g_pShareSys;
    11.7 -extern IdentityToken_t *myself;
    11.8 +extern IExtension *myself;
    11.9  extern IHandleSys *g_pHandleSys;
   11.10  
   11.11  #if defined SMEXT_CONF_METAMOD