From 16540bfe695e7436aae0f0f786890bce0a6991a2 Mon Sep 17 00:00:00 2001 From: Akash Mozumdar Date: Fri, 28 Feb 2020 00:34:34 -0700 Subject: [PATCH] move utility functions into common.h and module.h --- GUI/CMakeLists.txt | 2 +- GUI/host/cli.cpp | 15 ++++++-- GUI/host/exception.cpp | 5 +-- GUI/host/{util.cpp => hookcode.cpp} | 56 ++++------------------------- GUI/host/hookcode.h | 10 ++++++ GUI/host/host.cpp | 16 +++++---- GUI/host/textthread.cpp | 5 ++- GUI/host/util.h | 15 -------- GUI/main.cpp | 4 +-- GUI/mainwindow.cpp | 29 +++++++-------- extensions/extrawindow.cpp | 1 - extensions/googletranslate.cpp | 1 - extensions/lua.cpp | 1 - extensions/network.cpp | 1 - extensions/removerepeatphrase.cpp | 24 ++++++------- extensions/translatewrapper.cpp | 1 - extensions/util.h | 17 --------- include/common.h | 22 ++++++++++++ include/module.h | 27 ++++++++++++++ 19 files changed, 122 insertions(+), 130 deletions(-) rename GUI/host/{util.cpp => hookcode.cpp} (79%) create mode 100644 GUI/host/hookcode.h delete mode 100644 GUI/host/util.h delete mode 100644 extensions/util.h create mode 100644 include/module.h diff --git a/GUI/CMakeLists.txt b/GUI/CMakeLists.txt index a27c832..e8d0276 100644 --- a/GUI/CMakeLists.txt +++ b/GUI/CMakeLists.txt @@ -9,7 +9,7 @@ add_executable(Textractor WIN32 host/exception.cpp host/host.cpp host/textthread.cpp - host/util.cpp + host/hookcode.cpp Textractor.rc Textractor.ico ) diff --git a/GUI/host/cli.cpp b/GUI/host/cli.cpp index 47bd8ba..63fc38a 100644 --- a/GUI/host/cli.cpp +++ b/GUI/host/cli.cpp @@ -1,5 +1,5 @@ #include "host.h" -#include "util.h" +#include "hookcode.h" #include #include #include @@ -12,7 +12,16 @@ int main() fflush(stdout); Host::Start([](auto) {}, [](auto) {}, [](auto&) {}, [](auto&) {}, [](TextThread& thread, std::wstring& output) { - wprintf_s(L"[%I64X:%I32X:%I64X:%I64X:%I64X:%s:%s] %s\n", thread.handle, thread.tp.processId, thread.tp.addr, thread.tp.ctx, thread.tp.ctx2, thread.name.c_str(), Util::GenerateCode(thread.hp, thread.tp.processId).c_str(), output.c_str()); + wprintf_s(L"[%I64X:%I32X:%I64X:%I64X:%I64X:%s:%s] %s\n", + thread.handle, + thread.tp.processId, + thread.tp.addr, + thread.tp.ctx, + thread.tp.ctx2, + thread.name.c_str(), + HookCode::Generate(thread.hp, thread.tp.processId).c_str(), + output.c_str() + ); fflush(stdout); return false; }); @@ -24,7 +33,7 @@ int main() if (swscanf(input, L"%500s -P%d", command, &processId) != 2) ExitProcess(0); if (_wcsicmp(command, L"attach") == 0) Host::InjectProcess(processId); else if (_wcsicmp(command, L"detach") == 0) Host::DetachProcess(processId); - else if (auto hp = Util::ParseCode(command)) Host::InsertHook(processId, hp.value()); + else if (auto hp = HookCode::Parse(command)) Host::InsertHook(processId, hp.value()); else ExitProcess(0); } ExitProcess(0); diff --git a/GUI/host/exception.cpp b/GUI/host/exception.cpp index 625c06c..9215f9d 100644 --- a/GUI/host/exception.cpp +++ b/GUI/host/exception.cpp @@ -1,4 +1,5 @@ -#include "util.h" +#include "common.h" +#include "module.h" #include namespace @@ -36,7 +37,7 @@ namespace errorMsg << std::uppercase << std::hex << L"Error code: " << exception->ExceptionRecord->ExceptionCode << std::endl << L"Error address: " << exception->ExceptionRecord->ExceptionAddress << std::endl << - L"Error in module: " << Util::GetModuleFilename((HMODULE)info.AllocationBase).value_or(L"Could not find") << std::endl << + L"Error in module: " << GetModuleFilename((HMODULE)info.AllocationBase).value_or(L"Could not find") << std::endl << L"Additional info: " << info.AllocationBase << std::endl; if (exception->ExceptionRecord->ExceptionCode == 0xE06D7363) diff --git a/GUI/host/util.cpp b/GUI/host/hookcode.cpp similarity index 79% rename from GUI/host/util.cpp rename to GUI/host/hookcode.cpp index 0ad4e50..1bba481 100644 --- a/GUI/host/util.cpp +++ b/GUI/host/hookcode.cpp @@ -1,5 +1,5 @@ -#include "util.h" -#include +#include "hookcode.h" +#include "module.h" namespace { @@ -250,7 +250,7 @@ namespace if (processId && !(hp.type & MODULE_OFFSET)) if (AutoHandle<> process = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, processId)) if (MEMORY_BASIC_INFORMATION info = {}; VirtualQueryEx(process, (LPCVOID)hp.address, &info, sizeof(info))) - if (auto moduleName = Util::GetModuleFilename(processId, (HMODULE)info.AllocationBase)) + if (auto moduleName = GetModuleFilename(processId, (HMODULE)info.AllocationBase)) { hp.type |= MODULE_OFFSET; hp.address -= (uint64_t)info.AllocationBase; @@ -265,53 +265,9 @@ namespace } } -namespace Util +namespace HookCode { - std::optional GetModuleFilename(DWORD processId, HMODULE module) - { - std::vector buffer(MAX_PATH); - if (AutoHandle<> process = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, processId)) - if (GetModuleFileNameExW(process, module, buffer.data(), MAX_PATH)) return buffer.data(); - return {}; - } - - std::optional GetModuleFilename(HMODULE module) - { - std::vector buffer(MAX_PATH); - if (GetModuleFileNameW(module, buffer.data(), MAX_PATH)) return buffer.data(); - return {}; - } - - std::vector>> GetAllProcesses() - { - std::vector processIds(10000); - DWORD spaceUsed = 0; - EnumProcesses(processIds.data(), 10000 * sizeof(DWORD), &spaceUsed); - std::vector>> processes; - for (int i = 0; i < spaceUsed / sizeof(DWORD); ++i) processes.push_back({ processIds[i], Util::GetModuleFilename(processIds[i]) }); - return processes; - } - - std::optional GetClipboardText() - { - if (!IsClipboardFormatAvailable(CF_UNICODETEXT)) return {}; - if (!OpenClipboard(NULL)) return {}; - - std::optional text; - if (AutoHandle> clipboard = GetClipboardData(CF_UNICODETEXT)) text = (wchar_t*)GlobalLock(clipboard); - CloseClipboard(); - return text; - } - - std::optional StringToWideString(const std::string& text, UINT encoding) - { - std::vector buffer(text.size() + 1); - if (int length = MultiByteToWideChar(encoding, 0, text.c_str(), text.size() + 1, buffer.data(), buffer.size())) - return std::wstring(buffer.data(), length - 1); - return {}; - } - - std::optional ParseCode(std::wstring code) + std::optional Parse(std::wstring code) { if (code[0] == L'/') code.erase(0, 1); // legacy/AGTH compatibility if (code[0] == L'R') return ParseRCode(code.erase(0, 1)); @@ -319,7 +275,7 @@ namespace Util return {}; } - std::wstring GenerateCode(HookParam hp, DWORD processId) + std::wstring Generate(HookParam hp, DWORD processId) { return hp.type & DIRECT_READ ? GenerateRCode(hp) : GenerateHCode(hp, processId); } diff --git a/GUI/host/hookcode.h b/GUI/host/hookcode.h new file mode 100644 index 0000000..42c352a --- /dev/null +++ b/GUI/host/hookcode.h @@ -0,0 +1,10 @@ +#pragma once + +#include "common.h" +#include "types.h" + +namespace HookCode +{ + std::optional Parse(std::wstring code); + std::wstring Generate(HookParam hp, DWORD processId = 0); +} diff --git a/GUI/host/host.cpp b/GUI/host/host.cpp index b055e14..cdcf0f2 100644 --- a/GUI/host/host.cpp +++ b/GUI/host/host.cpp @@ -1,6 +1,6 @@ #include "host.h" #include "defs.h" -#include "util.h" +#include "hookcode.h" #include "../texthook/texthook.h" extern const wchar_t* ALREADY_INJECTED; @@ -48,7 +48,7 @@ namespace Host::HookEventHandler OnHookFound = [](HookParam hp, std::wstring text) { - Host::AddConsoleOutput(Util::GenerateCode(hp) + L": " + text); + Host::AddConsoleOutput(HookCode::Generate(hp) + L": " + text); }; private: @@ -107,9 +107,9 @@ namespace std::wstring wide = info.text; if (wide.size() > STRING) OnHookFound(info.hp, std::move(info.text)); info.hp.type &= ~USING_UNICODE; - if (auto converted = Util::StringToWideString((char*)info.text, info.hp.codepage)) + if (auto converted = StringToWideString((char*)info.text, info.hp.codepage)) if (converted->size() > STRING) OnHookFound(info.hp, std::move(converted.value())); - if (auto converted = Util::StringToWideString((char*)info.text, info.hp.codepage = CP_UTF8)) + if (auto converted = StringToWideString((char*)info.text, info.hp.codepage = CP_UTF8)) if (converted->size() > STRING) OnHookFound(info.hp, std::move(converted.value())); } break; @@ -122,7 +122,7 @@ namespace case HOST_NOTIFICATION_TEXT: { auto info = *(ConsoleOutputNotif*)buffer; - Host::AddConsoleOutput(Util::StringToWideString(info.message).value()); + Host::AddConsoleOutput(StringToWideString(info.message)); } break; default: @@ -179,8 +179,12 @@ namespace Host for (int retry = 0; !clipboardText && retry < 3; ++retry) // retry loop in case something else is using the clipboard { Sleep(10); - if (clipboardText = Util::GetClipboardText()) GetThread(clipboard).AddSentence(std::move(clipboardText.value())); + if (!IsClipboardFormatAvailable(CF_UNICODETEXT)) continue; + if (!OpenClipboard(NULL)) continue; + if (AutoHandle> clipboard = GetClipboardData(CF_UNICODETEXT)) clipboardText = (wchar_t*)GlobalLock(clipboard); + CloseClipboard(); } + if (clipboardText) GetThread(clipboard).AddSentence(std::move(clipboardText.value())); } throw; }).detach(); diff --git a/GUI/host/textthread.cpp b/GUI/host/textthread.cpp index f5c7db6..b08556e 100644 --- a/GUI/host/textthread.cpp +++ b/GUI/host/textthread.cpp @@ -1,6 +1,5 @@ #include "textthread.h" #include "host.h" -#include "util.h" extern const wchar_t* INVALID_CODEPAGE; @@ -16,7 +15,7 @@ static bool RemoveRepetition(std::wstring& text) TextThread::TextThread(ThreadParam tp, HookParam hp, std::optional name) : handle(threadCounter++), - name(name.value_or(Util::StringToWideString(hp.name).value())), + name(name.value_or(StringToWideString(hp.name))), tp(tp), hp(hp) {} @@ -48,7 +47,7 @@ void TextThread::Push(BYTE* data, int length) if (hp.type & HEX_DUMP) for (int i = 0; i < length; i += sizeof(short)) buffer.append(FormatString(L"%04hX ", *(short*)(data + i))); else if (hp.type & USING_UNICODE) buffer.append((wchar_t*)data, length / sizeof(wchar_t)); - else if (auto converted = Util::StringToWideString(std::string((char*)data, length), hp.codepage ? hp.codepage : Host::defaultCodepage)) buffer.append(converted.value()); + else if (auto converted = StringToWideString(std::string((char*)data, length), hp.codepage ? hp.codepage : Host::defaultCodepage)) buffer.append(converted.value()); else Host::AddConsoleOutput(INVALID_CODEPAGE); if (hp.type & FULL_STRING) buffer.push_back(L'\n'); lastPushTime = GetTickCount(); diff --git a/GUI/host/util.h b/GUI/host/util.h deleted file mode 100644 index aa8eaa4..0000000 --- a/GUI/host/util.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "common.h" -#include "types.h" - -namespace Util -{ - std::optional GetModuleFilename(DWORD processId, HMODULE module = NULL); - std::optional GetModuleFilename(HMODULE module = NULL); - std::vector>> GetAllProcesses(); - std::optional GetClipboardText(); - std::optional StringToWideString(const std::string& text, UINT encoding = CP_UTF8); - std::optional ParseCode(std::wstring code); - std::wstring GenerateCode(HookParam hp, DWORD processId = 0); -} diff --git a/GUI/main.cpp b/GUI/main.cpp index 9beb513..81c08cc 100644 --- a/GUI/main.cpp +++ b/GUI/main.cpp @@ -1,5 +1,5 @@ #include "mainwindow.h" -#include "host/util.h" +#include "module.h" #include #include @@ -24,7 +24,7 @@ int main(int argc, char *argv[]) } }).detach(); - QDir::setCurrent(QFileInfo(S(Util::GetModuleFilename().value())).absolutePath()); + QDir::setCurrent(QFileInfo(S(GetModuleFilename().value())).absolutePath()); QApplication app(argc, argv); app.setFont(QFont("MS Shell Dlg 2", 10)); diff --git a/GUI/mainwindow.cpp b/GUI/mainwindow.cpp index 120b427..611a52c 100644 --- a/GUI/mainwindow.cpp +++ b/GUI/mainwindow.cpp @@ -1,7 +1,8 @@ #include "mainwindow.h" #include "ui_mainwindow.h" #include "defs.h" -#include "host/util.h" +#include "module.h" +#include "host/hookcode.h" #include #include #include @@ -113,7 +114,7 @@ MainWindow::MainWindow(QWidget *parent) : AttachConsole(ATTACH_PARENT_PROCESS); WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), CL_OPTIONS, wcslen(CL_OPTIONS), DUMMY, NULL); - auto processes = Util::GetAllProcesses(); + auto processes = GetAllProcesses(); int argc; std::unique_ptr> argv(CommandLineToArgvW(GetCommandLineW(), &argc)); for (int i = 0; i < argc; ++i) @@ -136,7 +137,7 @@ MainWindow::MainWindow(QWidget *parent) : attachTargets.insert(S(process.split(" , ")[0])); if (!attachTargets.empty()) - for (auto [processId, processName] : Util::GetAllProcesses()) + for (auto [processId, processName] : GetAllProcesses()) if (processName && attachTargets.count(processName.value()) > 0 && alreadyAttached.count(processId) == 0) Host::InjectProcess(processId); } }).detach(); @@ -159,7 +160,7 @@ void MainWindow::ProcessConnected(DWORD processId) { alreadyAttached.insert(processId); - QString process = S(Util::GetModuleFilename(processId).value_or(L"???")); + QString process = S(GetModuleFilename(processId).value_or(L"???")); QMetaObject::invokeMethod(this, [this, process, processId] { ui->processCombo->addItem(QString::number(processId, 16).toUpper() + ": " + QFileInfo(process).fileName()); @@ -173,7 +174,7 @@ void MainWindow::ProcessConnected(DWORD processId) auto hookList = std::find_if(allProcesses.rbegin(), allProcesses.rend(), [&](QString hookList) { return hookList.contains(process); }); if (hookList != allProcesses.rend()) for (auto hookInfo : hookList->split(" , ")) - if (auto hp = Util::ParseCode(S(hookInfo))) Host::InsertHook(processId, hp.value()); + if (auto hp = HookCode::Parse(S(hookInfo))) Host::InsertHook(processId, hp.value()); else swscanf_s(S(hookInfo).c_str(), L"|%I64d:%I64d:%[^\n]", &savedThreadCtx, &savedThreadCtx2, savedThreadCode, (unsigned)std::size(savedThreadCode)); } @@ -187,7 +188,7 @@ void MainWindow::ProcessDisconnected(DWORD processId) void MainWindow::ThreadAdded(TextThread& thread) { - std::wstring threadCode = Util::GenerateCode(thread.hp, thread.tp.processId); + std::wstring threadCode = HookCode::Generate(thread.hp, thread.tp.processId); bool savedMatch = savedThreadCtx == thread.tp.ctx && savedThreadCtx2 == thread.tp.ctx2 && savedThreadCode == threadCode; if (savedMatch) savedThreadCtx = savedThreadCtx2 = savedThreadCode[0] = 0; QMetaObject::invokeMethod(this, [this, savedMatch, ttString = TextThreadString(thread) + S(FormatString(L" (%s)", threadCode))] @@ -290,7 +291,7 @@ std::optional MainWindow::UserSelectedProcess() void MainWindow::AttachProcess() { QMultiHash allProcesses; - for (auto [processId, processName] : Util::GetAllProcesses()) + for (auto [processId, processName] : GetAllProcesses()) if (processName && (showSystemProcesses || processName->find(L":\\Windows\\") == std::wstring::npos)) allProcesses.insert(QFileInfo(S(processName.value())).fileName(), processId); @@ -348,7 +349,7 @@ void MainWindow::DetachProcess() void MainWindow::ForgetProcess() { - std::optional processName = Util::GetModuleFilename(GetSelectedProcessId()); + std::optional processName = GetModuleFilename(GetSelectedProcessId()); if (!processName) processName = UserSelectedProcess(); DetachProcess(); if (!processName) return; @@ -369,7 +370,7 @@ void MainWindow::AddHook(QString hook) { if (QString hookCode = QInputDialog::getText(this, ADD_HOOK, CODE_INFODUMP, QLineEdit::Normal, hook, &ok, Qt::WindowCloseButtonHint); ok) if (hookCode.startsWith("S") || hookCode.startsWith("/S")) FindHooks(); - else if (auto hp = Util::ParseCode(S(hookCode))) try { Host::InsertHook(GetSelectedProcessId(), hp.value()); } catch (std::out_of_range) {} + else if (auto hp = HookCode::Parse(S(hookCode))) try { Host::InsertHook(GetSelectedProcessId(), hp.value()); } catch (std::out_of_range) {} else Host::AddConsoleOutput(INVALID_CODE); } @@ -403,7 +404,7 @@ void MainWindow::RemoveHooks() void MainWindow::SaveHooks() { - auto processName = Util::GetModuleFilename(GetSelectedProcessId()); + auto processName = GetModuleFilename(GetSelectedProcessId()); if (!processName) return; QHash hookCodes; for (int i = 0; i < ui->ttCombo->count(); ++i) @@ -412,12 +413,12 @@ void MainWindow::SaveHooks() if (tp.processId == GetSelectedProcessId()) { HookParam hp = Host::GetThread(tp).hp; - if (!(hp.type & HOOK_ENGINE)) hookCodes[tp.addr] = S(Util::GenerateCode(hp, tp.processId)); + if (!(hp.type & HOOK_ENGINE)) hookCodes[tp.addr] = S(HookCode::Generate(hp, tp.processId)); } } auto hookInfo = QStringList() << S(processName.value()) << hookCodes.values(); ThreadParam tp = current->tp; - if (tp.processId == GetSelectedProcessId()) hookInfo << QString("|%1:%2:%3").arg(tp.ctx).arg(tp.ctx2).arg(S(Util::GenerateCode(current->hp, tp.processId))); + if (tp.processId == GetSelectedProcessId()) hookInfo << QString("|%1:%2:%3").arg(tp.ctx).arg(tp.ctx2).arg(S(HookCode::Generate(current->hp, tp.processId))); QTextFile(HOOK_SAVE_FILE, QIODevice::WriteOnly | QIODevice::Append).write((hookInfo.join(" , ") + "\n").toUtf8()); } @@ -489,7 +490,7 @@ void MainWindow::FindHooks() layout.addRow(label, spinBox); connect(spinBox, qOverload(&QSpinBox::valueChanged), [&value](int newValue) { value = newValue; }); } - QLineEdit boundInput(QFileInfo(S(Util::GetModuleFilename(GetSelectedProcessId()).value_or(L""))).fileName(), &dialog); + QLineEdit boundInput(QFileInfo(S(GetModuleFilename(GetSelectedProcessId()).value_or(L""))).fileName(), &dialog); layout.addRow(SEARCH_MODULE, &boundInput); for (auto [value, label] : Array{ { sp.minAddress, MIN_ADDRESS }, @@ -530,7 +531,7 @@ void MainWindow::FindHooks() try { Host::FindHooks(processId, sp, - [hooks, filter](HookParam hp, std::wstring text) { if (std::regex_search(text, filter)) *hooks << sanitize(S(Util::GenerateCode(hp) + L" => " + text)); }); + [hooks, filter](HookParam hp, std::wstring text) { if (std::regex_search(text, filter)) *hooks << sanitize(S(HookCode::Generate(hp) + L" => " + text)); }); } catch (std::out_of_range) { return; } std::thread([this, hooks] diff --git a/extensions/extrawindow.cpp b/extensions/extrawindow.cpp index 5c92ca6..546d211 100644 --- a/extensions/extrawindow.cpp +++ b/extensions/extrawindow.cpp @@ -2,7 +2,6 @@ #include "extension.h" #include "ui_extrawindow.h" #include "defs.h" -#include "util.h" #include "blockmarkup.h" #include #include diff --git a/extensions/googletranslate.cpp b/extensions/googletranslate.cpp index e6ce5c8..1722ace 100644 --- a/extensions/googletranslate.cpp +++ b/extensions/googletranslate.cpp @@ -1,6 +1,5 @@ #include "extension.h" #include "network.h" -#include "util.h" #include #include diff --git a/extensions/lua.cpp b/extensions/lua.cpp index b41b336..f636b74 100644 --- a/extensions/lua.cpp +++ b/extensions/lua.cpp @@ -1,6 +1,5 @@ #include "qtcommon.h" #include "extension.h" -#include "util.h" #include #include diff --git a/extensions/network.cpp b/extensions/network.cpp index 5899b18..fc7e9a9 100644 --- a/extensions/network.cpp +++ b/extensions/network.cpp @@ -1,5 +1,4 @@ #include "network.h" -#include "util.h" HttpRequest::HttpRequest( const wchar_t* agentName, diff --git a/extensions/removerepeatphrase.cpp b/extensions/removerepeatphrase.cpp index 3785832..f8dc5ee 100644 --- a/extensions/removerepeatphrase.cpp +++ b/extensions/removerepeatphrase.cpp @@ -2,34 +2,34 @@ std::vector GenerateSuffixArray(const std::wstring& text) { - std::vector identity(text.size()); - for (int i = 0; i < text.size(); ++i) identity[i] = i; - std::vector suffixArray = identity; + std::vector suffixArray(text.size()); + for (int i = 0; i < text.size(); ++i) suffixArray[i] = i; // The below code is a more efficient way of doing this: // std::sort(suffixArray.begin(), suffixArray.end(), [&](int a, int b) { return wcscmp(text.c_str() + a, text.c_str() + b) > 0; }); std::stable_sort(suffixArray.begin(), suffixArray.end(), [&](int a, int b) { return text[a] > text[b]; }); - std::vector classes(text.begin(), text.end()); + std::vector eqClasses(text.begin(), text.end()); + std::vector count(text.size()); for (int length = 1; length < text.size(); length *= 2) { // Determine equivalence class up to length, by checking length / 2 equivalence of suffixes and their following length / 2 suffixes - std::vector oldClasses = classes; - classes[suffixArray[0]] = 0; + std::vector prevEqClasses = eqClasses; + eqClasses[suffixArray[0]] = 0; for (int i = 1; i < text.size(); ++i) { int currentSuffix = suffixArray[i]; int lastSuffix = suffixArray[i - 1]; - if (currentSuffix + length < text.size() && oldClasses[currentSuffix] == oldClasses[lastSuffix] && - oldClasses[currentSuffix + length / 2] == oldClasses.at(lastSuffix + length / 2)) // not completely certain that this will stay in range - classes[currentSuffix] = classes[lastSuffix]; - else classes[currentSuffix] = i; + if (currentSuffix + length < text.size() && prevEqClasses[currentSuffix] == prevEqClasses[lastSuffix] && + prevEqClasses[currentSuffix + length / 2] == prevEqClasses.at(lastSuffix + length / 2)) // not completely certain that this will stay in range + eqClasses[currentSuffix] = eqClasses[lastSuffix]; + else eqClasses[currentSuffix] = i; } // Sort within equivalence class based on order of following suffix after length (orders up to length * 2) - std::vector count = identity; + for (int i = 0; i < text.size(); ++i) count[i] = i; for (auto suffix : std::vector(suffixArray)) { int precedingSuffix = suffix - length; - if (precedingSuffix >= 0) suffixArray[count[classes[precedingSuffix]]++] = precedingSuffix; + if (precedingSuffix >= 0) suffixArray[count[eqClasses[precedingSuffix]]++] = precedingSuffix; } } for (int i = 0; i + 1 < text.size(); ++i) diff --git a/extensions/translatewrapper.cpp b/extensions/translatewrapper.cpp index 9725cad..43e6a93 100644 --- a/extensions/translatewrapper.cpp +++ b/extensions/translatewrapper.cpp @@ -1,7 +1,6 @@ #include "qtcommon.h" #include "extension.h" #include "defs.h" -#include "util.h" #include "blockmarkup.h" #include "network.h" #include diff --git a/extensions/util.h b/extensions/util.h deleted file mode 100644 index 3291367..0000000 --- a/extensions/util.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "common.h" - -inline std::wstring StringToWideString(const std::string& text) -{ - std::vector buffer(text.size() + 1); - MultiByteToWideChar(CP_UTF8, 0, text.c_str(), -1, buffer.data(), buffer.size()); - return buffer.data(); -} - -inline std::string WideStringToString(const std::wstring& text) -{ - std::vector buffer((text.size() + 1) * 4); - WideCharToMultiByte(CP_UTF8, 0, text.c_str(), -1, buffer.data(), buffer.size(), nullptr, nullptr); - return buffer.data(); -} diff --git a/include/common.h b/include/common.h index a303bb2..1eeb2c0 100644 --- a/include/common.h +++ b/include/common.h @@ -114,6 +114,28 @@ inline std::wstring FormatString(const wchar_t* format, const Args&... args) } #pragma warning(pop) +inline std::optional StringToWideString(const std::string& text, UINT encoding) +{ + std::vector buffer(text.size() + 1); + if (int length = MultiByteToWideChar(encoding, 0, text.c_str(), text.size() + 1, buffer.data(), buffer.size())) + return std::wstring(buffer.data(), length - 1); + return {}; +} + +inline std::wstring StringToWideString(const std::string& text) +{ + std::vector buffer(text.size() + 1); + MultiByteToWideChar(CP_UTF8, 0, text.c_str(), -1, buffer.data(), buffer.size()); + return buffer.data(); +} + +inline std::string WideStringToString(const std::wstring& text) +{ + std::vector buffer((text.size() + 1) * 4); + WideCharToMultiByte(CP_UTF8, 0, text.c_str(), -1, buffer.data(), buffer.size(), nullptr, nullptr); + return buffer.data(); +} + template inline void TEXTRACTOR_MESSAGE(const wchar_t* format, const Args&... args) { MessageBoxW(NULL, FormatString(format, args...).c_str(), L"Textractor", MB_OK); } diff --git a/include/module.h b/include/module.h new file mode 100644 index 0000000..ddf508e --- /dev/null +++ b/include/module.h @@ -0,0 +1,27 @@ +#include "common.h" +#include + +inline std::optional GetModuleFilename(DWORD processId, HMODULE module = NULL) +{ + std::vector buffer(MAX_PATH); + if (AutoHandle<> process = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, processId)) + if (GetModuleFileNameExW(process, module, buffer.data(), MAX_PATH)) return buffer.data(); + return {}; +} + +inline std::optional GetModuleFilename(HMODULE module = NULL) +{ + std::vector buffer(MAX_PATH); + if (GetModuleFileNameW(module, buffer.data(), MAX_PATH)) return buffer.data(); + return {}; +} + +inline std::vector>> GetAllProcesses() +{ + std::vector processIds(10000); + DWORD spaceUsed = 0; + EnumProcesses(processIds.data(), 10000 * sizeof(DWORD), &spaceUsed); + std::vector>> processes; + for (int i = 0; i < spaceUsed / sizeof(DWORD); ++i) processes.push_back({ processIds[i], GetModuleFilename(processIds[i]) }); + return processes; +}