diff --git a/Lang/en.h b/Lang/en.h index d9fd0d7..7ac53ef 100644 --- a/Lang/en.h +++ b/Lang/en.h @@ -66,6 +66,7 @@ #define MenuRemovePlugin L"Remove Plugin" #define MenuPluginRankUp L"Up" #define MenuPluginRankDown L"Down" +#define MenuPluginEnable L"Enable" #define DefaultFont L"Arial" #define CantLoadQtLoader L"Can't Load QtLoader.dll" #define LblPluginNotify L"Qt Plugins Will be Loaded at Start Only." diff --git a/Lang/zh.h b/Lang/zh.h index 702270c..950419a 100644 --- a/Lang/zh.h +++ b/Lang/zh.h @@ -66,6 +66,7 @@ #define MenuRemovePlugin L"移除插件" #define MenuPluginRankUp L"上移" #define MenuPluginRankDown L"下移" +#define MenuPluginEnable L"使用" #define DefaultFont L"微软雅黑" #define CantLoadQtLoader L"无法加载QtLoader.dll" #define LblPluginNotify L"依赖于Qt的插件仅会在启动时载入。" diff --git a/LunaHost/GUI/LunaHost.cpp b/LunaHost/GUI/LunaHost.cpp index f704311..3bfcb6b 100644 --- a/LunaHost/GUI/LunaHost.cpp +++ b/LunaHost/GUI/LunaHost.cpp @@ -101,11 +101,6 @@ void LunaHost::on_proc_connect(DWORD pid) autoattachexes.insert(WideStringToString(pexe.value())); } } -TextThread* LunaHost::getcurrthread(){ - auto handle = g_hListBox_listtext->getdata(g_hListBox_listtext->currentidx()); - auto tt=Host::GetThread(handle); - return tt; -} LunaHost::LunaHost(){ configs=new confighelper; @@ -174,32 +169,34 @@ LunaHost::LunaHost(){ g_showtexts->settext(get); g_showtexts->scrolltoend(); }; - g_hListBox_listtext->add_menu(MenuCopyHookCode,[&](){if(auto tt=getcurrthread())toclipboard(std::wstring(tt->hp.hookcode));}); - - g_hListBox_listtext->add_menu_sep(); - g_hListBox_listtext->add_menu(MenuRemoveHook,[&](){if(auto tt=getcurrthread())Host::RemoveHook(tt->tp.processId,tt->tp.addr);}); - - g_hListBox_listtext->add_menu(MenuDetachProcess,[&](){ - if(auto tt=getcurrthread()){ + g_hListBox_listtext->on_menu=[&]()->maybehavemenu{ + auto handle = g_hListBox_listtext->getdata(g_hListBox_listtext->currentidx()); + auto tt=Host::GetThread(handle); + if(!tt)return {}; + Menu menu; + menu.add(MenuCopyHookCode,[&](){toclipboard(std::wstring(tt->hp.hookcode));}); + menu.add_sep(); + menu.add(MenuRemoveHook,[&](){Host::RemoveHook(tt->tp.processId,tt->tp.addr);}); + menu.add(MenuDetachProcess,[&](){ + Host::DetachProcess(tt->tp.processId); - userdetachedpids.insert(tt->tp.processId); - } - }); - g_hListBox_listtext->add_menu_sep(); - g_hListBox_listtext->add_menu(MenuRemeberSelect,[&](){ - if(auto tt=getcurrthread()) + userdetachedpids.insert(tt->tp.processId); + }); + menu.add_sep(); + menu.add(MenuRemeberSelect,[&](){ if(auto pexe=gmf(tt->tp.processId)) savedhookcontext[WideStringToString(pexe.value())]={ {"hookcode",WideStringToString(tt->hp.hookcode)}, {"ctx1",tt->tp.ctx}, {"ctx2",tt->tp.ctx2}, }; - }); - g_hListBox_listtext->add_menu(MenuForgetSelect,[&](){ - if(auto tt=getcurrthread()) - if(auto pexe=gmf(tt->tp.processId)) - savedhookcontext.erase(WideStringToString(pexe.value())); - }); + }); + menu.add(MenuForgetSelect,[&](){ + if(auto pexe=gmf(tt->tp.processId)) + savedhookcontext.erase(WideStringToString(pexe.value())); + }); + return menu; + }; g_showtexts = new multilineedit(this); g_showtexts->setreadonly(true); @@ -414,8 +411,7 @@ void Pluginwindow::pluginrankmove(int moveoffset){ listplugins->insertitem(b,std::filesystem::path(pa).stem()); listplugins->setdata(b,(LONG_PTR)pa); } -Pluginwindow::Pluginwindow(mainwindow*p,Pluginmanager* pl):mainwindow(p){ - pluginmanager=pl; +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){ @@ -425,7 +421,9 @@ Pluginwindow::Pluginwindow(mainwindow*p,Pluginmanager* pl):mainwindow(p){ }; listplugins = new listbox(this); - listplugins->add_menu(MenuAddPlugin,[&](){ + listplugins->on_menu=[&](){ + Menu menu; + menu.add(MenuAddPlugin,[&](){ if(auto f=pluginmanager->selectpluginfile()) switch (auto res=pluginmanager->addplugin(f.value())) { @@ -440,21 +438,29 @@ Pluginwindow::Pluginwindow(mainwindow*p,Pluginmanager* pl):mainwindow(p){ }; MessageBoxW(winId,errorlog[res],MsgError,0); } - }); - - listplugins->add_menu(MenuRemovePlugin,[&](){ + }); auto idx=listplugins->currentidx(); - if(idx==-1)return; - pluginmanager->remove((LPCWSTR)listplugins->getdata(idx)); - listplugins->deleteitem(idx); - }); + if(idx!=-1) + { + menu.add(MenuRemovePlugin,[&](){ + auto idx=listplugins->currentidx(); + pluginmanager->remove((LPCWSTR)listplugins->getdata(idx)); + listplugins->deleteitem(idx); + }); + menu.add_sep(); + menu.add(MenuPluginRankUp,std::bind(&Pluginwindow::pluginrankmove,this,-1)); + menu.add(MenuPluginRankDown,std::bind(&Pluginwindow::pluginrankmove,this,1)); + menu.add_sep(); + menu.add_checkable(MenuPluginEnable,pluginmanager->getenable(idx),[&,idx](bool check){ + pluginmanager->setenable(idx,check); + }); + } + return menu; + }; - listplugins->add_menu_sep(); - listplugins->add_menu(MenuPluginRankUp,std::bind(&Pluginwindow::pluginrankmove,this,-1)); - listplugins->add_menu(MenuPluginRankDown,std::bind(&Pluginwindow::pluginrankmove,this,1)); - for(int i=0;iPluginRank.size();i++){ - listadd(pluginmanager->PluginRank[i]); + for(int i=0;icount();i++){ + listadd(pluginmanager->getname(i)); } settext(WndPlugins); setcentral(500,400); diff --git a/LunaHost/GUI/LunaHost.h b/LunaHost/GUI/LunaHost.h index 869f528..45d6588 100644 --- a/LunaHost/GUI/LunaHost.h +++ b/LunaHost/GUI/LunaHost.h @@ -101,7 +101,6 @@ class LunaHost:public mainwindow{ void on_thread_delete(TextThread& thread); void on_proc_connect(DWORD pid); public: - TextThread* getcurrthread(); confighelper* configs; int64_t currentselect=0; bool check_toclipboard; diff --git a/LunaHost/GUI/confighelper.cpp b/LunaHost/GUI/confighelper.cpp index 028d009..5ee7cca 100644 --- a/LunaHost/GUI/confighelper.cpp +++ b/LunaHost/GUI/confighelper.cpp @@ -37,65 +37,4 @@ confighelper::confighelper(){ confighelper::~confighelper(){ writefile(configpath.c_str(), configs.dump(4)); -} -void confighelper::pluginsremove(const std::string&s){ - auto &plgs=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 confighelper::pluginrankswap(int a,int b){ - auto &plgs=configs["plugins"]; - auto _b=plgs[b]; - plgs[b]=plgs[a]; - plgs[a]=_b; -} -void confighelper::pluginsadd(const pluginitem& item){ - configs["plugins"].push_back(item.dump()); -} -int confighelper::pluginsnum(){ - return configs["plugins"].size(); -} -pluginitem confighelper::pluginsget(int i){ - return pluginitem{configs["plugins"][i]}; -} -template -T safequeryjson(const nlohmann::json& js,const std::string& key,const T &defaultv){ - if(js.find(key)==js.end()){ - return defaultv; - } - return js[key]; -} -pluginitem::pluginitem(const nlohmann::json& js){ - path=js["path"]; - isQt=safequeryjson(js,"isQt",false); - isref=safequeryjson(js,"isref",false); -} -std::wstring pluginitem::wpath(){ - auto wp=StringToWideString(path); - if(isref)return std::filesystem::current_path()/wp; - else return wp; -} - -std::pair castabs2ref(const std::wstring&p){ - auto curr=std::filesystem::current_path().wstring(); - if(startWith(p,curr)){ - return {p.substr(curr.size()+1),true}; - } - return {p,false}; -} -pluginitem::pluginitem(const std::wstring& pabs,bool _isQt){ - isQt=_isQt; - auto [p,_isref]=castabs2ref(pabs); - isref=_isref; - path=WideStringToString(p); -} -nlohmann::json pluginitem::dump() const{ - return { - {"path",path}, - {"isQt",isQt}, - {"isref",isref} - }; } \ No newline at end of file diff --git a/LunaHost/GUI/confighelper.h b/LunaHost/GUI/confighelper.h index 3c9a7f9..97997e7 100644 --- a/LunaHost/GUI/confighelper.h +++ b/LunaHost/GUI/confighelper.h @@ -1,26 +1,13 @@ #ifndef LUNA_CONFIG_HELPER #define LUNA_CONFIG_HELPER #include -struct pluginitem{ - std::string path; - bool isQt; - bool isref; - pluginitem(const nlohmann::json&); - pluginitem(const std::wstring&,bool); - std::wstring wpath(); - nlohmann::json dump() const; -}; + class confighelper{ - nlohmann::json configs; std::wstring configpath; public: + nlohmann::json configs; confighelper(); ~confighelper(); - pluginitem pluginsget(int); - int pluginsnum(); - void pluginsadd(const pluginitem&); - void pluginsremove(const std::string&); - void pluginrankswap(int,int); template T get(const std::string&key,T default1){ if(configs.find(key)==configs.end())return default1; @@ -31,5 +18,11 @@ public: configs[key]=v; } }; - +template +T safequeryjson(const nlohmann::json& js,const std::string& key,const T &defaultv){ + if(js.find(key)==js.end()){ + return defaultv; + } + return js[key]; +} #endif \ No newline at end of file diff --git a/LunaHost/GUI/controls.cpp b/LunaHost/GUI/controls.cpp index 8b5acc1..a3d23f4 100644 --- a/LunaHost/GUI/controls.cpp +++ b/LunaHost/GUI/controls.cpp @@ -314,20 +314,24 @@ gridlayout::gridlayout(int row,int col):control(0){ void gridlayout::setmargin(int m){ margin=m; } -void control::menu_dispatch(WPARAM wparam){ +void Menu::dispatch(WPARAM wparam){ auto idx=LOWORD(wparam); menu_callbacks[idx].callback(); + DestroyMenu(hmenu); } -HMENU control::load_menu(){ - HMENU hMenu = CreatePopupMenu(); +HMENU Menu::load(){ + hmenu = CreatePopupMenu(); for(int i=0;i callback, UINT type){ - menu_callbacks.push_back({callback,type,str}); +void Menu::add(const std::wstring& str,std::function callback){ + menu_callbacks.push_back({MF_STRING,callback,str}); } -void control::add_menu_sep(){ - menu_callbacks.push_back({[](){},MF_SEPARATOR,L""}); +void Menu::add_checkable(const std::wstring& str,bool check,std::function callback){ + menu_callbacks.push_back({(UINT)(MF_STRING|(check?MF_CHECKED:MF_UNCHECKED)),std::bind(callback,!check),str}); +} +void Menu::add_sep(){ + menu_callbacks.push_back({MF_SEPARATOR}); } \ No newline at end of file diff --git a/LunaHost/GUI/controls.h b/LunaHost/GUI/controls.h index dd1de2b..d4bd971 100644 --- a/LunaHost/GUI/controls.h +++ b/LunaHost/GUI/controls.h @@ -2,22 +2,31 @@ #define LUNA_BASE_CONTROLS_H #include"window.h" #include +class Menu{ +public: + void dispatch(WPARAM); + struct menuinfos{ + UINT type; + std::function callback; + std::wstring str; + }; + std::vectormenu_callbacks; + HMENU load(); + HMENU hmenu; + void add(const std::wstring&,std::function callback); + void add_checkable(const std::wstring&,bool,std::function callback); + void add_sep(); +}; +using maybehavemenu=std::optional; + class control:public basewindow{ public: mainwindow* parent; control(mainwindow*); virtual void dispatch(WPARAM); virtual void dispatch_2(WPARAM wParam, LPARAM lParam); - void menu_dispatch(WPARAM); - HMENU load_menu(); - struct menuinfos{ - std::function callback; - UINT type; - std::wstring str; - }; - std::vectormenu_callbacks; - void add_menu(const std::wstring&,std::function callback, UINT type=MF_STRING); - void add_menu_sep(); + maybehavemenu menu; + std::function on_menu=[]()->maybehavemenu{return {};}; }; class button:public control{ diff --git a/LunaHost/GUI/pluginmanager.cpp b/LunaHost/GUI/pluginmanager.cpp index c278aa8..956d00d 100644 --- a/LunaHost/GUI/pluginmanager.cpp +++ b/LunaHost/GUI/pluginmanager.cpp @@ -128,45 +128,49 @@ void Pluginmanager::loadqtdlls(std::vector&collectQtplugs){ } SetEnvironmentVariableW(L"PATH",envs.c_str()); - #if 1 - auto modules=QtLoadLibrarys(collectQtplugs); - if(modules.empty())return; - #else + HMODULE* modules; + if(std::true_type::value){ + auto vmodules=QtLoadLibrarys(collectQtplugs); + if(vmodules.empty())return; + modules=vmodules.data(); + } + else{ + auto QtLoadLibrary = loadqtloader(pluginpath); + if(!QtLoadLibrary){ + MessageBoxW(host->winId,CantLoadQtLoader,L"Error",0); + return ; + } + std::vectorsaves; + for(auto&p:collectQtplugs){ + auto str=new wchar_t[p.size()+1]; + wcscpy(str,p.c_str()); + saves.emplace_back(str); + } + modules=QtLoadLibrary(saves.data(),collectQtplugs.size()); + for(auto str:saves)delete str; - auto QtLoadLibrary = loadqtloader(pluginpath); - if(!QtLoadLibrary){ - MessageBoxW(host->winId,CantLoadQtLoader,L"Error",0); - return ; } - std::vectorsaves; - for(auto&p:collectQtplugs){ - auto str=new wchar_t[p.size()+1]; - wcscpy(str,p.c_str()); - saves.emplace_back(str); - } - auto modules=QtLoadLibrary(saves.data(),collectQtplugs.size()); - for(auto str:saves)delete str; - #endif for(int i=0;iconfigs){ try { std::scoped_lock lock(OnNewSentenceSLock); std::vectorcollectQtplugs; - for (auto i=0;iconfigs->pluginsnum();i++) { - auto plg=host->configs->pluginsget(i); + for (auto i=0;i{L"InternalClipBoard"}, PluginRank}){ - for(const auto&path:pathl){ - auto funptr=OnNewSentenceS[path]; - if(funptr==0)continue; - if (!*(sentenceBuffer = ((OnNewSentence_t)funptr)(sentenceBuffer, sentenceInfo))){interupt=true;break;}; + for(int i=0;iconfigs["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()); +} +int Pluginmanager::count(){ + return configs->configs["plugins"].size(); +} +pluginitem Pluginmanager::get(int i){ + return pluginitem{configs->configs["plugins"][i]}; +} +void Pluginmanager::set(int i,const pluginitem& item){ + configs->configs["plugins"][i]=item.dump(); +} + +pluginitem::pluginitem(const nlohmann::json& js){ + path=js["path"]; + isQt=safequeryjson(js,"isQt",false); + isref=safequeryjson(js,"isref",false); + enable=safequeryjson(js,"enable",true); +} +std::wstring pluginitem::wpath(){ + auto wp=StringToWideString(path); + if(isref)return std::filesystem::current_path()/wp; + else return wp; +} + +std::pair castabs2ref(const std::wstring&p){ + auto curr=std::filesystem::current_path().wstring(); + if(startWith(p,curr)){ + return {p.substr(curr.size()+1),true}; + } + return {p,false}; +} +pluginitem::pluginitem(const std::wstring& pabs,bool _isQt){ + isQt=_isQt; + auto [p,_isref]=castabs2ref(pabs); + isref=_isref; + path=WideStringToString(p); + enable=true; +} +nlohmann::json pluginitem::dump() const{ + return { + {"path",path}, + {"isQt",isQt}, + {"isref",isref}, + {"enable",enable} + }; +} +bool Pluginmanager::getenable(int idx){ + return get(idx).enable; +} +void Pluginmanager::setenable(int idx,bool en){ + auto item=get(idx); + item.enable=en; + set(idx,item); +} +std::wstring Pluginmanager::getname(int idx){ + return get(idx).wpath(); +} std::optional Pluginmanager::checkisvalidplugin(const std::wstring& pl){ auto path=std::filesystem::path(pl); if (!std::filesystem::exists(path))return{}; @@ -221,22 +297,16 @@ bool Pluginmanager::checkisdump(const std::wstring& dll){ return false; } void Pluginmanager::remove(const std::wstring& ss){ - std::scoped_lock lock(OnNewSentenceSLock); - auto it = std::find(PluginRank.begin(), PluginRank.end(), ss); - if (it != PluginRank.end()) { - PluginRank.erase(it); - } - host->configs->pluginsremove(WideStringToString(ss)); + remove(WideStringToString(ss)); } std::optionalPluginmanager::selectpluginfile(){ - return SelectFile(host->winId,L"Plugin Files\0*.dll;*.xdll\0"); + return SelectFile(0,L"Plugin Files\0*.dll;*.xdll\0"); } void Pluginmanager::swaprank(int a,int b){ - std::scoped_lock lock(OnNewSentenceSLock); - auto _b=PluginRank[b]; - PluginRank[b]=PluginRank[a]; - PluginRank[a]=_b; - host->configs->pluginrankswap(a,b); + auto &plgs=configs->configs["plugins"]; + auto _b=plgs[b]; + plgs[b]=plgs[a]; + plgs[a]=_b; } DWORD Rva2Offset(DWORD rva, PIMAGE_SECTION_HEADER psh, PIMAGE_NT_HEADERS pnt) { @@ -330,10 +400,8 @@ addpluginresult Pluginmanager::addplugin(const std::wstring& p){ std::scoped_lock lock(OnNewSentenceSLock); if(checkisdump(p))return addpluginresult::dumplicate; - PluginRank.push_back(p); - //std::swap(PluginRank.end()-2,PluginRank.end()-1); OnNewSentenceS[p]=plugin; - host->configs->pluginsadd({p,isQt}); + add({p,isQt}); return addpluginresult::success; } diff --git a/LunaHost/GUI/pluginmanager.h b/LunaHost/GUI/pluginmanager.h index 3bcf18a..a2cbfa9 100644 --- a/LunaHost/GUI/pluginmanager.h +++ b/LunaHost/GUI/pluginmanager.h @@ -2,29 +2,50 @@ #define LUNA_PLUGINMANAGER_H #include"Plugin/plugindef.h" #include"textthread.h" +#include class LunaHost; +class confighelper; enum class addpluginresult{ success, invaliddll, isnotaplugins, dumplicate }; +struct pluginitem{ + std::string path; + bool isQt; + bool isref; + bool enable; + pluginitem(const nlohmann::json&); + pluginitem(const std::wstring&,bool); + std::wstring wpath(); + nlohmann::json dump() const; +}; class Pluginmanager{ std::unordered_mapOnNewSentenceS; std::optional checkisvalidplugin(const std::wstring&); concurrency::reader_writer_lock OnNewSentenceSLock; bool checkisdump(const std::wstring&); + confighelper* configs; LunaHost* host; std::array GetSentenceInfo(TextThread& thread); void loadqtdlls(std::vector&collectQtplugs); public: - std::vectorPluginRank; Pluginmanager(LunaHost*); bool dispatch(TextThread&, std::wstring& sentence); addpluginresult addplugin(const std::wstring&); - void swaprank(int,int); - void remove(const std::wstring&); std::optionalselectpluginfile(); + + pluginitem get(int); + std::wstring getname(int); + bool getenable(int); + void set(int,const pluginitem&); + void setenable(int ,bool); + int count(); + void add(const pluginitem&); + void remove(const std::string&); + void remove(const std::wstring&); + void swaprank(int,int); }; #endif \ No newline at end of file diff --git a/LunaHost/GUI/window.cpp b/LunaHost/GUI/window.cpp index 034a1e4..3437645 100644 --- a/LunaHost/GUI/window.cpp +++ b/LunaHost/GUI/window.cpp @@ -77,7 +77,9 @@ LRESULT mainwindow::wndproc(UINT message, WPARAM wParam, LPARAM lParam){ if(lParam==0){ for(auto ctl:controls){ if(lastcontexthwnd==ctl->winId){ - ctl->menu_dispatch(wParam);break; + if(ctl->menu) + ctl->menu.value().dispatch(wParam); + break; } } } @@ -94,11 +96,12 @@ LRESULT mainwindow::wndproc(UINT message, WPARAM wParam, LPARAM lParam){ bool succ=false;lastcontexthwnd=0; for(auto ctl:controls){ if((HWND)wParam==ctl->winId){ - auto hm=ctl->load_menu(); + auto hm=ctl->on_menu(); + ctl->menu=hm; if(hm){ int xPos = LOWORD(lParam); int yPos = HIWORD(lParam); - TrackPopupMenu(hm, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON, + TrackPopupMenu(hm.value().load(), TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON, xPos, yPos, 0, winId, NULL); lastcontexthwnd=ctl->winId; succ=true;