aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/PC
diff options
context:
space:
mode:
Diffstat (limited to 'PC')
-rw-r--r--PC/_wmimodule.cpp22
-rw-r--r--PC/launcher.c2
-rw-r--r--PC/layout/main.py28
-rw-r--r--PC/layout/support/arch.py34
-rw-r--r--PC/layout/support/constants.py45
-rw-r--r--PC/pyconfig.h (renamed from PC/pyconfig.h.in)35
-rwxr-xr-xPC/python3dll.c4
-rw-r--r--PC/python_uwp.cpp4
-rw-r--r--PC/python_ver_rc.h2
-rw-r--r--PC/winreg.c43
10 files changed, 167 insertions, 52 deletions
diff --git a/PC/_wmimodule.cpp b/PC/_wmimodule.cpp
index b6efb3e4a20..30d61c86587 100644
--- a/PC/_wmimodule.cpp
+++ b/PC/_wmimodule.cpp
@@ -57,11 +57,11 @@ _query_thread(LPVOID param)
IEnumWbemClassObject* enumerator = NULL;
HRESULT hr = S_OK;
BSTR bstrQuery = NULL;
- struct _query_data *data = (struct _query_data*)param;
+ _query_data data = *(struct _query_data*)param;
// gh-125315: Copy the query string first, so that if the main thread gives
// up on waiting we aren't left with a dangling pointer (and a likely crash)
- bstrQuery = SysAllocString(data->query);
+ bstrQuery = SysAllocString(data.query);
if (!bstrQuery) {
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
@@ -71,7 +71,7 @@ _query_thread(LPVOID param)
}
if (FAILED(hr)) {
- CloseHandle(data->writePipe);
+ CloseHandle(data.writePipe);
if (bstrQuery) {
SysFreeString(bstrQuery);
}
@@ -96,7 +96,7 @@ _query_thread(LPVOID param)
IID_IWbemLocator, (LPVOID *)&locator
);
}
- if (SUCCEEDED(hr) && !SetEvent(data->initEvent)) {
+ if (SUCCEEDED(hr) && !SetEvent(data.initEvent)) {
hr = HRESULT_FROM_WIN32(GetLastError());
}
if (SUCCEEDED(hr)) {
@@ -105,7 +105,7 @@ _query_thread(LPVOID param)
NULL, NULL, 0, NULL, 0, 0, &services
);
}
- if (SUCCEEDED(hr) && !SetEvent(data->connectEvent)) {
+ if (SUCCEEDED(hr) && !SetEvent(data.connectEvent)) {
hr = HRESULT_FROM_WIN32(GetLastError());
}
if (SUCCEEDED(hr)) {
@@ -143,7 +143,7 @@ _query_thread(LPVOID param)
if (FAILED(hr) || got != 1 || !value) {
continue;
}
- if (!startOfEnum && !WriteFile(data->writePipe, (LPVOID)L"\0", 2, &written, NULL)) {
+ if (!startOfEnum && !WriteFile(data.writePipe, (LPVOID)L"\0", 2, &written, NULL)) {
hr = HRESULT_FROM_WIN32(GetLastError());
break;
}
@@ -171,10 +171,10 @@ _query_thread(LPVOID param)
DWORD cbStr1, cbStr2;
cbStr1 = (DWORD)(wcslen(propName) * sizeof(propName[0]));
cbStr2 = (DWORD)(wcslen(propStr) * sizeof(propStr[0]));
- if (!WriteFile(data->writePipe, propName, cbStr1, &written, NULL) ||
- !WriteFile(data->writePipe, (LPVOID)L"=", 2, &written, NULL) ||
- !WriteFile(data->writePipe, propStr, cbStr2, &written, NULL) ||
- !WriteFile(data->writePipe, (LPVOID)L"\0", 2, &written, NULL)
+ if (!WriteFile(data.writePipe, propName, cbStr1, &written, NULL) ||
+ !WriteFile(data.writePipe, (LPVOID)L"=", 2, &written, NULL) ||
+ !WriteFile(data.writePipe, propStr, cbStr2, &written, NULL) ||
+ !WriteFile(data.writePipe, (LPVOID)L"\0", 2, &written, NULL)
) {
hr = HRESULT_FROM_WIN32(GetLastError());
}
@@ -200,7 +200,7 @@ _query_thread(LPVOID param)
locator->Release();
}
CoUninitialize();
- CloseHandle(data->writePipe);
+ CloseHandle(data.writePipe);
return (DWORD)hr;
}
diff --git a/PC/launcher.c b/PC/launcher.c
index 5c63d872bd4..fed5e156b92 100644
--- a/PC/launcher.c
+++ b/PC/launcher.c
@@ -140,7 +140,7 @@ static wchar_t * get_env(wchar_t * key)
return buf;
}
-#if defined(_DEBUG)
+#if defined(Py_DEBUG)
/* Do not define EXECUTABLEPATH_VALUE in debug builds as it'll
never point to the debug build. */
#if defined(_WINDOWS)
diff --git a/PC/layout/main.py b/PC/layout/main.py
index 7324a135133..8543e7c56e1 100644
--- a/PC/layout/main.py
+++ b/PC/layout/main.py
@@ -247,9 +247,15 @@ def get_layout(ns):
if ns.include_freethreaded:
yield from in_build("venvlaunchert.exe", "Lib/venv/scripts/nt/")
yield from in_build("venvwlaunchert.exe", "Lib/venv/scripts/nt/")
- else:
+ elif (VER_MAJOR, VER_MINOR) > (3, 12):
yield from in_build("venvlauncher.exe", "Lib/venv/scripts/nt/")
yield from in_build("venvwlauncher.exe", "Lib/venv/scripts/nt/")
+ else:
+ # Older versions of venv expected the scripts to be named 'python'
+ # and they were renamed at this stage. We need to replicate that
+ # when packaging older versions.
+ yield from in_build("venvlauncher.exe", "Lib/venv/scripts/nt/", "python")
+ yield from in_build("venvwlauncher.exe", "Lib/venv/scripts/nt/", "pythonw")
if ns.include_tools:
@@ -652,15 +658,6 @@ def main():
ns.doc_build = (Path.cwd() / ns.doc_build).resolve()
if ns.include_cat and not ns.include_cat.is_absolute():
ns.include_cat = (Path.cwd() / ns.include_cat).resolve()
- if not ns.arch:
- # TODO: Calculate arch from files in ns.build instead
- if sys.winver.endswith("-arm64"):
- ns.arch = "arm64"
- elif sys.winver.endswith("-32"):
- ns.arch = "win32"
- else:
- ns.arch = "amd64"
-
if ns.zip and not ns.zip.is_absolute():
ns.zip = (Path.cwd() / ns.zip).resolve()
if ns.catalog and not ns.catalog.is_absolute():
@@ -668,6 +665,17 @@ def main():
configure_logger(ns)
+ if not ns.arch:
+ from .support.arch import calculate_from_build_dir
+ ns.arch = calculate_from_build_dir(ns.build)
+
+ expect = f"{VER_MAJOR}.{VER_MINOR}.{VER_MICRO}{VER_SUFFIX}"
+ actual = check_patchlevel_version(ns.source)
+ if actual and actual != expect:
+ log_error(f"Inferred version {expect} does not match {actual} from patchlevel.h. "
+ "You should set %PYTHONINCLUDE% or %PYTHON_HEXVERSION% before launching.")
+ return 5
+
log_info(
"""OPTIONS
Source: {ns.source}
diff --git a/PC/layout/support/arch.py b/PC/layout/support/arch.py
new file mode 100644
index 00000000000..daf4efbc7ab
--- /dev/null
+++ b/PC/layout/support/arch.py
@@ -0,0 +1,34 @@
+from struct import unpack
+from .constants import *
+from .logging import *
+
+def calculate_from_build_dir(root):
+ candidates = [
+ root / PYTHON_DLL_NAME,
+ root / FREETHREADED_PYTHON_DLL_NAME,
+ *root.glob("*.dll"),
+ *root.glob("*.pyd"),
+ # Check EXE last because it's easier to have cross-platform EXE
+ *root.glob("*.exe"),
+ ]
+
+ ARCHS = {
+ b"PE\0\0\x4c\x01": "win32",
+ b"PE\0\0\x64\x86": "amd64",
+ b"PE\0\0\x64\xAA": "arm64"
+ }
+
+ first_exc = None
+ for pe in candidates:
+ try:
+ # Read the PE header to grab the machine type
+ with open(pe, "rb") as f:
+ f.seek(0x3C)
+ offset = int.from_bytes(f.read(4), "little")
+ f.seek(offset)
+ arch = ARCHS[f.read(6)]
+ except (FileNotFoundError, PermissionError, LookupError) as ex:
+ log_debug("Failed to open {}: {}", pe, ex)
+ continue
+ log_info("Inferred architecture {} from {}", arch, pe)
+ return arch
diff --git a/PC/layout/support/constants.py b/PC/layout/support/constants.py
index ae22aa16ebf..6b8c915e519 100644
--- a/PC/layout/support/constants.py
+++ b/PC/layout/support/constants.py
@@ -6,6 +6,8 @@ __author__ = "Steve Dower <steve.dower@python.org>"
__version__ = "3.8"
import os
+import pathlib
+import re
import struct
import sys
@@ -13,9 +15,15 @@ import sys
def _unpack_hexversion():
try:
hexversion = int(os.getenv("PYTHON_HEXVERSION"), 16)
+ return struct.pack(">i", hexversion)
except (TypeError, ValueError):
- hexversion = sys.hexversion
- return struct.pack(">i", hexversion)
+ pass
+ if os.getenv("PYTHONINCLUDE"):
+ try:
+ return _read_patchlevel_version(pathlib.Path(os.getenv("PYTHONINCLUDE")))
+ except OSError:
+ pass
+ return struct.pack(">i", sys.hexversion)
def _get_suffix(field4):
@@ -26,6 +34,39 @@ def _get_suffix(field4):
return ""
+def _read_patchlevel_version(sources):
+ if not sources.match("Include"):
+ sources /= "Include"
+ values = {}
+ with open(sources / "patchlevel.h", "r", encoding="utf-8") as f:
+ for line in f:
+ m = re.match(r'#\s*define\s+(PY_\S+?)\s+(\S+)', line.strip(), re.I)
+ if m and m.group(2):
+ v = m.group(2)
+ if v.startswith('"'):
+ v = v[1:-1]
+ else:
+ v = values.get(v, v)
+ if isinstance(v, str):
+ try:
+ v = int(v, 16 if v.startswith("0x") else 10)
+ except ValueError:
+ pass
+ values[m.group(1)] = v
+ return (
+ values["PY_MAJOR_VERSION"],
+ values["PY_MINOR_VERSION"],
+ values["PY_MICRO_VERSION"],
+ values["PY_RELEASE_LEVEL"] << 4 | values["PY_RELEASE_SERIAL"],
+ )
+
+
+def check_patchlevel_version(sources):
+ got = _read_patchlevel_version(sources)
+ if got != (VER_MAJOR, VER_MINOR, VER_MICRO, VER_FIELD4):
+ return f"{got[0]}.{got[1]}.{got[2]}{_get_suffix(got[3])}"
+
+
VER_MAJOR, VER_MINOR, VER_MICRO, VER_FIELD4 = _unpack_hexversion()
VER_SUFFIX = _get_suffix(VER_FIELD4)
VER_FIELD3 = VER_MICRO << 8 | VER_FIELD4
diff --git a/PC/pyconfig.h.in b/PC/pyconfig.h
index bbafaed808e..0e8379387cd 100644
--- a/PC/pyconfig.h.in
+++ b/PC/pyconfig.h
@@ -94,12 +94,22 @@ WIN32 is still required for the locale module.
#endif
#endif /* Py_BUILD_CORE || Py_BUILD_CORE_BUILTIN || Py_BUILD_CORE_MODULE */
-/* Define to 1 if you want to disable the GIL */
-/* Uncomment the definition for free-threaded builds, or define it manually
- * when compiling extension modules. Note that we test with #ifdef, so
- * defining as 0 will still disable the GIL. */
-#ifndef Py_GIL_DISABLED
-/* #define Py_GIL_DISABLED 1 */
+/* _DEBUG implies Py_DEBUG */
+#ifdef _DEBUG
+# define Py_DEBUG 1
+#endif
+
+/* Define to 1 when compiling for experimental free-threaded builds */
+#ifdef Py_GIL_DISABLED
+/* We undefine if it was set to zero because all later checks are #ifdef.
+ * Note that non-Windows builds do not do this, and so every effort should
+ * be made to avoid defining the variable at all when not desired. However,
+ * sysconfig.get_config_var always returns a 1 or a 0, and so it seems likely
+ * that a build backend will define it with the value.
+ */
+#if Py_GIL_DISABLED == 0
+#undef Py_GIL_DISABLED
+#endif
#endif
/* Compiler specific defines */
@@ -319,21 +329,21 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */
This is relevant when using build-system generator (e.g CMake) where
the linking is explicitly handled */
# if defined(Py_GIL_DISABLED)
-# if defined(_DEBUG)
+# if defined(Py_DEBUG)
# pragma comment(lib,"python315t_d.lib")
# elif defined(Py_LIMITED_API)
# pragma comment(lib,"python3t.lib")
# else
# pragma comment(lib,"python315t.lib")
-# endif /* _DEBUG */
+# endif /* Py_DEBUG */
# else /* Py_GIL_DISABLED */
-# if defined(_DEBUG)
+# if defined(Py_DEBUG)
# pragma comment(lib,"python315_d.lib")
# elif defined(Py_LIMITED_API)
# pragma comment(lib,"python3.lib")
# else
# pragma comment(lib,"python315.lib")
-# endif /* _DEBUG */
+# endif /* Py_DEBUG */
# endif /* Py_GIL_DISABLED */
# endif /* _MSC_VER && !Py_NO_LINK_LIB */
# endif /* Py_BUILD_CORE */
@@ -376,11 +386,6 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */
# define ALIGNOF_MAX_ALIGN_T 8
#endif
-#ifdef _DEBUG
-# define Py_DEBUG
-#endif
-
-
#ifdef MS_WIN32
#define SIZEOF_SHORT 2
diff --git a/PC/python3dll.c b/PC/python3dll.c
index f0c578e11c6..8ec791f8280 100755
--- a/PC/python3dll.c
+++ b/PC/python3dll.c
@@ -595,7 +595,11 @@ EXPORT_FUNC(PySys_Audit)
EXPORT_FUNC(PySys_AuditTuple)
EXPORT_FUNC(PySys_FormatStderr)
EXPORT_FUNC(PySys_FormatStdout)
+EXPORT_FUNC(PySys_GetAttr)
+EXPORT_FUNC(PySys_GetAttrString)
EXPORT_FUNC(PySys_GetObject)
+EXPORT_FUNC(PySys_GetOptionalAttr)
+EXPORT_FUNC(PySys_GetOptionalAttrString)
EXPORT_FUNC(PySys_GetXOptions)
EXPORT_FUNC(PySys_HasWarnOptions)
EXPORT_FUNC(PySys_ResetWarnOptions)
diff --git a/PC/python_uwp.cpp b/PC/python_uwp.cpp
index b9c408a580c..8cdb8d722cd 100644
--- a/PC/python_uwp.cpp
+++ b/PC/python_uwp.cpp
@@ -19,13 +19,13 @@
#include <winrt\Windows.Storage.h>
#ifdef PYTHONW
-#ifdef _DEBUG
+#ifdef Py_DEBUG
const wchar_t *PROGNAME = L"pythonw_d.exe";
#else
const wchar_t *PROGNAME = L"pythonw.exe";
#endif
#else
-#ifdef _DEBUG
+#ifdef Py_DEBUG
const wchar_t *PROGNAME = L"python_d.exe";
#else
const wchar_t *PROGNAME = L"python.exe";
diff --git a/PC/python_ver_rc.h b/PC/python_ver_rc.h
index ee867fe4122..bb98144cd03 100644
--- a/PC/python_ver_rc.h
+++ b/PC/python_ver_rc.h
@@ -10,7 +10,7 @@
#define MS_WINDOWS
#include "modsupport.h"
#include "patchlevel.h"
-#ifdef _DEBUG
+#ifdef Py_DEBUG
# define PYTHON_DEBUG_EXT "_d"
#else
# define PYTHON_DEBUG_EXT
diff --git a/PC/winreg.c b/PC/winreg.c
index c0de5c1353a..d1a1c3d1c97 100644
--- a/PC/winreg.c
+++ b/PC/winreg.c
@@ -426,7 +426,9 @@ PyHKEY_Close(winreg_state *st, PyObject *ob_handle)
if (PyHKEY_Check(st, ob_handle)) {
((PyHKEYObject*)ob_handle)->hkey = 0;
}
+ Py_BEGIN_ALLOW_THREADS
rc = key ? RegCloseKey(key) : ERROR_SUCCESS;
+ Py_END_ALLOW_THREADS
if (rc != ERROR_SUCCESS)
PyErr_SetFromWindowsErrWithFunction(rc, "RegCloseKey");
return rc == ERROR_SUCCESS;
@@ -499,14 +501,21 @@ PyWinObject_CloseHKEY(winreg_state *st, PyObject *obHandle)
}
#if SIZEOF_LONG >= SIZEOF_HKEY
else if (PyLong_Check(obHandle)) {
- long rc = RegCloseKey((HKEY)PyLong_AsLong(obHandle));
+ long rc;
+ Py_BEGIN_ALLOW_THREADS
+ rc = RegCloseKey((HKEY)PyLong_AsLong(obHandle));
+ Py_END_ALLOW_THREADS
ok = (rc == ERROR_SUCCESS);
if (!ok)
PyErr_SetFromWindowsErrWithFunction(rc, "RegCloseKey");
}
#else
else if (PyLong_Check(obHandle)) {
- long rc = RegCloseKey((HKEY)PyLong_AsVoidPtr(obHandle));
+ long rc;
+ HKEY hkey = (HKEY)PyLong_AsVoidPtr(obHandle);
+ Py_BEGIN_ALLOW_THREADS
+ rc = RegCloseKey(hkey);
+ Py_END_ALLOW_THREADS
ok = (rc == ERROR_SUCCESS);
if (!ok)
PyErr_SetFromWindowsErrWithFunction(rc, "RegCloseKey");
@@ -924,7 +933,9 @@ winreg_CreateKey_impl(PyObject *module, HKEY key, const wchar_t *sub_key)
(Py_ssize_t)KEY_WRITE) < 0) {
return NULL;
}
+ Py_BEGIN_ALLOW_THREADS
rc = RegCreateKeyW(key, sub_key, &retKey);
+ Py_END_ALLOW_THREADS
if (rc != ERROR_SUCCESS) {
PyErr_SetFromWindowsErrWithFunction(rc, "CreateKey");
return NULL;
@@ -973,8 +984,10 @@ winreg_CreateKeyEx_impl(PyObject *module, HKEY key, const wchar_t *sub_key,
(Py_ssize_t)access) < 0) {
return NULL;
}
+ Py_BEGIN_ALLOW_THREADS
rc = RegCreateKeyExW(key, sub_key, reserved, NULL, 0,
access, NULL, &retKey, NULL);
+ Py_END_ALLOW_THREADS
if (rc != ERROR_SUCCESS) {
PyErr_SetFromWindowsErrWithFunction(rc, "CreateKeyEx");
return NULL;
@@ -1187,10 +1200,12 @@ winreg_EnumValue_impl(PyObject *module, HKEY key, int index)
(Py_ssize_t)key, index) < 0) {
return NULL;
}
- if ((rc = RegQueryInfoKeyW(key, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL,
- &retValueSize, &retDataSize, NULL, NULL))
- != ERROR_SUCCESS)
+
+ Py_BEGIN_ALLOW_THREADS
+ rc = RegQueryInfoKeyW(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ &retValueSize, &retDataSize, NULL, NULL);
+ Py_END_ALLOW_THREADS
+ if (rc != ERROR_SUCCESS)
return PyErr_SetFromWindowsErrWithFunction(rc,
"RegQueryInfoKey");
++retValueSize; /* include null terminators */
@@ -1290,7 +1305,7 @@ winreg_ExpandEnvironmentStrings_impl(PyObject *module, const wchar_t *string)
return PyErr_SetFromWindowsErrWithFunction(retValueSize,
"ExpandEnvironmentStrings");
}
- o = PyUnicode_FromWideChar(retValue, wcslen(retValue));
+ o = PyUnicode_FromWideChar(retValue, -1);
PyMem_Free(retValue);
return o;
}
@@ -1477,9 +1492,11 @@ winreg_QueryInfoKey_impl(PyObject *module, HKEY key)
if (PySys_Audit("winreg.QueryInfoKey", "n", (Py_ssize_t)key) < 0) {
return NULL;
}
- if ((rc = RegQueryInfoKeyW(key, NULL, NULL, 0, &nSubKeys, NULL, NULL,
- &nValues, NULL, NULL, NULL, &ft))
- != ERROR_SUCCESS) {
+ Py_BEGIN_ALLOW_THREADS
+ rc = RegQueryInfoKeyW(key, NULL, NULL, 0, &nSubKeys, NULL, NULL,
+ &nValues, NULL, NULL, NULL, &ft);
+ Py_END_ALLOW_THREADS
+ if (rc != ERROR_SUCCESS) {
return PyErr_SetFromWindowsErrWithFunction(rc, "RegQueryInfoKey");
}
li.LowPart = ft.dwLowDateTime;
@@ -1587,7 +1604,9 @@ exit:
PyMem_Free(pbuf);
}
if (childKey != key) {
+ Py_BEGIN_ALLOW_THREADS
RegCloseKey(childKey);
+ Py_END_ALLOW_THREADS
}
return result;
}
@@ -1625,7 +1644,9 @@ winreg_QueryValueEx_impl(PyObject *module, HKEY key, const wchar_t *name)
(Py_ssize_t)key, NULL, name) < 0) {
return NULL;
}
+ Py_BEGIN_ALLOW_THREADS
rc = RegQueryValueExW(key, name, NULL, NULL, NULL, &bufSize);
+ Py_END_ALLOW_THREADS
if (rc == ERROR_MORE_DATA)
bufSize = 256;
else if (rc != ERROR_SUCCESS)
@@ -1637,8 +1658,10 @@ winreg_QueryValueEx_impl(PyObject *module, HKEY key, const wchar_t *name)
while (1) {
retSize = bufSize;
+ Py_BEGIN_ALLOW_THREADS
rc = RegQueryValueExW(key, name, NULL, &typ,
(BYTE *)retBuf, &retSize);
+ Py_END_ALLOW_THREADS
if (rc != ERROR_MORE_DATA)
break;