##// END OF EJS Templates
exewrapper: find the proper python3X.dll in the registry...
Matt Harbison -
r49378:67d14d4e default
parent child Browse files
Show More
@@ -29,6 +29,134 b' int strcpy_s(char *d, size_t n, const ch'
29 29 #define _countof(array) (sizeof(array) / sizeof(array[0]))
30 30 #endif
31 31
32 #if PY_MAJOR_VERSION >= 3
33
34 #pragma comment(lib, "Advapi32.lib")
35
36 /* python.org installations */
37 #define CORE_PATH L"SOFTWARE\\Python\\PythonCore"
38
39 /* Microsoft Store installations */
40 #define LOOKASIDE_PATH \
41 L"SOFTWARE\\Microsoft\\AppModel\\Lookaside\\user\\Software\\Python\\" \
42 L"PythonCore"
43
44 static wchar_t *_locate_python_for_key(HKEY root, LPCWSTR subkey, size_t *size)
45 {
46 wchar_t installPathKey[512];
47 wchar_t *executable = NULL;
48 DWORD type;
49 DWORD sz = 0;
50 HKEY ip_key;
51 LSTATUS status;
52
53 _snwprintf_s(installPathKey, sizeof(installPathKey), _TRUNCATE,
54 L"%ls\\%d.%d\\InstallPath", subkey, PY_MAJOR_VERSION,
55 PY_MINOR_VERSION);
56
57 status =
58 RegOpenKeyExW(root, installPathKey, 0, KEY_QUERY_VALUE, &ip_key);
59
60 if (status != ERROR_SUCCESS)
61 return NULL;
62
63 status = RegQueryValueExW(ip_key, L"ExecutablePath", NULL, &type,
64 (LPBYTE)executable, &sz);
65 if (status == ERROR_SUCCESS) {
66 /* Allocate extra space so path\to\python.exe can be converted
67 * to path\to\python39.dll + NUL.
68 */
69 *size = sz + sizeof(_T(HGPYTHONLIB ".dll")) + sizeof(wchar_t);
70 executable = malloc(*size);
71
72 if (executable) {
73 status =
74 RegQueryValueExW(ip_key, L"ExecutablePath", NULL,
75 &type, (LPBYTE)executable, &sz);
76
77 if (status != ERROR_SUCCESS) {
78 free(executable);
79 executable = NULL;
80 } else {
81 /* Not all values are stored NUL terminated */
82 executable[sz] = L'\0';
83 }
84 }
85 }
86
87 RegCloseKey(ip_key);
88 return executable;
89 }
90
91 static HMODULE load_system_py3(void)
92 {
93 wchar_t *subkeys[] = {CORE_PATH, LOOKASIDE_PATH};
94 HKEY roots[] = {HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER};
95
96 /* Give priority to python.org installs, because MS Store installs can
97 * break with user profile corruption, and also use some NTFS feature
98 * that MSYS doesn't understand.
99 */
100 for (int s = 0; s < _countof(subkeys); s++) {
101 for (int r = 0; r < _countof(roots); r++) {
102 size_t size = 0;
103 wchar_t *py =
104 _locate_python_for_key(roots[r], subkeys[s], &size);
105 wchar_t *cut = NULL;
106 HMODULE pydll;
107
108 if (!py) {
109 continue;
110 }
111
112 /* Cut off the python executable component */
113 cut = wcsrchr(py, L'\\');
114 if (cut == NULL) {
115 free(py);
116 continue;
117 }
118 *cut = 0;
119
120 wcscat_s(py, size, _T("\\" HGPYTHONLIB ".dll"));
121
122 pydll = LoadLibrary(py);
123
124 /* Also load python3.dll, so we don't pick up a random
125 * one on PATH. We don't search {sys.prefix}\DLLs like
126 * python.exe because this is commented as "not been a
127 * normal install layout for a while", and don't search
128 * LOAD_LIBRARY_SEARCH_APPLICATION_DIR because it's not
129 * clear what the use case is.
130 */
131 if (pydll != NULL) {
132 HANDLE py3dll = NULL;
133
134 *cut = 0;
135 wcscat_s(py, size, L"\\python3.dll");
136
137 py3dll = LoadLibrary(py);
138 if (py3dll == NULL) {
139 const char *err;
140 err = "failed to load python3.dll "
141 "for " HGPYTHONLIB ".dll";
142 fprintf(stderr, "abort: %s (0x%X)\n",
143 err, GetLastError());
144 exit(255);
145 }
146 }
147
148 free(py);
149
150 if (pydll != NULL) {
151 return pydll;
152 }
153 }
154 }
155
156 return NULL;
157 }
158 #endif
159
32 160 static TCHAR pyscript[MAX_PATH + 10];
33 161 static TCHAR pyhome[MAX_PATH + 10];
34 162 static TCHAR pydllfile[MAX_PATH + 10];
@@ -108,6 +236,12 b' int _tmain(int argc, TCHAR *argv[])'
108 236 Py_SetPythonHome(pyhome);
109 237 }
110 238
239 #if PY_MAJOR_VERSION >= 3
240 if (pydll == NULL) {
241 pydll = load_system_py3();
242 }
243 #endif
244
111 245 if (pydll == NULL) {
112 246 pydll = LoadLibrary(_T(HGPYTHONLIB) _T(".dll"));
113 247 if (pydll == NULL) {
General Comments 0
You need to be logged in to leave comments. Login now