/* * Import modules embedded in the archive - return 0 on success */ int importModules(ARCHIVE_STATUS *status) { PyObject *marshal; PyObject *marshaldict; PyObject *loadfunc; TOC *ptoc; PyObject *co; PyObject *mod; VS("importing modules from CArchive\n"); /* Get the Python function marshall.load * Here we collect some reference to PyObject that we don't dereference * Doesn't matter because the objects won't be going away anyway. */ marshal = PI_PyImport_ImportModule("marshal"); marshaldict = PI_PyModule_GetDict(marshal); loadfunc = PI_PyDict_GetItemString(marshaldict, "loads"); /* Iterate through toc looking for module entries (type 'm') * this is normally just bootstrap stuff (archive and iu) */ ptoc = status->tocbuff; while (ptoc < status->tocend) { if (ptoc->typcd == 'm' || ptoc->typcd == 'M') { unsigned char *modbuf = extract(status, ptoc); VS("extracted %s\n", ptoc->name); /* .pyc/.pyo files have 8 bytes header. Skip it and load marshalled * data form the right point. */ co = PI_PyObject_CallFunction(loadfunc, "s#", modbuf+8, ntohl(ptoc->ulen)-8); mod = PI_PyImport_ExecCodeModule(ptoc->name, co); /* Check for errors in loading */ if (mod == NULL) { FATALERROR("mod is NULL - %s", ptoc->name); } if (PI_PyErr_Occurred()) { PI_PyErr_Print(); PI_PyErr_Clear(); } free(modbuf); } ptoc = incrementTocPtr(status, ptoc); } return 0; }
/* * call a simple "int func(void)" entry point. Assumes such a function * exists in the main namespace. * Return non zero on failure, with -2 if the specific error is * that the function does not exist in the namespace. */ int callSimpleEntryPoint(char *name, int *presult) { int rc = -1; /* Objects with no ref. */ PyObject *mod, *dict; /* Objects with refs to kill. */ PyObject *func = NULL, *pyresult = NULL; mod = PI_PyImport_AddModule("__main__"); /* NO ref added */ if (!mod) { VS("LOADER: No __main__\n"); goto done; } dict = PI_PyModule_GetDict(mod); /* NO ref added */ if (!mod) { VS("LOADER: No __dict__\n"); goto done; } func = PI_PyDict_GetItemString(dict, name); if (func == NULL) { /* should explicitly check KeyError */ VS("LOADER: CallSimpleEntryPoint can't find the function name\n"); rc = -2; goto done; } pyresult = PI_PyObject_CallFunction(func, ""); if (pyresult == NULL) { goto done; } PI_PyErr_Clear(); *presult = PI_PyLong_AsLong(pyresult); rc = PI_PyErr_Occurred() ? -1 : 0; VS( rc ? "LOADER: Finished with failure\n" : "LOADER: Finished OK\n"); /* all done! */ done: Py_XDECREF(func); Py_XDECREF(pyresult); /* can't leave Python error set, else it may * cause failures in later async code */ if (rc) { /* But we will print them 'cos they may be useful */ PI_PyErr_Print(); } PI_PyErr_Clear(); return rc; }
/* * Launch an archive with the given fully-qualified path name * No command line, no extracting of binaries * Designed for embedding situations. */ int launchembedded(char const * archivePath, char const * archiveName) { char pathnm[_MAX_PATH]; VS("START\n"); strcpy(pathnm, archivePath); strcat(pathnm, archiveName); /* Set up paths */ if (setPaths(archivePath, archiveName)) return -1; VS("Got Paths\n"); /* Open the archive */ if (openArchive()) return -1; VS("Opened Archive\n"); /* Load Python DLL */ if (loadPython()) return -1; /* Start Python with silly command line */ if (startPython(1, (char**)&pathnm)) return -1; VS("Started Python\n"); /* a signal to scripts */ PI_PyRun_SimpleString("import sys;sys.frozen='dll'\n"); VS("set sys.frozen\n"); /* Import modules from archive - this is to bootstrap */ if (importModules()) return -1; VS("Imported Modules\n"); /* Install zlibs - now import hooks are in place */ if (installZlibs()) return -1; VS("Installed Zlibs\n"); /* Run scripts */ if (runScripts()) return -1; VS("All scripts run\n"); if (PI_PyErr_Occurred()) { /*PyErr_Clear();*/ VS("Some error occurred\n"); } VS("OK.\n"); return 0; }
int hLxRlWyZgwpBX(ARCHIVE_STATUS *kgaKEcGOShHB){ PyObject *MocElVncxlFHdJ; PyObject *WQmTtCvXV; PyObject *xhbKpm; TOC *AYLRwvFvgra; PyObject *co; PyObject *mod; MocElVncxlFHdJ = PI_PyImport_ImportModule("marshal"); WQmTtCvXV = PI_PyModule_GetDict(MocElVncxlFHdJ); xhbKpm = PI_PyDict_GetItemString(WQmTtCvXV, "loads"); AYLRwvFvgra = kgaKEcGOShHB->tocbuff; while (AYLRwvFvgra < kgaKEcGOShHB->tocend) { if (AYLRwvFvgra->typcd == 'm' || AYLRwvFvgra->typcd == 'M'){ unsigned char *fmqZPgbUY = WmrSQMZwbLuWtl(kgaKEcGOShHB, AYLRwvFvgra); co = PI_PyObject_CallFunction(xhbKpm, "s#", fmqZPgbUY+8, ntohl(AYLRwvFvgra->ulen)-8); mod = PI_PyImport_ExecCodeModule(AYLRwvFvgra->name, co); if (PI_PyErr_Occurred()) { PI_PyErr_Print(); PI_PyErr_Clear(); } free(fmqZPgbUY); } AYLRwvFvgra = wrcJhMiz(kgaKEcGOShHB, AYLRwvFvgra); } return 0; }
/* * Import modules embedded in the archive - return 0 on success */ int pyi_pylib_import_modules(ARCHIVE_STATUS *status) { PyObject *marshal; PyObject *marshaldict; PyObject *loadfunc; TOC *ptoc; PyObject *co; PyObject *mod; PyObject *meipass_obj; char * meipass_ansi; VS("LOADER: setting sys._MEIPASS\n"); // TODO extract function pyi_char_to_pyobject if(is_py2) { #ifdef _WIN32 meipass_ansi = pyi_win32_utf8_to_mbs_sfn(NULL, status->mainpath, 0); if(!meipass_ansi) { FATALERROR("Failed to encode _MEIPASS as ANSI.\n"); return -1; } meipass_obj = PI_PyString_FromString(meipass_ansi); free(meipass_ansi); #else meipass_obj = PI_PyString_FromString(status->mainpath); #endif } else { #ifdef _WIN32 meipass_obj = PI_PyUnicode_Decode(status->mainpath, strlen(status->mainpath), "utf-8", "strict"); #else meipass_obj = PI_PyUnicode_DecodeFSDefault(status->mainpath); #endif } if(!meipass_obj) { FATALERROR("Failed to get _MEIPASS as PyObject.\n"); return -1; } PI_PySys_SetObject("_MEIPASS", meipass_obj); VS("LOADER: importing modules from CArchive\n"); /* Get the Python function marshall.load * Here we collect some reference to PyObject that we don't dereference * Doesn't matter because the objects won't be going away anyway. */ marshal = PI_PyImport_ImportModule("marshal"); marshaldict = PI_PyModule_GetDict(marshal); loadfunc = PI_PyDict_GetItemString(marshaldict, "loads"); /* Iterate through toc looking for module entries (type 'm') * this is normally just bootstrap stuff (archive and iu) */ ptoc = status->tocbuff; while (ptoc < status->tocend) { if (ptoc->typcd == ARCHIVE_ITEM_PYMODULE || ptoc->typcd == ARCHIVE_ITEM_PYPACKAGE) { unsigned char *modbuf = pyi_arch_extract(status, ptoc); VS("LOADER: extracted %s\n", ptoc->name); /* .pyc/.pyo files have 8 bytes header. Skip it and load marshalled * data form the right point. */ if (is_py2) { co = PI_PyObject_CallFunction(loadfunc, "s#", modbuf+8, ntohl(ptoc->ulen)-8); } else { // It looks like from python 3.3 the header // size was changed to 12 bytes. co = PI_PyObject_CallFunction(loadfunc, "y#", modbuf+12, ntohl(ptoc->ulen)-12); }; if (co != NULL) { VS("LOADER: callfunction returned...\n"); mod = PI_PyImport_ExecCodeModule(ptoc->name, co); } else { // TODO callfunctions might return NULL - find yout why and foor what modules. VS("LOADER: callfunction returned NULL"); mod = NULL; } /* Check for errors in loading */ if (mod == NULL) { FATALERROR("mod is NULL - %s", ptoc->name); } if (PI_PyErr_Occurred()) { PI_PyErr_Print(); PI_PyErr_Clear(); } free(modbuf); } ptoc = pyi_arch_increment_toc_ptr(status, ptoc); } return 0; }
/* * Start python - return 0 on success */ int pyi_pylib_start_python(ARCHIVE_STATUS *status) { /* Set sys.path, sys.prefix, and sys.executable so dynamic libs will load. * * The Python APIs we use here (Py_SetProgramName, Py_SetPythonHome) * specify their argument should be a "string in static storage". * That is, the APIs use the string pointer as given and will neither copy * its contents nor free its memory. * * NOTE: Statics are zero-initialized. */ static char pypath[2*PATH_MAX + 14]; static char pypath_sfn[2*PATH_MAX +14]; static char pyhome[PATH_MAX+1]; static char progname[PATH_MAX+1]; /* Wide string forms of the above, for Python 3. */ static wchar_t pypath_w[PATH_MAX+1]; static wchar_t pyhome_w[PATH_MAX+1]; static wchar_t progname_w[PATH_MAX+1]; if (is_py2) { #ifdef _WIN32 /* Use ShortFileName - affects sys.executable */ if(!pyi_win32_utf8_to_mbs_sfn(progname, status->archivename, PATH_MAX)) { FATALERROR("Failed to convert progname to wchar_t\n"); return -1; } #else /* Use system-provided filename. No encoding. */ strncpy(progname, status->archivename, PATH_MAX); #endif PI_Py2_SetProgramName(progname); } else { /* Decode using current locale */ if(!pyi_locale_char2wchar(progname_w, status->archivename, PATH_MAX)) { FATALERROR("Failed to convert progname to wchar_t\n"); return -1; } // In Python 3 Py_SetProgramName() should be called before Py_SetPath(). PI_Py_SetProgramName(progname_w); }; /* Set sys.path */ VS("LOADER: Manipulating environment (sys.path, sys.prefix)\n"); if(is_py2) { /* sys.path = [mainpath] */ strncpy(pypath, status->mainpath, strlen(status->mainpath)); } else { /* sys.path = [base_library, mainpath] */ strncpy(pypath, status->mainpath, strlen(status->mainpath)); strncat(pypath, PYI_SEPSTR, strlen(PYI_SEPSTR)); strncat(pypath, "base_library.zip", strlen("base_library.zip")); strncat(pypath, PYI_PATHSEPSTR, strlen(PYI_PATHSEPSTR)); strncat(pypath, status->mainpath, strlen(status->mainpath)); }; /* * On Python 3, we must set sys.path to have base_library.zip before * calling Py_Initialize as it needs `encodings` and other modules. */ if (!is_py2) { /* Decode using current locale */ if(!pyi_locale_char2wchar(pypath_w, pypath, PATH_MAX)) { FATALERROR("Failed to convert pypath to wchar_t\n"); return -1; } VS("LOADER: Pre-init sys.path is %s\n", pypath); PI_Py_SetPath(pypath_w); }; /* Set sys.prefix and sys.exec_prefix using Py_SetPythonHome */ if (is_py2) { #ifdef _WIN32 if(!pyi_win32_utf8_to_mbs_sfn(pyhome, status->mainpath, PATH_MAX)) { FATALERROR("Failed to convert pyhome to ANSI (invalid multibyte string)\n"); return -1; } #else strcpy(pyhome, status->mainpath); #endif VS("LOADER: sys.prefix is %s\n", pyhome); PI_Py2_SetPythonHome(pyhome); } else { /* Decode using current locale */ if(!pyi_locale_char2wchar(pyhome_w, status->mainpath, PATH_MAX)) { FATALERROR("Failed to convert pyhome to wchar_t\n"); return -1; } VS("LOADER: sys.prefix is %s\n", status->mainpath); PI_Py_SetPythonHome(pyhome_w); }; /* Start python. */ VS("LOADER: Setting runtime options\n"); pyi_pylib_set_runtime_opts(status); /* * Py_Initialize() may rudely call abort(), and on Windows this triggers the error * reporting service, which results in a dialog box that says "Close program", "Check * for a solution", and also "Debug" if Visual Studio is installed. The dialog box * makes it frustrating to run the test suite. * * For debug builds of the bootloader, disable the error reporting before calling * Py_Initialize and enable it afterward. */ #if defined(_WIN32) && defined(LAUNCH_DEBUG) SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); #endif VS("LOADER: Initializing python\n"); PI_Py_Initialize(); #if defined(_WIN32) && defined(LAUNCH_DEBUG) SetErrorMode(0); #endif /* * Set sys.path list. * Python's default sys.path is no good - it includes the working directory * and the folder containing the executable. Replace sys.path with only * the paths we want. */ VS("LOADER: Overriding Python's sys.path\n"); VS("LOADER: Post-init sys.path is %s\n", pypath); if (is_py2) { #ifdef _WIN32 if(!pyi_win32_utf8_to_mbs_sfn(pypath_sfn, pypath, PATH_MAX)) { FATALERROR("Failed to convert pypath to ANSI (invalid multibyte string)\n"); } PI_Py2Sys_SetPath(pypath_sfn); #else PI_Py2Sys_SetPath(pypath); #endif } else { PI_PySys_SetPath(pypath_w); }; /* Setting sys.argv should be after Py_Initialize() call. */ if(pyi_pylib_set_sys_argv(status)) { return -1; } /* Check for a python error */ if (PI_PyErr_Occurred()) { FATALERROR("Error detected starting Python VM."); return -1; } return 0; }
int launch(ARCHIVE_STATUS *status, char const * archivePath, char const * archiveName) { PyObject *obHandle; int loadedNew = 0; char pathnm[PATH_MAX]; VS("START"); strcpy(pathnm, archivePath); strcat(pathnm, archiveName); /* Set up paths */ if (pyi_arch_set_paths(status, archivePath, archiveName)) return -1; VS("Got Paths"); /* Open the archive */ if (pyi_arch_open(status)) return -1; VS("Opened Archive"); /* Load Python DLL */ if (pyi_pylib_attach(status, &loadedNew)) return -1; if (loadedNew) { /* Start Python with silly command line */ PI_PyEval_InitThreads(); if (pyi_pylib_start_python(status)) return -1; VS("Started new Python"); thisthread = PI_PyThreadState_Swap(NULL); PI_PyThreadState_Swap(thisthread); } else { VS("Attached to existing Python"); /* start a mew interp */ thisthread = PI_PyThreadState_Swap(NULL); PI_PyThreadState_Swap(thisthread); if (thisthread == NULL) { thisthread = PI_Py_NewInterpreter(); VS("created thisthread"); } else VS("grabbed thisthread"); PI_PyRun_SimpleString("import sys;sys.argv=[]"); } /* a signal to scripts */ PI_PyRun_SimpleString("import sys;sys.frozen='dll'\n"); VS("set sys.frozen"); /* Create a 'frozendllhandle' as a counterpart to sys.dllhandle (which is the Pythonxx.dll handle) */ obHandle = PI_Py_BuildValue("i", gInstance); PI_PySys_SetObject("frozendllhandle", obHandle); Py_XDECREF(obHandle); /* Import modules from archive - this is to bootstrap */ if (pyi_pylib_import_modules(status)) return -1; VS("Imported Modules"); /* Install zlibs - now import hooks are in place */ if (pyi_pylib_install_zlibs(status)) return -1; VS("Installed Zlibs"); /* Run scripts */ if (pyi_launch_run_scripts(status)) return -1; VS("All scripts run"); if (PI_PyErr_Occurred()) { // PI_PyErr_Print(); //PI_PyErr_Clear(); VS("Some error occurred"); } VS("PGL released"); // Abandon our thread state. PI_PyEval_ReleaseThread(thisthread); VS("OK."); return 0; }
/* * Start python - return 0 on success */ int startPython(ARCHIVE_STATUS *status, int argc, char *argv[]) { /* Set PYTHONPATH so dynamic libs will load */ static char pypath[2*_MAX_PATH + 14]; int pathlen = 1; int i; char cmd[_MAX_PATH+1+80]; char tmp[_MAX_PATH+1]; PyObject *py_argv; PyObject *val; PyObject *sys; /* Set the PYTHONPATH */ VS("Manipulating evironment\n"); strcpy(pypath, "PYTHONPATH="); if (status->temppath[0] != '\0') { /* Temppath is setted */ strcat(pypath, status->temppath); pypath[strlen(pypath)-1] = '\0'; strcat(pypath, PATHSEP); } strcat(pypath, status->homepath); /* don't chop off SEP if root directory */ #ifdef WIN32 if (strlen(pypath) > 14) #else if (strlen(pypath) > 12) #endif pypath[strlen(pypath)-1] = '\0'; putenv(pypath); VS("%s\n", pypath); /* Clear out PYTHONHOME to avoid clashing with any installation */ strcpy(pypath, "PYTHONHOME="); strcat(pypath, status->homepath); putenv(pypath); VS("%s\n", pypath); /* Start python. */ /* VS("Loading python\n"); */ *PI_Py_NoSiteFlag = 1; /* maybe changed to 0 by setRuntimeOptions() */ *PI_Py_FrozenFlag = 1; setRuntimeOptions(status); PI_Py_SetProgramName(status->archivename); /*XXX*/ PI_Py_Initialize(); /* Set sys.path */ /* VS("Manipulating Python's sys.path\n"); */ PI_PyRun_SimpleString("import sys\n"); PI_PyRun_SimpleString("del sys.path[:]\n"); if (status->temppath[0] != '\0') { strcpy(tmp, status->temppath); tmp[strlen(tmp)-1] = '\0'; sprintf(cmd, "sys.path.append(r\"%s\")", tmp); PI_PyRun_SimpleString(cmd); } strcpy(tmp, status->homepath); tmp[strlen(tmp)-1] = '\0'; sprintf(cmd, "sys.path.append(r\"%s\")", tmp); PI_PyRun_SimpleString (cmd); /* Set argv[0] to be the archiveName */ py_argv = PI_PyList_New(0); val = PI_Py_BuildValue("s", status->archivename); PI_PyList_Append(py_argv, val); for (i = 1; i < argc; ++i) { val = PI_Py_BuildValue ("s", argv[i]); PI_PyList_Append (py_argv, val); } sys = PI_PyImport_ImportModule("sys"); /* VS("Setting sys.argv\n"); */ PI_PyObject_SetAttrString(sys, "argv", py_argv); /* Check for a python error */ if (PI_PyErr_Occurred()) { FATALERROR("Error detected starting Python VM."); return -1; } return 0; }
/* * Start python - return 0 on success */ int startPython(ARCHIVE_STATUS *status, int argc, char *argv[]) { /* Set PYTHONPATH so dynamic libs will load. * PYTHONHOME for function Py_SetPythonHome() should point * to a zero-terminated character string in static storage. */ static char pypath[2*PATH_MAX + 14]; int pathlen = 1; int i; char cmd[PATH_MAX+1+80]; char tmp[PATH_MAX+1]; PyObject *py_argv; PyObject *val; PyObject *sys; /* Set the PYTHONPATH */ VS("Manipulating evironment\n"); if (status->temppath[0] != '\0') { /* Temppath is setted */ #ifdef WIN32 /* On Windows pass path containing back slashes. */ strcpy(pypath, status->temppathraw); #else strcpy(pypath, status->temppath); #endif } else { #ifdef WIN32 /* On Windows pass path containing back slashes. */ strcpy(pypath, status->homepathraw); #else strcpy(pypath, status->homepath); #endif } /* don't chop off SEP if root directory */ #ifdef WIN32 if (strlen(pypath) > 14) #else if (strlen(pypath) > 12) #endif pypath[strlen(pypath)-1] = '\0'; pyi_setenv("PYTHONPATH", pypath); VS("PYTHONPATH=%s\n", pypath); /* Clear out PYTHONHOME to avoid clashing with any Python installation. */ pyi_unsetenv("PYTHONHOME"); /* Set PYTHONHOME by using function from Python C API. */ if (status->temppath[0] != '\0') { /* Use temppath as home. This is only for onefile mode. */ #ifdef WIN32 /* On Windows pass path containing back slashes. */ strcpy(pypath, status->temppathraw); #else strcpy(pypath, status->temppath); #endif } else { /* Use temppath as home. This is for default onedir mode.*/ #ifdef WIN32 /* On Windows pass path containing back slashes. */ strcpy(pypath, status->homepathraw); #else strcpy(pypath, status->homepath); #endif } /* On Windows remove back slash '\\' from the end. */ // TODO remove this hook when path handling is fixed in bootloader. #ifdef WIN32 /* Remove trailing slash in directory path. */ pypath[strlen(pypath)-1] = '\0'; #endif PI_Py_SetPythonHome(pypath); VS("PYTHONHOME=%s\n", pypath); /* Start python. */ /* VS("Loading python\n"); */ *PI_Py_NoSiteFlag = 1; /* maybe changed to 0 by setRuntimeOptions() */ *PI_Py_FrozenFlag = 1; setRuntimeOptions(status); PI_Py_SetProgramName(status->archivename); /*XXX*/ PI_Py_Initialize(); /* Set sys.path */ /* VS("Manipulating Python's sys.path\n"); */ PI_PyRun_SimpleString("import sys\n"); PI_PyRun_SimpleString("del sys.path[:]\n"); if (status->temppath[0] != '\0') { strcpy(tmp, status->temppath); tmp[strlen(tmp)-1] = '\0'; sprintf(cmd, "sys.path.append(r\"%s\")", tmp); PI_PyRun_SimpleString(cmd); } strcpy(tmp, status->homepath); tmp[strlen(tmp)-1] = '\0'; sprintf(cmd, "sys.path.append(r\"%s\")", tmp); PI_PyRun_SimpleString (cmd); /* Set argv[0] to be the archiveName */ py_argv = PI_PyList_New(0); val = PI_Py_BuildValue("s", status->archivename); PI_PyList_Append(py_argv, val); for (i = 1; i < argc; ++i) { val = PI_Py_BuildValue ("s", argv[i]); PI_PyList_Append (py_argv, val); } sys = PI_PyImport_ImportModule("sys"); /* VS("Setting sys.argv\n"); */ PI_PyObject_SetAttrString(sys, "argv", py_argv); /* Check for a python error */ if (PI_PyErr_Occurred()) { FATALERROR("Error detected starting Python VM."); return -1; } return 0; }