refactor extensions some and let user rearrange them

This commit is contained in:
Akash Mozumdar 2018-10-28 02:27:24 -04:00
parent 1e2f6e14ec
commit 3a3bdfd48e
7 changed files with 130 additions and 65 deletions

View File

@ -1,34 +1,46 @@
#include "extensions.h" #include "extensions.h"
#include <shared_mutex>
#include <QDir>
std::optional<Extension> LoadExtension(QString file) static std::optional<Extension> LoadExtension(QString extenName)
{ {
// Extension file format: {NUMBER}_{NAME}.dll and exports "OnNewSentence" // Extension is dll and exports "OnNewSentence"
QRegularExpressionMatch parsedFile = QRegularExpression("^(\\d+)_(.+).dll$").match(file); HMODULE module = GetModuleHandleW(extenName.toStdWString().c_str());
if (!parsedFile.hasMatch()) return {}; if (!module) module = LoadLibraryW(extenName.toStdWString().c_str());
HMODULE module = GetModuleHandleW(file.toStdWString().c_str());
if (!module) module = LoadLibraryW(file.toStdWString().c_str());
if (!module) return {}; if (!module) return {};
FARPROC callback = GetProcAddress(module, "OnNewSentence"); FARPROC callback = GetProcAddress(module, "OnNewSentence");
if (!callback) return {}; if (!callback) return {};
return Extension{ parsedFile.captured(1).toInt(), parsedFile.captured(2), (wchar_t*(*)(const wchar_t*, const InfoForExtension*))callback }; return Extension{ extenName, (wchar_t*(*)(const wchar_t*, const InfoForExtension*))callback };
} }
std::shared_mutex extenMutex; void Extension::Load(QString extenName)
std::set<Extension> extensions;
std::set<Extension> LoadExtensions()
{ {
std::set<Extension> newExtensions;
QStringList files = QDir().entryList();
for (auto file : files)
if (auto extension = LoadExtension(file)) newExtensions.insert(extension.value());
std::unique_lock<std::shared_mutex> extenLock(extenMutex); std::unique_lock<std::shared_mutex> extenLock(extenMutex);
return extensions = newExtensions; if (auto extension = LoadExtension(extenName)) extensions.push_back(extension.value());
} }
bool DispatchSentenceToExtensions(std::wstring& sentence, std::unordered_map<std::string, int64_t> miscInfo) void Extension::SendToBack(QString extenName)
{
std::unique_lock<std::shared_mutex> extenLock(extenMutex);
Extension* extenIter = std::find_if(extensions.begin(), extensions.end(), [&](Extension extension) { return extension.name == extenName; });
Extension extension = *extenIter;
extensions.erase(extenIter);
extensions.push_back(extension);
}
void Extension::Unload(QString extenName)
{
std::unique_lock<std::shared_mutex> extenLock(extenMutex);
extensions.erase(std::find_if(extensions.begin(), extensions.end(), [&](Extension extension) { return extension.name == extenName; }));
FreeLibrary(GetModuleHandleW(extenName.toStdWString().c_str()));
}
QVector<QString> Extension::GetNames()
{
QVector<QString> ret;
for (auto extension : extensions) ret.push_back(extension.name);
return ret;
}
bool Extension::DispatchSentence(std::wstring& sentence, std::unordered_map<std::string, int64_t> miscInfo)
{ {
bool success = true; bool success = true;
wchar_t* sentenceBuffer = (wchar_t*)HeapAlloc(GetProcessHeap(), 0, (sentence.size() + 1) * sizeof(wchar_t)); wchar_t* sentenceBuffer = (wchar_t*)HeapAlloc(GetProcessHeap(), 0, (sentence.size() + 1) * sizeof(wchar_t));
@ -51,16 +63,3 @@ bool DispatchSentenceToExtensions(std::wstring& sentence, std::unordered_map<std
HeapFree(GetProcessHeap(), 0, sentenceBuffer); HeapFree(GetProcessHeap(), 0, sentenceBuffer);
return success; return success;
} }
void UnloadExtension(int extenNumber)
{
std::unique_lock<std::shared_mutex> extenLock(extenMutex);
if (extensions.find({ extenNumber }) == extensions.end()) return;
QString extenFileName = QString::number(extenNumber) + "_" + extensions.find({ extenNumber })->name + ".dll";
FreeLibrary(GetModuleHandleW(extenFileName.toStdWString().c_str()));
QString removedFileName = extenFileName;
removedFileName.remove(0, removedFileName.indexOf("_"));
QFile::remove(removedFileName);
if (!QFile::rename(extenFileName, removedFileName)) QFile::remove(extenFileName);
extensions.erase(extensions.find({ extenNumber }));
}

View File

@ -2,7 +2,7 @@
#define EXTENSIONS_H #define EXTENSIONS_H
#include "qtcommon.h" #include "qtcommon.h"
#include <set> #include <shared_mutex>
struct InfoForExtension struct InfoForExtension
{ {
@ -12,16 +12,21 @@ struct InfoForExtension
~InfoForExtension() { if (next) delete next; }; ~InfoForExtension() { if (next) delete next; };
}; };
struct Extension class Extension
{ {
int number; public:
static bool DispatchSentence(std::wstring& sentence, std::unordered_map<std::string, int64_t> miscInfo);
static void Load(QString extenName);
static void SendToBack(QString extenName);
static void Unload(QString extenName);
static QVector<QString> GetNames();
QString name; QString name;
wchar_t*(*callback)(const wchar_t*, const InfoForExtension*); wchar_t* (*callback)(const wchar_t*, const InfoForExtension*);
bool operator<(const Extension& other) const { return number < other.number; }
private:
inline static std::shared_mutex extenMutex;
inline static QVector<Extension> extensions;
}; };
std::set<Extension> LoadExtensions();
bool DispatchSentenceToExtensions(std::wstring& sentence, std::unordered_map<std::string, int64_t> miscInfo);
void UnloadExtension(int extenNumber);
#endif // EXTENSIONS_H #endif // EXTENSIONS_H

View File

@ -11,24 +11,36 @@ MainWindow::MainWindow(QWidget *parent) :
ui(new Ui::MainWindow) ui(new Ui::MainWindow)
{ {
ui->setupUi(this); ui->setupUi(this);
if (settings.contains("Window")) this->setGeometry(settings.value("Window").toRect());
// TODO: add GUI for changing these
if (settings.contains("Flush_Delay")) TextThread::flushDelay = settings.value("Flush_Delay").toInt();
if (settings.contains("Max_Buffer_Size")) TextThread::maxBufferSize = settings.value("Max_Buffer_Size").toInt();
processCombo = findChild<QComboBox*>("processCombo"); processCombo = findChild<QComboBox*>("processCombo");
ttCombo = findChild<QComboBox*>("ttCombo"); ttCombo = findChild<QComboBox*>("ttCombo");
extenCombo = findChild<QComboBox*>("extenCombo"); extenCombo = findChild<QComboBox*>("extenCombo");
textOutput = findChild<QPlainTextEdit*>("textOutput"); textOutput = findChild<QPlainTextEdit*>("textOutput");
QFile extenSaveFile("Extensions.txt");
if (extenSaveFile.exists())
{
extenSaveFile.open(QIODevice::ReadOnly);
for (auto extenName : QString(extenSaveFile.readAll()).split(">")) Extension::Load(extenName);
}
else
{
for (auto file : QDir().entryList())
if (file.endsWith(".dll") && file != "vnrhook.dll") Extension::Load(file.left(file.lastIndexOf(".dll")));
}
ReloadExtensions();
if (settings.contains("Window")) this->setGeometry(settings.value("Window").toRect());
// TODO: add GUI for changing these
if (settings.contains("Flush_Delay")) TextThread::flushDelay = settings.value("Flush_Delay").toInt();
if (settings.contains("Max_Buffer_Size")) TextThread::maxBufferSize = settings.value("Max_Buffer_Size").toInt();
connect(this, &MainWindow::SigAddProcess, this, &MainWindow::AddProcess); connect(this, &MainWindow::SigAddProcess, this, &MainWindow::AddProcess);
connect(this, &MainWindow::SigRemoveProcess, this, &MainWindow::RemoveProcess); connect(this, &MainWindow::SigRemoveProcess, this, &MainWindow::RemoveProcess);
connect(this, &MainWindow::SigAddThread, this, &MainWindow::AddThread); connect(this, &MainWindow::SigAddThread, this, &MainWindow::AddThread);
connect(this, &MainWindow::SigRemoveThread, this, &MainWindow::RemoveThread); connect(this, &MainWindow::SigRemoveThread, this, &MainWindow::RemoveThread);
connect(this, &MainWindow::SigThreadOutput, this, &MainWindow::ThreadOutput); connect(this, &MainWindow::SigThreadOutput, this, &MainWindow::ThreadOutput);
ReloadExtensions();
Host::Start( Host::Start(
[&](DWORD processId) { emit SigAddProcess(processId); }, [&](DWORD processId) { emit SigAddProcess(processId); },
[&](DWORD processId) { emit SigRemoveProcess(processId); }, [&](DWORD processId) { emit SigRemoveProcess(processId); },
@ -53,7 +65,7 @@ void MainWindow::AddProcess(unsigned processId)
{ {
processCombo->addItem(QString::number(processId, 16).toUpper() + ": " + GetModuleName(processId)); processCombo->addItem(QString::number(processId, 16).toUpper() + ": " + GetModuleName(processId));
QFile file("SavedHooks.txt"); QFile file("SavedHooks.txt");
if (!file.open(QIODevice::ReadOnly)) return; file.open(QIODevice::ReadOnly);
QString processName = GetFullModuleName(processId); QString processName = GetFullModuleName(processId);
QStringList allProcesses = QString(file.readAll()).split("\r", QString::SkipEmptyParts); QStringList allProcesses = QString(file.readAll()).split("\r", QString::SkipEmptyParts);
for (auto hooks = allProcesses.rbegin(); hooks != allProcesses.rend(); ++hooks) for (auto hooks = allProcesses.rbegin(); hooks != allProcesses.rend(); ++hooks)
@ -105,7 +117,7 @@ void MainWindow::ThreadOutput(TextThread* thread, QString output)
bool MainWindow::ProcessThreadOutput(TextThread* thread, std::wstring& output) bool MainWindow::ProcessThreadOutput(TextThread* thread, std::wstring& output)
{ {
if (DispatchSentenceToExtensions(output, GetInfoForExtensions(thread))) if (Extension::DispatchSentence(output, GetInfoForExtensions(thread)))
{ {
output += L"\r\n"; output += L"\r\n";
emit SigThreadOutput(thread, QString::fromStdWString(output)); emit SigThreadOutput(thread, QString::fromStdWString(output));
@ -140,7 +152,13 @@ DWORD MainWindow::GetSelectedProcessId()
void MainWindow::ReloadExtensions() void MainWindow::ReloadExtensions()
{ {
extenCombo->clear(); extenCombo->clear();
for (auto extension : LoadExtensions()) extenCombo->addItem(QString::number(extension.number) + ": " + extension.name); QFile extenSaveFile("Extensions.txt");
extenSaveFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
for (auto extenName : Extension::GetNames())
{
extenSaveFile.write((extenName + ">").toUtf8());
extenCombo->addItem(extenName);
}
} }
std::unordered_map<std::string, int64_t> MainWindow::GetInfoForExtensions(TextThread* thread) std::unordered_map<std::string, int64_t> MainWindow::GetInfoForExtensions(TextThread* thread)
@ -226,7 +244,7 @@ void MainWindow::on_saveButton_clicked()
if (!(hook.type & HOOK_ENGINE)) if (!(hook.type & HOOK_ENGINE))
hookList += " , " + GenerateCode(hook, GetSelectedProcessId()); hookList += " , " + GenerateCode(hook, GetSelectedProcessId());
QFile file("SavedHooks.txt"); QFile file("SavedHooks.txt");
if (!file.open(QIODevice::Append | QIODevice::Text)) return; file.open(QIODevice::Append);
file.write((hookList + "\r\n").toUtf8()); file.write((hookList + "\r\n").toUtf8());
} }
@ -238,17 +256,25 @@ void MainWindow::on_ttCombo_activated(int index)
void MainWindow::on_addExtenButton_clicked() void MainWindow::on_addExtenButton_clicked()
{ {
QString extenFileName = QFileDialog::getOpenFileName(this, "Select Extension dll", "C:\\", "Extensions (*.dll)"); QString extenFileName = QFileDialog::getOpenFileName(this, "Select Extension", "C:\\", "Extensions (*.dll)");
if (!extenFileName.size()) return; if (!extenFileName.size()) return;
QString extenName = extenFileName.split("/")[extenFileName.split("/").count() - 1]; QString extenName = extenFileName.mid(extenFileName.lastIndexOf("/") + 1);
QString copyTo = QString::number(extenCombo->itemText(extenCombo->count() - 1).split(":")[0].toInt() + 1) + "_" + extenName; QFile::copy(extenFileName, extenName);
QFile::copy(extenFileName, copyTo); Extension::Load(extenName.left(extenName.lastIndexOf(".dll")));
ReloadExtensions(); ReloadExtensions();
} }
void MainWindow::on_moveExtenButton_clicked()
{
if (extenCombo->currentText() == "") return;
Extension::SendToBack(extenCombo->currentText());
ReloadExtensions();
Host::AddConsoleOutput(L"extension sent to back");
}
void MainWindow::on_rmvExtenButton_clicked() void MainWindow::on_rmvExtenButton_clicked()
{ {
if (extenCombo->currentText() == "") return; if (extenCombo->currentText() == "") return;
UnloadExtension(extenCombo->currentText().split(":")[0].toInt()); Extension::Unload(extenCombo->currentText());
ReloadExtensions(); ReloadExtensions();
} }

View File

@ -2,11 +2,11 @@
#define MAINWINDOW_H #define MAINWINDOW_H
#include "qtcommon.h" #include "qtcommon.h"
#include "host/host.h"
#include <QMainWindow> #include <QMainWindow>
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <QComboBox> #include <QComboBox>
#include <QSettings> #include <QSettings>
#include "host/host.h"
namespace Ui namespace Ui
{ {
@ -41,6 +41,7 @@ private slots:
void on_hookButton_clicked(); void on_hookButton_clicked();
void on_saveButton_clicked(); void on_saveButton_clicked();
void on_addExtenButton_clicked(); void on_addExtenButton_clicked();
void on_moveExtenButton_clicked();
void on_rmvExtenButton_clicked(); void on_rmvExtenButton_clicked();
private: private:

View File

@ -216,6 +216,13 @@ QPushButton, QComboBox
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="moveExtenButton">
<property name="text">
<string>Move extension</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QPushButton" name="rmvExtenButton"> <widget class="QPushButton" name="rmvExtenButton">
<property name="text"> <property name="text">

View File

@ -1,4 +1,31 @@
cd Builds/RelWithDebInfo/x86; cd Builds/RelWithDebInfo/x86;
Compress-Archive -Force -Path "Textractor.exe","styles","platforms","Qt5Core.dll","Qt5Gui.dll","Qt5Widgets.dll","vnrhook.dll","256_Remove Repetition.dll","512_Copy to Clipboard.dll","1024_Bing Translate.dll","2048_Extra Newlines.dll" -DestinationPath Textractor; Compress-Archive -Force -DestinationPath Textractor -Path @(
"Textractor.exe",
"styles",
"platforms",
"Qt5Core.dll",
"Qt5Gui.dll",
"Qt5Widgets.dll",
"vnrhook.dll",
"Remove Repetition.dll",
"Copy to Clipboard.dll",
"Bing Translate.dll",
"Extra Newlines.dll",
"Extensions.txt"
)
cd ../x64; cd ../x64;
Compress-Archive -Force -Path "Textractor.exe","styles","platforms","Qt5Core.dll","Qt5Gui.dll","Qt5Widgets.dll","vnrhook.dll","256_Remove Repetition.dll","512_Copy to Clipboard.dll","1024_Bing Translate.dll","2048_Extra Newlines.dll" -DestinationPath Textractor; Compress-Archive -Force -DestinationPath Textractor -Path @(
"Textractor.exe",
"styles",
"platforms",
"Qt5Core.dll",
"Qt5Gui.dll",
"Qt5Widgets.dll",
"vnrhook.dll",
"Remove Repetition.dll",
"Copy to Clipboard.dll",
"Bing Translate.dll",
"Extra Newlines.dll",
"Extensions.txt"
)

View File

@ -4,9 +4,9 @@ find_qt5(Core Widgets)
cmake_policy(SET CMP0037 OLD) cmake_policy(SET CMP0037 OLD)
add_library(256_Remove\ Repetition SHARED removerepeat.cpp extensionimpl.cpp) add_library(Remove\ Repetition SHARED removerepeat.cpp extensionimpl.cpp)
add_library(512_Copy\ to\ Clipboard SHARED copyclipboard.cpp extensionimpl.cpp) add_library(Copy\ to\ Clipboard SHARED copyclipboard.cpp extensionimpl.cpp)
add_library(1024_Bing\ Translate SHARED bingtranslate.cpp extensionimpl.cpp) add_library(Bing\ Translate SHARED bingtranslate.cpp extensionimpl.cpp)
add_library(2048_Extra\ Newlines SHARED extranewlines.cpp extensionimpl.cpp) add_library(Extra\ Newlines SHARED extranewlines.cpp extensionimpl.cpp)
target_link_libraries(1024_Bing\ Translate winhttp.lib Qt5::Widgets) target_link_libraries(Bing\ Translate winhttp.lib Qt5::Widgets)