This reverts commit 975f049797bcd6b9de0e11f9a926d5ac3ec79ef8.

1

1

Revert "Update QtLoader_inline.cpp"

This reverts commit 372dd2dc3e2f23c810f13e51437904fac1422c04.

Update QtLoader_inline.cpp

Update QtLoader_inline.cpp

1

1

1

Update CMakeLists.txt

1

1
This commit is contained in:
恍兮惚兮 2024-03-30 00:40:49 +08:00
parent b0fcc4cd72
commit c94547bbc9
11 changed files with 349 additions and 163 deletions

View File

@ -68,8 +68,7 @@
#define MenuPluginRankDown L"Down"
#define MenuPluginEnable L"Enable"
#define DefaultFont L"Arial"
#define LblPluginNotify L"Qt Plugins Will be Loaded at Start Only."
#define LblPluginRemove L"Remove Plugins Will be Useful after Restart."
#define CantLoadQtLoader L"Can't Load QtLoader.dll"
#define InvalidPlugin L"Invalid Plugin!"
#define InvalidDll L"Invalid Dll!"
#define InvalidDump L"Dumplicated!"

View File

@ -68,8 +68,7 @@
#define MenuPluginRankDown L"下移"
#define MenuPluginEnable L"使用"
#define DefaultFont L"微软雅黑"
#define LblPluginNotify L"依赖于Qt的插件仅会在启动时载入。"
#define LblPluginRemove L"移除插件要在重启后生效。"
#define CantLoadQtLoader L"无法加载QtLoader.dll"
#define InvalidPlugin L"插件无效!"
#define InvalidDll L"Dll无效"
#define InvalidDump L"重复!"

View File

@ -1,4 +1,4 @@
add_executable(LunaHost WIN32 confighelper.cpp controls.cpp main.cpp processlistwindow.cpp LunaHost.cpp window.cpp luna.rc pluginmanager.cpp Plugin/pluginexample.cpp QtLoader.cpp app.manifest)
add_executable(LunaHost WIN32 confighelper.cpp controls.cpp main.cpp processlistwindow.cpp LunaHost.cpp window.cpp luna.rc pluginmanager.cpp Plugin/pluginexample.cpp QtLoader_inline.cpp app.manifest)
target_precompile_headers(LunaHost REUSE_FROM pch)
set_target_properties(LunaHost PROPERTIES OUTPUT_NAME "LunaHost${bitappendix}")
target_link_libraries(LunaHost comctl32 pch host ${YY_Thunks_for_WinXP})

View File

@ -394,7 +394,7 @@ Settingwindow::Settingwindow(LunaHost* host):mainwindow(host){
settext(WndSetting);
}
void Pluginwindow::on_size(int w,int h){
listplugins->setgeo(10,80,w-20,h-90);
listplugins->setgeo(10,10,w-20,h-20);
}
void Pluginwindow::pluginrankmove(int moveoffset){
auto idx=listplugins->currentidx();
@ -412,8 +412,7 @@ void Pluginwindow::pluginrankmove(int moveoffset){
listplugins->setdata(b,(LONG_PTR)pa);
}
Pluginwindow::Pluginwindow(mainwindow*p,Pluginmanager* pl):mainwindow(p),pluginmanager(pl){
(new label(this,LblPluginNotify))->setgeo(10,10,500,30);
(new label(this,LblPluginRemove))->setgeo( 10,40,500,30);
static auto listadd=[&](const std::wstring& s){
auto idx=listplugins->additem(std::filesystem::path(s).stem());
auto _s=new wchar_t[s.size()+1];wcscpy(_s,s.c_str());
@ -443,7 +442,7 @@ Pluginwindow::Pluginwindow(mainwindow*p,Pluginmanager* pl):mainwindow(p),pluginm
if(idx!=-1)
{
menu.add(MenuRemovePlugin,[&,idx](){
pluginmanager->remove((LPCWSTR)listplugins->getdata(idx));
pluginmanager->remove((LPCWSTR)listplugins->getdata(idx),false);
listplugins->deleteitem(idx);
});
menu.add_sep();
@ -452,6 +451,10 @@ Pluginwindow::Pluginwindow(mainwindow*p,Pluginmanager* pl):mainwindow(p),pluginm
menu.add_sep();
menu.add_checkable(MenuPluginEnable,pluginmanager->getenable(idx),[&,idx](bool check){
pluginmanager->setenable(idx,check);
if(check)
pluginmanager->addplugin((LPCWSTR)listplugins->getdata(idx),true);
else
pluginmanager->remove((LPCWSTR)listplugins->getdata(idx),true);
});
}
return menu;

View File

@ -5,15 +5,15 @@ set_target_properties(ToClipboard PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_L
endif()
if(0)
include(QtUtils.cmake)
msvc_registry_search()
if(Qt5_DIR)
find_qt5(Core Widgets)
#set(CMAKE_AUTOMOC ON)
add_library(QtLoader MODULE QtLoader.cpp)
#qt5_wrap_cpp(MOC_SOURCES QtLoader.h)
#target_sources(QtLoader PRIVATE ${MOC_SOURCES})
target_link_libraries(QtLoader Qt5::Widgets Qt5::Core)
set_target_properties(QtLoader PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugin${bitappendix}")
endif()
include(QtUtils.cmake)
msvc_registry_search()
if(Qt5_DIR)
find_qt5(Core Widgets)
#set(CMAKE_AUTOMOC ON)
add_library(QtLoader MODULE QtLoader.cpp)
#qt5_wrap_cpp(MOC_SOURCES QtLoader.h)
#target_sources(QtLoader PRIVATE ${MOC_SOURCES})
target_link_libraries(QtLoader Qt5::Widgets Qt5::Core)
set_target_properties(QtLoader PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugin${bitappendix}")
endif()
endif()

View File

@ -0,0 +1,72 @@
#include<Windows.h>
#include<QApplication>
#include<QFont>
#include<QDir>
#include<thread>
#include<queue>
#include<mutex>
#include<Shlwapi.h>
#include<filesystem>
#include"../lockedqueue.hpp"
lockedqueue<std::wstring>waitingtask;
lockedqueue<HMODULE>waitingresult;
extern "C" __declspec(dllexport) int QtStartUp(std::vector<std::wstring>* dlls){
static bool once=false;
if(once)return 0;
once=true;
std::thread([=](){
for(int i=0;i<dlls->size();i++)
QApplication::addLibraryPath(QString::fromStdWString(std::filesystem::path(dlls->at(i)).parent_path()));
int _=0;
QApplication app(_, nullptr);
app.setFont(QFont("MS Shell Dlg 2", 10));
while(true)
{
if(!waitingtask.empty())
{
auto top=waitingtask.pop();
waitingresult.push(LoadLibraryW(top.c_str()));
}
app.processEvents(0);
}
}).detach();
return 0;
}
std::mutex loadmutex;
extern "C" __declspec(dllexport) std::vector<HMODULE>* QtLoadLibraryBatch(std::vector<std::wstring>* dlls){
std::lock_guard _(loadmutex);
static auto once=QtStartUp(dlls);
auto hdlls=new std::vector<HMODULE>;
for(int i=0;i<dlls->size();i++){
waitingtask.push(dlls->at(i));
hdlls->push_back(waitingresult.pop());
}
return hdlls;
}
#if 0
extern "C" __declspec(dllexport) std::vector<HMODULE>* QtLoadLibrary(std::vector<std::wstring>* dlls){
auto hdlls=new std::vector<HMODULE>;
auto mutex=CreateSemaphoreW(0,0,1,0);
std::thread([=](){
for(int i=0;i<dlls->size();i++)
QApplication::addLibraryPath(QString::fromStdWString(std::filesystem::path(dlls->at(i)).parent_path()));
int _=0;
QApplication app(_, nullptr);
app.setFont(QFont("MS Shell Dlg 2", 10));
for(int i=0;i<dlls->size();i++)
hdlls->push_back(LoadLibraryW(dlls->at(i).c_str()));
ReleaseSemaphore(mutex,1,0);
app.exec();
}).detach();
WaitForSingleObject(mutex,INFINITE);
return hdlls;
}
#endif

View File

@ -1,89 +0,0 @@
#include<Windows.h>
#include<thread>
#include<mutex>
#include<Shlwapi.h>
#include<filesystem>
#ifndef _WIN64
#define THISCALL __thiscall
#define _CDECL __cdecl
#define fnQString_fromStdWString "?fromStdWString@QString@@SA?AV1@ABV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@Z"
#define fnQCoreApplication_addLibraryPath "?addLibraryPath@QCoreApplication@@SAXABVQString@@@Z"
#define fnQString_dtor "??1QString@@QAE@XZ"
#define fnQApplication_ctor "??0QApplication@@QAE@AAHPAPADH@Z"
#define fnQFont_ctor "??0QFont@@QAE@ABVQString@@HH_N@Z"
#define fnQApplication_setFont "?setFont@QApplication@@SAXABVQFont@@PBD@Z"
#define fnQFont_dtor "??1QFont@@QAE@XZ"
#define fnQApplication_exec "?exec@QApplication@@SAHXZ"
#define fnQApplication_dtor "??1QApplication@@UAE@XZ"
#else
#define THISCALL __fastcall
#define _CDECL __fastcall
#define fnQString_fromStdWString "?fromStdWString@QString@@SA?AV1@AEBV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@Z"
#define fnQCoreApplication_addLibraryPath "?addLibraryPath@QCoreApplication@@SAXAEBVQString@@@Z"
#define fnQString_dtor "??1QString@@QEAA@XZ"
#define fnQApplication_ctor "??0QApplication@@QEAA@AEAHPEAPEADH@Z"
#define fnQFont_ctor "??0QFont@@QEAA@AEBVQString@@HH_N@Z"
#define fnQApplication_setFont "?setFont@QApplication@@SAXAEBVQFont@@PEBD@Z"
#define fnQFont_dtor "??1QFont@@QEAA@XZ"
#define fnQApplication_exec "?exec@QApplication@@SAHXZ"
#define fnQApplication_dtor "??1QApplication@@UEAA@XZ"
#endif
extern "C" __declspec(dllexport) std::vector<HMODULE>* QtLoadLibrary(std::vector<std::wstring>* dlls){
auto Qt5Widgets=LoadLibrary(L"Qt5Widgets.dll");
auto Qt5Gui=LoadLibrary(L"Qt5Gui.dll");
auto Qt5Core=LoadLibrary(L"Qt5Core.dll");
if(Qt5Core==0||Qt5Gui==0||Qt5Widgets==0)return new std::vector<HMODULE>{};
auto QString_fromStdWString=GetProcAddress(Qt5Core,fnQString_fromStdWString);
auto QCoreApplication_addLibraryPath=GetProcAddress(Qt5Core,fnQCoreApplication_addLibraryPath);
auto QString_dtor=GetProcAddress(Qt5Core,fnQString_dtor);
auto QApplication_ctor=GetProcAddress(Qt5Widgets,fnQApplication_ctor);
auto QFont_ctor=GetProcAddress(Qt5Gui,fnQFont_ctor);
auto QFont_dtor=GetProcAddress(Qt5Gui,fnQFont_dtor);
auto QApplication_setFont=GetProcAddress(Qt5Widgets,fnQApplication_setFont);
auto QApplication_exec=GetProcAddress(Qt5Widgets,fnQApplication_exec);
auto QApplication_dtor=GetProcAddress(Qt5Widgets,fnQApplication_dtor);
if(QString_fromStdWString==0||QCoreApplication_addLibraryPath==0||QString_dtor==0||QApplication_ctor==0||QFont_ctor==0||QFont_dtor==0||QApplication_setFont==0||QApplication_exec==0||QApplication_dtor==0)return {};
auto hdlls=new std::vector<HMODULE>;
auto mutex=CreateSemaphoreW(0,0,1,0);
std::thread([=](){
static void* qapp; //必须static
void* qstring;
void* qfont;
for(int i=0;i<dlls->size();i++){
auto dirname=std::filesystem::path(dlls->at(i)).parent_path().wstring();
((void* (_CDECL*)(void*,void*))QString_fromStdWString)(&qstring,&dirname);
((void(_CDECL *)(void*))QCoreApplication_addLibraryPath)(&qstring);
((void(THISCALL*)(void*))QString_dtor)(&qstring);
//QCoreApplication_addLibraryPath(QString_fromStdWString(std::filesystem::path(collectQtplugs[i]).parent_path()));
}
int _=0;
((void*(THISCALL*)(void*,int*,char**,int))QApplication_ctor)(&qapp,&_,0,331266);
std::wstring font=L"MS Shell Dlg 2";
((void* (_CDECL*)(void*,void*))QString_fromStdWString)(&qstring,&font);
((void*(THISCALL*)(void*,void*,int,int,bool))QFont_ctor)(&qfont,&qstring,10,-1,0);
((void(_CDECL*)(void*,void*))QApplication_setFont)(&qfont,0);
((void(THISCALL*)(void*))QFont_dtor)(&qfont);
((void(THISCALL*)(void*))QString_dtor)(&qstring);
for(int i=0;i<dlls->size();i++){
hdlls->push_back(LoadLibrary(dlls->at(i).c_str()));
}
ReleaseSemaphore(mutex,1,0);
((void(*)())QApplication_exec)();
((void(THISCALL*)(void*))QApplication_dtor)(&qapp);
}).detach();
WaitForSingleObject(mutex,INFINITE);
return hdlls;
}

View File

@ -0,0 +1,141 @@
#include<Windows.h>
#include<thread>
#include<mutex>
#include<Shlwapi.h>
#include<filesystem>
#include<queue>
#include"pluginmanager.h"
#include"lockedqueue.hpp"
#ifndef _WIN64
#define THISCALL __thiscall
#define _CDECL __cdecl
#define fnQString_fromStdWString "?fromStdWString@QString@@SA?AV1@ABV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@Z"
#define fnQCoreApplication_addLibraryPath "?addLibraryPath@QCoreApplication@@SAXABVQString@@@Z"
#define fnQString_dtor "??1QString@@QAE@XZ"
#define fnQApplication_ctor "??0QApplication@@QAE@AAHPAPADH@Z"
#define fnQFont_ctor "??0QFont@@QAE@ABVQString@@HH_N@Z"
#define fnQApplication_setFont "?setFont@QApplication@@SAXABVQFont@@PBD@Z"
#define fnQFont_dtor "??1QFont@@QAE@XZ"
#define fnQApplication_exec "?exec@QApplication@@SAHXZ"
#define fnQApplication_dtor "??1QApplication@@UAE@XZ"
#else
#define THISCALL __fastcall
#define _CDECL __fastcall
#define fnQString_fromStdWString "?fromStdWString@QString@@SA?AV1@AEBV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@Z"
#define fnQCoreApplication_addLibraryPath "?addLibraryPath@QCoreApplication@@SAXAEBVQString@@@Z"
#define fnQString_dtor "??1QString@@QEAA@XZ"
#define fnQApplication_ctor "??0QApplication@@QEAA@AEAHPEAPEADH@Z"
#define fnQFont_ctor "??0QFont@@QEAA@AEBVQString@@HH_N@Z"
#define fnQApplication_setFont "?setFont@QApplication@@SAXAEBVQFont@@PEBD@Z"
#define fnQFont_dtor "??1QFont@@QEAA@XZ"
#define fnQApplication_exec "?exec@QApplication@@SAHXZ"
#define fnQApplication_dtor "??1QApplication@@UEAA@XZ"
#endif
#define fnQApplication_processEvents "?processEvents@QCoreApplication@@SAXV?$QFlags@W4ProcessEventsFlag@QEventLoop@@@@@Z"
FARPROC QString_fromStdWString,QCoreApplication_addLibraryPath,QString_dtor,QApplication_ctor,QFont_ctor,QFont_dtor,QApplication_setFont,QApplication_exec,QApplication_dtor,QApplication_processEvents;
bool checkqterror(){
return QString_fromStdWString==0||QCoreApplication_addLibraryPath==0||QString_dtor==0||QApplication_ctor==0||QFont_ctor==0||QFont_dtor==0||QApplication_setFont==0||QApplication_exec==0||QApplication_dtor==0||QApplication_processEvents==0;
}
int loadqtdlls(){
QString_fromStdWString=QCoreApplication_addLibraryPath=QString_dtor=QApplication_ctor=QFont_ctor=QFont_dtor=QApplication_setFont=QApplication_exec=QApplication_dtor=QApplication_processEvents=0;
auto Qt5Widgets=LoadLibrary(L"Qt5Widgets.dll");
auto Qt5Gui=LoadLibrary(L"Qt5Gui.dll");
auto Qt5Core=LoadLibrary(L"Qt5Core.dll");
if(Qt5Core==0||Qt5Gui==0||Qt5Widgets==0)return 0;
QString_fromStdWString=GetProcAddress(Qt5Core,fnQString_fromStdWString);
QCoreApplication_addLibraryPath=GetProcAddress(Qt5Core,fnQCoreApplication_addLibraryPath);
QString_dtor=GetProcAddress(Qt5Core,fnQString_dtor);
QApplication_ctor=GetProcAddress(Qt5Widgets,fnQApplication_ctor);
QFont_ctor=GetProcAddress(Qt5Gui,fnQFont_ctor);
QFont_dtor=GetProcAddress(Qt5Gui,fnQFont_dtor);
QApplication_setFont=GetProcAddress(Qt5Widgets,fnQApplication_setFont);
QApplication_exec=GetProcAddress(Qt5Widgets,fnQApplication_exec);
QApplication_dtor=GetProcAddress(Qt5Widgets,fnQApplication_dtor);
QApplication_processEvents=GetProcAddress(Qt5Core,fnQApplication_processEvents);
return 0;
}
struct info{
int type;
std::wstring dll;
HMODULE hdll;
};
lockedqueue<info>waitingtask;
lockedqueue<HMODULE>waitingresult;
extern "C" __declspec(dllexport) int QtStartUp(std::vector<std::wstring>* dlls){
static bool once=false;
if(once)return 0;
once=true;
static auto once1=loadqtdlls();
if(checkqterror())return 0;
std::thread([=](){
static void* qapp; //必须static
void* qstring;
void* qfont;
for(int i=0;i<dlls->size();i++){
auto dirname=std::filesystem::path(dlls->at(i)).parent_path().wstring();
((void* (_CDECL*)(void*,void*))QString_fromStdWString)(&qstring,&dirname);
((void(_CDECL *)(void*))QCoreApplication_addLibraryPath)(&qstring);
((void(THISCALL*)(void*))QString_dtor)(&qstring);
//QCoreApplication_addLibraryPath(QString_fromStdWString(std::filesystem::path(collectQtplugs[i]).parent_path()));
}
int _=0;
((void*(THISCALL*)(void*,int*,char**,int))QApplication_ctor)(&qapp,&_,0,331266);
std::wstring font=L"MS Shell Dlg 2";
((void* (_CDECL*)(void*,void*))QString_fromStdWString)(&qstring,&font);
((void*(THISCALL*)(void*,void*,int,int,bool))QFont_ctor)(&qfont,&qstring,10,-1,0);
((void(_CDECL*)(void*,void*))QApplication_setFont)(&qfont,0);
((void(THISCALL*)(void*))QFont_dtor)(&qfont);
((void(THISCALL*)(void*))QString_dtor)(&qstring);
while(true)
{
if(!waitingtask.empty())
{
auto top=waitingtask.pop();
if(top.type==1)
{
waitingresult.push(LoadLibraryW(top.dll.c_str()));
}
else if(top.type==2)
{
FreeLibrary(top.hdll);
}
}
((void(_CDECL*)(DWORD))QApplication_processEvents)(0);
}
// ((void(*)())QApplication_exec)();
// ((void(THISCALL*)(void*))QApplication_dtor)(&qapp);
}).detach();
return 0;
}
std::mutex loadmutex;
extern "C" __declspec(dllexport) std::vector<HMODULE>* QtLoadLibraryBatch(std::vector<std::wstring>* dlls){
std::lock_guard _(loadmutex);
static auto once=QtStartUp(dlls);
auto hdlls=new std::vector<HMODULE>;
for(int i=0;i<dlls->size();i++){
waitingtask.push({1,dlls->at(i)});
hdlls->push_back(waitingresult.pop());
}
return hdlls;
}
extern "C" __declspec(dllexport) void QtFreeLibrary(HMODULE hd){
std::lock_guard _(loadmutex);
waitingtask.push({2,L"",hd});
}

View File

@ -0,0 +1,29 @@
template<class T>
class lockedqueue{
std::mutex lock;
std::queue<T>data;
HANDLE hsema;
public:
lockedqueue(){
hsema=CreateSemaphore(NULL,0,65535,NULL);
}
~lockedqueue(){
CloseHandle(hsema);
}
void push(T _){
std::lock_guard _l(lock);
data.push(std::move(_));
ReleaseSemaphore(hsema,1,NULL);
}
T pop(){
WaitForSingleObject(hsema,INFINITE);
std::lock_guard _l(lock);
auto _=data.front();
data.pop();
return _;
}
bool empty(){
std::lock_guard _l(lock);
return data.empty();
}
};

View File

@ -25,33 +25,51 @@ std::optional<std::wstring>SelectFile(HWND hwnd,LPCWSTR lpstrFilter){
}
else return {};
}
typedef std::vector<HMODULE>*(* QtLoadLibrary_t)(std::vector<std::wstring>* dlls);
void Pluginmanager::loadqtdlls(std::vector<std::wstring>&collectQtplugs){
if(collectQtplugs.size()==0)return;
auto pluginpath=std::filesystem::current_path()/(x64?"plugin64":"plugin32");
wchar_t env[65535];
GetEnvironmentVariableW(L"PATH",env,65535);
auto envs=std::wstring(env);
envs+=L";";envs+=pluginpath;
for(auto&p:collectQtplugs){
envs+=L";";envs+=std::filesystem::path(p).parent_path();
typedef std::vector<HMODULE>* (*QtLoadLibrary_t)(std::vector<std::wstring>* dlls);
typedef std::vector<HMODULE>* (*QtLoadLibraryBatch_t)(std::vector<std::wstring>* dlls);
typedef void (*QtFreeLibrary_t)(HMODULE hd);
void tryaddqttoenv(std::vector<std::wstring>&collectQtplugs){
static HMODULE qt5core=0;
if(qt5core==0)
{
auto pluginpath=std::filesystem::current_path()/(x64?"plugin64":"plugin32");
wchar_t env[65535];
GetEnvironmentVariableW(L"PATH",env,65535);
auto envs=std::wstring(env);
for(auto&p:collectQtplugs){
envs+=L";";envs+=std::filesystem::path(p).parent_path();
}
SetEnvironmentVariableW(L"PATH",envs.c_str());
qt5core= LoadLibrary(L"Qt5Core.dll");
}
SetEnvironmentVariableW(L"PATH",envs.c_str());
auto QtLoadLibrary = (QtLoadLibrary_t)GetProcAddress(GetModuleHandle(0), "QtLoadLibrary");
}
std::vector<HMODULE>loadqtdllsX(std::vector<std::wstring>&collectQtplugs){
if(collectQtplugs.empty())return {};
tryaddqttoenv(collectQtplugs);
#if 1
HMODULE base=GetModuleHandle(0);
#else
HMODULE base=LoadLibrary((std::filesystem::current_path()/(x64?"plugin64":"plugin32")/"QtLoader.dll").wstring().c_str());
#endif
//auto QtLoadLibrary = (QtLoadLibrary_t)GetProcAddress(base, "QtLoadLibrary");
auto QtLoadLibrary = (QtLoadLibrary_t)GetProcAddress(base, "QtLoadLibraryBatch");
auto modules=QtLoadLibrary(&collectQtplugs);
if(modules->empty())return;
for(int i=0;i<collectQtplugs.size();i++){
OnNewSentenceS[collectQtplugs[i]]=GetProcAddress(modules->at(i),"OnNewSentence");
}
std::vector<HMODULE> _{*modules};
delete modules;
return _;
}
HMODULE loadqtdllsX(const std::wstring&collectQtplugs){
std::vector<std::wstring> _ {collectQtplugs};
return loadqtdllsX(_)[0];
}
void Pluginmanager::loadqtdlls(std::vector<std::wstring>&collectQtplugs){
auto modules=loadqtdllsX(collectQtplugs);
for(int i=0;i<collectQtplugs.size();i++){
OnNewSentenceS[collectQtplugs[i]]={true,GetProcAddress(modules[i],"OnNewSentence"),modules[i]};
}
}
Pluginmanager::Pluginmanager(LunaHost* _host):host(_host),configs(_host->configs){
try {
@ -62,17 +80,19 @@ Pluginmanager::Pluginmanager(LunaHost* _host):host(_host),configs(_host->configs
auto plg=get(i);
bool isqt=plg.isQt;
auto path=plg.wpath();
OnNewSentenceS[path]=0;
OnNewSentenceS[path]={false,0,0};
if(isqt){
if(plg.enable==false)continue;
collectQtplugs.push_back((path));
}
else
OnNewSentenceS[path]=GetProcAddress(LoadLibraryW(path.c_str()),"OnNewSentence");
else{
auto base=LoadLibraryW(path.c_str());
OnNewSentenceS[path]={false,GetProcAddress(base,"OnNewSentence"),base};
}
}
loadqtdlls(collectQtplugs);
OnNewSentenceS[L"InternalClipBoard"]=GetProcAddress(GetModuleHandle(0),"OnNewSentence");//内部链接的剪贴板插件
OnNewSentenceS[L"InternalClipBoard"]={false,GetProcAddress(GetModuleHandle(0),"OnNewSentence"),GetModuleHandle(0)};//内部链接的剪贴板插件
} catch (const std::exception& ex) {
@ -94,7 +114,7 @@ bool Pluginmanager::dispatch(TextThread& thread, std::wstring& sentence){
path=getname(i);
}
auto funptr=OnNewSentenceS[path];
auto funptr=OnNewSentenceS[path].funcptr;
if(funptr==0)continue;
if (!*(sentenceBuffer = ((OnNewSentence_t)funptr)(sentenceBuffer, sentenceInfo)))
break;
@ -105,15 +125,6 @@ bool Pluginmanager::dispatch(TextThread& thread, std::wstring& sentence){
return !sentence.empty();
}
void Pluginmanager::remove(const std::string&s){
auto &plgs=configs->configs["plugins"];
auto it=std::remove_if(plgs.begin(),plgs.end(),[&](auto&t){
std::string p=t["path"];
return p==s;
});
plgs.erase(it, plgs.end());
}
void Pluginmanager::add(const pluginitem& item){
configs->configs["plugins"].push_back(item.dump());
}
@ -193,8 +204,23 @@ bool Pluginmanager::checkisdump(const std::wstring& dll){
}
return false;
}
void Pluginmanager::remove(const std::wstring& ss){
remove(WideStringToString(ss));
void Pluginmanager::remove(const std::wstring& wss,bool onlyload){
auto hm=OnNewSentenceS[wss].hmodule;
if(OnNewSentenceS[wss].isQt && hm){
((QtFreeLibrary_t)GetProcAddress(GetModuleHandle(0),"QtFreeLibrary"))(hm);
}
else
FreeLibrary(hm);
OnNewSentenceS[wss].funcptr=OnNewSentenceS[wss].hmodule=0;
if(onlyload)return;
auto s=WideStringToString(wss);
auto &plgs=configs->configs["plugins"];
auto it=std::remove_if(plgs.begin(),plgs.end(),[&](auto&t){
std::string p=t["path"];
return p==s;
});
plgs.erase(it, plgs.end());
}
std::optional<std::wstring>Pluginmanager::selectpluginfile(){
return SelectFile(0,L"Plugin Files\0*.dll;*.xdll\0");
@ -279,26 +305,28 @@ bool qtchecker(const std::set<std::string>& dll)
return true;
return false;
}
addpluginresult Pluginmanager::addplugin(const std::wstring& p){
addpluginresult Pluginmanager::addplugin(const std::wstring& p,bool onlyload){
if(!onlyload)
if(checkisdump(p))return addpluginresult::dumplicate;
auto importtable=getimporttable(p);
if(importtable.empty())return addpluginresult::invaliddll;
auto isQt=qtchecker(importtable);
LPVOID plugin;
HMODULE base;
if(isQt){
plugin=0;
base=loadqtdllsX(p);
}
else{
auto base=LoadLibraryW(p.c_str());
if(base==0)return addpluginresult::invaliddll;
plugin=GetProcAddress(base,"OnNewSentence");
if(!plugin)return addpluginresult::isnotaplugins;
base=LoadLibraryW(p.c_str());
}
if(base==0)return addpluginresult::invaliddll;
auto plugin=GetProcAddress(base,"OnNewSentence");
if(!plugin)return addpluginresult::isnotaplugins;
std::scoped_lock lock(OnNewSentenceSLock);
if(checkisdump(p))return addpluginresult::dumplicate;
OnNewSentenceS[p]=plugin;
add({p,isQt});
OnNewSentenceS[p]={isQt,plugin,base};
if(!onlyload)
add({p,isQt});
return addpluginresult::success;
}

View File

@ -21,8 +21,13 @@ struct pluginitem{
std::wstring wpath();
nlohmann::json dump() const;
};
struct plugindata{
bool isQt;
LPVOID funcptr;
HMODULE hmodule;
};
class Pluginmanager{
std::unordered_map<std::wstring,LPVOID>OnNewSentenceS;
std::unordered_map<std::wstring,plugindata>OnNewSentenceS;
std::optional<LPVOID> checkisvalidplugin(const std::wstring&);
concurrency::reader_writer_lock OnNewSentenceSLock;
bool checkisdump(const std::wstring&);
@ -33,7 +38,7 @@ class Pluginmanager{
public:
Pluginmanager(LunaHost*);
bool dispatch(TextThread&, std::wstring& sentence);
addpluginresult addplugin(const std::wstring&);
addpluginresult addplugin(const std::wstring&,bool onlyload=false);
std::optional<std::wstring>selectpluginfile();
pluginitem get(int);
@ -43,8 +48,7 @@ public:
void setenable(int ,bool);
int count();
void add(const pluginitem&);
void remove(const std::string&);
void remove(const std::wstring&);
void remove(const std::wstring&,bool);
void swaprank(int,int);
};