From fb9fb5d54a67cb456212454cde6b994e60b70433 Mon Sep 17 00:00:00 2001 From: Akash Mozumdar Date: Wed, 18 Aug 2021 00:22:23 -0600 Subject: [PATCH] add universal links to thread linker --- GUI/mainwindow.cpp | 5 +++- extensions/regexfilter.cpp | 2 +- extensions/threadlinker.cpp | 50 ++++++++++++++++++------------------- extensions/threadlinker.ui | 47 ++++++++++++++++++++++++++++++++++ text.cpp | 2 +- 5 files changed, 78 insertions(+), 28 deletions(-) create mode 100644 extensions/threadlinker.ui diff --git a/GUI/mainwindow.cpp b/GUI/mainwindow.cpp index ffff064..1f0437d 100644 --- a/GUI/mainwindow.cpp +++ b/GUI/mainwindow.cpp @@ -105,7 +105,7 @@ namespace return { threadParam[1].toUInt(nullptr, 16), threadParam[2].toULongLong(nullptr, 16), threadParam[3].toULongLong(nullptr, 16), threadParam[4].toULongLong(nullptr, 16) }; } - std::array GetSentenceInfo(TextThread& thread) + std::array GetSentenceInfo(TextThread& thread) { void (*AddText)(int64_t, const wchar_t*) = [](int64_t number, const wchar_t* text) { @@ -126,6 +126,9 @@ namespace { "hook address", (int64_t)thread.tp.addr }, { "text handle", thread.handle }, { "text name", (int64_t)thread.name.c_str() }, + { "add sentence", (int64_t)AddSentence }, + { "add text", (int64_t)AddText }, + { "get selected process id", (int64_t)GetSelectedProcessId }, { "void (*AddSentence)(int64_t number, const wchar_t* sentence)", (int64_t)AddSentence }, { "void (*AddText)(int64_t number, const wchar_t* text)", (int64_t)AddText }, { "DWORD (*GetSelectedProcessId)()", (int64_t)GetSelectedProcessId }, diff --git a/extensions/regexfilter.cpp b/extensions/regexfilter.cpp index 2ba237b..682e3e7 100644 --- a/extensions/regexfilter.cpp +++ b/extensions/regexfilter.cpp @@ -56,7 +56,7 @@ private: bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo) { - static auto _ = GetSelectedProcessId = (DWORD(*)())sentenceInfo["DWORD (*GetSelectedProcessId)()"]; + static auto _ = GetSelectedProcessId = (DWORD(*)())sentenceInfo["get selected process id"]; if (sentenceInfo["text number"] == 0) return false; if (/*sentenceInfo["current select"] && */!regex) if (auto processName = GetModuleFilename(sentenceInfo["process id"])) { diff --git a/extensions/threadlinker.cpp b/extensions/threadlinker.cpp index 0fc5230..6b5a167 100644 --- a/extensions/threadlinker.cpp +++ b/extensions/threadlinker.cpp @@ -1,5 +1,6 @@ #include "qtcommon.h" #include "extension.h" +#include "ui_threadlinker.h" #include extern const char* THREAD_LINKER; @@ -9,7 +10,9 @@ extern const char* THREAD_LINK_FROM; extern const char* THREAD_LINK_TO; extern const char* HEXADECIMAL; -std::unordered_map> linkedTextHandles; +std::unordered_map> links; +std::unordered_set universalLinks, empty; +bool separateSentences = true; // allow user to change? concurrency::reader_writer_lock m; class Window : public QDialog, Localizer @@ -17,15 +20,11 @@ class Window : public QDialog, Localizer public: Window() : QDialog(nullptr, Qt::WindowMinMaxButtonsHint) { - connect(&linkButton, &QPushButton::clicked, this, &Window::Link); - connect(&unlinkButton, &QPushButton::clicked, this, &Window::Unlink); - - layout.addWidget(&linkList); - layout.addLayout(&buttons); - buttons.addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding)); - buttons.addWidget(&linkButton); - buttons.addWidget(&unlinkButton); - buttons.addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding)); + ui.setupUi(this); + ui.linkButton->setText(LINK); + ui.unlinkButton->setText(UNLINK); + connect(ui.linkButton, &QPushButton::clicked, this, &Window::Link); + connect(ui.unlinkButton, &QPushButton::clicked, this, &Window::Unlink); setWindowTitle(THREAD_LINKER); QMetaObject::invokeMethod(this, &QWidget::show, Qt::QueuedConnection); @@ -35,23 +34,25 @@ private: void Link() { bool ok1, ok2, ok3, ok4; - int from = QInputDialog::getText(this, THREAD_LINK_FROM, HEXADECIMAL, QLineEdit::Normal, "", &ok1, Qt::WindowCloseButtonHint).toInt(&ok2, 16); - int to = QInputDialog::getText(this, THREAD_LINK_TO, HEXADECIMAL, QLineEdit::Normal, "", &ok3, Qt::WindowCloseButtonHint).toInt(&ok4, 16); - if (ok1 && ok2 && ok3 && ok4) + QString fromInput = QInputDialog::getText(this, THREAD_LINK_FROM, HEXADECIMAL, QLineEdit::Normal, "X", &ok1, Qt::WindowCloseButtonHint); + int from = fromInput.toInt(&ok2, 16), + to = QInputDialog::getText(this, THREAD_LINK_TO, HEXADECIMAL, QLineEdit::Normal, "", &ok3, Qt::WindowCloseButtonHint).toInt(&ok4, 16); + if (ok1 && (ok2 || fromInput == "X") && ok3 && ok4) { std::scoped_lock lock(m); - if (linkedTextHandles[from].insert(to).second) linkList.addItem(QString::number(from, 16) + "->" + QString::number(to, 16)); + if ((ok2 ? links[from] : universalLinks).insert(to).second) + ui.linkList->addItem((ok2 ? QString::number(from, 16) : "X") + "->" + QString::number(to, 16)); } } void Unlink() { - if (linkList.currentItem()) + if (ui.linkList->currentItem()) { - QStringList link = linkList.currentItem()->text().split("->"); - linkList.takeItem(linkList.currentRow()); + QStringList link = ui.linkList->currentItem()->text().split("->"); + ui.linkList->takeItem(ui.linkList->currentRow()); std::scoped_lock lock(m); - linkedTextHandles[link[0].toInt(nullptr, 16)].erase(link[1].toInt(nullptr, 16)); + (link[0] == "X" ? universalLinks : links[link[0].toInt(nullptr, 16)]).erase(link[1].toInt(nullptr, 16)); } } @@ -60,17 +61,16 @@ private: if (event->key() == Qt::Key_Delete) Unlink(); } - QHBoxLayout layout{ this }; - QVBoxLayout buttons; - QListWidget linkList{ this }; - QPushButton linkButton{ LINK, this }, unlinkButton{ UNLINK, this }; + Ui::LinkWindow ui; } window; bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo) { concurrency::reader_writer_lock::scoped_lock_read readLock(m); - auto links = linkedTextHandles.find(sentenceInfo["text number"]); - if (links != linkedTextHandles.end()) for (auto link : links->second) - ((void(*)(int64_t, const wchar_t*))sentenceInfo["void (*AddText)(int64_t number, const wchar_t* text)"])(link, sentence.c_str()); + auto action = separateSentences ? sentenceInfo["add sentence"] : sentenceInfo["add text"]; + auto it = links.find(sentenceInfo["text number"]); + for (const auto& linkSet : { it != links.end() ? it->second : empty, universalLinks }) + for (auto link : linkSet) + ((void(*)(int64_t, const wchar_t*))action)(link, sentence.c_str()); return false; } diff --git a/extensions/threadlinker.ui b/extensions/threadlinker.ui new file mode 100644 index 0000000..1247c63 --- /dev/null +++ b/extensions/threadlinker.ui @@ -0,0 +1,47 @@ + + + LinkWindow + + + + 0 + 0 + 400 + 300 + + + + + + + + + + + + Qt::Vertical + + + + + + + + + + + + + + + Qt::Vertical + + + + + + + + + + diff --git a/text.cpp b/text.cpp index c624979..6b83176 100644 --- a/text.cpp +++ b/text.cpp @@ -222,7 +222,7 @@ This file must be encoded in Unicode (UTF-16 Little Endian).)"; const char* THREAD_LINKER = u8"Thread Linker"; const char* LINK = u8"Link"; const char* UNLINK = u8"Unlink"; -const char* THREAD_LINK_FROM = u8"Thread number to link from"; +const char* THREAD_LINK_FROM = u8"Thread number to link from (or X to link from all threads)"; const char* THREAD_LINK_TO = u8"Thread number to link to"; const char* HEXADECIMAL = u8"Hexadecimal";