Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/PC/python_uwp.cpp
12 views
1
/* Main program when embedded in a UWP application on Windows */
2
3
#include "Python.h"
4
#include <string.h>
5
6
#define WIN32_LEAN_AND_MEAN
7
#include <Windows.h>
8
#include <shellapi.h>
9
#include <shlobj.h>
10
11
#include <string>
12
13
#include <appmodel.h>
14
#include <winrt\Windows.ApplicationModel.h>
15
#include <winrt\Windows.Storage.h>
16
17
#ifdef PYTHONW
18
#ifdef _DEBUG
19
const wchar_t *PROGNAME = L"pythonw_d.exe";
20
#else
21
const wchar_t *PROGNAME = L"pythonw.exe";
22
#endif
23
#else
24
#ifdef _DEBUG
25
const wchar_t *PROGNAME = L"python_d.exe";
26
#else
27
const wchar_t *PROGNAME = L"python.exe";
28
#endif
29
#endif
30
31
static std::wstring
32
get_package_family()
33
{
34
try {
35
UINT32 nameLength = MAX_PATH;
36
std::wstring name;
37
name.resize(nameLength);
38
DWORD rc = GetCurrentPackageFamilyName(&nameLength, name.data());
39
if (rc == ERROR_SUCCESS) {
40
name.resize(nameLength - 1);
41
return name;
42
}
43
else if (rc != ERROR_INSUFFICIENT_BUFFER) {
44
throw rc;
45
}
46
name.resize(nameLength);
47
rc = GetCurrentPackageFamilyName(&nameLength, name.data());
48
if (rc != ERROR_SUCCESS) {
49
throw rc;
50
}
51
name.resize(nameLength - 1);
52
return name;
53
}
54
catch (...) {
55
}
56
57
return std::wstring();
58
}
59
60
static std::wstring
61
get_user_base()
62
{
63
try {
64
const auto appData = winrt::Windows::Storage::ApplicationData::Current();
65
if (appData) {
66
const auto localCache = appData.LocalCacheFolder();
67
if (localCache) {
68
std::wstring path { localCache.Path().c_str() };
69
if (!path.empty()) {
70
return path + L"\\local-packages";
71
}
72
}
73
}
74
} catch (...) {
75
}
76
77
return std::wstring();
78
}
79
80
static std::wstring
81
get_package_home()
82
{
83
try {
84
UINT32 pathLength = MAX_PATH;
85
std::wstring path;
86
path.resize(pathLength);
87
DWORD rc = GetCurrentPackagePath(&pathLength, path.data());
88
if (rc == ERROR_SUCCESS) {
89
path.resize(pathLength - 1);
90
return path;
91
}
92
else if (rc != ERROR_INSUFFICIENT_BUFFER) {
93
throw rc;
94
}
95
path.resize(pathLength);
96
rc = GetCurrentPackagePath(&pathLength, path.data());
97
if (rc != ERROR_SUCCESS) {
98
throw rc;
99
}
100
path.resize(pathLength - 1);
101
return path;
102
}
103
catch (...) {
104
}
105
106
return std::wstring();
107
}
108
109
static PyStatus
110
set_process_name(PyConfig *config)
111
{
112
PyStatus status = PyStatus_Ok();
113
std::wstring executable;
114
115
const auto home = get_package_home();
116
const auto family = get_package_family();
117
118
if (!family.empty()) {
119
PWSTR localAppData;
120
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0,
121
NULL, &localAppData))) {
122
executable = std::wstring(localAppData)
123
+ L"\\Microsoft\\WindowsApps\\"
124
+ family
125
+ L"\\"
126
+ PROGNAME;
127
128
CoTaskMemFree(localAppData);
129
}
130
}
131
132
/* Only use module filename if we don't have a home */
133
if (home.empty() && executable.empty()) {
134
executable.resize(MAX_PATH);
135
while (true) {
136
DWORD len = GetModuleFileNameW(
137
NULL, executable.data(), (DWORD)executable.size());
138
if (len == 0) {
139
executable.clear();
140
break;
141
} else if (len == executable.size() &&
142
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
143
executable.resize(len * 2);
144
} else {
145
executable.resize(len);
146
break;
147
}
148
}
149
size_t i = executable.find_last_of(L"/\\");
150
if (i == std::wstring::npos) {
151
executable = PROGNAME;
152
} else {
153
executable.replace(i + 1, std::wstring::npos, PROGNAME);
154
}
155
}
156
157
if (!home.empty()) {
158
status = PyConfig_SetString(config, &config->home, home.c_str());
159
if (PyStatus_Exception(status)) {
160
return status;
161
}
162
}
163
164
const wchar_t *launcherPath = _wgetenv(L"__PYVENV_LAUNCHER__");
165
if (launcherPath) {
166
if (!executable.empty()) {
167
status = PyConfig_SetString(config, &config->base_executable,
168
executable.c_str());
169
if (PyStatus_Exception(status)) {
170
return status;
171
}
172
}
173
174
status = PyConfig_SetString(
175
config, &config->executable, launcherPath);
176
177
/* bpo-35873: Clear the environment variable to avoid it being
178
* inherited by child processes. */
179
_wputenv_s(L"__PYVENV_LAUNCHER__", L"");
180
} else if (!executable.empty()) {
181
status = PyConfig_SetString(
182
config, &config->executable, executable.c_str());
183
}
184
185
return status;
186
}
187
188
int
189
wmain(int argc, wchar_t **argv)
190
{
191
PyStatus status;
192
PyPreConfig preconfig;
193
PyConfig config;
194
195
const wchar_t *moduleName = NULL;
196
const wchar_t *p = wcsrchr(argv[0], L'\\');
197
if (!p) {
198
p = argv[0];
199
}
200
if (p) {
201
if (*p == L'\\') {
202
p++;
203
}
204
205
if (wcsnicmp(p, L"pip", 3) == 0) {
206
moduleName = L"pip";
207
} else if (wcsnicmp(p, L"idle", 4) == 0) {
208
moduleName = L"idlelib";
209
}
210
}
211
212
PyPreConfig_InitPythonConfig(&preconfig);
213
if (!moduleName) {
214
status = Py_PreInitializeFromArgs(&preconfig, argc, argv);
215
if (PyStatus_Exception(status)) {
216
goto fail_without_config;
217
}
218
}
219
220
PyConfig_InitPythonConfig(&config);
221
222
status = PyConfig_SetArgv(&config, argc, argv);
223
if (PyStatus_Exception(status)) {
224
goto fail;
225
}
226
if (moduleName) {
227
config.parse_argv = 0;
228
}
229
230
status = set_process_name(&config);
231
if (PyStatus_Exception(status)) {
232
goto fail;
233
}
234
235
p = _wgetenv(L"PYTHONUSERBASE");
236
if (!p || !*p) {
237
_wputenv_s(L"PYTHONUSERBASE", get_user_base().c_str());
238
}
239
240
if (moduleName) {
241
status = PyConfig_SetString(&config, &config.run_module, moduleName);
242
if (PyStatus_Exception(status)) {
243
goto fail;
244
}
245
status = PyConfig_SetString(&config, &config.run_filename, NULL);
246
if (PyStatus_Exception(status)) {
247
goto fail;
248
}
249
status = PyConfig_SetString(&config, &config.run_command, NULL);
250
if (PyStatus_Exception(status)) {
251
goto fail;
252
}
253
}
254
255
status = Py_InitializeFromConfig(&config);
256
if (PyStatus_Exception(status)) {
257
goto fail;
258
}
259
PyConfig_Clear(&config);
260
261
return Py_RunMain();
262
263
fail:
264
PyConfig_Clear(&config);
265
fail_without_config:
266
if (PyStatus_IsExit(status)) {
267
return status.exitcode;
268
}
269
assert(PyStatus_Exception(status));
270
Py_ExitStatusException(status);
271
/* Unreachable code */
272
return 0;
273
}
274
275
#ifdef PYTHONW
276
277
int WINAPI wWinMain(
278
HINSTANCE hInstance, /* handle to current instance */
279
HINSTANCE hPrevInstance, /* handle to previous instance */
280
LPWSTR lpCmdLine, /* pointer to command line */
281
int nCmdShow /* show state of window */
282
)
283
{
284
return wmain(__argc, __wargv);
285
}
286
287
#endif
288
289