From 7324cf42292838fd712f92fb5506758ebcb491e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=81=8D=E5=85=AE=E6=83=9A=E5=85=AE?= <101191390+HIllya51@users.noreply.github.com> Date: Sun, 21 Jul 2024 21:07:05 +0800 Subject: [PATCH] fmt --- include/const.h | 126 ++++++++------- include/defs.h | 6 +- include/hookcode.cpp | 345 +++++++++++++++++++++------------------ include/pch.h | 16 +- include/stringutils.cpp | 348 ++++++++++++++++++++++------------------ include/stringutils.h | 60 +++---- include/texthook.h | 30 ++-- include/types.h | 134 +++++++++------- include/utils.h | 97 +++++++---- include/winevent.hpp | 23 +-- 10 files changed, 663 insertions(+), 522 deletions(-) diff --git a/include/const.h b/include/const.h index 8a9be90..476b189 100644 --- a/include/const.h +++ b/include/const.h @@ -4,82 +4,96 @@ // 8/23/2013 jichi // Branch: ITH/common.h, rev 128 -enum { STRING = 12, MESSAGE_SIZE = 500, PIPE_BUFFER_SIZE = 50000, SHIFT_JIS = 932, MAX_MODULE_SIZE = 120, PATTERN_SIZE = 30, HOOK_NAME_SIZE = 60, FIXED_SPLIT_VALUE = 0x10001 , -HOOKCODE_LEN=500}; -enum WildcardByte { XX = 0x11 }; - -enum HostCommandType { - HOST_COMMAND_NEW_HOOK, - HOST_COMMAND_REMOVE_HOOK, - HOST_COMMAND_FIND_HOOK, - HOST_COMMAND_MODIFY_HOOK, - HOST_COMMAND_HIJACK_PROCESS, - HOST_COMMAND_DETACH +enum +{ + STRING = 12, + MESSAGE_SIZE = 500, + PIPE_BUFFER_SIZE = 50000, + SHIFT_JIS = 932, + MAX_MODULE_SIZE = 120, + PATTERN_SIZE = 30, + HOOK_NAME_SIZE = 60, + FIXED_SPLIT_VALUE = 0x10001, + HOOKCODE_LEN = 500 +}; +enum WildcardByte +{ + XX = 0x11 }; -enum HostNotificationType { - HOST_NOTIFICATION_TEXT, - HOST_NOTIFICATION_NEWHOOK, - HOST_NOTIFICATION_FOUND_HOOK, +enum HostCommandType +{ + HOST_COMMAND_NEW_HOOK, + HOST_COMMAND_REMOVE_HOOK, + HOST_COMMAND_FIND_HOOK, + HOST_COMMAND_MODIFY_HOOK, + HOST_COMMAND_HIJACK_PROCESS, + HOST_COMMAND_DETACH +}; + +enum HostNotificationType +{ + HOST_NOTIFICATION_TEXT, + HOST_NOTIFICATION_NEWHOOK, + HOST_NOTIFICATION_FOUND_HOOK, HOST_NOTIFICATION_RMVHOOK, HOST_NOTIFICATION_INSERTING_HOOK, HOST_SETTEXTTHREADTYPE }; -#define NEXT_MASK(x) \ - DUMMY1_##x, \ - x = (1U << (DUMMY1_##x)), \ - DUMMY2_##x = DUMMY1_##x -#define DECLARE_VALUE( x,v) \ - DUMMY1_##x,\ - x=v,\ - DUMMY2_##x=DUMMY1_##x-1 +#define NEXT_MASK(x) \ + DUMMY1_##x, \ + x = (1U << (DUMMY1_##x)), \ + DUMMY2_##x = DUMMY1_##x +#define DECLARE_VALUE(x, v) \ + DUMMY1_##x, \ + x = v, \ + DUMMY2_##x = DUMMY1_##x - 1 enum HookParamType : uint64_t { - //默认为CODEC_ANSI_LE&USING_CHAR - //若使用了text_fun|hook_before,会改为默认USING_STRING,这时若其实是USING_CHAR,需标明USING_STRING - DECLARE_VALUE(CODEC_ANSI_LE,0), + // 默认为CODEC_ANSI_LE&USING_CHAR + // 若使用了text_fun|hook_before,会改为默认USING_STRING,这时若其实是USING_CHAR,需标明USING_STRING + DECLARE_VALUE(CODEC_ANSI_LE, 0), NEXT_MASK(CODEC_ANSI_BE), - NEXT_MASK(CODEC_UTF8), - NEXT_MASK(CODEC_UTF16), + NEXT_MASK(CODEC_UTF8), + NEXT_MASK(CODEC_UTF16), NEXT_MASK(CODEC_UTF32), - NEXT_MASK(USING_CHAR),//text_fun!=nullptr && (CODE_ANSI_BE||CODE_UTF16) - NEXT_MASK(USING_STRING), + NEXT_MASK(USING_CHAR), // text_fun!=nullptr && (CODE_ANSI_BE||CODE_UTF16) + NEXT_MASK(USING_STRING), NEXT_MASK(SPECIAL_JIT_STRING), - - NEXT_MASK(FULL_STRING), - NEXT_MASK(DATA_INDIRECT), - NEXT_MASK(USING_SPLIT), // use ctx2 or not - NEXT_MASK(SPLIT_INDIRECT), - NEXT_MASK(FIXING_SPLIT), - NEXT_MASK(NO_CONTEXT), + NEXT_MASK(FULL_STRING), - NEXT_MASK(MODULE_OFFSET), // address is relative to module - NEXT_MASK(FUNCTION_OFFSET), // address is relative to function + NEXT_MASK(DATA_INDIRECT), + NEXT_MASK(USING_SPLIT), // use ctx2 or not + NEXT_MASK(SPLIT_INDIRECT), + NEXT_MASK(FIXING_SPLIT), + NEXT_MASK(NO_CONTEXT), - NEXT_MASK(KNOWN_UNSTABLE), + NEXT_MASK(MODULE_OFFSET), // address is relative to module + NEXT_MASK(FUNCTION_OFFSET), // address is relative to function - NEXT_MASK(EMBED_ABLE), - NEXT_MASK(EMBED_DYNA_SJIS), - NEXT_MASK(EMBED_BEFORE_SIMPLE), - NEXT_MASK(EMBED_AFTER_NEW), - NEXT_MASK(EMBED_AFTER_OVERWRITE), + NEXT_MASK(KNOWN_UNSTABLE), + + NEXT_MASK(EMBED_ABLE), + NEXT_MASK(EMBED_DYNA_SJIS), + NEXT_MASK(EMBED_BEFORE_SIMPLE), + NEXT_MASK(EMBED_AFTER_NEW), + NEXT_MASK(EMBED_AFTER_OVERWRITE), NEXT_MASK(EMBED_CODEC_UTF16), - DECLARE_VALUE(NORMAL_INLINEHOOK,0), + DECLARE_VALUE(NORMAL_INLINEHOOK, 0), NEXT_MASK(BREAK_POINT), - NEXT_MASK(DIRECT_READ), // /R read code instead of classic /H hook code + NEXT_MASK(DIRECT_READ), // /R read code instead of classic /H hook code NEXT_MASK(HOOK_RETURN), - NEXT_MASK(HOOK_EMPTY), + NEXT_MASK(HOOK_EMPTY), }; - enum HookFontType : unsigned { - DECLARE_VALUE(NOT_HOOK_FONT,0), + DECLARE_VALUE(NOT_HOOK_FONT, 0), NEXT_MASK(F_CreateFontA), NEXT_MASK(F_CreateFontW), NEXT_MASK(F_CreateFontIndirectA), @@ -90,8 +104,8 @@ enum HookFontType : unsigned NEXT_MASK(F_GetTextExtentPoint32W), NEXT_MASK(F_GetTextExtentExPointA), NEXT_MASK(F_GetTextExtentExPointW), - //F_GetCharABCWidthsA=0x - //F_GetCharABCWidthsW=0x + // F_GetCharABCWidthsA=0x + // F_GetCharABCWidthsW=0x NEXT_MASK(F_TextOutA), NEXT_MASK(F_TextOutW), NEXT_MASK(F_ExtTextOutA), @@ -101,11 +115,11 @@ enum HookFontType : unsigned NEXT_MASK(F_DrawTextExA), NEXT_MASK(F_DrawTextExW), NEXT_MASK(F_CharNextA), - //F_CharNextW=0x - //F_CharNextExA=0x - //F_CharNextExW=0x + // F_CharNextW=0x + // F_CharNextExA=0x + // F_CharNextExW=0x NEXT_MASK(F_CharPrevA), - //F_CharPrevW=0x + // F_CharPrevW=0x NEXT_MASK(F_MultiByteToWideChar), NEXT_MASK(F_WideCharToMultiByte), }; \ No newline at end of file diff --git a/include/defs.h b/include/defs.h index 7ecfd49..510fc81 100644 --- a/include/defs.h +++ b/include/defs.h @@ -18,13 +18,13 @@ constexpr auto ITH_HOOKMAN_MUTEX_ = L"LUNA_VNR_HOOKMAN_"; // ITH_HOOKMAN_%d constexpr auto CONNECTING_MUTEX = L"LUNA_CONNECTING_PIPES"; // Events -constexpr auto LUNA_EMBED_notify_event="LUNA_NOTIFY.%d.%llu"; +constexpr auto LUNA_EMBED_notify_event = "LUNA_NOTIFY.%d.%llu"; constexpr auto PIPE_AVAILABLE_EVENT = L"LUNA_PIPE_AVAILABLE"; // Files -constexpr auto LUNA_HOOK_DLL_64=L"LunaHook64"; -constexpr auto LUNA_HOOK_DLL_32=L"LunaHook32"; +constexpr auto LUNA_HOOK_DLL_64 = L"LunaHook64"; +constexpr auto LUNA_HOOK_DLL_32 = L"LunaHook32"; #ifdef _WIN64 constexpr auto LUNA_HOOK_DLL = LUNA_HOOK_DLL_64; // .dll but LoadLibrary automatically adds that diff --git a/include/hookcode.cpp b/include/hookcode.cpp index 5b54a7f..11c516f 100644 --- a/include/hookcode.cpp +++ b/include/hookcode.cpp @@ -3,7 +3,7 @@ namespace { std::optional ParseRCode(std::wstring RCode) { - RCode.erase(0,1); + RCode.erase(0, 1); std::wsmatch match; HookParam hp; hp.type |= DIRECT_READ; @@ -35,40 +35,42 @@ namespace } // @addr - if (!std::regex_match(RCode, match, std::wregex(L"@([[:xdigit:]]+)"))) return {}; + if (!std::regex_match(RCode, match, std::wregex(L"@([[:xdigit:]]+)"))) + return {}; hp.address = std::stoull(match[1], nullptr, 16); return hp; } - std::optional ParseHCode(std::wstring HCode,std::optional hpo={}) + std::optional ParseHCode(std::wstring HCode, std::optional hpo = {}) { - auto hp=hpo?hpo.value():HookParam{}; - if(HCode[0]=='L'){ - hp.type|=HOOK_RETURN; - HCode.erase(0,1); + auto hp = hpo ? hpo.value() : HookParam{}; + if (HCode[0] == 'L') + { + hp.type |= HOOK_RETURN; + HCode.erase(0, 1); } switch (HCode[0]) { - case L'B': - hp.type|=BREAK_POINT; - case L'H': - break; - default: - return {}; + case L'B': + hp.type |= BREAK_POINT; + case L'H': + break; + default: + return {}; } - - HCode.erase(0,1); - if(endWith(HCode,L":JIT:YUZU")) - hp.jittype=JITTYPE::YUZU; - else if(endWith(HCode,L":JIT:PPSSPP")) - hp.jittype=JITTYPE::PPSSPP; - else if(endWith(HCode,L":JIT:VITA3K")) - hp.jittype=JITTYPE::VITA3K; - else if(endWith(HCode,L":JIT:RPCS3")) - hp.jittype=JITTYPE::RPCS3; - else if(endWith(HCode,L":JIT:UNITY")) - hp.jittype=JITTYPE::UNITY; + HCode.erase(0, 1); + + if (endWith(HCode, L":JIT:YUZU")) + hp.jittype = JITTYPE::YUZU; + else if (endWith(HCode, L":JIT:PPSSPP")) + hp.jittype = JITTYPE::PPSSPP; + else if (endWith(HCode, L":JIT:VITA3K")) + hp.jittype = JITTYPE::VITA3K; + else if (endWith(HCode, L":JIT:RPCS3")) + hp.jittype = JITTYPE::RPCS3; + else if (endWith(HCode, L":JIT:UNITY")) + hp.jittype = JITTYPE::UNITY; // {A|B|W|H|S|Q|V|M} switch (HCode[0]) @@ -77,7 +79,7 @@ namespace hp.type |= CODEC_ANSI_BE; break; case L'B': - //ANSI LE + // ANSI LE break; case L'W': hp.type |= CODEC_UTF16; @@ -92,7 +94,7 @@ namespace hp.type |= USING_STRING | CODEC_UTF16; break; case L'M': - hp.type |=SPECIAL_JIT_STRING|USING_STRING|CODEC_UTF16; + hp.type |= SPECIAL_JIT_STRING | USING_STRING | CODEC_UTF16; break; case L'U': hp.type |= USING_STRING | CODEC_UTF32; @@ -112,7 +114,6 @@ namespace hp.type |= FULL_STRING; HCode.erase(0, 1); } - } // [N] @@ -121,7 +122,7 @@ namespace hp.type |= NO_CONTEXT; HCode.erase(0, 1); } - + std::wsmatch match; // [codepage#] if (std::regex_search(HCode, match, std::wregex(L"^([0-9]+)#"))) @@ -141,7 +142,13 @@ namespace { size_t size = 0; int value = 0; - try { value = std::stoi(HCode, &size, 16); } catch (std::invalid_argument) {} + try + { + value = std::stoi(HCode, &size, 16); + } + catch (std::invalid_argument) + { + } HCode.erase(0, size); return value; }; @@ -171,102 +178,110 @@ namespace hp.split_index = ConsumeHexInt(); } } - if(hp.jittype==JITTYPE::UNITY){ - if(HCode[0]!=L'@')return {}; - HCode.erase(0,1); - HCode=HCode.substr(0,HCode.size()-wcslen(L":JIT:UNITY")); - hp.argidx=hp.offset; - hp.offset=0; - hp.address=0; + if (hp.jittype == JITTYPE::UNITY) + { + if (HCode[0] != L'@') + return {}; + HCode.erase(0, 1); + HCode = HCode.substr(0, HCode.size() - wcslen(L":JIT:UNITY")); + hp.argidx = hp.offset; + hp.offset = 0; + hp.address = 0; hp.type &= ~MODULE_OFFSET; hp.type &= ~FUNCTION_OFFSET; - strcpy(hp.function,""); - wcscpy(hp.module,L""); - strcpy(hp.unityfunctioninfo,wcasta(HCode).c_str()); + strcpy(hp.function, ""); + wcscpy(hp.module, L""); + strcpy(hp.unityfunctioninfo, wcasta(HCode).c_str()); } - else{ - - // @addr[:module[:func]] - if (!std::regex_match(HCode, match, std::wregex(L"^@([[:xdigit:]]+)(:.+?)?(:.+)?"))) return {}; - hp.address = std::stoull(match[1], nullptr, 16); - if (match[2].matched) + else { - hp.type |= MODULE_OFFSET; - wcsncpy_s(hp.module, match[2].str().erase(0, 1).c_str(), MAX_MODULE_SIZE - 1); - } - if (match[3].matched) - { - hp.type |= FUNCTION_OFFSET; - std::wstring func = match[3]; - strncpy_s(hp.function, std::string(func.begin(), func.end()).erase(0, 1).c_str(), MAX_MODULE_SIZE - 1); - } - // ITH has registers offset by 4 vs AGTH: need this to correct - if (hp.offset < 0) hp.offset -= 4; - if (hp.split < 0) hp.split -= 4; - - if(hp.jittype!=JITTYPE::PC){ - hp.emu_addr=hp.address; - hp.argidx=hp.offset; - hp.offset=0; - hp.address=0; - hp.type &= ~MODULE_OFFSET; - hp.type &= ~FUNCTION_OFFSET; - strcpy(hp.function,""); - wcscpy(hp.module,L""); - } + // @addr[:module[:func]] + if (!std::regex_match(HCode, match, std::wregex(L"^@([[:xdigit:]]+)(:.+?)?(:.+)?"))) + return {}; + hp.address = std::stoull(match[1], nullptr, 16); + if (match[2].matched) + { + hp.type |= MODULE_OFFSET; + wcsncpy_s(hp.module, match[2].str().erase(0, 1).c_str(), MAX_MODULE_SIZE - 1); + } + if (match[3].matched) + { + hp.type |= FUNCTION_OFFSET; + std::wstring func = match[3]; + strncpy_s(hp.function, std::string(func.begin(), func.end()).erase(0, 1).c_str(), MAX_MODULE_SIZE - 1); + } + + // ITH has registers offset by 4 vs AGTH: need this to correct + if (hp.offset < 0) + hp.offset -= 4; + if (hp.split < 0) + hp.split -= 4; + + if (hp.jittype != JITTYPE::PC) + { + hp.emu_addr = hp.address; + hp.argidx = hp.offset; + hp.offset = 0; + hp.address = 0; + hp.type &= ~MODULE_OFFSET; + hp.type &= ~FUNCTION_OFFSET; + strcpy(hp.function, ""); + wcscpy(hp.module, L""); + } } return hp; } std::optional ParseECode(std::wstring code) - { - code.erase(0,1); + { + code.erase(0, 1); HookParam hp; - hp.type|=EMBED_ABLE; + hp.type |= EMBED_ABLE; - if(code[0]==L'D') + if (code[0] == L'D') { - hp.type|=EMBED_DYNA_SJIS; - code.erase(0,1); + hp.type |= EMBED_DYNA_SJIS; + code.erase(0, 1); } - if(code[0]==L'S') + if (code[0] == L'S') { - code.erase(0,1); - hp.type|=EMBED_BEFORE_SIMPLE; + code.erase(0, 1); + hp.type |= EMBED_BEFORE_SIMPLE; - if(code[0]==L'N') - hp.type|=EMBED_AFTER_NEW; - else if(code[0]==L'O') - hp.type|=EMBED_AFTER_OVERWRITE; + if (code[0] == L'N') + hp.type |= EMBED_AFTER_NEW; + else if (code[0] == L'O') + hp.type |= EMBED_AFTER_OVERWRITE; else - return ParseHCode(code,hp); - code.erase(0,1); + return ParseHCode(code, hp); + code.erase(0, 1); } - - return ParseHCode(code,hp); - + + return ParseHCode(code, hp); } std::wstring HexString(int64_t num) { - if (num < 0) return FormatString(L"-%I64X", -num); + if (num < 0) + return FormatString(L"-%I64X", -num); return FormatString(L"%I64X", num); } std::wstring GenerateRCode(HookParam hp) { std::wstring RCode = L"R"; - - if(hp.type&CODEC_UTF16) + + if (hp.type & CODEC_UTF16) RCode += L'Q'; - else if (hp.type&CODEC_UTF32) + else if (hp.type & CODEC_UTF32) RCode += L'U'; - else if (hp.type&CODEC_UTF8) + else if (hp.type & CODEC_UTF8) RCode += L'V'; else { RCode += L'S'; - if (hp.codepage != 0) RCode += std::to_wstring(hp.codepage) + L'#'; + if (hp.codepage != 0) + RCode += std::to_wstring(hp.codepage) + L'#'; } RCode += L'@' + HexString(hp.address); @@ -277,83 +292,93 @@ namespace std::wstring GenerateHCode(HookParam hp, DWORD processId) { std::wstring HCode; - if(hp.type&EMBED_ABLE) + if (hp.type & EMBED_ABLE) { - HCode +=L"E"; - - if (hp.hook_before || hp.hook_after) - HCode += L'X'; + HCode += L"E"; + + if (hp.hook_before || hp.hook_after) + HCode += L'X'; else { - if(hp.type&EMBED_DYNA_SJIS) - HCode+=L"D"; - if(hp.type&EMBED_BEFORE_SIMPLE) - HCode+=L"S"; + if (hp.type & EMBED_DYNA_SJIS) + HCode += L"D"; + if (hp.type & EMBED_BEFORE_SIMPLE) + HCode += L"S"; - if(hp.type&EMBED_AFTER_NEW) - HCode+=L"N"; - else if(hp.type&EMBED_AFTER_OVERWRITE) - HCode+=L"O"; + if (hp.type & EMBED_AFTER_NEW) + HCode += L"N"; + else if (hp.type & EMBED_AFTER_OVERWRITE) + HCode += L"O"; } - } - if(hp.type&BREAK_POINT) - HCode+=L"B"; + if (hp.type & BREAK_POINT) + HCode += L"B"; else HCode += L"H"; - - if(hp.type & USING_STRING) + if (hp.type & USING_STRING) { - if(hp.type&SPECIAL_JIT_STRING) - HCode+=L'M'; - else if(hp.type&CODEC_UTF16) + if (hp.type & SPECIAL_JIT_STRING) + HCode += L'M'; + else if (hp.type & CODEC_UTF16) HCode += L'Q'; - else if(hp.type&CODEC_UTF8) + else if (hp.type & CODEC_UTF8) HCode += L'V'; - else if(hp.type&CODEC_UTF32) + else if (hp.type & CODEC_UTF32) HCode += L'U'; - else + else HCode += L'S'; } else { - if(hp.type&CODEC_UTF16) + if (hp.type & CODEC_UTF16) HCode += L'W'; - else if(hp.type&CODEC_UTF32) + else if (hp.type & CODEC_UTF32) HCode += L'I'; - else if (hp.type & CODEC_ANSI_BE) + else if (hp.type & CODEC_ANSI_BE) HCode += L'A'; - else + else HCode += L'B'; } - - if (hp.text_fun || hp.filter_fun) HCode += L'X'; - - if (hp.type & FULL_STRING) HCode += L'F'; - if (hp.type & NO_CONTEXT) HCode += L'N'; + if (hp.text_fun || hp.filter_fun) + HCode += L'X'; - if (hp.codepage != 0 && !(hp.type & CODEC_UTF8)&&!(hp.type & CODEC_UTF16)&&!(hp.type & CODEC_UTF32) ) HCode += std::to_wstring(hp.codepage) + L'#'; + if (hp.type & FULL_STRING) + HCode += L'F'; - if (hp.padding) HCode += HexString(hp.padding) + L'+'; + if (hp.type & NO_CONTEXT) + HCode += L'N'; - if (hp.offset < 0) hp.offset += 4; - if (hp.split < 0) hp.split += 4; - - if(hp.jittype==JITTYPE::PC){ + if (hp.codepage != 0 && !(hp.type & CODEC_UTF8) && !(hp.type & CODEC_UTF16) && !(hp.type & CODEC_UTF32)) + HCode += std::to_wstring(hp.codepage) + L'#'; + + if (hp.padding) + HCode += HexString(hp.padding) + L'+'; + + if (hp.offset < 0) + hp.offset += 4; + if (hp.split < 0) + hp.split += 4; + + if (hp.jittype == JITTYPE::PC) + { HCode += HexString(hp.offset); } - else{ + else + { HCode += HexString(hp.argidx); } - if (hp.type & DATA_INDIRECT) HCode += L'*' + HexString(hp.index); - if (hp.type & USING_SPLIT) HCode += L':' + HexString(hp.split); - if (hp.type & SPLIT_INDIRECT) HCode += L'*' + HexString(hp.split_index); + if (hp.type & DATA_INDIRECT) + HCode += L'*' + HexString(hp.index); + if (hp.type & USING_SPLIT) + HCode += L':' + HexString(hp.split); + if (hp.type & SPLIT_INDIRECT) + HCode += L'*' + HexString(hp.split_index); // Attempt to make the address relative - if(hp.jittype==JITTYPE::PC) + if (hp.jittype == JITTYPE::PC) { if (processId && !(hp.type & MODULE_OFFSET)) if (AutoHandle<> process = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, processId)) @@ -366,32 +391,36 @@ namespace } HCode += L'@' + HexString(hp.address); - if (hp.type & MODULE_OFFSET) HCode += L':' + std::wstring(hp.module); - if (hp.type & FUNCTION_OFFSET) HCode += L':' + StringToWideString(hp.function); + if (hp.type & MODULE_OFFSET) + HCode += L':' + std::wstring(hp.module); + if (hp.type & FUNCTION_OFFSET) + HCode += L':' + StringToWideString(hp.function); } else - { - if(hp.jittype== JITTYPE::UNITY){ - HCode+=L'@'; - HCode+=acastw(hp.unityfunctioninfo); - HCode+=L":JIT:UNITY"; + { + if (hp.jittype == JITTYPE::UNITY) + { + HCode += L'@'; + HCode += acastw(hp.unityfunctioninfo); + HCode += L":JIT:UNITY"; } - else{ + else + { HCode += L'@' + HexString(hp.emu_addr); switch (hp.jittype) { - case JITTYPE::YUZU: - HCode+=L":JIT:YUZU"; + case JITTYPE::YUZU: + HCode += L":JIT:YUZU"; break; case JITTYPE::PPSSPP: - HCode+=L":JIT:PPSSPP"; + HCode += L":JIT:PPSSPP"; break; case JITTYPE::VITA3K: - HCode+=L":JIT:VITA3K"; + HCode += L":JIT:VITA3K"; break; case JITTYPE::RPCS3: - HCode+=L":JIT:RPCS3"; + HCode += L":JIT:RPCS3"; break; } } @@ -405,18 +434,22 @@ namespace HookCode { std::optional Parse(std::wstring code) { - if (code[0] == L'/') code.erase(0, 1); + if (code[0] == L'/') + code.erase(0, 1); code.erase(std::find(code.begin(), code.end(), L'/'), code.end()); // legacy/AGTH compatibility Trim(code); - if (code[0] == L'R') return ParseRCode(code); - else if (code[0] == L'E') return ParseECode(code); - else return ParseHCode(code); + if (code[0] == L'R') + return ParseRCode(code); + else if (code[0] == L'E') + return ParseECode(code); + else + return ParseHCode(code); } std::wstring Generate(HookParam hp, DWORD processId) { - std::wstring HCode =L""; - return HCode+=(hp.type & DIRECT_READ ? GenerateRCode(hp) : GenerateHCode(hp, processId)); + std::wstring HCode = L""; + return HCode += (hp.type & DIRECT_READ ? GenerateRCode(hp) : GenerateHCode(hp, processId)); } } diff --git a/include/pch.h b/include/pch.h index e54ed47..ee0f28b 100644 --- a/include/pch.h +++ b/include/pch.h @@ -33,11 +33,11 @@ #include #include -#include"stringutils.h" -#include"utils.h" -#include"defs.h" -#include"const.h" -#include"types.h" -#include"hookcode.h" -#include"texthook.h" -#include"winevent.hpp" \ No newline at end of file +#include "stringutils.h" +#include "utils.h" +#include "defs.h" +#include "const.h" +#include "types.h" +#include "hookcode.h" +#include "texthook.h" +#include "winevent.hpp" \ No newline at end of file diff --git a/include/stringutils.cpp b/include/stringutils.cpp index 7506bd6..5d25c16 100644 --- a/include/stringutils.cpp +++ b/include/stringutils.cpp @@ -1,5 +1,5 @@ -LPCSTR reverse_search_begin(const char *s, int maxsize ) +LPCSTR reverse_search_begin(const char *s, int maxsize) { if (*s) for (int i = 0; i < maxsize; i++, s--) @@ -8,205 +8,237 @@ LPCSTR reverse_search_begin(const char *s, int maxsize ) return nullptr; } -template -inline bool all_ascii_impl(const CharT* s,int maxsize){ +template +inline bool all_ascii_impl(const CharT *s, int maxsize) +{ if (s) for (int i = 0; i < maxsize && *s; i++, s++) - if ((unsigned)*s > 127) + if ((unsigned)*s > 127) return false; return true; } -template -inline void strReplace_impl(StringT& str, const StringT& oldStr, const StringT& newStr){ +template +inline void strReplace_impl(StringT &str, const StringT &oldStr, const StringT &newStr) +{ size_t pos = 0; - while ((pos = str.find(oldStr, pos)) != StringT::npos) { - str.replace(pos, oldStr.length(), newStr); - pos += newStr.length(); - } + while ((pos = str.find(oldStr, pos)) != StringT::npos) + { + str.replace(pos, oldStr.length(), newStr); + pos += newStr.length(); + } } +template +inline std::vector strSplit_impl(const StringT &s, const StringT &delim) +{ + StringT item; + std::vector tokens; -template -inline std::vector strSplit_impl(const StringT& s, const StringT& delim){ - StringT item; - std::vector tokens; + StringT str = s; - StringT str = s; - - size_t pos = 0; - while ((pos = str.find(delim)) != StringT::npos) { - item = str.substr(0, pos); - tokens.push_back(item); - str.erase(0, pos + delim.length()); - } - tokens.push_back(str); - return tokens; + size_t pos = 0; + while ((pos = str.find(delim)) != StringT::npos) + { + item = str.substr(0, pos); + tokens.push_back(item); + str.erase(0, pos + delim.length()); + } + tokens.push_back(str); + return tokens; } -template -inline bool endWith_impl(const StringT& s,const StringT& s2) { - if ((s.size() > s2.size()) && (s.substr(s.size() - s2.size(), s2.size()) == s2)) { - return true; - } - return false; -} +template +inline bool endWith_impl(const StringT &s, const StringT &s2) +{ + if ((s.size() > s2.size()) && (s.substr(s.size() - s2.size(), s2.size()) == s2)) + { + return true; + } + return false; +} -template -inline bool startWith_impl(const StringT& s,const StringT& s2) { - if ((s.size() > s2.size()) && (s.substr(0, s2.size()) == s2)) { - return true; - } - return false; -} +template +inline bool startWith_impl(const StringT &s, const StringT &s2) +{ + if ((s.size() > s2.size()) && (s.substr(0, s2.size()) == s2)) + { + return true; + } + return false; +} +bool all_ascii(const char *s, int maxsize) { return all_ascii_impl(s, maxsize); } +bool all_ascii(const wchar_t *s, int maxsize) { return all_ascii_impl(s, maxsize); } -bool all_ascii(const char *s, int maxsize ){return all_ascii_impl(s,maxsize);} -bool all_ascii(const wchar_t *s, int maxsize ){return all_ascii_impl(s,maxsize);} +void strReplace(std::string &str, const std::string &oldStr, const std::string &newStr) { strReplace_impl(str, oldStr, newStr); } +void strReplace(std::wstring &str, const std::wstring &oldStr, const std::wstring &newStr) { strReplace_impl(str, oldStr, newStr); } +std::vector strSplit(const std::string &s, const std::string &delim) { return strSplit_impl(s, delim); } +std::vector strSplit(const std::wstring &s, const std::wstring &delim) { return strSplit_impl(s, delim); } +bool startWith(const std::string &s, const std::string &s2) { return startWith_impl(s, s2); } +bool startWith(const std::wstring &s, const std::wstring &s2) { return startWith_impl(s, s2); } +bool endWith(const std::string &s, const std::string &s2) { return endWith_impl(s, s2); } +bool endWith(const std::wstring &s, const std::wstring &s2) { return endWith_impl(s, s2); } -void strReplace(std::string& str, const std::string& oldStr, const std::string& newStr){strReplace_impl(str,oldStr,newStr);} -void strReplace(std::wstring& str, const std::wstring& oldStr, const std::wstring& newStr){strReplace_impl(str,oldStr,newStr);} -std::vector strSplit(const std::string& s, const std::string& delim){return strSplit_impl(s,delim);} -std::vector strSplit(const std::wstring& s, const std::wstring& delim){return strSplit_impl(s,delim);} -bool startWith(const std::string& s,const std::string& s2){return startWith_impl(s,s2);} -bool startWith(const std::wstring& s,const std::wstring& s2){return startWith_impl(s,s2);} -bool endWith(const std::string& s,const std::string& s2){return endWith_impl(s,s2);} -bool endWith(const std::wstring& s,const std::wstring& s2){return endWith_impl(s,s2);} - -typedef HRESULT(WINAPI* CONVERTINETMULTIBYTETOUNICODE)( +typedef HRESULT(WINAPI *CONVERTINETMULTIBYTETOUNICODE)( LPDWORD lpdwMode, DWORD dwSrcEncoding, LPCSTR lpSrcStr, LPINT lpnMultiCharCount, LPWSTR lpDstStr, - LPINT lpnWideCharCount - ); -typedef HRESULT(WINAPI* CONVERTINETUNICODETOMULTIBYTE)( + LPINT lpnWideCharCount); +typedef HRESULT(WINAPI *CONVERTINETUNICODETOMULTIBYTE)( LPDWORD lpdwMode, DWORD dwEncoding, LPCWSTR lpSrcStr, LPINT lpnWideCharCount, LPSTR lpDstStr, - LPINT lpnMultiCharCount - ); + LPINT lpnMultiCharCount); -std::optional StringToWideString(const std::string& text, UINT encoding) +std::optional StringToWideString(const std::string &text, UINT encoding) { - std::vector buffer(text.size() + 1); - if(disable_mbwc){ - int _s = text.size(); int _s2 = buffer.size(); - auto h=LoadLibrary(TEXT("mlang.dll")); - if(h==0)return {}; - auto ConvertINetMultiByteToUnicode = (CONVERTINETMULTIBYTETOUNICODE)GetProcAddress(h, "ConvertINetMultiByteToUnicode"); - if(ConvertINetMultiByteToUnicode==0)return {}; - auto hr=ConvertINetMultiByteToUnicode(0, encoding, text.c_str(), &_s, buffer.data(), &_s2); - if(SUCCEEDED(hr)){ - return std::wstring(buffer.data(), _s2 ); - } - else return{}; - } - else{ - 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::wstring StringToWideString(const std::string& text) -{ - return StringToWideString(text,CP_UTF8).value(); -} - -std::string WideStringToString(const std::wstring& text,UINT cp) -{ - std::vector buffer((text.size() + 1) * 4); - if(disable_wcmb){ - int _s = text.size(); int _s2 = buffer.size(); - auto h=LoadLibrary(TEXT("mlang.dll")); - if(h==0)return {}; - auto ConvertINetUnicodeToMultiByte = (CONVERTINETUNICODETOMULTIBYTE)GetProcAddress(h, "ConvertINetUnicodeToMultiByte"); - if(ConvertINetUnicodeToMultiByte==0)return {}; - auto hr=ConvertINetUnicodeToMultiByte(0, cp, text.c_str(), &_s, buffer.data(), &_s2); - if(SUCCEEDED(hr)){ - return std::string(buffer.data(), _s2 ); - } - else return{}; - } - else{ - WideCharToMultiByte(cp, 0, text.c_str(), -1, buffer.data(), buffer.size(), nullptr, nullptr); - return buffer.data(); - } -} -inline unsigned int convertUTF32ToUTF16(unsigned int cUTF32, unsigned int& h, unsigned int& l) -{ - if (cUTF32 < 0x10000) - { - h = 0; - l = cUTF32; - return cUTF32; - } - unsigned int t = cUTF32 - 0x10000; - h = (((t << 12) >> 22) + 0xD800); - l = (((t << 22) >> 22) + 0xDC00); - unsigned int ret = ((h << 16) | (l & 0x0000FFFF)); - return ret; -} - -std::basic_string utf16_to_utf32(const wchar_t* u16str,size_t size){ - std::basic_string utf32String; - for (size_t i=0;i buffer(text.size() + 1); + if (disable_mbwc) { - auto u16c=u16str[i]; - if(u16c-0xd800u<2048u) - if((u16c&0xfffffc00==0xd800)&&(i buffer((text.size() + 1) * 4); + if (disable_wcmb) + { + int _s = text.size(); + int _s2 = buffer.size(); + auto h = LoadLibrary(TEXT("mlang.dll")); + if (h == 0) + return {}; + auto ConvertINetUnicodeToMultiByte = (CONVERTINETUNICODETOMULTIBYTE)GetProcAddress(h, "ConvertINetUnicodeToMultiByte"); + if (ConvertINetUnicodeToMultiByte == 0) + return {}; + auto hr = ConvertINetUnicodeToMultiByte(0, cp, text.c_str(), &_s, buffer.data(), &_s2); + if (SUCCEEDED(hr)) + { + return std::string(buffer.data(), _s2); + } + else + return {}; + } + else + { + WideCharToMultiByte(cp, 0, text.c_str(), -1, buffer.data(), buffer.size(), nullptr, nullptr); + return buffer.data(); + } +} +inline unsigned int convertUTF32ToUTF16(unsigned int cUTF32, unsigned int &h, unsigned int &l) +{ + if (cUTF32 < 0x10000) + { + h = 0; + l = cUTF32; + return cUTF32; + } + unsigned int t = cUTF32 - 0x10000; + h = (((t << 12) >> 22) + 0xD800); + l = (((t << 22) >> 22) + 0xDC00); + unsigned int ret = ((h << 16) | (l & 0x0000FFFF)); + return ret; +} + +std::basic_string utf16_to_utf32(const wchar_t *u16str, size_t size) +{ + std::basic_string utf32String; + for (size_t i = 0; i < size; i++) + { + auto u16c = u16str[i]; + if (u16c - 0xd800u < 2048u) + if ((u16c & 0xfffffc00 == 0xd800) && (i < size - 1) && (u16str[i + 1] & 0xfffffc00 == 0xdc00)) + { + utf32String += (u16c << 10) + u16str[i + 1] - 0x35fdc00; + i += 1; } - else{ - //error invalid u16 char + else + { + // error invalid u16 char } else - utf32String+=u16str[i]; + utf32String += u16str[i]; } return utf32String; } -std::wstring utf32_to_utf16(uint32_t* u32str,size_t size){ - std::wstring u16str; - for(auto i=0;i commonparsestring(void* data,size_t length,void* php,DWORD df){ - auto hp=(HookParam*)php; - if (hp->type & CODEC_UTF16) return std::wstring((wchar_t*)data, length / sizeof(wchar_t)); - else if(hp->type&CODEC_UTF32)return (std::move(utf32_to_utf16((uint32_t*)data,length/ sizeof(uint32_t)))); - else if (auto converted = StringToWideString(std::string((char*)data, length), (hp->type&CODEC_UTF8)?CP_UTF8:(hp->codepage ? hp->codepage :df))) return (converted.value()); - else return {}; +std::optional commonparsestring(void *data, size_t length, void *php, DWORD df) +{ + auto hp = (HookParam *)php; + if (hp->type & CODEC_UTF16) + return std::wstring((wchar_t *)data, length / sizeof(wchar_t)); + else if (hp->type & CODEC_UTF32) + return (std::move(utf32_to_utf16((uint32_t *)data, length / sizeof(uint32_t)))); + else if (auto converted = StringToWideString(std::string((char *)data, length), (hp->type & CODEC_UTF8) ? CP_UTF8 : (hp->codepage ? hp->codepage : df))) + return (converted.value()); + else + return {}; } \ No newline at end of file diff --git a/include/stringutils.h b/include/stringutils.h index 83eded5..60bb4f9 100644 --- a/include/stringutils.h +++ b/include/stringutils.h @@ -1,10 +1,14 @@ #ifndef __LUNA_STRINGUILTS_H #define __LUNA_STRINGUILTS_H -enum { VNR_TEXT_CAPACITY = 1500 }; // estimated max number of bytes allowed in VNR, slightly larger than VNR's text limit (1000) +enum +{ + VNR_TEXT_CAPACITY = 1500 +}; // estimated max number of bytes allowed in VNR, slightly larger than VNR's text limit (1000) -template -StringT stolower(StringT s){ +template +StringT stolower(StringT s) +{ std::transform(s.begin(), s.end(), s.begin(), tolower); return s; } @@ -13,41 +17,43 @@ LPCSTR reverse_search_begin(const char *s, int maxsize = VNR_TEXT_CAPACITY); bool all_ascii(const char *s, int maxsize = VNR_TEXT_CAPACITY); bool all_ascii(const wchar_t *s, int maxsize = VNR_TEXT_CAPACITY); -void strReplace(std::string& str, const std::string& oldStr, const std::string& newStr); -void strReplace(std::wstring& str, const std::wstring& oldStr, const std::wstring& newStr); -std::vector strSplit(const std::string& s, const std::string& delim); -std::vector strSplit(const std::wstring& s, const std::wstring& delim); -bool startWith(const std::string& s,const std::string& s2); -bool startWith(const std::wstring& s,const std::wstring &s2); -bool endWith(const std::string& s,const std::string& s2); -bool endWith(const std::wstring& s,const std::wstring& s2); +void strReplace(std::string &str, const std::string &oldStr, const std::string &newStr); +void strReplace(std::wstring &str, const std::wstring &oldStr, const std::wstring &newStr); +std::vector strSplit(const std::string &s, const std::string &delim); +std::vector strSplit(const std::wstring &s, const std::wstring &delim); +bool startWith(const std::string &s, const std::string &s2); +bool startWith(const std::wstring &s, const std::wstring &s2); +bool endWith(const std::string &s, const std::string &s2); +bool endWith(const std::wstring &s, const std::wstring &s2); -std::wstring utf32_to_utf16(uint32_t* u32str,size_t size); -std::basic_string utf16_to_utf32(const wchar_t* u16str,size_t size); +std::wstring utf32_to_utf16(uint32_t *u32str, size_t size); +std::basic_string utf16_to_utf32(const wchar_t *u16str, size_t size); -std::string WideStringToString(const std::wstring& text,UINT cp=CP_UTF8); -std::wstring StringToWideString(const std::string& text); -std::optional StringToWideString(const std::string& text, UINT encoding); +std::string WideStringToString(const std::wstring &text, UINT cp = CP_UTF8); +std::wstring StringToWideString(const std::string &text); +std::optional StringToWideString(const std::string &text, UINT encoding); std::string wcasta(const std::wstring x); std::wstring acastw(const std::string x); -size_t u32strlen(uint32_t* data); -inline bool disable_mbwc=false; -inline bool disable_wcmb=false; -template -inline void Trim(ST& text) +size_t u32strlen(uint32_t *data); +inline bool disable_mbwc = false; +inline bool disable_wcmb = false; +template +inline void Trim(ST &text) { text.erase(text.begin(), std::find_if_not(text.begin(), text.end(), iswspace)); text.erase(std::find_if_not(text.rbegin(), text.rend(), iswspace).base(), text.end()); } -template inline auto FormatArg(T arg) { return arg; } -template inline auto FormatArg(const std::basic_string& arg) { return arg.c_str(); } +template +inline auto FormatArg(T arg) { return arg; } +template +inline auto FormatArg(const std::basic_string &arg) { return arg.c_str(); } #pragma warning(push) -#pragma warning(disable: 4996) +#pragma warning(disable : 4996) template -inline std::string FormatString(const char* format, const Args&... args) +inline std::string FormatString(const char *format, const Args &...args) { std::string buffer(snprintf(nullptr, 0, format, FormatArg(args)...), '\0'); sprintf(buffer.data(), format, FormatArg(args)...); @@ -55,13 +61,13 @@ inline std::string FormatString(const char* format, const Args&... args) } template -inline std::wstring FormatString(const wchar_t* format, const Args&... args) +inline std::wstring FormatString(const wchar_t *format, const Args &...args) { std::wstring buffer(_snwprintf(nullptr, 0, format, FormatArg(args)...), L'\0'); _swprintf(buffer.data(), format, FormatArg(args)...); return buffer; } -std::optional commonparsestring(void*,size_t,void*,DWORD); +std::optional commonparsestring(void *, size_t, void *, DWORD); #pragma warning(pop) #endif \ No newline at end of file diff --git a/include/texthook.h b/include/texthook.h index 0a575b9..5ca7dee 100644 --- a/include/texthook.h +++ b/include/texthook.h @@ -8,11 +8,12 @@ // - Clean up this file // - Reduce global variables. Use namespaces or singleton classes instead. -inline std::atomic trigger_fun = nullptr; +inline std::atomic trigger_fun = nullptr; // jichi 9/25/2013: This class will be used by NtMapViewOfSectionfor // interprocedure communication, where constructor/destructor will NOT work. -struct EmbedSharedMem{ +struct EmbedSharedMem +{ uint64_t use[10]; uint64_t addr[10]; uint64_t ctx1[10]; @@ -28,12 +29,12 @@ struct EmbedSharedMem{ UINT codepage; bool fastskipignore; UINT32 line_text_length_limit; -}; +}; class TextHook { public: HookParam hp; - ALIGNPTR(uint64_t address,void* location); + ALIGNPTR(uint64_t address, void *location); uint64_t savetypeforremove; bool Insert(HookParam hp); void Clear(); @@ -46,20 +47,23 @@ private: bool RemoveBreakPoint(); bool breakpointcontext(PCONTEXT); void Send(uintptr_t dwDatabase); - int GetLength(hook_stack* stack, uintptr_t in); // jichi 12/25/2013: Return 0 if failed - int HookStrlen(BYTE* data); + int GetLength(hook_stack *stack, uintptr_t in); // jichi 12/25/2013: Return 0 if failed + int HookStrlen(BYTE *data); void RemoveHookCode(); void RemoveReadCode(); - bool waitfornotify(TextOutput_T* buffer,void*data ,size_t*len,ThreadParam tp); - void parsenewlineseperator(void*data ,size_t*len); + bool waitfornotify(TextOutput_T *buffer, void *data, size_t *len, ThreadParam tp); + void parsenewlineseperator(void *data, size_t *len); volatile DWORD useCount; - ALIGNPTR(uint64_t __1,HANDLE readerThread); - ALIGNPTR(uint64_t __2,HANDLE readerEvent); + ALIGNPTR(uint64_t __1, HANDLE readerThread); + ALIGNPTR(uint64_t __2, HANDLE readerEvent); bool err; - ALIGNPTR(BYTE __4[ 140],BYTE trampoline[x64 ? 140 : 40]); - ALIGNPTR(uint64_t __3,BYTE* local_buffer); + ALIGNPTR(BYTE __4[140], BYTE trampoline[x64 ? 140 : 40]); + ALIGNPTR(uint64_t __3, BYTE *local_buffer); }; -enum { MAX_HOOK = 2500}; +enum +{ + MAX_HOOK = 2500 +}; // EOF diff --git a/include/types.h b/include/types.h index fcb2162..cb96d58 100644 --- a/include/types.h +++ b/include/types.h @@ -1,40 +1,45 @@ #pragma once - class WinMutex // Like CMutex but works with scoped_lock { public: WinMutex(std::wstring name = L"", LPSECURITY_ATTRIBUTES sa = nullptr) : m(CreateMutexW(sa, FALSE, name.empty() ? NULL : name.c_str())) {} - void lock() { if (m) WaitForSingleObject(m, INFINITE); } - void unlock() { if (m) ReleaseMutex(m); } + void lock() + { + if (m) + WaitForSingleObject(m, INFINITE); + } + void unlock() + { + if (m) + ReleaseMutex(m); + } private: AutoHandle<> m; }; inline SECURITY_ATTRIBUTES allAccess = std::invoke([] // allows non-admin processes to access kernel objects made by admin processes -{ + { static SECURITY_DESCRIPTOR sd = {}; InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); - return SECURITY_ATTRIBUTES{ sizeof(SECURITY_ATTRIBUTES), &sd, FALSE }; -}); - + return SECURITY_ATTRIBUTES{ sizeof(SECURITY_ATTRIBUTES), &sd, FALSE }; }); struct hook_stack { #ifndef _WIN64 - uintptr_t _eflags; //pushfd - uintptr_t edi, // pushad + uintptr_t _eflags; // pushfd + uintptr_t edi, // pushad esi, ebp, esp, ebx, edx, - ecx, // this - eax; // 0x28 - + ecx, // this + eax; // 0x28 + #else uintptr_t r15, r14, @@ -53,65 +58,70 @@ struct hook_stack rbx, rax; #endif - uintptr_t eflags; // pushaf + uintptr_t eflags; // pushaf union { - uintptr_t stack[1]; // beginning of the runtime stack + uintptr_t stack[1]; // beginning of the runtime stack uintptr_t retaddr; BYTE base[1]; }; - uintptr_t get_base(){ - return (uintptr_t)this+sizeof(hook_stack)-sizeof(uintptr_t); + uintptr_t get_base() + { + return (uintptr_t)this + sizeof(hook_stack) - sizeof(uintptr_t); } }; -inline hook_stack* get_hook_stack(uintptr_t lpDataBase){ - return (hook_stack*)(lpDataBase-sizeof(hook_stack)+sizeof(uintptr_t)); +inline hook_stack *get_hook_stack(uintptr_t lpDataBase) +{ + return (hook_stack *)(lpDataBase - sizeof(hook_stack) + sizeof(uintptr_t)); } // jichi 3/7/2014: Add guessed comment -#define ALIGNPTR(Y,X) union { \ - ##Y; \ - ##X; \ -}; +#define ALIGNPTR(Y, X) \ + union \ + { \ + ##Y; \ + ##X; \ + }; - -enum class JITTYPE{ - PC,//not a jit - YUZU, - PPSSPP, +enum class JITTYPE +{ + PC, // not a jit + YUZU, + PPSSPP, VITA3K, RPCS3, UNITY }; struct HookParam { - ALIGNPTR(uint64_t __11,uintptr_t address); // absolute or relative address - int offset, // offset of the data in the memory - index, // deref_offset1 - split, // offset of the split character - split_index; // deref_offset2 + ALIGNPTR(uint64_t __11, uintptr_t address); // absolute or relative address + int offset, // offset of the data in the memory + index, // deref_offset1 + split, // offset of the split character + split_index; // deref_offset2 wchar_t module[MAX_MODULE_SIZE]; char function[MAX_MODULE_SIZE]; - uint64_t type; // flags - UINT codepage; // text encoding - short length_offset; // index of the string length - ALIGNPTR(uint64_t __1,uintptr_t padding); // padding before string - ALIGNPTR(uint64_t __12,uintptr_t user_value); - ALIGNPTR(uint64_t __2,void(*text_fun)(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len)) - ALIGNPTR(uint64_t __3,bool(*filter_fun)(void* data, size_t* len, HookParam* hp)); // jichi 10/24/2014: Add filter function. Return false to skip the text - ALIGNPTR(uint64_t __6,bool (*hook_before)(hook_stack* stack,void* data, size_t* len,uintptr_t*role)); - ALIGNPTR(uint64_t __7,void (*hook_after)(hook_stack* stack,void* data, size_t len)); - ALIGNPTR(uint64_t __8,uintptr_t hook_font); - ALIGNPTR(uint64_t __9,const wchar_t* newlineseperator); + uint64_t type; // flags + UINT codepage; // text encoding + short length_offset; // index of the string length + ALIGNPTR(uint64_t __1, uintptr_t padding); // padding before string + ALIGNPTR(uint64_t __12, uintptr_t user_value); + ALIGNPTR(uint64_t __2, void (*text_fun)(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)) + ALIGNPTR(uint64_t __3, bool (*filter_fun)(void *data, size_t *len, HookParam *hp)); // jichi 10/24/2014: Add filter function. Return false to skip the text + ALIGNPTR(uint64_t __6, bool (*hook_before)(hook_stack *stack, void *data, size_t *len, uintptr_t *role)); + ALIGNPTR(uint64_t __7, void (*hook_after)(hook_stack *stack, void *data, size_t len)); + ALIGNPTR(uint64_t __8, uintptr_t hook_font); + ALIGNPTR(uint64_t __9, const wchar_t *newlineseperator); char name[HOOK_NAME_SIZE]; wchar_t hookcode[HOOKCODE_LEN]; - HookParam(){ - ZeroMemory(this,sizeof(HookParam)); + HookParam() + { + ZeroMemory(this, sizeof(HookParam)); } - ALIGNPTR(uint64_t __10,uintptr_t emu_addr); + ALIGNPTR(uint64_t __10, uintptr_t emu_addr); int argidx; JITTYPE jittype; char unityfunctioninfo[1024]; @@ -122,28 +132,28 @@ struct ThreadParam bool operator==(ThreadParam other) const { return processId == other.processId && addr == other.addr && ctx == other.ctx && ctx2 == other.ctx2; } DWORD processId; uint64_t addr; - uint64_t ctx; // The context of the hook: by default the first value on stack, usually the return address - uint64_t ctx2; // The subcontext of the hook: 0 by default, generated in a method specific to the hook + uint64_t ctx; // The context of the hook: by default the first value on stack, usually the return address + uint64_t ctx2; // The subcontext of the hook: 0 by default, generated in a method specific to the hook }; struct SearchParam { - BYTE pattern[PATTERN_SIZE] = { x64 ? 0xcc : 0x55, x64 ? 0xcc : 0x8b, x64 ? 0x48 : 0xec, 0x89 }; // pattern in memory to search for - int address_method=0; - int search_method=0; + BYTE pattern[PATTERN_SIZE] = {x64 ? 0xcc : 0x55, x64 ? 0xcc : 0x8b, x64 ? 0x48 : 0xec, 0x89}; // pattern in memory to search for + int address_method = 0; + int search_method = 0; int length = x64 ? 4 : 3, // length of pattern (zero means this SearchParam is invalid and the default should be used) offset = x64 ? 2 : 0, // offset from start of pattern to add hook - searchTime = 30000, // ms + searchTime = 30000, // ms maxRecords = 100000, codepage = SHIFT_JIS; - //uintptr_t padding = 0, // same as hook param padding + // uintptr_t padding = 0, // same as hook param padding // minAddress = 0, maxAddress = (uintptr_t)-1; // hook all functions between these addresses (used only if both modules empty) - ALIGNPTR(uint64_t __1,uintptr_t padding = 0); - ALIGNPTR(uint64_t __2,uintptr_t minAddress = 0); - ALIGNPTR(uint64_t __3,uintptr_t maxAddress = (uintptr_t)-1); + ALIGNPTR(uint64_t __1, uintptr_t padding = 0); + ALIGNPTR(uint64_t __2, uintptr_t minAddress = 0); + ALIGNPTR(uint64_t __3, uintptr_t maxAddress = (uintptr_t)-1); wchar_t boundaryModule[MAX_MODULE_SIZE] = {}; // hook all functions within this module (middle priority) - wchar_t exportModule[MAX_MODULE_SIZE] = {}; // hook the exports of this module (highest priority) - wchar_t text[PATTERN_SIZE] = {}; // text to search for + wchar_t exportModule[MAX_MODULE_SIZE] = {}; // hook the exports of this module (highest priority) + wchar_t text[PATTERN_SIZE] = {}; // text to search for JITTYPE jittype; }; @@ -176,7 +186,7 @@ struct ConsoleOutputNotif // From dll struct HookFoundNotif // From dll { - HookFoundNotif(HookParam hp, wchar_t* text) : hp(hp) { wcsncpy_s(this->text, text, MESSAGE_SIZE - 1); } + HookFoundNotif(HookParam hp, wchar_t *text) : hp(hp) { wcsncpy_s(this->text, text, MESSAGE_SIZE - 1); } HostNotificationType command = HOST_NOTIFICATION_FOUND_HOOK; HookParam hp; wchar_t text[MESSAGE_SIZE] = {}; // though type is wchar_t, may not be encoded in UTF-16 (it's just convenient to use wcs* functions) @@ -184,15 +194,15 @@ struct HookFoundNotif // From dll struct HookRemovedNotif // From dll { - HookRemovedNotif(uint64_t address) : address(address) {}; + HookRemovedNotif(uint64_t address) : address(address){}; HostNotificationType command = HOST_NOTIFICATION_RMVHOOK; uint64_t address; }; struct HookInsertingNotif // From dll { - HookInsertingNotif(uint64_t addr1):addr(addr1){} - HostNotificationType command = HOST_NOTIFICATION_INSERTING_HOOK; + HookInsertingNotif(uint64_t addr1) : addr(addr1) {} + HostNotificationType command = HOST_NOTIFICATION_INSERTING_HOOK; uint64_t addr; wchar_t hookcode[HOOKCODE_LEN]; }; diff --git a/include/utils.h b/include/utils.h index 666f87c..96c3944 100644 --- a/include/utils.h +++ b/include/utils.h @@ -6,16 +6,27 @@ constexpr bool x64 = true; constexpr bool x64 = false; #endif -template struct ArrayImpl { using Type = std::tuple[]; }; -template struct ArrayImpl { using Type = T[]; }; -template using Array = typename ArrayImpl::Type; +template +struct ArrayImpl +{ + using Type = std::tuple[]; +}; +template +struct ArrayImpl +{ + using Type = T[]; +}; +template +using Array = typename ArrayImpl::Type; -template using Functor = std::integral_constant, F>; // shouldn't need remove_reference_t but MSVC is bugged +template +using Functor = std::integral_constant, F>; // shouldn't need remove_reference_t but MSVC is bugged struct PermissivePointer { - template operator T*() { return (T*)p; } - void* p; + template + operator T *() { return (T *)p; } + void *p; }; template > @@ -24,29 +35,41 @@ class AutoHandle public: AutoHandle(HANDLE h) : h(h) {} operator HANDLE() { return h.get(); } - PHANDLE operator&() { static_assert(sizeof(*this) == sizeof(HANDLE)); assert(!h); return (PHANDLE)this; } + PHANDLE operator&() + { + static_assert(sizeof(*this) == sizeof(HANDLE)); + assert(!h); + return (PHANDLE)this; + } operator bool() { return h.get() != NULL && h.get() != INVALID_HANDLE_VALUE; } private: - struct HandleCleaner { void operator()(void* h) { if (h != INVALID_HANDLE_VALUE) HandleCloser()(PermissivePointer{ h }); } }; + struct HandleCleaner + { + void operator()(void *h) + { + if (h != INVALID_HANDLE_VALUE) + HandleCloser()(PermissivePointer{h}); + } + }; std::unique_ptr h; }; -template +template class Synchronized { public: template - Synchronized(Args&&... args) : contents(std::forward(args)...) {} + Synchronized(Args &&...args) : contents(std::forward(args)...) {} struct Locker { - T* operator->() { return &contents; } + T *operator->() { return &contents; } std::unique_lock lock; - T& contents; + T &contents; }; - Locker Acquire() { return { std::unique_lock(m), contents }; } + Locker Acquire() { return {std::unique_lock(m), contents}; } Locker operator->() { return Acquire(); } T Copy() { return Acquire().contents; } @@ -56,52 +79,66 @@ private: }; template -void SpawnThread(const F& f) // works in DllMain unlike std thread +void SpawnThread(const F &f) // works in DllMain unlike std thread { - F* copy = new F(f); - CloseHandle(CreateThread(nullptr, 0, [](void* copy) - { + F *copy = new F(f); + CloseHandle(CreateThread(nullptr, 0, [](void *copy) + { (*(F*)copy)(); delete (F*)copy; - return 0UL; - }, copy, 0, nullptr)); + return 0UL; }, copy, 0, nullptr)); } inline struct // should be inline but MSVC (linker) is bugged { inline static BYTE DUMMY[100]; - template operator T*() { static_assert(sizeof(T) < sizeof(DUMMY)); return (T*)DUMMY; } + template + operator T *() + { + static_assert(sizeof(T) < sizeof(DUMMY)); + return (T *)DUMMY; + } } DUMMY; -inline auto Swallow = [](auto&&...) {}; - -template std::optional> Copy(T* ptr) { if (ptr) return *ptr; return {}; } +inline auto Swallow = [](auto &&...) {}; +template +std::optional> Copy(T *ptr) +{ + if (ptr) + return *ptr; + return {}; +} 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(); + 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(); + if (GetModuleFileNameW(module, buffer.data(), MAX_PATH)) + return buffer.data(); return {}; } -template -struct SafeFptr { +template +struct SafeFptr +{ T ptr; uintptr_t errorvalue; SafeFptr(T _ptr, uintptr_t v = {NULL}) : ptr(_ptr), errorvalue(v) {} - template - std::invoke_result_t operator()(Args... args) { - if (!ptr) return (std::invoke_result_t)(errorvalue); + template + std::invoke_result_t operator()(Args... args) + { + if (!ptr) + return (std::invoke_result_t)(errorvalue); return ptr(std::forward(args)...); } }; diff --git a/include/winevent.hpp b/include/winevent.hpp index e7dc80b..a50efd8 100644 --- a/include/winevent.hpp +++ b/include/winevent.hpp @@ -1,25 +1,26 @@ -#include +#include class win_event { typedef win_event _Self; typedef HANDLE __native_handle_type; - typedef const char * __native_string_type; + typedef const char *__native_string_type; __native_handle_type _M_handle; __native_string_type _M_name; - win_event(const _Self&); - _Self &operator=(const _Self&); + win_event(const _Self &); + _Self &operator=(const _Self &); + public: typedef __native_handle_type native_handle_type; typedef __native_string_type native_string_type; explicit win_event(native_string_type name, bool create = true) - : _M_name(name) + : _M_name(name) { _M_handle = create ? // lpEventAttributes, bManualReset, bInitialState, lpName - ::CreateEventA(nullptr, TRUE, FALSE, name) : - ::OpenEventA(EVENT_ALL_ACCESS, FALSE, name); // dwDesiredAccess, bInheritHandle, lpName + ::CreateEventA(nullptr, TRUE, FALSE, name) + : ::OpenEventA(EVENT_ALL_ACCESS, FALSE, name); // dwDesiredAccess, bInheritHandle, lpName } ~win_event() { ::CloseHandle(_M_handle); } @@ -30,9 +31,13 @@ public: bool valid() const { return _M_handle; } bool signal(bool t) - { return t ? ::SetEvent(_M_handle) : ::ResetEvent(_M_handle); } + { + return t ? ::SetEvent(_M_handle) : ::ResetEvent(_M_handle); + } /// Return true only if when it is wake up by notify instead of timeout bool wait(DWORD msec = INFINITE) - { return WAIT_OBJECT_0 == ::WaitForSingleObject(_M_handle, msec); } + { + return WAIT_OBJECT_0 == ::WaitForSingleObject(_M_handle, msec); + } };