LunaHook-mirror/LunaHost/GUI/LunaHost.cpp
恍兮惚兮 c94547bbc9 everyone
This reverts commit 975f049797.

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
2024-03-30 02:32:54 +08:00

687 lines
23 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <CommCtrl.h>
#include <TlHelp32.h>
#include<stdio.h>
#include<thread>
#include<fstream>
#include"host.h"
#include"hookcode.h"
#include"textthread.h"
#include"LunaHost.h"
#include"Lang/Lang.h"
auto gmf=[&](DWORD processId)->std::optional<std::wstring>{
//见鬼了GetModuleFileName找不到标识符
std::vector<wchar_t> buffer(MAX_PATH);
if (AutoHandle<> process = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, processId))
if (GetModuleFileNameExW(process, 0, buffer.data(), MAX_PATH)) return buffer.data();
return {};
};
void LunaHost::toclipboard(std::wstring& sentence){
for (int loop = 0; loop < 10; loop++) {
if (OpenClipboard(winId)) {
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, (sentence.size() + 2) * sizeof(wchar_t));
memcpy(GlobalLock(hMem), sentence.c_str(), (sentence.size() + 2) * sizeof(wchar_t));
EmptyClipboard();
SetClipboardData(CF_UNICODETEXT, hMem);
GlobalUnlock(hMem);
CloseClipboard();
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
}
void LunaHost::on_close(){
savesettings();
delete configs;
for(auto pid:attachedprocess){
Host::DetachProcess(pid);
}
if(attachedprocess.size())
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
void LunaHost::savesettings()
{
configs->set("ToClipboard",check_toclipboard);
configs->set("AutoAttach",autoattach);
configs->set("AutoAttach_SavedOnly",autoattach_savedonly);
configs->set("flushDelay",TextThread::flushDelay);
configs->set("filterRepetition",TextThread::filterRepetition);
configs->set("maxBufferSize",TextThread::maxBufferSize);
configs->set("maxHistorySize",TextThread::maxHistorySize);
configs->set("defaultCodepage",Host::defaultCodepage);
configs->set("autoattachexes",autoattachexes);
configs->set("savedhookcontext",savedhookcontext);
}
void LunaHost::loadsettings(){
check_toclipboard=configs->get("ToClipboard",false);
autoattach=configs->get("AutoAttach",false);
autoattach_savedonly=configs->get("AutoAttach_SavedOnly",true);
TextThread::flushDelay=configs->get("flushDelay",TextThread::flushDelay);
TextThread::filterRepetition=configs->get("filterRepetition",TextThread::filterRepetition);
TextThread::maxBufferSize=configs->get("maxBufferSize",TextThread::maxBufferSize);
TextThread::maxHistorySize=configs->get("maxHistorySize",TextThread::maxHistorySize);
Host::defaultCodepage=configs->get("defaultCodepage",Host::defaultCodepage);
autoattachexes=configs->get("autoattachexes",std::set<std::string>{});
savedhookcontext=configs->get("savedhookcontext",decltype(savedhookcontext){});
}
std::unordered_map<std::wstring,std::vector<int>> getprocesslist();
void LunaHost::doautoattach()
{
if(autoattach==false&&autoattach_savedonly==false)return;
if(autoattachexes.empty())return;
for(auto [pexe,pids ]:getprocesslist())
{
auto&& u8procname=WideStringToString(pexe);
if(autoattachexes.find(u8procname)==autoattachexes.end())continue;
if(autoattach_savedonly && savedhookcontext.find(u8procname)==savedhookcontext.end())continue;
for(auto pid:pids){
if(userdetachedpids.find(pid)!=userdetachedpids.end())continue;
if(attachedprocess.find(pid)==attachedprocess.end())
Host::InjectProcess(pid);
}
break;
}
}
void LunaHost::on_proc_connect(DWORD pid)
{
attachedprocess.insert(pid);
if(auto pexe=GetModuleFilename(pid))
{
autoattachexes.insert(WideStringToString(pexe.value()));
}
}
LunaHost::LunaHost(){
configs=new confighelper;
loadsettings();
std::thread([&]{
while(1){
doautoattach();
std::this_thread::sleep_for(std::chrono::seconds(2));
}
}).detach();
setfont(25);
settext(WndLunaHostGui);
btnshowsettionwindow=new button(this, BtnShowSettingWindow);
g_selectprocessbutton =new button(this,BtnSelectProcess) ;
// btnsavehook=new button(this,BtnSaveHook,10,10,10,10);
// btnsavehook->onclick=std::bind(&LunaHost::btnsavehookscallback,this);
btndetachall=new button(this,BtnDetach);
btndetachall->onclick=[&](){
for(auto pid:attachedprocess){
Host::DetachProcess(pid);
userdetachedpids.insert(pid);
}
};
g_hEdit_userhook = new lineedit(this);
btnplugin=new button(this,BtnPlugin);
plugins=new Pluginmanager(this);
btnplugin->onclick=[&](){
if(pluginwindow==0) pluginwindow=new Pluginwindow(this,plugins);
pluginwindow->show();
};
g_hButton_insert = new button(this,BtnInsertUserHook) ;
btnshowsettionwindow->onclick=[&](){
if(settingwindow==0) settingwindow=new Settingwindow(this);
settingwindow->show();
};
g_selectprocessbutton->onclick=[&](){
if(_processlistwindow==0) _processlistwindow=new processlistwindow(this);
_processlistwindow->show();
};
g_hButton_insert->onclick=[&](){
auto hp = HookCode::Parse(std::move(g_hEdit_userhook->text()));
if(hp){
for(auto _:attachedprocess){
Host::InsertHook(_,hp.value());
}
}
else{
g_showtexts->appendtext(NotifyInvalidHookCode);
}
};
g_hListBox_listtext = new listbox(this);
g_hListBox_listtext->oncurrentchange=[&](int idx){
uint64_t handle = g_hListBox_listtext->getdata(idx);
std::wstring get;
for(auto& _:savetext.at(handle)){
get+=_;
get+=L"\r\n";
}
currentselect=handle;
g_showtexts->settext(get);
g_showtexts->scrolltoend();
};
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,[&,tt](){toclipboard(std::wstring(tt->hp.hookcode));});
menu.add_sep();
menu.add(MenuRemoveHook,[&,tt](){Host::RemoveHook(tt->tp.processId,tt->tp.addr);});
menu.add(MenuDetachProcess,[&,tt](){
Host::DetachProcess(tt->tp.processId);
userdetachedpids.insert(tt->tp.processId);
});
menu.add_sep();
menu.add(MenuRemeberSelect,[&,tt](){
if(auto pexe=gmf(tt->tp.processId))
savedhookcontext[WideStringToString(pexe.value())]={
{"hookcode",WideStringToString(tt->hp.hookcode)},
{"ctx1",tt->tp.ctx},
{"ctx2",tt->tp.ctx2},
};
});
menu.add(MenuForgetSelect,[&,tt](){
if(auto pexe=gmf(tt->tp.processId))
savedhookcontext.erase(WideStringToString(pexe.value()));
});
return menu;
};
g_showtexts = new multilineedit(this);
g_showtexts->setreadonly(true);
btnsearchhooks=new button(this,BtnSearchHook);
btnsearchhooks->onclick=[&](){
if(hooksearchwindow==0) hooksearchwindow=new Hooksearchwindow(this);
hooksearchwindow->show();
};
Host::Start(
std::bind(&LunaHost::on_proc_connect,this,std::placeholders::_1),
[&](DWORD pid) {
attachedprocess.erase(pid);
},
std::bind(&LunaHost::on_thread_create,this,std::placeholders::_1),
std::bind(&LunaHost::on_thread_delete,this,std::placeholders::_1),
std::bind(&LunaHost::on_text_recv,this,std::placeholders::_1,std::placeholders::_2)
);
mainlayout=new gridlayout();
mainlayout->addcontrol(g_selectprocessbutton,0,0);
mainlayout->addcontrol(btndetachall,0,1);
mainlayout->addcontrol(btnshowsettionwindow,0,2);
mainlayout->addcontrol(btnplugin,0,3);
mainlayout->addcontrol(g_hEdit_userhook,1,0,1,2);
mainlayout->addcontrol(g_hButton_insert,1,2);
mainlayout->addcontrol(btnsearchhooks,1,3);
mainlayout->addcontrol(g_hListBox_listtext,2,0,1,4);
mainlayout->addcontrol(g_showtexts,3,0,1,4);
mainlayout->setfixedheigth(0,30);
mainlayout->setfixedheigth(1,30);
setlayout(mainlayout);
setcentral(1200,800);
}
void LunaHost::on_text_recv_checkissaved(TextThread& thread)
{
if(onceautoselectthread.find(thread.handle)!=onceautoselectthread.end())return;
onceautoselectthread.insert(thread.handle);
if(auto exe=GetModuleFilename(thread.tp.processId))
{
auto exea=WideStringToString(exe.value());
if(savedhookcontext.find(exea)==savedhookcontext.end())return;
std::string hc= savedhookcontext[exea]["hookcode"];
uint64_t ctx1=savedhookcontext[exea]["ctx1"];
uint64_t ctx2=savedhookcontext[exea]["ctx2"];
if(((ctx1&0xffff)==(thread.tp.ctx&0xffff) )&& (ctx2==thread.tp.ctx2) && (hc==WideStringToString(thread.hp.hookcode)))
{
for(int i=0;i<g_hListBox_listtext->count();i++)
{
auto handle=g_hListBox_listtext->getdata(i);
if(handle==thread.handle)
{
g_hListBox_listtext->setcurrent(i);
break;
}
}
}
}
}
bool LunaHost::on_text_recv(TextThread& thread, std::wstring& output){
std::lock_guard _(settextmutex);
on_text_recv_checkissaved(thread);
if(!plugins->dispatch(thread,output))return false;
strReplace(output,L"\n",L"\r\n");
savetext.at(thread.handle).push_back(output);
if(currentselect==thread.handle){
g_showtexts->scrolltoend();
g_showtexts->appendtext(output);
}
return true;
}
void LunaHost::on_thread_create(TextThread& thread){
wchar_t buff[65535];
swprintf_s(buff,L"[%I64X:%I32X:%I64X:%I64X:%I64X:%s:%s]",
thread.handle,
thread.tp.processId,
thread.tp.addr,
thread.tp.ctx,
thread.tp.ctx2,
thread.name.c_str(),
thread.hp.hookcode
);
savetext.insert({thread.handle,{}});
int index=g_hListBox_listtext->additem(buff);
g_hListBox_listtext->setdata(index,thread.handle);
}
void LunaHost::on_thread_delete(TextThread& thread){
int count = g_hListBox_listtext->count();
for (int i = 0; i < count; i++) {
uint64_t handle = g_hListBox_listtext->getdata(i);
if (handle== thread.handle) {
g_hListBox_listtext->deleteitem(i);
break;
}
}
}
Settingwindow::Settingwindow(LunaHost* host):mainwindow(host){
int height=30;int curry=10;int space=10;
int labelwidth=300;int spinwidth=200;
g_timeout = new spinbox(this,TextThread::flushDelay) ;
g_codepage = new spinbox(this,Host::defaultCodepage) ;
spinmaxbuffsize = new spinbox(this,TextThread::maxBufferSize);
;curry+=height+space;
spinmaxbuffsize->onvaluechange=[=](int v){
TextThread::maxBufferSize=v;
};
spinmaxhistsize = new spinbox(this,TextThread::maxHistorySize) ;
;curry+=height+space;
spinmaxhistsize->onvaluechange=[=](int v){
TextThread::maxHistorySize=v;
};
ckbfilterrepeat=new checkbox(this,LblFilterRepeat);
ckbfilterrepeat->onclick=[=](){
TextThread::filterRepetition=ckbfilterrepeat->ischecked();
};
ckbfilterrepeat->setcheck(TextThread::filterRepetition);
g_check_clipboard =new checkbox(this,BtnToClipboard);
g_check_clipboard->onclick=[=](){
host->check_toclipboard=g_check_clipboard->ischecked();
};
g_check_clipboard->setcheck(host->check_toclipboard);
autoattach =new checkbox(this,LblAutoAttach);
autoattach->onclick=[=](){
host->autoattach=autoattach->ischecked();
};
autoattach->setcheck(host->autoattach);
autoattach_so =new checkbox(this,LblAutoAttach_savedonly);
autoattach_so->onclick=[=](){
host->autoattach_savedonly=autoattach_so->ischecked();
};
autoattach_so->setcheck(host->autoattach_savedonly);
readonlycheck=new checkbox(this,BtnReadOnly);
readonlycheck->onclick=[=](){
host->g_showtexts->setreadonly(readonlycheck->ischecked());
};
readonlycheck->setcheck(true);
g_timeout->onvaluechange=[=](int v){
TextThread::flushDelay=v;
};
g_codepage->onvaluechange=[=](int v){
if(IsValidCodePage(v)){
Host::defaultCodepage= v;
}
};
g_codepage->setminmax(0,CP_UTF8);
mainlayout=new gridlayout();
mainlayout->addcontrol(new label(this,LblFlushDelay),0,0);
mainlayout->addcontrol(g_timeout,0,1);
mainlayout->addcontrol(new label(this,LblCodePage),1,0);
mainlayout->addcontrol(g_codepage,1,1);
mainlayout->addcontrol(new label(this,LblMaxBuff),2,0);
mainlayout->addcontrol(spinmaxbuffsize,2,1);
mainlayout->addcontrol(new label(this,LblMaxHist),3,0);
mainlayout->addcontrol(spinmaxhistsize,3,1);
mainlayout->addcontrol(ckbfilterrepeat,4,0,1,2);
mainlayout->addcontrol(g_check_clipboard,5,0,1,2);
mainlayout->addcontrol(autoattach,6,0,1,2);
mainlayout->addcontrol(autoattach_so,7,0,1,2);
mainlayout->addcontrol(readonlycheck,8,0,1,2);
setlayout(mainlayout);
setcentral(600,500);
settext(WndSetting);
}
void Pluginwindow::on_size(int w,int h){
listplugins->setgeo(10,10,w-20,h-20);
}
void Pluginwindow::pluginrankmove(int moveoffset){
auto idx=listplugins->currentidx();
if(idx==-1)return;
auto idx2=idx+moveoffset;
auto a=min(idx,idx2),b=max(idx,idx2);
if(a<0||b>=listplugins->count())return;
pluginmanager->swaprank(a,b);
auto pa=((LPCWSTR)listplugins->getdata(a));
auto pb=((LPCWSTR)listplugins->getdata(b));
listplugins->deleteitem(a);
listplugins->insertitem(b,std::filesystem::path(pa).stem());
listplugins->setdata(b,(LONG_PTR)pa);
}
Pluginwindow::Pluginwindow(mainwindow*p,Pluginmanager* pl):mainwindow(p),pluginmanager(pl){
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());
listplugins->setdata(idx,(LONG_PTR)_s);
};
listplugins = new listbox(this);
listplugins->on_menu=[&](){
Menu menu;
menu.add(MenuAddPlugin,[&](){
if(auto f=pluginmanager->selectpluginfile())
switch (auto res=pluginmanager->addplugin(f.value()))
{
case addpluginresult::success:
listadd(f.value());
break;
default:
std::map<addpluginresult,LPCWSTR> errorlog={
{addpluginresult::isnotaplugins,InvalidPlugin},
{addpluginresult::invaliddll,InvalidDll},
{addpluginresult::dumplicate,InvalidDump},
};
MessageBoxW(winId,errorlog[res],MsgError,0);
}
});
auto idx=listplugins->currentidx();
if(idx!=-1)
{
menu.add(MenuRemovePlugin,[&,idx](){
pluginmanager->remove((LPCWSTR)listplugins->getdata(idx),false);
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);
if(check)
pluginmanager->addplugin((LPCWSTR)listplugins->getdata(idx),true);
else
pluginmanager->remove((LPCWSTR)listplugins->getdata(idx),true);
});
}
return menu;
};
for(int i=0;i<pluginmanager->count();i++){
listadd(pluginmanager->getname(i));
}
settext(WndPlugins);
setcentral(500,400);
}
void HooksearchText::call(std::set<DWORD>pids){
edittext->settext(L"");
checkok->onclick=[&,pids](){
close();
auto cp=codepage->getcurr();
if(!IsValidCodePage(cp)) return;
SearchParam sp = {};
sp.codepage=cp;
wcsncpy_s(sp.text, edittext->text().c_str(), PATTERN_SIZE - 1);
for(auto pid:pids)
Host::FindHooks(pid, sp);
};
show();
}
HooksearchText::HooksearchText(mainwindow* p):mainwindow(p){
codepage=new spinbox(this,Host::defaultCodepage);
codepage->setminmax(0,CP_UTF8);
edittext=new lineedit(this);
checkok=new button(this,BtnOk);
layout=new gridlayout();
layout->addcontrol(new label(this,HS_TEXT),0,0);
layout->addcontrol(new label(this,HS_CODEPAGE),1,0);
layout->addcontrol(edittext,0,1);
layout->addcontrol(codepage,1,1);
layout->addcontrol(checkok,2,1);
setlayout(layout);
setcentral(500,200);
}
std::wstring tohex(BYTE* bs,int len){
std::wstring buffer;
for (int i = 0; i < len; i += 1){
buffer.append(FormatString(L"%02hX ", bs[i]));
}
return buffer;
}
std::wstring addr2hex(uintptr_t addr){
return FormatString(L"%p",addr);
}
void realcallsearchhooks(std::set<DWORD>pids,std::wstring filter,SearchParam sp){
auto hooks = std::make_shared<std::vector<std::wstring>>();
try
{
for(auto processId:pids)
Host::FindHooks(processId, sp,
[hooks, filter](HookParam hp, std::wstring text)
{
std::wsmatch matches;
if (std::regex_search(text, matches, std::wregex(filter))) {
hooks->emplace_back(std::wstring(hp.hookcode)+L"=>"+text);
}
});
}
catch (std::exception &e) {
//std::wcout<<e.what();
return;
}
std::thread([hooks]
{
for (int lastSize = 0; hooks->size() == 0 || hooks->size() != lastSize; Sleep(2000)) lastSize = hooks->size();
std::ofstream of;
of.open("savehooks.txt");
for (auto line:*hooks) of<<WideStringToString(line)<<"\n";
of.close();
hooks->clear();
}).detach();
}
Hooksearchsetting::Hooksearchsetting(mainwindow* p):mainwindow(p){
layout=new gridlayout();
SearchParam sp{};
spinduration=new spinbox(this,sp.searchTime);
spinoffset=new spinbox(this,sp.offset);
spincap=new spinbox(this,sp.maxRecords);
spincodepage=new spinbox(this,Host::defaultCodepage);
editpattern=new lineedit(this);
editpattern->settext(tohex(sp.pattern,sp.length));
editmodule=new lineedit(this);
editmaxaddr=new lineedit(this);
editmaxaddr->settext(addr2hex(sp.maxAddress));
editminaddr=new lineedit(this);
editminaddr->settext(addr2hex(sp.minAddress));
spinpadding=new spinbox(this,0);
editregex=new lineedit(this);
start=new button(this,HS_START_HOOK_SEARCH);
layout->addcontrol(new label(this,HS_SEARCH_PATTERN),0,0);
layout->addcontrol(new label(this,HS_SEARCH_DURATION),1,0);
layout->addcontrol(new label(this,HS_PATTERN_OFFSET),2,0);
layout->addcontrol(new label(this,HS_MAX_HOOK_SEARCH_RECORDS),3,0);
layout->addcontrol(new label(this,HS_CODEPAGE),4,0);
layout->addcontrol(new label(this,HS_SEARCH_MODULE),5,0);
layout->addcontrol(new label(this,HS_MIN_ADDRESS),6,0);
layout->addcontrol(new label(this,HS_MAX_ADDRESS),7,0);
layout->addcontrol(new label(this,HS_STRING_OFFSET),8,0);
layout->addcontrol(new label(this,HS_HOOK_SEARCH_FILTER),9,0);
layout->addcontrol(start,10,1);
layout->addcontrol(editpattern,0,1);
layout->addcontrol(spinduration,1,1);
layout->addcontrol(spinoffset,2,1);
layout->addcontrol(spincap,3,1);
layout->addcontrol(spincodepage,4,1);
layout->addcontrol(editmodule,5,1);
layout->addcontrol(editminaddr,6,1);
layout->addcontrol(editmaxaddr,7,1);
layout->addcontrol(spinpadding,8,1);
layout->addcontrol(editregex,9,1);
setlayout(layout);
setcentral(1000,600);
}
std::vector<BYTE> hexStringToBytes(const std::wstring& hexString_) {
auto hexString=hexString_;
strReplace(hexString,L" ",L"");
strReplace(hexString,L"??",FormatString(L"%02hX",XX));
std::vector<BYTE> bytes;
if (hexString.length() % 2 != 0) {
return {};
}
for (int i = 0; i < hexString.size() / 2; i++) {
auto byteValue = std::stoi(hexString.substr(i*2,2), nullptr, 16);
bytes.push_back(byteValue);
}
return bytes;
}
void Hooksearchsetting::call(std::set<DWORD>pids,std::wstring reg){
if(pids.empty())return;
if(auto filename=gmf(*pids.begin()))
editmodule->settext(std::filesystem::path(filename.value()).filename().wstring());
editregex->settext(reg);
spincodepage->setcurr(Host::defaultCodepage);
start->onclick=[&,pids](){
close();
SearchParam sp{};
sp.searchTime=spinduration->getcurr();
sp.offset=spinoffset->getcurr();
sp.maxRecords=spincap->getcurr();
sp.codepage=spincodepage->getcurr();
if(editpattern->text().find(L".")==std::wstring::npos){
auto hex=hexStringToBytes(editpattern->text());
memcpy(sp.pattern,hex.data(),hex.size());
sp.length=hex.size();
}
else{
wcsncpy_s(sp.exportModule, editpattern->text().c_str(), MAX_MODULE_SIZE - 1);
sp.length = 1;
}
wcscpy(sp.boundaryModule,editmodule->text().c_str());
sp.minAddress=std::stoll(editminaddr->text(), nullptr, 16);
sp.maxAddress=std::stoll(editmaxaddr->text(), nullptr, 16);
sp.padding=spinpadding->getcurr();
realcallsearchhooks(pids,editregex->text(),sp);
};
show();
}
Hooksearchwindow::Hooksearchwindow(LunaHost* host):mainwindow(host){
cjkcheck=new checkbox(this,SEARCH_CJK);
hs_default=new button(this,HS_START_HOOK_SEARCH);
hs_text=new button(this,HS_SEARCH_FOR_TEXT);
hs_user=new button(this,HS_SETTINGS);
layout=new gridlayout();
layout->addcontrol(cjkcheck,0,0,1,3);
layout->addcontrol(hs_default,1,0);
layout->addcontrol(hs_text,1,1);
layout->addcontrol(hs_user,1,2);
setlayout(layout);
settext(BtnSearchHook);
setcentral(800,200);
auto dohooksearchdispatch=[&,host](int type)
{
close();
if(type==1)
{
if(hooksearchText==0) hooksearchText=new HooksearchText(this);
hooksearchText->call(host->attachedprocess);
return;
}
auto filter=(cjkcheck->ischecked()?L"[\\u3000-\\ua000]{4,}" : L"[\\u0020-\\u1000]{4,}");
if(type==0)
{
SearchParam sp = {};
sp.codepage = Host::defaultCodepage;
sp.length = 0;
realcallsearchhooks(host->attachedprocess,filter,sp);
}
else if(type==2)
{
if(hooksearchsetting==0) hooksearchsetting=new Hooksearchsetting(this);
hooksearchsetting->call(host->attachedprocess,filter);
return;
}
};
hs_default->onclick=std::bind(dohooksearchdispatch,0);
hs_text->onclick=std::bind(dohooksearchdispatch,1);
hs_user->onclick=std::bind(dohooksearchdispatch,2);
}