LunaHook-mirror/LunaHook/engines/python/python2.cpp
2024-03-03 20:59:57 +08:00

207 lines
8.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include"types.h"
#include"embed_util.h"
#include"main.h"
namespace {
typedef wchar_t Py_UNICODE ;
typedef size_t Py_ssize_t;
typedef void PyObject ;
typedef PyObject* (*PyUnicode_FromObject_t)( PyObject *obj );
#ifdef Py_TRACE_REFS
/* Define pointers to support a doubly-linked list of all live heap objects. */
#define _PyObject_HEAD_EXTRA \
struct _object *_ob_next; \
struct _object *_ob_prev;
#define _PyObject_EXTRA_INIT 0, 0,
#else
#define _PyObject_HEAD_EXTRA
#define _PyObject_EXTRA_INIT
#endif
#define PyObject_HEAD \
_PyObject_HEAD_EXTRA \
Py_ssize_t ob_refcnt; \
struct _typeobject *ob_type;
typedef struct {
PyObject_HEAD
Py_ssize_t length; /* Length of raw Unicode data in buffer */
Py_UNICODE *str; /* Raw Unicode buffer */
long hash; /* Hash value; -1 if not set */
PyObject *defenc; /* (Default) Encoded version as Python
string, or NULL; this is used for
implementing the buffer protocol */
} PyUnicodeObject;
#define PyUnicode_AS_UNICODE(op) \
(((PyUnicodeObject *)(op))->str)
#define PyUnicode_GET_SIZE(op) \
(((PyUnicodeObject *)(op))->length)
PyUnicode_FromObject_t PyUnicode_FromObject;
inline std::pair<Py_UNICODE*,Py_ssize_t> GetPyUnicodeString(PyObject *object){
if(PyUnicode_FromObject==NULL)
return {};
if (object == NULL)
return {};
auto uformat = PyUnicode_FromObject(object);
if (uformat == NULL){
return {};
}
auto fmt = PyUnicode_AS_UNICODE(uformat);
auto fmtcnt = PyUnicode_GET_SIZE(uformat);
return {fmt,fmtcnt};
}
typedef PyObject* (*PyUnicode_FromUnicode_t)(
const Py_UNICODE *u, /* Unicode buffer */
Py_ssize_t size /* size of buffer */
);
PyUnicode_FromUnicode_t PyUnicode_FromUnicode;
typedef enum {PyGILState_LOCKED, PyGILState_UNLOCKED}
PyGILState_STATE;
typedef PyGILState_STATE (*PyGILState_Ensure_t)(void);
PyGILState_Ensure_t PyGILState_Ensure;
typedef void (*PyGILState_Release_t)(PyGILState_STATE);
PyGILState_Release_t PyGILState_Release;
typedef int (*PyRun_SimpleString_t)(const char *command);
PyRun_SimpleString_t PyRun_SimpleString;
}
bool InsertRenpyHook(){
wchar_t python[] = L"python2X.dll", libpython[] = L"libpython2.X.dll";
for (wchar_t* name : { python, libpython })
{
wchar_t* pos = wcschr(name, L'X');
for (int pythonMinorVersion = 0; pythonMinorVersion <= 8; ++pythonMinorVersion)
{
*pos = L'0' + pythonMinorVersion;
if (HMODULE module = GetModuleHandleW(name))
{
PyUnicode_FromObject=(PyUnicode_FromObject_t)GetProcAddress(module, "PyUnicodeUCS2_FromObject");
PyUnicode_FromUnicode=(PyUnicode_FromUnicode_t)GetProcAddress(module, "PyUnicodeUCS2_FromUnicode");
auto f1=[=](){
HookParam hp;
hp.address = (uintptr_t)GetProcAddress(module, "PyUnicodeUCS2_Format");
if (!hp.address) return false;
hp.text_fun = [](hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len)
{
#ifndef _WIN64
auto format=(PyObject *)stack->stack[1];
#else
auto format=(PyObject *)stack->rcx;
#endif
auto [strptr,strlen]=GetPyUnicodeString(format);
*data=(uintptr_t)strptr;
*len=0;
if(wcschr(strptr, L'%') == nullptr)
*len=sizeof(wchar_t)*strlen;
};
hp.type = USING_STRING | CODEC_UTF16 | NO_CONTEXT;
if(PyUnicode_FromUnicode)
{
hp.type|=EMBED_ABLE|EMBED_BEFORE_SIMPLE;
hp.hook_after=[](hook_stack* stack,void* data, size_t len)
{
#ifndef _WIN64
auto format=(PyObject *)stack->stack[1];
#else
auto format=(PyObject *)stack->rcx;
#endif
if(format==NULL)return;
#ifndef _WIN64
stack->stack[1]=
#else
stack->rcx=
#endif
(uintptr_t)PyUnicode_FromUnicode((Py_UNICODE *)data,len/2);
};
PyGILState_Ensure=(PyGILState_Ensure_t)GetProcAddress(module, "PyGILState_Ensure");
PyGILState_Release=(PyGILState_Release_t)GetProcAddress(module, "PyGILState_Release");
PyRun_SimpleString=(PyRun_SimpleString_t)GetProcAddress(module, "PyRun_SimpleString");
patch_fun=[](){
//由于不知道怎么从字体名映射到ttc/ttf文件名所以暂时写死arial/msyh
if(wcslen(embedsharedmem->fontFamily)==0)return;
auto state=PyGILState_Ensure();
PyRun_SimpleString(
R"(
try:
import renpy
import ctypes
import os
def hook_renpy_text_font_get_font_init(original):
def new_init(*args, **kwargs):
#ctypes.windll.user32.MessageBoxW(None, str(kwargs), str(args), 0)
if os.path.exists(r'C:\Windows\Fonts\msyh.ttc'):
font='msyh.ttc'
elif os.path.exists(r'C:\Windows\Fonts\arial.ttf'):
font='arial.ttf'
else:
font=None
if font:
args=(font,)+args[1:]
if 'fn' in kwargs:
kwargs['fn']=font
return original(*args, **kwargs)
return new_init
renpy.text.font.get_font = hook_renpy_text_font_get_font_init(renpy.text.font.get_font)
except:
pass
)");
PyGILState_Release(state);
};
}
return NewHook(hp, "Ren'py");
}();
#ifndef _WIN64
auto f2=[=](){
HookParam hp;
hp.address = (uintptr_t)GetProcAddress(module, "PyUnicodeUCS2_Concat");
if (!hp.address) return false;
hp.text_fun = [](hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len)
{
auto left=(PyObject *)stack->stack[1];
auto right=(PyObject *)stack->stack[2];
auto [strptr,strlen]=GetPyUnicodeString(right);
*data=(uintptr_t)strptr;
*len=sizeof(wchar_t)*strlen;
};
hp.filter_fun = [](void* data, size_t* len, HookParam* hp)
{
auto str=std::wstring(reinterpret_cast<LPWSTR>(data),*len/2);
auto filterpath={
L".rpy",L".rpa",L".py",L".pyc",L".txt",
L".png",L".jpg",L".bmp",
L".mp3",L".ogg",
L".webm",L".mp4",
L".otf",L".ttf"
};
for(auto _ :filterpath)
if(str.find(_)!=str.npos)
return false;
return true;
};
hp.type = USING_STRING | CODEC_UTF16;
//hp.filter_fun = [](void* str, auto, auto, auto) { return *(wchar_t*)str != L'%'; };
return NewHook(hp, "Ren'py");
}();
#else
auto f2=false;
#endif
return f1||f2;
}
}
}
ConsoleOutput("Ren'py failed: failed to find python2X.dll");
return false;
}