dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs) { int i; HMODULE lib; lib = LoadLibrary(name); if (!lib) return NULL; if (funcs) { for (i = 0; funcs[i].name; i++) { *funcs[i].funcptr = GetProcAddress(lib, funcs[i].name); if (!*funcs[i].funcptr) break; } if (funcs[i].name) { Sys_CloseLibrary((dllhandle_t*)lib); lib = NULL; } } return (dllhandle_t*)lib; }
/* * @brief Opens and loads the specified shared library. The function identified by * entry_point is resolved and invoked with the specified parameters, its * return value returned by this function. */ void *Sys_LoadLibrary(const char *name, void **handle, const char *entry_point, void *params) { typedef void *EntryPointFunc(void *); EntryPointFunc *EntryPoint; if (*handle) { Com_Warn("%s: handle already open\n", name); Sys_CloseLibrary(handle); } Sys_OpenLibrary(name, handle); EntryPoint = (EntryPointFunc *) dlsym(*handle, entry_point); if (!EntryPoint) { Sys_CloseLibrary(handle); Com_Error(ERR_DROP, "%s: Failed to resolve %s\n", name, entry_point); } return EntryPoint(params); }
void PbSvUnload() { pbsv.field_4 = 0; pbsv.sa = 0; pbsv.sb = 0; pbsv.ConnectStringTrap = 0; pbsv.AuthClient = 0; pbsv.CaptureConsole = 0; if ( pbsv.hLibModule ) { Sys_CloseLibrary(pbsv.hLibModule); } pbsv.hLibModule = 0; }
void PHandler_Unload(int id) // Unload a plugin, safe for use. { static qboolean unloading = qfalse; void *lib_handle; int i; if(unloading){ Com_PrintError("PHandler_Unload: tried to unload plugin #%d from it's destructor!\n",id); return; } if(pluginFunctions.plugins[id].loaded){ if(pluginFunctions.plugins[id].exports != 0){ // Library-plugins cannot be unloaded, see plugins/readme.txt Com_PrintError("PHandler_Unload: Cannot unload a library plugin!\n"); return; } if(pluginFunctions.plugins[id].scriptfunctions != 0 || pluginFunctions.plugins[id].scriptmethods != 0){ // Script-library plugins cannot be unloaded, see plugins/readme.txt Com_PrintError("PHandler_Unload: Cannot unload a script-library plugin!\n"); return; } unloading = qtrue; // Preventing endless recursion... if(pluginFunctions.plugins[id].OnUnload != NULL){ pluginFunctions.hasControl = id; (*pluginFunctions.plugins[id].OnUnload)(); pluginFunctions.hasControl = PLUGIN_UNKNOWN; } unloading = qfalse; // Remove all server commands of the plugin for(i=0;i<pluginFunctions.plugins[id].cmds;i++){ if(pluginFunctions.plugins[id].cmd[i].xcommand!=NULL){ Com_DPrintf("Removing command \"%s\"...\n",pluginFunctions.plugins[id].cmd[i].name); Cmd_RemoveCommand(pluginFunctions.plugins[id].cmd[i].name); } } lib_handle = pluginFunctions.plugins[id].lib_handle; // Save the lib handle Com_Memset(&(pluginFunctions.plugins[id]), 0x00, sizeof(plugin_t)); // Wipe out all the data Sys_CloseLibrary(lib_handle); // Close the dll as there are no more references to it --pluginFunctions.loadedPlugins; }else{ Com_Printf("Tried unloading a not loaded plugin!\nPlugin ID: %d.",id); } }
void PHandler_Load(char* name) // Load a plugin, safe for use { int i,j; char* realpath; char filepathbuf[MAX_OSPATH]; char hash[128]; long unsigned sizeofhash; void *lib_handle; pluginInfo_t info; if(!pluginFunctions.enabled){ Com_Printf("Plugin handler is not initialized!\n"); return; } if(pluginFunctions.loadedPlugins>=MAX_PLUGINS-1){ Com_Printf("Too many plugins loaded."); return; } /* +18 for "plugins/%s.dynlib" */ if(strlen(name) + 18 >= sizeof(pluginFunctions.plugins[0].name)){ Com_Printf("Pluginname is too long."); return; } Com_DPrintf("Checking if the plugin is not already loaded...\n"); // Check if the plugin is not already loaded... for(i=0;i<MAX_PLUGINS;i++){ if(Q_stricmp(name, pluginFunctions.plugins[i].name) == qfalse){ Com_Printf("This plugin is already loaded!\n"); return; } } Com_DPrintf("Checking if the plugin file exists and is of correct format...\n"); //Additional test if a file is there realpath = (char*)PHandler_OpenTempFile(name, filepathbuf, sizeof(filepathbuf)); // Load a plugin, safe for use if(realpath == NULL) { return; } Com_DPrintf("Loading the plugin .so...\n"); if(com_securemode) { hash[0] = '\0'; sizeofhash = sizeof(hash); Sec_HashFile(SEC_HASH_TIGER, realpath, hash, &sizeofhash, qfalse); if(Q_stricmp(hash ,PLUGINGAMERANGER_HASH) && Q_stricmp(hash ,PLUGINCENSOR_HASH) && Q_stricmp(hash ,PLUGINANTISPAM_HASH)) { Com_Printf("Tiger = %s\n", hash); Com_PrintError("%s checksum missmatch! This plugin will not be loaded in securemode.\n", realpath); return; } } lib_handle = Sys_LoadLibrary(realpath); if (!lib_handle) { Com_PrintError("Failed to load the plugin %s!\n", realpath); PHandler_CloseTempFile( realpath ); return; } PHandler_CloseTempFile( realpath ); Com_DPrintf("Plugin OK! Loading...\n"); // find first free plugin slot for(i=0;i<MAX_PLUGINS;i++){ if(!(pluginFunctions.plugins[i].loaded)) break; } pluginFunctions.plugins[i].OnInit = Sys_GetProcedure("OnInit"); for(j=0;j<PLUGINS_ITEMCOUNT;++j){ pluginFunctions.plugins[i].OnEvent[j] = Sys_GetProcedure(PHandler_Events[j]); } pluginFunctions.plugins[i].OnInfoRequest = pluginFunctions.plugins[i].OnEvent[PLUGINS_ONINFOREQUEST]; pluginFunctions.plugins[i].OnUnload = Sys_GetProcedure("OnUnload"); pluginFunctions.plugins[i].loaded = qtrue; pluginFunctions.plugins[i].enabled = qtrue; Q_strncpyz(pluginFunctions.plugins[i].name, name, sizeof(pluginFunctions.plugins[i].name)); pluginFunctions.initializing_plugin = qtrue; if(pluginFunctions.plugins[i].OnInit==NULL){ Com_Printf("Error loading plugin's OnInit function.\nPlugin load failed.\n"); pluginFunctions.initializing_plugin = qfalse; memset(pluginFunctions.plugins + i,0x00,sizeof(plugin_t)); // We need to remove all references so we can dlclose. Sys_CloseLibrary(lib_handle); return; } pluginFunctions.hasControl = PLUGIN_UNKNOWN; Com_Printf("Plugin's OnInit executed successfully!\n"); // Save info about the loaded plugin pluginFunctions.initializing_plugin = qfalse; pluginFunctions.loadedPlugins++; pluginFunctions.plugins[i].lib_handle = lib_handle; if(pluginFunctions.plugins[i].OnInfoRequest){ Com_DPrintf("Fetching plugin information...\n"); pluginFunctions.hasControl = i; (*pluginFunctions.plugins[i].OnInfoRequest)(&info); pluginFunctions.hasControl = PLUGIN_UNKNOWN; if(info.handlerVersion.major != PLUGIN_HANDLER_VERSION_MAJOR || (info.handlerVersion.minor - info.handlerVersion.minor %100) != (PLUGIN_HANDLER_VERSION_MINOR - PLUGIN_HANDLER_VERSION_MINOR %100)) { Com_PrintError("This plugin might not be compatible with this server version! Requested plugin handler version: %d.%d, server's plugin handler version: %d.%d. Unloading the plugin...\n",info.handlerVersion.major,info.handlerVersion.minor, PLUGIN_HANDLER_VERSION_MAJOR,PLUGIN_HANDLER_VERSION_MINOR); PHandler_Unload(i); return; } }else{ Com_PrintError("function OnInfoRequest not found in the plugin file. Unloading...\n"); PHandler_Unload(i); return; } Com_DPrintf("Executing plugin's OnInit...\n"); pluginFunctions.hasControl = i; if((*pluginFunctions.plugins[i].OnInit)()<0) { pluginFunctions.hasControl = PLUGIN_UNKNOWN; Com_Printf("Error in plugin's OnInit function!\nPlugin load failed.\n"); pluginFunctions.initializing_plugin = qfalse; memset(pluginFunctions.plugins + i,0x00,sizeof(plugin_t)); // We need to remove all references so we can dlclose. Sys_CloseLibrary(lib_handle); return; } Com_Printf("Plugin %s loaded successfully. Server is currently running %d plugins.\n",pluginFunctions.plugins[i].name,pluginFunctions.loadedPlugins); return; }