forked from Public-Mirror/Textractor
make thread linker asynchronous. also refactored, but in a way that makes me very concerned about the stability of host
This commit is contained in:
parent
3a103890ad
commit
566c0beb0a
@ -60,7 +60,7 @@ namespace
|
|||||||
|
|
||||||
size_t HashThreadParam(ThreadParam tp) { return std::hash<int64_t>()(tp.processId + tp.addr) + std::hash<int64_t>()(tp.ctx + tp.ctx2); }
|
size_t HashThreadParam(ThreadParam tp) { return std::hash<int64_t>()(tp.processId + tp.addr) + std::hash<int64_t>()(tp.ctx + tp.ctx2); }
|
||||||
Synchronized<std::unordered_map<ThreadParam, TextThread, Functor<HashThreadParam>>, std::recursive_mutex> textThreadsByParams;
|
Synchronized<std::unordered_map<ThreadParam, TextThread, Functor<HashThreadParam>>, std::recursive_mutex> textThreadsByParams;
|
||||||
Synchronized<std::unordered_map<DWORD, ProcessRecord>, std::recursive_mutex> processRecordsByIds;
|
Synchronized<std::unordered_map<DWORD, ProcessRecord>> processRecordsByIds;
|
||||||
|
|
||||||
Host::ProcessEventHandler OnConnect, OnDisconnect;
|
Host::ProcessEventHandler OnConnect, OnDisconnect;
|
||||||
Host::ThreadEventHandler OnCreate, OnDestroy;
|
Host::ThreadEventHandler OnCreate, OnDestroy;
|
||||||
@ -102,7 +102,7 @@ namespace
|
|||||||
case HOST_NOTIFICATION_FOUND_HOOK:
|
case HOST_NOTIFICATION_FOUND_HOOK:
|
||||||
{
|
{
|
||||||
auto info = *(HookFoundNotif*)buffer;
|
auto info = *(HookFoundNotif*)buffer;
|
||||||
auto& OnHookFound = processRecordsByIds->at(processId).OnHookFound;
|
auto OnHookFound = processRecordsByIds->at(processId).OnHookFound;
|
||||||
std::wstring wide = info.text;
|
std::wstring wide = info.text;
|
||||||
if (wide.size() > STRING) OnHookFound(info.hp, info.text);
|
if (wide.size() > STRING) OnHookFound(info.hp, info.text);
|
||||||
info.hp.type &= ~USING_UNICODE;
|
info.hp.type &= ~USING_UNICODE;
|
||||||
@ -132,7 +132,7 @@ namespace
|
|||||||
auto textThread = textThreadsByParams->find(tp);
|
auto textThread = textThreadsByParams->find(tp);
|
||||||
if (textThread == textThreadsByParams->end())
|
if (textThread == textThreadsByParams->end())
|
||||||
{
|
{
|
||||||
try { textThread = textThreadsByParams->try_emplace(tp, tp, Host::GetHookParam(tp)).first; }
|
try { textThread = textThreadsByParams->try_emplace(tp, tp, processRecordsByIds->at(tp.processId).GetHook(tp.addr).hp).first; }
|
||||||
catch (std::out_of_range) { continue; } // probably garbage data in pipe, try again
|
catch (std::out_of_range) { continue; } // probably garbage data in pipe, try again
|
||||||
OnCreate(textThread->second);
|
OnCreate(textThread->second);
|
||||||
}
|
}
|
||||||
@ -158,8 +158,6 @@ namespace Host
|
|||||||
OnDestroy = [Destroy](TextThread& thread) { thread.Stop(); Destroy(thread); };
|
OnDestroy = [Destroy](TextThread& thread) { thread.Stop(); Destroy(thread); };
|
||||||
TextThread::Output = Output;
|
TextThread::Output = Output;
|
||||||
|
|
||||||
processRecordsByIds->try_emplace(console.processId, console.processId, INVALID_HANDLE_VALUE);
|
|
||||||
OnConnect(console.processId);
|
|
||||||
textThreadsByParams->try_emplace(console, console, HookParam{}, CONSOLE);
|
textThreadsByParams->try_emplace(console, console, HookParam{}, CONSOLE);
|
||||||
OnCreate(GetThread(console));
|
OnCreate(GetThread(console));
|
||||||
textThreadsByParams->try_emplace(clipboard, clipboard, HookParam{}, CLIPBOARD);
|
textThreadsByParams->try_emplace(clipboard, clipboard, HookParam{}, CLIPBOARD);
|
||||||
@ -233,16 +231,18 @@ namespace Host
|
|||||||
processRecordsByIds->at(processId).Send(FindHookCmd(sp));
|
processRecordsByIds->at(processId).Send(FindHookCmd(sp));
|
||||||
}
|
}
|
||||||
|
|
||||||
HookParam GetHookParam(ThreadParam tp)
|
|
||||||
{
|
|
||||||
return processRecordsByIds->at(tp.processId).GetHook(tp.addr).hp;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextThread& GetThread(ThreadParam tp)
|
TextThread& GetThread(ThreadParam tp)
|
||||||
{
|
{
|
||||||
return textThreadsByParams->at(tp);
|
return textThreadsByParams->at(tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextThread* GetThread(int64_t handle)
|
||||||
|
{
|
||||||
|
auto textThreadsByParams = ::textThreadsByParams.Acquire();
|
||||||
|
auto thread = std::find_if(textThreadsByParams->begin(), textThreadsByParams->end(), [&](const auto& thread) { return thread.second.handle == handle; });
|
||||||
|
return thread != textThreadsByParams->end() ? &thread->second : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void AddConsoleOutput(std::wstring text)
|
void AddConsoleOutput(std::wstring text)
|
||||||
{
|
{
|
||||||
GetThread(console).AddSentence(std::move(text));
|
GetThread(console).AddSentence(std::move(text));
|
||||||
|
@ -12,11 +12,12 @@ namespace Host
|
|||||||
|
|
||||||
void InjectProcess(DWORD processId);
|
void InjectProcess(DWORD processId);
|
||||||
void DetachProcess(DWORD processId);
|
void DetachProcess(DWORD processId);
|
||||||
|
|
||||||
void InsertHook(DWORD processId, HookParam hp);
|
void InsertHook(DWORD processId, HookParam hp);
|
||||||
void RemoveHook(DWORD processId, uint64_t address);
|
void RemoveHook(DWORD processId, uint64_t address);
|
||||||
void FindHooks(DWORD processId, SearchParam sp, HookEventHandler HookFound = {});
|
void FindHooks(DWORD processId, SearchParam sp, HookEventHandler HookFound = {});
|
||||||
|
|
||||||
HookParam GetHookParam(ThreadParam tp);
|
TextThread* GetThread(int64_t handle);
|
||||||
TextThread& GetThread(ThreadParam tp);
|
TextThread& GetThread(ThreadParam tp);
|
||||||
|
|
||||||
void AddConsoleOutput(std::wstring text);
|
void AddConsoleOutput(std::wstring text);
|
||||||
|
@ -234,6 +234,13 @@ DWORD MainWindow::GetSelectedProcessId()
|
|||||||
|
|
||||||
std::array<InfoForExtension, 10> MainWindow::GetMiscInfo(TextThread& thread)
|
std::array<InfoForExtension, 10> MainWindow::GetMiscInfo(TextThread& thread)
|
||||||
{
|
{
|
||||||
|
void(*AddSentence)(MainWindow*, int64_t, const wchar_t*) = [](MainWindow* This, int64_t number, const wchar_t* sentence)
|
||||||
|
{
|
||||||
|
std::wstring sentenceStr = sentence;
|
||||||
|
// pointer from Host::GetThread may not stay valid unless on main thread
|
||||||
|
QMetaObject::invokeMethod(This, [=]() mutable { if (TextThread* thread = Host::GetThread(number)) thread->AddSentence(std::move(sentenceStr)); });
|
||||||
|
};
|
||||||
|
|
||||||
return
|
return
|
||||||
{ {
|
{ {
|
||||||
{ "current select", &thread == current },
|
{ "current select", &thread == current },
|
||||||
@ -242,6 +249,8 @@ std::array<InfoForExtension, 10> MainWindow::GetMiscInfo(TextThread& thread)
|
|||||||
{ "hook address", (int64_t)thread.tp.addr },
|
{ "hook address", (int64_t)thread.tp.addr },
|
||||||
{ "text handle", thread.handle },
|
{ "text handle", thread.handle },
|
||||||
{ "text name", (int64_t)thread.name.c_str() },
|
{ "text name", (int64_t)thread.name.c_str() },
|
||||||
|
{ "this", (int64_t)this },
|
||||||
|
{ "void (*AddSentence)(void* this, int64_t number, const wchar_t* sentence)", (int64_t)AddSentence },
|
||||||
{ nullptr, 0 } // nullptr marks end of info array
|
{ nullptr, 0 } // nullptr marks end of info array
|
||||||
} };
|
} };
|
||||||
}
|
}
|
||||||
@ -323,7 +332,7 @@ void MainWindow::RemoveHooks()
|
|||||||
for (int i = 0; i < ui->ttCombo->count(); ++i)
|
for (int i = 0; i < ui->ttCombo->count(); ++i)
|
||||||
{
|
{
|
||||||
ThreadParam tp = ParseTextThreadString(ui->ttCombo->itemText(i));
|
ThreadParam tp = ParseTextThreadString(ui->ttCombo->itemText(i));
|
||||||
if (tp.processId == GetSelectedProcessId()) hooks[tp.addr] = Host::GetHookParam(tp);
|
if (tp.processId == GetSelectedProcessId()) hooks[tp.addr] = Host::GetThread(tp).hp;
|
||||||
}
|
}
|
||||||
auto hookList = new QListWidget(this);
|
auto hookList = new QListWidget(this);
|
||||||
hookList->setWindowFlags(Qt::Window | Qt::WindowCloseButtonHint);
|
hookList->setWindowFlags(Qt::Window | Qt::WindowCloseButtonHint);
|
||||||
@ -346,24 +355,23 @@ void MainWindow::RemoveHooks()
|
|||||||
|
|
||||||
void MainWindow::SaveHooks()
|
void MainWindow::SaveHooks()
|
||||||
{
|
{
|
||||||
if (auto processName = Util::GetModuleFilename(GetSelectedProcessId()))
|
auto processName = Util::GetModuleFilename(GetSelectedProcessId());
|
||||||
{
|
if (!processName) return;
|
||||||
QHash<uint64_t, QString> hookCodes;
|
QHash<uint64_t, QString> hookCodes;
|
||||||
for (int i = 0; i < ui->ttCombo->count(); ++i)
|
for (int i = 0; i < ui->ttCombo->count(); ++i)
|
||||||
{
|
{
|
||||||
ThreadParam tp = ParseTextThreadString(ui->ttCombo->itemText(i));
|
ThreadParam tp = ParseTextThreadString(ui->ttCombo->itemText(i));
|
||||||
if (tp.processId == GetSelectedProcessId())
|
if (tp.processId == GetSelectedProcessId())
|
||||||
{
|
{
|
||||||
HookParam hp = Host::GetHookParam(tp);
|
HookParam hp = Host::GetThread(tp).hp;
|
||||||
if (!(hp.type & HOOK_ENGINE)) hookCodes[tp.addr] = S(Util::GenerateCode(hp, tp.processId));
|
if (!(hp.type & HOOK_ENGINE)) hookCodes[tp.addr] = S(Util::GenerateCode(hp, tp.processId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto hookInfo = QStringList() << S(processName.value()) << hookCodes.values();
|
auto hookInfo = QStringList() << S(processName.value()) << hookCodes.values();
|
||||||
ThreadParam tp = current.load()->tp;
|
ThreadParam tp = current.load()->tp;
|
||||||
if (tp.processId == GetSelectedProcessId()) hookInfo << QString("|%1:%2:%3").arg(tp.ctx).arg(tp.ctx2).arg(S(Util::GenerateCode(Host::GetHookParam(tp), tp.processId)));
|
if (tp.processId == GetSelectedProcessId()) hookInfo << QString("|%1:%2:%3").arg(tp.ctx).arg(tp.ctx2).arg(S(Util::GenerateCode(Host::GetThread(tp).hp, tp.processId)));
|
||||||
QTextFile(HOOK_SAVE_FILE, QIODevice::WriteOnly | QIODevice::Append).write((hookInfo.join(" , ") + "\n").toUtf8());
|
QTextFile(HOOK_SAVE_FILE, QIODevice::WriteOnly | QIODevice::Append).write((hookInfo.join(" , ") + "\n").toUtf8());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::FindHooks()
|
void MainWindow::FindHooks()
|
||||||
{
|
{
|
||||||
|
@ -93,13 +93,11 @@ BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved
|
|||||||
bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
||||||
{
|
{
|
||||||
std::lock_guard l(m);
|
std::lock_guard l(m);
|
||||||
static std::unordered_map<int64_t, std::wstring> queuedWritesByHandle;
|
int64_t textHandle = sentenceInfo["text number"];
|
||||||
int64_t textHandle = sentenceInfo["text handle"];
|
|
||||||
|
|
||||||
for (auto linkedHandle : linkedTextHandles[textHandle]) queuedWritesByHandle[linkedHandle] += L"\n" + sentence;
|
for (auto linkedHandle : linkedTextHandles[textHandle])
|
||||||
|
((void(*)(void*, int64_t, const wchar_t*))sentenceInfo["void (*AddSentence)(void* this, int64_t number, const wchar_t* sentence)"])
|
||||||
|
((void*)sentenceInfo["this"], linkedHandle, sentence.c_str());
|
||||||
|
|
||||||
if (queuedWritesByHandle[textHandle].empty()) return false;
|
return false;
|
||||||
sentence += queuedWritesByHandle[textHandle];
|
|
||||||
queuedWritesByHandle[textHandle].clear();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user