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