Home | History | Annotate | Download | only in PC
      1 '''
      2 This script gets the version number from ucrtbased.dll and checks
      3 whether it is a version with a known issue.
      4 '''
      5 
      6 import sys
      7 
      8 from ctypes import (c_buffer, POINTER, byref, create_unicode_buffer,
      9                     Structure, WinDLL)
     10 from ctypes.wintypes import DWORD, HANDLE
     11 
     12 class VS_FIXEDFILEINFO(Structure):
     13     _fields_ = [
     14         ("dwSignature", DWORD),
     15         ("dwStrucVersion", DWORD),
     16         ("dwFileVersionMS", DWORD),
     17         ("dwFileVersionLS", DWORD),
     18         ("dwProductVersionMS", DWORD),
     19         ("dwProductVersionLS", DWORD),
     20         ("dwFileFlagsMask", DWORD),
     21         ("dwFileFlags", DWORD),
     22         ("dwFileOS", DWORD),
     23         ("dwFileType", DWORD),
     24         ("dwFileSubtype", DWORD),
     25         ("dwFileDateMS", DWORD),
     26         ("dwFileDateLS", DWORD),
     27     ]
     28 
     29 kernel32 = WinDLL('kernel32')
     30 version = WinDLL('version')
     31 
     32 if len(sys.argv) < 2:
     33     print('Usage: validate_ucrtbase.py <ucrtbase|ucrtbased>')
     34     sys.exit(2)
     35 
     36 try:
     37     ucrtbased = WinDLL(sys.argv[1])
     38 except OSError:
     39     print('Cannot find ucrtbased.dll')
     40     # This likely means that VS is not installed, but that is an
     41     # obvious enough problem if you're trying to produce a debug
     42     # build that we don't need to fail here.
     43     sys.exit(0)
     44 
     45 # We will immediately double the length up to MAX_PATH, but the
     46 # path may be longer, so we retry until the returned string is
     47 # shorter than our buffer.
     48 name_len = actual_len = 130
     49 while actual_len == name_len:
     50     name_len *= 2
     51     name = create_unicode_buffer(name_len)
     52     actual_len = kernel32.GetModuleFileNameW(HANDLE(ucrtbased._handle),
     53                                              name, len(name))
     54     if not actual_len:
     55         print('Failed to get full module name.')
     56         sys.exit(2)
     57 
     58 size = version.GetFileVersionInfoSizeW(name, None)
     59 if not size:
     60     print('Failed to get size of version info.')
     61     sys.exit(2)
     62 
     63 ver_block = c_buffer(size)
     64 if (not version.GetFileVersionInfoW(name, None, size, ver_block) or
     65     not ver_block):
     66     print('Failed to get version info.')
     67     sys.exit(2)
     68 
     69 pvi = POINTER(VS_FIXEDFILEINFO)()
     70 if not version.VerQueryValueW(ver_block, "", byref(pvi), byref(DWORD())):
     71     print('Failed to get version value from info.')
     72     sys.exit(2)
     73 
     74 ver = (
     75     pvi.contents.dwProductVersionMS >> 16,
     76     pvi.contents.dwProductVersionMS & 0xFFFF,
     77     pvi.contents.dwProductVersionLS >> 16,
     78     pvi.contents.dwProductVersionLS & 0xFFFF,
     79 )
     80 
     81 print('{} is version {}.{}.{}.{}'.format(name.value, *ver))
     82 
     83 if ver < (10, 0, 10586):
     84     print('WARN: ucrtbased contains known issues. '
     85           'Please update the Windows 10 SDK.')
     86     print('See:')
     87     print('  http://bugs.python.org/issue27705')
     88     print('  https://developer.microsoft.com/en-US/windows/downloads/windows-10-sdk')
     89     sys.exit(1)
     90