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); }
|
||||
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::ThreadEventHandler OnCreate, OnDestroy;
|
||||
@ -102,7 +102,7 @@ namespace
|
||||
case HOST_NOTIFICATION_FOUND_HOOK:
|
||||
{
|
||||
auto info = *(HookFoundNotif*)buffer;
|
||||
auto& OnHookFound = processRecordsByIds->at(processId).OnHookFound;
|
||||
auto OnHookFound = processRecordsByIds->at(processId).OnHookFound;
|
||||
std::wstring wide = info.text;
|
||||
if (wide.size() > STRING) OnHookFound(info.hp, info.text);
|
||||
info.hp.type &= ~USING_UNICODE;
|
||||
@ -132,7 +132,7 @@ namespace
|
||||
auto textThread = textThreadsByParams->find(tp);
|
||||
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
|
||||
OnCreate(textThread->second);
|
||||
}
|
||||
@ -158,8 +158,6 @@ namespace Host
|
||||
OnDestroy = [Destroy](TextThread& thread) { thread.Stop(); Destroy(thread); };
|
||||
TextThread::Output = Output;
|
||||
|
||||
processRecordsByIds->try_emplace(console.processId, console.processId, INVALID_HANDLE_VALUE);
|
||||
OnConnect(console.processId);
|
||||
textThreadsByParams->try_emplace(console, console, HookParam{}, CONSOLE);
|
||||
OnCreate(GetThread(console));
|
||||
textThreadsByParams->try_emplace(clipboard, clipboard, HookParam{}, CLIPBOARD);
|
||||
@ -233,16 +231,18 @@ namespace Host
|
||||
processRecordsByIds->at(processId).Send(FindHookCmd(sp));
|
||||
}
|
||||
|
||||
HookParam GetHookParam(ThreadParam tp)
|
||||
{
|
||||
return processRecordsByIds->at(tp.processId).GetHook(tp.addr).hp;
|
||||
}
|
||||
|
||||
TextThread& GetThread(ThreadParam 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)
|
||||
{
|
||||
GetThread(console).AddSentence(std::move(text));
|
||||
|
@ -12,11 +12,12 @@ namespace Host
|
||||
|
||||
void InjectProcess(DWORD processId);
|
||||
void DetachProcess(DWORD processId);
|
||||
|
||||
void InsertHook(DWORD processId, HookParam hp);
|
||||
void RemoveHook(DWORD processId, uint64_t address);
|
||||
void FindHooks(DWORD processId, SearchParam sp, HookEventHandler HookFound = {});
|
||||
|
||||
HookParam GetHookParam(ThreadParam tp);
|
||||
TextThread* GetThread(int64_t handle);
|
||||
TextThread& GetThread(ThreadParam tp);
|
||||
|
||||
void AddConsoleOutput(std::wstring text);
|
||||
|
@ -234,6 +234,13 @@ DWORD MainWindow::GetSelectedProcessId()
|
||||
|
||||
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
|
||||
{ {
|
||||
{ "current select", &thread == current },
|
||||
@ -242,6 +249,8 @@ std::array<InfoForExtension, 10> MainWindow::GetMiscInfo(TextThread& thread)
|
||||
{ "hook address", (int64_t)thread.tp.addr },
|
||||
{ "text handle", thread.handle },
|
||||
{ "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
|
||||
} };
|
||||
}
|
||||
@ -323,7 +332,7 @@ void MainWindow::RemoveHooks()
|
||||
for (int i = 0; i < ui->ttCombo->count(); ++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);
|
||||
hookList->setWindowFlags(Qt::Window | Qt::WindowCloseButtonHint);
|
||||
@ -346,23 +355,22 @@ void MainWindow::RemoveHooks()
|
||||
|
||||
void MainWindow::SaveHooks()
|
||||
{
|
||||
if (auto processName = Util::GetModuleFilename(GetSelectedProcessId()))
|
||||
auto processName = Util::GetModuleFilename(GetSelectedProcessId());
|
||||
if (!processName) return;
|
||||
QHash<uint64_t, QString> hookCodes;
|
||||
for (int i = 0; i < ui->ttCombo->count(); ++i)
|
||||
{
|
||||
QHash<uint64_t, QString> hookCodes;
|
||||
for (int i = 0; i < ui->ttCombo->count(); ++i)
|
||||
ThreadParam tp = ParseTextThreadString(ui->ttCombo->itemText(i));
|
||||
if (tp.processId == GetSelectedProcessId())
|
||||
{
|
||||
ThreadParam tp = ParseTextThreadString(ui->ttCombo->itemText(i));
|
||||
if (tp.processId == GetSelectedProcessId())
|
||||
{
|
||||
HookParam hp = Host::GetHookParam(tp);
|
||||
if (!(hp.type & HOOK_ENGINE)) hookCodes[tp.addr] = S(Util::GenerateCode(hp, tp.processId));
|
||||
}
|
||||
HookParam hp = Host::GetThread(tp).hp;
|
||||
if (!(hp.type & HOOK_ENGINE)) hookCodes[tp.addr] = S(Util::GenerateCode(hp, tp.processId));
|
||||
}
|
||||
auto hookInfo = QStringList() << S(processName.value()) << hookCodes.values();
|
||||
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)));
|
||||
QTextFile(HOOK_SAVE_FILE, QIODevice::WriteOnly | QIODevice::Append).write((hookInfo.join(" , ") + "\n").toUtf8());
|
||||
}
|
||||
auto hookInfo = QStringList() << S(processName.value()) << hookCodes.values();
|
||||
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::GetThread(tp).hp, tp.processId)));
|
||||
QTextFile(HOOK_SAVE_FILE, QIODevice::WriteOnly | QIODevice::Append).write((hookInfo.join(" , ") + "\n").toUtf8());
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
std::lock_guard l(m);
|
||||
static std::unordered_map<int64_t, std::wstring> queuedWritesByHandle;
|
||||
int64_t textHandle = sentenceInfo["text handle"];
|
||||
int64_t textHandle = sentenceInfo["text number"];
|
||||
|
||||
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;
|
||||
sentence += queuedWritesByHandle[textHandle];
|
||||
queuedWritesByHandle[textHandle].clear();
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user