From ce225fd9007e591a67c43f522cc9e3c0781fda9c Mon Sep 17 00:00:00 2001 From: Akash Mozumdar Date: Thu, 1 Nov 2018 14:07:42 -0400 Subject: [PATCH] big refactor. move extension internals into unnamed namespace. use mainwindow instead of dialog for extension window. and other renames/bugfixes --- GUI/CMakeLists.txt | 2 +- GUI/extendialog.cpp | 117 ---------------------- GUI/extendialog.h | 70 ------------- GUI/extenwindow.cpp | 130 +++++++++++++++++++++++++ GUI/extenwindow.h | 36 +++++++ GUI/{extendialog.ui => extenwindow.ui} | 21 +--- GUI/mainwindow.cpp | 13 ++- GUI/mainwindow.h | 5 +- GUI/qtcommon.h | 2 + GUI/tests.cpp | 1 - 10 files changed, 181 insertions(+), 216 deletions(-) delete mode 100644 GUI/extendialog.cpp delete mode 100644 GUI/extendialog.h create mode 100644 GUI/extenwindow.cpp create mode 100644 GUI/extenwindow.h rename GUI/{extendialog.ui => extenwindow.ui} (74%) diff --git a/GUI/CMakeLists.txt b/GUI/CMakeLists.txt index 476f311..25048a7 100644 --- a/GUI/CMakeLists.txt +++ b/GUI/CMakeLists.txt @@ -9,7 +9,7 @@ set(gui_SRCS main.cpp mainwindow.cpp misc.cpp - extendialog.cpp + extenwindow.cpp tests.cpp host/host.cc host/textthread.cc diff --git a/GUI/extendialog.cpp b/GUI/extendialog.cpp deleted file mode 100644 index fe28cd6..0000000 --- a/GUI/extendialog.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include "extendialog.h" -#include "ui_extendialog.h" -#include "types.h" -#include - -ListRearrangeFilter::ListRearrangeFilter(QWidget* parent) : QObject(parent) {} - -bool ListRearrangeFilter::eventFilter(QObject*, QEvent* event) -{ - if (event->type() == QEvent::ChildRemoved) emit SigRearranged(); - return false; -} - -ExtenDialog::ExtenDialog(QWidget* parent) : - QDialog(parent), - ui(new Ui::ExtenDialog), - filter(new ListRearrangeFilter(this)) -{ - ui->setupUi(this); - - extenList = findChild("extenList"); - extenList->installEventFilter(filter); - connect(filter, &ListRearrangeFilter::SigRearranged, this, &ExtenDialog::Rearrange); - - if (extensions.empty()) - { - extenSaveFile.open(QIODevice::ReadOnly); - for (auto extenName : QString(extenSaveFile.readAll()).split(">")) Load(extenName); - extenSaveFile.close(); - } - - for (auto extension : extensions) - extenList->addItem(extension.name); -} - -ExtenDialog::~ExtenDialog() -{ - delete ui; -} - -bool ExtenDialog::DispatchSentenceToExtensions(std::wstring& sentence, std::unordered_map miscInfo) -{ - bool success = true; - wchar_t* sentenceBuffer = (wchar_t*)HeapAlloc(GetProcessHeap(), 0, (sentence.size() + 1) * sizeof(wchar_t)); - wcscpy_s(sentenceBuffer, sentence.size() + 1, sentence.c_str()); - - InfoForExtension miscInfoLinkedList{ "", 0, nullptr }; - InfoForExtension* miscInfoTraverser = &miscInfoLinkedList; - for (auto& i : miscInfo) miscInfoTraverser = miscInfoTraverser->next = new InfoForExtension{ i.first.c_str(), i.second, nullptr }; - - std::shared_lock sharedLock(extenMutex); - for (auto extension : extensions) - { - wchar_t* nextBuffer = extension.callback(sentenceBuffer, &miscInfoLinkedList); - if (nextBuffer == nullptr) { success = false; break; } - if (nextBuffer != sentenceBuffer) HeapFree(GetProcessHeap(), 0, sentenceBuffer); - sentenceBuffer = nextBuffer; - } - sentence = std::wstring(sentenceBuffer); - - HeapFree(GetProcessHeap(), 0, sentenceBuffer); - return success; -} - -void ExtenDialog::Load(QString extenName) -{ - // Extension is dll and exports "OnNewSentence" - HMODULE module = GetModuleHandleW(extenName.toStdWString().c_str()); - if (!module) module = LoadLibraryW(extenName.toStdWString().c_str()); - if (!module) return; - FARPROC callback = GetProcAddress(module, "OnNewSentence"); - if (!callback) return; - extensions.push_back({ extenName, (wchar_t*(*)(const wchar_t*, const InfoForExtension*))callback }); -} - -void ExtenDialog::Unload(QString extenName) -{ - extensions.erase(std::remove_if(extensions.begin(), extensions.end(), [&](Extension extension) { return extension.name == extenName; }), extensions.end()); - FreeLibrary(GetModuleHandleW(extenName.toStdWString().c_str())); -} - -void ExtenDialog::on_addButton_clicked() -{ - QString extenFileName = QFileDialog::getOpenFileName(this, "Select Extension", "C:\\", "Extensions (*.dll)"); - if (!extenFileName.size()) return; - QString extenName = extenFileName.mid(extenFileName.lastIndexOf("/") + 1); - QFile::copy(extenFileName, extenName); - Load(extenName.left(extenName.lastIndexOf(".dll"))); - Sync(); -} - -void ExtenDialog::on_rmvButton_clicked() -{ - for (auto extenName : extenList->selectedItems()) Unload(extenName->text()); - Sync(); -} - -void ExtenDialog::Rearrange() -{ - QVector newExtensions; - for (int i = 0; i < extenList->count(); ++i) - newExtensions.push_back(*std::find_if(extensions.begin(), extensions.end(), [=](Extension extension) { return extension.name == extenList->item(i)->text(); })); - extensions = newExtensions; - Sync(); -} - -void ExtenDialog::Sync() -{ - extenList->clear(); - extenSaveFile.open(QIODevice::WriteOnly | QIODevice::Truncate); - for (auto extension : extensions) - { - extenList->addItem(extension.name); - extenSaveFile.write((extension.name + ">").toUtf8()); - } - extenSaveFile.close(); -} diff --git a/GUI/extendialog.h b/GUI/extendialog.h deleted file mode 100644 index 2ad0c0e..0000000 --- a/GUI/extendialog.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef EXTENSIONS_H -#define EXTENSIONS_H - -#include "qtcommon.h" -#include -#include -#include -#include - -namespace Ui -{ - class ExtenDialog; -} - -class ListRearrangeFilter : public QObject -{ - Q_OBJECT - -public: - explicit ListRearrangeFilter(QWidget* parent = nullptr); - -protected: - bool eventFilter(QObject*, QEvent* event); - -signals: - void SigRearranged(); -}; - -class ExtenDialog : public QDialog -{ - Q_OBJECT - -public: - explicit ExtenDialog(QWidget* parent = nullptr); - ~ExtenDialog(); - static bool DispatchSentenceToExtensions(std::wstring& sentence, std::unordered_map miscInfo); - -private slots: - void on_addButton_clicked(); - void on_rmvButton_clicked(); - void Rearrange(); - -private: - struct InfoForExtension - { - const char* name; - int64_t value; - InfoForExtension* next; - ~InfoForExtension() { if (next) delete next; }; - }; - struct Extension - { - QString name; - wchar_t*(*callback)(const wchar_t*, const InfoForExtension*); - }; - inline static std::shared_mutex extenMutex; - inline static QVector extensions; - - static void Load(QString extenName); - static void Unload(QString extenName); - - void Sync(); - - Ui::ExtenDialog* ui; - QFile extenSaveFile = QFile("Extensions.txt"); - QListWidget* extenList; - ListRearrangeFilter* filter; -}; - -#endif // EXTENSIONS_H diff --git a/GUI/extenwindow.cpp b/GUI/extenwindow.cpp new file mode 100644 index 0000000..34cb6b1 --- /dev/null +++ b/GUI/extenwindow.cpp @@ -0,0 +1,130 @@ +#include "extenwindow.h" +#include "ui_extenwindow.h" +#include "types.h" +#include + +namespace +{ + struct InfoForExtension + { + const char* name; + int64_t value; + InfoForExtension* next; + ~InfoForExtension() { if (next) delete next; }; + }; + + struct Extension + { + QString name; + wchar_t*(*callback)(const wchar_t*, const InfoForExtension*); + }; + + std::shared_mutex extenMutex; + QVector extensions; + + void Load(QString extenName) + { + // Extension is dll and exports "OnNewSentence" + HMODULE module = GetModuleHandleW(extenName.toStdWString().c_str()); + if (!module) module = LoadLibraryW(extenName.toStdWString().c_str()); + if (!module) return; + FARPROC callback = GetProcAddress(module, "OnNewSentence"); + if (!callback) return; + extensions.push_back({ extenName, (wchar_t*(*)(const wchar_t*, const InfoForExtension*))callback }); + } + + void Unload(QString extenName) + { + extensions.erase(std::remove_if(extensions.begin(), extensions.end(), [&](Extension extension) { return extension.name == extenName; }), extensions.end()); + FreeLibrary(GetModuleHandleW(extenName.toStdWString().c_str())); + } +} + +bool DispatchSentenceToExtensions(std::wstring& sentence, std::unordered_map miscInfo) +{ + bool success = true; + wchar_t* sentenceBuffer = (wchar_t*)HeapAlloc(GetProcessHeap(), 0, (sentence.size() + 1) * sizeof(wchar_t)); + wcscpy_s(sentenceBuffer, sentence.size() + 1, sentence.c_str()); + + InfoForExtension miscInfoLinkedList{ "", 0, nullptr }; + InfoForExtension* miscInfoTraverser = &miscInfoLinkedList; + for (auto& i : miscInfo) miscInfoTraverser = miscInfoTraverser->next = new InfoForExtension{ i.first.c_str(), i.second, nullptr }; + + std::shared_lock sharedLock(extenMutex); + for (auto extension : extensions) + { + wchar_t* nextBuffer = extension.callback(sentenceBuffer, &miscInfoLinkedList); + if (nextBuffer == nullptr) { success = false; break; } + if (nextBuffer != sentenceBuffer) HeapFree(GetProcessHeap(), 0, sentenceBuffer); + sentenceBuffer = nextBuffer; + } + sentence = std::wstring(sentenceBuffer); + + HeapFree(GetProcessHeap(), 0, sentenceBuffer); + return success; +} + +ExtenWindow::ExtenWindow(QWidget* parent) : + QMainWindow(parent), + ui(new Ui::ExtenWindow) +{ + ui->setupUi(this); + + extenList = findChild("extenList"); + extenList->installEventFilter(this); + + if (extensions.empty()) + { + extenSaveFile.open(QIODevice::ReadOnly); + for (auto extenName : QString(extenSaveFile.readAll()).split(">")) Load(extenName); + extenSaveFile.close(); + } + Sync(); +} + +ExtenWindow::~ExtenWindow() +{ + delete ui; +} + +void ExtenWindow::on_addButton_clicked() +{ + QString extenFileName = QFileDialog::getOpenFileName(this, "Select Extension", "C:\\", "Extensions (*.dll)"); + if (!extenFileName.size()) return; + QString extenName = extenFileName.mid(extenFileName.lastIndexOf("/") + 1); + QFile::copy(extenFileName, extenName); + Load(extenName.left(extenName.lastIndexOf(".dll"))); + Sync(); +} + +void ExtenWindow::on_rmvButton_clicked() +{ + if (auto extenName = extenList->currentItem()) Unload(extenName->text()); + Sync(); +} + +bool ExtenWindow::eventFilter(QObject* target, QEvent* event) +{ + // See https://stackoverflow.com/questions/1224432/how-do-i-respond-to-an-internal-drag-and-drop-operation-using-a-qlistwidget/1528215 + if (event->type() == QEvent::ChildRemoved) + { + QVector newExtensions; + for (int i = 0; i < extenList->count(); ++i) + newExtensions.push_back(*std::find_if(extensions.begin(), extensions.end(), [=](Extension extension) { return extension.name == extenList->item(i)->text(); })); + extensions = newExtensions; + Sync(); + } + return false; +} + +void ExtenWindow::Sync() +{ + extenList->clear(); + extenSaveFile.open(QIODevice::WriteOnly | QIODevice::Truncate); + for (auto extension : extensions) + { + extenList->addItem(extension.name); + extenSaveFile.write((extension.name + ">").toUtf8()); + } + extenSaveFile.close(); +} diff --git a/GUI/extenwindow.h b/GUI/extenwindow.h new file mode 100644 index 0000000..576de31 --- /dev/null +++ b/GUI/extenwindow.h @@ -0,0 +1,36 @@ +#ifndef EXTENSIONS_H +#define EXTENSIONS_H + +#include "qtcommon.h" +#include +#include + +namespace Ui +{ + class ExtenWindow; +} + +bool DispatchSentenceToExtensions(std::wstring& sentence, std::unordered_map miscInfo); + +class ExtenWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit ExtenWindow(QWidget* parent = nullptr); + ~ExtenWindow(); + +private slots: + void on_addButton_clicked(); + void on_rmvButton_clicked(); + +private: + bool eventFilter(QObject* target, QEvent* event); + void Sync(); + + Ui::ExtenWindow* ui; + QFile extenSaveFile = QFile("Extensions.txt"); + QListWidget* extenList; +}; + +#endif // EXTENSIONS_H diff --git a/GUI/extendialog.ui b/GUI/extenwindow.ui similarity index 74% rename from GUI/extendialog.ui rename to GUI/extenwindow.ui index 31d3257..8a945ae 100644 --- a/GUI/extendialog.ui +++ b/GUI/extenwindow.ui @@ -1,7 +1,7 @@ - ExtenDialog - + ExtenWindow + 0 @@ -13,6 +13,7 @@ Extensions + @@ -22,9 +23,6 @@ Qt::MoveAction - - QAbstractItemView::MultiSelection - @@ -34,12 +32,6 @@ Qt::Vertical - - - 20 - 40 - - @@ -61,17 +53,12 @@ Qt::Vertical - - - 20 - 40 - - + diff --git a/GUI/mainwindow.cpp b/GUI/mainwindow.cpp index 15912f6..b4aea98 100644 --- a/GUI/mainwindow.cpp +++ b/GUI/mainwindow.cpp @@ -1,16 +1,14 @@ #include "mainwindow.h" #include "ui_mainwindow.h" #include "defs.h" -#include "extendialog.h" +#include "extenwindow.h" #include "misc.h" -#include #include -#include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), - extenDialog(new ExtenDialog(this)) + extenWindow(new ExtenWindow) { ui->setupUi(this); @@ -108,7 +106,7 @@ void MainWindow::ThreadOutput(QString threadString, QString output) bool MainWindow::ProcessThreadOutput(TextThread* thread, std::wstring& output) { - if (ExtenDialog::DispatchSentenceToExtensions(output, GetInfoForExtensions(thread))) + if (DispatchSentenceToExtensions(output, GetMiscInfo(thread))) { output += L"\r\n"; emit SigThreadOutput(TextThreadString(thread), QString::fromStdWString(output)); @@ -140,7 +138,7 @@ DWORD MainWindow::GetSelectedProcessId() return processCombo->currentText().split(":")[0].toULong(nullptr, 16); } -std::unordered_map MainWindow::GetInfoForExtensions(TextThread* thread) +std::unordered_map MainWindow::GetMiscInfo(TextThread* thread) { return { @@ -235,5 +233,6 @@ void MainWindow::on_ttCombo_activated(int index) void MainWindow::on_addExtenButton_clicked() { - extenDialog->show(); + extenWindow->activateWindow(); + extenWindow->showNormal(); } diff --git a/GUI/mainwindow.h b/GUI/mainwindow.h index c312a38..fc6f234 100644 --- a/GUI/mainwindow.h +++ b/GUI/mainwindow.h @@ -3,7 +3,6 @@ #include "qtcommon.h" #include "host/host.h" -#include #include #include #include @@ -49,7 +48,7 @@ private: QString TextThreadString(TextThread* thread); ThreadParam ParseTextThreadString(QString textThreadString); DWORD GetSelectedProcessId(); - std::unordered_map GetInfoForExtensions(TextThread* thread); + std::unordered_map GetMiscInfo(TextThread* thread); QVector GetAllHooks(DWORD processId); Ui::MainWindow* ui; @@ -58,7 +57,7 @@ private: QComboBox* ttCombo; QComboBox* extenCombo; QPlainTextEdit* textOutput; - QWidget* extenDialog; + QWidget* extenWindow; }; #endif // MAINWINDOW_H diff --git a/GUI/qtcommon.h b/GUI/qtcommon.h index 07fc0db..46029ba 100644 --- a/GUI/qtcommon.h +++ b/GUI/qtcommon.h @@ -3,4 +3,6 @@ #include "common.h" #include #include +#include +#include #include diff --git a/GUI/tests.cpp b/GUI/tests.cpp index 35ae875..0ae4dc0 100644 --- a/GUI/tests.cpp +++ b/GUI/tests.cpp @@ -1,4 +1,3 @@ -#include "extendialog.h" #include "misc.h" static int TESTS = []