mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-11-23 05:45:37 +08:00
fmt
This commit is contained in:
parent
b0b1fe4417
commit
7324cf4229
126
include/const.h
126
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),
|
||||
};
|
@ -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
|
||||
|
@ -3,7 +3,7 @@ namespace
|
||||
{
|
||||
std::optional<HookParam> 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<HookParam> ParseHCode(std::wstring HCode,std::optional<HookParam> hpo={})
|
||||
std::optional<HookParam> ParseHCode(std::wstring HCode, std::optional<HookParam> 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<HookParam> 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<HookParam> 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));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -33,11 +33,11 @@
|
||||
#include <shlobj.h>
|
||||
#include <Shlwapi.h>
|
||||
|
||||
#include"stringutils.h"
|
||||
#include"utils.h"
|
||||
#include"defs.h"
|
||||
#include"const.h"
|
||||
#include"types.h"
|
||||
#include"hookcode.h"
|
||||
#include"texthook.h"
|
||||
#include"winevent.hpp"
|
||||
#include "stringutils.h"
|
||||
#include "utils.h"
|
||||
#include "defs.h"
|
||||
#include "const.h"
|
||||
#include "types.h"
|
||||
#include "hookcode.h"
|
||||
#include "texthook.h"
|
||||
#include "winevent.hpp"
|
@ -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<class CharT>
|
||||
inline bool all_ascii_impl(const CharT* s,int maxsize){
|
||||
template <class CharT>
|
||||
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<class StringT>
|
||||
inline void strReplace_impl(StringT& str, const StringT& oldStr, const StringT& newStr){
|
||||
template <class StringT>
|
||||
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 <class StringT>
|
||||
inline std::vector<StringT> strSplit_impl(const StringT &s, const StringT &delim)
|
||||
{
|
||||
StringT item;
|
||||
std::vector<StringT> tokens;
|
||||
|
||||
template<class StringT>
|
||||
inline std::vector<StringT> strSplit_impl(const StringT& s, const StringT& delim){
|
||||
StringT item;
|
||||
std::vector<StringT> 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<class StringT>
|
||||
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 <class StringT>
|
||||
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<class StringT>
|
||||
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 <class StringT>
|
||||
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<char>(s, maxsize); }
|
||||
bool all_ascii(const wchar_t *s, int maxsize) { return all_ascii_impl<wchar_t>(s, maxsize); }
|
||||
|
||||
bool all_ascii(const char *s, int maxsize ){return all_ascii_impl<char>(s,maxsize);}
|
||||
bool all_ascii(const wchar_t *s, int maxsize ){return all_ascii_impl<wchar_t>(s,maxsize);}
|
||||
void strReplace(std::string &str, const std::string &oldStr, const std::string &newStr) { strReplace_impl<std::string>(str, oldStr, newStr); }
|
||||
void strReplace(std::wstring &str, const std::wstring &oldStr, const std::wstring &newStr) { strReplace_impl<std::wstring>(str, oldStr, newStr); }
|
||||
std::vector<std::string> strSplit(const std::string &s, const std::string &delim) { return strSplit_impl<std::string>(s, delim); }
|
||||
std::vector<std::wstring> strSplit(const std::wstring &s, const std::wstring &delim) { return strSplit_impl<std::wstring>(s, delim); }
|
||||
bool startWith(const std::string &s, const std::string &s2) { return startWith_impl<std::string>(s, s2); }
|
||||
bool startWith(const std::wstring &s, const std::wstring &s2) { return startWith_impl<std::wstring>(s, s2); }
|
||||
bool endWith(const std::string &s, const std::string &s2) { return endWith_impl<std::string>(s, s2); }
|
||||
bool endWith(const std::wstring &s, const std::wstring &s2) { return endWith_impl<std::wstring>(s, s2); }
|
||||
|
||||
void strReplace(std::string& str, const std::string& oldStr, const std::string& newStr){strReplace_impl<std::string>(str,oldStr,newStr);}
|
||||
void strReplace(std::wstring& str, const std::wstring& oldStr, const std::wstring& newStr){strReplace_impl<std::wstring>(str,oldStr,newStr);}
|
||||
std::vector<std::string> strSplit(const std::string& s, const std::string& delim){return strSplit_impl<std::string>(s,delim);}
|
||||
std::vector<std::wstring> strSplit(const std::wstring& s, const std::wstring& delim){return strSplit_impl<std::wstring>(s,delim);}
|
||||
bool startWith(const std::string& s,const std::string& s2){return startWith_impl<std::string>(s,s2);}
|
||||
bool startWith(const std::wstring& s,const std::wstring& s2){return startWith_impl<std::wstring>(s,s2);}
|
||||
bool endWith(const std::string& s,const std::string& s2){return endWith_impl<std::string>(s,s2);}
|
||||
bool endWith(const std::wstring& s,const std::wstring& s2){return endWith_impl<std::wstring>(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<std::wstring> StringToWideString(const std::string& text, UINT encoding)
|
||||
std::optional<std::wstring> StringToWideString(const std::string &text, UINT encoding)
|
||||
{
|
||||
std::vector<wchar_t> 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<char> 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<uint32_t> utf16_to_utf32(const wchar_t* u16str,size_t size){
|
||||
std::basic_string<uint32_t> utf32String;
|
||||
for (size_t i=0;i<size;i++)
|
||||
std::vector<wchar_t> buffer(text.size() + 1);
|
||||
if (disable_mbwc)
|
||||
{
|
||||
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;
|
||||
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<char> 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<uint32_t> utf16_to_utf32(const wchar_t *u16str, size_t size)
|
||||
{
|
||||
std::basic_string<uint32_t> 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<size;i++){
|
||||
unsigned h,l;
|
||||
convertUTF32ToUTF16(u32str[i],h,l);
|
||||
if(h)
|
||||
u16str.push_back((wchar_t)h);
|
||||
u16str.push_back((wchar_t)l);
|
||||
}
|
||||
return u16str;
|
||||
std::wstring utf32_to_utf16(uint32_t *u32str, size_t size)
|
||||
{
|
||||
std::wstring u16str;
|
||||
for (auto i = 0; i < size; i++)
|
||||
{
|
||||
unsigned h, l;
|
||||
convertUTF32ToUTF16(u32str[i], h, l);
|
||||
if (h)
|
||||
u16str.push_back((wchar_t)h);
|
||||
u16str.push_back((wchar_t)l);
|
||||
}
|
||||
return u16str;
|
||||
}
|
||||
|
||||
size_t u32strlen(uint32_t* data){
|
||||
size_t s=0;
|
||||
while(data[s])
|
||||
s++;
|
||||
return s;
|
||||
size_t u32strlen(uint32_t *data)
|
||||
{
|
||||
size_t s = 0;
|
||||
while (data[s])
|
||||
s++;
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string wcasta(const std::wstring x){
|
||||
std::string xx;
|
||||
for(auto c:x)
|
||||
xx+=c;
|
||||
return xx;
|
||||
std::string wcasta(const std::wstring x)
|
||||
{
|
||||
std::string xx;
|
||||
for (auto c : x)
|
||||
xx += c;
|
||||
return xx;
|
||||
}
|
||||
|
||||
std::wstring acastw(const std::string x){
|
||||
std::wstring xx;
|
||||
for(auto c:x)
|
||||
xx+=c;
|
||||
return xx;
|
||||
std::wstring acastw(const std::string x)
|
||||
{
|
||||
std::wstring xx;
|
||||
for (auto c : x)
|
||||
xx += c;
|
||||
return xx;
|
||||
}
|
||||
std::optional<std::wstring> 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<std::wstring> 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 {};
|
||||
}
|
@ -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<class StringT>
|
||||
StringT stolower(StringT s){
|
||||
template <class StringT>
|
||||
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<std::string> strSplit(const std::string& s, const std::string& delim);
|
||||
std::vector<std::wstring> 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<std::string> strSplit(const std::string &s, const std::string &delim);
|
||||
std::vector<std::wstring> 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<uint32_t> utf16_to_utf32(const wchar_t* u16str,size_t size);
|
||||
std::wstring utf32_to_utf16(uint32_t *u32str, size_t size);
|
||||
std::basic_string<uint32_t> 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<std::wstring> 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<std::wstring> 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<class ST>
|
||||
inline void Trim(ST& text)
|
||||
size_t u32strlen(uint32_t *data);
|
||||
inline bool disable_mbwc = false;
|
||||
inline bool disable_wcmb = false;
|
||||
template <class ST>
|
||||
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 <typename T> inline auto FormatArg(T arg) { return arg; }
|
||||
template <typename C> inline auto FormatArg(const std::basic_string<C>& arg) { return arg.c_str(); }
|
||||
template <typename T>
|
||||
inline auto FormatArg(T arg) { return arg; }
|
||||
template <typename C>
|
||||
inline auto FormatArg(const std::basic_string<C> &arg) { return arg.c_str(); }
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4996)
|
||||
#pragma warning(disable : 4996)
|
||||
template <typename... Args>
|
||||
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 <typename... Args>
|
||||
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<std::wstring> commonparsestring(void*,size_t,void*,DWORD);
|
||||
std::optional<std::wstring> commonparsestring(void *, size_t, void *, DWORD);
|
||||
#pragma warning(pop)
|
||||
#endif
|
@ -8,11 +8,12 @@
|
||||
// - Clean up this file
|
||||
// - Reduce global variables. Use namespaces or singleton classes instead.
|
||||
|
||||
inline std::atomic<bool (*)(LPVOID addr, hook_stack* stack)> trigger_fun = nullptr;
|
||||
inline std::atomic<bool (*)(LPVOID addr, hook_stack *stack)> 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
|
||||
|
134
include/types.h
134
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];
|
||||
};
|
||||
|
@ -6,16 +6,27 @@ constexpr bool x64 = true;
|
||||
constexpr bool x64 = false;
|
||||
#endif
|
||||
|
||||
template <typename T, typename... Xs> struct ArrayImpl { using Type = std::tuple<T, Xs...>[]; };
|
||||
template <typename T> struct ArrayImpl<T> { using Type = T[]; };
|
||||
template <typename... Ts> using Array = typename ArrayImpl<Ts...>::Type;
|
||||
template <typename T, typename... Xs>
|
||||
struct ArrayImpl
|
||||
{
|
||||
using Type = std::tuple<T, Xs...>[];
|
||||
};
|
||||
template <typename T>
|
||||
struct ArrayImpl<T>
|
||||
{
|
||||
using Type = T[];
|
||||
};
|
||||
template <typename... Ts>
|
||||
using Array = typename ArrayImpl<Ts...>::Type;
|
||||
|
||||
template <auto F> using Functor = std::integral_constant<std::remove_reference_t<decltype(F)>, F>; // shouldn't need remove_reference_t but MSVC is bugged
|
||||
template <auto F>
|
||||
using Functor = std::integral_constant<std::remove_reference_t<decltype(F)>, F>; // shouldn't need remove_reference_t but MSVC is bugged
|
||||
|
||||
struct PermissivePointer
|
||||
{
|
||||
template <typename T> operator T*() { return (T*)p; }
|
||||
void* p;
|
||||
template <typename T>
|
||||
operator T *() { return (T *)p; }
|
||||
void *p;
|
||||
};
|
||||
|
||||
template <typename HandleCloser = Functor<CloseHandle>>
|
||||
@ -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<void, HandleCleaner> h;
|
||||
};
|
||||
|
||||
template<typename T, typename M = std::mutex>
|
||||
template <typename T, typename M = std::mutex>
|
||||
class Synchronized
|
||||
{
|
||||
public:
|
||||
template <typename... Args>
|
||||
Synchronized(Args&&... args) : contents(std::forward<Args>(args)...) {}
|
||||
Synchronized(Args &&...args) : contents(std::forward<Args>(args)...) {}
|
||||
|
||||
struct Locker
|
||||
{
|
||||
T* operator->() { return &contents; }
|
||||
T *operator->() { return &contents; }
|
||||
std::unique_lock<M> 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 <typename F>
|
||||
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 <typename T> operator T*() { static_assert(sizeof(T) < sizeof(DUMMY)); return (T*)DUMMY; }
|
||||
template <typename T>
|
||||
operator T *()
|
||||
{
|
||||
static_assert(sizeof(T) < sizeof(DUMMY));
|
||||
return (T *)DUMMY;
|
||||
}
|
||||
} DUMMY;
|
||||
|
||||
inline auto Swallow = [](auto&&...) {};
|
||||
|
||||
template <typename T> std::optional<std::remove_cv_t<T>> Copy(T* ptr) { if (ptr) return *ptr; return {}; }
|
||||
inline auto Swallow = [](auto &&...) {};
|
||||
|
||||
template <typename T>
|
||||
std::optional<std::remove_cv_t<T>> Copy(T *ptr)
|
||||
{
|
||||
if (ptr)
|
||||
return *ptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
inline std::optional<std::wstring> getModuleFilename(DWORD processId, HMODULE module = NULL)
|
||||
{
|
||||
std::vector<wchar_t> 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<std::wstring> getModuleFilename(HMODULE module = NULL)
|
||||
{
|
||||
std::vector<wchar_t> 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<typename T>
|
||||
struct SafeFptr {
|
||||
template <typename T>
|
||||
struct SafeFptr
|
||||
{
|
||||
T ptr;
|
||||
uintptr_t errorvalue;
|
||||
SafeFptr(T _ptr, uintptr_t v = {NULL}) : ptr(_ptr), errorvalue(v) {}
|
||||
|
||||
template<typename... Args>
|
||||
std::invoke_result_t<T, Args...> operator()(Args... args) {
|
||||
if (!ptr) return (std::invoke_result_t<T, Args...>)(errorvalue);
|
||||
template <typename... Args>
|
||||
std::invoke_result_t<T, Args...> operator()(Args... args)
|
||||
{
|
||||
if (!ptr)
|
||||
return (std::invoke_result_t<T, Args...>)(errorvalue);
|
||||
return ptr(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
@ -1,25 +1,26 @@
|
||||
#include<Windows.h>
|
||||
#include <Windows.h>
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user