Bug 1193033 - Teach mozinfo to get the real os version number for Windows >= 8.1, r=ted
authorJames Graham <james@hoppipolla.co.uk>
Tue, 11 Aug 2015 16:43:20 +0100
changeset 290415 1989889145ce0f32bec326eb32d84d59eaf40eec
parent 290414 d791ba00bf065740fc504329a1075f5132cdc800
child 290416 c69d8db6828a4f39118a64c96a5f1a52b27e9170
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs1193033
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1193033 - Teach mozinfo to get the real os version number for Windows >= 8.1, r=ted For contemporary versions of Windows the sys.getwindowsversion call is unreliable because it depends on a API which had its return value frozen. If we detect this case use an alternate API instead
testing/mozbase/mozinfo/mozinfo/mozinfo.py
--- a/testing/mozbase/mozinfo/mozinfo/mozinfo.py
+++ b/testing/mozbase/mozinfo/mozinfo/mozinfo.py
@@ -23,16 +23,39 @@ from .string_version import StringVersio
 class unknown(object):
     """marker class for unknown information"""
     def __nonzero__(self):
         return False
     def __str__(self):
         return 'UNKNOWN'
 unknown = unknown() # singleton
 
+def get_windows_version():
+    import ctypes
+    class OSVERSIONINFOEXW(ctypes.Structure):
+        _fields_ = [('dwOSVersionInfoSize', ctypes.c_ulong),
+                    ('dwMajorVersion', ctypes.c_ulong),
+                    ('dwMinorVersion', ctypes.c_ulong),
+                    ('dwBuildNumber', ctypes.c_ulong),
+                    ('dwPlatformId', ctypes.c_ulong),
+                    ('szCSDVersion', ctypes.c_wchar*128),
+                    ('wServicePackMajor', ctypes.c_ushort),
+                    ('wServicePackMinor', ctypes.c_ushort),
+                    ('wSuiteMask', ctypes.c_ushort),
+                    ('wProductType', ctypes.c_byte),
+                    ('wReserved', ctypes.c_byte)]
+
+    os_version = OSVERSIONINFOEXW()
+    os_version.dwOSVersionInfoSize = ctypes.sizeof(os_version)
+    retcode = ctypes.windll.Ntdll.RtlGetVersion(ctypes.byref(os_version))
+    if retcode != 0:
+        raise OSError
+
+    return os_version.dwMajorVersion, os_version.dwMinorVersion, os_version.dwBuildNumber
+
 # get system information
 info = {'os': unknown,
         'processor': unknown,
         'version': unknown,
         'os_version': unknown,
         'bits': unknown,
         'has_sandbox': unknown }
 (system, node, release, version, machine, processor) = platform.uname()
@@ -45,16 +68,24 @@ if system in ["Microsoft", "Windows"]:
     # http://bugs.python.org/issue7860
     if "PROCESSOR_ARCHITEW6432" in os.environ:
         processor = os.environ.get("PROCESSOR_ARCHITEW6432", processor)
     else:
         processor = os.environ.get('PROCESSOR_ARCHITECTURE', processor)
     system = os.environ.get("OS", system).replace('_', ' ')
     (major, minor, _, _, service_pack) = os.sys.getwindowsversion()
     info['service_pack'] = service_pack
+    if major >= 6 and minor >= 2:
+        # On windows >= 8.1 the system call that getwindowsversion uses has
+        # been frozen to always return the same values. In this case we call
+        # the RtlGetVersion API directly, which still provides meaningful
+        # values, at least for now.
+        major, minor, build_number = get_windows_version()
+        version = "%d.%d.%d" % (major, minor, build_number)
+
     os_version = "%d.%d" % (major, minor)
 elif system == "Linux":
     if hasattr(platform, "linux_distribution"):
         (distro, os_version, codename) = platform.linux_distribution()
     else:
         (distro, os_version, codename) = platform.dist()
     if not processor:
         processor = machine