blob: fd5cfa7e1a8a3fc160319fa611579f3aca50c763 [file] [log] [blame]
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +00001
2/* Return the initial module search path. */
Jesus Ceaf1af7052012-10-05 02:48:46 +02003/* Used by DOS, Windows 3.1, Windows 95/98, Windows NT. */
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +00004
Guido van Rossum88716bb2000-03-30 19:45:39 +00005/* ----------------------------------------------------------------
6 PATH RULES FOR WINDOWS:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00007 This describes how sys.path is formed on Windows. It describes the
8 functionality, not the implementation (ie, the order in which these
Steve Dowered51b262016-09-17 12:54:06 -07009 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.
Guido van Rossum88716bb2000-03-30 19:45:39 +000012
13 * Python always adds an empty entry at the start, which corresponds
14 to the current directory.
15
Georg Brandl7eb4b7d2005-07-22 21:49:32 +000016 * If the PYTHONPATH env. var. exists, its entries are added next.
Guido van Rossum88716bb2000-03-30 19:45:39 +000017
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
Martin Panterfd13c0f2016-09-10 10:45:28 +000028 to try and locate one of our "landmarks" and deduce our home.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000029 - If we DO have a Python Home: The relevant sub-directories (Lib,
Zachary Warec4b53af2016-09-09 17:59:49 -070030 DLLs, etc) are based on the Python Home
Guido van Rossum88716bb2000-03-30 19:45:39 +000031 - If we DO NOT have a Python Home, the core Python Path is
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000032 loaded from the registry. This is the main PythonPath key,
Guido van Rossum88716bb2000-03-30 19:45:39 +000033 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_
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000037 we can assume is a good path), a default path with relative entries is
Zachary Warec4b53af2016-09-09 17:59:49 -070038 used (eg. .\Lib;.\DLLs, etc)
Guido van Rossum88716bb2000-03-30 19:45:39 +000039
40
Steve Dowered51b262016-09-17 12:54:06 -070041 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
Steve Dower4db86bc2016-09-09 09:17:35 -070056
Guido van Rossum88716bb2000-03-30 19:45:39 +000057 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
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000063 * When Python is hosted in another exe (different directory, embedded via
Guido van Rossum88716bb2000-03-30 19:45:39 +000064 COM, etc), the Python Home will not be deduced, so the core path from
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000065 the registry is used. Other "application paths" in the registry are
Guido van Rossum88716bb2000-03-30 19:45:39 +000066 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
Kristján Valur Jónsson3b69db22010-09-27 05:32:54 +000072 * An embedding application can use Py_SetPath() to override all of
Steve Dower4db86bc2016-09-09 09:17:35 -070073 these automatic path computations.
74
Steve Dowered51b262016-09-17 12:54:06 -070075 * 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.
Kristján Valur Jónsson3b69db22010-09-27 05:32:54 +000078
Guido van Rossum88716bb2000-03-30 19:45:39 +000079 ---------------------------------------------------------------- */
80
81
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +000082#include "Python.h"
Victor Stinner361dcdc2020-04-15 03:24:57 +020083#include "pycore_initconfig.h" // PyStatus
84#include "pycore_pathconfig.h" // _PyPathConfig
85#include "osdefs.h" // SEP, ALTSEP
Martin v. Löwis790465f2008-04-05 20:41:37 +000086#include <wchar.h>
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +000087
Steve Dower4db86bc2016-09-09 09:17:35 -070088#ifndef MS_WINDOWS
89#error getpathp.c should only be built on Windows
Guido van Rossum8f1b6511997-08-13 19:55:43 +000090#endif
91
Steve Dower4db86bc2016-09-09 09:17:35 -070092#include <windows.h>
Steve Dower6a65eba2020-01-29 13:46:33 +110093#include <pathcch.h>
erikjanss6cf82552018-07-25 02:41:46 +020094#include <shlwapi.h>
Steve Dower4db86bc2016-09-09 09:17:35 -070095
Thomas Wouters0e3f5912006-08-11 14:57:12 +000096#ifdef HAVE_SYS_TYPES_H
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +000097#include <sys/types.h>
Thomas Wouters0e3f5912006-08-11 14:57:12 +000098#endif /* HAVE_SYS_TYPES_H */
99
100#ifdef HAVE_SYS_STAT_H
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000101#include <sys/stat.h>
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000102#endif /* HAVE_SYS_STAT_H */
103
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000104#include <string.h>
105
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000106/* Search in some common locations for the associated Python libraries.
107 *
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000108 * Py_GetPath() tries to return a sensible Python module search path.
109 *
Guido van Rossum42a97441998-02-19 21:00:45 +0000110 * The approach is an adaptation for Windows of the strategy used in
111 * ../Modules/getpath.c; it uses the Windows Registry as one of its
112 * information sources.
Kristján Valur Jónsson3b69db22010-09-27 05:32:54 +0000113 *
114 * Py_SetPath() can be used to override this mechanism. Call Py_SetPath
115 * with a semicolon separated path prior to calling Py_Initialize.
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000116 */
117
118#ifndef LANDMARK
Victor Stinner85ce0a72019-09-24 00:55:48 +0200119# define LANDMARK L"lib\\os.py"
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000120#endif
121
Victor Stinner85ce0a72019-09-24 00:55:48 +0200122#define INIT_ERR_BUFFER_OVERFLOW() _PyStatus_ERR("buffer overflow")
123
124
Victor Stinner0327bde2017-11-23 17:03:20 +0100125typedef struct {
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200126 const wchar_t *path_env; /* PATH environment variable */
127 const wchar_t *home; /* PYTHONHOME environment variable */
Victor Stinner0327bde2017-11-23 17:03:20 +0100128
Victor Stinner85ce0a72019-09-24 00:55:48 +0200129 /* Registry key "Software\Python\PythonCore\X.Y\PythonPath"
130 where X.Y is the Python version (major.minor) */
Victor Stinner0327bde2017-11-23 17:03:20 +0100131 wchar_t *machine_path; /* from HKEY_LOCAL_MACHINE */
132 wchar_t *user_path; /* from HKEY_CURRENT_USER */
133
Victor Stinnerc4221672019-09-21 01:02:56 +0200134 wchar_t *dll_path;
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200135
136 const wchar_t *pythonpath_env;
Victor Stinner0327bde2017-11-23 17:03:20 +0100137} PyCalculatePath;
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000138
Guido van Rossumeea14491997-08-13 21:30:44 +0000139
Victor Stinner0327bde2017-11-23 17:03:20 +0100140/* determine if "ch" is a separator character */
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000141static int
Victor Stinner0327bde2017-11-23 17:03:20 +0100142is_sep(wchar_t ch)
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000143{
144#ifdef ALTSEP
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000145 return ch == SEP || ch == ALTSEP;
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000146#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000147 return ch == SEP;
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000148#endif
149}
150
Victor Stinner0327bde2017-11-23 17:03:20 +0100151
Mark Hammond8bf9e3b2000-10-07 11:10:50 +0000152/* assumes 'dir' null terminated in bounds. Never writes
Victor Stinner0327bde2017-11-23 17:03:20 +0100153 beyond existing terminator. */
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000154static void
Martin v. Löwis790465f2008-04-05 20:41:37 +0000155reduce(wchar_t *dir)
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000156{
Steve Dower4a7fe7e2015-05-22 15:10:10 -0700157 size_t i = wcsnlen_s(dir, MAXPATHLEN+1);
Victor Stinner0327bde2017-11-23 17:03:20 +0100158 if (i >= MAXPATHLEN+1) {
Steve Dower4a7fe7e2015-05-22 15:10:10 -0700159 Py_FatalError("buffer overflow in getpathp.c's reduce()");
Victor Stinner0327bde2017-11-23 17:03:20 +0100160 }
Steve Dower4a7fe7e2015-05-22 15:10:10 -0700161
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000162 while (i > 0 && !is_sep(dir[i]))
163 --i;
164 dir[i] = '\0';
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000165}
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000166
Victor Stinner0327bde2017-11-23 17:03:20 +0100167
Steve Dowered51b262016-09-17 12:54:06 -0700168static int
169change_ext(wchar_t *dest, const wchar_t *src, const wchar_t *ext)
170{
171 size_t src_len = wcsnlen_s(src, MAXPATHLEN+1);
172 size_t i = src_len;
Victor Stinner0327bde2017-11-23 17:03:20 +0100173 if (i >= MAXPATHLEN+1) {
Steve Dowered51b262016-09-17 12:54:06 -0700174 Py_FatalError("buffer overflow in getpathp.c's reduce()");
Victor Stinner0327bde2017-11-23 17:03:20 +0100175 }
Steve Dowered51b262016-09-17 12:54:06 -0700176
177 while (i > 0 && src[i] != '.' && !is_sep(src[i]))
178 --i;
179
180 if (i == 0) {
181 dest[0] = '\0';
182 return -1;
183 }
184
Victor Stinner0327bde2017-11-23 17:03:20 +0100185 if (is_sep(src[i])) {
Steve Dowered51b262016-09-17 12:54:06 -0700186 i = src_len;
Victor Stinner0327bde2017-11-23 17:03:20 +0100187 }
Steve Dowered51b262016-09-17 12:54:06 -0700188
189 if (wcsncpy_s(dest, MAXPATHLEN+1, src, i) ||
Victor Stinner0327bde2017-11-23 17:03:20 +0100190 wcscat_s(dest, MAXPATHLEN+1, ext))
191 {
Steve Dowered51b262016-09-17 12:54:06 -0700192 dest[0] = '\0';
193 return -1;
194 }
195
196 return 0;
197}
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000198
Victor Stinner0327bde2017-11-23 17:03:20 +0100199
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000200static int
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200201exists(const wchar_t *filename)
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000202{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000203 return GetFileAttributesW(filename) != 0xFFFFFFFF;
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000204}
205
Victor Stinner0327bde2017-11-23 17:03:20 +0100206
207/* Is module -- check for .pyc too.
208 Assumes 'filename' MAXPATHLEN+1 bytes long -
209 may extend 'filename' by one character. */
Guido van Rossum43ff1141998-08-08 23:40:40 +0000210static int
Victor Stinner0327bde2017-11-23 17:03:20 +0100211ismodule(wchar_t *filename, int update_filename)
Guido van Rossum43ff1141998-08-08 23:40:40 +0000212{
Victor Stinnerccb1f8c2016-03-23 11:31:58 +0100213 size_t n;
Steve Dower4a7fe7e2015-05-22 15:10:10 -0700214
Victor Stinner0327bde2017-11-23 17:03:20 +0100215 if (exists(filename)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000216 return 1;
Victor Stinner0327bde2017-11-23 17:03:20 +0100217 }
Guido van Rossum43ff1141998-08-08 23:40:40 +0000218
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000219 /* Check for the compiled version of prefix. */
Steve Dower4a7fe7e2015-05-22 15:10:10 -0700220 n = wcsnlen_s(filename, MAXPATHLEN+1);
221 if (n < MAXPATHLEN) {
222 int exist = 0;
Xiang Zhang0710d752017-03-11 13:02:52 +0800223 filename[n] = L'c';
Steve Dower4a7fe7e2015-05-22 15:10:10 -0700224 filename[n + 1] = L'\0';
225 exist = exists(filename);
Victor Stinner0327bde2017-11-23 17:03:20 +0100226 if (!update_filename) {
Steve Dower4a7fe7e2015-05-22 15:10:10 -0700227 filename[n] = L'\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100228 }
Steve Dower4a7fe7e2015-05-22 15:10:10 -0700229 return exist;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000230 }
231 return 0;
Guido van Rossum43ff1141998-08-08 23:40:40 +0000232}
233
Victor Stinner0327bde2017-11-23 17:03:20 +0100234
Tim Peters8484fbf2004-08-07 19:12:27 +0000235/* Add a path component, by appending stuff to buffer.
236 buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a
237 NUL-terminated string with no more than MAXPATHLEN characters (not counting
238 the trailing NUL). It's a fatal error if it contains a string longer than
239 that (callers must be careful!). If these requirements are met, it's
240 guaranteed that buffer will still be a NUL-terminated string with no more
241 than MAXPATHLEN characters at exit. If stuff is too long, only as much of
242 stuff as fits will be appended.
243*/
Steve Dower4db86bc2016-09-09 09:17:35 -0700244
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000245static void
Steve Dower4a7fe7e2015-05-22 15:10:10 -0700246join(wchar_t *buffer, const wchar_t *stuff)
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000247{
Steve Dower6a65eba2020-01-29 13:46:33 +1100248 if (FAILED(PathCchCombineEx(buffer, MAXPATHLEN+1, buffer, stuff, 0))) {
249 Py_FatalError("buffer overflow in getpathp.c's join()");
Steve Dower4a7fe7e2015-05-22 15:10:10 -0700250 }
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000251}
252
Victor Stinner85ce0a72019-09-24 00:55:48 +0200253/* Call PathCchCanonicalizeEx(path): remove navigation elements such as "."
254 and ".." to produce a direct, well-formed path. */
255static PyStatus
256canonicalize(wchar_t *buffer, const wchar_t *path)
Steve Dower48e8c822018-02-22 10:39:26 -0800257{
258 if (buffer == NULL) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200259 return _PyStatus_NO_MEMORY();
Steve Dower48e8c822018-02-22 10:39:26 -0800260 }
261
Steve Dower6a65eba2020-01-29 13:46:33 +1100262 if (FAILED(PathCchCanonicalizeEx(buffer, MAXPATHLEN + 1, path, 0))) {
263 return INIT_ERR_BUFFER_OVERFLOW();
Steve Dower48e8c822018-02-22 10:39:26 -0800264 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200265 return _PyStatus_OK();
Steve Dower48e8c822018-02-22 10:39:26 -0800266}
267
Victor Stinner0327bde2017-11-23 17:03:20 +0100268
Mark Hammond8bf9e3b2000-10-07 11:10:50 +0000269/* gotlandmark only called by search_for_prefix, which ensures
270 'prefix' is null terminated in bounds. join() ensures
Victor Stinner0327bde2017-11-23 17:03:20 +0100271 'landmark' can not overflow prefix if too long. */
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000272static int
Victor Stinnerdec39712019-09-30 14:49:34 +0200273gotlandmark(const wchar_t *prefix, const wchar_t *landmark)
Guido van Rossume02e48b2000-03-29 01:49:47 +0000274{
Victor Stinnerdec39712019-09-30 14:49:34 +0200275 wchar_t filename[MAXPATHLEN+1];
276 memset(filename, 0, sizeof(filename));
277 wcscpy_s(filename, Py_ARRAY_LENGTH(filename), prefix);
278 join(filename, landmark);
279 return ismodule(filename, FALSE);
Guido van Rossume02e48b2000-03-29 01:49:47 +0000280}
281
Victor Stinner0327bde2017-11-23 17:03:20 +0100282
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000283/* assumes argv0_path is MAXPATHLEN+1 bytes long, already \0 term'd.
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200284 assumption provided by only caller, calculate_path() */
Guido van Rossume02e48b2000-03-29 01:49:47 +0000285static int
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200286search_for_prefix(wchar_t *prefix, const wchar_t *argv0_path, const wchar_t *landmark)
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000287{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000288 /* Search from argv0_path, until landmark is found */
Steve Dower4a7fe7e2015-05-22 15:10:10 -0700289 wcscpy_s(prefix, MAXPATHLEN + 1, argv0_path);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000290 do {
Victor Stinner0327bde2017-11-23 17:03:20 +0100291 if (gotlandmark(prefix, landmark)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000292 return 1;
Victor Stinner0327bde2017-11-23 17:03:20 +0100293 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000294 reduce(prefix);
295 } while (prefix[0]);
296 return 0;
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000297}
298
Victor Stinner0327bde2017-11-23 17:03:20 +0100299
Martin v. Löwisbc186a82009-02-02 15:32:22 +0000300#ifdef Py_ENABLE_SHARED
Guido van Rossum43ff1141998-08-08 23:40:40 +0000301
Guido van Rossum88716bb2000-03-30 19:45:39 +0000302/* a string loaded from the DLL at startup.*/
303extern const char *PyWin_DLLVersionString;
Guido van Rossum271f9771997-09-29 23:39:31 +0000304
Guido van Rossumeea14491997-08-13 21:30:44 +0000305/* Load a PYTHONPATH value from the registry.
306 Load from either HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER.
307
Guido van Rossum88716bb2000-03-30 19:45:39 +0000308 Works in both Unicode and 8bit environments. Only uses the
309 Ex family of functions so it also works with Windows CE.
310
Guido van Rossumeea14491997-08-13 21:30:44 +0000311 Returns NULL, or a pointer that should be freed.
Mark Hammond5edc6272001-02-23 11:38:38 +0000312
313 XXX - this code is pretty strange, as it used to also
314 work on Win16, where the buffer sizes werent available
315 in advance. It could be simplied now Win16/Win32s is dead!
Guido van Rossumeea14491997-08-13 21:30:44 +0000316*/
Martin v. Löwis790465f2008-04-05 20:41:37 +0000317static wchar_t *
Guido van Rossum88716bb2000-03-30 19:45:39 +0000318getpythonregpath(HKEY keyBase, int skipcore)
Guido van Rossumeea14491997-08-13 21:30:44 +0000319{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000320 HKEY newKey = 0;
321 DWORD dataSize = 0;
322 DWORD numKeys = 0;
323 LONG rc;
324 wchar_t *retval = NULL;
325 WCHAR *dataBuf = NULL;
326 static const WCHAR keyPrefix[] = L"Software\\Python\\PythonCore\\";
327 static const WCHAR keySuffix[] = L"\\PythonPath";
Steve Dower4a7fe7e2015-05-22 15:10:10 -0700328 size_t versionLen, keyBufLen;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000329 DWORD index;
330 WCHAR *keyBuf = NULL;
331 WCHAR *keyBufPtr;
332 WCHAR **ppPaths = NULL;
Guido van Rossum271f9771997-09-29 23:39:31 +0000333
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000334 /* Tried to use sysget("winver") but here is too early :-( */
335 versionLen = strlen(PyWin_DLLVersionString);
336 /* Space for all the chars, plus one \0 */
Steve Dower4a7fe7e2015-05-22 15:10:10 -0700337 keyBufLen = sizeof(keyPrefix) +
338 sizeof(WCHAR)*(versionLen-1) +
339 sizeof(keySuffix);
340 keyBuf = keyBufPtr = PyMem_RawMalloc(keyBufLen);
Victor Stinner0327bde2017-11-23 17:03:20 +0100341 if (keyBuf==NULL) {
342 goto done;
343 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000344
Steve Dower4a7fe7e2015-05-22 15:10:10 -0700345 memcpy_s(keyBufPtr, keyBufLen, keyPrefix, sizeof(keyPrefix)-sizeof(WCHAR));
Victor Stinner63941882011-09-29 00:42:28 +0200346 keyBufPtr += Py_ARRAY_LENGTH(keyPrefix) - 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000347 mbstowcs(keyBufPtr, PyWin_DLLVersionString, versionLen);
348 keyBufPtr += versionLen;
349 /* NULL comes with this one! */
350 memcpy(keyBufPtr, keySuffix, sizeof(keySuffix));
351 /* Open the root Python key */
352 rc=RegOpenKeyExW(keyBase,
353 keyBuf, /* subkey */
354 0, /* reserved */
355 KEY_READ,
356 &newKey);
Victor Stinner0327bde2017-11-23 17:03:20 +0100357 if (rc!=ERROR_SUCCESS) {
358 goto done;
359 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000360 /* Find out how big our core buffer is, and how many subkeys we have */
Minmin Gong98e42d12020-05-18 09:50:03 -0700361 rc = RegQueryInfoKeyW(newKey, NULL, NULL, NULL, &numKeys, NULL, NULL,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000362 NULL, NULL, &dataSize, NULL, NULL);
Victor Stinner0327bde2017-11-23 17:03:20 +0100363 if (rc!=ERROR_SUCCESS) {
364 goto done;
365 }
366 if (skipcore) {
367 dataSize = 0; /* Only count core ones if we want them! */
368 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000369 /* Allocate a temp array of char buffers, so we only need to loop
370 reading the registry once
371 */
Andy Lester7668a8b2020-03-24 23:26:44 -0500372 ppPaths = PyMem_RawCalloc(numKeys, sizeof(WCHAR *));
Victor Stinner0327bde2017-11-23 17:03:20 +0100373 if (ppPaths==NULL) {
374 goto done;
375 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000376 /* Loop over all subkeys, allocating a temp sub-buffer. */
377 for(index=0;index<numKeys;index++) {
378 WCHAR keyBuf[MAX_PATH+1];
379 HKEY subKey = 0;
380 DWORD reqdSize = MAX_PATH+1;
381 /* Get the sub-key name */
382 DWORD rc = RegEnumKeyExW(newKey, index, keyBuf, &reqdSize,
383 NULL, NULL, NULL, NULL );
Victor Stinner0327bde2017-11-23 17:03:20 +0100384 if (rc!=ERROR_SUCCESS) {
385 goto done;
386 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000387 /* Open the sub-key */
388 rc=RegOpenKeyExW(newKey,
389 keyBuf, /* subkey */
390 0, /* reserved */
391 KEY_READ,
392 &subKey);
Victor Stinner0327bde2017-11-23 17:03:20 +0100393 if (rc!=ERROR_SUCCESS) {
394 goto done;
395 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000396 /* Find the value of the buffer size, malloc, then read it */
397 RegQueryValueExW(subKey, NULL, 0, NULL, NULL, &reqdSize);
398 if (reqdSize) {
Victor Stinner1a7425f2013-07-07 16:25:15 +0200399 ppPaths[index] = PyMem_RawMalloc(reqdSize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000400 if (ppPaths[index]) {
401 RegQueryValueExW(subKey, NULL, 0, NULL,
402 (LPBYTE)ppPaths[index],
403 &reqdSize);
404 dataSize += reqdSize + 1; /* 1 for the ";" */
405 }
406 }
407 RegCloseKey(subKey);
408 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000409
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000410 /* return null if no path to return */
Victor Stinner0327bde2017-11-23 17:03:20 +0100411 if (dataSize == 0) {
412 goto done;
413 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000414
415 /* original datasize from RegQueryInfo doesn't include the \0 */
Victor Stinner1a7425f2013-07-07 16:25:15 +0200416 dataBuf = PyMem_RawMalloc((dataSize+1) * sizeof(WCHAR));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000417 if (dataBuf) {
418 WCHAR *szCur = dataBuf;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000419 /* Copy our collected strings */
420 for (index=0;index<numKeys;index++) {
421 if (index > 0) {
422 *(szCur++) = L';';
423 dataSize--;
424 }
425 if (ppPaths[index]) {
426 Py_ssize_t len = wcslen(ppPaths[index]);
427 wcsncpy(szCur, ppPaths[index], len);
428 szCur += len;
429 assert(dataSize > (DWORD)len);
430 dataSize -= (DWORD)len;
431 }
432 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100433 if (skipcore) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000434 *szCur = '\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100435 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000436 else {
luzpaza5293b42017-11-05 07:37:50 -0600437 /* If we have no values, we don't need a ';' */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000438 if (numKeys) {
439 *(szCur++) = L';';
440 dataSize--;
441 }
442 /* Now append the core path entries -
443 this will include the NULL
444 */
445 rc = RegQueryValueExW(newKey, NULL, 0, NULL,
446 (LPBYTE)szCur, &dataSize);
Serhiy Storchakae0cb9da2015-12-18 09:54:19 +0200447 if (rc != ERROR_SUCCESS) {
448 PyMem_RawFree(dataBuf);
449 goto done;
450 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000451 }
452 /* And set the result - caller must free */
453 retval = dataBuf;
454 }
Guido van Rossum88716bb2000-03-30 19:45:39 +0000455done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000456 /* Loop freeing my temp buffers */
457 if (ppPaths) {
Victor Stinner1a7425f2013-07-07 16:25:15 +0200458 for(index=0; index<numKeys; index++)
459 PyMem_RawFree(ppPaths[index]);
460 PyMem_RawFree(ppPaths);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000461 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100462 if (newKey) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000463 RegCloseKey(newKey);
Victor Stinner0327bde2017-11-23 17:03:20 +0100464 }
Victor Stinner1a7425f2013-07-07 16:25:15 +0200465 PyMem_RawFree(keyBuf);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000466 return retval;
Guido van Rossumeea14491997-08-13 21:30:44 +0000467}
Martin v. Löwisbc186a82009-02-02 15:32:22 +0000468#endif /* Py_ENABLE_SHARED */
Guido van Rossumeea14491997-08-13 21:30:44 +0000469
Victor Stinner0327bde2017-11-23 17:03:20 +0100470
Victor Stinner410759f2019-05-18 04:17:01 +0200471wchar_t*
472_Py_GetDLLPath(void)
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000473{
Victor Stinner9316ee42017-11-25 03:17:57 +0100474 wchar_t dll_path[MAXPATHLEN+1];
475 memset(dll_path, 0, sizeof(dll_path));
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000476
Martin v. Löwisbc186a82009-02-02 15:32:22 +0000477#ifdef Py_ENABLE_SHARED
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000478 extern HANDLE PyWin_DLLhModule;
Victor Stinner0327bde2017-11-23 17:03:20 +0100479 if (PyWin_DLLhModule) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100480 if (!GetModuleFileNameW(PyWin_DLLhModule, dll_path, MAXPATHLEN)) {
481 dll_path[0] = 0;
Victor Stinner0327bde2017-11-23 17:03:20 +0100482 }
483 }
Martin v. Löwisbc186a82009-02-02 15:32:22 +0000484#else
Victor Stinner9316ee42017-11-25 03:17:57 +0100485 dll_path[0] = 0;
Martin v. Löwisbc186a82009-02-02 15:32:22 +0000486#endif
Victor Stinner9316ee42017-11-25 03:17:57 +0100487
Victor Stinner410759f2019-05-18 04:17:01 +0200488 return _PyMem_RawWcsdup(dll_path);
Victor Stinner9316ee42017-11-25 03:17:57 +0100489}
490
491
Victor Stinner331a6a52019-05-27 16:39:22 +0200492static PyStatus
Victor Stinnerfcdb0272019-09-23 14:45:47 +0200493get_program_full_path(_PyPathConfig *pathconfig)
Victor Stinner9316ee42017-11-25 03:17:57 +0100494{
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200495 PyStatus status;
Steve Dower1c3de542018-12-10 08:11:21 -0800496 const wchar_t *pyvenv_launcher;
Victor Stinnerb64de462017-12-01 18:27:09 +0100497 wchar_t program_full_path[MAXPATHLEN+1];
498 memset(program_full_path, 0, sizeof(program_full_path));
Victor Stinner9316ee42017-11-25 03:17:57 +0100499
Steve Dower9048c492019-06-29 10:34:11 -0700500 if (!GetModuleFileNameW(NULL, program_full_path, MAXPATHLEN)) {
501 /* GetModuleFileName should never fail when passed NULL */
502 return _PyStatus_ERR("Cannot determine program path");
503 }
504
Steve Dower1c3de542018-12-10 08:11:21 -0800505 /* The launcher may need to force the executable path to a
506 * different environment, so override it here. */
507 pyvenv_launcher = _wgetenv(L"__PYVENV_LAUNCHER__");
508 if (pyvenv_launcher && pyvenv_launcher[0]) {
Steve Dower9048c492019-06-29 10:34:11 -0700509 /* If overridden, preserve the original full path */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200510 if (pathconfig->base_executable == NULL) {
511 pathconfig->base_executable = PyMem_RawMalloc(
512 sizeof(wchar_t) * (MAXPATHLEN + 1));
513 if (pathconfig->base_executable == NULL) {
514 return _PyStatus_NO_MEMORY();
515 }
516
517 status = canonicalize(pathconfig->base_executable,
518 program_full_path);
519 if (_PyStatus_EXCEPTION(status)) {
520 return status;
521 }
Steve Dower9048c492019-06-29 10:34:11 -0700522 }
523
Steve Dower1c3de542018-12-10 08:11:21 -0800524 wcscpy_s(program_full_path, MAXPATHLEN+1, pyvenv_launcher);
Steve Dower9048c492019-06-29 10:34:11 -0700525 /* bpo-35873: Clear the environment variable to avoid it being
526 * inherited by child processes. */
527 _wputenv_s(L"__PYVENV_LAUNCHER__", L"");
Victor Stinner0327bde2017-11-23 17:03:20 +0100528 }
Guido van Rossumeea14491997-08-13 21:30:44 +0000529
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200530 if (pathconfig->program_full_path == NULL) {
531 pathconfig->program_full_path = PyMem_RawMalloc(
532 sizeof(wchar_t) * (MAXPATHLEN + 1));
533 if (pathconfig->program_full_path == NULL) {
534 return _PyStatus_NO_MEMORY();
535 }
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000536
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200537 status = canonicalize(pathconfig->program_full_path,
538 program_full_path);
539 if (_PyStatus_EXCEPTION(status)) {
540 return status;
541 }
542 }
543 return _PyStatus_OK();
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000544}
545
Victor Stinner0327bde2017-11-23 17:03:20 +0100546
Victor Stinner85ce0a72019-09-24 00:55:48 +0200547static PyStatus
548read_pth_file(_PyPathConfig *pathconfig, wchar_t *prefix, const wchar_t *path,
549 int *found)
Steve Dower4db86bc2016-09-09 09:17:35 -0700550{
Victor Stinner85ce0a72019-09-24 00:55:48 +0200551 PyStatus status;
552 wchar_t *buf = NULL;
553 wchar_t *wline = NULL;
554 FILE *sp_file;
555
556 sp_file = _Py_wfopen(path, L"r");
Victor Stinner0327bde2017-11-23 17:03:20 +0100557 if (sp_file == NULL) {
Victor Stinner85ce0a72019-09-24 00:55:48 +0200558 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100559 }
Steve Dower4db86bc2016-09-09 09:17:35 -0700560
Steve Dowered51b262016-09-17 12:54:06 -0700561 wcscpy_s(prefix, MAXPATHLEN+1, path);
562 reduce(prefix);
Victor Stinner331a6a52019-05-27 16:39:22 +0200563 pathconfig->isolated = 1;
564 pathconfig->site_import = 0;
Steve Dowered51b262016-09-17 12:54:06 -0700565
Steve Dower4db86bc2016-09-09 09:17:35 -0700566 size_t bufsiz = MAXPATHLEN;
567 size_t prefixlen = wcslen(prefix);
568
Victor Stinner85ce0a72019-09-24 00:55:48 +0200569 buf = (wchar_t*)PyMem_RawMalloc(bufsiz * sizeof(wchar_t));
Zackery Spytz4c49da02018-12-07 03:11:30 -0700570 if (buf == NULL) {
Victor Stinner85ce0a72019-09-24 00:55:48 +0200571 status = _PyStatus_NO_MEMORY();
572 goto done;
Zackery Spytz4c49da02018-12-07 03:11:30 -0700573 }
Steve Dower4db86bc2016-09-09 09:17:35 -0700574 buf[0] = '\0';
575
576 while (!feof(sp_file)) {
577 char line[MAXPATHLEN + 1];
Victor Stinner85ce0a72019-09-24 00:55:48 +0200578 char *p = fgets(line, Py_ARRAY_LENGTH(line), sp_file);
Victor Stinner0327bde2017-11-23 17:03:20 +0100579 if (!p) {
Steve Dower4db86bc2016-09-09 09:17:35 -0700580 break;
Victor Stinner0327bde2017-11-23 17:03:20 +0100581 }
582 if (*p == '\0' || *p == '\r' || *p == '\n' || *p == '#') {
Steve Dowered51b262016-09-17 12:54:06 -0700583 continue;
Victor Stinner0327bde2017-11-23 17:03:20 +0100584 }
Steve Dowered51b262016-09-17 12:54:06 -0700585 while (*++p) {
586 if (*p == '\r' || *p == '\n') {
587 *p = '\0';
588 break;
589 }
590 }
Steve Dower4db86bc2016-09-09 09:17:35 -0700591
Steve Dowered51b262016-09-17 12:54:06 -0700592 if (strcmp(line, "import site") == 0) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200593 pathconfig->site_import = 1;
Steve Dowered51b262016-09-17 12:54:06 -0700594 continue;
Victor Stinnerf2626ce2018-07-21 03:54:20 +0200595 }
596 else if (strncmp(line, "import ", 7) == 0) {
Victor Stinner85ce0a72019-09-24 00:55:48 +0200597 status = _PyStatus_ERR("only 'import site' is supported "
598 "in ._pth file");
599 goto done;
Steve Dowered51b262016-09-17 12:54:06 -0700600 }
Steve Dower4db86bc2016-09-09 09:17:35 -0700601
Steve Dowered51b262016-09-17 12:54:06 -0700602 DWORD wn = MultiByteToWideChar(CP_UTF8, 0, line, -1, NULL, 0);
Steve Dower4db86bc2016-09-09 09:17:35 -0700603 wchar_t *wline = (wchar_t*)PyMem_RawMalloc((wn + 1) * sizeof(wchar_t));
Zackery Spytz4c49da02018-12-07 03:11:30 -0700604 if (wline == NULL) {
Victor Stinner85ce0a72019-09-24 00:55:48 +0200605 status = _PyStatus_NO_MEMORY();
606 goto done;
Zackery Spytz4c49da02018-12-07 03:11:30 -0700607 }
Steve Dowered51b262016-09-17 12:54:06 -0700608 wn = MultiByteToWideChar(CP_UTF8, 0, line, -1, wline, wn + 1);
Steve Dower4db86bc2016-09-09 09:17:35 -0700609 wline[wn] = '\0';
610
Steve Dowerc6dd4152016-10-27 14:28:07 -0700611 size_t usedsiz = wcslen(buf);
612 while (usedsiz + wn + prefixlen + 4 > bufsiz) {
Steve Dower4db86bc2016-09-09 09:17:35 -0700613 bufsiz += MAXPATHLEN;
Zackery Spytz4c49da02018-12-07 03:11:30 -0700614 wchar_t *tmp = (wchar_t*)PyMem_RawRealloc(buf, (bufsiz + 1) *
615 sizeof(wchar_t));
616 if (tmp == NULL) {
Victor Stinner85ce0a72019-09-24 00:55:48 +0200617 status = _PyStatus_NO_MEMORY();
618 goto done;
Steve Dower4db86bc2016-09-09 09:17:35 -0700619 }
Zackery Spytz4c49da02018-12-07 03:11:30 -0700620 buf = tmp;
Steve Dower4db86bc2016-09-09 09:17:35 -0700621 }
622
Steve Dowerc6dd4152016-10-27 14:28:07 -0700623 if (usedsiz) {
Steve Dower4db86bc2016-09-09 09:17:35 -0700624 wcscat_s(buf, bufsiz, L";");
Steve Dowerc6dd4152016-10-27 14:28:07 -0700625 usedsiz += 1;
626 }
Steve Dowered51b262016-09-17 12:54:06 -0700627
Steve Dowerc6dd4152016-10-27 14:28:07 -0700628 errno_t result;
629 _Py_BEGIN_SUPPRESS_IPH
630 result = wcscat_s(buf, bufsiz, prefix);
631 _Py_END_SUPPRESS_IPH
Victor Stinner85ce0a72019-09-24 00:55:48 +0200632
Steve Dowerc6dd4152016-10-27 14:28:07 -0700633 if (result == EINVAL) {
Victor Stinner85ce0a72019-09-24 00:55:48 +0200634 status = _PyStatus_ERR("invalid argument during ._pth processing");
635 goto done;
Steve Dowerc6dd4152016-10-27 14:28:07 -0700636 } else if (result == ERANGE) {
Victor Stinner85ce0a72019-09-24 00:55:48 +0200637 status = _PyStatus_ERR("buffer overflow during ._pth processing");
638 goto done;
Steve Dowerc6dd4152016-10-27 14:28:07 -0700639 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200640
Steve Dowerc6dd4152016-10-27 14:28:07 -0700641 wchar_t *b = &buf[usedsiz];
Steve Dower4db86bc2016-09-09 09:17:35 -0700642 join(b, wline);
643
644 PyMem_RawFree(wline);
Victor Stinner85ce0a72019-09-24 00:55:48 +0200645 wline = NULL;
Steve Dower4db86bc2016-09-09 09:17:35 -0700646 }
647
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200648 if (pathconfig->module_search_path == NULL) {
649 pathconfig->module_search_path = _PyMem_RawWcsdup(buf);
650 if (pathconfig->module_search_path == NULL) {
Victor Stinner85ce0a72019-09-24 00:55:48 +0200651 status = _PyStatus_NO_MEMORY();
652 goto done;
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200653 }
654 }
Steve Dower4db86bc2016-09-09 09:17:35 -0700655
Victor Stinner85ce0a72019-09-24 00:55:48 +0200656 *found = 1;
657 status = _PyStatus_OK();
658 goto done;
659
660done:
Steve Dower4db86bc2016-09-09 09:17:35 -0700661 PyMem_RawFree(buf);
Victor Stinner85ce0a72019-09-24 00:55:48 +0200662 PyMem_RawFree(wline);
Steve Dower4db86bc2016-09-09 09:17:35 -0700663 fclose(sp_file);
Victor Stinner85ce0a72019-09-24 00:55:48 +0200664 return status;
Victor Stinner0327bde2017-11-23 17:03:20 +0100665}
666
667
668static int
Victor Stinnerc4221672019-09-21 01:02:56 +0200669get_pth_filename(PyCalculatePath *calculate, wchar_t *filename,
670 const _PyPathConfig *pathconfig)
Victor Stinner0327bde2017-11-23 17:03:20 +0100671{
Victor Stinnerc4221672019-09-21 01:02:56 +0200672 if (calculate->dll_path[0]) {
673 if (!change_ext(filename, calculate->dll_path, L"._pth") &&
674 exists(filename))
Victor Stinner31a83932017-12-04 13:39:15 +0100675 {
Victor Stinner0327bde2017-11-23 17:03:20 +0100676 return 1;
677 }
678 }
Victor Stinner331a6a52019-05-27 16:39:22 +0200679 if (pathconfig->program_full_path[0]) {
Victor Stinnerc4221672019-09-21 01:02:56 +0200680 if (!change_ext(filename, pathconfig->program_full_path, L"._pth") &&
681 exists(filename))
Victor Stinner31a83932017-12-04 13:39:15 +0100682 {
Victor Stinner0327bde2017-11-23 17:03:20 +0100683 return 1;
684 }
685 }
686 return 0;
687}
688
689
Victor Stinner85ce0a72019-09-24 00:55:48 +0200690static PyStatus
Victor Stinnerc4221672019-09-21 01:02:56 +0200691calculate_pth_file(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
Victor Stinner85ce0a72019-09-24 00:55:48 +0200692 wchar_t *prefix, int *found)
Victor Stinner0327bde2017-11-23 17:03:20 +0100693{
Victor Stinnerc4221672019-09-21 01:02:56 +0200694 wchar_t filename[MAXPATHLEN+1];
Victor Stinner0327bde2017-11-23 17:03:20 +0100695
Victor Stinnerc4221672019-09-21 01:02:56 +0200696 if (!get_pth_filename(calculate, filename, pathconfig)) {
Victor Stinner85ce0a72019-09-24 00:55:48 +0200697 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100698 }
699
Victor Stinner85ce0a72019-09-24 00:55:48 +0200700 return read_pth_file(pathconfig, prefix, filename, found);
Victor Stinner0327bde2017-11-23 17:03:20 +0100701}
702
703
704/* Search for an environment configuration file, first in the
705 executable's directory and then in the parent directory.
706 If found, open it for use when searching for prefixes.
707*/
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200708static PyStatus
Victor Stinner85ce0a72019-09-24 00:55:48 +0200709calculate_pyvenv_file(PyCalculatePath *calculate,
710 wchar_t *argv0_path, size_t argv0_path_len)
Victor Stinner0327bde2017-11-23 17:03:20 +0100711{
Victor Stinner221fd842019-09-25 02:54:25 +0200712 wchar_t filename[MAXPATHLEN+1];
Victor Stinner0327bde2017-11-23 17:03:20 +0100713 const wchar_t *env_cfg = L"pyvenv.cfg";
714
Victor Stinner221fd842019-09-25 02:54:25 +0200715 /* Filename: <argv0_path_len> / "pyvenv.cfg" */
716 wcscpy_s(filename, MAXPATHLEN+1, argv0_path);
717 join(filename, env_cfg);
Victor Stinner0327bde2017-11-23 17:03:20 +0100718
Victor Stinner221fd842019-09-25 02:54:25 +0200719 FILE *env_file = _Py_wfopen(filename, L"r");
Victor Stinner0327bde2017-11-23 17:03:20 +0100720 if (env_file == NULL) {
721 errno = 0;
Victor Stinner9bee3292017-12-21 16:49:13 +0100722
Victor Stinner221fd842019-09-25 02:54:25 +0200723 /* Filename: <basename(basename(argv0_path_len))> / "pyvenv.cfg" */
724 reduce(filename);
725 reduce(filename);
726 join(filename, env_cfg);
Victor Stinner9bee3292017-12-21 16:49:13 +0100727
Victor Stinner221fd842019-09-25 02:54:25 +0200728 env_file = _Py_wfopen(filename, L"r");
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100729 if (env_file == NULL) {
730 errno = 0;
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200731 return _PyStatus_OK();
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100732 }
733 }
734
Victor Stinner0327bde2017-11-23 17:03:20 +0100735 /* Look for a 'home' variable and set argv0_path to it, if found */
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200736 wchar_t *home = NULL;
737 PyStatus status = _Py_FindEnvConfigValue(env_file, L"home", &home);
738 if (_PyStatus_EXCEPTION(status)) {
739 fclose(env_file);
740 return status;
741 }
742 if (home) {
Victor Stinner221fd842019-09-25 02:54:25 +0200743 wcscpy_s(argv0_path, argv0_path_len, home);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200744 PyMem_RawFree(home);
Victor Stinner0327bde2017-11-23 17:03:20 +0100745 }
746 fclose(env_file);
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200747 return _PyStatus_OK();
Victor Stinner0327bde2017-11-23 17:03:20 +0100748}
749
750
751static void
Victor Stinner85ce0a72019-09-24 00:55:48 +0200752calculate_home_prefix(PyCalculatePath *calculate,
753 const wchar_t *argv0_path,
754 const wchar_t *zip_path,
755 wchar_t *prefix)
Victor Stinner0327bde2017-11-23 17:03:20 +0100756{
Victor Stinner0327bde2017-11-23 17:03:20 +0100757 if (calculate->home == NULL || *calculate->home == '\0') {
Victor Stinner85ce0a72019-09-24 00:55:48 +0200758 if (zip_path[0] && exists(zip_path)) {
759 wcscpy_s(prefix, MAXPATHLEN+1, zip_path);
Victor Stinner9316ee42017-11-25 03:17:57 +0100760 reduce(prefix);
761 calculate->home = prefix;
762 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200763 else if (search_for_prefix(prefix, argv0_path, LANDMARK)) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100764 calculate->home = prefix;
Victor Stinner0327bde2017-11-23 17:03:20 +0100765 }
766 else {
767 calculate->home = NULL;
768 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000769 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100770 else {
Victor Stinner9316ee42017-11-25 03:17:57 +0100771 wcscpy_s(prefix, MAXPATHLEN+1, calculate->home);
Victor Stinner0327bde2017-11-23 17:03:20 +0100772 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100773}
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000774
Victor Stinner9316ee42017-11-25 03:17:57 +0100775
Victor Stinner331a6a52019-05-27 16:39:22 +0200776static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200777calculate_module_search_path(PyCalculatePath *calculate,
778 _PyPathConfig *pathconfig,
Victor Stinner85ce0a72019-09-24 00:55:48 +0200779 const wchar_t *argv0_path,
780 wchar_t *prefix,
781 const wchar_t *zip_path)
Victor Stinner9316ee42017-11-25 03:17:57 +0100782{
Victor Stinner0327bde2017-11-23 17:03:20 +0100783 int skiphome = calculate->home==NULL ? 0 : 1;
Martin v. Löwisbc186a82009-02-02 15:32:22 +0000784#ifdef Py_ENABLE_SHARED
Zackery Spytz676b10512020-03-30 10:04:45 -0600785 if (!Py_IgnoreEnvironmentFlag) {
786 calculate->machine_path = getpythonregpath(HKEY_LOCAL_MACHINE,
787 skiphome);
788 calculate->user_path = getpythonregpath(HKEY_CURRENT_USER, skiphome);
789 }
Martin v. Löwisbc186a82009-02-02 15:32:22 +0000790#endif
luzpaza5293b42017-11-05 07:37:50 -0600791 /* We only use the default relative PYTHONPATH if we haven't
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000792 anything better to use! */
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200793 int skipdefault = (calculate->pythonpath_env != NULL ||
Victor Stinner31a83932017-12-04 13:39:15 +0100794 calculate->home != NULL ||
795 calculate->machine_path != NULL ||
796 calculate->user_path != NULL);
Guido van Rossum43ff1141998-08-08 23:40:40 +0000797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000798 /* We need to construct a path from the following parts.
799 (1) the PYTHONPATH environment variable, if set;
800 (2) for Win32, the zip archive file path;
Victor Stinner0327bde2017-11-23 17:03:20 +0100801 (3) for Win32, the machine_path and user_path, if set;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000802 (4) the PYTHONPATH config macro, with the leading "."
Victor Stinner0327bde2017-11-23 17:03:20 +0100803 of each component replaced with home, if set;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000804 (5) the directory containing the executable (argv0_path).
805 The length calculation calculates #4 first.
806 Extra rules:
807 - If PYTHONHOME is set (in any way) item (3) is ignored.
808 - If registry values are used, (4) and (5) are ignored.
809 */
Guido van Rossumeea14491997-08-13 21:30:44 +0000810
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000811 /* Calculate size of return buffer */
Victor Stinner0327bde2017-11-23 17:03:20 +0100812 size_t bufsz = 0;
813 if (calculate->home != NULL) {
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200814 const wchar_t *p;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000815 bufsz = 1;
816 for (p = PYTHONPATH; *p; p++) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100817 if (*p == DELIM) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000818 bufsz++; /* number of DELIM plus one */
Victor Stinner0327bde2017-11-23 17:03:20 +0100819 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000820 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100821 bufsz *= wcslen(calculate->home);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000822 }
Steve Dowerf64b9d52015-05-23 17:34:50 -0700823 bufsz += wcslen(PYTHONPATH) + 1;
Victor Stinner85ce0a72019-09-24 00:55:48 +0200824 bufsz += wcslen(argv0_path) + 1;
Victor Stinner0327bde2017-11-23 17:03:20 +0100825 if (calculate->user_path) {
826 bufsz += wcslen(calculate->user_path) + 1;
827 }
828 if (calculate->machine_path) {
829 bufsz += wcslen(calculate->machine_path) + 1;
830 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200831 bufsz += wcslen(zip_path) + 1;
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200832 if (calculate->pythonpath_env != NULL) {
833 bufsz += wcslen(calculate->pythonpath_env) + 1;
Victor Stinner0327bde2017-11-23 17:03:20 +0100834 }
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +0000835
Victor Stinner0327bde2017-11-23 17:03:20 +0100836 wchar_t *buf, *start_buf;
837 buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000838 if (buf == NULL) {
Victor Stinner85ce0a72019-09-24 00:55:48 +0200839 return _PyStatus_NO_MEMORY();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000840 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100841 start_buf = buf;
Guido van Rossumeea14491997-08-13 21:30:44 +0000842
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200843 if (calculate->pythonpath_env) {
Victor Stinner31a83932017-12-04 13:39:15 +0100844 if (wcscpy_s(buf, bufsz - (buf - start_buf),
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200845 calculate->pythonpath_env)) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100846 return INIT_ERR_BUFFER_OVERFLOW();
Victor Stinner0327bde2017-11-23 17:03:20 +0100847 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000848 buf = wcschr(buf, L'\0');
849 *buf++ = DELIM;
850 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200851 if (zip_path[0]) {
852 if (wcscpy_s(buf, bufsz - (buf - start_buf), zip_path)) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100853 return INIT_ERR_BUFFER_OVERFLOW();
Victor Stinner0327bde2017-11-23 17:03:20 +0100854 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000855 buf = wcschr(buf, L'\0');
856 *buf++ = DELIM;
857 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100858 if (calculate->user_path) {
859 if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->user_path)) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100860 return INIT_ERR_BUFFER_OVERFLOW();
Victor Stinner0327bde2017-11-23 17:03:20 +0100861 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000862 buf = wcschr(buf, L'\0');
863 *buf++ = DELIM;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000864 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100865 if (calculate->machine_path) {
866 if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->machine_path)) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100867 return INIT_ERR_BUFFER_OVERFLOW();
Victor Stinner0327bde2017-11-23 17:03:20 +0100868 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000869 buf = wcschr(buf, L'\0');
870 *buf++ = DELIM;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000871 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100872 if (calculate->home == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000873 if (!skipdefault) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100874 if (wcscpy_s(buf, bufsz - (buf - start_buf), PYTHONPATH)) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100875 return INIT_ERR_BUFFER_OVERFLOW();
Victor Stinner0327bde2017-11-23 17:03:20 +0100876 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000877 buf = wcschr(buf, L'\0');
Steve Dower4a7fe7e2015-05-22 15:10:10 -0700878 *buf++ = DELIM;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000879 }
Steve Dower4db86bc2016-09-09 09:17:35 -0700880 } else {
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200881 const wchar_t *p = PYTHONPATH;
882 const wchar_t *q;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000883 size_t n;
884 for (;;) {
885 q = wcschr(p, DELIM);
Victor Stinner0327bde2017-11-23 17:03:20 +0100886 if (q == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000887 n = wcslen(p);
Victor Stinner0327bde2017-11-23 17:03:20 +0100888 }
889 else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000890 n = q-p;
Victor Stinner0327bde2017-11-23 17:03:20 +0100891 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000892 if (p[0] == '.' && is_sep(p[1])) {
Victor Stinner0327bde2017-11-23 17:03:20 +0100893 if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->home)) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100894 return INIT_ERR_BUFFER_OVERFLOW();
Victor Stinner0327bde2017-11-23 17:03:20 +0100895 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000896 buf = wcschr(buf, L'\0');
897 p++;
898 n--;
899 }
900 wcsncpy(buf, p, n);
901 buf += n;
Steve Dower4a7fe7e2015-05-22 15:10:10 -0700902 *buf++ = DELIM;
Victor Stinner0327bde2017-11-23 17:03:20 +0100903 if (q == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000904 break;
Victor Stinner0327bde2017-11-23 17:03:20 +0100905 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000906 p = q+1;
907 }
908 }
Victor Stinner85ce0a72019-09-24 00:55:48 +0200909 if (argv0_path) {
910 wcscpy(buf, argv0_path);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000911 buf = wcschr(buf, L'\0');
Steve Dower4a7fe7e2015-05-22 15:10:10 -0700912 *buf++ = DELIM;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000913 }
Steve Dower4a7fe7e2015-05-22 15:10:10 -0700914 *(buf - 1) = L'\0';
Victor Stinner0327bde2017-11-23 17:03:20 +0100915
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000916 /* Now to pull one last hack/trick. If sys.prefix is
917 empty, then try and find it somewhere on the paths
918 we calculated. We scan backwards, as our general policy
919 is that Python core directories are at the *end* of
920 sys.path. We assume that our "lib" directory is
921 on the path, and that our 'prefix' directory is
922 the parent of that.
923 */
Victor Stinner9316ee42017-11-25 03:17:57 +0100924 if (prefix[0] == L'\0') {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000925 wchar_t lookBuf[MAXPATHLEN+1];
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200926 const wchar_t *look = buf - 1; /* 'buf' is at the end of the buffer */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000927 while (1) {
928 Py_ssize_t nchars;
Serhiy Storchaka4ae06c52017-12-12 13:55:04 +0200929 const wchar_t *lookEnd = look;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000930 /* 'look' will end up one character before the
931 start of the path in question - even if this
932 is one character before the start of the buffer
933 */
Victor Stinner0327bde2017-11-23 17:03:20 +0100934 while (look >= start_buf && *look != DELIM)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000935 look--;
936 nchars = lookEnd-look;
937 wcsncpy(lookBuf, look+1, nchars);
938 lookBuf[nchars] = L'\0';
939 /* Up one level to the parent */
940 reduce(lookBuf);
Victor Stinner9316ee42017-11-25 03:17:57 +0100941 if (search_for_prefix(prefix, lookBuf, LANDMARK)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000942 break;
943 }
944 /* If we are out of paths to search - give up */
Victor Stinner0327bde2017-11-23 17:03:20 +0100945 if (look < start_buf) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000946 break;
Victor Stinner0327bde2017-11-23 17:03:20 +0100947 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000948 look--;
949 }
950 }
Victor Stinner0327bde2017-11-23 17:03:20 +0100951
Victor Stinner331a6a52019-05-27 16:39:22 +0200952 pathconfig->module_search_path = start_buf;
953 return _PyStatus_OK();
Victor Stinner9316ee42017-11-25 03:17:57 +0100954}
955
956
Victor Stinner331a6a52019-05-27 16:39:22 +0200957static PyStatus
Victor Stinner9c42f8c2019-09-23 18:47:29 +0200958calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig)
Victor Stinner9316ee42017-11-25 03:17:57 +0100959{
Victor Stinner331a6a52019-05-27 16:39:22 +0200960 PyStatus status;
Victor Stinner9316ee42017-11-25 03:17:57 +0100961
Victor Stinnerfcdb0272019-09-23 14:45:47 +0200962 status = get_program_full_path(pathconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +0200963 if (_PyStatus_EXCEPTION(status)) {
964 return status;
Victor Stinner9316ee42017-11-25 03:17:57 +0100965 }
966
Victor Stinnerb64de462017-12-01 18:27:09 +0100967 /* program_full_path guaranteed \0 terminated in MAXPATH+1 bytes. */
Victor Stinner85ce0a72019-09-24 00:55:48 +0200968 wchar_t argv0_path[MAXPATHLEN+1];
969 memset(argv0_path, 0, sizeof(argv0_path));
970
971 wcscpy_s(argv0_path, MAXPATHLEN+1, pathconfig->program_full_path);
972 reduce(argv0_path);
Victor Stinner9316ee42017-11-25 03:17:57 +0100973
974 wchar_t prefix[MAXPATHLEN+1];
975 memset(prefix, 0, sizeof(prefix));
976
977 /* Search for a sys.path file */
Victor Stinner85ce0a72019-09-24 00:55:48 +0200978 int pth_found = 0;
979 status = calculate_pth_file(calculate, pathconfig, prefix, &pth_found);
980 if (_PyStatus_EXCEPTION(status)) {
981 return status;
982 }
983 if (pth_found) {
Victor Stinner9316ee42017-11-25 03:17:57 +0100984 goto done;
985 }
986
Victor Stinnerc02b41b2019-10-04 19:53:43 +0200987 status = calculate_pyvenv_file(calculate,
988 argv0_path, Py_ARRAY_LENGTH(argv0_path));
989 if (_PyStatus_EXCEPTION(status)) {
990 return status;
991 }
Victor Stinner9316ee42017-11-25 03:17:57 +0100992
993 /* Calculate zip archive path from DLL or exe path */
Victor Stinner85ce0a72019-09-24 00:55:48 +0200994 wchar_t zip_path[MAXPATHLEN+1];
995 memset(zip_path, 0, sizeof(zip_path));
996
997 change_ext(zip_path,
Victor Stinnerc4221672019-09-21 01:02:56 +0200998 calculate->dll_path[0] ? calculate->dll_path : pathconfig->program_full_path,
Victor Stinner9316ee42017-11-25 03:17:57 +0100999 L".zip");
1000
Victor Stinner85ce0a72019-09-24 00:55:48 +02001001 calculate_home_prefix(calculate, argv0_path, zip_path, prefix);
Victor Stinner9316ee42017-11-25 03:17:57 +01001002
Victor Stinnere2677932019-09-21 01:50:16 +02001003 if (pathconfig->module_search_path == NULL) {
Victor Stinner85ce0a72019-09-24 00:55:48 +02001004 status = calculate_module_search_path(calculate, pathconfig,
1005 argv0_path, prefix, zip_path);
Victor Stinnere2677932019-09-21 01:50:16 +02001006 if (_PyStatus_EXCEPTION(status)) {
1007 return status;
1008 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001009 }
1010
1011done:
Victor Stinner331a6a52019-05-27 16:39:22 +02001012 if (pathconfig->prefix == NULL) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001013 pathconfig->prefix = _PyMem_RawWcsdup(prefix);
1014 if (pathconfig->prefix == NULL) {
1015 return _PyStatus_NO_MEMORY();
1016 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001017 }
Victor Stinner331a6a52019-05-27 16:39:22 +02001018 if (pathconfig->exec_prefix == NULL) {
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001019 pathconfig->exec_prefix = _PyMem_RawWcsdup(prefix);
1020 if (pathconfig->exec_prefix == NULL) {
1021 return _PyStatus_NO_MEMORY();
1022 }
Steve Dower177a41a2018-11-17 20:41:48 -08001023 }
Victor Stinner9316ee42017-11-25 03:17:57 +01001024
Victor Stinner331a6a52019-05-27 16:39:22 +02001025 return _PyStatus_OK();
Guido van Rossum1aa7e3a1997-05-19 14:16:21 +00001026}
1027
1028
Victor Stinner85ce0a72019-09-24 00:55:48 +02001029static PyStatus
1030calculate_init(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
1031 const PyConfig *config)
1032{
1033 calculate->home = pathconfig->home;
1034 calculate->path_env = _wgetenv(L"PATH");
1035
1036 calculate->dll_path = _Py_GetDLLPath();
1037 if (calculate->dll_path == NULL) {
1038 return _PyStatus_NO_MEMORY();
1039 }
1040
1041 calculate->pythonpath_env = config->pythonpath_env;
1042
1043 return _PyStatus_OK();
1044}
1045
1046
Victor Stinner0327bde2017-11-23 17:03:20 +01001047static void
1048calculate_free(PyCalculatePath *calculate)
1049{
1050 PyMem_RawFree(calculate->machine_path);
1051 PyMem_RawFree(calculate->user_path);
Victor Stinnerc4221672019-09-21 01:02:56 +02001052 PyMem_RawFree(calculate->dll_path);
Victor Stinner0327bde2017-11-23 17:03:20 +01001053}
1054
Victor Stinner9316ee42017-11-25 03:17:57 +01001055
Victor Stinner85ce0a72019-09-24 00:55:48 +02001056/* Calculate the Python path configuration.
1057
1058 Inputs:
1059
1060 - PyConfig.pythonpath_env: PYTHONPATH environment variable
1061 - _PyPathConfig.home: Py_SetPythonHome() or PYTHONHOME environment variable
1062 - DLL path: _Py_GetDLLPath()
1063 - PATH environment variable
1064 - __PYVENV_LAUNCHER__ environment variable
1065 - GetModuleFileNameW(NULL): fully qualified path of the executable file of
1066 the current process
Victor Stinner8bf39b62019-09-26 02:22:35 +02001067 - ._pth configuration file
Victor Stinner85ce0a72019-09-24 00:55:48 +02001068 - pyvenv.cfg configuration file
1069 - Registry key "Software\Python\PythonCore\X.Y\PythonPath"
Victor Stinner8bf39b62019-09-26 02:22:35 +02001070 of HKEY_CURRENT_USER and HKEY_LOCAL_MACHINE where X.Y is the Python
1071 version.
Victor Stinner85ce0a72019-09-24 00:55:48 +02001072
1073 Outputs, 'pathconfig' fields:
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001074
1075 - base_executable
1076 - program_full_path
1077 - module_search_path
1078 - prefix
1079 - exec_prefix
1080 - isolated
1081 - site_import
1082
Victor Stinner85ce0a72019-09-24 00:55:48 +02001083 If a field is already set (non NULL), it is left unchanged. */
Victor Stinner331a6a52019-05-27 16:39:22 +02001084PyStatus
1085_PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config)
Serhiy Storchaka13badcb2017-12-02 21:36:00 +02001086{
Victor Stinnerc4221672019-09-21 01:02:56 +02001087 PyStatus status;
Victor Stinner0327bde2017-11-23 17:03:20 +01001088 PyCalculatePath calculate;
1089 memset(&calculate, 0, sizeof(calculate));
1090
Victor Stinner85ce0a72019-09-24 00:55:48 +02001091 status = calculate_init(&calculate, pathconfig, config);
Victor Stinner331a6a52019-05-27 16:39:22 +02001092 if (_PyStatus_EXCEPTION(status)) {
Victor Stinner9316ee42017-11-25 03:17:57 +01001093 goto done;
1094 }
1095
Victor Stinner9c42f8c2019-09-23 18:47:29 +02001096 status = calculate_path(&calculate, pathconfig);
Victor Stinner0327bde2017-11-23 17:03:20 +01001097
Victor Stinner9316ee42017-11-25 03:17:57 +01001098done:
Victor Stinner0327bde2017-11-23 17:03:20 +01001099 calculate_free(&calculate);
Victor Stinner331a6a52019-05-27 16:39:22 +02001100 return status;
Victor Stinner0327bde2017-11-23 17:03:20 +01001101}
1102
1103
Victor Stinner63941882011-09-29 00:42:28 +02001104/* Load python3.dll before loading any extension module that might refer
1105 to it. That way, we can be sure that always the python3.dll corresponding
Martin v. Löwis4d0d4712010-12-03 20:14:31 +00001106 to this python DLL is loaded, not a python3.dll that might be on the path
1107 by chance.
1108 Return whether the DLL was found.
1109*/
1110static int python3_checked = 0;
1111static HANDLE hPython3;
1112int
Victor Stinner31a83932017-12-04 13:39:15 +01001113_Py_CheckPython3(void)
Martin v. Löwis4d0d4712010-12-03 20:14:31 +00001114{
1115 wchar_t py3path[MAXPATHLEN+1];
1116 wchar_t *s;
Victor Stinner0327bde2017-11-23 17:03:20 +01001117 if (python3_checked) {
Martin v. Löwis4d0d4712010-12-03 20:14:31 +00001118 return hPython3 != NULL;
Victor Stinner0327bde2017-11-23 17:03:20 +01001119 }
Martin v. Löwis4d0d4712010-12-03 20:14:31 +00001120 python3_checked = 1;
1121
1122 /* If there is a python3.dll next to the python3y.dll,
1123 assume this is a build tree; use that DLL */
Victor Stinnerc4221672019-09-21 01:02:56 +02001124 if (_Py_dll_path != NULL) {
1125 wcscpy(py3path, _Py_dll_path);
1126 }
1127 else {
1128 wcscpy(py3path, L"");
1129 }
Martin v. Löwis4d0d4712010-12-03 20:14:31 +00001130 s = wcsrchr(py3path, L'\\');
Victor Stinner0327bde2017-11-23 17:03:20 +01001131 if (!s) {
Martin v. Löwis4d0d4712010-12-03 20:14:31 +00001132 s = py3path;
Victor Stinner0327bde2017-11-23 17:03:20 +01001133 }
Martin v. Löwis4d0d4712010-12-03 20:14:31 +00001134 wcscpy(s, L"\\python3.dll");
1135 hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
Victor Stinner0327bde2017-11-23 17:03:20 +01001136 if (hPython3 != NULL) {
Martin v. Löwis4d0d4712010-12-03 20:14:31 +00001137 return 1;
Victor Stinner0327bde2017-11-23 17:03:20 +01001138 }
Martin v. Löwis4d0d4712010-12-03 20:14:31 +00001139
1140 /* Check sys.prefix\DLLs\python3.dll */
1141 wcscpy(py3path, Py_GetPrefix());
1142 wcscat(py3path, L"\\DLLs\\python3.dll");
1143 hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
1144 return hPython3 != NULL;
1145}