diff options
author | Steve Dower <steve.dower@python.org> | 2022-09-07 21:09:20 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-07 21:09:20 +0100 |
commit | de33df27aaf930be6a34027c530a651f0b4c91f5 (patch) | |
tree | 789d8df85c96cdf28c36a3e89f65d96d49949bc5 /Python/sysmodule.c | |
parent | 4114bcc9ef7595a07196bcecf9c7d6d39f57f64d (diff) | |
download | cpython-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.c | 93 |
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; } |