| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | /* 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>
 | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  | #include <shlobj.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <string>
 | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-23 19:50:15 +00:00
										 |  |  | #include <appmodel.h>
 | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | #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
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  | static std::wstring | 
					
						
							| 
									
										
										
										
											2022-11-23 19:50:15 +00:00
										 |  |  | get_package_family() | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | { | 
					
						
							|  |  |  |     try { | 
					
						
							| 
									
										
										
										
											2022-11-23 19:50:15 +00:00
										 |  |  |         UINT32 nameLength = MAX_PATH; | 
					
						
							|  |  |  |         std::wstring name; | 
					
						
							|  |  |  |         name.resize(nameLength); | 
					
						
							|  |  |  |         DWORD rc = GetCurrentPackageFamilyName(&nameLength, name.data()); | 
					
						
							|  |  |  |         if (rc == ERROR_SUCCESS) { | 
					
						
							|  |  |  |             name.resize(nameLength - 1); | 
					
						
							|  |  |  |             return name; | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-11-23 19:50:15 +00:00
										 |  |  |         else if (rc != ERROR_INSUFFICIENT_BUFFER) { | 
					
						
							|  |  |  |             throw rc; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         name.resize(nameLength); | 
					
						
							|  |  |  |         rc = GetCurrentPackageFamilyName(&nameLength, name.data()); | 
					
						
							|  |  |  |         if (rc != ERROR_SUCCESS) { | 
					
						
							|  |  |  |             throw rc; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         name.resize(nameLength - 1); | 
					
						
							|  |  |  |         return name; | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-11-23 19:50:15 +00:00
										 |  |  |     catch (...) { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |     return std::wstring(); | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  | static std::wstring | 
					
						
							| 
									
										
										
										
											2022-11-23 19:50:15 +00:00
										 |  |  | get_user_base() | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |     try { | 
					
						
							| 
									
										
										
										
											2022-11-23 19:50:15 +00:00
										 |  |  |         const auto appData = winrt::Windows::Storage::ApplicationData::Current(); | 
					
						
							|  |  |  |         if (appData) { | 
					
						
							|  |  |  |             const auto localCache = appData.LocalCacheFolder(); | 
					
						
							|  |  |  |             if (localCache) { | 
					
						
							|  |  |  |                 std::wstring path { localCache.Path().c_str() }; | 
					
						
							|  |  |  |                 if (!path.empty()) { | 
					
						
							|  |  |  |                     return path + L"\\local-packages"; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-11-23 19:50:15 +00:00
										 |  |  |     } catch (...) { | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return std::wstring(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  | static std::wstring | 
					
						
							|  |  |  | get_package_home() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     try { | 
					
						
							| 
									
										
										
										
											2022-11-23 19:50:15 +00:00
										 |  |  |         UINT32 pathLength = MAX_PATH; | 
					
						
							|  |  |  |         std::wstring path; | 
					
						
							|  |  |  |         path.resize(pathLength); | 
					
						
							|  |  |  |         DWORD rc = GetCurrentPackagePath(&pathLength, path.data()); | 
					
						
							|  |  |  |         if (rc == ERROR_SUCCESS) { | 
					
						
							|  |  |  |             path.resize(pathLength - 1); | 
					
						
							|  |  |  |             return path; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (rc != ERROR_INSUFFICIENT_BUFFER) { | 
					
						
							|  |  |  |             throw rc; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         path.resize(pathLength); | 
					
						
							|  |  |  |         rc = GetCurrentPackagePath(&pathLength, path.data()); | 
					
						
							|  |  |  |         if (rc != ERROR_SUCCESS) { | 
					
						
							|  |  |  |             throw rc; | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-11-23 19:50:15 +00:00
										 |  |  |         path.resize(pathLength - 1); | 
					
						
							|  |  |  |         return path; | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     } | 
					
						
							|  |  |  |     catch (...) { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |     return std::wstring(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  | static PyStatus | 
					
						
							|  |  |  | set_process_name(PyConfig *config) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyStatus status = PyStatus_Ok(); | 
					
						
							|  |  |  |     std::wstring executable; | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |     const auto home = get_package_home(); | 
					
						
							|  |  |  |     const auto family = get_package_family(); | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |     if (!family.empty()) { | 
					
						
							|  |  |  |         PWSTR localAppData; | 
					
						
							|  |  |  |         if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, | 
					
						
							|  |  |  |                                            NULL, &localAppData))) { | 
					
						
							|  |  |  |             executable = std::wstring(localAppData) | 
					
						
							|  |  |  |                          + L"\\Microsoft\\WindowsApps\\" | 
					
						
							|  |  |  |                          + family | 
					
						
							|  |  |  |                          + L"\\" | 
					
						
							|  |  |  |                          + PROGNAME; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             CoTaskMemFree(localAppData); | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |     /* Only use module filename if we don't have a home */ | 
					
						
							|  |  |  |     if (home.empty() && executable.empty()) { | 
					
						
							|  |  |  |         executable.resize(MAX_PATH); | 
					
						
							|  |  |  |         while (true) { | 
					
						
							|  |  |  |             DWORD len = GetModuleFileNameW( | 
					
						
							|  |  |  |                 NULL, executable.data(), (DWORD)executable.size()); | 
					
						
							|  |  |  |             if (len == 0) { | 
					
						
							|  |  |  |                 executable.clear(); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } else if (len == executable.size() && | 
					
						
							|  |  |  |                        GetLastError() == ERROR_INSUFFICIENT_BUFFER) { | 
					
						
							|  |  |  |                 executable.resize(len * 2); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 executable.resize(len); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-07-24 15:13:22 -07:00
										 |  |  |         size_t i = executable.find_last_of(L"/\\"); | 
					
						
							|  |  |  |         if (i == std::wstring::npos) { | 
					
						
							|  |  |  |             executable = PROGNAME; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             executable.replace(i + 1, std::wstring::npos, PROGNAME); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |     if (!home.empty()) { | 
					
						
							|  |  |  |         status = PyConfig_SetString(config, &config->home, home.c_str()); | 
					
						
							|  |  |  |         if (PyStatus_Exception(status)) { | 
					
						
							|  |  |  |             return status; | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const wchar_t *launcherPath = _wgetenv(L"__PYVENV_LAUNCHER__"); | 
					
						
							|  |  |  |     if (launcherPath) { | 
					
						
							|  |  |  |         if (!executable.empty()) { | 
					
						
							|  |  |  |             status = PyConfig_SetString(config, &config->base_executable, | 
					
						
							|  |  |  |                                         executable.c_str()); | 
					
						
							|  |  |  |             if (PyStatus_Exception(status)) { | 
					
						
							|  |  |  |                 return status; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         status = PyConfig_SetString( | 
					
						
							|  |  |  |             config, &config->executable, launcherPath); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* bpo-35873: Clear the environment variable to avoid it being
 | 
					
						
							|  |  |  |         * inherited by child processes. */ | 
					
						
							|  |  |  |         _wputenv_s(L"__PYVENV_LAUNCHER__", L""); | 
					
						
							|  |  |  |     } else if (!executable.empty()) { | 
					
						
							|  |  |  |         status = PyConfig_SetString( | 
					
						
							|  |  |  |             config, &config->executable, executable.c_str()); | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |     return status; | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | wmain(int argc, wchar_t **argv) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |     PyStatus status; | 
					
						
							|  |  |  |     PyPreConfig preconfig; | 
					
						
							|  |  |  |     PyConfig config; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-24 15:13:22 -07:00
										 |  |  |     const wchar_t *moduleName = NULL; | 
					
						
							|  |  |  |     const wchar_t *p = wcsrchr(argv[0], L'\\'); | 
					
						
							|  |  |  |     if (!p) { | 
					
						
							|  |  |  |         p = argv[0]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (p) { | 
					
						
							|  |  |  |         if (*p == L'\\') { | 
					
						
							|  |  |  |             p++; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (wcsnicmp(p, L"pip", 3) == 0) { | 
					
						
							|  |  |  |             moduleName = L"pip"; | 
					
						
							|  |  |  |         } else if (wcsnicmp(p, L"idle", 4) == 0) { | 
					
						
							|  |  |  |             moduleName = L"idlelib"; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-01 10:56:37 +02:00
										 |  |  |     PyPreConfig_InitPythonConfig(&preconfig); | 
					
						
							| 
									
										
										
										
											2019-07-24 15:13:22 -07:00
										 |  |  |     if (!moduleName) { | 
					
						
							|  |  |  |         status = Py_PreInitializeFromArgs(&preconfig, argc, argv); | 
					
						
							|  |  |  |         if (PyStatus_Exception(status)) { | 
					
						
							|  |  |  |             goto fail_without_config; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-01 12:06:16 +02:00
										 |  |  |     PyConfig_InitPythonConfig(&config); | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |     status = PyConfig_SetArgv(&config, argc, argv); | 
					
						
							|  |  |  |     if (PyStatus_Exception(status)) { | 
					
						
							|  |  |  |         goto fail; | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-07-24 15:13:22 -07:00
										 |  |  |     if (moduleName) { | 
					
						
							|  |  |  |         config.parse_argv = 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |     status = set_process_name(&config); | 
					
						
							|  |  |  |     if (PyStatus_Exception(status)) { | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-24 15:13:22 -07:00
										 |  |  |     p = _wgetenv(L"PYTHONUSERBASE"); | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |     if (!p || !*p) { | 
					
						
							|  |  |  |         _wputenv_s(L"PYTHONUSERBASE", get_user_base().c_str()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-24 15:13:22 -07:00
										 |  |  |     if (moduleName) { | 
					
						
							|  |  |  |         status = PyConfig_SetString(&config, &config.run_module, moduleName); | 
					
						
							|  |  |  |         if (PyStatus_Exception(status)) { | 
					
						
							|  |  |  |             goto fail; | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-07-24 15:13:22 -07:00
										 |  |  |         status = PyConfig_SetString(&config, &config.run_filename, NULL); | 
					
						
							|  |  |  |         if (PyStatus_Exception(status)) { | 
					
						
							|  |  |  |             goto fail; | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-07-24 15:13:22 -07:00
										 |  |  |         status = PyConfig_SetString(&config, &config.run_command, NULL); | 
					
						
							|  |  |  |         if (PyStatus_Exception(status)) { | 
					
						
							|  |  |  |             goto fail; | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |     status = Py_InitializeFromConfig(&config); | 
					
						
							|  |  |  |     if (PyStatus_Exception(status)) { | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyConfig_Clear(&config); | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |     return Py_RunMain(); | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  | fail: | 
					
						
							|  |  |  |     PyConfig_Clear(&config); | 
					
						
							| 
									
										
										
										
											2019-06-29 14:28:43 -07:00
										 |  |  | fail_without_config: | 
					
						
							| 
									
										
										
										
											2019-06-29 10:34:11 -07:00
										 |  |  |     if (PyStatus_IsExit(status)) { | 
					
						
							|  |  |  |         return status.exitcode; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     assert(PyStatus_Exception(status)); | 
					
						
							|  |  |  |     Py_ExitStatusException(status); | 
					
						
							|  |  |  |     /* Unreachable code */ | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #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
 |