refactor extensions some and let user rearrange them
This commit is contained in:
parent
1e2f6e14ec
commit
3a3bdfd48e
@ -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 }));
|
|
||||||
}
|
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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:
|
||||||
|
@ -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">
|
||||||
|
33
deploy.ps1
33
deploy.ps1
@ -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"
|
||||||
|
)
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user