mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-11-23 22:05:36 +08:00
635 lines
21 KiB
C++
635 lines
21 KiB
C++
|
// hijackfuns.cc
|
||
|
// 6/3/2015 jichi
|
||
|
#include "hijackfuns.h"
|
||
|
#include"embed_util.h"
|
||
|
//#define DEBUG "hijackfuns"
|
||
|
#include"dyncodec/dynsjis.h"
|
||
|
//#include "sakurakit/skdebug.h"
|
||
|
#pragma intrinsic(_ReturnAddress)
|
||
|
|
||
|
// Disable only for debugging purpose
|
||
|
//#define HIJACK_GDI_FONT
|
||
|
//#define HIJACK_GDI_TEXT
|
||
|
|
||
|
#define DEF_FUN(_f) Hijack::_f##_fun_t Hijack::old##_f = ::_f;
|
||
|
DEF_FUN(CreateFontA)
|
||
|
DEF_FUN(CreateFontW)
|
||
|
DEF_FUN(CreateFontIndirectA)
|
||
|
DEF_FUN(CreateFontIndirectW)
|
||
|
DEF_FUN(GetGlyphOutlineA)
|
||
|
DEF_FUN(GetGlyphOutlineW)
|
||
|
DEF_FUN(GetTextExtentPoint32A)
|
||
|
DEF_FUN(GetTextExtentPoint32W)
|
||
|
DEF_FUN(GetTextExtentExPointA)
|
||
|
DEF_FUN(GetTextExtentExPointW)
|
||
|
DEF_FUN(GetCharABCWidthsA)
|
||
|
DEF_FUN(GetCharABCWidthsW)
|
||
|
DEF_FUN(TextOutA)
|
||
|
DEF_FUN(TextOutW)
|
||
|
DEF_FUN(ExtTextOutA)
|
||
|
DEF_FUN(ExtTextOutW)
|
||
|
DEF_FUN(DrawTextA)
|
||
|
DEF_FUN(DrawTextW)
|
||
|
DEF_FUN(DrawTextExA)
|
||
|
DEF_FUN(DrawTextExW)
|
||
|
DEF_FUN(CharNextA)
|
||
|
//DEF_FUN(CharNextW)
|
||
|
//DEF_FUN(CharNextExA)
|
||
|
//DEF_FUN(CharNextExW)
|
||
|
DEF_FUN(CharPrevA)
|
||
|
//DEF_FUN(CharPrevW)
|
||
|
DEF_FUN(MultiByteToWideChar)
|
||
|
DEF_FUN(WideCharToMultiByte)
|
||
|
#undef DEF_FUN
|
||
|
|
||
|
/** Helper */
|
||
|
|
||
|
namespace { // unnamed
|
||
|
UINT8 systemCharSet(){
|
||
|
enum CodePage {
|
||
|
NullCodePage = 0
|
||
|
, Utf8CodePage = 65001 // UTF-8
|
||
|
, Utf16CodePage = 1200 // UTF-16
|
||
|
, SjisCodePage = 932 // SHIFT-JIS
|
||
|
, GbkCodePage = 936 // GB2312
|
||
|
, KscCodePage = 949 // EUC-KR
|
||
|
, Big5CodePage = 950 // BIG5
|
||
|
, TisCodePage = 874 // TIS-620
|
||
|
, Koi8CodePage = 866 // KOI8-R
|
||
|
};
|
||
|
auto systemCodePage = ::GetACP();
|
||
|
switch (systemCodePage) {
|
||
|
case TisCodePage: return THAI_CHARSET;
|
||
|
case Koi8CodePage: return RUSSIAN_CHARSET;
|
||
|
case SjisCodePage: return SHIFTJIS_CHARSET;
|
||
|
case GbkCodePage: return GB2312_CHARSET;
|
||
|
case Big5CodePage: return CHINESEBIG5_CHARSET;
|
||
|
|
||
|
case KscCodePage: return HANGUL_CHARSET;
|
||
|
case 1361: return JOHAB_CHARSET; // alternative Korean character set
|
||
|
|
||
|
case 1250: return EASTEUROPE_CHARSET;
|
||
|
case 1251: return RUSSIAN_CHARSET; // cyrillic
|
||
|
case 1253: return GREEK_CHARSET;
|
||
|
case 1254: return TURKISH_CHARSET;
|
||
|
|
||
|
case 862: return HEBREW_CHARSET; // obsolete
|
||
|
case 1255: return HEBREW_CHARSET;
|
||
|
|
||
|
case 1256: return ARABIC_CHARSET;
|
||
|
case 1257: return BALTIC_CHARSET;
|
||
|
case 1258: return VIETNAMESE_CHARSET;
|
||
|
|
||
|
//default: return DEFAULT_CHARSET;
|
||
|
default: return 0;
|
||
|
}
|
||
|
}
|
||
|
void customizeLogFontA(LOGFONTA *lplf)
|
||
|
{
|
||
|
|
||
|
if (embedsharedmem->fontCharSetEnabled) {
|
||
|
auto charSet = embedsharedmem->fontCharSet;
|
||
|
if (!charSet)
|
||
|
charSet = systemCharSet();
|
||
|
if (charSet)
|
||
|
lplf->lfCharSet = charSet;
|
||
|
}
|
||
|
/*
|
||
|
if (s->fontWeight)
|
||
|
lplf->lfWeight = s->fontWeight;
|
||
|
if (s->isFontScaled()) {
|
||
|
lplf->lfWidth *= s->fontScale;
|
||
|
lplf->lfHeight *= s->fontScale;
|
||
|
}
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
void customizeLogFontW(LOGFONTW *lplf)
|
||
|
{
|
||
|
customizeLogFontA((LOGFONTA *)lplf);
|
||
|
|
||
|
std::wstring s=embedsharedmem->fontFamily;
|
||
|
if (! s.empty()) {
|
||
|
lplf->lfFaceName[s.size()] = 0;
|
||
|
//s->fontFamily.toWCharArray(lplf->lfFaceName);
|
||
|
memcpy(lplf->lfFaceName, s.c_str(), s.size());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// LogFont manager
|
||
|
|
||
|
class LogFontManager
|
||
|
{
|
||
|
typedef std::pair<HFONT, LOGFONTW> font_pair;
|
||
|
std::list<font_pair> fonts_;
|
||
|
|
||
|
static bool eq(const LOGFONTW &x, const LOGFONTW&y);
|
||
|
|
||
|
public:
|
||
|
HFONT get(const LOGFONTW &lf) const;
|
||
|
void add(HFONT hf, const LOGFONTW &lf);
|
||
|
void remove(HFONT hf);
|
||
|
void remove(const LOGFONTW &lf);
|
||
|
};
|
||
|
|
||
|
bool LogFontManager::eq(const LOGFONTW &x, const LOGFONTW &y)
|
||
|
{ // I assume there is no padding
|
||
|
return ::wcscmp(x.lfFaceName, y.lfFaceName) == 0
|
||
|
&& ::memcmp(&x, &y, sizeof(x) - sizeof(x.lfFaceName)) == 0;
|
||
|
}
|
||
|
|
||
|
void LogFontManager::add(HFONT hf, const LOGFONTW &lf)
|
||
|
{ fonts_.push_back(std::make_pair(hf, lf)); }
|
||
|
|
||
|
void LogFontManager::remove(HFONT hf)
|
||
|
{
|
||
|
auto _=std::remove_if(fonts_.begin(), fonts_.end(), [&hf](const font_pair &it) {
|
||
|
return it.first == hf;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
void LogFontManager::remove(const LOGFONTW &lf)
|
||
|
{
|
||
|
auto _=std::remove_if(fonts_.begin(), fonts_.end(), [&lf](const font_pair &it) {
|
||
|
return eq(it.second, lf);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
HFONT LogFontManager::get(const LOGFONTW &lf) const
|
||
|
{
|
||
|
for each (const font_pair &it in fonts_)
|
||
|
if (eq(it.second, lf))
|
||
|
return it.first;
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
// GDI font switcher
|
||
|
|
||
|
class DCFontSwitcher
|
||
|
{
|
||
|
static LogFontManager fonts_;
|
||
|
|
||
|
HDC hdc_;
|
||
|
HFONT oldFont_,
|
||
|
newFont_;
|
||
|
std::wstring newfontname;
|
||
|
public:
|
||
|
explicit DCFontSwitcher(HDC hdc); // pass 0 to disable this class
|
||
|
~DCFontSwitcher();
|
||
|
};
|
||
|
|
||
|
LogFontManager DCFontSwitcher::fonts_;
|
||
|
|
||
|
DCFontSwitcher::~DCFontSwitcher()
|
||
|
{
|
||
|
// No idea why selecting old font will crash Mogeko Castle
|
||
|
//if (oldFont_ && oldFont_ != HGDI_ERROR)
|
||
|
// ::SelectObject(hdc_, oldFont_);
|
||
|
|
||
|
// Never delete new font but cache them
|
||
|
// This could result in bad font after game is reset and deleted my font
|
||
|
//if (newFont_)
|
||
|
// ::DeleteObject(newFont_);
|
||
|
}
|
||
|
bool isFontCustomized(){
|
||
|
return embedsharedmem->fontCharSetEnabled||wcslen(embedsharedmem->fontFamily);
|
||
|
}
|
||
|
DCFontSwitcher::DCFontSwitcher(HDC hdc)
|
||
|
: hdc_(hdc), oldFont_(nullptr), newFont_(nullptr),newfontname(L"")
|
||
|
{
|
||
|
if (!hdc_)
|
||
|
return;
|
||
|
/*
|
||
|
auto p = HijackHelper::instance();
|
||
|
if (!p)
|
||
|
return;
|
||
|
auto s = p->settings();
|
||
|
if (!s->deviceContextFontEnabled || !s->isFontCustomized())
|
||
|
return;
|
||
|
*/
|
||
|
TEXTMETRICW tm;
|
||
|
if (!::GetTextMetricsW(hdc, &tm))
|
||
|
return;
|
||
|
|
||
|
LOGFONTW lf = {};
|
||
|
lf.lfHeight = tm.tmHeight;
|
||
|
lf.lfWeight = tm.tmWeight;
|
||
|
lf.lfItalic = tm.tmItalic;
|
||
|
lf.lfUnderline = tm.tmUnderlined;
|
||
|
lf.lfStrikeOut = tm.tmStruckOut;
|
||
|
lf.lfCharSet = tm.tmCharSet;
|
||
|
lf.lfPitchAndFamily = tm.tmPitchAndFamily;
|
||
|
|
||
|
customizeLogFontW(&lf);
|
||
|
|
||
|
if (std::wstring(embedsharedmem->fontFamily).empty())
|
||
|
::GetTextFaceW(hdc_, LF_FACESIZE, lf.lfFaceName);
|
||
|
else{
|
||
|
wcscpy(lf.lfFaceName,embedsharedmem->fontFamily);
|
||
|
}
|
||
|
newFont_ = fonts_.get(lf);
|
||
|
if ((!newFont_ )||(newfontname!=std::wstring(embedsharedmem->fontFamily))) {
|
||
|
newFont_ = Hijack::oldCreateFontIndirectW(&lf);
|
||
|
fonts_.add(newFont_, lf);
|
||
|
newfontname=std::wstring(embedsharedmem->fontFamily);
|
||
|
}
|
||
|
oldFont_ = (HFONT)SelectObject(hdc_, newFont_);
|
||
|
|
||
|
}
|
||
|
|
||
|
} // unnamed namespace
|
||
|
|
||
|
/** Fonts */
|
||
|
|
||
|
// http://forums.codeguru.com/showthread.php?500522-Need-clarification-about-CreateFontIndirect
|
||
|
// The font creation functions will never fail
|
||
|
HFONT WINAPI Hijack::newCreateFontIndirectA(const LOGFONTA *lplf)
|
||
|
{
|
||
|
|
||
|
//DOUT("width:" << lplf->lfWidth << ", height:" << lplf->lfHeight << ", weight:" << lplf->lfWeight);
|
||
|
// if (auto p = HijackHelper::instance()) {
|
||
|
// auto s = p->settings();
|
||
|
std::wstring fontFamily=embedsharedmem->fontFamily;
|
||
|
if (lplf && isFontCustomized()) {
|
||
|
union {
|
||
|
LOGFONTA a;
|
||
|
LOGFONTW w;
|
||
|
} lf = {*lplf}; // only initialize the first member of LOGFONTA
|
||
|
customizeLogFontA(&lf.a);
|
||
|
if (!fontFamily.empty()) {
|
||
|
if (all_ascii(fontFamily.c_str(),fontFamily.size()))
|
||
|
::strcpy(lf.a.lfFaceName, WideStringToString(fontFamily,CP_ACP).c_str());
|
||
|
else {
|
||
|
lf.w.lfFaceName[fontFamily.size()] = 0;
|
||
|
//s->fontFamily.toWCharArray(lf.w.lfFaceName);
|
||
|
memcpy(lf.w.lfFaceName, fontFamily.c_str(), fontFamily.size());
|
||
|
return oldCreateFontIndirectW(&lf.w);
|
||
|
}
|
||
|
}
|
||
|
return oldCreateFontIndirectA(&lf.a);
|
||
|
}
|
||
|
//}
|
||
|
return oldCreateFontIndirectA(lplf);
|
||
|
}
|
||
|
|
||
|
HFONT WINAPI Hijack::newCreateFontIndirectW(const LOGFONTW *lplf)
|
||
|
{
|
||
|
|
||
|
//DOUT("width:" << lplf->lfWidth << ", height:" << lplf->lfHeight << ", weight:" << lplf->lfWeight);
|
||
|
// if (auto p = HijackHelper::instance()) {
|
||
|
// auto s = p->settings();
|
||
|
if (lplf && isFontCustomized()) {
|
||
|
LOGFONTW lf(*lplf);
|
||
|
customizeLogFontW(&lf);
|
||
|
return oldCreateFontIndirectW(&lf);
|
||
|
}
|
||
|
// }
|
||
|
return oldCreateFontIndirectW(lplf);
|
||
|
}
|
||
|
|
||
|
#define CREATE_FONT_ARGS nHeight, nWidth, nEscapement, nOrientation, fnWeight, fdwItalic, fdwUnderline, fdwStrikeOut, fdwCharSet, fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily, lpszFace
|
||
|
HFONT WINAPI Hijack::newCreateFontA(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD fdwItalic, DWORD fdwUnderline, DWORD fdwStrikeOut, DWORD fdwCharSet, DWORD fdwOutputPrecision, DWORD fdwClipPrecision, DWORD fdwQuality, DWORD fdwPitchAndFamily, LPCSTR lpszFace)
|
||
|
{
|
||
|
|
||
|
|
||
|
|
||
|
if ( isFontCustomized()) {
|
||
|
if (embedsharedmem->fontCharSetEnabled) {
|
||
|
auto charSet = embedsharedmem->fontCharSet;
|
||
|
if (!charSet)
|
||
|
charSet = systemCharSet();
|
||
|
if (charSet)
|
||
|
fdwCharSet = charSet;
|
||
|
}
|
||
|
/*
|
||
|
if (s->fontWeight)
|
||
|
fnWeight = s->fontWeight;
|
||
|
if (s->isFontScaled()) {
|
||
|
nWidth *= s->fontScale;
|
||
|
nHeight *= s->fontScale;
|
||
|
}
|
||
|
*/
|
||
|
std::wstring fontFamily=embedsharedmem->fontFamily;
|
||
|
if (!fontFamily.empty()) {
|
||
|
if (all_ascii(fontFamily.c_str(),fontFamily.size())) {
|
||
|
lpszFace =WideStringToString(fontFamily,CP_ACP).c_str();
|
||
|
return oldCreateFontA(CREATE_FONT_ARGS);
|
||
|
} else {
|
||
|
auto lpszFace = (LPCWSTR)fontFamily.c_str();
|
||
|
return oldCreateFontW(CREATE_FONT_ARGS);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return oldCreateFontA(CREATE_FONT_ARGS);
|
||
|
}
|
||
|
|
||
|
HFONT WINAPI Hijack::newCreateFontW(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD fdwItalic, DWORD fdwUnderline, DWORD fdwStrikeOut, DWORD fdwCharSet, DWORD fdwOutputPrecision, DWORD fdwClipPrecision, DWORD fdwQuality, DWORD fdwPitchAndFamily, LPCWSTR lpszFace)
|
||
|
{
|
||
|
|
||
|
|
||
|
if (isFontCustomized()) {
|
||
|
if (embedsharedmem->fontCharSetEnabled) {
|
||
|
auto charSet = embedsharedmem->fontCharSet;
|
||
|
if (!charSet)
|
||
|
charSet = systemCharSet();
|
||
|
if (charSet)
|
||
|
fdwCharSet = charSet;
|
||
|
}
|
||
|
/*
|
||
|
if (s->fontWeight)
|
||
|
fnWeight = s->fontWeight;
|
||
|
if (s->isFontScaled()) {
|
||
|
nWidth *= s->fontScale;
|
||
|
nHeight *= s->fontScale;
|
||
|
}*/
|
||
|
if (!std::wstring(embedsharedmem->fontFamily).empty())
|
||
|
lpszFace = (LPCWSTR)embedsharedmem;
|
||
|
}
|
||
|
return oldCreateFontW(CREATE_FONT_ARGS);
|
||
|
}
|
||
|
#undef CREATE_FONT_ARGS
|
||
|
|
||
|
/** Encoding */
|
||
|
|
||
|
LPSTR WINAPI Hijack::newCharNextA(LPCSTR lpString)
|
||
|
{
|
||
|
|
||
|
//if (::GetACP() == 932)
|
||
|
return const_cast<char *>(dynsjis::nextchar(lpString));
|
||
|
//return oldCharNextA(lpString);
|
||
|
}
|
||
|
|
||
|
LPSTR WINAPI Hijack::newCharPrevA(LPCSTR lpStart, LPCSTR lpCurrent)
|
||
|
{
|
||
|
|
||
|
//if (::GetACP() == 932)
|
||
|
return const_cast<char *>(dynsjis::prevchar(lpCurrent, lpStart));
|
||
|
//return oldCharNextA(lpStart, lpCurrent);
|
||
|
}
|
||
|
extern DynamicShiftJISCodec *dynamiccodec ;
|
||
|
int WINAPI Hijack::newMultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar)
|
||
|
{
|
||
|
//
|
||
|
/* if (auto p = HijackHelper::instance())
|
||
|
if (p->settings()->localeEmulationEnabled)
|
||
|
if (CodePage == CP_THREAD_ACP || CodePage == CP_OEMCP)
|
||
|
CodePage = CP_ACP;
|
||
|
*/
|
||
|
if (CodePage == CP_THREAD_ACP || CodePage == CP_OEMCP)
|
||
|
CodePage = CP_ACP;
|
||
|
// CP_ACP(0), CP_MACCP(1), CP_OEMCP(2), CP_THREAD_ACP(3)
|
||
|
if ((CodePage <= 3 || CodePage == 932) && cchWideChar > 0 && cbMultiByte > 1) {
|
||
|
bool dynamic;
|
||
|
std::string data(lpMultiByteStr, cbMultiByte);
|
||
|
auto text = dynamiccodec->decode(data, &dynamic);
|
||
|
if (dynamic && !text.empty()) {
|
||
|
int size = min(text.size() + 1, cchWideChar);
|
||
|
::memcpy(lpWideCharStr, text.c_str(), size * 2);
|
||
|
//lpWideCharStr[size - 1] = 0; // enforce trailing zero
|
||
|
return size - 1;
|
||
|
}
|
||
|
}
|
||
|
return oldMultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, lpWideCharStr, cchWideChar);
|
||
|
}
|
||
|
|
||
|
int WINAPI Hijack::newWideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar)
|
||
|
{
|
||
|
//
|
||
|
if (CodePage == CP_THREAD_ACP || CodePage == CP_OEMCP)
|
||
|
CodePage = CP_ACP;
|
||
|
|
||
|
if ((CodePage <= 3 || CodePage == 932) && cchWideChar > 0 && cbMultiByte >= 0) {
|
||
|
bool dynamic;
|
||
|
auto text = std::wstring(lpWideCharStr, cchWideChar);
|
||
|
auto data = dynamiccodec->encodeSTD(text, &dynamic);
|
||
|
if (dynamic && !data.empty()) {
|
||
|
|
||
|
int size = data.size() + 1;
|
||
|
if (cbMultiByte && cbMultiByte < size)
|
||
|
size = cbMultiByte;
|
||
|
::memcpy(lpMultiByteStr, data.c_str(), size);
|
||
|
//lpMultiByteStr[size - 1] = 0; // enforce trailing zero
|
||
|
return size - 1;
|
||
|
}
|
||
|
}
|
||
|
return oldWideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, lpMultiByteStr, cbMultiByte, lpDefaultChar, lpUsedDefaultChar);
|
||
|
}
|
||
|
|
||
|
/** Text */
|
||
|
UINT decodeChar(UINT ch, bool *dynamic)
|
||
|
{
|
||
|
if (dynamic)
|
||
|
*dynamic = false;
|
||
|
if (ch > 0xff) {
|
||
|
bool t;
|
||
|
char data[3] = {(BYTE)(ch>>8)&0xff, (BYTE)ch&0xff, 0};
|
||
|
auto text = dynamiccodec->decode(data, &t);
|
||
|
if (t && text.size() == 1) {
|
||
|
if (dynamic)
|
||
|
*dynamic= true;
|
||
|
return text[0] ;
|
||
|
}
|
||
|
}
|
||
|
return ch;
|
||
|
}
|
||
|
#define DECODE_CHAR(uChar, ...) \
|
||
|
{ \
|
||
|
if (uChar > 0xff) \
|
||
|
if (1) { \
|
||
|
bool dynamic; \
|
||
|
UINT ch = decodeChar(uChar, &dynamic); \
|
||
|
if (dynamic && ch) { \
|
||
|
uChar = ch; \
|
||
|
return (__VA_ARGS__); \
|
||
|
} \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
#define DECODE_TEXT(lpString, cchString, ...) \
|
||
|
{ \
|
||
|
if(cchString == -1 || cchString > 1) \
|
||
|
if (1) { \
|
||
|
bool dynamic; \
|
||
|
auto data = std::string(lpString, cchString == -1 ? ::strlen(lpString) : cchString); \
|
||
|
if (data.size() > 1) { \
|
||
|
auto text = dynamiccodec->decode(data, &dynamic); \
|
||
|
if (dynamic && !text.empty()) { \
|
||
|
LPCWSTR lpString = (LPCWSTR)text.c_str(); \
|
||
|
cchString = text.size(); \
|
||
|
return (__VA_ARGS__); \
|
||
|
} \
|
||
|
} \
|
||
|
} \
|
||
|
}
|
||
|
#include<intrin.h>
|
||
|
#define TRANSLATE_TEXT_A(lpString, cchString, ...) \
|
||
|
{ \
|
||
|
if (auto q = EngineController::instance()) { \
|
||
|
auto data = std::string(lpString, cchString == -1 ? ::strlen(lpString) : cchString); \
|
||
|
std::wstring oldText = q->decode(data); \
|
||
|
if (!oldText.empty()) { \
|
||
|
enum { role = Engine::OtherRole }; \
|
||
|
ULONG split = (ULONG)_ReturnAddress(); \
|
||
|
auto sig = Engine::hashThreadSignature(role, split); \
|
||
|
auto newText = q->dispatchTextWSTD(oldText, role, sig); \
|
||
|
if (newText != oldText) { \
|
||
|
LPCWSTR lpString = (LPCWSTR)newText.c_str(); \
|
||
|
cchString = newText.size(); \
|
||
|
return (__VA_ARGS__); \
|
||
|
} \
|
||
|
} \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
#define TRANSLATE_TEXT_W(lpString, cchString, ...) \
|
||
|
{ \
|
||
|
if (auto q = EngineController::instance()) { \
|
||
|
auto text = std::wstring(lpString, cchString); \
|
||
|
if (!text.empty()) { \
|
||
|
enum { role = Engine::OtherRole }; \
|
||
|
ULONG split = (ULONG)_ReturnAddress(); \
|
||
|
auto sig = Engine::hashThreadSignature(role, split); \
|
||
|
text = q->dispatchTextWSTD(text, role, sig); \
|
||
|
LPCWSTR lpString = (LPCWSTR)text.c_str(); \
|
||
|
cchString = text.size(); \
|
||
|
return (__VA_ARGS__); \
|
||
|
} \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
DWORD WINAPI Hijack::newGetGlyphOutlineA(HDC hdc, UINT uChar, UINT uFormat, LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPVOID lpvBuffer, const MAT2 *lpmat2)
|
||
|
{
|
||
|
DCFontSwitcher fs(hdc);
|
||
|
|
||
|
DECODE_CHAR(uChar, oldGetGlyphOutlineW(hdc, ch, uFormat, lpgm, cbBuffer, lpvBuffer, lpmat2))
|
||
|
return oldGetGlyphOutlineA(hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, lpmat2);
|
||
|
}
|
||
|
|
||
|
DWORD WINAPI Hijack::newGetGlyphOutlineW(HDC hdc, UINT uChar, UINT uFormat, LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPVOID lpvBuffer, const MAT2 *lpmat2)
|
||
|
{
|
||
|
|
||
|
DCFontSwitcher fs(hdc);
|
||
|
return oldGetGlyphOutlineW(hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, lpmat2);
|
||
|
}
|
||
|
|
||
|
BOOL WINAPI Hijack::newGetTextExtentPoint32A(HDC hdc, LPCSTR lpString, int cchString, LPSIZE lpSize)
|
||
|
{
|
||
|
|
||
|
|
||
|
DCFontSwitcher fs(hdc);
|
||
|
//TRANSLATE_TEXT_A(lpString, cchString, oldGetTextExtentPoint32W(hdc, lpString, cchString, lpSize))
|
||
|
DECODE_TEXT(lpString, cchString, oldGetTextExtentPoint32W(hdc, lpString, cchString, lpSize))
|
||
|
return oldGetTextExtentPoint32A(hdc, lpString, cchString, lpSize);
|
||
|
}
|
||
|
|
||
|
BOOL WINAPI Hijack::newGetTextExtentPoint32W(HDC hdc, LPCWSTR lpString, int cchString, LPSIZE lpSize)
|
||
|
{
|
||
|
|
||
|
DCFontSwitcher fs(hdc);
|
||
|
//TRANSLATE_TEXT_W(lpString, cchString, oldGetTextExtentPoint32W(hdc, lpString, cchString, lpSize))
|
||
|
return oldGetTextExtentPoint32W(hdc, lpString, cchString, lpSize);
|
||
|
}
|
||
|
|
||
|
BOOL WINAPI Hijack::newGetTextExtentExPointA(HDC hdc, LPCSTR lpString, int cchString, int nMaxExtent, LPINT lpnFit, LPINT alpDx, LPSIZE lpSize)
|
||
|
{
|
||
|
|
||
|
// DCFontSwitcher fs(hdc);
|
||
|
//TRANSLATE_TEXT_A(lpString, cchString, oldGetTextExtentExPointW(hdc, lpString, cchString, nMaxExtent, lpnFit, alpDx, lpSize))
|
||
|
DECODE_TEXT(lpString, cchString, oldGetTextExtentExPointW(hdc, lpString, cchString, nMaxExtent, lpnFit, alpDx, lpSize))
|
||
|
return oldGetTextExtentExPointA(hdc, lpString, cchString, nMaxExtent, lpnFit, alpDx, lpSize);
|
||
|
}
|
||
|
|
||
|
BOOL WINAPI Hijack::newGetTextExtentExPointW(HDC hdc, LPCWSTR lpString, int cchString, int nMaxExtent, LPINT lpnFit, LPINT alpDx, LPSIZE lpSize)
|
||
|
{
|
||
|
|
||
|
DCFontSwitcher fs(hdc);
|
||
|
//TRANSLATE_TEXT_W(lpString, cchString, oldGetTextExtentExPointW(hdc, lpString, cchString, nMaxExtent, lpnFit, alpDx, lpSize))
|
||
|
return oldGetTextExtentExPointW(hdc, lpString, cchString, nMaxExtent, lpnFit, alpDx, lpSize);
|
||
|
}
|
||
|
|
||
|
int WINAPI Hijack::newDrawTextA(HDC hdc, LPCSTR lpString, int cchString, LPRECT lpRect, UINT uFormat)
|
||
|
{
|
||
|
|
||
|
DCFontSwitcher fs(hdc);
|
||
|
// if (HijackManager::instance()->isFunctionTranslated((uintptr_t)::DrawTextA))
|
||
|
// TRANSLATE_TEXT_A(lpString, cchString, oldDrawTextW(hdc, lpString, cchString, lpRect, uFormat))
|
||
|
// else
|
||
|
DECODE_TEXT(lpString, cchString, oldDrawTextW(hdc, lpString, cchString, lpRect, uFormat))
|
||
|
return oldDrawTextA(hdc, lpString, cchString, lpRect, uFormat);
|
||
|
}
|
||
|
|
||
|
int WINAPI Hijack::newDrawTextW(HDC hdc, LPCWSTR lpString, int cchString, LPRECT lpRect, UINT uFormat)
|
||
|
{
|
||
|
|
||
|
DCFontSwitcher fs(hdc);
|
||
|
// if (HijackManager::instance()->isFunctionTranslated((ULONG)::DrawTextW))
|
||
|
// TRANSLATE_TEXT_W(lpString, cchString, oldDrawTextW(hdc, lpString, cchString, lpRect, uFormat))
|
||
|
return oldDrawTextW(hdc, lpString, cchString, lpRect, uFormat);
|
||
|
}
|
||
|
|
||
|
int WINAPI Hijack::newDrawTextExA(HDC hdc, LPSTR lpString, int cchString, LPRECT lpRect, UINT dwDTFormat, LPDRAWTEXTPARAMS lpDTParams)
|
||
|
{
|
||
|
|
||
|
DCFontSwitcher fs(hdc);
|
||
|
if (!(dwDTFormat & DT_MODIFYSTRING)) {
|
||
|
// if (HijackManager::instance()->isFunctionTranslated((uintptr_t)::DrawTextExA))
|
||
|
// TRANSLATE_TEXT_A(lpString, cchString, oldDrawTextExW(hdc, const_cast<LPWSTR>(lpString), cchString, lpRect, dwDTFormat, lpDTParams))
|
||
|
// else
|
||
|
DECODE_TEXT(lpString, cchString, oldDrawTextExW(hdc, const_cast<LPWSTR>(lpString), cchString, lpRect, dwDTFormat, lpDTParams))
|
||
|
}
|
||
|
return oldDrawTextExA(hdc, lpString, cchString, lpRect, dwDTFormat, lpDTParams);
|
||
|
}
|
||
|
|
||
|
int WINAPI Hijack::newDrawTextExW(HDC hdc, LPWSTR lpString, int cchString, LPRECT lpRect, UINT dwDTFormat, LPDRAWTEXTPARAMS lpDTParams)
|
||
|
{
|
||
|
|
||
|
DCFontSwitcher fs(hdc);
|
||
|
// if (!(dwDTFormat & DT_MODIFYSTRING) && HijackManager::instance()->isFunctionTranslated((ULONG)::DrawTextExW))
|
||
|
// TRANSLATE_TEXT_W(lpString, cchString, oldDrawTextExW(hdc, const_cast<LPWSTR>(lpString), cchString, lpRect, dwDTFormat, lpDTParams))
|
||
|
return oldDrawTextExW(hdc, lpString, cchString, lpRect, dwDTFormat, lpDTParams);
|
||
|
}
|
||
|
|
||
|
BOOL WINAPI Hijack::newTextOutA(HDC hdc, int nXStart, int nYStart, LPCSTR lpString, int cchString)
|
||
|
{
|
||
|
|
||
|
DCFontSwitcher fs(hdc);
|
||
|
// if (HijackManager::instance()->isFunctionTranslated((uintptr_t)::TextOutA))
|
||
|
// TRANSLATE_TEXT_A(lpString, cchString, oldTextOutW(hdc, nXStart, nYStart, lpString, cchString))
|
||
|
// else
|
||
|
DECODE_TEXT(lpString, cchString, oldTextOutW(hdc, nXStart, nYStart, lpString, cchString))
|
||
|
return oldTextOutA(hdc, nXStart, nYStart, lpString, cchString);
|
||
|
}
|
||
|
|
||
|
BOOL WINAPI Hijack::newTextOutW(HDC hdc, int nXStart, int nYStart, LPCWSTR lpString, int cchString)
|
||
|
{
|
||
|
|
||
|
DCFontSwitcher fs(hdc);
|
||
|
// if (HijackManager::instance()->isFunctionTranslated((ULONG)::TextOutW))
|
||
|
// TRANSLATE_TEXT_W(lpString, cchString, oldTextOutW(hdc, nXStart, nYStart, lpString, cchString))
|
||
|
return oldTextOutW(hdc, nXStart, nYStart, lpString, cchString);
|
||
|
}
|
||
|
|
||
|
BOOL WINAPI Hijack::newExtTextOutA(HDC hdc, int X, int Y, UINT fuOptions, const RECT *lprc, LPCSTR lpString, UINT cchString, const INT *lpDx)
|
||
|
{
|
||
|
|
||
|
DCFontSwitcher fs(hdc);
|
||
|
// if (HijackManager::instance()->isFunctionTranslated((uintptr_t)::ExtTextOutA))
|
||
|
// TRANSLATE_TEXT_A(lpString, cchString, oldExtTextOutW(hdc, X, Y, fuOptions, lprc, lpString, cchString, lpDx))
|
||
|
// else
|
||
|
DECODE_TEXT(lpString, cchString, oldExtTextOutW(hdc, X, Y, fuOptions, lprc, lpString, cchString, lpDx))
|
||
|
return oldExtTextOutA(hdc, X, Y, fuOptions, lprc, lpString, cchString, lpDx);
|
||
|
}
|
||
|
|
||
|
BOOL WINAPI Hijack::newExtTextOutW(HDC hdc, int X, int Y, UINT fuOptions, const RECT *lprc, LPCWSTR lpString, UINT cchString, const INT *lpDx)
|
||
|
{
|
||
|
|
||
|
DCFontSwitcher fs(hdc);
|
||
|
// if (HijackManager::instance()->isFunctionTranslated((ULONG)::ExtTextOutW))
|
||
|
// TRANSLATE_TEXT_W(lpString, cchString, oldExtTextOutW(hdc, X, Y, fuOptions, lprc, lpString, cchString, lpDx))
|
||
|
return oldExtTextOutW(hdc, X, Y, fuOptions, lprc, lpString, cchString, lpDx);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// EOF
|