aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/sysmodule.c
diff options
context:
space:
mode:
authorSteve Dower <steve.dower@python.org>2022-09-07 21:09:20 +0100
committerGitHub <noreply@github.com>2022-09-07 21:09:20 +0100
commitde33df27aaf930be6a34027c530a651f0b4c91f5 (patch)
tree789d8df85c96cdf28c36a3e89f65d96d49949bc5 /Python/sysmodule.c
parent4114bcc9ef7595a07196bcecf9c7d6d39f57f64d (diff)
downloadcpython-de33df27aaf930be6a34027c530a651f0b4c91f5.tar.gz
cpython-de33df27aaf930be6a34027c530a651f0b4c91f5.zip
gh-89545: Updates platform module to use new internal _wmi module on Windows to directly query OS properties (GH-96289)
Diffstat (limited to 'Python/sysmodule.c')
-rw-r--r--Python/sysmodule.c93
1 files changed, 63 insertions, 30 deletions
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index a33abb2a841..653b5a55e88 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -1487,6 +1487,44 @@ static PyStructSequence_Desc windows_version_desc = {
via indexing, the rest are name only */
};
+static PyObject *
+_sys_getwindowsversion_from_kernel32()
+{
+ HANDLE hKernel32;
+ wchar_t kernel32_path[MAX_PATH];
+ LPVOID verblock;
+ DWORD verblock_size;
+ VS_FIXEDFILEINFO *ffi;
+ UINT ffi_len;
+ DWORD realMajor, realMinor, realBuild;
+
+ Py_BEGIN_ALLOW_THREADS
+ hKernel32 = GetModuleHandleW(L"kernel32.dll");
+ Py_END_ALLOW_THREADS
+ if (!hKernel32 || !GetModuleFileNameW(hKernel32, kernel32_path, MAX_PATH)) {
+ PyErr_SetFromWindowsErr(0);
+ return NULL;
+ }
+ verblock_size = GetFileVersionInfoSizeW(kernel32_path, NULL);
+ if (!verblock_size) {
+ PyErr_SetFromWindowsErr(0);
+ return NULL;
+ }
+ verblock = PyMem_RawMalloc(verblock_size);
+ if (!verblock ||
+ !GetFileVersionInfoW(kernel32_path, 0, verblock_size, verblock) ||
+ !VerQueryValueW(verblock, L"", (LPVOID)&ffi, &ffi_len)) {
+ PyErr_SetFromWindowsErr(0);
+ return NULL;
+ }
+
+ realMajor = HIWORD(ffi->dwProductVersionMS);
+ realMinor = LOWORD(ffi->dwProductVersionMS);
+ realBuild = HIWORD(ffi->dwProductVersionLS);
+ PyMem_RawFree(verblock);
+ return Py_BuildValue("(kkk)", realMajor, realMinor, realBuild);
+}
+
/* Disable deprecation warnings about GetVersionEx as the result is
being passed straight through to the caller, who is responsible for
using it correctly. */
@@ -1516,11 +1554,13 @@ sys_getwindowsversion_impl(PyObject *module)
PyObject *version;
int pos = 0;
OSVERSIONINFOEXW ver;
- DWORD realMajor, realMinor, realBuild;
- HANDLE hKernel32;
- wchar_t kernel32_path[MAX_PATH];
- LPVOID verblock;
- DWORD verblock_size;
+
+ version = PyObject_GetAttrString(module, "_cached_windows_version");
+ if (version && PyObject_TypeCheck(version, &WindowsVersionType)) {
+ return version;
+ }
+ Py_XDECREF(version);
+ PyErr_Clear();
ver.dwOSVersionInfoSize = sizeof(ver);
if (!GetVersionExW((OSVERSIONINFOW*) &ver))
@@ -1540,41 +1580,34 @@ sys_getwindowsversion_impl(PyObject *module)
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wSuiteMask));
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wProductType));
- realMajor = ver.dwMajorVersion;
- realMinor = ver.dwMinorVersion;
- realBuild = ver.dwBuildNumber;
-
// GetVersion will lie if we are running in a compatibility mode.
// We need to read the version info from a system file resource
// to accurately identify the OS version. If we fail for any reason,
// just return whatever GetVersion said.
- Py_BEGIN_ALLOW_THREADS
- hKernel32 = GetModuleHandleW(L"kernel32.dll");
- Py_END_ALLOW_THREADS
- if (hKernel32 && GetModuleFileNameW(hKernel32, kernel32_path, MAX_PATH) &&
- (verblock_size = GetFileVersionInfoSizeW(kernel32_path, NULL)) &&
- (verblock = PyMem_RawMalloc(verblock_size))) {
- VS_FIXEDFILEINFO *ffi;
- UINT ffi_len;
-
- if (GetFileVersionInfoW(kernel32_path, 0, verblock_size, verblock) &&
- VerQueryValueW(verblock, L"", (LPVOID)&ffi, &ffi_len)) {
- realMajor = HIWORD(ffi->dwProductVersionMS);
- realMinor = LOWORD(ffi->dwProductVersionMS);
- realBuild = HIWORD(ffi->dwProductVersionLS);
- }
- PyMem_RawFree(verblock);
+ PyObject *realVersion = _sys_getwindowsversion_from_kernel32();
+ if (!realVersion) {
+ PyErr_Clear();
+ realVersion = Py_BuildValue("(kkk)",
+ ver.dwMajorVersion,
+ ver.dwMinorVersion,
+ ver.dwBuildNumber
+ );
+ }
+
+ if (realVersion) {
+ PyStructSequence_SET_ITEM(version, pos++, realVersion);
}
- PyStructSequence_SET_ITEM(version, pos++, Py_BuildValue("(kkk)",
- realMajor,
- realMinor,
- realBuild
- ));
if (PyErr_Occurred()) {
Py_DECREF(version);
return NULL;
}
+
+ if (PyObject_SetAttrString(module, "_cached_windows_version", version) < 0) {
+ Py_DECREF(version);
+ return NULL;
+ }
+
return version;
}