diff --git a/extras/win32-portable/openslides.c b/extras/win32-portable/openslides.c index 7e6abdcc4..e69d9824b 100644 --- a/extras/win32-portable/openslides.c +++ b/extras/win32-portable/openslides.c @@ -12,6 +12,17 @@ #include +#define PYTHON_DLL_PATH "\\Dlls\\python27.dll" + +static void (*py_initialize)(void) = 0; +static void (*py_finalize)(void) = 0; +static void (*py_set_program_name)(char *) = 0; +static void (*py_set_python_home)(char *) = 0; +static int (*py_run_simple_string_flags)(const char *, PyCompilerFlags *) = 0; +static void (*py_sys_set_argv_ex)(int, char **, int) = 0; +static int (*py_main)(int, char **) = 0; +static int *py_ignore_environment_flag = 0; + static const char *run_openslides_code = "import openslides_gui.gui;" "openslides_gui.gui.main()"; @@ -71,14 +82,94 @@ _get_module_name() return NULL; } +static void +_fatal_error(const char *text) +{ + MessageBoxA(NULL, text, "Fatal error", MB_OK | MB_ICONERROR); + exit(1); +} + +static void +_fatal_error_fmt(const char *fmt, ...) +{ + int size = 512; + char *buf = malloc(size); + va_list args; + int bytes_written; + + if (!buf) + abort(); + + va_start(args, fmt); + for (;;) + { + bytes_written = vsnprintf(buf, size, fmt, args); + if (bytes_written > -1 && bytes_written < size) + break; + else if (bytes_written > size) + size = bytes_written + 1; + else + size *= 2; + + buf = realloc(buf, size); + if (!buf) + abort(); + } + va_end(args); + + _fatal_error(buf); +} + +static void * +_load_func(HMODULE module, const char *name) +{ + void *address = GetProcAddress(module, name); + if (!address) + _fatal_error_fmt("Failed to look up symbol %s", name); + return address; +} + +static void +_load_python(const char *pyhome) +{ + size_t pyhome_len = strlen(pyhome); + size_t size = pyhome_len + strlen(PYTHON_DLL_PATH) + 1; + char *buf = malloc(size); + HMODULE py_dll; + + if (!buf) + abort(); + memcpy(buf, pyhome, pyhome_len); + memcpy(buf + pyhome_len, PYTHON_DLL_PATH, sizeof(PYTHON_DLL_PATH)); + buf[size - 1] = '\0'; + + py_dll = LoadLibrary(buf); + if (!py_dll) + { + DWORD error = GetLastError(); + _fatal_error_fmt("Failed to load %s (error %d)", buf, error); + } + + py_initialize = (void (*)(void))_load_func(py_dll, "Py_Initialize"); + py_finalize = (void (*)(void))_load_func(py_dll, "Py_Finalize"); + py_set_program_name = (void (*)(char *)) + _load_func(py_dll, "Py_SetProgramName"); + py_set_python_home = (void (*)(char *)) + _load_func(py_dll, "Py_SetPythonHome"); + py_run_simple_string_flags = (int (*)(const char *, PyCompilerFlags *)) + _load_func(py_dll, "PyRun_SimpleStringFlags"); + py_sys_set_argv_ex = (void (*)(int, char **, int)) + _load_func(py_dll, "PySys_SetArgvEx"); + py_main = (int (*)(int, char **))_load_func(py_dll, "Py_Main"); + py_ignore_environment_flag = (int *) + _load_func(py_dll, "Py_IgnoreEnvironmentFlag"); +} + static int _run() { - if (PyRun_SimpleString(run_openslides_code) != 0) - { - fprintf(stderr, "ERROR: failed to execute openslides\n"); - return 1; - } + if (py_run_simple_string_flags(run_openslides_code, NULL) != 0) + _fatal_error("Failed to execute openslides"); return 0; } @@ -91,33 +182,33 @@ WinMain(HINSTANCE inst, HINSTANCE prev_inst, LPSTR cmdline, int show) int run_py_main = __argc > 1; char *py_home, *sep = NULL; - Py_SetProgramName(__argv[0]); - py_home = _get_module_name(); + if (!py_home) + _fatal_error("Could not determine portable root directory"); - if (py_home) - sep = strrchr(py_home, '\\'); + sep = strrchr(py_home, '\\'); /* should always be the true */ if (sep) - { *sep = '\0'; - Py_SetPythonHome(py_home); - Py_IgnoreEnvironmentFlag = 1; - } + + _load_python(py_home); + py_set_program_name(__argv[0]); + py_set_python_home(py_home); + *py_ignore_environment_flag = 1; if (run_py_main) { /* we where given extra arguments, behave like python.exe */ - returncode = Py_Main(__argc, __argv); + returncode = py_main(__argc, __argv); } else { /* no arguments given => start openslides gui */ - Py_Initialize(); - PySys_SetArgvEx(__argc, __argv, 0); + py_initialize(); + py_sys_set_argv_ex(__argc, __argv, 0); returncode = _run(); - Py_Finalize(); + py_finalize(); } free(py_home); diff --git a/extras/win32-portable/openslides.exe b/extras/win32-portable/openslides.exe index 812eabdc0..7d1bd450f 100755 Binary files a/extras/win32-portable/openslides.exe and b/extras/win32-portable/openslides.exe differ diff --git a/extras/win32-portable/prepare_portable.py b/extras/win32-portable/prepare_portable.py index 770fef517..41d81c9e1 100644 --- a/extras/win32-portable/prepare_portable.py +++ b/extras/win32-portable/prepare_portable.py @@ -318,7 +318,7 @@ def compile_openslides_launcher(): return False cc.add_include_dir(distutils.sysconfig.get_python_inc()) - cc.add_library_dir(os.path.join(sys.exec_prefix, "Libs")) + cc.define_macro("_CRT_SECURE_NO_WARNINGS") gui_data_dir = os.path.dirname(openslides_gui.__file__) gui_data_dir = os.path.join(gui_data_dir, "data") @@ -343,7 +343,8 @@ def compile_openslides_launcher(): ]) cc.link_executable( objs, "extras/win32-portable/openslides", - extra_preargs=["/subsystem:windows"], + extra_preargs=["/subsystem:windows", "/nodefaultlib:python27.lib"], + libraries = ["user32"] ) return True @@ -361,7 +362,7 @@ def copy_dlls(odir): pydllname = "python{0}{1}.dll".format(*sys.version_info[:2]) src = os.path.join(os.environ["WINDIR"], "System32", pydllname) - dest = os.path.join(odir, pydllname) + dest = os.path.join(dll_dest, pydllname) shutil.copyfile(src, dest)