Home | History | Annotate | Download | only in PC
      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
    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
    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
    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
    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
    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
    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 
    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
    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
    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 *
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   1009 calculate_free(PyCalculatePath *calculate)
   1010 {
   1011     PyMem_RawFree(calculate->machine_path);
   1012     PyMem_RawFree(calculate->user_path);
   1013 }
   1014 
   1015 
   1016 _PyInitError
   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
   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