diff --git a/LunaTranslator/files/defaultconfig/static_data.json b/LunaTranslator/files/defaultconfig/static_data.json index 66ed3b15..33a138a0 100644 --- a/LunaTranslator/files/defaultconfig/static_data.json +++ b/LunaTranslator/files/defaultconfig/static_data.json @@ -1,5 +1,5 @@ { - "version": "v2.47.1", + "version": "v2.48.0", "themes": { "dark": [ { diff --git a/LunaTranslator/retrieval.py b/LunaTranslator/retrieval.py index b0b66182..231b3155 100644 --- a/LunaTranslator/retrieval.py +++ b/LunaTranslator/retrieval.py @@ -4,10 +4,8 @@ import builtins x86 = int(sys.argv[1]) if len(sys.argv) > 1 else 0 if x86: downlevel = r"C:\Windows\SysWOW64\downlevel" - src = py37Pathlocal = ( - os.environ["LOCALAPPDATA"] + r"\Programs\Python\Python37-32" + "\\" - ) - tgt = r"..\build\LunaTranslator_x86\LunaTranslator\runtime" + + runtime = r"..\build\LunaTranslator_x86\LunaTranslator\runtime" targetdir = r"..\build\LunaTranslator_x86" launch = r"..\plugins\builds\_x86" baddll = "DLL64" @@ -21,33 +19,17 @@ else: baddll = "DLL32" gooddll = "DLL64" launch = r"..\plugins\builds\_x64" - tgt = r"..\build\LunaTranslator\LunaTranslator\runtime" + runtime = r"..\build\LunaTranslator\LunaTranslator\runtime" targetdir = r"..\build\LunaTranslator" downlevel = r"C:\Windows\system32\downlevel" - src = py37Pathlocal = ( - os.environ["LOCALAPPDATA"] + r"\Programs\Python\Python37" + "\\" - ) + py37Path = "C:\\hostedtoolcache\\windows\\Python\\3.7.9\\x64\\python.exe" py37Pathlocal = os.environ["LOCALAPPDATA"] + r"\Programs\Python\Python37\python.exe" webviewappendix = r"Lib\site-packages\webviewpy\platform\win32\x64\webview.dll" if os.path.exists(py37Path) == False: py37Path = py37Pathlocal -py37Pathwebview = os.path.join(os.path.dirname(py37Path), webviewappendix) - -saveopen = builtins.open - - -def __open(*arg, **kwarg): - if len(arg) > 1: - mode = arg[1] - else: - mode = "" - if "b" not in mode: - kwarg["encoding"] = "utf8" - return saveopen(*arg, **kwarg) - - -builtins.open = __open +py37Path = os.path.dirname(py37Path) +py37Pathwebview = os.path.join(py37Path, webviewappendix) def get_import_table(file_path): @@ -61,6 +43,18 @@ def get_import_table(file_path): def get_dependencies(filename): + saveopen = builtins.open + + def __open(*arg, **kwarg): + if len(arg) > 1: + mode = arg[1] + else: + mode = "" + if "b" not in mode: + kwarg["encoding"] = "utf8" + return saveopen(*arg, **kwarg) + + builtins.open = __open finder = modulefinder.ModuleFinder() finder.run_script(filename) @@ -69,11 +63,12 @@ def get_dependencies(filename): for name, module in finder.modules.items(): if module.__file__ is not None: dependencies.append(module.__file__) - + builtins.open = saveopen return dependencies def copycheck(src, tgt): + print(src, tgt, os.path.exists(src)) if not os.path.exists(src): return if src.lower().endswith("_ssl.pyd"): @@ -131,104 +126,121 @@ for dependency in all_dependencies: if dependency.startswith("./"): continue print(dependency) - end = dependency[len(src) :] + end = dependency[len(py37Path) + 1 :] if end.lower().startswith("lib"): end = end[4:] if end.lower().startswith("site-packages"): end = end[len("site-packages") + 1 :] elif end.lower().startswith("dlls"): end = end[5:] - tgtreal = os.path.dirname(os.path.join(tgt, end)) + print(end) + tgtreal = os.path.join(runtime, os.path.dirname(end)) copycheck(dependency, tgtreal) -with open(os.path.join(tgt, "python37._pth"), "w") as ff: +with open(os.path.join(runtime, "python37._pth"), "w") as ff: ff.write(".\n..") -copycheck(os.path.join(src, "python3.dll"), tgt) -copycheck(os.path.join(src, "python37.dll"), tgt) -copycheck(os.path.join(src, "Dlls/sqlite3.dll"), tgt) +copycheck(os.path.join(py37Path, "python3.dll"), runtime) +copycheck(os.path.join(py37Path, "python37.dll"), runtime) +copycheck(os.path.join(py37Path, "Dlls/sqlite3.dll"), runtime) -copycheck(os.path.join(src, "Lib/encodings"), os.path.join(tgt)) +copycheck(os.path.join(py37Path, "Lib/encodings"), runtime) -copycheck(rf"{downlevel}\ucrtbase.dll", tgt) +copycheck(rf"{downlevel}\ucrtbase.dll", runtime) copycheck( - os.path.join(src, "Lib/site-packages/PyQt5/Qt5/bin/vcruntime140.dll"), - os.path.join(tgt), + os.path.join(py37Path, "Lib/site-packages/PyQt5/Qt5/bin/vcruntime140.dll"), + os.path.join(runtime), ) copycheck( - os.path.join(src, "Lib/site-packages/PyQt5/Qt5/bin/vcruntime140_1.dll"), - os.path.join(tgt), + os.path.join(py37Path, "Lib/site-packages/PyQt5/Qt5/bin/vcruntime140_1.dll"), + os.path.join(runtime), ) copycheck( - os.path.join(src, "Lib/site-packages/PyQt5/Qt5/bin/msvcp140.dll"), os.path.join(tgt) + os.path.join(py37Path, "Lib/site-packages/PyQt5/Qt5/bin/msvcp140.dll"), + os.path.join(runtime), ) copycheck( - os.path.join(src, "Lib/site-packages/PyQt5/Qt5/bin/Qt5/msvcp140_1.dll"), - os.path.join(tgt), + os.path.join(py37Path, "Lib/site-packages/PyQt5/Qt5/bin/msvcp140_1.dll"), + os.path.join(runtime), ) -for _ in os.listdir(os.path.join(src, "Lib/site-packages/PyQt5")): +for _ in os.listdir(os.path.join(py37Path, "Lib/site-packages/PyQt5")): if _.startswith("sip"): copycheck( - os.path.join(src, "Lib/site-packages/PyQt5", _), os.path.join(tgt, "PyQt5") + os.path.join(py37Path, "Lib/site-packages/PyQt5", _), + os.path.join(runtime, "PyQt5"), ) copycheck( - os.path.join(src, "Lib/site-packages/PyQt5/Qt5/bin/Qt5Core.dll"), - os.path.join(tgt, "PyQt5/Qt5/bin"), + os.path.join(py37Path, "Lib/site-packages/PyQt5/Qt5/bin/Qt5Core.dll"), + os.path.join(runtime, "PyQt5/Qt5/bin"), ) copycheck( - os.path.join(src, "Lib/site-packages/PyQt5/Qt5/bin/Qt5Gui.dll"), - os.path.join(tgt, "PyQt5/Qt5/bin"), + os.path.join(py37Path, "Lib/site-packages/PyQt5/Qt5/bin/Qt5Gui.dll"), + os.path.join(runtime, "PyQt5/Qt5/bin"), ) copycheck( - os.path.join(src, "Lib/site-packages/PyQt5/Qt5/bin/Qt5Widgets.dll"), - os.path.join(tgt, "PyQt5/Qt5/bin"), + os.path.join(py37Path, "Lib/site-packages/PyQt5/Qt5/bin/Qt5Widgets.dll"), + os.path.join(runtime, "PyQt5/Qt5/bin"), ) copycheck( - os.path.join(src, "Lib/site-packages/PyQt5/Qt5/plugins/imageformats"), - os.path.join(tgt, "PyQt5/Qt5/plugins"), -) -copycheck( - os.path.join(src, "Lib/site-packages/PyQt5/Qt5/plugins/platforms/qoffscreen.dll"), - os.path.join(tgt, "PyQt5/Qt5/plugins/platforms"), -) -copycheck( - os.path.join(src, "Lib/site-packages/PyQt5/Qt5/plugins/platforms/qwindows.dll"), - os.path.join(tgt, "PyQt5/Qt5/plugins/platforms"), + os.path.join(py37Path, "Lib/site-packages/PyQt5/Qt5/plugins/imageformats"), + os.path.join(runtime, "PyQt5/Qt5/plugins"), ) copycheck( os.path.join( - src, "Lib/site-packages/PyQt5/Qt5/plugins/styles/qwindowsvistastyle.dll" + py37Path, "Lib/site-packages/PyQt5/Qt5/plugins/platforms/qoffscreen.dll" ), - os.path.join(tgt, "PyQt5/Qt5/plugins/styles"), + os.path.join(runtime, "PyQt5/Qt5/plugins/platforms"), +) +copycheck( + os.path.join( + py37Path, "Lib/site-packages/PyQt5/Qt5/plugins/platforms/qwindows.dll" + ), + os.path.join(runtime, "PyQt5/Qt5/plugins/platforms"), +) +copycheck( + os.path.join( + py37Path, "Lib/site-packages/PyQt5/Qt5/plugins/styles/qwindowsvistastyle.dll" + ), + os.path.join(runtime, "PyQt5/Qt5/plugins/styles"), ) collect = [] for _dir, _, fs in os.walk(targetdir): for f in fs: collect.append(os.path.join(_dir, f)) -for src in collect: - if src.endswith(".pyc") or src.endswith("Thumbs.db"): +for f in collect: + if f.endswith(".pyc") or f.endswith("Thumbs.db"): os.remove(f) + elif f.endswith(".exe") or f.endswith(".pyd") or f.endswith(".dll"): - elif src.lower().endswith(".pyd") or src.lower().endswith(".dll"): - - if src.endswith("QtWidgets.pyd"): - imports = [ + try: + pe = pefile.PE(f) + import_table = pe.DIRECTORY_ENTRY_IMPORT + imports = [] + for entry in import_table: + if entry.dll.decode("utf-8").lower().startswith("api"): + imports.append(entry.dll.decode("utf-8")) + pe.close() + except: + continue + if f.endswith("Magpie.Core.exe"): + continue + if f.endswith("QtWidgets.pyd"): + imports += [ "api-ms-win-crt-runtime-l1-1-0.dll", "api-ms-win-crt-heap-l1-1-0.dll", ] - else: - imports = get_import_table(src) - print(src, imports) + # pefile好像有bug,仅对于QtWidgets.pyd这个文件,只能读取到导入了Qt5Widgets.dll + print(f, imports) if len(imports) == 0: continue - with open(src, "rb") as ff: + with open(f, "rb") as ff: bs = bytearray(ff.read()) for _dll in imports: if _dll.lower().startswith("api-ms-win-core"): @@ -236,13 +248,13 @@ for src in collect: _target = "kernel32.dll" elif _dll.lower().startswith("api-ms-win-crt"): _target = "ucrtbase.dll" - else: - continue _dll = _dll.encode() _target = _target.encode() idx = bs.find(_dll) + # print(len(bs)) bs[idx : idx + len(_dll)] = _target + b"\0" * (len(_dll) - len(_target)) - with open(os.path.join(tgt, os.path.basename(src)), "wb") as ff: + # print(len(bs)) + with open(f, "wb") as ff: ff.write(bs) target = os.path.basename(targetdir) diff --git a/plugins/exec/PyStand.cpp b/plugins/exec/PyStand.cpp index aa0d42a6..7bc80bde 100644 --- a/plugins/exec/PyStand.cpp +++ b/plugins/exec/PyStand.cpp @@ -47,40 +47,6 @@ PyStand::PyStand(const wchar_t *runtime) } } - -//--------------------------------------------------------------------- -// ctor for ansi -//--------------------------------------------------------------------- -PyStand::PyStand(const char *runtime) -{ - _hDLL = NULL; - _Py_Main = NULL; - std::wstring rtp = Ansi2Unicode(runtime); - if (CheckEnviron(rtp.c_str()) == false) { - exit(1); - } - if (LoadPython() == false) { - exit(2); - } -} - - -//--------------------------------------------------------------------- -// char to wchar_t -//--------------------------------------------------------------------- -std::wstring PyStand::Ansi2Unicode(const char *text) -{ - int len = (int)strlen(text); - std::wstring wide; - int require = MultiByteToWideChar(CP_ACP, 0, text, len, NULL, 0); - if (require > 0) { - wide.resize(require); - MultiByteToWideChar(CP_ACP, 0, text, len, &wide[0], require); - } - return wide; -} - - //--------------------------------------------------------------------- // init: _args, _argv, _cwd, _pystand, _home, _runtime, //--------------------------------------------------------------------- @@ -247,25 +213,6 @@ int PyStand::RunString(const wchar_t *script) } -//--------------------------------------------------------------------- -// run ansi string -//--------------------------------------------------------------------- -int PyStand::RunString(const char *script) -{ - std::wstring text = Ansi2Unicode(script); - return RunString(text.c_str()); -} - - - -//--------------------------------------------------------------------- -// static init script -//--------------------------------------------------------------------- -#ifndef PYSTAND_STATIC_NAME -#define PYSTAND_STATIC_NAME "LunaTranslator\\LunaTranslator_main.py" -#endif - - //--------------------------------------------------------------------- // LoadScript() //--------------------------------------------------------------------- @@ -281,33 +228,20 @@ int PyStand::DetectScript() std::vector exts; std::vector scripts; _script.clear(); -#if !(PYSTAND_DISABLE_STATIC) + std::wstring test; - test = _home + L"\\" + Ansi2Unicode(PYSTAND_STATIC_NAME); + test = _home + L"LunaTranslator\\LunaTranslator_main.py"; if (PathFileExistsW(test.c_str())) { _script = test; } -#endif + if (_script.empty()) { - exts.push_back(L".int"); - exts.push_back(L".py"); - exts.push_back(L".pyw"); - for (int i = 0; i < (int)exts.size(); i++) { - std::wstring test = main + exts[i]; - scripts.push_back(test); - if (PathFileExistsW(test.c_str())) { - _script = test; - break; - } - } - if (_script.size() == 0) { std::wstring msg = L"Can't find either of:\r\n"; for (int j = 0; j < (int)scripts.size(); j++) { msg += scripts[j] + L"\r\n"; } MessageBoxW(NULL, msg.c_str(), L"ERROR", MB_OK); return -1; - } } SetEnvironmentVariableW(L"PYSTAND_SCRIPT", _script.c_str()); return 0; @@ -317,53 +251,53 @@ int PyStand::DetectScript() //--------------------------------------------------------------------- // init script //--------------------------------------------------------------------- -const char *init_script = -"import sys\n" -"import os\n" -"PYSTAND = os.environ['PYSTAND']\n" -"PYSTAND_HOME = os.environ['PYSTAND_HOME']\n" -"PYSTAND_RUNTIME = os.environ['PYSTAND_RUNTIME']\n" -"PYSTAND_SCRIPT = os.environ['PYSTAND_SCRIPT']\n" -"sys.path_origin = [n for n in sys.path]\n" -"sys.PYSTAND = PYSTAND\n" -"sys.PYSTAND_HOME = PYSTAND_HOME\n" -"sys.PYSTAND_SCRIPT = PYSTAND_SCRIPT\n" -"def MessageBox(msg, info = 'Message'):\n" -" import ctypes\n" -" ctypes.windll.user32.MessageBoxW(None, str(msg), str(info), 0)\n" -" return 0\n" -"os.MessageBox = MessageBox\n" +const auto init_script = +L"import sys\n" +L"import os\n" +L"PYSTAND = os.environ['PYSTAND']\n" +L"PYSTAND_HOME = os.environ['PYSTAND_HOME']\n" +L"PYSTAND_RUNTIME = os.environ['PYSTAND_RUNTIME']\n" +L"PYSTAND_SCRIPT = os.environ['PYSTAND_SCRIPT']\n" +L"sys.path_origin = [n for n in sys.path]\n" +L"sys.PYSTAND = PYSTAND\n" +L"sys.PYSTAND_HOME = PYSTAND_HOME\n" +L"sys.PYSTAND_SCRIPT = PYSTAND_SCRIPT\n" +L"def MessageBox(msg, info = 'Message'):\n" +L" import ctypes\n" +L" ctypes.windll.user32.MessageBoxW(None, str(msg), str(info), 0)\n" +L" return 0\n" +L"os.MessageBox = MessageBox\n" #ifndef PYSTAND_CONSOLE -"try:\n" -" fd = os.open('CONOUT$', os.O_RDWR | os.O_BINARY)\n" -" fp = os.fdopen(fd, 'w')\n" -" sys.stdout = fp\n" -" sys.stderr = fp\n" -" attached = True\n" -"except Exception as e:\n" -" fp = open(os.devnull, 'w')\n" -" sys.stdout = fp\n" -" sys.stderr = fp\n" -" attached = False\n" +L"try:\n" +L" fd = os.open('CONOUT$', os.O_RDWR | os.O_BINARY)\n" +L" fp = os.fdopen(fd, 'w')\n" +L" sys.stdout = fp\n" +L" sys.stderr = fp\n" +L" attached = True\n" +L"except Exception as e:\n" +L" fp = open(os.devnull, 'w')\n" +L" sys.stdout = fp\n" +L" sys.stderr = fp\n" +L" attached = False\n" #endif -"sys.argv = [PYSTAND_SCRIPT] + sys.argv[1:]\n" -"text = open(PYSTAND_SCRIPT, 'rb').read()\n" -"environ = {'__file__': PYSTAND_SCRIPT, '__name__': '__main__'}\n" -"environ['__package__'] = None\n" +L"sys.argv = [PYSTAND_SCRIPT] + sys.argv[1:]\n" +L"text = open(PYSTAND_SCRIPT, 'rb').read()\n" +L"environ = {'__file__': PYSTAND_SCRIPT, '__name__': '__main__'}\n" +L"environ['__package__'] = None\n" #ifndef PYSTAND_CONSOLE -"try:\n" -" code = compile(text, PYSTAND_SCRIPT, 'exec')\n" -" exec(code, environ)\n" -"except Exception:\n" -" if attached:\n" -" raise\n" -" import traceback, io\n" -" sio = io.StringIO()\n" -" traceback.print_exc(file = sio)\n" -" os.MessageBox(sio.getvalue(), 'Error')\n" +L"try:\n" +L" code = compile(text, PYSTAND_SCRIPT, 'exec')\n" +L" exec(code, environ)\n" +L"except Exception:\n" +L" if attached:\n" +L" raise\n" +L" import traceback, io\n" +L" sio = io.StringIO()\n" +L" traceback.print_exc(file = sio)\n" +L" os.MessageBox(sio.getvalue(), 'Error')\n" #else -"code = compile(text, PYSTAND_SCRIPT, 'exec')\n" -"exec(code, environ)\n" +L"code = compile(text, PYSTAND_SCRIPT, 'exec')\n" +L"exec(code, environ)\n" #endif ""; @@ -386,7 +320,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR args, int show) #endif { - PyStand ps("LunaTranslator\\runtime"); + PyStand ps(L"LunaTranslator\\runtime"); if (ps.DetectScript() != 0) { return 3; } diff --git a/plugins/exec/PyStand.h b/plugins/exec/PyStand.h index 40a1194b..0f4131fa 100644 --- a/plugins/exec/PyStand.h +++ b/plugins/exec/PyStand.h @@ -24,16 +24,11 @@ class PyStand public: virtual ~PyStand(); PyStand(const wchar_t *runtime); - PyStand(const char *runtime); public: - std::wstring Ansi2Unicode(const char *text); int RunString(const wchar_t *script); - int RunString(const char *script); - int DetectScript(); - protected: bool CheckEnviron(const wchar_t *rtp); bool LoadPython();