/* Main program when embedded in a UWP application on Windows */ #include "Python.h" #include #define WIN32_LEAN_AND_MEAN #include #include #include #include #ifdef PYTHONW #ifdef _DEBUG const wchar_t *PROGNAME = L"pythonw_d.exe"; #else const wchar_t *PROGNAME = L"pythonw.exe"; #endif #else #ifdef _DEBUG const wchar_t *PROGNAME = L"python_d.exe"; #else const wchar_t *PROGNAME = L"python.exe"; #endif #endif static void set_user_base() { wchar_t envBuffer[2048]; try { const auto appData = winrt::Windows::Storage::ApplicationData::Current(); if (appData) { const auto localCache = appData.LocalCacheFolder(); if (localCache) { auto path = localCache.Path(); if (!path.empty() && !wcscpy_s(envBuffer, path.c_str()) && !wcscat_s(envBuffer, L"\\local-packages") ) { _wputenv_s(L"PYTHONUSERBASE", envBuffer); } } } } catch (...) { } } static const wchar_t * get_argv0(const wchar_t *argv0) { winrt::hstring installPath; const wchar_t *launcherPath; wchar_t *buffer; size_t len; launcherPath = _wgetenv(L"__PYVENV_LAUNCHER__"); if (launcherPath && launcherPath[0]) { len = wcslen(launcherPath) + 1; buffer = (wchar_t *)malloc(sizeof(wchar_t) * len); if (!buffer) { Py_FatalError("out of memory"); return NULL; } if (wcscpy_s(buffer, len, launcherPath)) { Py_FatalError("failed to copy to buffer"); return NULL; } return buffer; } try { const auto package = winrt::Windows::ApplicationModel::Package::Current(); if (package) { const auto install = package.InstalledLocation(); if (install) { installPath = install.Path(); } } } catch (...) { } if (!installPath.empty()) { len = installPath.size() + wcslen(PROGNAME) + 2; } else { len = wcslen(argv0) + wcslen(PROGNAME) + 1; } buffer = (wchar_t *)malloc(sizeof(wchar_t) * len); if (!buffer) { Py_FatalError("out of memory"); return NULL; } if (!installPath.empty()) { if (wcscpy_s(buffer, len, installPath.c_str())) { Py_FatalError("failed to copy to buffer"); return NULL; } if (wcscat_s(buffer, len, L"\\")) { Py_FatalError("failed to concatenate backslash"); return NULL; } } else { if (wcscpy_s(buffer, len, argv0)) { Py_FatalError("failed to copy argv[0]"); return NULL; } wchar_t *name = wcsrchr(buffer, L'\\'); if (name) { name[1] = L'\0'; } else { buffer[0] = L'\0'; } } if (wcscat_s(buffer, len, PROGNAME)) { Py_FatalError("failed to concatenate program name"); return NULL; } return buffer; } static wchar_t * get_process_name() { DWORD bufferLen = MAX_PATH; DWORD len = bufferLen; wchar_t *r = NULL; while (!r) { r = (wchar_t *)malloc(bufferLen * sizeof(wchar_t)); if (!r) { Py_FatalError("out of memory"); return NULL; } len = GetModuleFileNameW(NULL, r, bufferLen); if (len == 0) { free((void *)r); return NULL; } else if (len == bufferLen && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { free(r); r = NULL; bufferLen *= 2; } } return r; } int wmain(int argc, wchar_t **argv) { const wchar_t **new_argv; int new_argc; const wchar_t *exeName; new_argc = argc; new_argv = (const wchar_t**)malloc(sizeof(wchar_t *) * (argc + 2)); if (new_argv == NULL) { Py_FatalError("out of memory"); return -1; } exeName = get_process_name(); new_argv[0] = get_argv0(exeName ? exeName : argv[0]); for (int i = 1; i < argc; ++i) { new_argv[i] = argv[i]; } set_user_base(); if (exeName) { const wchar_t *p = wcsrchr(exeName, L'\\'); if (p) { const wchar_t *moduleName = NULL; if (*p++ == L'\\') { if (wcsnicmp(p, L"pip", 3) == 0) { moduleName = L"pip"; _wputenv_s(L"PIP_USER", L"true"); } else if (wcsnicmp(p, L"idle", 4) == 0) { moduleName = L"idlelib"; } } if (moduleName) { new_argc += 2; for (int i = argc; i >= 1; --i) { new_argv[i + 2] = new_argv[i]; } new_argv[1] = L"-m"; new_argv[2] = moduleName; } } } /* Override program_full_path from here so that sys.executable is set correctly. */ _Py_SetProgramFullPath(new_argv[0]); int result = Py_Main(new_argc, (wchar_t **)new_argv); free((void *)exeName); free((void *)new_argv); return result; } #ifdef PYTHONW int WINAPI wWinMain( HINSTANCE hInstance, /* handle to current instance */ HINSTANCE hPrevInstance, /* handle to previous instance */ LPWSTR lpCmdLine, /* pointer to command line */ int nCmdShow /* show state of window */ ) { return wmain(__argc, __wargv); } #endif