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 ESC[4;38;5;81mVS_FIXEDFILEINFO(ESC[4;38;5;149mStructure):
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)