17db96d56Sopenharmony_ci'''
27db96d56Sopenharmony_ciThis script gets the version number from ucrtbased.dll and checks
37db96d56Sopenharmony_ciwhether it is a version with a known issue.
47db96d56Sopenharmony_ci'''
57db96d56Sopenharmony_ci
67db96d56Sopenharmony_ciimport sys
77db96d56Sopenharmony_ci
87db96d56Sopenharmony_cifrom ctypes import (c_buffer, POINTER, byref, create_unicode_buffer,
97db96d56Sopenharmony_ci                    Structure, WinDLL)
107db96d56Sopenharmony_cifrom ctypes.wintypes import DWORD, HANDLE
117db96d56Sopenharmony_ci
127db96d56Sopenharmony_ciclass VS_FIXEDFILEINFO(Structure):
137db96d56Sopenharmony_ci    _fields_ = [
147db96d56Sopenharmony_ci        ("dwSignature", DWORD),
157db96d56Sopenharmony_ci        ("dwStrucVersion", DWORD),
167db96d56Sopenharmony_ci        ("dwFileVersionMS", DWORD),
177db96d56Sopenharmony_ci        ("dwFileVersionLS", DWORD),
187db96d56Sopenharmony_ci        ("dwProductVersionMS", DWORD),
197db96d56Sopenharmony_ci        ("dwProductVersionLS", DWORD),
207db96d56Sopenharmony_ci        ("dwFileFlagsMask", DWORD),
217db96d56Sopenharmony_ci        ("dwFileFlags", DWORD),
227db96d56Sopenharmony_ci        ("dwFileOS", DWORD),
237db96d56Sopenharmony_ci        ("dwFileType", DWORD),
247db96d56Sopenharmony_ci        ("dwFileSubtype", DWORD),
257db96d56Sopenharmony_ci        ("dwFileDateMS", DWORD),
267db96d56Sopenharmony_ci        ("dwFileDateLS", DWORD),
277db96d56Sopenharmony_ci    ]
287db96d56Sopenharmony_ci
297db96d56Sopenharmony_cikernel32 = WinDLL('kernel32')
307db96d56Sopenharmony_civersion = WinDLL('version')
317db96d56Sopenharmony_ci
327db96d56Sopenharmony_ciif len(sys.argv) < 2:
337db96d56Sopenharmony_ci    print('Usage: validate_ucrtbase.py <ucrtbase|ucrtbased>')
347db96d56Sopenharmony_ci    sys.exit(2)
357db96d56Sopenharmony_ci
367db96d56Sopenharmony_citry:
377db96d56Sopenharmony_ci    ucrtbased = WinDLL(sys.argv[1])
387db96d56Sopenharmony_ciexcept OSError:
397db96d56Sopenharmony_ci    print('Cannot find ucrtbased.dll')
407db96d56Sopenharmony_ci    # This likely means that VS is not installed, but that is an
417db96d56Sopenharmony_ci    # obvious enough problem if you're trying to produce a debug
427db96d56Sopenharmony_ci    # build that we don't need to fail here.
437db96d56Sopenharmony_ci    sys.exit(0)
447db96d56Sopenharmony_ci
457db96d56Sopenharmony_ci# We will immediately double the length up to MAX_PATH, but the
467db96d56Sopenharmony_ci# path may be longer, so we retry until the returned string is
477db96d56Sopenharmony_ci# shorter than our buffer.
487db96d56Sopenharmony_ciname_len = actual_len = 130
497db96d56Sopenharmony_ciwhile actual_len == name_len:
507db96d56Sopenharmony_ci    name_len *= 2
517db96d56Sopenharmony_ci    name = create_unicode_buffer(name_len)
527db96d56Sopenharmony_ci    actual_len = kernel32.GetModuleFileNameW(HANDLE(ucrtbased._handle),
537db96d56Sopenharmony_ci                                             name, len(name))
547db96d56Sopenharmony_ci    if not actual_len:
557db96d56Sopenharmony_ci        print('Failed to get full module name.')
567db96d56Sopenharmony_ci        sys.exit(2)
577db96d56Sopenharmony_ci
587db96d56Sopenharmony_cisize = version.GetFileVersionInfoSizeW(name, None)
597db96d56Sopenharmony_ciif not size:
607db96d56Sopenharmony_ci    print('Failed to get size of version info.')
617db96d56Sopenharmony_ci    sys.exit(2)
627db96d56Sopenharmony_ci
637db96d56Sopenharmony_civer_block = c_buffer(size)
647db96d56Sopenharmony_ciif (not version.GetFileVersionInfoW(name, None, size, ver_block) or
657db96d56Sopenharmony_ci    not ver_block):
667db96d56Sopenharmony_ci    print('Failed to get version info.')
677db96d56Sopenharmony_ci    sys.exit(2)
687db96d56Sopenharmony_ci
697db96d56Sopenharmony_cipvi = POINTER(VS_FIXEDFILEINFO)()
707db96d56Sopenharmony_ciif not version.VerQueryValueW(ver_block, "", byref(pvi), byref(DWORD())):
717db96d56Sopenharmony_ci    print('Failed to get version value from info.')
727db96d56Sopenharmony_ci    sys.exit(2)
737db96d56Sopenharmony_ci
747db96d56Sopenharmony_civer = (
757db96d56Sopenharmony_ci    pvi.contents.dwProductVersionMS >> 16,
767db96d56Sopenharmony_ci    pvi.contents.dwProductVersionMS & 0xFFFF,
777db96d56Sopenharmony_ci    pvi.contents.dwProductVersionLS >> 16,
787db96d56Sopenharmony_ci    pvi.contents.dwProductVersionLS & 0xFFFF,
797db96d56Sopenharmony_ci)
807db96d56Sopenharmony_ci
817db96d56Sopenharmony_ciprint('{} is version {}.{}.{}.{}'.format(name.value, *ver))
827db96d56Sopenharmony_ci
837db96d56Sopenharmony_ciif ver < (10, 0, 10586):
847db96d56Sopenharmony_ci    print('WARN: ucrtbased contains known issues. '
857db96d56Sopenharmony_ci          'Please update the Windows 10 SDK.')
867db96d56Sopenharmony_ci    print('See:')
877db96d56Sopenharmony_ci    print('  http://bugs.python.org/issue27705')
887db96d56Sopenharmony_ci    print('  https://developer.microsoft.com/en-US/windows/downloads/windows-10-sdk')
897db96d56Sopenharmony_ci    sys.exit(1)
90