Added extension loading/unloading

Extended SDK for interface sharing
Completed Metamod extension support

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40309
This commit is contained in:
David Anderson 2007-01-17 03:01:38 +00:00
parent b7e10b111f
commit 1857f29efc
11 changed files with 305 additions and 92 deletions

View File

@ -7,6 +7,7 @@
namespace SourceMod namespace SourceMod
{ {
class IExtensionInterface; class IExtensionInterface;
typedef void * ITERATOR;
/** /**
* @brief Encapsulates an IExtension. * @brief Encapsulates an IExtension.
@ -40,6 +41,32 @@ namespace SourceMod
* @return An IdentityToken_t pointer. * @return An IdentityToken_t pointer.
*/ */
virtual IdentityToken_t *GetIdentity() =0; virtual IdentityToken_t *GetIdentity() =0;
/**
* @brief Retrieves the extension dependency list for this extension.
*
* @param pOwner Optional pointer to store the first interface's owner.
* @param pInterface Optional pointer to store the first interface.
* @return An ITERATOR pointer for the results, or NULL if no results at all.
*/
virtual ITERATOR *FindFirstDependency(IExtension **pOwner, SMInterface **pInterface) =0;
/**
* @brief Finds the next dependency in the dependency list.
*
* @param iter Pointer to iterator from FindFirstDependency.
* @param pOwner Optional pointer to store the interface's owner.
* @param pInterface Optional pointer to store the interface.
* @return True if there are more results after this, false otherwise.
*/
virtual bool FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface) =0;
/**
* @brief Frees an ITERATOR handle from FindFirstDependency.
*
* @param iter Pointer to iterator to free.
*/
virtual void FreeDependencyIterator(ITERATOR *iter) =0;
}; };
#define SMINTERFACE_EXTENSIONAPI_VERSION 1 #define SMINTERFACE_EXTENSIONAPI_VERSION 1
@ -49,6 +76,11 @@ namespace SourceMod
*/ */
class IExtensionInterface class IExtensionInterface
{ {
public:
virtual unsigned int GetExtensionVersion()
{
return SMINTERFACE_EXTENSIONAPI_VERSION;
}
public: public:
/** /**
* @brief Called when the extension is loaded. * @brief Called when the extension is loaded.
@ -84,16 +116,29 @@ namespace SourceMod
*/ */
virtual void OnExtensionPauseChange(bool pause) =0; virtual void OnExtensionPauseChange(bool pause) =0;
virtual unsigned int GetExtensionVersion() /**
* @brief Asks the extension whether it's safe to remove an external interface it's using.
* If it's not safe, return false, and the extension will be unloaded afterwards.
* NOTE: It is important to also hook NotifyInterfaceDrop() in order to clean up resources.
*
* @param pInterface Pointer to interface being dropped.
* @return True to continue, false to unload this extension afterwards.
*/
virtual bool QueryInterfaceDrop(SMInterface *pInterface)
{ {
return SMINTERFACE_EXTENSIONAPI_VERSION; return true;
} }
/** /**
* @brief Returns true if the extension is Metamod-dependent. * @brief Notifies the extension that an external interface it uses is being removed.
*
* @param pInterface Pointer to interface being dropped.
*/ */
virtual bool IsMetamodExtension() =0; virtual void NotifyInterfaceDrop(SMInterface *pInterface)
{
}
public: public:
virtual bool IsMetamodExtension() =0;
virtual const char *GetExtensionName() =0; virtual const char *GetExtensionName() =0;
virtual const char *GetExtensionURL() =0; virtual const char *GetExtensionURL() =0;
virtual const char *GetExtensionTag() =0; virtual const char *GetExtensionTag() =0;
@ -138,25 +183,6 @@ namespace SourceMod
char *error, char *error,
size_t err_max) =0; size_t err_max) =0;
/**
* @brief Returns the number of plugins that will be unloaded when this
* module is unloaded.
*
* @param pExt IExtension pointer.
* @param optional Optional pointer to be filled with # of plugins that
* are dependent, but will continue safely. NOT YET USED.
* @return Total number of dependent plugins.
*/
virtual unsigned int NumberOfPluginDependents(IExtension *pExt, unsigned int *optional) =0;
/**
* @brief Returns whether or not the extension can be unloaded.
*
* @param pExt IExtension pointer.
* @return True if unloading is possible, false otherwise.
*/
virtual bool IsExtensionUnloadable(IExtension *pExtension) =0;
/** /**
* @brief Attempts to unload a module. * @brief Attempts to unload a module.
* *

View File

@ -7,6 +7,7 @@
namespace SourceMod namespace SourceMod
{ {
class IExtension;
struct IdentityToken_t; struct IdentityToken_t;
typedef unsigned int HandleType_t; typedef unsigned int HandleType_t;
typedef HandleType_t IdentityType_t; typedef HandleType_t IdentityType_t;
@ -53,11 +54,11 @@ namespace SourceMod
/** /**
* @brief Adds an interface to the global interface system. * @brief Adds an interface to the global interface system.
* *
* @param myself Object adding this interface, in order to track dependencies.
* @param iface Interface pointer (must be unique). * @param iface Interface pointer (must be unique).
* @param token Parent token of the module/interface.
* @return True on success, false otherwise. * @return True on success, false otherwise.
*/ */
virtual bool AddInterface(SMInterface *iface, IdentityToken_t *token) =0; virtual bool AddInterface(IExtension *myself, SMInterface *iface) =0;
/** /**
* @brief Requests an interface from the global interface system. * @brief Requests an interface from the global interface system.
@ -65,12 +66,12 @@ namespace SourceMod
* *
* @param iface_name Interface name. * @param iface_name Interface name.
* @param iface_vers Interface version to attempt to match. * @param iface_vers Interface version to attempt to match.
* @param token Object requesting this interface, in order to track dependencies. * @param myself Object requesting this interface, in order to track dependencies.
* @param pIface Pointer to store the return value in. * @param pIface Pointer to store the return value in.
*/ */
virtual bool RequestInterface(const char *iface_name, virtual bool RequestInterface(const char *iface_name,
unsigned int iface_vers, unsigned int iface_vers,
IdentityToken_t *token, IExtension *myself,
SMInterface **pIface) =0; SMInterface **pIface) =0;
/** /**

View File

@ -7,6 +7,7 @@ SourceMod_Core g_SourceMod_Core;
IVEngineServer *engine = NULL; IVEngineServer *engine = NULL;
IServerGameDLL *gamedll = NULL; IServerGameDLL *gamedll = NULL;
IServerGameClients *serverClients = NULL; IServerGameClients *serverClients = NULL;
ISmmPluginManager *g_pMMPlugins = NULL;
PLUGIN_EXPOSE(SourceMod, g_SourceMod_Core); PLUGIN_EXPOSE(SourceMod, g_SourceMod_Core);
@ -18,6 +19,15 @@ bool SourceMod_Core::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen
GET_V_IFACE_CURRENT(engineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER); GET_V_IFACE_CURRENT(engineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER);
GET_V_IFACE_CURRENT(serverFactory, serverClients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS); GET_V_IFACE_CURRENT(serverFactory, serverClients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS);
if ((g_pMMPlugins = (ISmmPluginManager *)g_SMAPI->MetaFactory(MMIFACE_PLMANAGER, NULL, NULL)) == NULL)
{
if (error)
{
snprintf(error, maxlen, "Unable to find interface %s", MMIFACE_PLMANAGER);
}
return false;
}
return g_SourceMod.InitializeSourceMod(error, maxlen, late); return g_SourceMod.InitializeSourceMod(error, maxlen, late);
} }

View File

@ -31,6 +31,7 @@ extern SourceMod_Core g_SourceMod_Core;
extern IVEngineServer *engine; extern IVEngineServer *engine;
extern IServerGameDLL *gamedll; extern IServerGameDLL *gamedll;
extern IServerGameClients *serverClients; extern IServerGameClients *serverClients;
extern ISmmPluginManager *g_pMMPlugins;
PLUGIN_GLOBALVARS(); PLUGIN_GLOBALVARS();

View File

@ -2,6 +2,7 @@
#include "LibrarySys.h" #include "LibrarySys.h"
#include "ShareSys.h" #include "ShareSys.h"
#include "CLogger.h" #include "CLogger.h"
#include "sourcemm_api.h"
CExtensionManager g_Extensions; CExtensionManager g_Extensions;
IdentityType_t g_ExtType; IdentityType_t g_ExtType;
@ -11,6 +12,7 @@ CExtension::CExtension(const char *filename, char *error, size_t err_max)
m_File.assign(filename); m_File.assign(filename);
m_pAPI = NULL; m_pAPI = NULL;
m_pIdentToken = NULL; m_pIdentToken = NULL;
m_PlId = 0;
char path[PLATFORM_MAX_PATH+1]; char path[PLATFORM_MAX_PATH+1];
g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s/extensions/%s", g_SourceMod.GetSMBaseDir(), filename); g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s/extensions/%s", g_SourceMod.GetSMBaseDir(), filename);
@ -44,7 +46,8 @@ CExtension::CExtension(const char *filename, char *error, size_t err_max)
if (m_pAPI->IsMetamodExtension()) if (m_pAPI->IsMetamodExtension())
{ {
/* :TODO: STUFF */ bool already;
m_PlId = g_pMMPlugins->Load(path, g_PLID, already, error, err_max);
} }
m_pIdentToken = g_ShareSys.CreateIdentity(g_ExtType); m_pIdentToken = g_ShareSys.CreateIdentity(g_ExtType);
@ -53,7 +56,12 @@ CExtension::CExtension(const char *filename, char *error, size_t err_max)
{ {
if (m_pAPI->IsMetamodExtension()) if (m_pAPI->IsMetamodExtension())
{ {
/* :TODO: stuff */ if (m_PlId)
{
char dummy[255];
g_pMMPlugins->Unload(m_PlId, true, dummy, sizeof(dummy));
m_PlId = 0;
}
} }
m_pAPI = NULL; m_pAPI = NULL;
m_pLib->CloseLibrary(); m_pLib->CloseLibrary();
@ -69,6 +77,10 @@ CExtension::~CExtension()
if (m_pAPI) if (m_pAPI)
{ {
m_pAPI->OnExtensionUnload(); m_pAPI->OnExtensionUnload();
if (m_PlId)
{
g_pMMPlugins->Unload(m_PlId, true, NULL, 0);
}
} }
if (m_pIdentToken) if (m_pIdentToken)
@ -107,6 +119,81 @@ bool CExtension::IsLoaded()
return (m_pLib != NULL); return (m_pLib != NULL);
} }
void CExtension::AddDependency(IfaceInfo *pInfo)
{
m_Deps.push_back(*pInfo);
}
ITERATOR *CExtension::FindFirstDependency(IExtension **pOwner, SMInterface **pInterface)
{
List<IfaceInfo>::iterator iter = m_Deps.begin();
if (iter == m_Deps.end())
{
return NULL;
}
if (pOwner)
{
*pOwner = (*iter).owner;
}
if (pInterface)
{
*pInterface = (*iter).iface;
}
List<IfaceInfo>::iterator *pIter = new List<IfaceInfo>::iterator(iter);
return (ITERATOR *)pIter;
}
bool CExtension::FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface)
{
List<IfaceInfo>::iterator *pIter = (List<IfaceInfo>::iterator *)iter;
List<IfaceInfo>::iterator _iter;
if (_iter == m_Deps.end())
{
return false;
}
_iter++;
if (pOwner)
{
*pOwner = (*_iter).owner;
}
if (pInterface)
{
*pInterface = (*_iter).iface;
}
*pIter = _iter;
if (_iter == m_Deps.end())
{
return false;
}
return true;
}
void CExtension::FreeDependencyIterator(ITERATOR *iter)
{
List<IfaceInfo>::iterator *pIter = (List<IfaceInfo>::iterator *)iter;
delete pIter;
}
void CExtension::AddInterface(SMInterface *pInterface)
{
m_Interfaces.push_back(pInterface);
}
/*********************
* EXTENSION MANAGER *
*********************/
void CExtensionManager::OnSourceModAllInitialized() void CExtensionManager::OnSourceModAllInitialized()
{ {
g_ExtType = g_ShareSys.CreateIdentType("EXTENSION"); g_ExtType = g_ShareSys.CreateIdentType("EXTENSION");
@ -119,6 +206,12 @@ void CExtensionManager::OnSourceModShutdown()
IExtension *CExtensionManager::LoadAutoExtension(const char *path) IExtension *CExtensionManager::LoadAutoExtension(const char *path)
{ {
IExtension *pAlready;
if ((pAlready=FindExtensionByFile(path)) != NULL)
{
return pAlready;
}
char error[256]; char error[256];
CExtension *p = new CExtension(path, error, sizeof(error)); CExtension *p = new CExtension(path, error, sizeof(error));
@ -188,6 +281,12 @@ IExtension *CExtensionManager::FindExtensionByName(const char *ext)
IExtension *CExtensionManager::LoadExtension(const char *file, ExtensionLifetime lifetime, char *error, size_t err_max) IExtension *CExtensionManager::LoadExtension(const char *file, ExtensionLifetime lifetime, char *error, size_t err_max)
{ {
IExtension *pAlready;
if ((pAlready=FindExtensionByFile(file)) != NULL)
{
return pAlready;
}
CExtension *pExt = new CExtension(file, error, err_max); CExtension *pExt = new CExtension(file, error, err_max);
/* :NOTE: lifetime is currently ignored */ /* :NOTE: lifetime is currently ignored */
@ -203,20 +302,80 @@ IExtension *CExtensionManager::LoadExtension(const char *file, ExtensionLifetime
return pExt; return pExt;
} }
bool CExtensionManager::UnloadExtension(IExtension *pExt) void CExtensionManager::BindDependency(IExtension *pOwner, IfaceInfo *pInfo)
{ {
/* :TODO: implement */ CExtension *pExt = (CExtension *)pOwner;
return true;
pExt->AddDependency(pInfo);
} }
unsigned int CExtensionManager::NumberOfPluginDependents(IExtension *pExt, unsigned int *optional) void CExtensionManager::AddInterface(IExtension *pOwner, SMInterface *pInterface)
{ {
/* :TODO: implement */ CExtension *pExt = (CExtension *)pOwner;
return 0;
pExt->AddInterface(pInterface);
} }
bool CExtensionManager::IsExtensionUnloadable(IExtension *pExtension) bool CExtensionManager::UnloadExtension(IExtension *_pExt)
{ {
/* :TODO: implement */ if (!_pExt)
{
return false;
}
CExtension *pExt = (CExtension *)_pExt;
if (m_Libs.find(pExt) == m_Libs.end())
{
return false;
}
/* First remove us from internal lists */
g_ShareSys.RemoveInterfaces(_pExt);
m_Libs.remove(pExt);
List<CExtension *> UnloadQueue;
/* Handle dependencies */
if (pExt->IsLoaded())
{
/* Notify and/or unload all dependencies */
List<CExtension *>::iterator c_iter;
CExtension *pDep;
IExtensionInterface *pAPI;
for (c_iter = m_Libs.begin(); c_iter != m_Libs.end(); c_iter++)
{
pDep = (*c_iter);
if ((pAPI=pDep->GetAPI()) == NULL)
{
continue;
}
/* Now, get its dependency list */
bool dropped = false;
List<IfaceInfo>::iterator i_iter = pDep->m_Deps.begin();
while (i_iter != pDep->m_Deps.end())
{
if ((*i_iter).owner == _pExt)
{
if (!dropped && !pAPI->QueryInterfaceDrop((*i_iter).iface))
{
dropped = true;
}
pAPI->NotifyInterfaceDrop((*i_iter).iface);
i_iter = pDep->m_Deps.erase(i_iter);
} else {
i_iter++;
}
}
}
}
List<CExtension *>::iterator iter;
for (iter=UnloadQueue.begin(); iter!=UnloadQueue.end(); iter++)
{
/* NOTE: This is safe because the unload function backs out of anything not present */
UnloadExtension((*iter));
}
return true; return true;
} }

View File

@ -6,12 +6,15 @@
#include <sh_list.h> #include <sh_list.h>
#include <sh_string.h> #include <sh_string.h>
#include "sm_globals.h" #include "sm_globals.h"
#include "ShareSys.h"
#include <ISmmAPI.h>
using namespace SourceMod; using namespace SourceMod;
using namespace SourceHook; using namespace SourceHook;
class CExtension : public IExtension class CExtension : public IExtension
{ {
friend class CExtensionManager;
public: public:
CExtension(const char *filename, char *error, size_t maxlen); CExtension(const char *filename, char *error, size_t maxlen);
~CExtension(); ~CExtension();
@ -20,14 +23,22 @@ public: //IExtension
const char *GetFilename(); const char *GetFilename();
IdentityToken_t *GetIdentity(); IdentityToken_t *GetIdentity();
bool IsLoaded(); bool IsLoaded();
ITERATOR *FindFirstDependency(IExtension **pOwner, SMInterface **pInterface);
bool FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface);
void FreeDependencyIterator(ITERATOR *iter);
public: public:
void SetError(const char *error); void SetError(const char *error);
void AddDependency(IfaceInfo *pInfo);
void AddInterface(SMInterface *pInterface);
private: private:
IdentityToken_t *m_pIdentToken; IdentityToken_t *m_pIdentToken;
IExtensionInterface *m_pAPI; IExtensionInterface *m_pAPI;
String m_File; String m_File;
ILibrary *m_pLib; ILibrary *m_pLib;
String m_Error; String m_Error;
List<IfaceInfo> m_Deps;
List<SMInterface *> m_Interfaces;
PluginId m_PlId;
}; };
class CExtensionManager : class CExtensionManager :
@ -42,13 +53,13 @@ public: //IExtensionManager
ExtensionLifetime lifetime, ExtensionLifetime lifetime,
char *error, char *error,
size_t err_max); size_t err_max);
unsigned int NumberOfPluginDependents(IExtension *pExt, unsigned int *optional);
bool IsExtensionUnloadable(IExtension *pExtension);
bool UnloadExtension(IExtension *pExt); bool UnloadExtension(IExtension *pExt);
IExtension *FindExtensionByFile(const char *file); IExtension *FindExtensionByFile(const char *file);
IExtension *FindExtensionByName(const char *ext); IExtension *FindExtensionByName(const char *ext);
public: public:
IExtension *LoadAutoExtension(const char *path); IExtension *LoadAutoExtension(const char *path);
void BindDependency(IExtension *pOwner, IfaceInfo *pInfo);
void AddInterface(IExtension *pOwner, SMInterface *pInterface);
private: private:
List<CExtension *> m_Libs; List<CExtension *> m_Libs;
}; };

View File

@ -1,5 +1,6 @@
#include "ShareSys.h" #include "ShareSys.h"
#include "HandleSys.h" #include "HandleSys.h"
#include "ExtensionSys.h"
ShareSystem g_ShareSys; ShareSystem g_ShareSys;
@ -90,7 +91,7 @@ IdentityToken_t *ShareSystem::CreateIdentity(IdentityType_t type)
return pToken; return pToken;
} }
bool ShareSystem::AddInterface(SMInterface *iface, IdentityToken_t *token) bool ShareSystem::AddInterface(IExtension *myself, SMInterface *iface)
{ {
if (!iface) if (!iface)
{ {
@ -99,17 +100,9 @@ bool ShareSystem::AddInterface(SMInterface *iface, IdentityToken_t *token)
IfaceInfo info; IfaceInfo info;
info.owner = myself;
info.iface = iface; info.iface = iface;
info.token = token;
if (token)
{
/* If we're an external object, we have to do this */
info.handle = g_HandleSys.CreateHandle(m_IfaceType, iface, token, GetIdentRoot(), NULL);
} else {
info.handle = 0;
}
m_Interfaces.push_back(info); m_Interfaces.push_back(info);
return true; return true;
@ -117,28 +110,13 @@ bool ShareSystem::AddInterface(SMInterface *iface, IdentityToken_t *token)
bool ShareSystem::RequestInterface(const char *iface_name, bool ShareSystem::RequestInterface(const char *iface_name,
unsigned int iface_vers, unsigned int iface_vers,
IdentityToken_t *token, IExtension *mysql,
SMInterface **pIface) SMInterface **pIface)
{ {
/* If Some yahoo.... SOME HOOLIGAN... some NO GOOD DIRTY
* HORRIBLE PERSON passed in a token that we don't recognize....
* <b>Punish them.</b>
*/
HandleSecurity sec;
sec.pIdentity = GetIdentRoot();
sec.pOwner = NULL;
if (!g_HandleSys.ReadHandle(token->ident, m_TypeRoot, &sec, NULL))
{
return false;
}
/* See if the interface exists */ /* See if the interface exists */
List<IfaceInfo>::iterator iter; List<IfaceInfo>::iterator iter;
SMInterface *iface; SMInterface *iface;
IdentityToken_t *iface_owner; IExtension *iface_owner;
Handle_t iface_handle;
bool found = false; bool found = false;
for (iter=m_Interfaces.begin(); iter!=m_Interfaces.end(); iter++) for (iter=m_Interfaces.begin(); iter!=m_Interfaces.end(); iter++)
{ {
@ -149,8 +127,7 @@ bool ShareSystem::RequestInterface(const char *iface_name,
if (iface->GetInterfaceVersion() == iface_vers if (iface->GetInterfaceVersion() == iface_vers
|| iface->IsVersionCompatible(iface_vers)) || iface->IsVersionCompatible(iface_vers))
{ {
iface_owner = info.token; iface_owner = info.owner;
iface_handle = info.handle;
found = true; found = true;
break; break;
} }
@ -162,23 +139,21 @@ bool ShareSystem::RequestInterface(const char *iface_name,
return false; return false;
} }
/* If something external owns this, we need to track it. */ /* Add a dependency node */
if (iface_owner) if (iface_owner)
{ {
Handle_t newhandle; IfaceInfo info;
if (g_HandleSys.CloneHandle(iface_handle, &newhandle, token, &sec) info.iface = iface;
!= HandleError_None) info.owner = iface_owner;
{ g_Extensions.BindDependency(iface_owner, &info);
return false;
}
/**
* Now we can deny module loads based on dependencies.
*/
} }
/* :TODO: finish */ if (pIface)
{
*pIface = iface;
}
return NULL; return true;
} }
void ShareSystem::AddNatives(IdentityToken_t *token, const sp_nativeinfo_t *natives[]) void ShareSystem::AddNatives(IdentityToken_t *token, const sp_nativeinfo_t *natives[])
@ -202,3 +177,17 @@ void ShareSystem::DestroyIdentType(IdentityType_t type)
g_HandleSys.RemoveType(type, GetIdentRoot()); g_HandleSys.RemoveType(type, GetIdentRoot());
} }
void ShareSystem::RemoveInterfaces(IExtension *pExtension)
{
List<IfaceInfo>::iterator iter = m_Interfaces.begin();
while (iter != m_Interfaces.end())
{
if ((*iter).owner == pExtension)
{
iter = m_Interfaces.erase(iter);
} else {
iter++;
}
}
}

View File

@ -20,8 +20,7 @@ namespace SourceMod
struct IfaceInfo struct IfaceInfo
{ {
SMInterface *iface; SMInterface *iface;
IdentityToken_t *token; IExtension *owner;
Handle_t handle;
}; };
class ShareSystem : class ShareSystem :
@ -32,10 +31,10 @@ class ShareSystem :
public: public:
ShareSystem(); ShareSystem();
public: //IShareSys public: //IShareSys
bool AddInterface(SMInterface *iface, IdentityToken_t *token); bool AddInterface(IExtension *myself, SMInterface *pIface);
bool RequestInterface(const char *iface_name, bool RequestInterface(const char *iface_name,
unsigned int iface_vers, unsigned int iface_vers,
IdentityToken_t *token, IExtension *mysql,
SMInterface **pIface); SMInterface **pIface);
void AddNatives(IdentityToken_t *token, const sp_nativeinfo_t *natives[]); void AddNatives(IdentityToken_t *token, const sp_nativeinfo_t *natives[]);
IdentityType_t CreateIdentType(const char *name); IdentityType_t CreateIdentType(const char *name);
@ -51,6 +50,7 @@ public: //IHandleTypeDispatch
void OnHandleDestroy(HandleType_t type, void *object); void OnHandleDestroy(HandleType_t type, void *object);
public: public:
IdentityToken_t *CreateCoreIdentity(); IdentityToken_t *CreateCoreIdentity();
void RemoveInterfaces(IExtension *pExtension);
public: public:
inline IdentityToken_t *GetIdentRoot() inline IdentityToken_t *GetIdentRoot()
{ {

View File

@ -43,7 +43,7 @@
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="true" MinimalRebuild="true"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
RuntimeLibrary="3" RuntimeLibrary="1"
UsePrecompiledHeader="0" UsePrecompiledHeader="0"
WarningLevel="3" WarningLevel="3"
Detect64BitPortabilityProblems="true" Detect64BitPortabilityProblems="true"
@ -60,6 +60,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
OutputFile="$(OutDir)\sample.ext.dll"
LinkIncremental="2" LinkIncremental="2"
GenerateDebugInformation="true" GenerateDebugInformation="true"
SubSystem="2" SubSystem="2"
@ -116,7 +117,7 @@
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE" PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="2" RuntimeLibrary="0"
UsePrecompiledHeader="0" UsePrecompiledHeader="0"
WarningLevel="3" WarningLevel="3"
Detect64BitPortabilityProblems="true" Detect64BitPortabilityProblems="true"
@ -133,6 +134,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
OutputFile="$(OutDir)\sample.ext.dll"
LinkIncremental="1" LinkIncremental="1"
GenerateDebugInformation="true" GenerateDebugInformation="true"
SubSystem="2" SubSystem="2"
@ -193,7 +195,7 @@
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SMEXT_CONF_METAMOD" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SMEXT_CONF_METAMOD"
MinimalRebuild="true" MinimalRebuild="true"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
RuntimeLibrary="3" RuntimeLibrary="1"
UsePrecompiledHeader="0" UsePrecompiledHeader="0"
WarningLevel="3" WarningLevel="3"
Detect64BitPortabilityProblems="true" Detect64BitPortabilityProblems="true"
@ -211,6 +213,7 @@
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="tier0.lib" AdditionalDependencies="tier0.lib"
OutputFile="$(OutDir)\sample.ext.dll"
LinkIncremental="2" LinkIncremental="2"
GenerateDebugInformation="true" GenerateDebugInformation="true"
SubSystem="2" SubSystem="2"
@ -267,7 +270,7 @@
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SMEXT_CONF_METAMOD" PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SMEXT_CONF_METAMOD"
RuntimeLibrary="2" RuntimeLibrary="0"
UsePrecompiledHeader="0" UsePrecompiledHeader="0"
WarningLevel="3" WarningLevel="3"
Detect64BitPortabilityProblems="true" Detect64BitPortabilityProblems="true"
@ -284,6 +287,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
OutputFile="$(OutDir)\sample.ext.dll"
LinkIncremental="1" LinkIncremental="1"
GenerateDebugInformation="true" GenerateDebugInformation="true"
SubSystem="2" SubSystem="2"

View File

@ -2,7 +2,7 @@
#include "smsdk_ext.h" #include "smsdk_ext.h"
IShareSys *g_pShareSys = NULL; IShareSys *g_pShareSys = NULL;
IdentityToken_t *myself = NULL; IExtension *myself = NULL;
IHandleSys *g_pHandleSys = NULL; IHandleSys *g_pHandleSys = NULL;
PLATFORM_EXTERN_C IExtensionInterface *GetSMExtAPI() PLATFORM_EXTERN_C IExtensionInterface *GetSMExtAPI()
@ -22,7 +22,9 @@ SDKExtension::SDKExtension()
bool SDKExtension::OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t err_max, bool late) bool SDKExtension::OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t err_max, bool late)
{ {
g_pShareSys = sys; g_pShareSys = sys;
myself = me->GetIdentity(); myself = me;
m_WeAreUnloaded = true;
#if defined SMEXT_CONF_METAMOD #if defined SMEXT_CONF_METAMOD
if (!m_SourceMMLoaded) if (!m_SourceMMLoaded)
@ -37,7 +39,13 @@ bool SDKExtension::OnExtensionLoad(IExtension *me, IShareSys *sys, char *error,
SM_GET_IFACE(HANDLESYSTEM, g_pHandleSys); SM_GET_IFACE(HANDLESYSTEM, g_pHandleSys);
return SDK_OnLoad(error, err_max, late); if (SDK_OnLoad(error, err_max, late))
{
m_WeAreUnloaded = true;
return true;
}
return false;
} }
bool SDKExtension::IsMetamodExtension() bool SDKExtension::IsMetamodExtension()
@ -51,7 +59,9 @@ bool SDKExtension::IsMetamodExtension()
void SDKExtension::OnExtensionPauseChange(bool state) void SDKExtension::OnExtensionPauseChange(bool state)
{ {
#if defined SMEXT_CONF_METAMOD
m_WeGotPauseChange = true; m_WeGotPauseChange = true;
#endif
SDK_OnPauseChange(state); SDK_OnPauseChange(state);
} }
@ -62,7 +72,9 @@ void SDKExtension::OnExtensionsAllLoaded()
void SDKExtension::OnExtensionUnload() void SDKExtension::OnExtensionUnload()
{ {
#if defined SMEXT_CONF_METAMOD
m_WeAreUnloaded = true; m_WeAreUnloaded = true;
#endif
SDK_OnUnload(); SDK_OnUnload();
} }

View File

@ -118,7 +118,7 @@ private:
extern SDKExtension *g_pExtensionIface; extern SDKExtension *g_pExtensionIface;
extern IShareSys *g_pShareSys; extern IShareSys *g_pShareSys;
extern IdentityToken_t *myself; extern IExtension *myself;
extern IHandleSys *g_pHandleSys; extern IHandleSys *g_pHandleSys;
#if defined SMEXT_CONF_METAMOD #if defined SMEXT_CONF_METAMOD