Mercurial > hg
comparison mercurial/exewrapper.c @ 48304:2ec5fbe26659
backout: backed out changeset 67d14d4e036c
Same as the previous patch, this breaks the Windows CI for some yet unknown
reason.
Differential Revision: https://phab.mercurial-scm.org/D11727
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Wed, 27 Oct 2021 15:18:52 +0200 |
parents | 67d14d4e036c |
children |
comparison
equal
deleted
inserted
replaced
48303:2ce31dbde4b1 | 48304:2ec5fbe26659 |
---|---|
25 } | 25 } |
26 | 26 |
27 #define _tcscpy_s strcpy_s | 27 #define _tcscpy_s strcpy_s |
28 #define _tcscat_s strcat_s | 28 #define _tcscat_s strcat_s |
29 #define _countof(array) (sizeof(array) / sizeof(array[0])) | 29 #define _countof(array) (sizeof(array) / sizeof(array[0])) |
30 #endif | |
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 | 30 #endif |
159 | 31 |
160 static TCHAR pyscript[MAX_PATH + 10]; | 32 static TCHAR pyscript[MAX_PATH + 10]; |
161 static TCHAR pyhome[MAX_PATH + 10]; | 33 static TCHAR pyhome[MAX_PATH + 10]; |
162 static TCHAR pydllfile[MAX_PATH + 10]; | 34 static TCHAR pydllfile[MAX_PATH + 10]; |
234 goto bail; | 106 goto bail; |
235 } | 107 } |
236 Py_SetPythonHome(pyhome); | 108 Py_SetPythonHome(pyhome); |
237 } | 109 } |
238 | 110 |
239 #if PY_MAJOR_VERSION >= 3 | |
240 if (pydll == NULL) { | |
241 pydll = load_system_py3(); | |
242 } | |
243 #endif | |
244 | |
245 if (pydll == NULL) { | 111 if (pydll == NULL) { |
246 pydll = LoadLibrary(_T(HGPYTHONLIB) _T(".dll")); | 112 pydll = LoadLibrary(_T(HGPYTHONLIB) _T(".dll")); |
247 if (pydll == NULL) { | 113 if (pydll == NULL) { |
248 err = "failed to load Python DLL " HGPYTHONLIB ".dll"; | 114 err = "failed to load Python DLL " HGPYTHONLIB ".dll"; |
249 goto bail; | 115 goto bail; |