summaryrefslogtreecommitdiffstats
path: root/PC/python_uwp.cpp
diff options
context:
space:
mode:
authorSteve Dower <steve.dower@microsoft.com>2018-12-07 05:09:20 (GMT)
committerGitHub <noreply@github.com>2018-12-07 05:09:20 (GMT)
commit468a15aaf9206448a744fc5eab3fc21f51966aad (patch)
tree75c8f2aae7835ae7ca718ef8660a4c0899837bd3 /PC/python_uwp.cpp
parentc9566b8c454120e3d0ddb5ab970f262a6cd80077 (diff)
downloadcpython-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.cpp226
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