From 717bfa09d20c1a692dbb65bffe29c94eea2d4fba Mon Sep 17 00:00:00 2001 From: Hauke Moenck <hauke_moenck@gmx.de> Date: Thu, 25 Oct 2018 10:21:00 +0200 Subject: [PATCH] Removed factory method. Fixed packaging --- .gitlab-ci.yml | 19 +-- SrcBehaviorLoader/PluginLoader.cpp | 208 +++++++++++++++++++++++++++-- SrcBehaviorLoader/PluginLoader.h | 14 +- 3 files changed, 215 insertions(+), 26 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3240c0d..2f49aae 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -57,18 +57,19 @@ build windows: - cmake -Bbuild "-H." -DCMAKE_BUILD_TYPE=Release -G Ninja -DCMAKE_PREFIX_PATH="$Env:VCPKG_INSTALL_DIR" - ninja -C build -build windows[cuda]: - <<: *build_windows - script: - - cmake -Bbuild "-H." -DCMAKE_BUILD_TYPE=Release -G Ninja -DCMAKE_PREFIX_PATH="$Env:VCPKG_CUDA_INSTALL_DIR" - - ninja -C build - .package: &package stage: package artifacts: paths: - build/*.tar.xz expire_in: 1 week + before_script: + - 'curl.exe -o artifacts.zip --header "JOB-TOKEN: $CI_JOB_TOKEN" "https://git.imp.fu-berlin.de/api/v4/projects/2576/jobs/artifacts/master/download?job=package%20windows%5bcuda%5d"' + - 7z e artifacts.zip; 7z e *.tar.xz; Remove-Item -Force *.tar.xz; 7z x *.tar; Remove-Item -Force *.tar + - New-Item -ItemType Directory -Force 'dependencies' + - $name='RF_Interfaces'; Move-Item -Force "$name-*" dependencies/$name + - $env:CMAKE_PREFIX_PATH="$((Get-Item -Path '.').FullName)/dependencies;$env:VCPKG_CUDA_INSTALL_DIR" + - C:/VsDevEnv.ps1 -arch=amd64 script: - ninja -C build package @@ -84,12 +85,6 @@ package windows: - build windows <<: *package -package windows[cuda]: - <<: *base_windows - dependencies: - - build windows[cuda] - <<: *package - trigger dependents: stage: deploy <<: *base_ubuntu_18_04 diff --git a/SrcBehaviorLoader/PluginLoader.cpp b/SrcBehaviorLoader/PluginLoader.cpp index ca4aa39..6f0c3cd 100644 --- a/SrcBehaviorLoader/PluginLoader.cpp +++ b/SrcBehaviorLoader/PluginLoader.cpp @@ -1,13 +1,209 @@ #include "PluginLoader.h" +#include <QDebug> +#include <vector> +#include <filesystem> + +#ifdef _WIN32 +#include <stdio.h> +#include <tchar.h> +#include <string.h> +#include <atlbase.h> #include <QDebug> +#include <QFileInfo> +#define MAX_KEY_LENGTH 255 +#define MAX_VALUE_NAME 16383 + +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; + TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name + DWORD cchClassName = MAX_PATH; // size of class string + DWORD cSubKeys=0; // number of subkeys + DWORD cbMaxSubKey; // longest subkey size + DWORD cchMaxClass; // longest class string + DWORD cValues; // number of values for key + DWORD cchMaxValue; // longest value name + DWORD cbMaxValueData; // longest value data + DWORD cbSecurityDescriptor; // size of security descriptor + FILETIME ftLastWriteTime; // last write time + + DWORD i, retCode; + + TCHAR achValue[MAX_VALUE_NAME]; + DWORD cchValue = MAX_VALUE_NAME; + + // Get the class name and the value count. + retCode = RegQueryInfoKey( + hKey, // key handle + achClass, // buffer for class name + &cchClassName, // size of class string + NULL, // reserved + &cSubKeys, // number of subkeys + &cbMaxSubKey, // longest subkey size + &cchMaxClass, // longest class string + &cValues, // number of values for this key + &cchMaxValue, // longest value name + &cbMaxValueData, // longest value data + &cbSecurityDescriptor, // security descriptor + &ftLastWriteTime); // last write time + + // Enumerate the key values. + if (cValues) + { + //printf( "\nNumber of values: %d\n", cValues); + + for (i=0, retCode=ERROR_SUCCESS; i<cValues; i++) + { + cchValue = MAX_VALUE_NAME; + achValue[0] = '\0'; + retCode = RegEnumValue(hKey, i, + achValue, + &cchValue, + NULL, + NULL, + NULL, + NULL); + + 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); + } + } + } + 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; +} + +#ifdef _WIN32 +const char * WinGetEnv(const char * name) +{ + const DWORD buffSize = 65535; + static char buffer[buffSize]; + if (GetEnvironmentVariableA(name, buffer, buffSize)) + { + return buffer; + } + else + { + return 0; + } +} +bool WinSetEnv(const char* name, const char* toWhat){ + return SetEnvironmentVariableA(name, toWhat); +} +#endif + +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 ""; +} + +void PluginLoader::delDllPath(const char* oldPath){ + //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); + if (ending.size() > value.size()) return false; + return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); +} + +std::vector<std::string> PluginLoader::searchDirectoriesForPlugins(std::vector<std::string> list){ + //Search directories + std::vector<std::string> filesFromFolders; + + for (auto f: list) { + std::string file = f; + try { + if (!file.empty() && file[file.size() - 1] == '/') { + for (auto& p : std::filesystem::directory_iterator(file)) { + std::string s = p.path().string(); + if(endsWith(s,".robo_tracker.dll") || endsWith(s,".robo_tracker.so")) + filesFromFolders.push_back(s); + } + } + else { + if(endsWith(f,".robo_tracker.dll") || endsWith(f,".robo_tracker.so")) + filesFromFolders.push_back(f); + } + } + catch (...){ + qWarning() << "Could not read file/directory: " << file.c_str(); + } + } + + return filesFromFolders; +} PluginLoader::PluginLoader(QObject *parent) { m_PluginLoader = new QPluginLoader(this); } -/*---------------------------------------*/ bool PluginLoader::loadPluginFromFilename(QString const& filename) { bool retval = false; @@ -28,7 +224,7 @@ bool PluginLoader::loadPluginFromFilename(QString const& filename) QString s = m_PluginLoader->errorString(); std::string ss = s.toStdString(); - if (!m_PluginLoader->isLoaded()) + if (!m_PluginLoader->isLoaded()) { qWarning() << ss.c_str(); } @@ -40,19 +236,11 @@ bool PluginLoader::loadPluginFromFilename(QString const& filename) return retval; } -/*---------------------------------------*/ -IBehaviourFactory* PluginLoader::getPluginInstance() -{ - return qobject_cast<IBehaviourFactory*>(m_PluginLoader->instance()); -} - -/*---------------------------------------*/ QJsonObject PluginLoader::getPluginMetaData() const { return m_MetaData; } -/*---------------------------------------*/ void PluginLoader::readMetaDataFromPlugin() { m_MetaData = m_PluginLoader->metaData().value("MetaData").toObject(); diff --git a/SrcBehaviorLoader/PluginLoader.h b/SrcBehaviorLoader/PluginLoader.h index 8f23006..439e62e 100644 --- a/SrcBehaviorLoader/PluginLoader.h +++ b/SrcBehaviorLoader/PluginLoader.h @@ -1,20 +1,26 @@ + #ifndef PLUGINLOADER_H #define PLUGINLOADER_H #include "QPluginLoader" #include "QStringListModel" -#include "IBehaviourFactory.h" #include "QPointer" class PluginLoader : QObject -{ +{ Q_OBJECT public: explicit PluginLoader(QObject *parent = 0); bool loadPluginFromFilename(QString const& filename); - IBehaviourFactory *getPluginInstance(); QJsonObject getPluginMetaData() const; + + static std::vector<std::string> queryRegistryBehaviors(std::string path); + static std::vector<std::string> searchDirectoriesForPlugins(std::vector<std::string> list); + + //return oldPath + static const char* addDllPath(std::string file); + static void delDllPath(const char* oldPath); private: void readMetaDataFromPlugin(); @@ -23,4 +29,4 @@ private: QJsonObject m_MetaData; }; -#endif // PLUGINLOADER_H +#endif // PLUGINLOADER_H \ No newline at end of file -- GitLab