diff --git a/mercurial/exewrapper.c b/mercurial/exewrapper.c
index f12a19d03d2ce06e4c107a8f42944e57a6881229_bWVyY3VyaWFsL2V4ZXdyYXBwZXIuYw==..67d14d4e036ce8d22e240f3b77600ade2be8dbbf_bWVyY3VyaWFsL2V4ZXdyYXBwZXIuYw== 100644
--- a/mercurial/exewrapper.c
+++ b/mercurial/exewrapper.c
@@ -29,6 +29,134 @@
 #define _countof(array) (sizeof(array) / sizeof(array[0]))
 #endif
 
+#if PY_MAJOR_VERSION >= 3
+
+#pragma comment(lib, "Advapi32.lib")
+
+/* python.org installations */
+#define CORE_PATH L"SOFTWARE\\Python\\PythonCore"
+
+/* Microsoft Store installations */
+#define LOOKASIDE_PATH                                                         \
+	L"SOFTWARE\\Microsoft\\AppModel\\Lookaside\\user\\Software\\Python\\"  \
+	L"PythonCore"
+
+static wchar_t *_locate_python_for_key(HKEY root, LPCWSTR subkey, size_t *size)
+{
+	wchar_t installPathKey[512];
+	wchar_t *executable = NULL;
+	DWORD type;
+	DWORD sz = 0;
+	HKEY ip_key;
+	LSTATUS status;
+
+	_snwprintf_s(installPathKey, sizeof(installPathKey), _TRUNCATE,
+	             L"%ls\\%d.%d\\InstallPath", subkey, PY_MAJOR_VERSION,
+	             PY_MINOR_VERSION);
+
+	status =
+	    RegOpenKeyExW(root, installPathKey, 0, KEY_QUERY_VALUE, &ip_key);
+
+	if (status != ERROR_SUCCESS)
+		return NULL;
+
+	status = RegQueryValueExW(ip_key, L"ExecutablePath", NULL, &type,
+	                          (LPBYTE)executable, &sz);
+	if (status == ERROR_SUCCESS) {
+		/* Allocate extra space so path\to\python.exe can be converted
+		 * to path\to\python39.dll + NUL.
+		 */
+		*size = sz + sizeof(_T(HGPYTHONLIB ".dll")) + sizeof(wchar_t);
+		executable = malloc(*size);
+
+		if (executable) {
+			status =
+			    RegQueryValueExW(ip_key, L"ExecutablePath", NULL,
+			                     &type, (LPBYTE)executable, &sz);
+
+			if (status != ERROR_SUCCESS) {
+				free(executable);
+				executable = NULL;
+			} else {
+				/* Not all values are stored NUL terminated */
+				executable[sz] = L'\0';
+			}
+		}
+	}
+
+	RegCloseKey(ip_key);
+	return executable;
+}
+
+static HMODULE load_system_py3(void)
+{
+	wchar_t *subkeys[] = {CORE_PATH, LOOKASIDE_PATH};
+	HKEY roots[] = {HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER};
+
+	/* Give priority to python.org installs, because MS Store installs can
+	 * break with user profile corruption, and also use some NTFS feature
+	 * that MSYS doesn't understand.
+	 */
+	for (int s = 0; s < _countof(subkeys); s++) {
+		for (int r = 0; r < _countof(roots); r++) {
+			size_t size = 0;
+			wchar_t *py =
+			    _locate_python_for_key(roots[r], subkeys[s], &size);
+			wchar_t *cut = NULL;
+			HMODULE pydll;
+
+			if (!py) {
+				continue;
+			}
+
+			/* Cut off the python executable component */
+			cut = wcsrchr(py, L'\\');
+			if (cut == NULL) {
+				free(py);
+				continue;
+			}
+			*cut = 0;
+
+			wcscat_s(py, size, _T("\\" HGPYTHONLIB ".dll"));
+
+			pydll = LoadLibrary(py);
+
+			/* Also load python3.dll, so we don't pick up a random
+			 * one on PATH. We don't search {sys.prefix}\DLLs like
+			 * python.exe because this is commented as "not been a
+			 * normal install layout for a while", and don't search
+			 * LOAD_LIBRARY_SEARCH_APPLICATION_DIR because it's not
+			 * clear what the use case is.
+			 */
+			if (pydll != NULL) {
+				HANDLE py3dll = NULL;
+
+				*cut = 0;
+				wcscat_s(py, size, L"\\python3.dll");
+
+				py3dll = LoadLibrary(py);
+				if (py3dll == NULL) {
+					const char *err;
+					err = "failed to load python3.dll "
+					      "for " HGPYTHONLIB ".dll";
+					fprintf(stderr, "abort: %s (0x%X)\n",
+					        err, GetLastError());
+					exit(255);
+				}
+			}
+
+			free(py);
+
+			if (pydll != NULL) {
+				return pydll;
+			}
+		}
+	}
+
+	return NULL;
+}
+#endif
+
 static TCHAR pyscript[MAX_PATH + 10];
 static TCHAR pyhome[MAX_PATH + 10];
 static TCHAR pydllfile[MAX_PATH + 10];
@@ -108,6 +236,12 @@
 		Py_SetPythonHome(pyhome);
 	}
 
+#if PY_MAJOR_VERSION >= 3
+	if (pydll == NULL) {
+		pydll = load_system_py3();
+	}
+#endif
+
 	if (pydll == NULL) {
 		pydll = LoadLibrary(_T(HGPYTHONLIB) _T(".dll"));
 		if (pydll == NULL) {