1
2 /* Return the initial module search path. */
3 /* Used by DOS, Windows 3.1, Windows 95/98, Windows NT. */
4
5 /* ----------------------------------------------------------------
6 PATH RULES FOR WINDOWS:
7 This describes how sys.path is formed on Windows. It describes the
8 functionality, not the implementation (ie, the order in which these
9 are actually fetched is different). The presence of a python._pth or
10 pythonXY._pth file alongside the program overrides these rules - see
11 below.
12
13 * Python always adds an empty entry at the start, which corresponds
14 to the current directory.
15
16 * If the PYTHONPATH env. var. exists, its entries are added next.
17
18 * We look in the registry for "application paths" - that is, sub-keys
19 under the main PythonPath registry key. These are added next (the
20 order of sub-key processing is undefined).
21 HKEY_CURRENT_USER is searched and added first.
22 HKEY_LOCAL_MACHINE is searched and added next.
23 (Note that all known installers only use HKLM, so HKCU is typically
24 empty)
25
26 * We attempt to locate the "Python Home" - if the PYTHONHOME env var
27 is set, we believe it. Otherwise, we use the path of our host .EXE's
28 to try and locate one of our "landmarks" and deduce our home.
29 - If we DO have a Python Home: The relevant sub-directories (Lib,
30 DLLs, etc) are based on the Python Home
31 - If we DO NOT have a Python Home, the core Python Path is
32 loaded from the registry. This is the main PythonPath key,
33 and both HKLM and HKCU are combined to form the path)
34
35 * Iff - we can not locate the Python Home, have not had a PYTHONPATH
36 specified, and can't locate any Registry entries (ie, we have _nothing_
37 we can assume is a good path), a default path with relative entries is
38 used (eg. .\Lib;.\DLLs, etc)
39
40
41 If a '._pth' file exists adjacent to the executable with the same base name
42 (e.g. python._pth adjacent to python.exe) or adjacent to the shared library
43 (e.g. python36._pth adjacent to python36.dll), it is used in preference to
44 the above process. The shared library file takes precedence over the
45 executable. The path file must contain a list of paths to add to sys.path,
46 one per line. Each path is relative to the directory containing the file.
47 Blank lines and comments beginning with '#' are permitted.
48
49 In the presence of this ._pth file, no other paths are added to the search
50 path, the registry finder is not enabled, site.py is not imported and
51 isolated mode is enabled. The site package can be enabled by including a
52 line reading "import site"; no other imports are recognized. Any invalid
53 entry (other than directories that do not exist) will result in immediate
54 termination of the program.
55
56
57 The end result of all this is:
58 * When running python.exe, or any other .exe in the main Python directory
59 (either an installed version, or directly from the PCbuild directory),
60 the core path is deduced, and the core paths in the registry are
61 ignored. Other "application paths" in the registry are always read.
62
63 * When Python is hosted in another exe (different directory, embedded via
64 COM, etc), the Python Home will not be deduced, so the core path from
65 the registry is used. Other "application paths" in the registry are
66 always read.
67
68 * If Python can't find its home and there is no registry (eg, frozen
69 exe, some very strange installation setup) you get a path with
70 some default, but relative, paths.
71
72 * An embedding application can use Py_SetPath() to override all of
73 these automatic path computations.
74
75 * An install of Python can fully specify the contents of sys.path using
76 either a 'EXENAME._pth' or 'DLLNAME._pth' file, optionally including
77 "import site" to enable the site module.
78
79 ---------------------------------------------------------------- */
80
81
82 #include "Python.h"
83 #include "internal/pystate.h"
84 #include "osdefs.h"
85 #include <wchar.h>
86
87 #ifndef MS_WINDOWS
88 #error getpathp.c should only be built on Windows
89 #endif
90
91 #include <windows.h>
92 #include <shlwapi.h>
93
94 #ifdef HAVE_SYS_TYPES_H
95 #include <sys/types.h>
96 #endif /* HAVE_SYS_TYPES_H */
97
98 #ifdef HAVE_SYS_STAT_H
99 #include <sys/stat.h>
100 #endif /* HAVE_SYS_STAT_H */
101
102 #include <string.h>
103
104 /* Search in some common locations for the associated Python libraries.
105 *
106 * Py_GetPath() tries to return a sensible Python module search path.
107 *
108 * The approach is an adaptation for Windows of the strategy used in
109 * ../Modules/getpath.c; it uses the Windows Registry as one of its
110 * information sources.
111 *
112 * Py_SetPath() can be used to override this mechanism. Call Py_SetPath
113 * with a semicolon separated path prior to calling Py_Initialize.
114 */
115
116 #ifndef LANDMARK
117 #define LANDMARK L"lib\\os.py"
118 #endif
119
120 typedef struct {
121 const wchar_t *path_env; /* PATH environment variable */
122 const wchar_t *home; /* PYTHONHOME environment variable */
123
124 /* Registry key "Software\Python\PythonCore\PythonPath" */
125 wchar_t *machine_path; /* from HKEY_LOCAL_MACHINE */
126 wchar_t *user_path; /* from HKEY_CURRENT_USER */
127
128 wchar_t argv0_path[MAXPATHLEN+1];
129 wchar_t zip_path[MAXPATHLEN+1];
130 } PyCalculatePath;
131
132
133 /* determine if "ch" is a separator character */
134 static int
is_sep(wchar_t ch)135 is_sep(wchar_t ch)
136 {
137 #ifdef ALTSEP
138 return ch == SEP || ch == ALTSEP;
139 #else
140 return ch == SEP;
141 #endif
142 }
143
144
145 /* assumes 'dir' null terminated in bounds. Never writes
146 beyond existing terminator. */
147 static void
reduce(wchar_t * dir)148 reduce(wchar_t *dir)
149 {
150 size_t i = wcsnlen_s(dir, MAXPATHLEN+1);
151 if (i >= MAXPATHLEN+1) {
152 Py_FatalError("buffer overflow in getpathp.c's reduce()");
153 }
154
155 while (i > 0 && !is_sep(dir[i]))
156 --i;
157 dir[i] = '\0';
158 }
159
160
161 static int
change_ext(wchar_t * dest,const wchar_t * src,const wchar_t * ext)162 change_ext(wchar_t *dest, const wchar_t *src, const wchar_t *ext)
163 {
164 size_t src_len = wcsnlen_s(src, MAXPATHLEN+1);
165 size_t i = src_len;
166 if (i >= MAXPATHLEN+1) {
167 Py_FatalError("buffer overflow in getpathp.c's reduce()");
168 }
169
170 while (i > 0 && src[i] != '.' && !is_sep(src[i]))
171 --i;
172
173 if (i == 0) {
174 dest[0] = '\0';
175 return -1;
176 }
177
178 if (is_sep(src[i])) {
179 i = src_len;
180 }
181
182 if (wcsncpy_s(dest, MAXPATHLEN+1, src, i) ||
183 wcscat_s(dest, MAXPATHLEN+1, ext))
184 {
185 dest[0] = '\0';
186 return -1;
187 }
188
189 return 0;
190 }
191
192
193 static int
exists(const wchar_t * filename)194 exists(const wchar_t *filename)
195 {
196 return GetFileAttributesW(filename) != 0xFFFFFFFF;
197 }
198
199
200 /* Is module -- check for .pyc too.
201 Assumes 'filename' MAXPATHLEN+1 bytes long -
202 may extend 'filename' by one character. */
203 static int
ismodule(wchar_t * filename,int update_filename)204 ismodule(wchar_t *filename, int update_filename)
205 {
206 size_t n;
207
208 if (exists(filename)) {
209 return 1;
210 }
211
212 /* Check for the compiled version of prefix. */
213 n = wcsnlen_s(filename, MAXPATHLEN+1);
214 if (n < MAXPATHLEN) {
215 int exist = 0;
216 filename[n] = L'c';
217 filename[n + 1] = L'\0';
218 exist = exists(filename);
219 if (!update_filename) {
220 filename[n] = L'\0';
221 }
222 return exist;
223 }
224 return 0;
225 }
226
227
228 /* Add a path component, by appending stuff to buffer.
229 buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a
230 NUL-terminated string with no more than MAXPATHLEN characters (not counting
231 the trailing NUL). It's a fatal error if it contains a string longer than
232 that (callers must be careful!). If these requirements are met, it's
233 guaranteed that buffer will still be a NUL-terminated string with no more
234 than MAXPATHLEN characters at exit. If stuff is too long, only as much of
235 stuff as fits will be appended.
236 */
237
238 static int _PathCchCombineEx_Initialized = 0;
239 typedef HRESULT(__stdcall *PPathCchCombineEx) (PWSTR pszPathOut, size_t cchPathOut,
240 PCWSTR pszPathIn, PCWSTR pszMore,
241 unsigned long dwFlags);
242 static PPathCchCombineEx _PathCchCombineEx;
243
244 static void
join(wchar_t * buffer,const wchar_t * stuff)245 join(wchar_t *buffer, const wchar_t *stuff)
246 {
247 if (_PathCchCombineEx_Initialized == 0) {
248 HMODULE pathapi = LoadLibraryW(L"api-ms-win-core-path-l1-1-0.dll");
249 if (pathapi) {
250 _PathCchCombineEx = (PPathCchCombineEx)GetProcAddress(pathapi, "PathCchCombineEx");
251 }
252 else {
253 _PathCchCombineEx = NULL;
254 }
255 _PathCchCombineEx_Initialized = 1;
256 }
257
258 if (_PathCchCombineEx) {
259 if (FAILED(_PathCchCombineEx(buffer, MAXPATHLEN+1, buffer, stuff, 0))) {
260 Py_FatalError("buffer overflow in getpathp.c's join()");
261 }
262 } else {
263 if (!PathCombineW(buffer, buffer, stuff)) {
264 Py_FatalError("buffer overflow in getpathp.c's join()");
265 }
266 }
267 }
268
269 static int _PathCchCanonicalizeEx_Initialized = 0;
270 typedef HRESULT(__stdcall *PPathCchCanonicalizeEx) (PWSTR pszPathOut, size_t cchPathOut,
271 PCWSTR pszPathIn, unsigned long dwFlags);
272 static PPathCchCanonicalizeEx _PathCchCanonicalizeEx;
273
canonicalize(wchar_t * buffer,const wchar_t * path)274 static _PyInitError canonicalize(wchar_t *buffer, const wchar_t *path)
275 {
276 if (buffer == NULL) {
277 return _Py_INIT_NO_MEMORY();
278 }
279
280 if (_PathCchCanonicalizeEx_Initialized == 0) {
281 HMODULE pathapi = LoadLibraryW(L"api-ms-win-core-path-l1-1-0.dll");
282 if (pathapi) {
283 _PathCchCanonicalizeEx = (PPathCchCanonicalizeEx)GetProcAddress(pathapi, "PathCchCanonicalizeEx");
284 }
285 else {
286 _PathCchCanonicalizeEx = NULL;
287 }
288 _PathCchCanonicalizeEx_Initialized = 1;
289 }
290
291 if (_PathCchCanonicalizeEx) {
292 if (FAILED(_PathCchCanonicalizeEx(buffer, MAXPATHLEN + 1, path, 0))) {
293 return _Py_INIT_ERR("buffer overflow in getpathp.c's canonicalize()");
294 }
295 }
296 else {
297 if (!PathCanonicalizeW(buffer, path)) {
298 return _Py_INIT_ERR("buffer overflow in getpathp.c's canonicalize()");
299 }
300 }
301 return _Py_INIT_OK();
302 }
303
304
305 /* gotlandmark only called by search_for_prefix, which ensures
306 'prefix' is null terminated in bounds. join() ensures
307 'landmark' can not overflow prefix if too long. */
308 static int
gotlandmark(wchar_t * prefix,const wchar_t * landmark)309 gotlandmark(wchar_t *prefix, const wchar_t *landmark)
310 {
311 int ok;
312 Py_ssize_t n = wcsnlen_s(prefix, MAXPATHLEN);
313
314 join(prefix, landmark);
315 ok = ismodule(prefix, FALSE);
316 prefix[n] = '\0';
317 return ok;
318 }
319
320
321 /* assumes argv0_path is MAXPATHLEN+1 bytes long, already \0 term'd.
322 assumption provided by only caller, calculate_path_impl() */
323 static int
search_for_prefix(wchar_t * prefix,const wchar_t * argv0_path,const wchar_t * landmark)324 search_for_prefix(wchar_t *prefix, const wchar_t *argv0_path, const wchar_t *landmark)
325 {
326 /* Search from argv0_path, until landmark is found */
327 wcscpy_s(prefix, MAXPATHLEN + 1, argv0_path);
328 do {
329 if (gotlandmark(prefix, landmark)) {
330 return 1;
331 }
332 reduce(prefix);
333 } while (prefix[0]);
334 return 0;
335 }
336
337
338 #ifdef Py_ENABLE_SHARED
339
340 /* a string loaded from the DLL at startup.*/
341 extern const char *PyWin_DLLVersionString;
342
343 /* Load a PYTHONPATH value from the registry.
344 Load from either HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER.
345
346 Works in both Unicode and 8bit environments. Only uses the
347 Ex family of functions so it also works with Windows CE.
348
349 Returns NULL, or a pointer that should be freed.
350
351 XXX - this code is pretty strange, as it used to also
352 work on Win16, where the buffer sizes werent available
353 in advance. It could be simplied now Win16/Win32s is dead!
354 */
355 static wchar_t *
getpythonregpath(HKEY keyBase,int skipcore)356 getpythonregpath(HKEY keyBase, int skipcore)
357 {
358 HKEY newKey = 0;
359 DWORD dataSize = 0;
360 DWORD numKeys = 0;
361 LONG rc;
362 wchar_t *retval = NULL;
363 WCHAR *dataBuf = NULL;
364 static const WCHAR keyPrefix[] = L"Software\\Python\\PythonCore\\";
365 static const WCHAR keySuffix[] = L"\\PythonPath";
366 size_t versionLen, keyBufLen;
367 DWORD index;
368 WCHAR *keyBuf = NULL;
369 WCHAR *keyBufPtr;
370 WCHAR **ppPaths = NULL;
371
372 /* Tried to use sysget("winver") but here is too early :-( */
373 versionLen = strlen(PyWin_DLLVersionString);
374 /* Space for all the chars, plus one \0 */
375 keyBufLen = sizeof(keyPrefix) +
376 sizeof(WCHAR)*(versionLen-1) +
377 sizeof(keySuffix);
378 keyBuf = keyBufPtr = PyMem_RawMalloc(keyBufLen);
379 if (keyBuf==NULL) {
380 goto done;
381 }
382
383 memcpy_s(keyBufPtr, keyBufLen, keyPrefix, sizeof(keyPrefix)-sizeof(WCHAR));
384 keyBufPtr += Py_ARRAY_LENGTH(keyPrefix) - 1;
385 mbstowcs(keyBufPtr, PyWin_DLLVersionString, versionLen);
386 keyBufPtr += versionLen;
387 /* NULL comes with this one! */
388 memcpy(keyBufPtr, keySuffix, sizeof(keySuffix));
389 /* Open the root Python key */
390 rc=RegOpenKeyExW(keyBase,
391 keyBuf, /* subkey */
392 0, /* reserved */
393 KEY_READ,
394 &newKey);
395 if (rc!=ERROR_SUCCESS) {
396 goto done;
397 }
398 /* Find out how big our core buffer is, and how many subkeys we have */
399 rc = RegQueryInfoKey(newKey, NULL, NULL, NULL, &numKeys, NULL, NULL,
400 NULL, NULL, &dataSize, NULL, NULL);
401 if (rc!=ERROR_SUCCESS) {
402 goto done;
403 }
404 if (skipcore) {
405 dataSize = 0; /* Only count core ones if we want them! */
406 }
407 /* Allocate a temp array of char buffers, so we only need to loop
408 reading the registry once
409 */
410 ppPaths = PyMem_RawMalloc( sizeof(WCHAR *) * numKeys );
411 if (ppPaths==NULL) {
412 goto done;
413 }
414 memset(ppPaths, 0, sizeof(WCHAR *) * numKeys);
415 /* Loop over all subkeys, allocating a temp sub-buffer. */
416 for(index=0;index<numKeys;index++) {
417 WCHAR keyBuf[MAX_PATH+1];
418 HKEY subKey = 0;
419 DWORD reqdSize = MAX_PATH+1;
420 /* Get the sub-key name */
421 DWORD rc = RegEnumKeyExW(newKey, index, keyBuf, &reqdSize,
422 NULL, NULL, NULL, NULL );
423 if (rc!=ERROR_SUCCESS) {
424 goto done;
425 }
426 /* Open the sub-key */
427 rc=RegOpenKeyExW(newKey,
428 keyBuf, /* subkey */
429 0, /* reserved */
430 KEY_READ,
431 &subKey);
432 if (rc!=ERROR_SUCCESS) {
433 goto done;
434 }
435 /* Find the value of the buffer size, malloc, then read it */
436 RegQueryValueExW(subKey, NULL, 0, NULL, NULL, &reqdSize);
437 if (reqdSize) {
438 ppPaths[index] = PyMem_RawMalloc(reqdSize);
439 if (ppPaths[index]) {
440 RegQueryValueExW(subKey, NULL, 0, NULL,
441 (LPBYTE)ppPaths[index],
442 &reqdSize);
443 dataSize += reqdSize + 1; /* 1 for the ";" */
444 }
445 }
446 RegCloseKey(subKey);
447 }
448
449 /* return null if no path to return */
450 if (dataSize == 0) {
451 goto done;
452 }
453
454 /* original datasize from RegQueryInfo doesn't include the \0 */
455 dataBuf = PyMem_RawMalloc((dataSize+1) * sizeof(WCHAR));
456 if (dataBuf) {
457 WCHAR *szCur = dataBuf;
458 /* Copy our collected strings */
459 for (index=0;index<numKeys;index++) {
460 if (index > 0) {
461 *(szCur++) = L';';
462 dataSize--;
463 }
464 if (ppPaths[index]) {
465 Py_ssize_t len = wcslen(ppPaths[index]);
466 wcsncpy(szCur, ppPaths[index], len);
467 szCur += len;
468 assert(dataSize > (DWORD)len);
469 dataSize -= (DWORD)len;
470 }
471 }
472 if (skipcore) {
473 *szCur = '\0';
474 }
475 else {
476 /* If we have no values, we don't need a ';' */
477 if (numKeys) {
478 *(szCur++) = L';';
479 dataSize--;
480 }
481 /* Now append the core path entries -
482 this will include the NULL
483 */
484 rc = RegQueryValueExW(newKey, NULL, 0, NULL,
485 (LPBYTE)szCur, &dataSize);
486 if (rc != ERROR_SUCCESS) {
487 PyMem_RawFree(dataBuf);
488 goto done;
489 }
490 }
491 /* And set the result - caller must free */
492 retval = dataBuf;
493 }
494 done:
495 /* Loop freeing my temp buffers */
496 if (ppPaths) {
497 for(index=0; index<numKeys; index++)
498 PyMem_RawFree(ppPaths[index]);
499 PyMem_RawFree(ppPaths);
500 }
501 if (newKey) {
502 RegCloseKey(newKey);
503 }
504 PyMem_RawFree(keyBuf);
505 return retval;
506 }
507 #endif /* Py_ENABLE_SHARED */
508
509
510 static _PyInitError
get_dll_path(PyCalculatePath * calculate,_PyPathConfig * config)511 get_dll_path(PyCalculatePath *calculate, _PyPathConfig *config)
512 {
513 wchar_t dll_path[MAXPATHLEN+1];
514 memset(dll_path, 0, sizeof(dll_path));
515
516 #ifdef Py_ENABLE_SHARED
517 extern HANDLE PyWin_DLLhModule;
518 if (PyWin_DLLhModule) {
519 if (!GetModuleFileNameW(PyWin_DLLhModule, dll_path, MAXPATHLEN)) {
520 dll_path[0] = 0;
521 }
522 }
523 #else
524 dll_path[0] = 0;
525 #endif
526
527 config->dll_path = _PyMem_RawWcsdup(dll_path);
528 if (config->dll_path == NULL) {
529 return _Py_INIT_NO_MEMORY();
530 }
531 return _Py_INIT_OK();
532 }
533
534
535 static _PyInitError
get_program_full_path(const _PyCoreConfig * core_config,PyCalculatePath * calculate,_PyPathConfig * config)536 get_program_full_path(const _PyCoreConfig *core_config,
537 PyCalculatePath *calculate, _PyPathConfig *config)
538 {
539 const wchar_t *pyvenv_launcher;
540 wchar_t program_full_path[MAXPATHLEN+1];
541 memset(program_full_path, 0, sizeof(program_full_path));
542
543 /* The launcher may need to force the executable path to a
544 * different environment, so override it here. */
545 pyvenv_launcher = _wgetenv(L"__PYVENV_LAUNCHER__");
546 if (pyvenv_launcher && pyvenv_launcher[0]) {
547 wcscpy_s(program_full_path, MAXPATHLEN+1, pyvenv_launcher);
548 } else if (!GetModuleFileNameW(NULL, program_full_path, MAXPATHLEN)) {
549 /* GetModuleFileName should never fail when passed NULL */
550 return _Py_INIT_ERR("Cannot determine program path");
551 }
552
553 config->program_full_path = PyMem_RawMalloc(
554 sizeof(wchar_t) * (MAXPATHLEN + 1));
555
556 return canonicalize(config->program_full_path,
557 program_full_path);
558 }
559
560
561 static int
read_pth_file(_PyPathConfig * config,wchar_t * prefix,const wchar_t * path,int * isolated,int * nosite)562 read_pth_file(_PyPathConfig *config, wchar_t *prefix, const wchar_t *path,
563 int *isolated, int *nosite)
564 {
565 FILE *sp_file = _Py_wfopen(path, L"r");
566 if (sp_file == NULL) {
567 return 0;
568 }
569
570 wcscpy_s(prefix, MAXPATHLEN+1, path);
571 reduce(prefix);
572 *isolated = 1;
573 *nosite = 1;
574
575 size_t bufsiz = MAXPATHLEN;
576 size_t prefixlen = wcslen(prefix);
577
578 wchar_t *buf = (wchar_t*)PyMem_RawMalloc(bufsiz * sizeof(wchar_t));
579 if (buf == NULL) {
580 goto error;
581 }
582 buf[0] = '\0';
583
584 while (!feof(sp_file)) {
585 char line[MAXPATHLEN + 1];
586 char *p = fgets(line, MAXPATHLEN + 1, sp_file);
587 if (!p) {
588 break;
589 }
590 if (*p == '\0' || *p == '\r' || *p == '\n' || *p == '#') {
591 continue;
592 }
593 while (*++p) {
594 if (*p == '\r' || *p == '\n') {
595 *p = '\0';
596 break;
597 }
598 }
599
600 if (strcmp(line, "import site") == 0) {
601 *nosite = 0;
602 continue;
603 } else if (strncmp(line, "import ", 7) == 0) {
604 Py_FatalError("only 'import site' is supported in ._pth file");
605 }
606
607 DWORD wn = MultiByteToWideChar(CP_UTF8, 0, line, -1, NULL, 0);
608 wchar_t *wline = (wchar_t*)PyMem_RawMalloc((wn + 1) * sizeof(wchar_t));
609 if (wline == NULL) {
610 goto error;
611 }
612 wn = MultiByteToWideChar(CP_UTF8, 0, line, -1, wline, wn + 1);
613 wline[wn] = '\0';
614
615 size_t usedsiz = wcslen(buf);
616 while (usedsiz + wn + prefixlen + 4 > bufsiz) {
617 bufsiz += MAXPATHLEN;
618 wchar_t *tmp = (wchar_t*)PyMem_RawRealloc(buf, (bufsiz + 1) *
619 sizeof(wchar_t));
620 if (tmp == NULL) {
621 PyMem_RawFree(wline);
622 goto error;
623 }
624 buf = tmp;
625 }
626
627 if (usedsiz) {
628 wcscat_s(buf, bufsiz, L";");
629 usedsiz += 1;
630 }
631
632 errno_t result;
633 _Py_BEGIN_SUPPRESS_IPH
634 result = wcscat_s(buf, bufsiz, prefix);
635 _Py_END_SUPPRESS_IPH
636 if (result == EINVAL) {
637 Py_FatalError("invalid argument during ._pth processing");
638 } else if (result == ERANGE) {
639 Py_FatalError("buffer overflow during ._pth processing");
640 }
641 wchar_t *b = &buf[usedsiz];
642 join(b, wline);
643
644 PyMem_RawFree(wline);
645 }
646
647 fclose(sp_file);
648 config->module_search_path = buf;
649 return 1;
650
651 error:
652 PyMem_RawFree(buf);
653 fclose(sp_file);
654 return 0;
655 }
656
657
658 static void
calculate_init(PyCalculatePath * calculate,const _PyCoreConfig * core_config)659 calculate_init(PyCalculatePath *calculate,
660 const _PyCoreConfig *core_config)
661 {
662 calculate->home = core_config->home;
663 calculate->path_env = _wgetenv(L"PATH");
664 }
665
666
667 static int
get_pth_filename(wchar_t * spbuffer,_PyPathConfig * config)668 get_pth_filename(wchar_t *spbuffer, _PyPathConfig *config)
669 {
670 if (config->dll_path[0]) {
671 if (!change_ext(spbuffer, config->dll_path, L"._pth") &&
672 exists(spbuffer))
673 {
674 return 1;
675 }
676 }
677 if (config->program_full_path[0]) {
678 if (!change_ext(spbuffer, config->program_full_path, L"._pth") &&
679 exists(spbuffer))
680 {
681 return 1;
682 }
683 }
684 return 0;
685 }
686
687
688 static int
calculate_pth_file(_PyPathConfig * config,wchar_t * prefix)689 calculate_pth_file(_PyPathConfig *config, wchar_t *prefix)
690 {
691 wchar_t spbuffer[MAXPATHLEN+1];
692
693 if (!get_pth_filename(spbuffer, config)) {
694 return 0;
695 }
696
697 /* FIXME, bpo-32030: Global configuration variables should not be modified
698 here, _PyPathConfig_Init() is called early in Python initialization:
699 see pymain_cmdline(). */
700 return read_pth_file(config, prefix, spbuffer,
701 &Py_IsolatedFlag, &Py_NoSiteFlag);
702 }
703
704
705 /* Search for an environment configuration file, first in the
706 executable's directory and then in the parent directory.
707 If found, open it for use when searching for prefixes.
708 */
709 static void
calculate_pyvenv_file(PyCalculatePath * calculate)710 calculate_pyvenv_file(PyCalculatePath *calculate)
711 {
712 wchar_t envbuffer[MAXPATHLEN+1];
713 const wchar_t *env_cfg = L"pyvenv.cfg";
714
715 wcscpy_s(envbuffer, MAXPATHLEN+1, calculate->argv0_path);
716 join(envbuffer, env_cfg);
717
718 FILE *env_file = _Py_wfopen(envbuffer, L"r");
719 if (env_file == NULL) {
720 errno = 0;
721
722 reduce(envbuffer);
723 reduce(envbuffer);
724 join(envbuffer, env_cfg);
725
726 env_file = _Py_wfopen(envbuffer, L"r");
727 if (env_file == NULL) {
728 errno = 0;
729 }
730 }
731
732 if (env_file == NULL) {
733 return;
734 }
735
736 /* Look for a 'home' variable and set argv0_path to it, if found */
737 wchar_t tmpbuffer[MAXPATHLEN+1];
738 if (_Py_FindEnvConfigValue(env_file, L"home", tmpbuffer, MAXPATHLEN)) {
739 wcscpy_s(calculate->argv0_path, MAXPATHLEN+1, tmpbuffer);
740 }
741 fclose(env_file);
742 }
743
744
745 #define INIT_ERR_BUFFER_OVERFLOW() _Py_INIT_ERR("buffer overflow")
746
747
748 static void
calculate_home_prefix(PyCalculatePath * calculate,wchar_t * prefix)749 calculate_home_prefix(PyCalculatePath *calculate, wchar_t *prefix)
750 {
751 if (calculate->home == NULL || *calculate->home == '\0') {
752 if (calculate->zip_path[0] && exists(calculate->zip_path)) {
753 wcscpy_s(prefix, MAXPATHLEN+1, calculate->zip_path);
754 reduce(prefix);
755 calculate->home = prefix;
756 }
757 else if (search_for_prefix(prefix, calculate->argv0_path, LANDMARK)) {
758 calculate->home = prefix;
759 }
760 else {
761 calculate->home = NULL;
762 }
763 }
764 else {
765 wcscpy_s(prefix, MAXPATHLEN+1, calculate->home);
766 }
767 }
768
769
770 static _PyInitError
calculate_module_search_path(const _PyCoreConfig * core_config,PyCalculatePath * calculate,_PyPathConfig * config,wchar_t * prefix)771 calculate_module_search_path(const _PyCoreConfig *core_config,
772 PyCalculatePath *calculate, _PyPathConfig *config,
773 wchar_t *prefix)
774 {
775 int skiphome = calculate->home==NULL ? 0 : 1;
776 #ifdef Py_ENABLE_SHARED
777 calculate->machine_path = getpythonregpath(HKEY_LOCAL_MACHINE, skiphome);
778 calculate->user_path = getpythonregpath(HKEY_CURRENT_USER, skiphome);
779 #endif
780 /* We only use the default relative PYTHONPATH if we haven't
781 anything better to use! */
782 int skipdefault = (core_config->module_search_path_env != NULL ||
783 calculate->home != NULL ||
784 calculate->machine_path != NULL ||
785 calculate->user_path != NULL);
786
787 /* We need to construct a path from the following parts.
788 (1) the PYTHONPATH environment variable, if set;
789 (2) for Win32, the zip archive file path;
790 (3) for Win32, the machine_path and user_path, if set;
791 (4) the PYTHONPATH config macro, with the leading "."
792 of each component replaced with home, if set;
793 (5) the directory containing the executable (argv0_path).
794 The length calculation calculates #4 first.
795 Extra rules:
796 - If PYTHONHOME is set (in any way) item (3) is ignored.
797 - If registry values are used, (4) and (5) are ignored.
798 */
799
800 /* Calculate size of return buffer */
801 size_t bufsz = 0;
802 if (calculate->home != NULL) {
803 const wchar_t *p;
804 bufsz = 1;
805 for (p = PYTHONPATH; *p; p++) {
806 if (*p == DELIM) {
807 bufsz++; /* number of DELIM plus one */
808 }
809 }
810 bufsz *= wcslen(calculate->home);
811 }
812 bufsz += wcslen(PYTHONPATH) + 1;
813 bufsz += wcslen(calculate->argv0_path) + 1;
814 if (calculate->user_path) {
815 bufsz += wcslen(calculate->user_path) + 1;
816 }
817 if (calculate->machine_path) {
818 bufsz += wcslen(calculate->machine_path) + 1;
819 }
820 bufsz += wcslen(calculate->zip_path) + 1;
821 if (core_config->module_search_path_env != NULL) {
822 bufsz += wcslen(core_config->module_search_path_env) + 1;
823 }
824
825 wchar_t *buf, *start_buf;
826 buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t));
827 if (buf == NULL) {
828 /* We can't exit, so print a warning and limp along */
829 fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n");
830 if (core_config->module_search_path_env) {
831 fprintf(stderr, "Using environment $PYTHONPATH.\n");
832 config->module_search_path = core_config->module_search_path_env;
833 }
834 else {
835 fprintf(stderr, "Using default static path.\n");
836 config->module_search_path = PYTHONPATH;
837 }
838 return _Py_INIT_OK();
839 }
840 start_buf = buf;
841
842 if (core_config->module_search_path_env) {
843 if (wcscpy_s(buf, bufsz - (buf - start_buf),
844 core_config->module_search_path_env)) {
845 return INIT_ERR_BUFFER_OVERFLOW();
846 }
847 buf = wcschr(buf, L'\0');
848 *buf++ = DELIM;
849 }
850 if (calculate->zip_path[0]) {
851 if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->zip_path)) {
852 return INIT_ERR_BUFFER_OVERFLOW();
853 }
854 buf = wcschr(buf, L'\0');
855 *buf++ = DELIM;
856 }
857 if (calculate->user_path) {
858 if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->user_path)) {
859 return INIT_ERR_BUFFER_OVERFLOW();
860 }
861 buf = wcschr(buf, L'\0');
862 *buf++ = DELIM;
863 }
864 if (calculate->machine_path) {
865 if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->machine_path)) {
866 return INIT_ERR_BUFFER_OVERFLOW();
867 }
868 buf = wcschr(buf, L'\0');
869 *buf++ = DELIM;
870 }
871 if (calculate->home == NULL) {
872 if (!skipdefault) {
873 if (wcscpy_s(buf, bufsz - (buf - start_buf), PYTHONPATH)) {
874 return INIT_ERR_BUFFER_OVERFLOW();
875 }
876 buf = wcschr(buf, L'\0');
877 *buf++ = DELIM;
878 }
879 } else {
880 const wchar_t *p = PYTHONPATH;
881 const wchar_t *q;
882 size_t n;
883 for (;;) {
884 q = wcschr(p, DELIM);
885 if (q == NULL) {
886 n = wcslen(p);
887 }
888 else {
889 n = q-p;
890 }
891 if (p[0] == '.' && is_sep(p[1])) {
892 if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->home)) {
893 return INIT_ERR_BUFFER_OVERFLOW();
894 }
895 buf = wcschr(buf, L'\0');
896 p++;
897 n--;
898 }
899 wcsncpy(buf, p, n);
900 buf += n;
901 *buf++ = DELIM;
902 if (q == NULL) {
903 break;
904 }
905 p = q+1;
906 }
907 }
908 if (calculate->argv0_path) {
909 wcscpy(buf, calculate->argv0_path);
910 buf = wcschr(buf, L'\0');
911 *buf++ = DELIM;
912 }
913 *(buf - 1) = L'\0';
914
915 /* Now to pull one last hack/trick. If sys.prefix is
916 empty, then try and find it somewhere on the paths
917 we calculated. We scan backwards, as our general policy
918 is that Python core directories are at the *end* of
919 sys.path. We assume that our "lib" directory is
920 on the path, and that our 'prefix' directory is
921 the parent of that.
922 */
923 if (prefix[0] == L'\0') {
924 wchar_t lookBuf[MAXPATHLEN+1];
925 const wchar_t *look = buf - 1; /* 'buf' is at the end of the buffer */
926 while (1) {
927 Py_ssize_t nchars;
928 const wchar_t *lookEnd = look;
929 /* 'look' will end up one character before the
930 start of the path in question - even if this
931 is one character before the start of the buffer
932 */
933 while (look >= start_buf && *look != DELIM)
934 look--;
935 nchars = lookEnd-look;
936 wcsncpy(lookBuf, look+1, nchars);
937 lookBuf[nchars] = L'\0';
938 /* Up one level to the parent */
939 reduce(lookBuf);
940 if (search_for_prefix(prefix, lookBuf, LANDMARK)) {
941 break;
942 }
943 /* If we are out of paths to search - give up */
944 if (look < start_buf) {
945 break;
946 }
947 look--;
948 }
949 }
950
951 config->module_search_path = start_buf;
952 return _Py_INIT_OK();
953 }
954
955
956 static _PyInitError
calculate_path_impl(const _PyCoreConfig * core_config,PyCalculatePath * calculate,_PyPathConfig * config)957 calculate_path_impl(const _PyCoreConfig *core_config,
958 PyCalculatePath *calculate, _PyPathConfig *config)
959 {
960 _PyInitError err;
961
962 err = get_dll_path(calculate, config);
963 if (_Py_INIT_FAILED(err)) {
964 return err;
965 }
966
967 err = get_program_full_path(core_config, calculate, config);
968 if (_Py_INIT_FAILED(err)) {
969 return err;
970 }
971
972 /* program_full_path guaranteed \0 terminated in MAXPATH+1 bytes. */
973 wcscpy_s(calculate->argv0_path, MAXPATHLEN+1, config->program_full_path);
974 reduce(calculate->argv0_path);
975
976 wchar_t prefix[MAXPATHLEN+1];
977 memset(prefix, 0, sizeof(prefix));
978
979 /* Search for a sys.path file */
980 if (calculate_pth_file(config, prefix)) {
981 goto done;
982 }
983
984 calculate_pyvenv_file(calculate);
985
986 /* Calculate zip archive path from DLL or exe path */
987 change_ext(calculate->zip_path,
988 config->dll_path[0] ? config->dll_path : config->program_full_path,
989 L".zip");
990
991 calculate_home_prefix(calculate, prefix);
992
993 err = calculate_module_search_path(core_config, calculate, config, prefix);
994 if (_Py_INIT_FAILED(err)) {
995 return err;
996 }
997
998 done:
999 config->prefix = _PyMem_RawWcsdup(prefix);
1000 if (config->prefix == NULL) {
1001 return _Py_INIT_NO_MEMORY();
1002 }
1003
1004 return _Py_INIT_OK();
1005 }
1006
1007
1008 static void
calculate_free(PyCalculatePath * calculate)1009 calculate_free(PyCalculatePath *calculate)
1010 {
1011 PyMem_RawFree(calculate->machine_path);
1012 PyMem_RawFree(calculate->user_path);
1013 }
1014
1015
1016 _PyInitError
_PyPathConfig_Calculate(_PyPathConfig * config,const _PyCoreConfig * core_config)1017 _PyPathConfig_Calculate(_PyPathConfig *config, const _PyCoreConfig *core_config)
1018 {
1019 PyCalculatePath calculate;
1020 memset(&calculate, 0, sizeof(calculate));
1021
1022 calculate_init(&calculate, core_config);
1023
1024 _PyInitError err = calculate_path_impl(core_config, &calculate, config);
1025 if (_Py_INIT_FAILED(err)) {
1026 goto done;
1027 }
1028
1029 err = _Py_INIT_OK();
1030
1031 done:
1032 calculate_free(&calculate);
1033 return err;
1034 }
1035
1036
1037 /* Load python3.dll before loading any extension module that might refer
1038 to it. That way, we can be sure that always the python3.dll corresponding
1039 to this python DLL is loaded, not a python3.dll that might be on the path
1040 by chance.
1041 Return whether the DLL was found.
1042 */
1043 static int python3_checked = 0;
1044 static HANDLE hPython3;
1045 int
_Py_CheckPython3(void)1046 _Py_CheckPython3(void)
1047 {
1048 wchar_t py3path[MAXPATHLEN+1];
1049 wchar_t *s;
1050 if (python3_checked) {
1051 return hPython3 != NULL;
1052 }
1053 python3_checked = 1;
1054
1055 /* If there is a python3.dll next to the python3y.dll,
1056 assume this is a build tree; use that DLL */
1057 wcscpy(py3path, _Py_path_config.dll_path);
1058 s = wcsrchr(py3path, L'\\');
1059 if (!s) {
1060 s = py3path;
1061 }
1062 wcscpy(s, L"\\python3.dll");
1063 hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
1064 if (hPython3 != NULL) {
1065 return 1;
1066 }
1067
1068 /* Check sys.prefix\DLLs\python3.dll */
1069 wcscpy(py3path, Py_GetPrefix());
1070 wcscat(py3path, L"\\DLLs\\python3.dll");
1071 hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
1072 return hPython3 != NULL;
1073 }
1074