mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-11-23 13:55:36 +08:00
Update CatSystem.cpp
This commit is contained in:
parent
5fa33f740c
commit
067b0c288b
@ -1,4 +1,4 @@
|
||||
#include"CatSystem.h"
|
||||
#include "CatSystem.h"
|
||||
// jichi 5/10/2014
|
||||
// See also: http://bbs.sumisora.org/read.php?tid=11044704&fpage=2
|
||||
//
|
||||
@ -133,9 +133,9 @@
|
||||
// 051ae554 042c4c20
|
||||
// 051ae558 0000002c
|
||||
|
||||
static void SpecialHookCatSystem3(hook_stack* stack, HookParam *, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
static void SpecialHookCatSystem3(hook_stack *stack, HookParam *, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
//DWORD ch = *data = *(DWORD *)(esp_base + hp->offset); // arg2
|
||||
// DWORD ch = *data = *(DWORD *)(esp_base + hp->offset); // arg2
|
||||
DWORD ch = *data = stack->stack[2];
|
||||
*len = LeadByteTable[(ch >> 8) & 0xff]; // CODEC_ANSI_BE
|
||||
*split = stack->edx >> 16;
|
||||
@ -143,43 +143,53 @@ static void SpecialHookCatSystem3(hook_stack* stack, HookParam *, uintptr_t *da
|
||||
|
||||
bool InsertCatSystemHook()
|
||||
{
|
||||
//DWORD search=0x95EB60F;
|
||||
//DWORD j,i=SearchPattern(processStartAddress,processStopAddress-processStartAddress,&search,4);
|
||||
//if (i==0) return;
|
||||
//i+=processStartAddress;
|
||||
//for (j=i-0x100;i>j;i--)
|
||||
// DWORD search=0x95EB60F;
|
||||
// DWORD j,i=SearchPattern(processStartAddress,processStopAddress-processStartAddress,&search,4);
|
||||
// if (i==0) return;
|
||||
// i+=processStartAddress;
|
||||
// for (j=i-0x100;i>j;i--)
|
||||
// if (*(DWORD*)i==0xcccccccc) break;
|
||||
//if (i==j) return;
|
||||
//hp.address=i+4;
|
||||
//hp.offset=get_reg(regs::eax);
|
||||
//hp.index=4;
|
||||
//hp.type =CODEC_ANSI_BE|DATA_INDIRECT|USING_SPLIT|SPLIT_INDIRECT;
|
||||
//hp.length_offset=1;
|
||||
// if (i==j) return;
|
||||
// hp.address=i+4;
|
||||
// hp.offset=get_reg(regs::eax);
|
||||
// hp.index=4;
|
||||
// hp.type =CODEC_ANSI_BE|DATA_INDIRECT|USING_SPLIT|SPLIT_INDIRECT;
|
||||
// hp.length_offset=1;
|
||||
|
||||
enum { beg = 0xff6acccc }; // jichi 7/12/2014: beginning of the function
|
||||
enum { addr_offset = 2 }; // skip two leading 0xcc
|
||||
enum
|
||||
{
|
||||
beg = 0xff6acccc
|
||||
}; // jichi 7/12/2014: beginning of the function
|
||||
enum
|
||||
{
|
||||
addr_offset = 2
|
||||
}; // skip two leading 0xcc
|
||||
ULONG addr = MemDbg::findCallerAddress((ULONG)::GetTextMetricsA, beg, processStartAddress, processStopAddress);
|
||||
if (!addr) {
|
||||
if (!addr)
|
||||
{
|
||||
ConsoleOutput("CatSystem2: pattern not exist");
|
||||
return false;
|
||||
}
|
||||
|
||||
HookParam hp;
|
||||
hp.address = addr + addr_offset; // skip 1 push?
|
||||
hp.offset=get_stack(2); // text character is in arg2
|
||||
hp.offset = get_stack(2); // text character is in arg2
|
||||
|
||||
// jichi 12/23/2014: Modify split for new catsystem
|
||||
bool newEngine = Util::CheckFile(L"cs2conf.dll");
|
||||
if (newEngine) {
|
||||
//hp.text_fun = SpecialHookCatSystem3; // type not needed
|
||||
//NewHook(hp, "CatSystem3");
|
||||
//ConsoleOutput("INSERT CatSystem3");
|
||||
hp.type = CODEC_ANSI_BE|USING_SPLIT;
|
||||
if (newEngine)
|
||||
{
|
||||
// hp.text_fun = SpecialHookCatSystem3; // type not needed
|
||||
// NewHook(hp, "CatSystem3");
|
||||
// ConsoleOutput("INSERT CatSystem3");
|
||||
hp.type = CODEC_ANSI_BE | USING_SPLIT;
|
||||
hp.split = get_reg(regs::esi);
|
||||
ConsoleOutput("INSERT CatSystem3new");
|
||||
return NewHook(hp, "CatSystem3new");
|
||||
} else {
|
||||
hp.type = CODEC_ANSI_BE|USING_SPLIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
hp.type = CODEC_ANSI_BE | USING_SPLIT;
|
||||
hp.split = get_reg(regs::edx);
|
||||
ConsoleOutput("INSERT CatSystem2");
|
||||
return NewHook(hp, "CatSystem2");
|
||||
@ -205,23 +215,30 @@ bool InsertCatSystem2Hook()
|
||||
|
||||
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
||||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
||||
if (!addr) {
|
||||
ConsoleOutput("CatSystem2new: pattern not found");
|
||||
if (!addr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HookParam hp;
|
||||
hp.address = addr;
|
||||
hp.offset=get_reg(regs::eax);
|
||||
hp.type = USING_STRING|CODEC_UTF8;
|
||||
ConsoleOutput("INSERT CatSystem2new");
|
||||
|
||||
hp.offset = get_reg(regs::eax);
|
||||
hp.type = USING_STRING | CODEC_UTF8;
|
||||
hp.filter_fun = [](void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
static std::regex rx(R"(\[(.+?)/.+\])");
|
||||
auto _ = std::regex_replace(std::string((char *)data, *len), rx, "$1");
|
||||
return write_string_overwrite(data, len, _);
|
||||
};
|
||||
return NewHook(hp, "CatSystem2new");
|
||||
}
|
||||
namespace { // unnamed
|
||||
namespace Patch {
|
||||
namespace
|
||||
{ // unnamed
|
||||
namespace Patch
|
||||
{
|
||||
|
||||
namespace Private {
|
||||
namespace Private
|
||||
{
|
||||
// String in ecx
|
||||
// bool __fastcall isLeadByteChar(const char *s, DWORD edx)
|
||||
// bool isLeadByteChar(hook_stack*s,void* data, size_t* len,uintptr_t*role)
|
||||
@ -234,17 +251,17 @@ namespace Private {
|
||||
// //return dynsjis::isleadstr(s); // no idea why this will cause Grisaia3 to hang
|
||||
// //return ::IsDBCSLeadByte(HIBYTE(testChar));
|
||||
// }
|
||||
bool isLeadByteChar(char* s)
|
||||
bool isLeadByteChar(char *s)
|
||||
{
|
||||
return s && dynsjis::isleadchar(*s);
|
||||
|
||||
//return dynsjis::isleadstr(s); // no idea why this will cause Grisaia3 to hang
|
||||
//return ::IsDBCSLeadByte(HIBYTE(testChar));
|
||||
// return dynsjis::isleadstr(s); // no idea why this will cause Grisaia3 to hang
|
||||
// return ::IsDBCSLeadByte(HIBYTE(testChar));
|
||||
}
|
||||
|
||||
} // namespace Private
|
||||
} // namespace Private
|
||||
|
||||
/**
|
||||
/**
|
||||
* Sample game: ゆきこいめると
|
||||
*
|
||||
* This function is found by searching the following instruction:
|
||||
@ -362,8 +379,8 @@ namespace Private {
|
||||
* 004148C8 CC INT3
|
||||
*/
|
||||
|
||||
ULONG patchEncoding(ULONG startAddress, ULONG stopAddress)
|
||||
{
|
||||
ULONG patchEncoding(ULONG startAddress, ULONG stopAddress)
|
||||
{
|
||||
const uint8_t bytes[] = {
|
||||
0x74, 0x29, // 00511c8c 74 29 je short .00511cb7
|
||||
0x3c, 0x81 // 00511c8e 3c 81 cmp al,0x81
|
||||
@ -375,14 +392,14 @@ ULONG patchEncoding(ULONG startAddress, ULONG stopAddress)
|
||||
if (!addr)
|
||||
return false;
|
||||
for (auto p = addr; p - addr < 20; p += ::disasm((LPCVOID)p))
|
||||
if (*(WORD *)p == 0xc985)// 00414890 85C9 TEST ECX,ECX ; jichi: text in ecx
|
||||
return addr;//winhook::replace_fun(p, (ULONG)Private::isLeadByteChar);
|
||||
if (*(WORD *)p == 0xc985) // 00414890 85C9 TEST ECX,ECX ; jichi: text in ecx
|
||||
return addr; // winhook::replace_fun(p, (ULONG)Private::isLeadByteChar);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Patch
|
||||
} // namespace Patch
|
||||
|
||||
/**
|
||||
/**
|
||||
* Sample game: ゆきこいめると
|
||||
*
|
||||
* Example prefix to skip:
|
||||
@ -407,17 +424,19 @@ ULONG patchEncoding(ULONG startAddress, ULONG stopAddress)
|
||||
*
|
||||
* 1 select_go_tar たるひ初キスシーンを見る
|
||||
*/
|
||||
template <typename strT>
|
||||
strT ltrim(strT text)
|
||||
{
|
||||
template <typename strT>
|
||||
strT ltrim(strT text)
|
||||
{
|
||||
strT lastText = nullptr;
|
||||
while (*text && text != lastText) {
|
||||
while (*text && text != lastText)
|
||||
{
|
||||
lastText = text;
|
||||
if (text[0] == 0x20)
|
||||
text++;
|
||||
if ((UINT8)text[0] == 0x81 && (UINT8)text[1] == 0x40) // skip space \u3000 (0x8140 in sjis)
|
||||
text += 2;
|
||||
if (text[0] == '\\') {
|
||||
if (text[0] == '\\')
|
||||
{
|
||||
text++;
|
||||
while (::islower(text[0]) || text[0] == '@')
|
||||
text++;
|
||||
@ -426,19 +445,21 @@ strT ltrim(strT text)
|
||||
while ((signed char)text[0] > 0 && text[0] != '[') // skip all leading ascii characters except "[" needed for ruby
|
||||
text++;
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove trailing '\@'
|
||||
size_t rtrim(LPCSTR text)
|
||||
{
|
||||
// Remove trailing '\@'
|
||||
size_t rtrim(LPCSTR text)
|
||||
{
|
||||
size_t size = ::strlen(text);
|
||||
while (size >= 2 && text[size - 2] == '\\' && (UINT8)text[size - 1] <= 127)
|
||||
size -= 2;
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ScenarioHook {
|
||||
namespace Private {
|
||||
namespace ScenarioHook
|
||||
{
|
||||
namespace Private
|
||||
{
|
||||
|
||||
bool isOtherText(LPCSTR text)
|
||||
{
|
||||
@ -460,48 +481,63 @@ namespace Private {
|
||||
* 03283AC8 00 00 00 00 48 80 4F 03 00 00 00 00 CC CC CC CC ....HO....フフフフ
|
||||
* 03283AD8 CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC フフフフフフフフフフフフフフフフ
|
||||
*/
|
||||
//struct ClassArgument // for ecx
|
||||
// struct ClassArgument // for ecx
|
||||
//{
|
||||
// DWORD unknown[7],
|
||||
// split1, // 0x20 - 9
|
||||
// split2; // 0x20
|
||||
// // split1 - split2 is always 0x94
|
||||
// DWORD split() const { return split1 - split2; } //
|
||||
//};
|
||||
// };
|
||||
|
||||
static bool containsNamePunct_(const char *text)
|
||||
{
|
||||
static bool containsNamePunct_(const char *text)
|
||||
{
|
||||
static const char *puncts[] = {
|
||||
"\x81\x41" /* 、 */
|
||||
, "\x81\x43" /* , */
|
||||
, "\x81\x42" /* 。 */
|
||||
,
|
||||
"\x81\x43" /* , */
|
||||
,
|
||||
"\x81\x42" /* 。 */
|
||||
//, "\x81\x48" /* ? */
|
||||
, "\x81\x49" /* ! */
|
||||
, "\x81\x63" /* … */
|
||||
, "\x81\x64" /* ‥ */
|
||||
,
|
||||
"\x81\x49" /* ! */
|
||||
,
|
||||
"\x81\x63" /* … */
|
||||
,
|
||||
"\x81\x64" /* ‥ */
|
||||
|
||||
//, "\x81\x79" /* 【 */
|
||||
//, "\x81\x7a" /* 】 */
|
||||
, "\x81\x75" /* 「 */
|
||||
, "\x81\x76" /* 」 */
|
||||
, "\x81\x77" /* 『 */
|
||||
, "\x81\x78" /* 』 */
|
||||
,
|
||||
"\x81\x75" /* 「 */
|
||||
,
|
||||
"\x81\x76" /* 」 */
|
||||
,
|
||||
"\x81\x77" /* 『 */
|
||||
,
|
||||
"\x81\x78" /* 』 */
|
||||
//, "\x81\x69" /* ( */
|
||||
//, "\x81\x6a" /* ) */
|
||||
//, "\x81\x6f" /* { */
|
||||
//, "\x81\x70" /* } */
|
||||
//, "\x81\x71" /* 〈 */
|
||||
//, "\x81\x72" /* 〉 */
|
||||
, "\x81\x6d" /* [ */
|
||||
, "\x81\x6e" /* ] */
|
||||
,
|
||||
"\x81\x6d" /* [ */
|
||||
,
|
||||
"\x81\x6e" /* ] */
|
||||
//, "\x81\x83", /* < */
|
||||
//, "\x81\x84", /* > */
|
||||
, "\x81\x65" /* ‘ */
|
||||
, "\x81\x66" /* ’ */
|
||||
, "\x81\x67" /* “ */
|
||||
, "\x81\x68" /* ” */
|
||||
,
|
||||
"\x81\x65" /* ‘ */
|
||||
,
|
||||
"\x81\x66" /* ’ */
|
||||
,
|
||||
"\x81\x67" /* “ */
|
||||
,
|
||||
"\x81\x68" /* ” */
|
||||
};
|
||||
for (size_t i = 0; i < sizeof(puncts)/sizeof(*puncts); i++)
|
||||
for (size_t i = 0; i < sizeof(puncts) / sizeof(*puncts); i++)
|
||||
if (::strstr(text, puncts[i]))
|
||||
return true;
|
||||
|
||||
@ -509,43 +545,47 @@ static bool containsNamePunct_(const char *text)
|
||||
&& !::strstr(text, "\x81\x48\x81\x48\x81\x48")) /* ??? */
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool guessIsNameText(const char *text, size_t size)
|
||||
{
|
||||
enum { MaximumNameSize = 0x10 };
|
||||
{
|
||||
enum
|
||||
{
|
||||
MaximumNameSize = 0x10
|
||||
};
|
||||
if (!size)
|
||||
size = ::strlen(text);
|
||||
return size < MaximumNameSize && !containsNamePunct_(text);
|
||||
}
|
||||
LPSTR trimmedText;size_t trimmedSize;
|
||||
bool hookBefore(hook_stack*s,void* data, size_t* len,uintptr_t*role)
|
||||
}
|
||||
LPSTR trimmedText;
|
||||
size_t trimmedSize;
|
||||
bool hookBefore(hook_stack *s, void *data, size_t *len, uintptr_t *role)
|
||||
{
|
||||
//static std::unordered_set<uint64_t> hashes_;
|
||||
// static std::unordered_set<uint64_t> hashes_;
|
||||
auto text = (LPSTR)s->eax; // arg1
|
||||
if (!text || !*text || all_ascii(text))
|
||||
return false;
|
||||
// Alternatively, if do not skip ascii chars, edx is always 0x4ef74 for Japanese texts
|
||||
//if (s->edx != 0x4ef74)
|
||||
// if (s->edx != 0x4ef74)
|
||||
// return true;
|
||||
trimmedText = ltrim(text);
|
||||
if (!trimmedText || !*trimmedText)
|
||||
return false;
|
||||
trimmedSize = rtrim(trimmedText);
|
||||
* role = Engine::OtherRole;
|
||||
//DOUT(QString::fromLocal8Bit((LPCSTR)s->esi));
|
||||
//auto splitText = (LPCSTR)s->esi;
|
||||
//if (::strcmp(splitText, "MES_SETNAME")) // This is for scenario text with voice
|
||||
//if (::strcmp(splitText, "MES_SETFACE"))
|
||||
//if (::strcmp(splitText, "pcm")) // first scenario or history without text
|
||||
*role = Engine::OtherRole;
|
||||
// DOUT(QString::fromLocal8Bit((LPCSTR)s->esi));
|
||||
// auto splitText = (LPCSTR)s->esi;
|
||||
// if (::strcmp(splitText, "MES_SETNAME")) // This is for scenario text with voice
|
||||
// if (::strcmp(splitText, "MES_SETFACE"))
|
||||
// if (::strcmp(splitText, "pcm")) // first scenario or history without text
|
||||
// return true;
|
||||
//auto retaddr = s->stack[1]; // caller
|
||||
//auto retaddr = s->stack[13]; // parent caller
|
||||
//auto split = *(DWORD *)s->esi;
|
||||
//auto split = s->esi - s->eax;
|
||||
//DOUT(split);
|
||||
//auto self = (ClassArgument *)s->ecx;
|
||||
//auto split = self->split();
|
||||
//enum { sig = 0 };
|
||||
// auto retaddr = s->stack[1]; // caller
|
||||
// auto retaddr = s->stack[13]; // parent caller
|
||||
// auto split = *(DWORD *)s->esi;
|
||||
// auto split = s->esi - s->eax;
|
||||
// DOUT(split);
|
||||
// auto self = (ClassArgument *)s->ecx;
|
||||
// auto split = self->split();
|
||||
// enum { sig = 0 };
|
||||
auto self = s->ecx;
|
||||
if (!Engine::isAddressWritable(self)) // old cs2 game such as Grisaia
|
||||
self = s->stack[2]; // arg1
|
||||
@ -555,8 +595,9 @@ static bool containsNamePunct_(const char *text)
|
||||
{
|
||||
static ULONG minimumGroupId_ = -1; // I assume scenario thread to have minimum groupId
|
||||
|
||||
//if (session_.addText(groupId, Engine::hashCharArray(text))) {
|
||||
if (groupId <= minimumGroupId_) {
|
||||
// if (session_.addText(groupId, Engine::hashCharArray(text))) {
|
||||
if (groupId <= minimumGroupId_)
|
||||
{
|
||||
minimumGroupId_ = groupId;
|
||||
|
||||
*role = Engine::ScenarioRole;
|
||||
@ -567,24 +608,24 @@ static bool containsNamePunct_(const char *text)
|
||||
else if (trimmedText == text && !trimmedText[trimmedSize] // no prefix and suffix
|
||||
&& guessIsNameText(trimmedText, trimmedSize))
|
||||
*role = Engine::NameRole;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::string oldData(trimmedText, trimmedSize);
|
||||
|
||||
return write_string_overwrite(data,len,oldData);
|
||||
return write_string_overwrite(data, len, oldData);
|
||||
}
|
||||
void hookafter(hook_stack*s,void* data, size_t len){
|
||||
void hookafter(hook_stack *s, void *data, size_t len)
|
||||
{
|
||||
|
||||
auto newData =std::string((char*)data,len);
|
||||
auto newData = std::string((char *)data, len);
|
||||
if (trimmedText[trimmedSize])
|
||||
newData.append(trimmedText + trimmedSize);
|
||||
::strcpy(trimmedText, newData.c_str());
|
||||
}
|
||||
} // namespace Private
|
||||
} // namespace Private
|
||||
|
||||
/**
|
||||
/**
|
||||
* Sample game: 果つることなき未来ヨリ
|
||||
*
|
||||
* Debugging message:
|
||||
@ -749,46 +790,62 @@ static bool containsNamePunct_(const char *text)
|
||||
* 004985CC CC INT3
|
||||
* 004985CD CC INT3
|
||||
*/
|
||||
bool attach(ULONG startAddress, ULONG stopAddress)
|
||||
{
|
||||
bool attach(ULONG startAddress, ULONG stopAddress, HookParamType code)
|
||||
{
|
||||
const uint8_t bytes[] = {
|
||||
0xe8, XX4, // 004b00dc e8 7f191300 call .005e1a60 ; jichi: hook after here
|
||||
0xbe, XX4, // 004b00e1 be d0e87b00 mov esi,.007be8d0
|
||||
0x8b,0xc8, // 004b00e6 8bc8 mov ecx,eax
|
||||
0x2b,0xf0 // 004b00e8 2bf0 sub esi,eax
|
||||
//XX2, XX, 0x00,0x00,0x00 // 004b00ea 8d9b 00000000 lea ebx,dword ptr ds:[ebx]
|
||||
0x8b, 0xc8, // 004b00e6 8bc8 mov ecx,eax
|
||||
0x2b, 0xf0 // 004b00e8 2bf0 sub esi,eax
|
||||
// XX2, XX, 0x00,0x00,0x00 // 004b00ea 8d9b 00000000 lea ebx,dword ptr ds:[ebx]
|
||||
};
|
||||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
|
||||
if(addr==0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
HookParam hp;
|
||||
hp.address=addr+5;
|
||||
hp.type=USING_STRING|EMBED_ABLE|EMBED_DYNA_SJIS;
|
||||
hp.hook_before=Private::hookBefore;
|
||||
hp.hook_after=Private::hookafter;
|
||||
hp.hook_font=F_GetGlyphOutlineA;
|
||||
hp.filter_fun=[](void* data, size_t* len, HookParam* hp){
|
||||
|
||||
hp.address = addr + 5;
|
||||
hp.type = USING_STRING | EMBED_ABLE;
|
||||
if (code)
|
||||
hp.type |= code;
|
||||
else
|
||||
hp.type |= EMBED_DYNA_SJIS;
|
||||
hp.hook_before = Private::hookBefore;
|
||||
hp.hook_after = Private::hookafter;
|
||||
hp.hook_font = F_GetGlyphOutlineA;
|
||||
hp.filter_fun = [](void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
static std::regex rx(R"(\[(.+?)/.+\])");
|
||||
auto _=std::regex_replace(std::string((char*)data,*len), rx, "$1");
|
||||
return write_string_overwrite(data,len,_);
|
||||
auto _ = std::regex_replace(std::string((char *)data, *len), rx, "$1");
|
||||
return write_string_overwrite(data, len, _);
|
||||
};
|
||||
|
||||
static ULONG p;
|
||||
p=Patch::patchEncoding(startAddress, stopAddress) ;
|
||||
if(p){
|
||||
hp.type|= EMBED_DYNA_SJIS;
|
||||
hp.hook_font=F_GetGlyphOutlineA;
|
||||
patch_fun=[](){
|
||||
ReplaceFunction((PVOID*)&p, (PVOID)(ULONG)Patch::Private::isLeadByteChar);
|
||||
p = Patch::patchEncoding(startAddress, stopAddress);
|
||||
if (p)
|
||||
{
|
||||
hp.type |= EMBED_DYNA_SJIS;
|
||||
hp.hook_font = F_GetGlyphOutlineA;
|
||||
patch_fun = []()
|
||||
{
|
||||
ReplaceFunction((PVOID *)&p, (PVOID)(ULONG)Patch::Private::isLeadByteChar);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
return NewHook(hp,"EmbedCS2");
|
||||
}
|
||||
}
|
||||
return NewHook(hp, "EmbedCS2");
|
||||
}
|
||||
}
|
||||
} // namespace ScenarioHook
|
||||
bool CatSystem::attach_function() {
|
||||
auto embed=ScenarioHook::attach(processStartAddress,processStopAddress);
|
||||
return InsertCatSystemHook()||InsertCatSystem2Hook()||embed;
|
||||
bool CatSystem::attach_function()
|
||||
{
|
||||
HookParamType code = CODEC_ANSI_LE;
|
||||
auto b1 = InsertCatSystemHook();
|
||||
if (!b1)
|
||||
{
|
||||
b1 |= InsertCatSystem2Hook();
|
||||
code = CODEC_UTF8;
|
||||
}
|
||||
auto embed = ScenarioHook::attach(processStartAddress, processStopAddress, code);
|
||||
|
||||
b1 |= embed;
|
||||
return b1;
|
||||
}
|
Loading…
Reference in New Issue
Block a user