add extension class and refactor extensions using it

This commit is contained in:
Akash Mozumdar 2018-10-10 07:03:15 -04:00
parent ec1bd5622e
commit effb005376
6 changed files with 52 additions and 36 deletions

View File

@ -2,28 +2,34 @@
#include <shared_mutex> #include <shared_mutex>
#include <QDir> #include <QDir>
std::shared_mutex extenMutex; std::optional<Extension> LoadExtension(QString file)
std::map<int, ExtensionFunction> extensions;
std::map<int, QString> LoadExtensions()
{ {
std::map<int, ExtensionFunction> newExtensions; // Extension file format: {NUMBER}_{NAME}.dll and exports "OnNewSentence"
std::map<int, QString> extensionNames; QRegularExpressionMatch parsedFile = QRegularExpression("^(\\d+)_(.+).dll$").match(file);
if (!parsedFile.hasMatch()) return {};
HMODULE module = GetModuleHandleW(file.toStdWString().c_str());
if (!module) module = LoadLibraryW(file.toStdWString().c_str());
if (!module) return {};
auto callback = (wchar_t*(*)(const wchar_t*, const InfoForExtension*))GetProcAddress(module, "OnNewSentence");
if (!callback) return {};
return Extension{ parsedFile.captured(1).toInt(), parsedFile.captured(2), callback };
}
std::shared_mutex extenMutex;
std::set<Extension> extensions;
std::set<Extension> LoadExtensions()
{
std::set<Extension> newExtensions;
QStringList files = QDir().entryList(); QStringList files = QDir().entryList();
for (auto file : files) for (auto file : files)
if (file.split("_").size() > 1 && file.split("_")[0].toInt() && file.endsWith(".dll")) if (auto extension = LoadExtension(file)) newExtensions.insert(extension.value());
if (GetProcAddress(GetModuleHandleW(file.toStdWString().c_str()), "OnNewSentence") ||
GetProcAddress(LoadLibraryW(file.toStdWString().c_str()), "OnNewSentence"))
{
int extensionNumber = file.split("_")[0].toInt();
newExtensions[extensionNumber] = (ExtensionFunction)GetProcAddress(GetModuleHandleW(file.toStdWString().c_str()), "OnNewSentence");
file.chop(sizeof("dll"));
file.remove(0, file.indexOf("_") + 1);
extensionNames[extensionNumber] = file;
}
std::unique_lock<std::shared_mutex> extenLock(extenMutex); std::unique_lock<std::shared_mutex> extenLock(extenMutex);
extensions = newExtensions; return extensions = newExtensions;
return extensionNames;
} }
bool DispatchSentenceToExtensions(std::wstring& sentence, std::unordered_map<std::string, int64_t> miscInfo) bool DispatchSentenceToExtensions(std::wstring& sentence, std::unordered_map<std::string, int64_t> miscInfo)
@ -31,19 +37,21 @@ bool DispatchSentenceToExtensions(std::wstring& sentence, std::unordered_map<std
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));
wcscpy_s(sentenceBuffer, sentence.size() + 1, sentence.c_str()); wcscpy_s(sentenceBuffer, sentence.size() + 1, sentence.c_str());
InfoForExtension* miscInfoLinkedList = new InfoForExtension;
InfoForExtension* miscInfoTraverser = miscInfoLinkedList; InfoForExtension miscInfoLinkedList{ "", 0, nullptr };
for (auto& i : miscInfo) miscInfoTraverser = miscInfoTraverser->nextProperty = new InfoForExtension{ i.first.c_str(), i.second, nullptr }; InfoForExtension* miscInfoTraverser = &miscInfoLinkedList;
for (auto& i : miscInfo) miscInfoTraverser = miscInfoTraverser->next = new InfoForExtension{ i.first.c_str(), i.second, nullptr };
std::shared_lock<std::shared_mutex> extenLock(extenMutex); std::shared_lock<std::shared_mutex> extenLock(extenMutex);
for (auto i : extensions) for (auto extension : extensions)
{ {
wchar_t* nextBuffer = i.second(sentenceBuffer, miscInfoLinkedList); wchar_t* nextBuffer = extension.callback(sentenceBuffer, &miscInfoLinkedList);
if (nextBuffer == nullptr) { success = false; break; } if (nextBuffer == nullptr) { success = false; break; }
if (nextBuffer != sentenceBuffer) HeapFree(GetProcessHeap(), 0, sentenceBuffer); if (nextBuffer != sentenceBuffer) HeapFree(GetProcessHeap(), 0, sentenceBuffer);
sentenceBuffer = nextBuffer; sentenceBuffer = nextBuffer;
} }
sentence = std::wstring(sentenceBuffer); sentence = std::wstring(sentenceBuffer);
HeapFree(GetProcessHeap(), 0, sentenceBuffer); HeapFree(GetProcessHeap(), 0, sentenceBuffer);
delete miscInfoLinkedList;
return success; return success;
} }

View File

@ -2,17 +2,25 @@
#define EXTENSIONS_H #define EXTENSIONS_H
#include "qtcommon.h" #include "qtcommon.h"
#include <map> #include <set>
std::map<int, QString> LoadExtensions();
bool DispatchSentenceToExtensions(std::wstring& sentence, std::unordered_map<std::string, int64_t> miscInfo);
struct InfoForExtension struct InfoForExtension
{ {
~InfoForExtension() { if (nextProperty) delete nextProperty; }; const char* name;
const char* propertyName = ""; int64_t value;
int64_t propertyValue = 0; InfoForExtension* next;
InfoForExtension* nextProperty = nullptr; ~InfoForExtension() { if (next) delete next; };
}; };
typedef wchar_t*(*ExtensionFunction)(const wchar_t*, const InfoForExtension*);
struct Extension
{
int number;
QString name;
wchar_t*(*callback)(const wchar_t*, const InfoForExtension*);
bool operator<(const Extension& other) const { return number < other.number; }
};
std::set<Extension> LoadExtensions();
bool DispatchSentenceToExtensions(std::wstring& sentence, std::unordered_map<std::string, int64_t> miscInfo);
#endif // EXTENSIONS_H #endif // EXTENSIONS_H

View File

@ -141,8 +141,7 @@ DWORD MainWindow::GetSelectedProcessId()
void MainWindow::ReloadExtensions() void MainWindow::ReloadExtensions()
{ {
extenCombo->clear(); extenCombo->clear();
std::map<int, QString> extensions = LoadExtensions(); for (auto extension : LoadExtensions()) extenCombo->addItem(QString::number(extension.number) + ": " + extension.name);
for (auto i : extensions) extenCombo->addItem(QString::number(i.first) + ": " + i.second);
} }
std::unordered_map<std::string, int64_t> MainWindow::GetInfoForExtensions(TextThread* thread) std::unordered_map<std::string, int64_t> MainWindow::GetInfoForExtensions(TextThread* thread)

View File

@ -4,7 +4,6 @@
#include "qtcommon.h" #include "qtcommon.h"
#include "types.h" #include "types.h"
#include <QHash> #include <QHash>
#include <optional>
QString GetFullModuleName(DWORD processId, HMODULE module = NULL); QString GetFullModuleName(DWORD processId, HMODULE module = NULL);
QString GetModuleName(DWORD processId, HMODULE module = NULL); QString GetModuleName(DWORD processId, HMODULE module = NULL);

View File

@ -4,3 +4,4 @@
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <QVector> #include <QVector>
#include <QRegularExpression>

View File

@ -6,6 +6,7 @@
#include <vector> #include <vector>
#include <unordered_map> #include <unordered_map>
#include <functional> #include <functional>
#include <optional>
#include <thread> #include <thread>
#include <mutex> #include <mutex>
#include <cstdint> #include <cstdint>