|
| 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 Visual Studio or the Windows SDK.') |
| 86 | + print('See:') |
| 87 | + print(' http://bugs.python.org/issue26624') |
| 88 | + sys.exit(1) |
0 commit comments