1
0
Fork 0

Simplify pluginload and rename globals

This commit is contained in:
Duncan Ogilvie 2023-10-01 16:05:22 +02:00
parent 68112f51da
commit e3adaaac5d
3 changed files with 242 additions and 216 deletions

View File

@ -17,55 +17,57 @@
/**
\brief List of plugins.
*/
static std::vector<PLUG_DATA> pluginList;
static std::vector<PLUG_DATA> gPluginList;
/**
\brief Saved plugin directory
*/
static std::wstring pluginDirectory;
static std::wstring gPluginDirectory;
/**
\brief The current plugin handle.
*/
static int curPluginHandle = 0;
static int gCurPluginHandle = 0;
/**
\brief List of plugin callbacks.
*/
static std::vector<PLUG_CALLBACK> pluginCallbackList[CB_LAST];
static std::vector<PLUG_CALLBACK> gPluginCallbackList[CB_LAST];
/**
\brief List of plugin commands.
*/
static std::vector<PLUG_COMMAND> pluginCommandList;
static std::vector<PLUG_COMMAND> gPluginCommandList;
/**
\brief List of plugin menus.
*/
static std::vector<PLUG_MENU> pluginMenuList;
static std::vector<PLUG_MENU> gPluginMenuList;
/**
\brief List of plugin menu entries.
*/
static std::vector<PLUG_MENUENTRY> pluginMenuEntryList;
static std::vector<PLUG_MENUENTRY> gPluginMenuEntryList;
/**
\brief List of plugin exprfunctions.
*/
static std::vector<PLUG_EXPRFUNCTION> pluginExprfunctionList;
static std::vector<PLUG_EXPRFUNCTION> gPluginExprfunctionList;
/**
\brief List of plugin formatfunctions.
*/
static std::vector<PLUG_FORMATFUNCTION> pluginFormatfunctionList;
static std::vector<PLUG_FORMATFUNCTION> gPluginFormatfunctionList;
static PLUG_DATA pluginData;
/**
\brief Global data for the plugin currently being loaded
*/
static PLUG_DATA gLoadingPlugin;
#ifdef _WIN64
static const char* pluginExtension = ".dp64";
#else
static const char* pluginExtension = ".dp32";
#endif
/**
\brief Extension for the plugin file
*/
static const wchar_t* gPluginExtension = ArchValue(L".dp32", L".dp64");
/**
/brief Normalizes the plugin name. Strips the extension and path.
@ -77,152 +79,185 @@ static std::string pluginNormalizeName(std::string pluginName)
auto pathPos = pluginName.find_last_of("\\/");
if(pathPos != std::string::npos)
pluginName = pluginName.substr(pathPos + 1);
auto extPos = pluginName.find_last_of(".");
auto extPos = pluginName.rfind(StringUtils::Utf16ToUtf8(gPluginExtension));
if(extPos != std::string::npos)
pluginName = pluginName.substr(0, extPos);
return pluginName;
}
/**
\brief Returns the full path to the plugin.
\param pluginName Name of the plugin, the parameter must not contain the extension.
\return The full path to the plugin.
*/
static std::string pluginGetFullPath(std::string pluginName)
struct ChangeDirectory
{
std::string pluginPath = StringUtils::Utf16ToUtf8(pluginDirectory) + "\\" + pluginName;
ChangeDirectory(const ChangeDirectory &) = delete;
ChangeDirectory(ChangeDirectory &&) = delete;
// Check if the plugin is in a sub-directory.
std::string pluginPathSubdir = pluginPath + "\\" + pluginName + pluginExtension;
if(PathFileExistsW(StringUtils::Utf8ToUtf16(pluginPathSubdir).c_str()))
explicit ChangeDirectory(const wchar_t* newDirectory)
{
// Plugin resides in sub directory.
return pluginPathSubdir;
GetCurrentDirectoryW(_countof(mPreviousDirectory), mPreviousDirectory);
SetCurrentDirectoryW(newDirectory);
}
// Check if plugin is from the main plugin directory.
std::string pluginPathWithExt = pluginPath + pluginExtension;
if(PathFileExistsW(StringUtils::Utf8ToUtf16(pluginPathWithExt).c_str()))
~ChangeDirectory()
{
// Plugin resides in main plugins directory.
return pluginPathWithExt;
SetCurrentDirectoryW(mPreviousDirectory);
}
// Unable to determine the full path to the plugin, probably doesn't exist.
return "";
private:
wchar_t mPreviousDirectory[deflen];
};
static void* addDllDirectory(const wchar_t* newDirectory)
{
typedef PVOID(WINAPI * pfnAddDllDirectory)(LPCWSTR);
static auto pAddDllDirectory = (pfnAddDllDirectory)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "AddDllDirectory");
return pAddDllDirectory ? pAddDllDirectory(newDirectory) : nullptr;
}
static bool removeDllDirectory(void* cookie)
{
typedef BOOL(WINAPI * pfnRemoveDllDirectory)(PVOID Cookie);
static auto pRemoveDllDirectory = (pfnRemoveDllDirectory)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "RemoveDllDirectory");
return pRemoveDllDirectory ? !!pRemoveDllDirectory(cookie) : false;
}
struct DllDirectory
{
DllDirectory(const DllDirectory &) = delete;
DllDirectory(DllDirectory &&) = delete;
explicit DllDirectory(const wchar_t* directory)
{
if(directory != nullptr)
{
mCookie = addDllDirectory(directory);
}
}
~DllDirectory()
{
if(mCookie != nullptr)
{
removeDllDirectory(mCookie);
}
}
private:
void* mCookie = nullptr;
};
/**
\brief Loads a plugin from the plugin directory.
\param pluginName Name of the plugin.
\param loadall true on unload all.
\return true if it succeeds, false if it fails.
*/
bool pluginload(const char* pluginName, bool loadall)
bool pluginload(const char* pluginName)
{
//no empty plugin names allowed
if(!pluginName)
// No empty plugin names allowed
if(pluginName == nullptr || *pluginName == '\0')
return false;
// Normalize the plugin name, this can be potentially called from the pluginload command.
std::string name = pluginNormalizeName(pluginName);
// Normalize the plugin name, for flexibility the pluginload command
auto normalizedName = pluginNormalizeName(pluginName);
auto pluginDirectory = gPluginDirectory;
// Obtain the actual plugin path.
std::string pluginFullPath = pluginGetFullPath(name);
wchar_t currentDir[deflen] = L"";
if(!loadall)
auto pluginPath = gPluginDirectory + L"\\" + StringUtils::Utf8ToUtf16(normalizedName);
auto pluginSubPath = pluginPath + L"\\" + StringUtils::Utf8ToUtf16(normalizedName) + gPluginExtension;
if(PathFileExistsW(pluginSubPath.c_str()))
{
GetCurrentDirectoryW(deflen, currentDir);
SetCurrentDirectoryW(pluginDirectory.c_str());
// Plugin resides in a subdirectory
pluginDirectory = pluginPath;
pluginPath = pluginSubPath;
}
else
{
pluginPath += gPluginExtension;
}
//Check to see if this plugin is already loaded
// Check to see if this plugin is already loaded
EXCLUSIVE_ACQUIRE(LockPluginList);
for(auto it = pluginList.begin(); it != pluginList.end(); ++it)
for(auto it = gPluginList.begin(); it != gPluginList.end(); ++it)
{
if(_stricmp(it->plugname, name.c_str()) == 0)
if(_stricmp(it->plugname, normalizedName.c_str()) == 0)
{
if(!loadall)
{
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] %s already loaded\n"), it->plugname);
SetCurrentDirectoryW(currentDir);
}
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] %s already loaded\n"), it->plugname);
return false;
}
}
//check if the file exists
if(!loadall && !PathFileExistsW(StringUtils::Utf8ToUtf16(pluginFullPath).c_str()))
// Check if the file exists
if(!PathFileExistsW(pluginPath.c_str()))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] Cannot find plugin: %s\n"), name.c_str());
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] Cannot find plugin: %s\n"), StringUtils::Utf16ToUtf8(pluginPath).c_str());
return false;
}
//setup plugin data
memset(&pluginData, 0, sizeof(pluginData));
pluginData.initStruct.pluginHandle = curPluginHandle;
pluginData.hPlugin = LoadLibraryW(StringUtils::Utf8ToUtf16(pluginFullPath).c_str()); //load the plugin library
if(!pluginData.hPlugin)
// Set the working and DLL load directories
ChangeDirectory cd(pluginDirectory.c_str());
DllDirectory dd(pluginDirectory == gPluginDirectory ? nullptr : pluginDirectory.c_str());
// Setup plugin data
// NOTE: This is a global because during registration the plugin
// isn't in the gPluginList yet
gLoadingPlugin = {};
gLoadingPlugin.initStruct.pluginHandle = gCurPluginHandle;
gLoadingPlugin.hPlugin = LoadLibraryW(pluginPath.c_str()); //load the plugin library
if(!gLoadingPlugin.hPlugin)
{
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] Failed to load plugin: %s\n"), name.c_str());
SetCurrentDirectoryW(currentDir);
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] Failed to load plugin: %s\n"), normalizedName.c_str());
return false;
}
pluginData.pluginit = (PLUGINIT)GetProcAddress(pluginData.hPlugin, "pluginit");
if(!pluginData.pluginit)
gLoadingPlugin.pluginit = (PLUGINIT)GetProcAddress(gLoadingPlugin.hPlugin, "pluginit");
if(!gLoadingPlugin.pluginit)
{
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] Export \"pluginit\" not found in plugin: %s\n"), name.c_str());
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] Export \"pluginit\" not found in plugin: %s\n"), normalizedName.c_str());
for(int i = CB_INITDEBUG; i < CB_LAST; i++)
pluginunregistercallback(curPluginHandle, CBTYPE(i));
FreeLibrary(pluginData.hPlugin);
SetCurrentDirectoryW(currentDir);
pluginunregistercallback(gCurPluginHandle, CBTYPE(i));
FreeLibrary(gLoadingPlugin.hPlugin);
return false;
}
pluginData.plugstop = (PLUGSTOP)GetProcAddress(pluginData.hPlugin, "plugstop");
pluginData.plugsetup = (PLUGSETUP)GetProcAddress(pluginData.hPlugin, "plugsetup");
gLoadingPlugin.plugstop = (PLUGSTOP)GetProcAddress(gLoadingPlugin.hPlugin, "plugstop");
gLoadingPlugin.plugsetup = (PLUGSETUP)GetProcAddress(gLoadingPlugin.hPlugin, "plugsetup");
strncpy_s(pluginData.plugpath, pluginFullPath.c_str(), MAX_PATH);
strncpy_s(pluginData.plugname, name.c_str(), MAX_PATH);
strncpy_s(gLoadingPlugin.plugpath, StringUtils::Utf16ToUtf8(pluginPath).c_str(), _TRUNCATE);
strncpy_s(gLoadingPlugin.plugname, normalizedName.c_str(), _TRUNCATE);
//init plugin
if(!pluginData.pluginit(&pluginData.initStruct))
// Init plugin
if(!gLoadingPlugin.pluginit(&gLoadingPlugin.initStruct))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] pluginit failed for plugin: %s\n"), name.c_str());
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] pluginit failed for plugin: %s\n"), normalizedName.c_str());
for(int i = CB_INITDEBUG; i < CB_LAST; i++)
pluginunregistercallback(curPluginHandle, CBTYPE(i));
FreeLibrary(pluginData.hPlugin);
SetCurrentDirectoryW(currentDir);
pluginunregistercallback(gCurPluginHandle, CBTYPE(i));
FreeLibrary(gLoadingPlugin.hPlugin);
return false;
}
if(pluginData.initStruct.sdkVersion < PLUG_SDKVERSION) //the plugin SDK is not compatible
if(gLoadingPlugin.initStruct.sdkVersion < PLUG_SDKVERSION) //the plugin SDK is not compatible
{
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] %s is incompatible with this SDK version\n"), pluginData.initStruct.pluginName);
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] %s is incompatible with this SDK version\n"), gLoadingPlugin.initStruct.pluginName);
for(int i = CB_INITDEBUG; i < CB_LAST; i++)
pluginunregistercallback(curPluginHandle, CBTYPE(i));
FreeLibrary(pluginData.hPlugin);
SetCurrentDirectoryW(currentDir);
pluginunregistercallback(gCurPluginHandle, CBTYPE(i));
FreeLibrary(gLoadingPlugin.hPlugin);
return false;
}
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] %s v%d Loaded!\n"), pluginData.initStruct.pluginName, pluginData.initStruct.pluginVersion);
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] %s v%d Loaded!\n"), gLoadingPlugin.initStruct.pluginName, gLoadingPlugin.initStruct.pluginVersion);
//auto-register callbacks for certain export names
auto cbPlugin = CBPLUGIN(GetProcAddress(pluginData.hPlugin, "CBALLEVENTS"));
// Auto-register callbacks for certain export names
auto cbPlugin = CBPLUGIN(GetProcAddress(gLoadingPlugin.hPlugin, "CBALLEVENTS"));
if(cbPlugin)
{
for(int i = CB_INITDEBUG; i < CB_LAST; i++)
pluginregistercallback(curPluginHandle, CBTYPE(i), cbPlugin);
pluginregistercallback(gCurPluginHandle, CBTYPE(i), cbPlugin);
}
auto regExport = [](const char* exportname, CBTYPE cbType)
{
auto cbPlugin = CBPLUGIN(GetProcAddress(pluginData.hPlugin, exportname));
auto cbPlugin = CBPLUGIN(GetProcAddress(gLoadingPlugin.hPlugin, exportname));
if(cbPlugin)
pluginregistercallback(curPluginHandle, cbType, cbPlugin);
pluginregistercallback(gCurPluginHandle, cbType, cbPlugin);
};
regExport("CBINITDEBUG", CB_INITDEBUG);
regExport("CBSTOPDEBUG", CB_STOPDEBUG);
regExport("CB_STOPPINGDEBUG", CB_STOPPINGDEBUG);
regExport("CBSTOPPINGDEBUG", CB_STOPPINGDEBUG);
regExport("CBCREATEPROCESS", CB_CREATEPROCESS);
regExport("CBEXITPROCESS", CB_EXITPROCESS);
regExport("CBCREATETHREAD", CB_CREATETHREAD);
@ -253,16 +288,16 @@ bool pluginload(const char* pluginName, bool loadall)
regExport("CBVALTOSTRING", CB_VALTOSTRING);
regExport("CBMENUPREPARE", CB_MENUPREPARE);
//add plugin menus
// Add plugin menus
{
SectionLocker<LockPluginMenuList, false, false> menuLock; //exclusive lock
auto addPluginMenu = [](GUIMENUTYPE type)
{
int hNewMenu = GuiMenuAdd(type, pluginData.initStruct.pluginName);
int hNewMenu = GuiMenuAdd(type, gLoadingPlugin.initStruct.pluginName);
if(hNewMenu == -1)
{
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] GuiMenuAdd(%d) failed for plugin: %s\n"), type, pluginData.initStruct.pluginName);
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] GuiMenuAdd(%d) failed for plugin: %s\n"), type, gLoadingPlugin.initStruct.pluginName);
return -1;
}
else
@ -270,45 +305,46 @@ bool pluginload(const char* pluginName, bool loadall)
PLUG_MENU newMenu;
newMenu.hEntryMenu = hNewMenu;
newMenu.hParentMenu = type;
newMenu.pluginHandle = pluginData.initStruct.pluginHandle;
pluginMenuList.push_back(newMenu);
newMenu.pluginHandle = gLoadingPlugin.initStruct.pluginHandle;
gPluginMenuList.push_back(newMenu);
return newMenu.hEntryMenu;
}
};
pluginData.hMenu = addPluginMenu(GUI_PLUGIN_MENU);
pluginData.hMenuDisasm = addPluginMenu(GUI_DISASM_MENU);
pluginData.hMenuDump = addPluginMenu(GUI_DUMP_MENU);
pluginData.hMenuStack = addPluginMenu(GUI_STACK_MENU);
pluginData.hMenuGraph = addPluginMenu(GUI_GRAPH_MENU);
pluginData.hMenuMemmap = addPluginMenu(GUI_MEMMAP_MENU);
pluginData.hMenuSymmod = addPluginMenu(GUI_SYMMOD_MENU);
gLoadingPlugin.hMenu = addPluginMenu(GUI_PLUGIN_MENU);
gLoadingPlugin.hMenuDisasm = addPluginMenu(GUI_DISASM_MENU);
gLoadingPlugin.hMenuDump = addPluginMenu(GUI_DUMP_MENU);
gLoadingPlugin.hMenuStack = addPluginMenu(GUI_STACK_MENU);
gLoadingPlugin.hMenuGraph = addPluginMenu(GUI_GRAPH_MENU);
gLoadingPlugin.hMenuMemmap = addPluginMenu(GUI_MEMMAP_MENU);
gLoadingPlugin.hMenuSymmod = addPluginMenu(GUI_SYMMOD_MENU);
}
//add the plugin to the list
// Add the plugin to the list
{
SectionLocker<LockPluginList, false> pluginLock; //exclusive lock
pluginList.push_back(pluginData);
gPluginList.push_back(gLoadingPlugin);
}
//setup plugin
if(pluginData.plugsetup)
// Setup plugin
if(gLoadingPlugin.plugsetup)
{
PLUG_SETUPSTRUCT setupStruct;
setupStruct.hwndDlg = GuiGetWindowHandle();
setupStruct.hMenu = pluginData.hMenu;
setupStruct.hMenuDisasm = pluginData.hMenuDisasm;
setupStruct.hMenuDump = pluginData.hMenuDump;
setupStruct.hMenuStack = pluginData.hMenuStack;
setupStruct.hMenuGraph = pluginData.hMenuGraph;
setupStruct.hMenuMemmap = pluginData.hMenuMemmap;
setupStruct.hMenuSymmod = pluginData.hMenuSymmod;
pluginData.plugsetup(&setupStruct);
setupStruct.hMenu = gLoadingPlugin.hMenu;
setupStruct.hMenuDisasm = gLoadingPlugin.hMenuDisasm;
setupStruct.hMenuDump = gLoadingPlugin.hMenuDump;
setupStruct.hMenuStack = gLoadingPlugin.hMenuStack;
setupStruct.hMenuGraph = gLoadingPlugin.hMenuGraph;
setupStruct.hMenuMemmap = gLoadingPlugin.hMenuMemmap;
setupStruct.hMenuSymmod = gLoadingPlugin.hMenuSymmod;
gLoadingPlugin.plugsetup(&setupStruct);
}
curPluginHandle++;
gCurPluginHandle++;
// Clear the loading plugin structure (since it's now in the plugin list)
gLoadingPlugin = {};
if(!loadall)
SetCurrentDirectoryW(currentDir);
return true;
}
@ -323,10 +359,10 @@ bool pluginunload(const char* pluginName, bool unloadall)
// Normalize the plugin name.
std::string name = pluginNormalizeName(pluginName);
auto found = pluginList.end();
auto found = gPluginList.end();
{
EXCLUSIVE_ACQUIRE(LockPluginList);
found = std::find_if(pluginList.begin(), pluginList.end(), [&name](const PLUG_DATA & a)
found = std::find_if(gPluginList.begin(), gPluginList.end(), [&name](const PLUG_DATA & a)
{
return _stricmp(a.plugname, name.c_str()) == 0;
});
@ -335,7 +371,7 @@ bool pluginunload(const char* pluginName, bool unloadall)
// Will contain the actual plugin name if found.
std::string actualName = name;
if(found != pluginList.end())
if(found != gPluginList.end())
{
bool canFreeLibrary = true;
auto currentPlugin = *found;
@ -352,7 +388,7 @@ bool pluginunload(const char* pluginName, bool unloadall)
//remove the callbacks
{
EXCLUSIVE_ACQUIRE(LockPluginCallbackList);
for(auto & cbList : pluginCallbackList)
for(auto & cbList : gPluginCallbackList)
{
for(auto it = cbList.begin(); it != cbList.end();)
{
@ -376,7 +412,7 @@ bool pluginunload(const char* pluginName, bool unloadall)
if(!unloadall)
{
//remove from main pluginlist. We do this so unloadall doesn't try to unload an already released plugin
pluginList.erase(found);
gPluginList.erase(found);
}
}
@ -389,17 +425,15 @@ bool pluginunload(const char* pluginName, bool unloadall)
return false;
}
typedef BOOL(WINAPI* pfnAddDllDirectory)(LPCWSTR lpPathName);
// Returns a list of all available plugins in the specified directory without the extension.
static std::vector<std::wstring> enumerateAvailablePlugins(const std::wstring & pluginDir)
{
std::vector<std::wstring> result;
const std::wstring pluginExt = StringUtils::Utf8ToUtf16(pluginExtension);
const std::wstring pluginExt = gPluginExtension;
wchar_t searchQuery[deflen] = L"";
swprintf_s(searchQuery, L"%s\\*.*", pluginDir.c_str());
swprintf_s(searchQuery, L"%s\\*", pluginDir.c_str());
WIN32_FIND_DATAW foundData;
HANDLE hSearch = FindFirstFileW(searchQuery, &foundData);
@ -408,7 +442,7 @@ static std::vector<std::wstring> enumerateAvailablePlugins(const std::wstring &
return result;
}
const auto stripExtension = [](const std::wstring & fileName)->std::wstring
const auto stripExtension = [](const std::wstring & fileName) -> std::wstring
{
size_t pos = fileName.find_last_of(L'.');
if(pos == std::wstring::npos)
@ -450,7 +484,16 @@ static std::vector<std::wstring> enumerateAvailablePlugins(const std::wstring &
continue;
}
result.push_back(stripExtension(foundData.cFileName));
auto pluginName = stripExtension(foundData.cFileName);
auto pluginFolderPath = pluginDir + L"\\" + pluginName + L"\\" + pluginName + gPluginExtension;
if(PathFileExistsW(pluginFolderPath.c_str()))
{
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] Ignoring top-level plugin in favor of the directory 'plugins\\%s'\n"), StringUtils::Utf16ToUtf8(pluginName).c_str());
}
else
{
result.push_back(pluginName);
}
}
}
while(FindNextFileW(hSearch, &foundData));
@ -470,47 +513,30 @@ static std::vector<std::wstring> enumerateAvailablePlugins(const std::wstring &
void pluginloadall(const char* pluginDir)
{
//reserve menu space
pluginMenuList.reserve(1024);
pluginMenuEntryList.reserve(1024);
gPluginMenuList.reserve(1024);
gPluginMenuEntryList.reserve(1024);
//load new plugins
wchar_t currentDir[deflen] = L"";
pluginDirectory = StringUtils::Utf8ToUtf16(pluginDir);
//add the plugins directory as valid dependency directory
static auto pAddDllDirectory = (pfnAddDllDirectory)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "AddDllDirectory");
if(pAddDllDirectory)
pAddDllDirectory(pluginDirectory.c_str());
gPluginDirectory = StringUtils::Utf8ToUtf16(pluginDir);
// Enumerate all plugins from plugins directory.
const auto availablePlugins = enumerateAvailablePlugins(StringUtils::Utf8ToUtf16(pluginDir));
// Check the sorted list for duplicate names.
for(size_t i = 1; i < availablePlugins.size(); ++i)
{
if(availablePlugins[i] == availablePlugins[i - 1])
{
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] Plugin with same name found: %s, will only load plugin using sub-directory.\n"), StringUtils::Utf16ToUtf8(availablePlugins[i]).c_str());
}
}
GetCurrentDirectoryW(deflen, currentDir);
SetCurrentDirectoryW(pluginDirectory.c_str());
// Add the plugins directory as valid dependency directory
auto pluginDirectoryCookie = addDllDirectory(gPluginDirectory.c_str());
for(const std::wstring & pluginName : availablePlugins)
{
// Check if the plugin is a sub-directory and also add it to the search paths.
std::wstring pluginPath = pluginDirectory + L"\\" + pluginName;
if(PathIsDirectoryW(pluginPath.c_str()))
{
pAddDllDirectory(pluginPath.c_str());
}
pluginload(StringUtils::Utf16ToUtf8(pluginName).c_str(), true);
dprintf("[pluginload] %S\n", pluginName.c_str());
pluginload(StringUtils::Utf16ToUtf8(pluginName).c_str());
}
SetCurrentDirectoryW(currentDir);
// Remove the plugins directory after loading finished
if(pluginDirectoryCookie != nullptr)
{
removeDllDirectory(pluginDirectoryCookie);
}
}
/**
@ -522,7 +548,7 @@ void pluginunloadall()
const auto pluginListCopy = []()
{
SHARED_ACQUIRE(LockPluginList);
return pluginList;
return gPluginList;
}();
// Unload all plugins.
@ -531,7 +557,7 @@ void pluginunloadall()
// Remove all plugins from the list.
SHARED_ACQUIRE(LockPluginList);
pluginList.clear();
gPluginList.clear();
SHARED_RELEASE();
}
@ -542,7 +568,7 @@ void pluginunloadall()
void plugincmdunregisterall(int pluginHandle)
{
SHARED_ACQUIRE(LockPluginCommandList);
auto commandList = pluginCommandList; //copy for thread-safety reasons
auto commandList = gPluginCommandList; //copy for thread-safety reasons
SHARED_RELEASE();
for(auto itr = commandList.begin(); itr != commandList.end();)
{
@ -566,7 +592,7 @@ void plugincmdunregisterall(int pluginHandle)
void pluginexprfuncunregisterall(int pluginHandle)
{
SHARED_ACQUIRE(LockPluginExprfunctionList);
auto exprFuncList = pluginExprfunctionList; //copy for thread-safety reasons
auto exprFuncList = gPluginExprfunctionList; //copy for thread-safety reasons
SHARED_RELEASE();
auto i = exprFuncList.begin();
while(i != exprFuncList.end())
@ -589,7 +615,7 @@ void pluginexprfuncunregisterall(int pluginHandle)
void pluginformatfuncunregisterall(int pluginHandle)
{
SHARED_ACQUIRE(LockPluginFormatfunctionList);
auto formatFuncList = pluginFormatfunctionList; //copy for thread-safety reasons
auto formatFuncList = gPluginFormatfunctionList; //copy for thread-safety reasons
SHARED_RELEASE();
auto i = formatFuncList.begin();
while(i != formatFuncList.end())
@ -619,7 +645,7 @@ void pluginregistercallback(int pluginHandle, CBTYPE cbType, CBPLUGIN cbPlugin)
cbStruct.cbType = cbType;
cbStruct.cbPlugin = cbPlugin;
EXCLUSIVE_ACQUIRE(LockPluginCallbackList);
pluginCallbackList[cbType].push_back(cbStruct);
gPluginCallbackList[cbType].push_back(cbStruct);
}
/**
@ -630,7 +656,7 @@ void pluginregistercallback(int pluginHandle, CBTYPE cbType, CBPLUGIN cbPlugin)
bool pluginunregistercallback(int pluginHandle, CBTYPE cbType)
{
EXCLUSIVE_ACQUIRE(LockPluginCallbackList);
auto & cbList = pluginCallbackList[cbType];
auto & cbList = gPluginCallbackList[cbType];
for(auto it = cbList.begin(); it != cbList.end();)
{
if(it->pluginHandle == pluginHandle)
@ -651,10 +677,10 @@ bool pluginunregistercallback(int pluginHandle, CBTYPE cbType)
*/
void plugincbcall(CBTYPE cbType, void* callbackInfo)
{
if(pluginCallbackList[cbType].empty())
if(gPluginCallbackList[cbType].empty())
return;
SHARED_ACQUIRE(LockPluginCallbackList);
auto cbList = pluginCallbackList[cbType]; //copy for thread-safety reasons
auto cbList = gPluginCallbackList[cbType]; //copy for thread-safety reasons
SHARED_RELEASE();
for(const auto & currentCallback : cbList)
currentCallback.cbPlugin(cbType, callbackInfo);
@ -667,18 +693,18 @@ void plugincbcall(CBTYPE cbType, void* callbackInfo)
*/
bool plugincbempty(CBTYPE cbType)
{
return pluginCallbackList[cbType].empty();
return gPluginCallbackList[cbType].empty();
}
static bool findPluginName(int pluginHandle, String & name)
{
SHARED_ACQUIRE(LockPluginList);
if(pluginData.initStruct.pluginHandle == pluginHandle)
if(gLoadingPlugin.initStruct.pluginHandle == pluginHandle)
{
name = pluginData.initStruct.pluginName;
name = gLoadingPlugin.initStruct.pluginName;
return true;
}
for(auto & plugin : pluginList)
for(auto & plugin : gPluginList)
{
if(plugin.initStruct.pluginHandle == pluginHandle)
{
@ -714,7 +740,7 @@ bool plugincmdregister(int pluginHandle, const char* command, CBPLUGINCOMMAND cb
return false;
}
EXCLUSIVE_ACQUIRE(LockPluginCommandList);
pluginCommandList.push_back(plugCmd);
gPluginCommandList.push_back(plugCmd);
EXCLUSIVE_RELEASE();
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN, %s] Command \"%s\" registered!\n"), plugName.c_str(), command);
return true;
@ -734,12 +760,12 @@ bool plugincmdunregister(int pluginHandle, const char* command)
if(!findPluginName(pluginHandle, plugName))
return false;
EXCLUSIVE_ACQUIRE(LockPluginCommandList);
for(auto it = pluginCommandList.begin(); it != pluginCommandList.end(); ++it)
for(auto it = gPluginCommandList.begin(); it != gPluginCommandList.end(); ++it)
{
const auto & currentCommand = *it;
if(currentCommand.pluginHandle == pluginHandle && !strcmp(currentCommand.command, command))
{
pluginCommandList.erase(it);
gPluginCommandList.erase(it);
EXCLUSIVE_RELEASE();
if(!dbgcmddel(command))
goto beach;
@ -764,9 +790,9 @@ int pluginmenuadd(int hMenu, const char* title)
return -1;
EXCLUSIVE_ACQUIRE(LockPluginMenuList);
int nFound = -1;
for(unsigned int i = 0; i < pluginMenuList.size(); i++)
for(unsigned int i = 0; i < gPluginMenuList.size(); i++)
{
if(pluginMenuList.at(i).hEntryMenu == hMenu)
if(gPluginMenuList.at(i).hEntryMenu == hMenu)
{
nFound = i;
break;
@ -776,10 +802,10 @@ int pluginmenuadd(int hMenu, const char* title)
return -1;
int hMenuNew = GuiMenuAdd(hMenu, title);
PLUG_MENU newMenu;
newMenu.pluginHandle = pluginMenuList.at(nFound).pluginHandle;
newMenu.pluginHandle = gPluginMenuList.at(nFound).pluginHandle;
newMenu.hEntryMenu = hMenuNew;
newMenu.hParentMenu = hMenu;
pluginMenuList.push_back(newMenu);
gPluginMenuList.push_back(newMenu);
return hMenuNew;
}
@ -797,7 +823,7 @@ bool pluginmenuaddentry(int hMenu, int hEntry, const char* title)
EXCLUSIVE_ACQUIRE(LockPluginMenuList);
int pluginHandle = -1;
//find plugin handle
for(const auto & currentMenu : pluginMenuList)
for(const auto & currentMenu : gPluginMenuList)
{
if(currentMenu.hEntryMenu == hMenu)
{
@ -808,7 +834,7 @@ bool pluginmenuaddentry(int hMenu, int hEntry, const char* title)
if(pluginHandle == -1) //not found
return false;
//search if hEntry was previously used
for(const auto & currentMenu : pluginMenuEntryList)
for(const auto & currentMenu : gPluginMenuEntryList)
if(currentMenu.pluginHandle == pluginHandle && currentMenu.hEntryPlugin == hEntry)
return false;
int hNewEntry = GuiMenuAddEntry(hMenu, title);
@ -819,7 +845,7 @@ bool pluginmenuaddentry(int hMenu, int hEntry, const char* title)
newMenu.hParentMenu = hMenu;
newMenu.hEntryPlugin = hEntry;
newMenu.pluginHandle = pluginHandle;
pluginMenuEntryList.push_back(newMenu);
gPluginMenuEntryList.push_back(newMenu);
return true;
}
@ -831,7 +857,7 @@ bool pluginmenuaddentry(int hMenu, int hEntry, const char* title)
bool pluginmenuaddseparator(int hMenu)
{
SHARED_ACQUIRE(LockPluginMenuList);
for(const auto & currentMenu : pluginMenuList)
for(const auto & currentMenu : gPluginMenuList)
{
if(currentMenu.hEntryMenu == hMenu)
{
@ -849,17 +875,17 @@ bool pluginmenuaddseparator(int hMenu)
static void pluginmenuclear_helper(int hMenu)
{
//delete menu entries
for(auto i = pluginMenuEntryList.size() - 1; i != -1; i--)
if(hMenu == pluginMenuEntryList.at(i).hParentMenu) //we found an entry that has the menu as parent
pluginMenuEntryList.erase(pluginMenuEntryList.begin() + i);
for(auto i = gPluginMenuEntryList.size() - 1; i != -1; i--)
if(hMenu == gPluginMenuEntryList.at(i).hParentMenu) //we found an entry that has the menu as parent
gPluginMenuEntryList.erase(gPluginMenuEntryList.begin() + i);
//delete the menus
std::vector<int> menuClearQueue;
for(auto i = pluginMenuList.size() - 1; i != -1; i--)
for(auto i = gPluginMenuList.size() - 1; i != -1; i--)
{
if(hMenu == pluginMenuList.at(i).hParentMenu) //we found a menu that has the menu as parent
if(hMenu == gPluginMenuList.at(i).hParentMenu) //we found a menu that has the menu as parent
{
menuClearQueue.push_back(pluginMenuList.at(i).hEntryMenu);
pluginMenuList.erase(pluginMenuList.begin() + i);
menuClearQueue.push_back(gPluginMenuList.at(i).hEntryMenu);
gPluginMenuList.erase(gPluginMenuList.begin() + i);
}
}
//recursively clear the menus
@ -876,14 +902,14 @@ bool pluginmenuclear(int hMenu, bool erase)
{
EXCLUSIVE_ACQUIRE(LockPluginMenuList);
pluginmenuclear_helper(hMenu);
for(auto it = pluginMenuList.begin(); it != pluginMenuList.end(); ++it)
for(auto it = gPluginMenuList.begin(); it != gPluginMenuList.end(); ++it)
{
const auto & currentMenu = *it;
if(currentMenu.hEntryMenu == hMenu)
{
if(erase)
{
it = pluginMenuList.erase(it);
it = gPluginMenuList.erase(it);
GuiMenuRemove(hMenu);
}
else
@ -904,8 +930,8 @@ void pluginmenucall(int hEntry)
return;
SectionLocker<LockPluginMenuList, true, false> menuLock; //shared lock
auto i = pluginMenuEntryList.begin();
while(i != pluginMenuEntryList.end())
auto i = gPluginMenuEntryList.begin();
while(i != gPluginMenuEntryList.end())
{
const auto currentMenu = *i;
++i;
@ -914,7 +940,7 @@ void pluginmenucall(int hEntry)
PLUG_CB_MENUENTRY menuEntryInfo;
menuEntryInfo.hEntry = currentMenu.hEntryPlugin;
SectionLocker<LockPluginCallbackList, true> callbackLock; //shared lock
const auto & cbList = pluginCallbackList[CB_MENUENTRY];
const auto & cbList = gPluginCallbackList[CB_MENUENTRY];
for(auto j = cbList.begin(); j != cbList.end();)
{
auto currentCallback = *j++;
@ -968,7 +994,7 @@ bool pluginwineventglobal(MSG* message)
void pluginmenuseticon(int hMenu, const ICONDATA* icon)
{
SHARED_ACQUIRE(LockPluginMenuList);
for(const auto & currentMenu : pluginMenuList)
for(const auto & currentMenu : gPluginMenuList)
{
if(currentMenu.hEntryMenu == hMenu)
{
@ -989,7 +1015,7 @@ void pluginmenuentryseticon(int pluginHandle, int hEntry, const ICONDATA* icon)
if(hEntry == -1)
return;
SHARED_ACQUIRE(LockPluginMenuList);
for(const auto & currentMenu : pluginMenuEntryList)
for(const auto & currentMenu : gPluginMenuEntryList)
{
if(currentMenu.pluginHandle == pluginHandle && currentMenu.hEntryPlugin == hEntry)
{
@ -1004,7 +1030,7 @@ void pluginmenuentrysetchecked(int pluginHandle, int hEntry, bool checked)
if(hEntry == -1)
return;
SHARED_ACQUIRE(LockPluginMenuList);
for(const auto & currentMenu : pluginMenuEntryList)
for(const auto & currentMenu : gPluginMenuEntryList)
{
if(currentMenu.pluginHandle == pluginHandle && currentMenu.hEntryPlugin == hEntry)
{
@ -1017,7 +1043,7 @@ void pluginmenuentrysetchecked(int pluginHandle, int hEntry, bool checked)
void pluginmenusetvisible(int pluginHandle, int hMenu, bool visible)
{
SHARED_ACQUIRE(LockPluginMenuList);
for(const auto & currentMenu : pluginMenuList)
for(const auto & currentMenu : gPluginMenuList)
{
if(currentMenu.hEntryMenu == hMenu)
{
@ -1032,7 +1058,7 @@ void pluginmenuentrysetvisible(int pluginHandle, int hEntry, bool visible)
if(hEntry == -1)
return;
SHARED_ACQUIRE(LockPluginMenuList);
for(const auto & currentMenu : pluginMenuEntryList)
for(const auto & currentMenu : gPluginMenuEntryList)
{
if(currentMenu.pluginHandle == pluginHandle && currentMenu.hEntryPlugin == hEntry)
{
@ -1047,7 +1073,7 @@ void pluginmenusetname(int pluginHandle, int hMenu, const char* name)
if(!name)
return;
SHARED_ACQUIRE(LockPluginMenuList);
for(const auto & currentMenu : pluginMenuList)
for(const auto & currentMenu : gPluginMenuList)
{
if(currentMenu.hEntryMenu == hMenu)
{
@ -1062,7 +1088,7 @@ void pluginmenuentrysetname(int pluginHandle, int hEntry, const char* name)
if(hEntry == -1 || !name)
return;
SHARED_ACQUIRE(LockPluginMenuList);
for(const auto & currentMenu : pluginMenuEntryList)
for(const auto & currentMenu : gPluginMenuEntryList)
{
if(currentMenu.pluginHandle == pluginHandle && currentMenu.hEntryPlugin == hEntry)
{
@ -1077,11 +1103,11 @@ void pluginmenuentrysethotkey(int pluginHandle, int hEntry, const char* hotkey)
if(hEntry == -1 || !hotkey)
return;
SHARED_ACQUIRE(LockPluginMenuList);
for(const auto & currentMenu : pluginMenuEntryList)
for(const auto & currentMenu : gPluginMenuEntryList)
{
if(currentMenu.pluginHandle == pluginHandle && currentMenu.hEntryPlugin == hEntry)
{
for(const auto & plugin : pluginList)
for(const auto & plugin : gPluginList)
{
if(plugin.initStruct.pluginHandle == pluginHandle)
{
@ -1103,7 +1129,7 @@ void pluginmenuentrysethotkey(int pluginHandle, int hEntry, const char* hotkey)
bool pluginmenuremove(int hMenu)
{
EXCLUSIVE_ACQUIRE(LockPluginMenuList);
for(const auto & currentMenu : pluginMenuList)
for(const auto & currentMenu : gPluginMenuList)
if(currentMenu.hEntryMenu == hMenu && currentMenu.hParentMenu < 256)
return false;
return pluginmenuclear(hMenu, true);
@ -1112,13 +1138,13 @@ bool pluginmenuremove(int hMenu)
bool pluginmenuentryremove(int pluginHandle, int hEntry)
{
EXCLUSIVE_ACQUIRE(LockPluginMenuList);
for(auto it = pluginMenuEntryList.begin(); it != pluginMenuEntryList.end(); ++it)
for(auto it = gPluginMenuEntryList.begin(); it != gPluginMenuEntryList.end(); ++it)
{
const auto & currentEntry = *it;
if(currentEntry.pluginHandle == pluginHandle && currentEntry.hEntryPlugin == hEntry)
{
GuiMenuRemove(currentEntry.hEntryMenu);
pluginMenuEntryList.erase(it);
gPluginMenuEntryList.erase(it);
return true;
}
}
@ -1172,7 +1198,7 @@ bool pluginexprfuncregister(int pluginHandle, const char* name, int argc, CBPLUG
return false;
}
EXCLUSIVE_ACQUIRE(LockPluginExprfunctionList);
pluginExprfunctionList.push_back(plugExprfunction);
gPluginExprfunctionList.push_back(plugExprfunction);
EXCLUSIVE_RELEASE();
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN, %s] Expression function \"%s\" registered!\n"), plugName.c_str(), name);
return true;
@ -1198,7 +1224,7 @@ bool pluginexprfuncregisterex(int pluginHandle, const char* name, const ValueTyp
return false;
}
EXCLUSIVE_ACQUIRE(LockPluginExprfunctionList);
pluginExprfunctionList.push_back(plugExprfunction);
gPluginExprfunctionList.push_back(plugExprfunction);
EXCLUSIVE_RELEASE();
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN, %s] Expression function \"%s\" registered!\n"), plugName.c_str(), name);
return true;
@ -1211,12 +1237,12 @@ bool pluginexprfuncunregister(int pluginHandle, const char* name)
if(!findPluginName(pluginHandle, plugName))
return false;
EXCLUSIVE_ACQUIRE(LockPluginExprfunctionList);
for(auto it = pluginExprfunctionList.begin(); it != pluginExprfunctionList.end(); ++it)
for(auto it = gPluginExprfunctionList.begin(); it != gPluginExprfunctionList.end(); ++it)
{
const auto & currentExprfunction = *it;
if(currentExprfunction.pluginHandle == pluginHandle && !strcmp(currentExprfunction.name, name))
{
pluginExprfunctionList.erase(it);
gPluginExprfunctionList.erase(it);
EXCLUSIVE_RELEASE();
if(!ExpressionFunctions::Unregister(name))
goto beach;
@ -1243,7 +1269,7 @@ bool pluginformatfuncregister(int pluginHandle, const char* type, CBPLUGINFORMAT
return false;
}
EXCLUSIVE_ACQUIRE(LockPluginFormatfunctionList);
pluginFormatfunctionList.push_back(plugFormatfunction);
gPluginFormatfunctionList.push_back(plugFormatfunction);
EXCLUSIVE_RELEASE();
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN, %s] Format function \"%s\" registered!\n"), plugName.c_str(), type);
return true;
@ -1255,12 +1281,12 @@ bool pluginformatfuncunregister(int pluginHandle, const char* type)
if(!findPluginName(pluginHandle, plugName))
return false;
EXCLUSIVE_ACQUIRE(LockPluginFormatfunctionList);
for(auto it = pluginFormatfunctionList.begin(); it != pluginFormatfunctionList.end(); ++it)
for(auto it = gPluginFormatfunctionList.begin(); it != gPluginFormatfunctionList.end(); ++it)
{
const auto & currentFormatfunction = *it;
if(currentFormatfunction.pluginHandle == pluginHandle && !strcmp(currentFormatfunction.name, type))
{
pluginFormatfunctionList.erase(it);
gPluginFormatfunctionList.erase(it);
EXCLUSIVE_RELEASE();
if(!FormatFunctions::Unregister(type))
goto beach;

View File

@ -66,7 +66,7 @@ struct PLUG_FORMATFUNCTION
};
//plugin management functions
bool pluginload(const char* pluginname, bool loadall = false);
bool pluginload(const char* pluginname);
bool pluginunload(const char* pluginname, bool unloadall = false);
void pluginloadall(const char* pluginDir);
void pluginunloadall();

View File

@ -319,7 +319,7 @@ static VOID CALLBACK MyLdrDllNotification(
typedef BOOL(WINAPI* pfnSetDefaultDllDirectories)(DWORD DirectoryFlags);
typedef BOOL(WINAPI* pfnSetDllDirectoryW)(LPCWSTR lpPathName);
typedef BOOL(WINAPI* pfnAddDllDirectory)(LPCWSTR lpPathName);
typedef PVOID(WINAPI* pfnAddDllDirectory)(LPCWSTR lpPathName);
static pfnSetDefaultDllDirectories pSetDefaultDllDirectories;
static pfnSetDllDirectoryW pSetDllDirectoryW;