mirror of
https://github.com/Artikash/Textractor.git
synced 2024-12-23 08:54:12 +08:00
improve hook search ux
This commit is contained in:
parent
bf97055155
commit
54a285b53b
@ -35,6 +35,7 @@ extern const char* PROCESSES;
|
||||
extern const char* CODE_INFODUMP;
|
||||
extern const char* FAILED_TO_CREATE_CONFIG_FILE;
|
||||
extern const char* HOOK_SEARCH_UNSTABLE_WARNING;
|
||||
extern const char* HOOK_SEARCH_STARTING_VIEW_CONSOLE;
|
||||
extern const char* SEARCH_CJK;
|
||||
extern const char* SEARCH_PATTERN;
|
||||
extern const char* SEARCH_DURATION;
|
||||
@ -99,7 +100,7 @@ namespace
|
||||
|
||||
ThreadParam ParseTextThreadString(QString ttString)
|
||||
{
|
||||
QStringList threadParam = ttString.split(":");
|
||||
auto threadParam = ttString.splitRef(":");
|
||||
return { threadParam[1].toUInt(nullptr, 16), threadParam[2].toULongLong(nullptr, 16), threadParam[3].toULongLong(nullptr, 16), threadParam[4].toULongLong(nullptr, 16) };
|
||||
}
|
||||
|
||||
@ -143,6 +144,13 @@ namespace
|
||||
return {};
|
||||
}
|
||||
|
||||
void ViewThread(int index)
|
||||
{
|
||||
ui.ttCombo->setCurrentIndex(index);
|
||||
ui.textOutput->setPlainText(sanitize(S((current = &Host::GetThread(ParseTextThreadString(ui.ttCombo->itemText(index))))->storage->c_str())));
|
||||
ui.textOutput->moveCursor(QTextCursor::End);
|
||||
}
|
||||
|
||||
void AttachProcess()
|
||||
{
|
||||
QMultiHash<QString, DWORD> allProcesses;
|
||||
@ -170,7 +178,7 @@ namespace
|
||||
{
|
||||
if (HMODULE localeEmulator = LoadLibraryW(L"LoaderDll"))
|
||||
{
|
||||
// see https://github.com/xupefei/Locale-Emulator/blob/aa99dec3b25708e676c90acf5fed9beaac319160/LEProc/LoaderWrapper.cs#L252
|
||||
// https://github.com/xupefei/Locale-Emulator/blob/aa99dec3b25708e676c90acf5fed9beaac319160/LEProc/LoaderWrapper.cs#L252
|
||||
struct
|
||||
{
|
||||
ULONG AnsiCodePage = SHIFT_JIS;
|
||||
@ -229,14 +237,11 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
void FindHooks();
|
||||
|
||||
void 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 = HookCode::Parse(S(hookCode))) try { Host::InsertHook(selectedProcessId, hp.value()); } catch (std::out_of_range) {}
|
||||
else Host::AddConsoleOutput(INVALID_CODE);
|
||||
if (auto hp = HookCode::Parse(S(hookCode))) try { Host::InsertHook(selectedProcessId, hp.value()); } catch (std::out_of_range) {}
|
||||
else Host::AddConsoleOutput(INVALID_CODE);
|
||||
}
|
||||
|
||||
void AddHook()
|
||||
@ -334,7 +339,11 @@ namespace
|
||||
layout.addRow(&confirm);
|
||||
if (!dialog.exec()) return;
|
||||
wcsncpy_s(sp.text, S(textEdit.text()).c_str(), PATTERN_SIZE - 1);
|
||||
try { Host::FindHooks(selectedProcessId, sp); } catch (std::out_of_range) {}
|
||||
try
|
||||
{
|
||||
Host::FindHooks(selectedProcessId, sp);
|
||||
ViewThread(0);
|
||||
} catch (std::out_of_range) {}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -404,6 +413,7 @@ namespace
|
||||
[hooks, filter](HookParam hp, std::wstring text) { if (filter.match(S(text)).hasMatch()) *hooks << sanitize(S(HookCode::Generate(hp) + L" => " + text)); });
|
||||
}
|
||||
catch (std::out_of_range) { return; }
|
||||
ViewThread(0);
|
||||
std::thread([hooks]
|
||||
{
|
||||
for (int lastSize = 0; hooks->size() == 0 || hooks->size() != lastSize; Sleep(2000)) lastSize = hooks->size();
|
||||
@ -434,6 +444,7 @@ namespace
|
||||
}
|
||||
hooks->clear();
|
||||
}).detach();
|
||||
QMessageBox::information(This, SEARCH_FOR_HOOKS, HOOK_SEARCH_STARTING_VIEW_CONSOLE);
|
||||
}
|
||||
|
||||
void OpenSettings()
|
||||
@ -485,13 +496,6 @@ namespace
|
||||
extenWindow->showNormal();
|
||||
}
|
||||
|
||||
void ViewThread(int index)
|
||||
{
|
||||
ui.ttCombo->setCurrentIndex(index);
|
||||
ui.textOutput->setPlainText(sanitize(S((current = &Host::GetThread(ParseTextThreadString(ui.ttCombo->itemText(index))))->storage->c_str())));
|
||||
ui.textOutput->moveCursor(QTextCursor::End);
|
||||
}
|
||||
|
||||
void SetOutputFont(QString fontString)
|
||||
{
|
||||
QFont font = ui.textOutput->font();
|
||||
|
18
text.cpp
18
text.cpp
@ -69,6 +69,7 @@ const char* EXTENSION_WRITE_ERROR = u8"Failed to save extension";
|
||||
const char* USE_JP_LOCALE = u8"Emulate japanese locale?";
|
||||
const char* FAILED_TO_CREATE_CONFIG_FILE = u8"Failed to create config file \"%1\"";
|
||||
const char* HOOK_SEARCH_UNSTABLE_WARNING = u8"Searching for hooks is unstable! Be prepared for your game to crash!";
|
||||
const char* HOOK_SEARCH_STARTING_VIEW_CONSOLE = u8"Initializing hook search - please check console for further instructions";
|
||||
const char* SEARCH_CJK = u8"Search for Chinese/Japanese/Korean";
|
||||
const char* SEARCH_PATTERN = u8"Search pattern (hex byte array)";
|
||||
const char* SEARCH_DURATION = u8"Search duration (ms)";
|
||||
@ -120,9 +121,10 @@ const char* INSERTING_HOOK = u8"Textractor: inserting hook: %s";
|
||||
const char* REMOVING_HOOK = u8"Textractor: removing hook: %s";
|
||||
const char* HOOK_FAILED = u8"Textractor: failed to insert hook";
|
||||
const char* TOO_MANY_HOOKS = u8"Textractor: too many hooks: can't insert";
|
||||
const char* STARTING_SEARCH = u8"Textractor: starting search";
|
||||
const char* HOOK_SEARCH_STARTING = u8"Textractor: starting hook search";
|
||||
const char* HOOK_SEARCH_INITIALIZING = u8"Textractor: initializing hook search (%f%%)";
|
||||
const char* NOT_ENOUGH_TEXT = u8"Textractor: not enough text to search accurately";
|
||||
const char* HOOK_SEARCH_INITIALIZED = u8"Textractor: search initialized with %zd hooks";
|
||||
const char* HOOK_SEARCH_INITIALIZED = u8"Textractor: initialized hook search with %zd hooks";
|
||||
const char* MAKE_GAME_PROCESS_TEXT = u8"Textractor: please click around in the game to force it to process text during the next %d seconds";
|
||||
const char* HOOK_SEARCH_FINISHED = u8"Textractor: hook search finished, %d results found";
|
||||
const char* OUT_OF_RECORDS_RETRY = u8"Textractor: out of search records, please retry if results are poor (default record count increased)";
|
||||
@ -145,7 +147,7 @@ const wchar_t* TOO_MANY_TRANS_REQUESTS = L"Rate limit exceeded: refuse to make m
|
||||
const wchar_t* TRANSLATION_ERROR = L"Error while translating";
|
||||
const char* USE_PREV_SENTENCE_CONTEXT = u8"Use previous sentence as context";
|
||||
const char* API_KEY = u8"API key";
|
||||
const char* CHROME_LOCATION = "Google Chrome location";
|
||||
const char* CHROME_LOCATION = "Google Chrome file location";
|
||||
const char* START_DEVTOOLS = u8"Start DevTools";
|
||||
const char* STOP_DEVTOOLS = u8"Stop DevTools";
|
||||
const char* HEADLESS_MODE = u8"Headless mode";
|
||||
@ -397,7 +399,7 @@ Clic y arrastra los bordes de la ventana para moverla, o en la esquina inferior
|
||||
REMOVING_HOOK = u8"Textractor: 移除钩子: %s";
|
||||
HOOK_FAILED = u8"Textractor: 钩子注入失败";
|
||||
TOO_MANY_HOOKS = u8"Textractor: 钩子数量已达上限: 无法注入";
|
||||
STARTING_SEARCH = u8"Textractor: 开始搜索钩子";
|
||||
HOOK_SEARCH_STARTING = u8"Textractor: 开始搜索钩子";
|
||||
NOT_ENOUGH_TEXT = u8"Textractor: 没有足够的文本用来精确搜索";
|
||||
HOOK_SEARCH_INITIALIZED = u8"Textractor: 搜索初始化完成, 创建了 %zd 个钩子";
|
||||
MAKE_GAME_PROCESS_TEXT = u8"Textractor: 请点击游戏区域, 在接下来的 %d 秒内使游戏强制处理文本";
|
||||
@ -573,7 +575,7 @@ padding: длина добавочных данных перед строкой
|
||||
REMOVING_HOOK = u8"Textractor: удаление хука: %s";
|
||||
HOOK_FAILED = u8"Textractor: не удалось вставить хук";
|
||||
TOO_MANY_HOOKS = u8"Textractor: слишком много хуков: невозможно вставить";
|
||||
STARTING_SEARCH = u8"Textractor: начало поиска";
|
||||
HOOK_SEARCH_STARTING = u8"Textractor: начало поиска";
|
||||
NOT_ENOUGH_TEXT = u8"Textractor: не достаточно текста для точного поиска";
|
||||
HOOK_SEARCH_INITIALIZED = u8"Textractor: поиск инициализирован с %zd хуками";
|
||||
MAKE_GAME_PROCESS_TEXT = u8"Textractor: покликайте в игре, чтобы вызвать смену текста в течение %d секунд";
|
||||
@ -831,7 +833,7 @@ esempio: Textractor -p4466 -p"My Game.exe" sta tentando di inniettare i processi
|
||||
REMOVING_HOOK = u8"Textractor: rimuovi gancio: %s";
|
||||
HOOK_FAILED = u8"Textractor: inserimento gancio non riuscito";
|
||||
TOO_MANY_HOOKS = u8"Textractor: troppi ganci: impossibile inserirli";
|
||||
STARTING_SEARCH = u8"Textractor: avvia la ricerca";
|
||||
HOOK_SEARCH_STARTING = u8"Textractor: avvia la ricerca";
|
||||
NOT_ENOUGH_TEXT = u8"Textractor: testo insufficente per la ricerca accurata";
|
||||
HOOK_SEARCH_INITIALIZED = u8"Textractor: ricerca inizializzata con %zd ganci";
|
||||
MAKE_GAME_PROCESS_TEXT = u8"Textractor: clicca intorno al gioco per forzarlo nel testo del processo durante i prossimi %d secondi";
|
||||
@ -977,7 +979,7 @@ Se você gostou desse projeto, divulgue a todos :))";
|
||||
REMOVING_HOOK = u8"Textractor: removendo hook: %s";
|
||||
HOOK_FAILED = u8"Textractor: falha na inserção do hook";
|
||||
TOO_MANY_HOOKS = u8"Textractor: há hooks de mais: não é possível inserir mais";
|
||||
STARTING_SEARCH = u8"Textractor: iniciando busca ";
|
||||
HOOK_SEARCH_STARTING = u8"Textractor: iniciando busca ";
|
||||
NOT_ENOUGH_TEXT = u8"Textractor: não há texto suficiente para uma buscar precisa";
|
||||
HOOK_SEARCH_INITIALIZED = u8"Textractor: busca inicializada com %zd hooks";
|
||||
HOOK_SEARCH_FINISHED = u8"Textractor: busca por hooks finalizada, %d resultados encontrados";
|
||||
@ -1251,7 +1253,7 @@ example: Textractor -p4466 -p"My Game.exe" tries to inject processes with id 446
|
||||
REMOVING_HOOK = u8"Textractor: enlève le hook: %s";
|
||||
HOOK_FAILED = u8"Textractor: n'a pas réussi à insérer un hook";
|
||||
TOO_MANY_HOOKS = u8"Textractor: trop de hooks: impossible d'insérer";
|
||||
STARTING_SEARCH = u8"Textractor: démarrage de la recherche";
|
||||
HOOK_SEARCH_STARTING = u8"Textractor: démarrage de la recherche";
|
||||
NOT_ENOUGH_TEXT = u8"Textractor: pas assez de texte pour effectuer une recherche précise";
|
||||
HOOK_SEARCH_INITIALIZED = u8"Textractor: la recherche a été initialisé avec %zd hooks";
|
||||
MAKE_GAME_PROCESS_TEXT = u8"Textractor: veuillez cliquer dans le jeu pour le forcer à traiter le texte lors de la prochaine %d seconds";
|
||||
|
@ -3,7 +3,8 @@
|
||||
#include "main.h"
|
||||
#include "util.h"
|
||||
|
||||
extern const char* STARTING_SEARCH;
|
||||
extern const char* HOOK_SEARCH_STARTING;
|
||||
extern const char* HOOK_SEARCH_INITIALIZING;
|
||||
extern const char* HOOK_SEARCH_INITIALIZED;
|
||||
extern const char* MAKE_GAME_PROCESS_TEXT;
|
||||
extern const char* HOOK_SEARCH_FINISHED;
|
||||
@ -200,12 +201,12 @@ void SearchForHooks(SearchParam spUser)
|
||||
|
||||
sp = spUser.length == 0 ? spDefault : spUser;
|
||||
|
||||
ConsoleOutput(HOOK_SEARCH_INITIALIZING, 0.);
|
||||
do
|
||||
try { records = std::make_unique<HookRecord[]>(recordsAvailable = sp.maxRecords); }
|
||||
catch (std::bad_alloc) { ConsoleOutput("Textractor: SearchForHooks ERROR: out of memory, retrying to allocate %d", sp.maxRecords /= 2); }
|
||||
while (!records && sp.maxRecords);
|
||||
|
||||
ConsoleOutput(STARTING_SEARCH);
|
||||
std::vector<uint64_t> addresses;
|
||||
if (*sp.boundaryModule) std::tie(sp.minAddress, sp.maxAddress) = Util::QueryModuleLimits(GetModuleHandleW(sp.boundaryModule));
|
||||
if (*sp.exportModule) addresses = GetFunctions((uintptr_t)GetModuleHandleW(sp.exportModule));
|
||||
@ -222,11 +223,13 @@ void SearchForHooks(SearchParam spUser)
|
||||
MH_CreateHook((void*)addresses[i], trampolines[i], &original);
|
||||
MH_QueueEnableHook((void*)addresses[i]);
|
||||
memcpy(trampolines[i], trampoline, sizeof(trampoline));
|
||||
*(uintptr_t*)(trampolines[i] + addr_offset) = addresses[i];
|
||||
*(uintptr_t*)(trampolines[i] + addr_offset) = addresses[i];
|
||||
*(void**)(trampolines[i] + original_offset) = original;
|
||||
if (i % 2500 == 0) ConsoleOutput(HOOK_SEARCH_INITIALIZING, 1 + 98. * i / addresses.size());
|
||||
}
|
||||
ConsoleOutput(HOOK_SEARCH_INITIALIZED, addresses.size());
|
||||
MH_ApplyQueued();
|
||||
ConsoleOutput(HOOK_SEARCH_STARTING);
|
||||
ConsoleOutput(MAKE_GAME_PROCESS_TEXT, sp.searchTime / 1000);
|
||||
Sleep(sp.searchTime);
|
||||
for (auto addr : addresses) MH_QueueDisableHook((void*)addr);
|
||||
@ -261,7 +264,7 @@ void SearchForText(wchar_t* text, UINT codepage)
|
||||
char codepageText[PATTERN_SIZE * 4] = {};
|
||||
WideCharToMultiByte(codepage, 0, text, PATTERN_SIZE, codepageText, PATTERN_SIZE * 4, nullptr, nullptr);
|
||||
if (strlen(utf8Text) < 4 || strlen(codepageText) < 4 || wcslen(text) < 4) return ConsoleOutput(NOT_ENOUGH_TEXT);
|
||||
ConsoleOutput(STARTING_SEARCH);
|
||||
ConsoleOutput(HOOK_SEARCH_STARTING);
|
||||
auto GenerateHooks = [&](std::vector<uint64_t> addresses, HookParamType type)
|
||||
{
|
||||
for (auto addr : addresses)
|
||||
|
Loading…
x
Reference in New Issue
Block a user