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;