/** \file pluginLoader.cpp \brief Define the session plugin loader test \author alpha_one_x86 */ #include "pluginLoader.h" #include "PlatformMacro.h" #include "../../../cpp11addition.h" #include #include #ifdef ULTRACOPIER_PLUGIN_ALL_IN_ONE #include #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(index0 || 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(index0 || 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 > KeysList; KeysList.push_back(std::pair("allDllIsImportant","false")); KeysList.push_back(std::pair("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 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)); }