Skip to content

Commit a7a222f

Browse files
committed
Closes python#26624: Adds validation of ucrtbase[d].dll version with warning for old versions.
1 parent 1b80b24 commit a7a222f

File tree

4 files changed

+99
-2
lines changed

4 files changed

+99
-2
lines changed

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,9 @@ Tests
385385
Build
386386
-----
387387

388+
- Issue #26624: Adds validation of ucrtbase[d].dll version with warning
389+
for old versions.
390+
388391
- Issue #17603: Avoid error about nonexistant fileblocks.o file by using a
389392
lower-level check for st_blocks in struct stat.
390393

PC/python_ver_rc.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@
99
#define MS_WINDOWS
1010
#include "modsupport.h"
1111
#include "patchlevel.h"
12+
#include <pythonnt_rc.h>
1213
#ifdef _DEBUG
13-
# include <pythonnt_rc_d.h>
1414
# define PYTHON_DEBUG_EXT "_d"
1515
#else
16-
# include <pythonnt_rc.h>
1716
# define PYTHON_DEBUG_EXT
1817
#endif
1918

PC/validate_ucrtbase.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
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)

PCbuild/python.vcxproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@
8383
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
8484
<ImportGroup Label="ExtensionTargets">
8585
</ImportGroup>
86+
<Target Name="ValidateUcrtbase" AfterTargets="AfterBuild">
87+
<PropertyGroup>
88+
<UcrtName>ucrtbase</UcrtName>
89+
<UcrtName Condition="'$(Configuration)' == 'Debug'">ucrtbased</UcrtName>
90+
</PropertyGroup>
91+
<Exec Command='"$(OutDir)python$(PyDebugExt).exe" "$(PySourcePath)PC\validate_ucrtbase.py" $(UcrtName)' ContinueOnError="true" />
92+
</Target>
8693
<Target Name="GeneratePythonBat" AfterTargets="AfterBuild">
8794
<PropertyGroup>
8895
<_Content>@rem This script invokes the most recently built Python with all arguments

0 commit comments

Comments
 (0)