diff --git a/cpp/LunaHook/LunaHook/NoEngine.h b/cpp/LunaHook/LunaHook/NoEngine.h index d823cc3e..2ce9d8f4 100644 --- a/cpp/LunaHook/LunaHook/NoEngine.h +++ b/cpp/LunaHook/LunaHook/NoEngine.h @@ -4,9 +4,7 @@ public: bool attach_function() { ConsoleOutput("IGNORE %s", getenginename()); - // ConsoleOutput("IGNORE engine"); - PcHooks::hooknormalfunctions(); - return true; + return false; } }; class oldSystem40ini : public NoEngine diff --git a/cpp/LunaHook/LunaHook/engine32/Anim.cpp b/cpp/LunaHook/LunaHook/engine32/Anim.cpp index a5565ea6..32b7dda6 100644 --- a/cpp/LunaHook/LunaHook/engine32/Anim.cpp +++ b/cpp/LunaHook/LunaHook/engine32/Anim.cpp @@ -99,21 +99,10 @@ namespace return NewHook(hp, "Anim3"); } } -namespace -{ - bool gdi() - { - HookParam hp; - hp.address = (DWORD)::GetGlyphOutlineA; - hp.offset = get_stack(2); - hp.type = CODEC_ANSI_BE; - return NewHook(hp, "Anim"); - } -} bool Anim::attach_function() { - + PcHooks::hookGDIFunctions(GetGlyphOutlineA); auto b1 = InsertAnimHook() || InsertAnim2Hook(); b1 = InsertAnim3Hook() || b1; - return gdi() || b1; + return b1; } \ No newline at end of file diff --git a/cpp/LunaHook/LunaHook/engine32/CodeX.cpp b/cpp/LunaHook/LunaHook/engine32/CodeX.cpp index 81b41cd2..b11be3ab 100644 --- a/cpp/LunaHook/LunaHook/engine32/CodeX.cpp +++ b/cpp/LunaHook/LunaHook/engine32/CodeX.cpp @@ -143,5 +143,6 @@ namespace } bool CodeX::attach_function() { + PcHooks::hookGDIFunctions(GetGlyphOutlineA); // 对于部分游戏,文本分两段显示,会吞掉后半段。故此用这个兜底 return (hook3() | InsertCodeXHook()) || hook() || hook2(); } \ No newline at end of file diff --git a/cpp/LunaHook/LunaHook/enginecontrol.cpp b/cpp/LunaHook/LunaHook/enginecontrol.cpp index eeb56737..7acb3a5e 100644 --- a/cpp/LunaHook/LunaHook/enginecontrol.cpp +++ b/cpp/LunaHook/LunaHook/enginecontrol.cpp @@ -138,7 +138,7 @@ void HIJACK() if (!result) { - PcHooks::hooknormalfunctions(); + PcHooks::hookGdiGdiplusD3dxFunctions(); PcHooks::hookOtherPcFunctions(); } } \ No newline at end of file diff --git a/cpp/LunaHook/LunaHook/engines/pchooks/pchooks.cpp b/cpp/LunaHook/LunaHook/engines/pchooks/pchooks.cpp index 7f4d73d2..66ebf6f0 100644 --- a/cpp/LunaHook/LunaHook/engines/pchooks/pchooks.cpp +++ b/cpp/LunaHook/LunaHook/engines/pchooks/pchooks.cpp @@ -11,18 +11,22 @@ // http://bytes.com/topic/c/answers/135834-defining-wide-character-strings-macros // #define LPASTE(s) L##s // #define L(s) LPASTE(s) -#define NEW_HOOK(_dll, _fun, _data, _data_ind, _split_off, _split_ind, _type, _len_off) \ - { \ - HookParam hp; \ - wcsncpy_s(hp.module, _dll, MAX_MODULE_SIZE - 1); \ - strncpy_s(hp.function, #_fun, MAX_MODULE_SIZE - 1); \ - hp.offset = _data; \ - hp.index = _data_ind; \ - hp.split = _split_off; \ - hp.split_index = _split_ind; \ - hp.type = _type | MODULE_OFFSET | FUNCTION_OFFSET; \ - hp.length_offset = _len_off; \ - NewHook(hp, #_fun); \ +#define NEW_HOOK(ptr, _dll, _fun, _data, _data_ind, _split_off, _split_ind, _type, _len_off) \ + { \ + HookParam hp; \ + wcsncpy_s(hp.module, _dll, MAX_MODULE_SIZE - 1); \ + strncpy_s(hp.function, #_fun, MAX_MODULE_SIZE - 1); \ + hp.offset = _data; \ + hp.index = _data_ind; \ + hp.split = _split_off; \ + hp.split_index = _split_ind; \ + hp.type = _type | MODULE_OFFSET | FUNCTION_OFFSET; \ + hp.length_offset = _len_off; \ + if ((!ptr) || \ + (GetModuleHandle(hp.module) && \ + GetProcAddress(GetModuleHandle(hp.module), hp.function) && \ + GetProcAddress(GetModuleHandle(hp.module), hp.function) == ptr)) \ + NewHook(hp, #_fun); \ } #define NEW_MODULE_HOOK(_module, _fun, _data, _data_ind, _split_off, _split_ind, _type, _len_off) \ @@ -45,18 +49,12 @@ enum args { s_retaddr = 0, - s_arg1 = 4 * 1 // 0x4 - , - s_arg2 = 4 * 2 // 0x8 - , - s_arg3 = 4 * 3 // 0xc - , - s_arg4 = 4 * 4 // 0x10 - , - s_arg5 = 4 * 5 // 0x14 - , - s_arg6 = 4 * 6 // 0x18 - , + s_arg1 = 4 * 1, // 0x4 + s_arg2 = 4 * 2, // 0x8 + s_arg3 = 4 * 3, // 0xc + s_arg4 = 4 * 4, // 0x10 + s_arg5 = 4 * 5, // 0x14 + s_arg6 = 4 * 6, // 0x18 s_arg7 = 4 * 7 }; #else // _WIN32 @@ -73,8 +71,18 @@ enum args }; #endif // _WIN64 +bool once_hookGDIFunctions = false; +bool once_hookGDIPlusFunctions = false; +bool once_hookD3DXFunctions = false; +bool once_hookOtherPcFunctions = false; +#define once_run_pchooks(x) \ + { \ + if (once_##x) \ + return; \ + once_##x = true; \ + } constexpr short arg_sz = (short)sizeof(void *); -void PcHooks::hooknormalfunctions() +void PcHooks::hookGdiGdiplusD3dxFunctions() { for (std::wstring DXVersion : {L"d3dx9", L"d3dx10"}) if (HMODULE module = GetModuleHandleW(DXVersion.c_str())) @@ -88,78 +96,50 @@ void PcHooks::hooknormalfunctions() PcHooks::hookGDIPlusFunctions(); } // jichi 7/17/2014: Renamed from InitDefaultHook -void PcHooks::hookGDIFunctions() +void PcHooks::hookGDIFunctions(void *ptr) { - // int TextHook::InitHook(LPVOID addr, DWORD data, DWORD data_ind, DWORD split_off, DWORD split_ind, WORD type, DWORD len_off) - // - // jichi 9/8/2013: Guessed meaning - // - data(off): 4 * the n-th (base 1) parameter representing the data of the string - // - len_off: - // - the n-th (base 1) parameter representing the length of the string - // - or 1 if is char - // - or 0 if detect on run time - // - type: USING_STRING if len_off != 1 else CODEC_ANSI_BE or CODEC_UTF16 - // - // Examples: - // int WINAPI lstrlenA(LPCSTR lpString) - // - data: 4 * 1 = 4, as lpString is the first - // - len_off: 0, as no parameter representing string length - // - type: CODEC_ANSI_BE, since len_off == 1 - // BOOL GetTextExtentPoint32(HDC hdc, LPCTSTR lpString, int c, LPSIZE lpSize); - // - data: 4 * 2 = 0x8, as lpString is the second - // - len_off: 3, as nCount is the 3rd parameter - // - type: USING_STRING, since len_off != 1 - // - // Note: All functions does not have NO_CONTEXT attribute and will be filtered. - - //#define _(Name, ...) \ -// hookman[HF_##Name].InitHook(Name, __VA_ARGS__); \ -// hookman[HF_##Name].SetHookName(names[HF_##Name]); - - // Always use s_arg1 = hDC as split_off - // 7/26/2014 jichi: Why there is no USING_SPLIT type? - + once_run_pchooks(hookGDIFunctions); // gdi32.dll - NEW_HOOK(L"gdi32.dll", GetTextExtentPoint32A, s_arg2, 0, s_arg1, 0, USING_STRING, s_arg3 / arg_sz) // BOOL GetTextExtentPoint32(HDC hdc, LPCTSTR lpString, int c, LPSIZE lpSize); - NEW_HOOK(L"gdi32.dll", GetTextExtentExPointA, s_arg2, 0, s_arg1, 0, USING_STRING, s_arg3 / arg_sz) // BOOL GetTextExtentExPoint(HDC hdc, LPCTSTR lpszStr, int cchString, int nMaxExtent, LPINT lpnFit, LPINT alpDx, LPSIZE lpSize); - NEW_HOOK(L"gdi32.dll", GetCharacterPlacementA, s_arg2, 0, s_arg1, 0, USING_STRING, s_arg3 / arg_sz) // DWORD GetCharacterPlacement(HDC hdc, LPCTSTR lpString, int nCount, int nMaxExtent, LPGCP_RESULTS lpResults, DWORD dwFlags); - NEW_HOOK(L"gdi32.dll", GetGlyphIndicesA, s_arg2, 0, s_arg1, 0, USING_STRING, s_arg3 / arg_sz) // DWORD GetGlyphIndices( HDC hdc, LPCTSTR lpstr, int c, LPWORD pgi, DWORD fl); - NEW_HOOK(L"gdi32.dll", GetGlyphOutlineA, s_arg2, 0, s_arg1, 0, CODEC_ANSI_BE, 0) // DWORD GetGlyphOutline(HDC hdc, UINT uChar, UINT uFormat, LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPVOID lpvBuffer, const MAT2 *lpmat2); - NEW_HOOK(L"gdi32.dll", ExtTextOutA, s_arg6, 0, s_arg1, 0, USING_STRING, s_arg7 / arg_sz) // BOOL ExtTextOut(HDC hdc, int X, int Y, UINT fuOptions, const RECT *lprc, LPCTSTR lpString, UINT cbCount, const INT *lpDx); - NEW_HOOK(L"gdi32.dll", TextOutA, s_arg4, 0, s_arg1, 0, USING_STRING, s_arg5 / arg_sz) // BOOL TextOut(HDC hdc, int nXStart, int nYStart, LPCTSTR lpString, int cchString); - NEW_HOOK(L"gdi32.dll", GetCharABCWidthsA, s_arg2, 0, s_arg1, 0, CODEC_ANSI_BE, 0) // BOOL GetCharABCWidths(HDC hdc, UINT uFirstChar, UINT uLastChar, LPABC lpabc); - NEW_HOOK(L"gdi32.dll", GetCharABCWidthsFloatA, s_arg2, 0, s_arg1, 0, CODEC_ANSI_BE, 0) // BOOL GetCharABCWidthsFloat(HDC hdc, UINT iFirstChar, UINT iLastChar, LPABCFLOAT lpABCF); - NEW_HOOK(L"gdi32.dll", GetCharWidth32A, s_arg2, 0, s_arg1, 0, CODEC_ANSI_BE, 0) // BOOL GetCharWidth32(HDC hdc, UINT iFirstChar, UINT iLastChar, LPINT lpBuffer); - NEW_HOOK(L"gdi32.dll", GetCharWidthFloatA, s_arg2, 0, s_arg1, 0, CODEC_ANSI_BE, 0) // BOOL GetCharWidthFloat(HDC hdc, UINT iFirstChar, UINT iLastChar, PFLOAT pxBuffer); + NEW_HOOK(ptr, L"gdi32.dll", GetTextExtentPoint32A, s_arg2, 0, s_arg1, 0, USING_STRING, s_arg3 / arg_sz) + NEW_HOOK(ptr, L"gdi32.dll", GetTextExtentExPointA, s_arg2, 0, s_arg1, 0, USING_STRING, s_arg3 / arg_sz) + NEW_HOOK(ptr, L"gdi32.dll", GetCharacterPlacementA, s_arg2, 0, s_arg1, 0, USING_STRING, s_arg3 / arg_sz) + NEW_HOOK(ptr, L"gdi32.dll", GetGlyphIndicesA, s_arg2, 0, s_arg1, 0, USING_STRING, s_arg3 / arg_sz) + NEW_HOOK(ptr, L"gdi32.dll", GetGlyphOutlineA, s_arg2, 0, s_arg1, 0, CODEC_ANSI_BE, 0) + NEW_HOOK(ptr, L"gdi32.dll", ExtTextOutA, s_arg6, 0, s_arg1, 0, USING_STRING, s_arg7 / arg_sz) + NEW_HOOK(ptr, L"gdi32.dll", TextOutA, s_arg4, 0, s_arg1, 0, USING_STRING, s_arg5 / arg_sz) + NEW_HOOK(ptr, L"gdi32.dll", GetCharABCWidthsA, s_arg2, 0, s_arg1, 0, CODEC_ANSI_BE, 0) + NEW_HOOK(ptr, L"gdi32.dll", GetCharABCWidthsFloatA, s_arg2, 0, s_arg1, 0, CODEC_ANSI_BE, 0) + NEW_HOOK(ptr, L"gdi32.dll", GetCharWidth32A, s_arg2, 0, s_arg1, 0, CODEC_ANSI_BE, 0) + NEW_HOOK(ptr, L"gdi32.dll", GetCharWidthFloatA, s_arg2, 0, s_arg1, 0, CODEC_ANSI_BE, 0) - NEW_HOOK(L"gdi32.dll", GetTextExtentPoint32W, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) - NEW_HOOK(L"gdi32.dll", GetTextExtentExPointW, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) - NEW_HOOK(L"gdi32.dll", GetCharacterPlacementW, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) - NEW_HOOK(L"gdi32.dll", GetGlyphIndicesW, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) - NEW_HOOK(L"gdi32.dll", GetGlyphOutlineW, s_arg2, 0, s_arg1, 0, CODEC_UTF16, 0) + NEW_HOOK(ptr, L"gdi32.dll", GetTextExtentPoint32W, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) + NEW_HOOK(ptr, L"gdi32.dll", GetTextExtentExPointW, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) + NEW_HOOK(ptr, L"gdi32.dll", GetCharacterPlacementW, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) + NEW_HOOK(ptr, L"gdi32.dll", GetGlyphIndicesW, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) + NEW_HOOK(ptr, L"gdi32.dll", GetGlyphOutlineW, s_arg2, 0, s_arg1, 0, CODEC_UTF16, 0) // ExtTextOutW全是乱码,没卵用 - // NEW_HOOK(L"gdi32.dll", ExtTextOutW, s_arg6, 0,s_arg1,0, CODEC_UTF16|USING_STRING, s_arg7 / arg_sz) - NEW_HOOK(L"gdi32.dll", TextOutW, s_arg4, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg5 / arg_sz) - NEW_HOOK(L"gdi32.dll", GetCharABCWidthsW, s_arg2, 0, s_arg1, 0, CODEC_UTF16, 0) - NEW_HOOK(L"gdi32.dll", GetCharABCWidthsFloatW, s_arg2, 0, s_arg1, 0, CODEC_UTF16, 0) - NEW_HOOK(L"gdi32.dll", GetCharWidth32W, s_arg2, 0, s_arg1, 0, CODEC_UTF16, 0) - NEW_HOOK(L"gdi32.dll", GetCharWidthFloatW, s_arg2, 0, s_arg1, 0, CODEC_UTF16, 0) + // NEW_HOOK(ptr, L"gdi32.dll", ExtTextOutW, s_arg6, 0,s_arg1,0, CODEC_UTF16|USING_STRING, s_arg7 / arg_sz) + NEW_HOOK(ptr, L"gdi32.dll", TextOutW, s_arg4, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg5 / arg_sz) + NEW_HOOK(ptr, L"gdi32.dll", GetCharABCWidthsW, s_arg2, 0, s_arg1, 0, CODEC_UTF16, 0) + NEW_HOOK(ptr, L"gdi32.dll", GetCharABCWidthsFloatW, s_arg2, 0, s_arg1, 0, CODEC_UTF16, 0) + NEW_HOOK(ptr, L"gdi32.dll", GetCharWidth32W, s_arg2, 0, s_arg1, 0, CODEC_UTF16, 0) + NEW_HOOK(ptr, L"gdi32.dll", GetCharWidthFloatW, s_arg2, 0, s_arg1, 0, CODEC_UTF16, 0) // user32.dll - NEW_HOOK(L"user32.dll", DrawTextA, s_arg2, 0, s_arg1, 0, USING_STRING, s_arg3 / arg_sz) // int DrawText(HDC hDC, LPCTSTR lpchText, int nCount, LPRECT lpRect, UINT uFormat); - NEW_HOOK(L"user32.dll", DrawTextExA, s_arg2, 0, s_arg1, 0, USING_STRING, s_arg3 / arg_sz) // int DrawTextEx(HDC hdc, LPTSTR lpchText,int cchText, LPRECT lprc, UINT dwDTFormat, LPDRAWTEXTPARAMS lpDTParams);NEW_HOOK(L"gdi32.dll", GetTabbedTextExtentA, s_arg2, 0,s_arg1,0, USING_STRING, s_arg3 / arg_sz) // DWORD GetTabbedTextExtent(HDC hDC, LPCTSTR lpString, int nCount, int nTabPositions, const LPINT lpnTabStopPositions); - NEW_HOOK(L"user32.dll", TabbedTextOutA, s_arg4, 0, s_arg1, 0, USING_STRING, s_arg5 / arg_sz) // LONG TabbedTextOut(HDC hDC, int X, int Y, LPCTSTR lpString, int nCount, int nTabPositions, const LPINT lpnTabStopPositions, int nTabOrigin); - NEW_HOOK(L"user32.dll", GetTabbedTextExtentA, s_arg2, 0, s_arg1, 0, USING_STRING, s_arg3 / arg_sz) // DWORD GetTabbedTextExtent(HDC hDC, LPCTSTR lpString, int nCount, int nTabPositions, const LPINT lpnTabStopPositions); - - NEW_HOOK(L"user32.dll", DrawTextW, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) - NEW_HOOK(L"user32.dll", DrawTextExW, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) - NEW_HOOK(L"user32.dll", TabbedTextOutW, s_arg4, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg5 / arg_sz) - NEW_HOOK(L"user32.dll", GetTabbedTextExtentW, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) + NEW_HOOK(ptr, L"user32.dll", DrawTextA, s_arg2, 0, s_arg1, 0, USING_STRING, s_arg3 / arg_sz) + NEW_HOOK(ptr, L"user32.dll", DrawTextExA, s_arg2, 0, s_arg1, 0, USING_STRING, s_arg3 / arg_sz) + NEW_HOOK(ptr, L"user32.dll", TabbedTextOutA, s_arg4, 0, s_arg1, 0, USING_STRING, s_arg5 / arg_sz) + NEW_HOOK(ptr, L"user32.dll", GetTabbedTextExtentA, s_arg2, 0, s_arg1, 0, USING_STRING, s_arg3 / arg_sz) + NEW_HOOK(ptr, L"user32.dll", DrawTextW, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) + NEW_HOOK(ptr, L"user32.dll", DrawTextExW, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) + NEW_HOOK(ptr, L"user32.dll", TabbedTextOutW, s_arg4, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg5 / arg_sz) + NEW_HOOK(ptr, L"user32.dll", GetTabbedTextExtentW, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) } // jichi 6/18/2015: GDI+ functions void PcHooks::hookGDIPlusFunctions() { + once_run_pchooks(hookGDIPlusFunctions); HMODULE hModule = ::GetModuleHandleA("gdiplus.dll"); if (!hModule) return; @@ -171,17 +151,18 @@ void PcHooks::hookGDIPlusFunctions() // Use arg1 pionter to GpGraphics as split // using namespace Gdiplus::DllExports; // Use arg5 style as split - NEW_MODULE_HOOK(hModule, GdipAddPathString, s_arg2, 0, s_arg5, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) // GpStatus WINGDIPAPI GdipAddPathString(GpPath *path, GDIPCONST WCHAR *string, INT length, GDIPCONST GpFontFamily *family, INT style, REAL emSize, GDIPCONST RectF *layoutRect, GDIPCONST GpStringFormat *format) - NEW_MODULE_HOOK(hModule, GdipAddPathStringI, s_arg2, 0, s_arg5, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) // GpStatus WINGDIPAPI GdipAddPathStringI(GpPath *path, GDIPCONST WCHAR *string, INT length, GDIPCONST GpFontFamily *family, INT style, REAL emSize, GDIPCONST Rect *layoutRect, GDIPCONST GpStringFormat *format) - NEW_MODULE_HOOK(hModule, GdipMeasureCharacterRanges, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) // GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics *graphics, GDIPCONST WCHAR *string, INT length, GDIPCONST GpFont *font, GDIPCONST RectF &layoutRect, GDIPCONST GpStringFormat *stringFormat, INT regionCount, GpRegion **regions) - NEW_MODULE_HOOK(hModule, GdipDrawString, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) // GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string, INT length, GDIPCONST GpFont *font, GDIPCONST RectF *layoutRect, GDIPCONST GpStringFormat *stringFormat, GDIPCONST GpBrush *brush); - NEW_MODULE_HOOK(hModule, GdipMeasureString, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) // GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics, GDIPCONST WCHAR *string, INT length, GDIPCONST GpFont *font, GDIPCONST RectF *layoutRect, GDIPCONST GpStringFormat *stringFormat, RectF *boundingBox, INT *codepointsFitted, INT *linesFilled ) + NEW_MODULE_HOOK(hModule, GdipAddPathString, s_arg2, 0, s_arg5, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) + NEW_MODULE_HOOK(hModule, GdipAddPathStringI, s_arg2, 0, s_arg5, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) + NEW_MODULE_HOOK(hModule, GdipMeasureCharacterRanges, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) + NEW_MODULE_HOOK(hModule, GdipDrawString, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) + NEW_MODULE_HOOK(hModule, GdipMeasureString, s_arg2, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) NEW_MODULE_HOOK(hModule, GdipDrawDriverString, s_arg1, 0, s_arg3, 0, CODEC_UTF16 | USING_STRING, s_arg2 / arg_sz) NEW_MODULE_HOOK(hModule, GdipMeasureDriverString, s_arg1, 0, s_arg3, 0, CODEC_UTF16 | USING_STRING, s_arg2 / arg_sz) } -bool PcHooks::hookD3DXFunctions(HMODULE d3dxModule) +void PcHooks::hookD3DXFunctions(HMODULE d3dxModule) { + once_run_pchooks(hookD3DXFunctions); if (GetProcAddress(d3dxModule, "D3DXCreateTextA")) { NEW_MODULE_HOOK(d3dxModule, D3DXCreateTextA, s_arg3, 0, 0, 0, USING_STRING, 0) @@ -196,7 +177,7 @@ bool PcHooks::hookD3DXFunctions(HMODULE d3dxModule) if (!createFont) { ConsoleOutput("D3DX failed: couldn't find entry function"); - return false; + return; } struct D3DXFont @@ -227,17 +208,18 @@ bool PcHooks::hookD3DXFunctions(HMODULE d3dxModule) hp.address = (*font.vtable)[15]; hp.type = USING_STRING | CODEC_UTF16; suc |= NewHook(hp, "ID3DXFont::DrawTextW"); - return suc; + return; } } ConsoleOutput("D3DX failed: couldn't find vtable"); - return false; + return; } // jichi 10/2/2013 // Note: All functions does not have NO_CONTEXT attribute and will be filtered. -void PcHooks::hookOtherPcFunctions() +void PcHooks::hookOtherPcFunctions(void *ptr) { + once_run_pchooks(hookOtherPcFunctions); // int TextHook::InitHook(LPVOID addr, DWORD data, DWORD data_ind, DWORD split_off, DWORD split_ind, WORD type, DWORD len_off) // http://msdn.microsoft.com/en-us/library/78zh94ax.aspx @@ -245,13 +227,13 @@ void PcHooks::hookOtherPcFunctions() // Lstr functions usually extracts rubbish, and might crash certain games like 「Magical Marriage Lunatics!!」 // Needed by Gift // Use arg1 address for both split and data - NEW_HOOK(L"kernel32.dll", lstrlenA, s_arg1, 0, s_arg1, 0, USING_STRING, 0) // 9/8/2013 jichi: int WINAPI lstrlen(LPCTSTR lpString); - NEW_HOOK(L"kernel32.dll", lstrcpyA, s_arg2, 0, 0, 0, USING_STRING, 0) - NEW_HOOK(L"kernel32.dll", lstrcpynA, s_arg2, 0, 0, 0, USING_STRING, 0) + NEW_HOOK(ptr, L"kernel32.dll", lstrlenA, s_arg1, 0, s_arg1, 0, USING_STRING, 0) + NEW_HOOK(ptr, L"kernel32.dll", lstrcpyA, s_arg2, 0, 0, 0, USING_STRING, 0) + NEW_HOOK(ptr, L"kernel32.dll", lstrcpynA, s_arg2, 0, 0, 0, USING_STRING, 0) - NEW_HOOK(L"kernel32.dll", lstrlenW, s_arg1, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, 0) // 9/8/2013 jichi: add lstrlen - NEW_HOOK(L"kernel32.dll", lstrcpyW, s_arg2, 0, 0, 0, CODEC_UTF16 | USING_STRING, 0) - NEW_HOOK(L"kernel32.dll", lstrcpynW, s_arg2, 0, 0, 0, CODEC_UTF16 | USING_STRING, 0) + NEW_HOOK(ptr, L"kernel32.dll", lstrlenW, s_arg1, 0, s_arg1, 0, CODEC_UTF16 | USING_STRING, 0) + NEW_HOOK(ptr, L"kernel32.dll", lstrcpyW, s_arg2, 0, 0, 0, CODEC_UTF16 | USING_STRING, 0) + NEW_HOOK(ptr, L"kernel32.dll", lstrcpynW, s_arg2, 0, 0, 0, CODEC_UTF16 | USING_STRING, 0) // size_t strlen(const char *str); // size_t strlen_l(const char *str, _locale_t locale); @@ -306,26 +288,26 @@ void PcHooks::hookOtherPcFunctions() // 2/29/2020 Artikash: TODO: Sort out what to do for string comparison functions // http://sakuradite.com/topic/159 - NEW_HOOK(L"kernel32.dll", MultiByteToWideChar, s_arg3, 0, 4, 0, USING_STRING, s_arg4 / arg_sz) - NEW_HOOK(L"kernel32.dll", WideCharToMultiByte, s_arg3, 0, 4, 0, CODEC_UTF16 | USING_STRING, s_arg4 / arg_sz) + NEW_HOOK(ptr, L"kernel32.dll", MultiByteToWideChar, s_arg3, 0, 4, 0, USING_STRING, s_arg4 / arg_sz) + NEW_HOOK(ptr, L"kernel32.dll", WideCharToMultiByte, s_arg3, 0, 4, 0, CODEC_UTF16 | USING_STRING, s_arg4 / arg_sz) - NEW_HOOK(L"kernel32.dll", GetStringTypeA, s_arg3, 0, 0, 0, USING_STRING, s_arg4 / arg_sz) - NEW_HOOK(L"kernel32.dll", GetStringTypeExA, s_arg3, 0, 0, 0, USING_STRING, s_arg4 / arg_sz) - NEW_HOOK(L"kernel32.dll", FoldStringA, s_arg2, 0, 0, 0, USING_STRING, s_arg3 / arg_sz) - NEW_HOOK(L"kernel32.dll", GetStringTypeW, s_arg2, 0, 0, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) - NEW_HOOK(L"kernel32.dll", GetStringTypeExW, s_arg3, 0, 0, 0, CODEC_UTF16 | USING_STRING, s_arg4 / arg_sz) - NEW_HOOK(L"kernel32.dll", FoldStringW, s_arg2, 0, 0, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) + NEW_HOOK(ptr, L"kernel32.dll", GetStringTypeA, s_arg3, 0, 0, 0, USING_STRING, s_arg4 / arg_sz) + NEW_HOOK(ptr, L"kernel32.dll", GetStringTypeExA, s_arg3, 0, 0, 0, USING_STRING, s_arg4 / arg_sz) + NEW_HOOK(ptr, L"kernel32.dll", FoldStringA, s_arg2, 0, 0, 0, USING_STRING, s_arg3 / arg_sz) + NEW_HOOK(ptr, L"kernel32.dll", GetStringTypeW, s_arg2, 0, 0, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) + NEW_HOOK(ptr, L"kernel32.dll", GetStringTypeExW, s_arg3, 0, 0, 0, CODEC_UTF16 | USING_STRING, s_arg4 / arg_sz) + NEW_HOOK(ptr, L"kernel32.dll", FoldStringW, s_arg2, 0, 0, 0, CODEC_UTF16 | USING_STRING, s_arg3 / arg_sz) - NEW_HOOK(L"user32.dll", CharNextA, s_arg1, 0, 0, 0, DATA_INDIRECT, 0) // LPTSTR WINAPI CharNext(_In_ LPCTSTR lpsz); - NEW_HOOK(L"user32.dll", CharNextW, s_arg1, 0, 0, 0, CODEC_UTF16 | DATA_INDIRECT, 0) - NEW_HOOK(L"user32.dll", CharPrevA, s_arg1, 0, 0, 0, DATA_INDIRECT, 0) // LPTSTR WINAPI CharPrev(_In_ LPCTSTR lpszStart, _In_ LPCTSTR lpszCurrent); - NEW_HOOK(L"user32.dll", CharPrevW, s_arg1, 0, 0, 0, CODEC_UTF16 | DATA_INDIRECT, 0) - NEW_HOOK(L"user32.dll", CharNextExA, s_arg2, 0, 0, 0, DATA_INDIRECT, 0) // LPSTR WINAPI CharNextExA(_In_ WORD CodePage, _In_ LPCSTR lpCurrentChar, _In_ DWORD dwFlags); - NEW_HOOK(L"user32.dll", CharPrevExA, s_arg2, 0, 0, 0, CODEC_UTF16 | DATA_INDIRECT, 0) + NEW_HOOK(ptr, L"user32.dll", CharNextA, s_arg1, 0, 0, 0, DATA_INDIRECT, 0) + NEW_HOOK(ptr, L"user32.dll", CharNextW, s_arg1, 0, 0, 0, CODEC_UTF16 | DATA_INDIRECT, 0) + NEW_HOOK(ptr, L"user32.dll", CharPrevA, s_arg1, 0, 0, 0, DATA_INDIRECT, 0) + NEW_HOOK(ptr, L"user32.dll", CharPrevW, s_arg1, 0, 0, 0, CODEC_UTF16 | DATA_INDIRECT, 0) + NEW_HOOK(ptr, L"user32.dll", CharNextExA, s_arg2, 0, 0, 0, DATA_INDIRECT, 0) + NEW_HOOK(ptr, L"user32.dll", CharPrevExA, s_arg2, 0, 0, 0, CODEC_UTF16 | DATA_INDIRECT, 0) // トキノ戦華 - NEW_HOOK(L"user32.dll", wvsprintfA, s_arg2, 0, 0, 0, USING_STRING, 0) - NEW_HOOK(L"user32.dll", wvsprintfW, s_arg2, 0, 0, 0, CODEC_UTF16 | USING_STRING, 0) + NEW_HOOK(ptr, L"user32.dll", wvsprintfA, s_arg2, 0, 0, 0, USING_STRING, 0) + NEW_HOOK(ptr, L"user32.dll", wvsprintfW, s_arg2, 0, 0, 0, CODEC_UTF16 | USING_STRING, 0) if (HMODULE module = GetModuleHandleW(L"OLEAUT32.dll")) { diff --git a/cpp/LunaHook/LunaHook/engines/pchooks/pchooks.h b/cpp/LunaHook/LunaHook/engines/pchooks/pchooks.h index b2918e6d..f7633481 100644 --- a/cpp/LunaHook/LunaHook/engines/pchooks/pchooks.h +++ b/cpp/LunaHook/LunaHook/engines/pchooks/pchooks.h @@ -7,11 +7,11 @@ namespace PcHooks { - void hookGDIFunctions(); + void hookGDIFunctions(void *ptr = 0); void hookGDIPlusFunctions(); - bool hookD3DXFunctions(HMODULE d3dxModule); - void hookOtherPcFunctions(); - void hooknormalfunctions(); + void hookD3DXFunctions(HMODULE d3dxModule); + void hookOtherPcFunctions(void *ptr = 0); + void hookGdiGdiplusD3dxFunctions(); } // namespace PcHooks // EOF diff --git a/cpp/LunaHook/LunaHook/main.cc b/cpp/LunaHook/LunaHook/main.cc index dc2dba53..872cc1a8 100644 --- a/cpp/LunaHook/LunaHook/main.cc +++ b/cpp/LunaHook/LunaHook/main.cc @@ -34,7 +34,7 @@ DWORD WINAPI Pipe(LPVOID) *(DWORD *)buffer = GetCurrentProcessId(); WriteFile(hookPipe, buffer, sizeof(DWORD), &count, nullptr); - WORD hookversion[4]=LUNA_VERSION; + WORD hookversion[4] = LUNA_VERSION; WriteFile(hookPipe, hookversion, sizeof(hookversion), &count, nullptr); ConsoleOutput(PIPE_CONNECTED); @@ -50,6 +50,15 @@ DWORD WINAPI Pipe(LPVOID) NewHook(info.hp, ("UserHook" + std::to_string(userHooks += 1)).c_str()); } break; + case HOST_COMMAND_INSERT_PC_HOOKS: + { + auto info = *(InsertPCHooksCmd *)buffer; + if (info.which == 0) + PcHooks::hookGdiGdiplusD3dxFunctions(); + else if (info.which == 1) + PcHooks::hookOtherPcFunctions(); + } + break; case HOST_COMMAND_REMOVE_HOOK: { auto info = *(RemoveHookCmd *)buffer; diff --git a/cpp/LunaHook/LunaHost/LunaHostDll.cpp b/cpp/LunaHook/LunaHost/LunaHostDll.cpp index 62e357ea..5ffafa5f 100644 --- a/cpp/LunaHook/LunaHost/LunaHostDll.cpp +++ b/cpp/LunaHook/LunaHost/LunaHostDll.cpp @@ -72,6 +72,10 @@ C_LUNA_API void Luna_Settings(int flushDelay, bool filterRepetition, int default TextThread::maxHistorySize = maxHistorySize; } +C_LUNA_API void Luna_InsertPCHooks(DWORD pid, int which) +{ + Host::InsertPCHooks(pid, which); +} C_LUNA_API bool Luna_InsertHookCode(DWORD pid, LPCWSTR hookcode) { auto hp = HookCode::Parse(hookcode); diff --git a/cpp/LunaHook/LunaHost/host.cpp b/cpp/LunaHook/LunaHost/host.cpp index ed677655..817bd8fa 100644 --- a/cpp/LunaHook/LunaHost/host.cpp +++ b/cpp/LunaHook/LunaHost/host.cpp @@ -350,6 +350,13 @@ namespace Host prs.at(processId).Send(HOST_COMMAND_DETACH); } + void InsertPCHooks(DWORD processId, int which) + { + auto &prs = processRecordsByIds.Acquire().contents; + if (prs.find(processId) == prs.end()) + return; + prs.at(processId).Send(InsertPCHooksCmd(which)); + } void InsertHook(DWORD processId, HookParam hp) { auto &prs = processRecordsByIds.Acquire().contents; diff --git a/cpp/LunaHook/LunaHost/host.h b/cpp/LunaHook/LunaHost/host.h index 9b0d2c8f..1efe63a7 100644 --- a/cpp/LunaHook/LunaHost/host.h +++ b/cpp/LunaHook/LunaHost/host.h @@ -17,6 +17,7 @@ namespace Host void DetachProcess(DWORD processId); void InsertHook(DWORD processId, HookParam hp); + void InsertPCHooks(DWORD processId, int which); void RemoveHook(DWORD processId, uint64_t address); void FindHooks(DWORD processId, SearchParam sp, HookEventHandler HookFound = {}); CommonSharedMem *GetCommonSharedMem(DWORD pid); diff --git a/cpp/LunaHook/include/const.h b/cpp/LunaHook/include/const.h index 6282326c..ca913d3b 100644 --- a/cpp/LunaHook/include/const.h +++ b/cpp/LunaHook/include/const.h @@ -26,7 +26,8 @@ enum HostCommandType HOST_COMMAND_FIND_HOOK, HOST_COMMAND_MODIFY_HOOK, HOST_COMMAND_HIJACK_PROCESS, - HOST_COMMAND_DETACH + HOST_COMMAND_DETACH, + HOST_COMMAND_INSERT_PC_HOOKS, }; enum HostNotificationType diff --git a/cpp/LunaHook/include/types.h b/cpp/LunaHook/include/types.h index e9a16bdd..c0b6c5ed 100644 --- a/cpp/LunaHook/include/types.h +++ b/cpp/LunaHook/include/types.h @@ -157,7 +157,12 @@ struct SearchParam wchar_t text[PATTERN_SIZE] = {}; // text to search for JITTYPE jittype; }; - +struct InsertPCHooksCmd +{ + InsertPCHooksCmd(int _which) : which(_which) {} + HostCommandType command = HOST_COMMAND_INSERT_PC_HOOKS; + int which; +}; struct InsertHookCmd // From host { InsertHookCmd(HookParam hp) : hp(hp) {} diff --git a/py/LunaTranslator/gui/dialog_savedgame_setting.py b/py/LunaTranslator/gui/dialog_savedgame_setting.py index d7660017..d38afb7f 100644 --- a/py/LunaTranslator/gui/dialog_savedgame_setting.py +++ b/py/LunaTranslator/gui/dialog_savedgame_setting.py @@ -16,7 +16,7 @@ from myutils.config import ( ) from myutils.localetools import getgamecamptools, maycreatesettings from myutils.hwnd import getExeIcon -from myutils.wrapper import Singleton, Singleton_close +from myutils.wrapper import Singleton, Singleton_close, trypass from myutils.utils import ( gamdidchangedtask, checkpostlangmatch, @@ -58,6 +58,7 @@ from gui.dynalang import ( LAction, LLabel, LDialog, + LGroupBox, ) from gui.dialog_savedgame_common import tagitem @@ -1005,8 +1006,33 @@ class dialog_setting_game_internal(QWidget): "延迟注入_(ms)", getspinbox(0, 1000000, savehook_new_data[gameuid], "inserthooktimeout"), ) + box = LGroupBox() + box.setTitle("额外的钩子") + settinglayout = LFormLayout() + box.setLayout(settinglayout) + formLayout.addRow(box) + settinglayout.addRow( + "Win32文字绘制函数钩子", + getsimpleswitch( + savehook_new_data[gameuid], + "insertpchooks_GdiGdiplusD3dx", + callback=lambda _: ( + gobject.baseobject.textsource.InsertPCHooks(0) if _ else None + ), + ), + ) + settinglayout.addRow( + "Win32字符串函数钩子", + getsimpleswitch( + savehook_new_data[gameuid], + "insertpchooks_string", + callback=lambda _: ( + gobject.baseobject.textsource.InsertPCHooks(1) if _ else None + ), + ), + ) - formLayout.addRow( + settinglayout.addRow( "特殊码", listediterline( ("特殊码"), @@ -1014,7 +1040,10 @@ class dialog_setting_game_internal(QWidget): savehook_new_data[gameuid]["needinserthookcode"], ), ) - + box = QGroupBox() + settinglayout = LFormLayout() + box.setLayout(settinglayout) + formLayout.addRow(box) for k in [ "codepage_index", "textthreaddelay", @@ -1028,7 +1057,7 @@ class dialog_setting_game_internal(QWidget): formLayout2 = self.createfollowdefault( savehook_new_data[gameuid], "hooksetting_follow_default", - formLayout, + settinglayout, lambda: gobject.baseobject.textsource.setsettings(), ) formLayout2.addRow( diff --git a/py/LunaTranslator/myutils/config.py b/py/LunaTranslator/myutils/config.py index 8bc60702..0b850250 100644 --- a/py/LunaTranslator/myutils/config.py +++ b/py/LunaTranslator/myutils/config.py @@ -139,7 +139,9 @@ def getdefaultsavehook(title=None): "statistic_wordcount_nodump": 0, # "leuse": True, 废弃 "hook": [], - "inserthooktimeout": 1000, + "inserthooktimeout": 500, + "insertpchooks_GdiGdiplusD3dx": False, + "insertpchooks_string": False, "needinserthookcode": [], # "allow_tts_auto_names": "",#->v4 # "allow_tts_auto_names_v4": [], diff --git a/py/LunaTranslator/textsource/texthook.py b/py/LunaTranslator/textsource/texthook.py index b42c0d94..9cd6f16d 100644 --- a/py/LunaTranslator/textsource/texthook.py +++ b/py/LunaTranslator/textsource/texthook.py @@ -192,6 +192,8 @@ class texthook(basetext): ) self.Luna_SyncThread = LunaHost.Luna_SyncThread self.Luna_SyncThread.argtypes = ThreadParam, c_bool + self.Luna_InsertPCHooks = LunaHost.Luna_InsertPCHooks + self.Luna_InsertPCHooks.argtypes = (DWORD, c_int) self.Luna_Settings = LunaHost.Luna_Settings self.Luna_Settings.argtypes = c_int, c_bool, c_int, c_int, c_int self.Luna_Start = LunaHost.Luna_Start @@ -438,11 +440,19 @@ class texthook(basetext): pass for hookcode in self.needinserthookcode: self.Luna_InsertHookCode(pid, hookcode) + if savehook_new_data[self.gameuid]["insertpchooks_GdiGdiplusD3dx"]: + self.Luna_InsertPCHooks(pid, 0) + if savehook_new_data[self.gameuid]["insertpchooks_string"]: + self.Luna_InsertPCHooks(pid, 1) gobject.baseobject.displayinfomessage( savehook_new_data[self.gameuid]["title"], "" ) self.flashembedsettings(pid) + def InsertPCHooks(self, which): + for pid in self.pids: + self.Luna_InsertPCHooks(pid, which) + def newhookinsert(self, pid, addr, hcode): for _hc, _addr, _ctx1, _ctx2 in savehook_new_data[self.gameuid][ "embedablehook" @@ -490,7 +500,7 @@ class texthook(basetext): trans = kanjitrans(zhconv.convert(trans, "zh-tw")) self.embedcallback(text, trans, tp) - def embedcallback(self, text: str, trans: str, tp:ThreadParam): + def embedcallback(self, text: str, trans: str, tp: ThreadParam): trans = splitembedlines(trans) self.Luna_embedcallback(tp, text, trans) diff --git a/py/files/lang/ar.json b/py/files/lang/ar.json index 21e9d828..c75f1fc1 100644 --- a/py/files/lang/ar.json +++ b/py/files/lang/ar.json @@ -789,5 +789,8 @@ "延迟": "تأخر", "开始": "بداية .", "最长等待时间": "أقصى وقت الانتظار", - "截取行数": "اعتراض عدد الصفوف" + "截取行数": "اعتراض عدد الصفوف", + "Win32文字绘制函数钩子": "win32 وظيفة رسم النص هوك", + "Win32字符串函数钩子": "win32 سلسلة هوك", + "额外的钩子": "خطاف إضافية" } \ No newline at end of file diff --git a/py/files/lang/cht.json b/py/files/lang/cht.json index 80381438..13ebaf70 100644 --- a/py/files/lang/cht.json +++ b/py/files/lang/cht.json @@ -789,5 +789,8 @@ "延迟": "延遲", "开始": "開始", "最长等待时间": "最長等待時間", - "截取行数": "截取行數" + "截取行数": "截取行數", + "Win32文字绘制函数钩子": "Win32文字繪製函數鉤子", + "Win32字符串函数钩子": "Win32字串函數鉤子", + "额外的钩子": "額外的鉤子" } \ No newline at end of file diff --git a/py/files/lang/cs.json b/py/files/lang/cs.json index 38cff2f5..96aa5654 100644 --- a/py/files/lang/cs.json +++ b/py/files/lang/cs.json @@ -789,5 +789,8 @@ "延迟": "zpoždění", "开始": "start", "最长等待时间": "Maximální čekací doba", - "截取行数": "Snížit počet řádků" + "截取行数": "Snížit počet řádků", + "Win32文字绘制函数钩子": "Win32 funkce kreslení textu", + "Win32字符串函数钩子": "Win32 řetězcový funkční hák", + "额外的钩子": "Extra háčky" } \ No newline at end of file diff --git a/py/files/lang/de.json b/py/files/lang/de.json index b6075c3b..5310f106 100644 --- a/py/files/lang/de.json +++ b/py/files/lang/de.json @@ -789,5 +789,8 @@ "延迟": "Verzögerung", "开始": "Start", "最长等待时间": "Maximale Wartezeit", - "截取行数": "Anzahl der Zeilen abschneiden" + "截取行数": "Anzahl der Zeilen abschneiden", + "Win32文字绘制函数钩子": "Win32 Text Zeichenfunktion Hook", + "Win32字符串函数钩子": "Win32 String Function Hook", + "额外的钩子": "Zusätzliche Haken" } \ No newline at end of file diff --git a/py/files/lang/en.json b/py/files/lang/en.json index 331973ba..a50b6be4 100644 --- a/py/files/lang/en.json +++ b/py/files/lang/en.json @@ -789,5 +789,8 @@ "延迟": "delay", "开始": "start", "最长等待时间": "Maximum waiting time", - "截取行数": "Cut the number of lines" + "截取行数": "Cut the number of lines", + "Win32文字绘制函数钩子": "Win32 text drawing function hook", + "Win32字符串函数钩子": "Win32 string function hook", + "额外的钩子": "Extra hooks" } \ No newline at end of file diff --git a/py/files/lang/es.json b/py/files/lang/es.json index d198c694..fcce6f45 100644 --- a/py/files/lang/es.json +++ b/py/files/lang/es.json @@ -789,5 +789,8 @@ "延迟": "Retraso", "开始": "Empezar", "最长等待时间": "Tiempo máximo de espera", - "截取行数": "Número de líneas interceptadas" + "截取行数": "Número de líneas interceptadas", + "Win32文字绘制函数钩子": "Gancho de función de dibujo de texto Win32", + "Win32字符串函数钩子": "Gancho de función de cadena Win32", + "额外的钩子": "Ganchos adicionales" } \ No newline at end of file diff --git a/py/files/lang/fr.json b/py/files/lang/fr.json index 02e2b95a..ca77975a 100644 --- a/py/files/lang/fr.json +++ b/py/files/lang/fr.json @@ -789,5 +789,8 @@ "延迟": "Retard", "开始": "Commencer", "最长等待时间": "Temps d'attente maximum", - "截取行数": "Nombre de lignes interceptées" + "截取行数": "Nombre de lignes interceptées", + "Win32文字绘制函数钩子": "Win32 crochet de fonction de dessin de texte", + "Win32字符串函数钩子": "Crochet de fonction de chaîne Win32", + "额外的钩子": "Crochets supplémentaires" } \ No newline at end of file diff --git a/py/files/lang/it.json b/py/files/lang/it.json index 1fc1a4e5..b01ea4bc 100644 --- a/py/files/lang/it.json +++ b/py/files/lang/it.json @@ -789,5 +789,8 @@ "延迟": "ritardo", "开始": "inizio", "最长等待时间": "Tempo massimo di attesa", - "截取行数": "Taglia il numero di righe" + "截取行数": "Taglia il numero di righe", + "Win32文字绘制函数钩子": "Gancio della funzione di disegno del testo Win32", + "Win32字符串函数钩子": "Aggancio della funzione stringa Win32", + "额外的钩子": "Ganci supplementari" } \ No newline at end of file diff --git a/py/files/lang/ja.json b/py/files/lang/ja.json index 27cdc713..ef234f7f 100644 --- a/py/files/lang/ja.json +++ b/py/files/lang/ja.json @@ -789,5 +789,8 @@ "延迟": "遅延", "开始": "スタート", "最长等待时间": "最長待ち時間", - "截取行数": "切り取り行数" + "截取行数": "切り取り行数", + "Win32文字绘制函数钩子": "Win 32文字描画関数フック", + "Win32字符串函数钩子": "Win 32文字列関数フック", + "额外的钩子": "エクストラフック" } \ No newline at end of file diff --git a/py/files/lang/ko.json b/py/files/lang/ko.json index d851fb4a..f9562ac2 100644 --- a/py/files/lang/ko.json +++ b/py/files/lang/ko.json @@ -789,5 +789,8 @@ "延迟": "지연", "开始": "시작", "最长等待时间": "최대 대기 시간", - "截取行数": "행 수 캡처" + "截取行数": "행 수 캡처", + "Win32文字绘制函数钩子": "Win32 텍스트 그리기 함수 갈고리", + "Win32字符串函数钩子": "Win32 문자열 함수 후크", + "额外的钩子": "추가 갈고리" } \ No newline at end of file diff --git a/py/files/lang/nl.json b/py/files/lang/nl.json index 1842ee3c..887b7095 100644 --- a/py/files/lang/nl.json +++ b/py/files/lang/nl.json @@ -789,5 +789,8 @@ "延迟": "vertraging", "开始": "start", "最长等待时间": "Maximale wachttijd", - "截取行数": "Aantal regels snijden" + "截取行数": "Aantal regels snijden", + "Win32文字绘制函数钩子": "Win32 teksttekenfunctiehook", + "Win32字符串函数钩子": "Win32 tekenfunctiehook", + "额外的钩子": "Extra haken" } \ No newline at end of file diff --git a/py/files/lang/pl.json b/py/files/lang/pl.json index fec1b63f..18f15b16 100644 --- a/py/files/lang/pl.json +++ b/py/files/lang/pl.json @@ -789,5 +789,8 @@ "延迟": "opóźnienie", "开始": "uruchomić", "最长等待时间": "Maksymalny czas oczekiwania", - "截取行数": "Wyciąć liczbę linii" + "截取行数": "Wyciąć liczbę linii", + "Win32文字绘制函数钩子": "Hook funkcji rysowania tekstu Win32", + "Win32字符串函数钩子": "Hook funkcji ciągów Win32", + "额外的钩子": "Dodatkowe haki" } \ No newline at end of file diff --git a/py/files/lang/pt.json b/py/files/lang/pt.json index 8ba8300b..df1b8730 100644 --- a/py/files/lang/pt.json +++ b/py/files/lang/pt.json @@ -789,5 +789,8 @@ "延迟": "atraso", "开始": "iniciar", "最长等待时间": "Tempo máximo de espera", - "截取行数": "Cortar o número de linhas" + "截取行数": "Cortar o número de linhas", + "Win32文字绘制函数钩子": "Gancho de função de desenho de texto Win32", + "Win32字符串函数钩子": "Gancho de função de cadeia Win32", + "额外的钩子": "Ganchos extra" } \ No newline at end of file diff --git a/py/files/lang/ru.json b/py/files/lang/ru.json index 75ccea9a..8802bce8 100644 --- a/py/files/lang/ru.json +++ b/py/files/lang/ru.json @@ -789,5 +789,8 @@ "延迟": "Задержка", "开始": "Начинаем.", "最长等待时间": "Максимальное время ожидания", - "截取行数": "Количество перехваченных строк" + "截取行数": "Количество перехваченных строк", + "Win32文字绘制函数钩子": "Win32 Графический крюк", + "Win32字符串函数钩子": "Win32 Строчный крюк", + "额外的钩子": "Дополнительный крюк" } \ No newline at end of file diff --git a/py/files/lang/sv.json b/py/files/lang/sv.json index 498b020e..7582b859 100644 --- a/py/files/lang/sv.json +++ b/py/files/lang/sv.json @@ -789,5 +789,8 @@ "延迟": "fördröjning", "开始": "start", "最长等待时间": "Maximal väntetid", - "截取行数": "Klipp av antalet rader" + "截取行数": "Klipp av antalet rader", + "Win32文字绘制函数钩子": "Win32 textritfunktionskrok", + "Win32字符串函数钩子": "Win32 strängfunktionskrok", + "额外的钩子": "Extra krokar" } \ No newline at end of file diff --git a/py/files/lang/th.json b/py/files/lang/th.json index 47a2c366..063f6cb0 100644 --- a/py/files/lang/th.json +++ b/py/files/lang/th.json @@ -789,5 +789,8 @@ "延迟": "ความล่าช้า", "开始": "เริ่มต้นใช้งาน", "最长等待时间": "ระยะเวลารอคอยนานที่สุด", - "截取行数": "จำนวนแถวที่ถูกสกัดกั้น" + "截取行数": "จำนวนแถวที่ถูกสกัดกั้น", + "Win32文字绘制函数钩子": "Win32 วาดคำฟังก์ชันตะขอ", + "Win32字符串函数钩子": "Win32 ฟังก์ชั่นสตริงตะขอ", + "额外的钩子": "ตะขอเพิ่มเติม" } \ No newline at end of file diff --git a/py/files/lang/tr.json b/py/files/lang/tr.json index b367df13..c336e6a0 100644 --- a/py/files/lang/tr.json +++ b/py/files/lang/tr.json @@ -789,5 +789,8 @@ "延迟": "gecikme", "开始": "başlat", "最长等待时间": "Maksimum bekleme zamanı", - "截取行数": "Çizgi sayısını kesin" + "截取行数": "Çizgi sayısını kesin", + "Win32文字绘制函数钩子": "Win32 metin çizim fonksiyonu çubuğu", + "Win32字符串函数钩子": "Win32 string fonksiyonu", + "额外的钩子": "Ekstra hücreler" } \ No newline at end of file diff --git a/py/files/lang/uk.json b/py/files/lang/uk.json index f3536707..2c8cfcb0 100644 --- a/py/files/lang/uk.json +++ b/py/files/lang/uk.json @@ -789,5 +789,8 @@ "延迟": "затримка", "开始": "початок", "最长等待时间": "Максимальний час чекання", - "截取行数": "Вирізати кількість рядків" + "截取行数": "Вирізати кількість рядків", + "Win32文字绘制函数钩子": "Хук функції малювання тексту Win32", + "Win32字符串函数钩子": "Хук функції рядка Win32", + "额外的钩子": "Додаткові хаки" } \ No newline at end of file diff --git a/py/files/lang/vi.json b/py/files/lang/vi.json index 2715230a..b1cccb85 100644 --- a/py/files/lang/vi.json +++ b/py/files/lang/vi.json @@ -789,5 +789,8 @@ "延迟": "Trì hoãn", "开始": "Bắt đầu", "最长等待时间": "Thời gian chờ tối đa", - "截取行数": "Số dòng bị chặn" + "截取行数": "Số dòng bị chặn", + "Win32文字绘制函数钩子": "Win32 Chức năng vẽ văn bản Hook", + "Win32字符串函数钩子": "Win32 Chuỗi chức năng Hook", + "额外的钩子": "Thêm móc" } \ No newline at end of file diff --git a/py/files/lang/zh.json b/py/files/lang/zh.json index cfaf0517..a09518fa 100644 --- a/py/files/lang/zh.json +++ b/py/files/lang/zh.json @@ -789,5 +789,8 @@ "核心设置": "", "开始": "", "截取行数": "", - "最长等待时间": "" + "最长等待时间": "", + "Win32文字绘制函数钩子": "", + "Win32字符串函数钩子": "", + "额外的钩子": "" } \ No newline at end of file