IExtension *CExtensionManager::LoadExternal(IExtensionInterface *pInterface, const char *filepath, const char *filename, char *error, size_t maxlength) { IExtension *pAlready; if ((pAlready=FindExtensionByFile(filename)) != NULL) { return pAlready; } CExtension *pExt = new CRemoteExtension(pInterface, filename, filepath); if (!pExt->Load(error, maxlength) || !pExt->IsLoaded()) { pExt->Unload(); delete pExt; return NULL; } m_Libs.push_back(pExt); return pExt; }
IExtension *CExtensionManager::LoadExtension(const char *file, char *error, size_t maxlength) { /* Remove platform extension if it's there. Compat hack. */ const char *ext = libsys->GetFileExtension(file); if (strcmp(ext, PLATFORM_LIB_EXT) == 0) { char path2[PLATFORM_MAX_PATH]; smcore.Format(path2, sizeof(path2), "%s", file); path2[strlen(file) - strlen(PLATFORM_LIB_EXT) - 1] = '\0'; return LoadExtension(path2, error, maxlength); } IExtension *pAlready; if ((pAlready=FindExtensionByFile(file)) != NULL) { return pAlready; } CExtension *pExt = new CLocalExtension(file); if (!pExt->Load(error, maxlength) || !pExt->IsLoaded()) { pExt->Unload(); delete pExt; return NULL; } /* :TODO: do QueryRunning check if the map is loaded */ m_Libs.push_back(pExt); return pExt; }
IExtension *CExtensionManager::LoadExtension(const char *file, char *error, size_t maxlength) { IExtension *pAlready; if ((pAlready=FindExtensionByFile(file)) != NULL) { return pAlready; } CExtension *pExt = new CLocalExtension(file); if (!pExt->Load(error, maxlength) || !pExt->IsLoaded()) { pExt->Unload(); delete pExt; return NULL; } /* :TODO: do QueryRunning check if the map is loaded */ m_Libs.push_back(pExt); return pExt; }
bool CExtensionManager::UnloadExtension(IExtension *_pExt) { if (!_pExt) { return false; } CExtension *pExt = (CExtension *)_pExt; if (m_Libs.find(pExt) == m_Libs.end()) { return false; } /* Tell it to unload */ if (pExt->IsLoaded()) { IExtensionInterface *pAPI = pExt->GetAPI(); pAPI->OnExtensionUnload(); } /* First remove us from internal lists */ g_ShareSys.RemoveInterfaces(_pExt); m_Libs.remove(pExt); List<CExtension *> UnloadQueue; /* Handle dependencies */ if (pExt->IsLoaded()) { /* Unload any dependent plugins */ List<CPlugin *>::iterator p_iter = pExt->m_Dependents.begin(); while (p_iter != pExt->m_Dependents.end()) { /* We have to manually unlink ourselves here, since we're no longer being managed */ scripts->UnloadPlugin((*p_iter)); p_iter = pExt->m_Dependents.erase(p_iter); } List<String>::iterator s_iter; for (s_iter = pExt->m_Libraries.begin(); s_iter != pExt->m_Libraries.end(); s_iter++) { scripts->OnLibraryAction((*s_iter).c_str(), LibraryAction_Removed); } /* 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; } if (pDep == pExt) { 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 (!pAPI->QueryInterfaceDrop((*i_iter).iface)) { if (!dropped) { dropped = true; UnloadQueue.push_back(pDep); } } pAPI->NotifyInterfaceDrop((*i_iter).iface); i_iter = pDep->m_Deps.erase(i_iter); } else { i_iter++; } } /* Flush out any back references to this plugin */ i_iter = pDep->m_ChildDeps.begin(); while (i_iter != pDep->m_ChildDeps.end()) { if ((*i_iter).owner == pExt) { i_iter = pDep->m_ChildDeps.erase(i_iter); } else { i_iter++; } } } /* Unbind our natives from Core */ pExt->DropEverything(); } IdentityToken_t *pIdentity; if ((pIdentity = pExt->GetIdentity()) != NULL) { SMGlobalClass *glob = SMGlobalClass::head; while (glob) { glob->OnSourceModIdentityDropped(pIdentity); glob = glob->m_pGlobalClassNext; } } pExt->Unload(); delete pExt; 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; }