diff options
author | Steve Dower <steve.dower@microsoft.com> | 2018-12-07 05:09:20 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-07 05:09:20 (GMT) |
commit | 468a15aaf9206448a744fc5eab3fc21f51966aad (patch) | |
tree | 75c8f2aae7835ae7ca718ef8660a4c0899837bd3 /PC/python_uwp.cpp | |
parent | c9566b8c454120e3d0ddb5ab970f262a6cd80077 (diff) | |
download | cpython-468a15aaf9206448a744fc5eab3fc21f51966aad.zip cpython-468a15aaf9206448a744fc5eab3fc21f51966aad.tar.gz cpython-468a15aaf9206448a744fc5eab3fc21f51966aad.tar.bz2 |
bpo-34977: Add Windows App Store package (GH-10245)
Diffstat (limited to 'PC/python_uwp.cpp')
-rw-r--r-- | PC/python_uwp.cpp | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/PC/python_uwp.cpp b/PC/python_uwp.cpp new file mode 100644 index 0000000..1658d05 --- /dev/null +++ b/PC/python_uwp.cpp @@ -0,0 +1,226 @@ +/* Main program when embedded in a UWP application on Windows */ + +#include "Python.h" +#include <string.h> + +#define WIN32_LEAN_AND_MEAN +#include <Windows.h> +#include <shellapi.h> +#include <winrt\Windows.ApplicationModel.h> +#include <winrt\Windows.Storage.h> + +#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 |