@@ -835,17 +835,16 @@ Py_ssize_t py3_PyList_GET_SIZE(PyObject *op)
835835 * Look up the library "libname" using the InstallPath registry key.
836836 * Return NULL when failed. Return an allocated string when successful.
837837 */
838- static char *
838+ static WCHAR *
839839py3_get_system_libname (const char * libname )
840840{
841+ const WCHAR * pythoncore = L"Software\\Python\\PythonCore" ;
841842 const char * cp = libname ;
842- char subkey [128 ];
843+ WCHAR subkey [128 ];
843844 HKEY hKey ;
844- char installpath [MAXPATHL ];
845- LONG len = sizeof (installpath );
846- LSTATUS rc ;
847- size_t sysliblen ;
848- char * syslibname ;
845+ int i ;
846+ DWORD j , len ;
847+ LSTATUS ret ;
849848
850849 while (* cp != '\0' )
851850 {
@@ -857,35 +856,95 @@ py3_get_system_libname(const char *libname)
857856 }
858857 ++ cp ;
859858 }
860- vim_snprintf (subkey , sizeof (subkey ),
859+
860+ WCHAR keyfound [32 ];
861+ HKEY hKeyTop [] = {HKEY_CURRENT_USER , HKEY_LOCAL_MACHINE };
862+ HKEY hKeyFound = NULL ;
863+ # ifdef USE_LIMITED_API
864+ long maxminor = -1 ;
865+ # endif
866+ for (i = 0 ; i < ARRAY_LENGTH (hKeyTop ); i ++ )
867+ {
868+ long major , minor ;
869+
870+ ret = RegOpenKeyExW (hKeyTop [i ], pythoncore , 0 , KEY_READ , & hKey );
871+ if (ret != ERROR_SUCCESS )
872+ continue ;
873+ for (j = 0 ;; j ++ )
874+ {
875+ WCHAR keyname [32 ];
876+ WCHAR * wp ;
877+
878+ len = ARRAY_LENGTH (keyname );
879+ ret = RegEnumKeyExW (hKey , j , keyname , & len ,
880+ NULL , NULL , NULL , NULL );
881+ if (ret == ERROR_NO_MORE_ITEMS )
882+ break ;
883+
884+ major = wcstol (keyname , & wp , 10 );
885+ if (* wp == L'.' )
886+ minor = wcstol (wp + 1 , & wp , 10 );
861887# ifdef _WIN64
862- "Software\\Python\\PythonCore\\%d.%d\\InstallPath" ,
888+ if (* wp != L'\0' )
889+ continue ;
863890# else
864- "Software\\Python\\PythonCore\\%d.%d-32\\InstallPath" ,
891+ if (wcscmp (wp , L"-32" ) != 0 )
892+ continue ;
865893# endif
866- PY_MAJOR_VERSION , PY_MINOR_VERSION );
867- if (RegOpenKeyExA (HKEY_LOCAL_MACHINE , subkey , 0 , KEY_QUERY_VALUE , & hKey )
868- != ERROR_SUCCESS )
894+
895+ if (major != PY_MAJOR_VERSION )
896+ continue ;
897+ # ifdef USE_LIMITED_API
898+ // Search the latest version.
899+ if ((minor > maxminor )
900+ && (minor >= ((Py_LIMITED_API >> 16 ) & 0xff )))
901+ {
902+ maxminor = minor ;
903+ wcscpy (keyfound , keyname );
904+ hKeyFound = hKeyTop [i ];
905+ }
906+ # else
907+ // Check if it matches with the compiled version.
908+ if (minor == PY_MINOR_VERSION )
909+ {
910+ wcscpy (keyfound , keyname );
911+ hKeyFound = hKeyTop [i ];
912+ break ;
913+ }
914+ # endif
915+ }
916+ RegCloseKey (hKey );
917+ # ifdef USE_LIMITED_API
918+ if (hKeyFound != NULL )
919+ break ;
920+ # endif
921+ }
922+ if (hKeyFound == NULL )
869923 return NULL ;
870- rc = RegQueryValueA (hKey , NULL , installpath , & len );
871- RegCloseKey (hKey );
872- if (ERROR_SUCCESS != rc )
924+
925+ swprintf (subkey , ARRAY_LENGTH (subkey ), L"%ls\\%ls\\InstallPath" ,
926+ pythoncore , keyfound );
927+ ret = RegGetValueW (hKeyFound , subkey , NULL , RRF_RT_REG_SZ ,
928+ NULL , NULL , & len );
929+ if (ret != ERROR_MORE_DATA && ret != ERROR_SUCCESS )
873930 return NULL ;
874- cp = installpath + len ;
875- // Just in case registry value contains null terminators.
876- while (cp > installpath && * (cp - 1 ) == '\0' )
877- -- cp ;
878- // Remove trailing path separators.
879- while (cp > installpath && (* (cp - 1 ) == '\\' || * (cp - 1 ) == '/' ))
880- -- cp ;
881- // Ignore if InstallPath is effectively empty.
882- if (cp <= installpath )
931+ size_t len2 = len / sizeof (WCHAR ) + 1 + strlen (libname );
932+ WCHAR * path = alloc (len2 * sizeof (WCHAR ));
933+ if (path == NULL )
883934 return NULL ;
884- sysliblen = (cp - installpath ) + 1 + STRLEN (libname ) + 1 ;
885- syslibname = alloc (sysliblen );
886- vim_snprintf (syslibname , sysliblen , "%.*s\\%s" ,
887- (int )(cp - installpath ), installpath , libname );
888- return syslibname ;
935+ ret = RegGetValueW (hKeyFound , subkey , NULL , RRF_RT_REG_SZ ,
936+ NULL , path , & len );
937+ if (ret != ERROR_SUCCESS )
938+ {
939+ vim_free (path );
940+ return NULL ;
941+ }
942+ // Remove trailing path separators.
943+ size_t len3 = wcslen (path );
944+ if ((len3 > 0 ) && (path [len3 - 1 ] == L'/' || path [len3 - 1 ] == L'\\' ))
945+ -- len3 ;
946+ swprintf (path + len3 , len2 - len3 , L"\\%hs" , libname );
947+ return path ;
889948}
890949# endif
891950
@@ -923,11 +982,13 @@ py3_runtime_link_init(char *libname, int verbose)
923982 if (!hinstPy3 )
924983 {
925984 // Attempt to use the path from InstallPath as stored in the registry.
926- char * syslibname = py3_get_system_libname (libname );
985+ WCHAR * syslibname = py3_get_system_libname (libname );
927986
928987 if (syslibname != NULL )
929988 {
930- hinstPy3 = load_dll (syslibname );
989+ hinstPy3 = LoadLibraryExW (syslibname , NULL ,
990+ LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR |
991+ LOAD_LIBRARY_SEARCH_SYSTEM32 );
931992 vim_free (syslibname );
932993 }
933994 }
0 commit comments