core/systems/ExtensionSys.cpp
changeset 1689 451c11ef473a
parent 1668 e1700463d1d8
child 1947 e73a1e51833b
     1.1 --- a/core/systems/ExtensionSys.cpp	Sat Nov 17 02:54:44 2007 +0000
     1.2 +++ b/core/systems/ExtensionSys.cpp	Sat Nov 17 04:31:01 2007 +0000
     1.3 @@ -285,7 +285,22 @@
     1.4  		if ((*iter).pl == pPlugin)
     1.5  		{
     1.6  			iter = m_WeakNatives.erase(iter);
     1.7 -		} else {
     1.8 +		}
     1.9 +		else
    1.10 +		{
    1.11 +			iter++;
    1.12 +		}
    1.13 +	}
    1.14 +
    1.15 +	iter = m_ReplacedNatives.begin();
    1.16 +	while (iter != m_ReplacedNatives.end())
    1.17 +	{
    1.18 +		if ((*iter).pl == pPlugin)
    1.19 +		{
    1.20 +			iter = m_ReplacedNatives.erase(iter);
    1.21 +		}
    1.22 +		else
    1.23 +		{
    1.24  			iter++;
    1.25  		}
    1.26  	}
    1.27 @@ -703,6 +718,7 @@
    1.28  	uint32_t natives = pContext->GetNativesNum();
    1.29  	sp_native_t *native;
    1.30  	sm_extnative_t *x_native;
    1.31 +	sm_repnative_t *r_native;
    1.32  	for (uint32_t i=0; i<natives; i++)
    1.33  	{
    1.34  		/* Make sure the native is valid */
    1.35 @@ -710,11 +726,26 @@
    1.36  		{
    1.37  			continue;
    1.38  		}
    1.39 +
    1.40  		/* Make sure the native is not already bound */
    1.41  		if (native->status == SP_NATIVE_BOUND)
    1.42  		{
    1.43 +			/* If it is bound, see if there is a replacement. */
    1.44 +			if ((r_native = m_RepNatives.retrieve(native->name)) == NULL)
    1.45 +			{
    1.46 +				continue;
    1.47 +			}
    1.48 +
    1.49 +			/* Rewrite the address.  Whee! */
    1.50 +			native->pfn = r_native->info.func;
    1.51 +
    1.52 +			/* Make sure this will unload safely */
    1.53 +			WeakNative wn((CPlugin *)pPlugin, i);
    1.54 +			r_native->owner->m_ReplacedNatives.push_back(wn);
    1.55 +
    1.56  			continue;
    1.57  		}
    1.58 +
    1.59  		/* See if we've got this native in our cache */
    1.60  		if ((x_native = m_ExtNatives.retrieve(native->name)) == NULL)
    1.61  		{
    1.62 @@ -789,7 +820,7 @@
    1.63  			g_PluginSys.OnLibraryAction((*s_iter).c_str(), false, true);
    1.64  		}
    1.65  
    1.66 -		/* Unbound weak natives */
    1.67 +		/* Unbind weak natives */
    1.68  		List<WeakNative>::iterator wkn_iter;
    1.69  		for (wkn_iter=pExt->m_WeakNatives.begin(); wkn_iter!=pExt->m_WeakNatives.end(); wkn_iter++)
    1.70  		{
    1.71 @@ -798,6 +829,21 @@
    1.72  			ctx->natives[wkn.idx].status = SP_NATIVE_UNBOUND;
    1.73  		}
    1.74  
    1.75 +		/* Unbind replacement natives, link them back to their originals */
    1.76 +		for (wkn_iter = pExt->m_ReplacedNatives.begin();
    1.77 +			 wkn_iter != pExt->m_ReplacedNatives.end();
    1.78 +			 wkn_iter++)
    1.79 +		{
    1.80 +			WeakNative & wkn = (*wkn_iter);
    1.81 +			sp_context_t *ctx = wkn.pl->GetContext();
    1.82 +			sm_repnative_t *r_native = m_RepNatives.retrieve(ctx->natives[wkn.idx].name);
    1.83 +			if (r_native == NULL || ctx->natives[wkn.idx].pfn != r_native->info.func)
    1.84 +			{
    1.85 +				continue;
    1.86 +			}
    1.87 +			ctx->natives[wkn.idx].pfn = r_native->original;
    1.88 +		}
    1.89 +
    1.90  		/* Notify and/or unload all dependencies */
    1.91  		List<CExtension *>::iterator c_iter;
    1.92  		CExtension *pDep;
    1.93 @@ -871,6 +917,22 @@
    1.94  			}
    1.95  		}
    1.96  
    1.97 +		/* Unbind our replacement natives */
    1.98 +		List<sm_repnative_t>::iterator rep_iter = m_RepNativeList.begin();
    1.99 +		while (rep_iter != m_RepNativeList.end())
   1.100 +		{
   1.101 +			sm_repnative_t & r_native = (*rep_iter);
   1.102 +			if (r_native.owner == pExt)
   1.103 +			{
   1.104 +				m_RepNatives.remove(r_native.info.name);
   1.105 +				rep_iter = m_RepNativeList.erase(rep_iter);
   1.106 +			}
   1.107 +			else
   1.108 +			{
   1.109 +				rep_iter++;
   1.110 +			}
   1.111 +		}
   1.112 +
   1.113  		/* Tell it to unload */
   1.114  		pAPI = pExt->GetAPI();
   1.115  		pAPI->OnExtensionUnload();
   1.116 @@ -919,6 +981,25 @@
   1.117  	}
   1.118  }
   1.119  
   1.120 +void CExtensionManager::OverrideNatives(IExtension *myself, const sp_nativeinfo_t *natives)
   1.121 +{
   1.122 +	SPVM_NATIVE_FUNC orig;
   1.123 +
   1.124 +	for (unsigned int i = 0; natives[i].func != NULL && natives[i].name != NULL; i++)
   1.125 +	{
   1.126 +		if ((orig = g_PluginSys.FindCoreNative(natives[i].name)) == NULL)
   1.127 +		{
   1.128 +			continue;
   1.129 +		}
   1.130 +		sm_repnative_t rep;
   1.131 +		rep.info = natives[i];
   1.132 +		rep.owner = (CExtension *)myself;
   1.133 +		rep.original = orig;
   1.134 +		m_RepNativeList.push_back(rep);
   1.135 +		m_RepNatives.insert(natives[i].name, rep);
   1.136 +	}
   1.137 +}
   1.138 +
   1.139  void CExtensionManager::MarkAllLoaded()
   1.140  {
   1.141  	List<CExtension *>::iterator iter;