can use right click and file dialog to add extension, also fix segfault when multiple copies of extension are added then removed

This commit is contained in:
Akash Mozumdar 2019-08-29 13:46:21 -04:00
parent 590c08e8d0
commit 1cf60785e3
4 changed files with 43 additions and 23 deletions

View File

@ -2,12 +2,15 @@
#include "ui_extenwindow.h" #include "ui_extenwindow.h"
#include "defs.h" #include "defs.h"
#include <concrt.h> #include <concrt.h>
#include <QMenu>
#include <QFileDialog>
#include <QDragEnterEvent> #include <QDragEnterEvent>
#include <QDropEvent> #include <QDropEvent>
#include <QMimeData> #include <QMimeData>
#include <QUrl> #include <QUrl>
extern const char* EXTENSIONS; extern const char* EXTENSIONS;
extern const char* ADD_EXTENSION;
extern const char* INVALID_EXTENSION; extern const char* INVALID_EXTENSION;
extern const char* CONFIRM_EXTENSION_OVERWRITE; extern const char* CONFIRM_EXTENSION_OVERWRITE;
extern const char* EXTENSION_WRITE_ERROR; extern const char* EXTENSION_WRITE_ERROR;
@ -20,7 +23,7 @@ namespace
struct Extension struct Extension
{ {
std::wstring name; std::wstring name;
wchar_t*(*callback)(wchar_t*, const InfoForExtension*); wchar_t* (*callback)(wchar_t*, const InfoForExtension*);
}; };
concurrency::reader_writer_lock extenMutex; concurrency::reader_writer_lock extenMutex;
@ -31,11 +34,15 @@ namespace
// Extension is dll and exports "OnNewSentence" // Extension is dll and exports "OnNewSentence"
if (QTextFile(extenName + ".dll", QIODevice::ReadOnly).readAll().contains("OnNewSentence")) if (QTextFile(extenName + ".dll", QIODevice::ReadOnly).readAll().contains("OnNewSentence"))
{ {
if (auto callback = (decltype(Extension::callback))GetProcAddress(LoadLibraryOnce(S(extenName)), "OnNewSentence")) if (HMODULE module = LoadLibraryW(S(extenName).c_str()))
{ {
std::scoped_lock writeLock(extenMutex); if (auto callback = (decltype(Extension::callback))GetProcAddress(LoadLibraryOnce(S(extenName)), "OnNewSentence"))
extensions.push_back({ S(extenName), callback }); {
return true; std::scoped_lock writeLock(extenMutex);
extensions.push_back({ S(extenName), callback });
return true;
}
FreeLibrary(module);
} }
} }
return false; return false;
@ -73,8 +80,7 @@ bool DispatchSentenceToExtensions(std::wstring& sentence, const InfoForExtension
void CleanupExtensions() void CleanupExtensions()
{ {
std::scoped_lock writeLock(extenMutex); std::scoped_lock writeLock(extenMutex);
for (auto extension : extensions) for (auto extension : extensions) FreeLibrary(GetModuleHandleW(extension.name.c_str()));
FreeLibrary(GetModuleHandleW(extension.name.c_str()));
extensions.clear(); extensions.clear();
} }
@ -84,6 +90,12 @@ ExtenWindow::ExtenWindow(QWidget* parent) :
{ {
ui->setupUi(this); ui->setupUi(this);
connect(ui->extenList, &QListWidget::customContextMenuRequested, [this](QPoint point)
{
if (QMenu(this).exec({ std::make_unique<QAction>(ADD_EXTENSION).get() }, ui->extenList->mapToGlobal(point)))
if (QString extenFile = QFileDialog::getOpenFileName(this, ADD_EXTENSION, ".", EXTENSIONS + QString(" (*.dll)")); !extenFile.isEmpty()) Add(extenFile);
});
ui->vboxLayout->addWidget(new QLabel(EXTEN_WINDOW_INSTRUCTIONS, this)); ui->vboxLayout->addWidget(new QLabel(EXTEN_WINDOW_INSTRUCTIONS, this));
setWindowTitle(EXTENSIONS); setWindowTitle(EXTENSIONS);
@ -99,6 +111,20 @@ ExtenWindow::~ExtenWindow()
delete ui; delete ui;
} }
void ExtenWindow::Add(QFileInfo extenFile)
{
if (extenFile.suffix() == "dll")
{
if (extenFile.absolutePath() != QDir::currentPath())
{
if (QFile::exists(extenFile.fileName()) && QMessageBox::question(this, EXTENSIONS, CONFIRM_EXTENSION_OVERWRITE) == QMessageBox::Yes) QFile::remove(extenFile.fileName());
if (!QFile::copy(extenFile.absoluteFilePath(), extenFile.fileName())) QMessageBox::warning(this, EXTENSIONS, EXTENSION_WRITE_ERROR);
}
if (Load(extenFile.completeBaseName())) return Sync();
}
QMessageBox::information(this, EXTENSIONS, QString(INVALID_EXTENSION).arg(extenFile.fileName()));
}
void ExtenWindow::Sync() void ExtenWindow::Sync()
{ {
ui->extenList->clear(); ui->extenList->clear();
@ -140,16 +166,5 @@ void ExtenWindow::dragEnterEvent(QDragEnterEvent* event)
void ExtenWindow::dropEvent(QDropEvent* event) void ExtenWindow::dropEvent(QDropEvent* event)
{ {
for (auto file : event->mimeData()->urls()) for (auto file : event->mimeData()->urls()) Add(file.toLocalFile());
{
QFileInfo extenFile = file.toLocalFile();
if (extenFile.suffix() != "dll") continue;
if (extenFile.absolutePath() != QDir::currentPath())
{
if (QFile::exists(extenFile.fileName()) && QMessageBox::question(this, EXTENSIONS, CONFIRM_EXTENSION_OVERWRITE) == QMessageBox::Yes) QFile::remove(extenFile.fileName());
if (!QFile::copy(extenFile.absoluteFilePath(), extenFile.fileName())) QMessageBox::warning(this, EXTENSIONS, EXTENSION_WRITE_ERROR);
}
if (Load(extenFile.completeBaseName())) Sync();
else QMessageBox::information(this, EXTENSIONS, QString(INVALID_EXTENSION).arg(extenFile.fileName()));
}
} }

View File

@ -25,6 +25,7 @@ public:
private: private:
inline static constexpr auto EXTEN_SAVE_FILE = u8"SavedExtensions.txt"; inline static constexpr auto EXTEN_SAVE_FILE = u8"SavedExtensions.txt";
void Add(QFileInfo extenFile);
void Sync(); void Sync();
bool eventFilter(QObject* target, QEvent* event) override; bool eventFilter(QObject* target, QEvent* event) override;
void keyPressEvent(QKeyEvent* event) override; void keyPressEvent(QKeyEvent* event) override;

View File

@ -17,6 +17,9 @@
<layout class="QVBoxLayout"> <layout class="QVBoxLayout">
<item> <item>
<widget class="QListWidget" name="extenList"> <widget class="QListWidget" name="extenList">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="dragDropMode"> <property name="dragDropMode">
<enum>QAbstractItemView::InternalMove</enum> <enum>QAbstractItemView::InternalMove</enum>
</property> </property>

View File

@ -41,11 +41,12 @@ Negatives for data_offset/split_offset refer to registers
-C for RAX, -14 for RBX, -1C for RCX, -24 for RDX, and so on for RSP, RBP, RSI, RDI, R8-R15 -C for RAX, -14 for RBX, -1C for RCX, -24 for RDX, and so on for RSP, RBP, RSI, RDI, R8-R15
* means dereference pointer+deref_offset)"; * means dereference pointer+deref_offset)";
const char* SAVE_SETTINGS = u8"Save settings"; const char* SAVE_SETTINGS = u8"Save settings";
const char* EXTEN_WINDOW_INSTRUCTIONS = u8R"(Drag and drop extension (.dll) files here from your computer to add them const char* EXTEN_WINDOW_INSTRUCTIONS = u8R"(To add an extension, right click the extension list
(Does not work if running as administrator) Alternatively, drag and drop the extension file from your computer
Drag and drop within the list to reorder To reorder extensions, drag and drop them within the list
(Extensions are used from top to bottom: order DOES matter) (Extensions are used from top to bottom: order DOES matter)
Press delete with an extension selected to remove it)"; To remove an extension, select it and press delete)";
const char* ADD_EXTENSION = u8"Add extension";
const char* INVALID_EXTENSION = u8"%1 is an invalid extension"; const char* INVALID_EXTENSION = u8"%1 is an invalid extension";
const char* CONFIRM_EXTENSION_OVERWRITE = u8"Another version of this extension already exists, do you want to delete and overwrite it?"; const char* CONFIRM_EXTENSION_OVERWRITE = u8"Another version of this extension already exists, do you want to delete and overwrite it?";
const char* EXTENSION_WRITE_ERROR = u8"Failed to save extension"; const char* EXTENSION_WRITE_ERROR = u8"Failed to save extension";