diff --git a/SrcBehaviorLoader/PluginLoader.cpp b/SrcBehaviorLoader/PluginLoader.cpp index 11e3a5a4201120cceab5561bd0080a4bfa242a39..7d81e1427b70b5c64ff95a15f4bddbab065e5452 100644 --- a/SrcBehaviorLoader/PluginLoader.cpp +++ b/SrcBehaviorLoader/PluginLoader.cpp @@ -16,8 +16,8 @@ std::vector<std::string> QueryKey(HKEY hKey, std::string path) { - //See https://docs.microsoft.com/en-us/windows/desktop/sysinfo/enumerating-registry-subkeys - std::vector<std::string> list; + //See https://docs.microsoft.com/en-us/windows/desktop/sysinfo/enumerating-registry-subkeys + std::vector<std::string> list; TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name DWORD cchClassName = MAX_PATH; // size of class string DWORD cSubKeys=0; // number of subkeys @@ -52,7 +52,7 @@ std::vector<std::string> QueryKey(HKEY hKey, std::string path) // Enumerate the key values. if (cValues) { - //printf( "\nNumber of values: %d\n", cValues); + //printf( "\nNumber of values: %d\n", cValues); for (i=0, retCode=ERROR_SUCCESS; i<cValues; i++) { @@ -68,51 +68,51 @@ std::vector<std::string> QueryKey(HKEY hKey, std::string path) if (retCode == ERROR_SUCCESS ) { - CRegKey regKey; - CHAR szBuffer[512]; - ULONG dwBufferSize = sizeof(szBuffer); - - if(ERROR_SUCCESS != regKey.Open(HKEY_LOCAL_MACHINE, path.c_str())) - { - qWarning() << "Error opening registry path " << path.c_str(); - regKey.Close(); - } - if( ERROR_SUCCESS != regKey.QueryStringValue(achValue,szBuffer,&dwBufferSize)) - { - qWarning() << "Error opening registry value " << achValue; - regKey.Close(); - } - - std::string fp = szBuffer; - std::replace( fp.begin(), fp.end(), '\\', '/'); - list.push_back(fp); + CRegKey regKey; + CHAR szBuffer[512]; + ULONG dwBufferSize = sizeof(szBuffer); + + if(ERROR_SUCCESS != regKey.Open(HKEY_LOCAL_MACHINE, path.c_str())) + { + qWarning() << "Error opening registry path " << path.c_str(); + regKey.Close(); + } + if( ERROR_SUCCESS != regKey.QueryStringValue(achValue,szBuffer,&dwBufferSize)) + { + qWarning() << "Error opening registry value " << achValue; + regKey.Close(); + } + + std::string fp = szBuffer; + std::replace( fp.begin(), fp.end(), '\\', '/'); + list.push_back(fp); } } } - return list; + return list; } #endif std::vector<std::string> PluginLoader::queryRegistryBehaviors(std::string path) { - std::vector<std::string> list; - - #ifdef _WIN32 - HKEY hTestKey; - - if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, - TEXT(path.c_str()), - 0, - KEY_READ, - &hTestKey) == ERROR_SUCCESS) - { - list = QueryKey(hTestKey, path); - } - - RegCloseKey(hTestKey); - #endif - - return list; + std::vector<std::string> list; + + #ifdef _WIN32 + HKEY hTestKey; + + if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, + TEXT(path.c_str()), + 0, + KEY_READ, + &hTestKey) == ERROR_SUCCESS) + { + list = QueryKey(hTestKey, path); + } + + RegCloseKey(hTestKey); + #endif + + return list; } #ifdef _WIN32 @@ -130,7 +130,7 @@ const char * WinGetEnv(const char * name) } } bool WinSetEnv(const char* name, const char* toWhat){ - return SetEnvironmentVariableA(name, toWhat); + return SetEnvironmentVariableA(name, toWhat); } #endif @@ -142,198 +142,198 @@ bool is_shared_library(std::filesystem::path const& p) const char* PluginLoader::addDllPath(std::string f) { - //Get the directory of the DLL/*.so and add it to the PATH env variable. - //This way dependencies can be shipped in the same directory - #ifdef _WIN32 - QFileInfo finf(f.c_str()); - //rather than the buggy _getenv: https://docs.microsoft.com/de-de/windows/desktop/api/winbase/nf-winbase-getenvironmentvariable - auto old_path = WinGetEnv("PATH"); - auto path = std::ostringstream(); - if(old_path){ - path << old_path << ";" << finf.absolutePath().toStdString().c_str(); - WinSetEnv("PATH", path.str().c_str()); - }else{ - qWarning() << "Failed to get and modify PATH enviromental variable."; - } - return old_path; - #endif - - return ""; + //Get the directory of the DLL/*.so and add it to the PATH env variable. + //This way dependencies can be shipped in the same directory + #ifdef _WIN32 + QFileInfo finf(f.c_str()); + //rather than the buggy _getenv: https://docs.microsoft.com/de-de/windows/desktop/api/winbase/nf-winbase-getenvironmentvariable + auto old_path = WinGetEnv("PATH"); + auto path = std::ostringstream(); + if(old_path){ + path << old_path << ";" << finf.absolutePath().toStdString().c_str(); + WinSetEnv("PATH", path.str().c_str()); + }else{ + qWarning() << "Failed to get and modify PATH enviromental variable."; + } + return old_path; + #endif + + return ""; } void PluginLoader::delDllPath(const char* oldPath){ - //reset path. We don't want some weird cross-effects - #ifdef _WIN32 - if(oldPath){ - WinSetEnv("PATH", oldPath); - } - #endif + //reset path. We don't want some weird cross-effects + #ifdef _WIN32 + if(oldPath){ + WinSetEnv("PATH", oldPath); + } + #endif } bool endsWith(std::string value, std::string ending) { - std::transform(value.begin(), value.end(), value.begin(), ::tolower); - std::transform(ending.begin(), ending.end(), ending.begin(), ::tolower); + std::transform(value.begin(), value.end(), value.begin(), ::tolower); + std::transform(ending.begin(), ending.end(), ending.begin(), ::tolower); if (ending.size() > value.size()) return false; return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); } bool validSuffix(std::string f, std::string suffix){ - return (endsWith(f,suffix+".dll") || endsWith(f,suffix+".so")); + return (endsWith(f,suffix+".dll") || endsWith(f,suffix+".so")); } std::vector<std::string> PluginLoader::searchDirectoriesForPlugins(std::vector<std::string> list, std::string suffix){ - //Search directories + //Search directories std::vector<std::string> filesFromFolders; - for (auto f: list) - { - auto path = std::filesystem::path(f); - if (path.empty()) - { - continue; - } - if (std::filesystem::is_directory(path)) - { - try - { - for (auto& e : std::filesystem::directory_iterator(path)) - { - auto p = e.path(); - if (is_shared_library(p) && p.replace_extension().extension() == ".robo_tracker") - { - filesFromFolders.push_back(p.string()); - } - } - } - catch (std::filesystem::filesystem_error const& e) - { - qWarning() << e.what(); - } - } - else if (is_shared_library(path)) - { - filesFromFolders.push_back(f); - } - else - { - qWarning() << "Neither a directory, nor a shared library:" << f.data(); - } - } - - return filesFromFolders; + for (auto f: list) + { + auto path = std::filesystem::path(f); + if (path.empty()) + { + continue; + } + if (std::filesystem::is_directory(path)) + { + try + { + for (auto& e : std::filesystem::directory_iterator(path)) + { + auto p = e.path(); + if (is_shared_library(p) && p.replace_extension().extension() == ".robo_tracker") + { + filesFromFolders.push_back(p.string()); + } + } + } + catch (std::filesystem::filesystem_error const& e) + { + qWarning() << e.what(); + } + } + else if (is_shared_library(path)) + { + filesFromFolders.push_back(f); + } + else + { + qWarning() << "Neither a directory, nor a shared library:" << f.data(); + } + } + + return filesFromFolders; } PluginLoader::PluginLoader(QObject *parent) { - m_MetaData = nullptr; - m_PluginLoader = new QPluginLoader(this); - m_PluginListModel = new QStringListModel(); + m_MetaData = nullptr; + m_PluginLoader = new QPluginLoader(this); + m_PluginListModel = new QStringListModel(); } PluginLoader::~PluginLoader() { - delete m_PluginLoader; - delete m_PluginListModel; + delete m_PluginLoader; + delete m_PluginListModel; } bool PluginLoader::loadPluginFromFilename(QString const& filename) { - bool retval = false; - if (m_PluginLoader->isLoaded()) { - m_PluginLoader->unload(); - } + bool retval = false; + if (m_PluginLoader->isLoaded()) { + m_PluginLoader->unload(); + } - bool isLib = QLibrary::isLibrary(filename); + bool isLib = QLibrary::isLibrary(filename); - if (isLib) { - - auto oldPath = PluginLoader::addDllPath(filename.toStdString()); - m_PluginLoader->setFileName(filename); + if (isLib) { + + auto oldPath = PluginLoader::addDllPath(filename.toStdString()); + m_PluginLoader->setFileName(filename); - readMetaDataFromPlugin(); + readMetaDataFromPlugin(); - retval = m_PluginLoader->load(); - QString s = m_PluginLoader->errorString(); - std::string ss = s.toStdString(); - addPluginnameToLists(getCurrentPluginName(), filename); + retval = m_PluginLoader->load(); + QString s = m_PluginLoader->errorString(); + std::string ss = s.toStdString(); + addPluginnameToLists(getCurrentPluginName(), filename); if (!m_PluginLoader->isLoaded()) - { - qWarning() << ss.c_str(); - retval = false; - } - PluginLoader::delDllPath(oldPath); - } - else { - retval = false; - } - - return retval; + { + qWarning() << ss.c_str(); + retval = false; + } + PluginLoader::delDllPath(oldPath); + } + else { + retval = false; + } + + return retval; } void PluginLoader::addPluginnameToLists(QString mstring, QString filename) -{ - if (!m_PluginList.contains(mstring)) - m_PluginList.append(mstring); - m_PluginListModel->setStringList(m_PluginList); - m_PluginMap.insert(std::pair<QString, QString>(mstring, filename)); +{ + if (!m_PluginList.contains(mstring)) + m_PluginList.append(mstring); + m_PluginListModel->setStringList(m_PluginList); + m_PluginMap.insert(std::pair<QString, QString>(mstring, filename)); } bool PluginLoader::loadPluginFromName(QString name) { - QString filename = m_PluginMap.find(name)->second; - return loadPluginFromFilename(filename); + QString filename = m_PluginMap.find(name)->second; + return loadPluginFromFilename(filename); } int PluginLoader::addToPluginList(QString filename, QString suffix) { - if (!validSuffix(filename.toStdString(), suffix.toStdString())) - return 1; - - bool isLib = QLibrary::isLibrary(filename); - - if (isLib) { - - QPluginLoader loader; - loader.setFileName(filename); - QJsonValue pluginMeda(loader.metaData().value("MetaData")); - QJsonObject metaObj = pluginMeda.toObject(); - QString mstring = metaObj.value("name").toString(); - addPluginnameToLists(mstring, filename); - } - else { - return 2; - qWarning() << "Error reading plugin: " << filename; - } - return 0; + if (!validSuffix(filename.toStdString(), suffix.toStdString())) + return 1; + + bool isLib = QLibrary::isLibrary(filename); + + if (isLib) { + + QPluginLoader loader; + loader.setFileName(filename); + QJsonValue pluginMeda(loader.metaData().value("MetaData")); + QJsonObject metaObj = pluginMeda.toObject(); + QString mstring = metaObj.value("name").toString(); + addPluginnameToLists(mstring, filename); + } + else { + return 2; + qWarning() << "Error reading plugin: " << filename; + } + return 0; } QStringListModel* PluginLoader::getPluginList() { - return m_PluginListModel; + return m_PluginListModel; } QObject* PluginLoader::getPluginInstance() { - return (m_PluginLoader->instance()); + return (m_PluginLoader->instance()); } QJsonObject PluginLoader::getPluginMetaData() const { - if (m_MetaData == nullptr) - qFatal("(getPluginMetaData) No plugin loaded"); - return *m_MetaData; + if (m_MetaData == nullptr) + qFatal("(getPluginMetaData) No plugin loaded"); + return *m_MetaData; } void PluginLoader::readMetaDataFromPlugin() { - m_MetaData = std::make_shared<QJsonObject>(m_PluginLoader->metaData().value("MetaData").toObject()); + m_MetaData = std::make_shared<QJsonObject>(m_PluginLoader->metaData().value("MetaData").toObject()); } bool PluginLoader::getIsPluginLoaded() { - return m_isPluginLoaded; + return m_isPluginLoaded; } QString PluginLoader::getCurrentPluginName() { - if (m_MetaData == nullptr) - return "Error name"; - return m_MetaData->value("name").toString(); + if (m_MetaData == nullptr) + return "Error name"; + return m_MetaData->value("name").toString(); } const std::map<QString, QString> &PluginLoader::getPluginMap() const { diff --git a/SrcBehaviorLoader/PluginLoader.h b/SrcBehaviorLoader/PluginLoader.h index 221a8b657aea813bbb2ae7c30200b965209712cc..2a41531ed6d56d2894724a6b9415955f1bad2238 100644 --- a/SrcBehaviorLoader/PluginLoader.h +++ b/SrcBehaviorLoader/PluginLoader.h @@ -16,90 +16,90 @@ class PluginLoader : QObject { - Q_OBJECT + Q_OBJECT public: - explicit PluginLoader(QObject *parent = 0); - - ~PluginLoader(); - - /** - * Loads a file as a QT plugin and reads it's name from the metadata. - * It will then be added to the stringlist and is selectable via "loadPluginFromName". - * This function does not actually set the plugin instance. - */ - int addToPluginList(QString filename, QString suffix); - - /** - * Returns a QStrinListModel with the names of all seen Plugins. - */ - QStringListModel* getPluginList(); - - /** - * Loads a BioTracker Plugin from a file path. It returns true if the Plugin could be loaded, otherwise false. - * The loaded plugin acts as singleton! - */ - bool loadPluginFromFilename(QString const& filename); - - /** - * Loads a plugin from it's name (given in the metadata) instead of the filename. - * Only works if it is already known to the pluginloader, i.e. was loaded manually or automatically before or - * or has been added to the pluginlist via "addToPluginList" - */ - bool loadPluginFromName(QString name); - - QJsonObject getPluginMetaData() const; - - static std::vector<std::string> queryRegistryBehaviors(std::string path); - - static std::vector<std::string> searchDirectoriesForPlugins(std::vector<std::string> list, std::string suffix); - - //return oldPath - static const char* addDllPath(std::string file); - - static void delDllPath(const char* oldPath); - - // Is a plugin loaded or not? - bool getIsPluginLoaded(); - - // Gets the name of the currently loaded plugin - QString getCurrentPluginName(); - - /** - * Returns the Instance of the BioTracker Plugin. - */ - QObject *getPluginInstance(); - - /** - * Returns a map containing the mapping "plugin name -> filename" - */ - std::map<QString, QString> const& getPluginMap() const; + explicit PluginLoader(QObject *parent = 0); + + ~PluginLoader(); + + /** + * Loads a file as a QT plugin and reads it's name from the metadata. + * It will then be added to the stringlist and is selectable via "loadPluginFromName". + * This function does not actually set the plugin instance. + */ + int addToPluginList(QString filename, QString suffix); + + /** + * Returns a QStrinListModel with the names of all seen Plugins. + */ + QStringListModel* getPluginList(); + + /** + * Loads a BioTracker Plugin from a file path. It returns true if the Plugin could be loaded, otherwise false. + * The loaded plugin acts as singleton! + */ + bool loadPluginFromFilename(QString const& filename); + + /** + * Loads a plugin from it's name (given in the metadata) instead of the filename. + * Only works if it is already known to the pluginloader, i.e. was loaded manually or automatically before or + * or has been added to the pluginlist via "addToPluginList" + */ + bool loadPluginFromName(QString name); + + QJsonObject getPluginMetaData() const; + + static std::vector<std::string> queryRegistryBehaviors(std::string path); + + static std::vector<std::string> searchDirectoriesForPlugins(std::vector<std::string> list, std::string suffix); + + //return oldPath + static const char* addDllPath(std::string file); + + static void delDllPath(const char* oldPath); + + // Is a plugin loaded or not? + bool getIsPluginLoaded(); + + // Gets the name of the currently loaded plugin + QString getCurrentPluginName(); + + /** + * Returns the Instance of the BioTracker Plugin. + */ + QObject *getPluginInstance(); + + /** + * Returns a map containing the mapping "plugin name -> filename" + */ + std::map<QString, QString> const& getPluginMap() const; private: - void addPluginnameToLists(QString name, QString filename); + void addPluginnameToLists(QString name, QString filename); - //a map containing the mapping "plugin name -> filename" - std::map<QString, QString> m_PluginMap; + //a map containing the mapping "plugin name -> filename" + std::map<QString, QString> m_PluginMap; - /** - * Gets the metadata from the currently loaded plugin. - * Currently this is nothing but the advertised name of the plugin - */ - void readMetaDataFromPlugin(); + /** + * Gets the metadata from the currently loaded plugin. + * Currently this is nothing but the advertised name of the plugin + */ + void readMetaDataFromPlugin(); - // The QT object to actually load the plugins - QPluginLoader *m_PluginLoader; + // The QT object to actually load the plugins + QPluginLoader *m_PluginLoader; - std::shared_ptr<QJsonObject> m_MetaData; + std::shared_ptr<QJsonObject> m_MetaData; - //nomen est omen - bool m_isPluginLoaded; + //nomen est omen + bool m_isPluginLoaded; - // List of all available plugins - QStringList m_PluginList; + // List of all available plugins + QStringList m_PluginList; - // Entire ListModel of the metadata (actually containing all metadata, not only name) - QStringListModel* m_PluginListModel; + // Entire ListModel of the metadata (actually containing all metadata, not only name) + QStringListModel* m_PluginListModel; }; #endif // PLUGINLOADER_H