diff options
Diffstat (limited to 'plugins/PluginLoader/catchcopy-v0002/pluginLoader.cpp')
-rw-r--r-- | plugins/PluginLoader/catchcopy-v0002/pluginLoader.cpp | 450 |
1 files changed, 450 insertions, 0 deletions
diff --git a/plugins/PluginLoader/catchcopy-v0002/pluginLoader.cpp b/plugins/PluginLoader/catchcopy-v0002/pluginLoader.cpp new file mode 100644 index 0000000..363f372 --- /dev/null +++ b/plugins/PluginLoader/catchcopy-v0002/pluginLoader.cpp @@ -0,0 +1,450 @@ +/** \file pluginLoader.cpp +\brief Define the session plugin loader test +\author alpha_one_x86 */ + +#include "pluginLoader.h" +#include "PlatformMacro.h" +#include "../../../cpp11addition.h" + +#include <QFile> +#include <QDir> +#ifdef ULTRACOPIER_PLUGIN_ALL_IN_ONE +#include <QCoreApplication> +#endif + +#ifdef ULTRACOPIER_PLUGIN_DEBUG + #define NORMAL_EXT "d.dll" + #define SECOND_EXT ".dll" +#else + #define NORMAL_EXT ".dll" + #define SECOND_EXT "d.dll" +#endif +#define CATCHCOPY_DLL_32 "catchcopy32" +#define CATCHCOPY_DLL_64 "catchcopy64" + +WindowsExplorerLoader::WindowsExplorerLoader() +{ + //set the startup value into the variable + dllChecked=false; + optionsEngine=NULL; + allDllIsImportant=false; + Debug=false; + needBeRegistred=false; + changeOfArchDetected=false; + is64Bits=false; + optionsWidget=new OptionsWidget(); + connect(optionsWidget,&OptionsWidget::sendAllDllIsImportant,this,&WindowsExplorerLoader::setAllDllIsImportant); + connect(optionsWidget,&OptionsWidget::sendDebug,this,&WindowsExplorerLoader::setDebug); + +#if defined(_M_X64)//64Bits + is64Bits=true; +#else//32Bits + char *arch=getenv("windir"); + if(arch!=NULL) + { + QDir dir; + if(dir.exists(QString(arch)+"\\SysWOW64\\")) + is64Bits=true; + /// \note commented because it do a crash at the startup, and useless, because is global variable, it should be removed only by the OS + //delete arch; + } +#endif +} + +WindowsExplorerLoader::~WindowsExplorerLoader() +{ + //delete optionsWidget;//attached to the main program, then it's the main program responsive the delete + setEnabled(false); +} + +void WindowsExplorerLoader::setEnabled(const bool &needBeRegistred) +{ + if(!checkExistsDll()) + { + #ifdef ULTRACOPIER_PLUGIN_ALL_IN_ONE + if(needBeRegistred) + emit newState(Ultracopier::Caught); + else + emit newState(Ultracopier::Uncaught); + #else + emit newState(Ultracopier::Uncaught); + #endif + if(!needBeRegistred) + correctlyLoaded.clear(); + return; + } + if(this->needBeRegistred==needBeRegistred) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,QStringLiteral("Double event dropped: %1").arg(needBeRegistred).toStdString()); + if(needBeRegistred) + emit newState(Ultracopier::Caught); + else + emit newState(Ultracopier::Uncaught); + return; + } + this->needBeRegistred=needBeRegistred; + unsigned int index=0; + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,QStringLiteral("start, needBeRegistred: %1, allDllIsImportant: %2").arg(needBeRegistred).arg(allDllIsImportant).toStdString()); + + bool oneHaveFound=false; + index=0; + while(index<importantDll.size()) + { + if(QFile::exists(QString::fromStdString(pluginPath+importantDll.at(index)))) + { + oneHaveFound=true; + break; + } + index++; + } + if(!oneHaveFound) + { + index=0; + while(index<secondDll.size()) + { + if(QFile::exists(QString::fromStdString(pluginPath+secondDll.at(index)))) + { + oneHaveFound=true; + break; + } + index++; + } + } + if(!oneHaveFound) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"No dll have found"); + emit newState(Ultracopier::Uncaught); + if(!needBeRegistred) + correctlyLoaded.clear(); + return; + } + + index=0; + bool importantDll_is_loaded=false,secondDll_is_loaded=false; + bool importantDll_have_bug=false,secondDll_have_bug=false; + int importantDll_count=0,secondDll_count=0; + while(index<importantDll.size()) + { + if(!RegisterShellExtDll(pluginPath+importantDll.at(index),needBeRegistred, + !( + (needBeRegistred) + || + (!needBeRegistred && correctlyLoaded.find(importantDll.at(index))!=correctlyLoaded.cend()) + ) + )) + { + if(changeOfArchDetected) + { + setEnabled(needBeRegistred); + return; + } + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"the important dll have failed: "+importantDll.at(index)); + importantDll_have_bug=true; + } + else + { + importantDll_is_loaded=true; + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"the important dll have been loaded: "+importantDll.at(index)); + } + importantDll_count++; + index++; + } + index=0; + while(index<secondDll.size()) + { + if(!RegisterShellExtDll(pluginPath+secondDll.at(index),needBeRegistred, + !( + (needBeRegistred && allDllIsImportant) + || + (!needBeRegistred && correctlyLoaded.find(secondDll.at(index))!=correctlyLoaded.cend()) + ) + )) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"the second dll have failed: "+secondDll.at(index)); + secondDll_have_bug=true; + } + else + { + secondDll_is_loaded=true; + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"the second dll have been loaded: "+secondDll.at(index)); + } + secondDll_count++; + index++; + } + + Ultracopier::CatchState importantDll_state,secondDll_state; + if(importantDll_count==0) + { + if(needBeRegistred) + importantDll_state=Ultracopier::Caught; + else + importantDll_state=Ultracopier::Uncaught; + } + else + { + if(importantDll_is_loaded) + { + if(!importantDll_have_bug) + importantDll_state=Ultracopier::Caught; + else + importantDll_state=Ultracopier::Semiuncaught; + } + else + importantDll_state=Ultracopier::Uncaught; + } + if(secondDll_count==0) + if(needBeRegistred) + secondDll_state=Ultracopier::Caught; + else + secondDll_state=Ultracopier::Uncaught; + else + { + if(secondDll_is_loaded) + { + if(!secondDll_have_bug) + secondDll_state=Ultracopier::Caught; + else + secondDll_state=Ultracopier::Semiuncaught; + } + else + secondDll_state=Ultracopier::Uncaught; + } + + if((importantDll_state==Ultracopier::Uncaught && secondDll_state==Ultracopier::Uncaught) || !needBeRegistred || (importantDll_count==0 && secondDll_count==0)) + emit newState(Ultracopier::Uncaught); + else if(importantDll_state==Ultracopier::Caught) + emit newState(Ultracopier::Caught); + else + emit newState(Ultracopier::Semiuncaught); + + if(!needBeRegistred) + correctlyLoaded.clear(); +} + +bool WindowsExplorerLoader::checkExistsDll() +{ + if(dllChecked) + { + if(importantDll.size()>0 || secondDll.size()>0) + return true; + else + return false; + } + dllChecked=true; + + if(is64Bits) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Information,"64Bits is important"); + importantDll.push_back(CATCHCOPY_DLL_64); + secondDll.push_back(CATCHCOPY_DLL_32); + } + else + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Information,"32Bits is important"); + importantDll.push_back(CATCHCOPY_DLL_32); + secondDll.push_back(CATCHCOPY_DLL_64); + } + + unsigned int index=0; + while(index<importantDll.size()) + { + if(!QFile::exists(QString::fromStdString(pluginPath+importantDll.at(index)+NORMAL_EXT))) + { + if(!QFile::exists(QString::fromStdString(pluginPath+importantDll.at(index)+SECOND_EXT))) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"file not found, drop to the list: "+ + pluginPath+importantDll.at(index)+NORMAL_EXT+ + " and "+ + pluginPath+importantDll.at(index)+SECOND_EXT + ); + importantDll.erase(importantDll.cbegin()+index); + index--; + } + else + importantDll[index]+=SECOND_EXT; + } + else + importantDll[index]+=NORMAL_EXT; + index++; + } + index=0; + while(index<secondDll.size()) + { + if(!QFile::exists(QString::fromStdString(pluginPath+secondDll.at(index)+NORMAL_EXT))) + { + if(!QFile::exists(QString::fromStdString(pluginPath+secondDll.at(index)+SECOND_EXT))) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning, + "file not found, drop to the list: "+pluginPath+secondDll.at(index)+NORMAL_EXT+ + " and "+pluginPath+secondDll.at(index)+SECOND_EXT + ); + secondDll.erase(secondDll.cbegin()+index); + index--; + } + else + secondDll[index]+=SECOND_EXT; + } + else + secondDll[index]+=NORMAL_EXT; + index++; + } + if(importantDll.size()>0 || secondDll.size()>0) + return true; + else + return false; +} + +void WindowsExplorerLoader::setResources(OptionInterface * options, const std::string &writePath, const std::string &pluginPath, const bool &portableVersion) +{ + Q_UNUSED(options); + Q_UNUSED(writePath); + Q_UNUSED(pluginPath); + Q_UNUSED(portableVersion); + #ifdef ULTRACOPIER_PLUGIN_ALL_IN_ONE + this->pluginPath=QCoreApplication::applicationDirPath().toStdString()+"/"; + #else + this->pluginPath=pluginPath; + #endif + this->optionsEngine=options; + if(optionsEngine!=NULL) + { + std::vector<std::pair<std::string, std::string> > KeysList; + KeysList.push_back(std::pair<std::string, std::string>("allDllIsImportant","false")); + KeysList.push_back(std::pair<std::string, std::string>("Debug","false")); + optionsEngine->addOptionGroup(KeysList); + allDllIsImportant=stringtobool(optionsEngine->getOptionValue("allDllIsImportant")); + Debug=stringtobool(optionsEngine->getOptionValue("Debug")); + optionsWidget->setAllDllIsImportant(allDllIsImportant); + optionsWidget->setDebug(Debug); + } +} + +bool WindowsExplorerLoader::RegisterShellExtDll(const std::string &dllPath, const bool &bRegister, const bool &quiet) +{ + if(Debug) + { + std::string message; + if(bRegister) + message+="Try load the dll: %1, and "+dllPath; + else + message+="Try unload the dll: %1, and "+dllPath; + if(quiet) + message+="don't open the UAC"; + else + message+="open the UAC if needed"; + QMessageBox::information(NULL,"Debug",QString::fromStdString(message)); + } + if(bRegister && correctlyLoaded.find(dllPath)!=correctlyLoaded.cend()) + { + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"Try dual load: "+dllPath); + return false; + } + ////////////////////////////// First way to load ////////////////////////////// + QStringList arguments; + if(!Debug) + arguments.append("/s"); + if(!bRegister) + arguments.append("/u"); + arguments.append(QString::fromStdString(dllPath)); + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"start: regsvr32 "+arguments.join(" ").toStdString()); + int result; + #ifdef Q_OS_WIN32 + QProcess process; + process.start("regsvr32",arguments); + if(!process.waitForStarted()) + result=985; + else if(!process.waitForFinished()) + result=984; + else + { + result=process.exitCode(); + QString out=QString::fromLocal8Bit(process.readAllStandardOutput()); + QString outError=QString::fromLocal8Bit(process.readAllStandardError()); + if(!out.isEmpty()) + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"regsvr32 output: "+out.toStdString()); + if(!outError.isEmpty()) + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"regsvr32 error output: "+outError.toStdString()); + } + #else + result=0; + #endif + bool ok=false; + if(result==0) + { + if(bRegister) + correctlyLoaded.insert(dllPath); + ok=true; + } + #if ! defined(_M_X64) + if(result==999 && !changeOfArchDetected)//code of wrong arch for the dll + { + changeOfArchDetected=true; + std::vector<std::string> temp; + temp = importantDll; + secondDll = importantDll; + importantDll = temp; + return false; + } + #endif + if(result==5) + { + if(!quiet || (!bRegister && correctlyLoaded.find(dllPath)!=correctlyLoaded.cend())) + { + arguments.last()=QStringLiteral("\"%1\"").arg(arguments.last()); + ////////////////////////////// Last way to load ////////////////////////////// + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"try it in win32"); + // try with regsvr32, win32 because for admin dialog + + #ifdef Q_OS_WIN32 + wchar_t arrayArg[65535]; + int size_lenght=arguments.join(" ").toWCharArray(arrayArg); + //size_lenght*sizeof(wchar_t) + wcscpy(arrayArg+size_lenght*sizeof(wchar_t),TEXT("\0")); + SHELLEXECUTEINFO sei; + memset(&sei, 0, sizeof(sei)); + sei.cbSize = sizeof(sei); + sei.fMask = SEE_MASK_UNICODE; + sei.lpVerb = TEXT("runas"); + sei.lpFile = TEXT("regsvr32.exe"); + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"in win32 mode: arrayArg: "+QString::fromWCharArray(arrayArg,size_lenght).toStdString()); + sei.lpParameters = arrayArg; + sei.nShow = SW_SHOW; + ok=ShellExecuteEx(&sei); + #else + ok=true; + #endif + if(ok && bRegister) + correctlyLoaded.insert(dllPath); + } + else + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"not try because need be quiet: "+dllPath); + } + else + ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"regsvr32 terminated with: "+std::to_string(result)); + if(!bRegister) + correctlyLoaded.erase(dllPath); + return ok; +} + +/// \brief to get the options widget, NULL if not have +QWidget * WindowsExplorerLoader::options() +{ + return optionsWidget; +} + +void WindowsExplorerLoader::newLanguageLoaded() +{ + optionsWidget->retranslate(); +} + +void WindowsExplorerLoader::setAllDllIsImportant(bool allDllIsImportant) +{ + this->allDllIsImportant=allDllIsImportant; + optionsEngine->setOptionValue("allDllIsImportant",std::to_string(allDllIsImportant)); +} + +void WindowsExplorerLoader::setDebug(bool Debug) +{ + this->Debug=Debug; + optionsEngine->setOptionValue("Debug",std::to_string(Debug)); +} |