summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-12-25 13:52:37 +0100
committerBram Moolenaar <Bram@vim.org>2020-12-25 13:52:37 +0100
commitb2f9e0e2c537bcde16dab3b62687a17e17849ce1 (patch)
treee4801bdb4252443a817156b771d23dbd7ae0a765
parent3868f59466ed5ff1c5624f40b93c0034ce62cb82 (diff)
downloadvim-git-8.2.2211.tar.gz
patch 8.2.2211: MS-Windows: can't load Python dll if not in the pathv8.2.2211
Problem: MS-Windows: can't load Python dll if not in the path. Solution: Use the InstallPath registry entry. (Kelvin Lee, closes #7540)
-rw-r--r--src/if_python3.c73
-rw-r--r--src/version.c2
2 files changed, 75 insertions, 0 deletions
diff --git a/src/if_python3.c b/src/if_python3.c
index ea4fd7dd8..f9c8002da 100644
--- a/src/if_python3.c
+++ b/src/if_python3.c
@@ -671,6 +671,65 @@ py3_PyType_HasFeature(PyTypeObject *type, unsigned long feature)
# define PyType_HasFeature(t,f) py3_PyType_HasFeature(t,f)
# endif
+# ifdef MSWIN
+/*
+ * Look up the library "libname" using the InstallPath registry key.
+ * Return NULL when failed. Return an allocated string when successful.
+ */
+ static char *
+py3_get_system_libname(const char *libname)
+{
+ const char *cp = libname;
+ char subkey[128];
+ HKEY hKey;
+ char installpath[MAXPATHL];
+ LONG len = sizeof(installpath);
+ LSTATUS rc;
+ size_t sysliblen;
+ char *syslibname;
+
+ while (*cp != '\0')
+ {
+ if (*cp == ':' || *cp == '\\' || *cp == '/')
+ {
+ // Bail out if "libname" contains path separator, assume it is
+ // an absolute path.
+ return NULL;
+ }
+ ++cp;
+ }
+ vim_snprintf(subkey, sizeof(subkey),
+# ifdef _WIN64
+ "Software\\Python\\PythonCore\\%d.%d\\InstallPath",
+# else
+ "Software\\Python\\PythonCore\\%d.%d-32\\InstallPath",
+# endif
+ PY_MAJOR_VERSION, PY_MINOR_VERSION);
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, subkey, 0, KEY_QUERY_VALUE, &hKey)
+ != ERROR_SUCCESS)
+ return NULL;
+ rc = RegQueryValueA(hKey, NULL, installpath, &len);
+ RegCloseKey(hKey);
+ if (ERROR_SUCCESS != rc)
+ return NULL;
+ cp = installpath + len;
+ // Just in case registry value contains null terminators.
+ while (cp > installpath && *(cp-1) == '\0')
+ --cp;
+ // Remove trailing path separators.
+ while (cp > installpath && (*(cp-1) == '\\' || *(cp-1) == '/'))
+ --cp;
+ // Ignore if InstallPath is effectively empty.
+ if (cp <= installpath)
+ return NULL;
+ sysliblen = (cp - installpath) + 1 + STRLEN(libname) + 1;
+ syslibname = alloc(sysliblen);
+ vim_snprintf(syslibname, sysliblen, "%.*s\\%s",
+ (int)(cp - installpath), installpath, libname);
+ return syslibname;
+}
+# endif
+
/*
* Load library and get all pointers.
* Parameter 'libname' provides name of DLL.
@@ -701,6 +760,20 @@ py3_runtime_link_init(char *libname, int verbose)
return OK;
hinstPy3 = load_dll(libname);
+# ifdef MSWIN
+ if (!hinstPy3)
+ {
+ // Attempt to use the path from InstallPath as stored in the registry.
+ char *syslibname = py3_get_system_libname(libname);
+
+ if (syslibname != NULL)
+ {
+ hinstPy3 = load_dll(syslibname);
+ vim_free(syslibname);
+ }
+ }
+# endif
+
if (!hinstPy3)
{
if (verbose)
diff --git a/src/version.c b/src/version.c
index 018bfd52a..762e91263 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2211,
+/**/
2210,
/**/
2209,