[3.6] bpo-29778: Ensure python3.dll is loaded from correct locations when Python is embedded (GH-21298) by zooba · Pull Request #21354 · python/cpython
static wchar_t prefix[MAXPATHLEN+1]; static wchar_t progpath[MAXPATHLEN+1]; static wchar_t dllpath[MAXPATHLEN+1]; static wchar_t *module_search_path = NULL;
while (i > 0 && src[i] != '.' && !is_sep(src[i])) --i; while (i > 0 && src[i] != '.' && !is_sep(src[i])) --i;
if (i == 0) { dest[0] = '\0'; return -1; } if (i == 0) { dest[0] = '\0'; return -1; }
if (is_sep(src[i])) i = src_len; if (is_sep(src[i])) { i = src_len; }
if (wcsncpy_s(dest, MAXPATHLEN+1, src, i)) { dest[0] = '\0'; return -1; } } else { wchar_t *s = wcsrchr(dest, L'.'); if (s) { s[0] = '\0'; } }
if (wcsncpy_s(dest, MAXPATHLEN+1, src, i) || wcscat_s(dest, MAXPATHLEN+1, ext)) { if (wcscat_s(dest, MAXPATHLEN+1, ext)) { dest[0] = '\0'; return -1; }
static int get_dllpath(wchar_t *dllpath) { #ifdef Py_ENABLE_SHARED extern HANDLE PyWin_DLLhModule; if (PyWin_DLLhModule && GetModuleFileNameW(PyWin_DLLhModule, dllpath, MAXPATHLEN)) { return 0; } #endif return -1; }
#ifdef Py_ENABLE_SHARED
/* a string loaded from the DLL at startup.*/
#ifdef Py_ENABLE_SHARED extern HANDLE PyWin_DLLhModule; /* static init of progpath ensures final char remains \0 */ if (PyWin_DLLhModule) if (!GetModuleFileNameW(PyWin_DLLhModule, dllpath, MAXPATHLEN)) dllpath[0] = 0; #else dllpath[0] = 0; #endif if (GetModuleFileNameW(NULL, modulepath, MAXPATHLEN)) { canonicalize(progpath, modulepath); return;
if ((dllpath[0] && !change_ext(spbuffer, dllpath, L"._pth") && exists(spbuffer)) || if ((!get_dllpath(spbuffer) && !change_ext(spbuffer, spbuffer, L"._pth") && exists(spbuffer)) || (progpath[0] && !change_ext(spbuffer, progpath, L"._pth") && exists(spbuffer))) {
if (!read_pth_file(spbuffer, prefix, &Py_IsolatedFlag, &Py_NoSiteFlag)) {
/* Calculate zip archive path from DLL or exe path */ change_ext(zip_path, dllpath[0] ? dllpath : progpath, L".zip"); if (!get_dllpath(zip_path)) { change_ext(zip_path, zip_path, L".zip"); } else { change_ext(zip_path, progpath, L".zip"); }
if (pythonhome == NULL || *pythonhome == '\0') { if (zip_path[0] && exists(zip_path)) {
/* External interface */
void Py_SetPath(const wchar_t *path) {
/* If there is a python3.dll next to the python3y.dll, assume this is a build tree; use that DLL */ wcscpy(py3path, dllpath); s = wcsrchr(py3path, L'\\'); if (!s) s = py3path; wcscpy(s, L"\\python3.dll"); hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (hPython3 != NULL) return 1; use that DLL */ if (!get_dllpath(py3path)) { reduce(py3path); join(py3path, PY3_DLLNAME); hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (hPython3 != NULL) { return 1; } }
/* If we can locate python3.dll in our application dir, use that DLL */ wcscpy(py3path, Py_GetPrefix()); if (py3path[0]) { join(py3path, PY3_DLLNAME); hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (hPython3 != NULL) { return 1; } }
/* Check sys.prefix\DLLs\python3.dll */ /* For back-compat, also search {sys.prefix}\DLLs, though that has not been a normal install layout for a while */ wcscpy(py3path, Py_GetPrefix()); wcscat(py3path, L"\\DLLs\\python3.dll"); hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (py3path[0]) { join(py3path, L"DLLs\\" PY3_DLLNAME); hPython3 = LoadLibraryExW(py3path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); } return hPython3 != NULL; }