Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb9f4fea

Browse files
committed
Issue#19143: platform module now reads Windows version from kernel32.dll to avoid compatibility shims.
1 parenta2ea0e4 commitb9f4fea

File tree

2 files changed

+123
-168
lines changed

2 files changed

+123
-168
lines changed

‎Lib/platform.py

Lines changed: 120 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,14 @@
2626
# Betancourt, Randall Hopper, Karl Putland, John Farrell, Greg
2727
# Andruk, Just van Rossum, Thomas Heller, Mark R. Levinson, Mark
2828
# Hammond, Bill Tutt, Hans Nowak, Uwe Zessin (OpenVMS support),
29-
# Colin Kong, Trent Mick, Guido van Rossum, Anthony Baxter
29+
# Colin Kong, Trent Mick, Guido van Rossum, Anthony Baxter, Steve
30+
# Dower
3031
#
3132
# History:
3233
#
3334
# <see CVS and SVN checkin messages for history>
3435
#
36+
# 1.0.8 - changed Windows support to read version from kernel32.dll
3537
# 1.0.7 - added DEV_NULL
3638
# 1.0.6 - added linux_distribution()
3739
# 1.0.5 - fixed Java support to allow running the module on Jython
@@ -469,189 +471,139 @@ def _syscmd_ver(system='', release='', version='',
469471
version=_norm_version(version)
470472
returnsystem,release,version
471473

472-
def_win32_getvalue(key,name,default=''):
474+
_WIN32_CLIENT_RELEASES= {
475+
(5,0):"2000",
476+
(5,1):"XP",
477+
# Strictly, 5.2 client is XP 64-bit, but platform.py historically
478+
# has always called it 2003 Server
479+
(5,2):"2003Server",
480+
(5,None):"post2003",
481+
482+
(6,0):"Vista",
483+
(6,1):"7",
484+
(6,2):"8",
485+
(6,3):"8.1",
486+
(6,None):"post8.1",
487+
488+
(10,0):"10",
489+
(10,None):"post10",
490+
}
473491

474-
""" Read a value for name from the registry key.
492+
# Server release name lookup will default to client names if necessary
493+
_WIN32_SERVER_RELEASES= {
494+
(5,2):"2003Server",
475495

476-
In case this fails, default is returned.
496+
(6,0):"2008Server",
497+
(6,1):"2008ServerR2",
498+
(6,2):"2012Server",
499+
(6,3):"2012ServerR2",
500+
(6,None):"post2012ServerR2",
501+
}
477502

478-
"""
479-
try:
480-
# Use win32api if available
481-
fromwin32apiimportRegQueryValueEx
482-
exceptImportError:
483-
# On Python 2.0 and later, emulate using winreg
484-
importwinreg
485-
RegQueryValueEx=winreg.QueryValueEx
486-
try:
487-
returnRegQueryValueEx(key,name)
488-
except:
489-
returndefault
503+
def_get_real_winver(maj,min,build):
504+
ifmaj<6or (maj==6andmin<2):
505+
returnmaj,min,build
506+
507+
fromctypesimport (c_buffer,POINTER,byref,create_unicode_buffer,
508+
Structure,WinDLL)
509+
fromctypes.wintypesimportDWORD,HANDLE
510+
511+
classVS_FIXEDFILEINFO(Structure):
512+
_fields_= [
513+
("dwSignature",DWORD),
514+
("dwStrucVersion",DWORD),
515+
("dwFileVersionMS",DWORD),
516+
("dwFileVersionLS",DWORD),
517+
("dwProductVersionMS",DWORD),
518+
("dwProductVersionLS",DWORD),
519+
("dwFileFlagsMask",DWORD),
520+
("dwFileFlags",DWORD),
521+
("dwFileOS",DWORD),
522+
("dwFileType",DWORD),
523+
("dwFileSubtype",DWORD),
524+
("dwFileDateMS",DWORD),
525+
("dwFileDateLS",DWORD),
526+
]
527+
528+
kernel32=WinDLL('kernel32')
529+
version=WinDLL('version')
530+
531+
# We will immediately double the length up to MAX_PATH, but the
532+
# path may be longer, so we retry until the returned string is
533+
# shorter than our buffer.
534+
name_len=actual_len=130
535+
whileactual_len==name_len:
536+
name_len*=2
537+
name=create_unicode_buffer(name_len)
538+
actual_len=kernel32.GetModuleFileNameW(HANDLE(kernel32._handle),
539+
name,len(name))
540+
ifnotactual_len:
541+
returnmaj,min,build
542+
543+
size=version.GetFileVersionInfoSizeW(name,None)
544+
ifnotsize:
545+
returnmaj,min,build
546+
547+
ver_block=c_buffer(size)
548+
if (notversion.GetFileVersionInfoW(name,None,size,ver_block)or
549+
notver_block):
550+
returnmaj,min,build
551+
552+
pvi=POINTER(VS_FIXEDFILEINFO)()
553+
ifnotversion.VerQueryValueW(ver_block,"",byref(pvi),byref(DWORD())):
554+
returnmaj,min,build
555+
556+
maj=pvi.contents.dwProductVersionMS>>16
557+
min=pvi.contents.dwProductVersionMS&0xFFFF
558+
build=pvi.contents.dwProductVersionLS>>16
559+
560+
returnmaj,min,build
490561

491562
defwin32_ver(release='',version='',csd='',ptype=''):
563+
fromsysimportgetwindowsversion
564+
try:
565+
fromwinregimportOpenKeyEx,QueryValueEx,CloseKey,HKEY_LOCAL_MACHINE
566+
exceptImportError:
567+
from_winregimportOpenKeyEx,QueryValueEx,CloseKey,HKEY_LOCAL_MACHINE
492568

493-
""" Get additional version information from the Windows Registry
494-
and return a tuple (version, csd, ptype) referring to version
495-
number, CSD level (service pack), and OS type (multi/single
496-
processor).
497-
498-
As a hint: ptype returns 'Uniprocessor Free' on single
499-
processor NT machines and 'Multiprocessor Free' on multi
500-
processor machines. The 'Free' refers to the OS version being
501-
free of debugging code. It could also state 'Checked' which
502-
means the OS version uses debugging code, i.e. code that
503-
checks arguments, ranges, etc. (Thomas Heller).
569+
winver=getwindowsversion()
570+
maj,min,build=_get_real_winver(*winver[:3])
571+
version='{0}.{1}.{2}'.format(maj,min,build)
504572

505-
Note: this function works best with Mark Hammond's win32
506-
package installed, but also on Python 2.3 and later. It
507-
obviously only runs on Win32 compatible platforms.
573+
release= (_WIN32_CLIENT_RELEASES.get((maj,min))or
574+
_WIN32_CLIENT_RELEASES.get((maj,None))or
575+
release)
508576

509-
"""
510-
# XXX Is there any way to find out the processor type on WinXX ?
511-
# XXX Is win32 available on Windows CE ?
512-
#
513-
# Adapted from code posted by Karl Putland to comp.lang.python.
514-
#
515-
# The mappings between reg. values and release names can be found
516-
# here: http://msdn.microsoft.com/library/en-us/sysinfo/base/osversioninfo_str.asp
517-
518-
# Import the needed APIs
519-
try:
520-
fromwin32apiimportRegQueryValueEx,RegOpenKeyEx, \
521-
RegCloseKey,GetVersionEx
522-
fromwin32conimportHKEY_LOCAL_MACHINE,VER_PLATFORM_WIN32_NT, \
523-
VER_PLATFORM_WIN32_WINDOWS,VER_NT_WORKSTATION
524-
exceptImportError:
525-
# Emulate the win32api module using Python APIs
577+
# getwindowsversion() reflect the compatibility mode Python is
578+
# running under, and so the service pack value is only going to be
579+
# valid if the versions match.
580+
ifwinver[:2]== (maj,min):
526581
try:
527-
sys.getwindowsversion
582+
csd='SP{}'.format(winver.service_pack_major)
528583
exceptAttributeError:
529-
# No emulation possible, so return the defaults...
530-
returnrelease,version,csd,ptype
531-
else:
532-
# Emulation using winreg (added in Python 2.0) and
533-
# sys.getwindowsversion() (added in Python 2.3)
534-
importwinreg
535-
GetVersionEx=sys.getwindowsversion
536-
RegQueryValueEx=winreg.QueryValueEx
537-
RegOpenKeyEx=winreg.OpenKeyEx
538-
RegCloseKey=winreg.CloseKey
539-
HKEY_LOCAL_MACHINE=winreg.HKEY_LOCAL_MACHINE
540-
VER_PLATFORM_WIN32_WINDOWS=1
541-
VER_PLATFORM_WIN32_NT=2
542-
VER_NT_WORKSTATION=1
543-
VER_NT_SERVER=3
544-
REG_SZ=1
545-
546-
# Find out the registry key and some general version infos
547-
winver=GetVersionEx()
548-
maj,min,buildno,plat,csd=winver
549-
version='%i.%i.%i'% (maj,min,buildno&0xFFFF)
550-
ifhasattr(winver,"service_pack"):
551-
ifwinver.service_pack!="":
552-
csd='SP%s'%winver.service_pack_major
553-
else:
554-
ifcsd[:13]=='Service Pack ':
555-
csd='SP'+csd[13:]
556-
557-
ifplat==VER_PLATFORM_WIN32_WINDOWS:
558-
regkey='SOFTWARE\\Microsoft\\Windows\\CurrentVersion'
559-
# Try to guess the release name
560-
ifmaj==4:
561-
ifmin==0:
562-
release='95'
563-
elifmin==10:
564-
release='98'
565-
elifmin==90:
566-
release='Me'
567-
else:
568-
release='postMe'
569-
elifmaj==5:
570-
release='2000'
571-
572-
elifplat==VER_PLATFORM_WIN32_NT:
573-
regkey='SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion'
574-
ifmaj<=4:
575-
release='NT'
576-
elifmaj==5:
577-
ifmin==0:
578-
release='2000'
579-
elifmin==1:
580-
release='XP'
581-
elifmin==2:
582-
release='2003Server'
583-
else:
584-
release='post2003'
585-
elifmaj==6:
586-
ifhasattr(winver,"product_type"):
587-
product_type=winver.product_type
588-
else:
589-
product_type=VER_NT_WORKSTATION
590-
# Without an OSVERSIONINFOEX capable sys.getwindowsversion(),
591-
# or help from the registry, we cannot properly identify
592-
# non-workstation versions.
593-
try:
594-
key=RegOpenKeyEx(HKEY_LOCAL_MACHINE,regkey)
595-
name,type=RegQueryValueEx(key,"ProductName")
596-
# Discard any type that isn't REG_SZ
597-
iftype==REG_SZandname.find("Server")!=-1:
598-
product_type=VER_NT_SERVER
599-
exceptOSError:
600-
# Use default of VER_NT_WORKSTATION
601-
pass
602-
603-
ifmin==0:
604-
ifproduct_type==VER_NT_WORKSTATION:
605-
release='Vista'
606-
else:
607-
release='2008Server'
608-
elifmin==1:
609-
ifproduct_type==VER_NT_WORKSTATION:
610-
release='7'
611-
else:
612-
release='2008ServerR2'
613-
elifmin==2:
614-
ifproduct_type==VER_NT_WORKSTATION:
615-
release='8'
616-
else:
617-
release='2012Server'
618-
else:
619-
release='post2012Server'
584+
ifcsd[:13]=='Service Pack ':
585+
csd='SP'+csd[13:]
620586

621-
else:
622-
ifnotrelease:
623-
# E.g. Win3.1 with win32s
624-
release='%i.%i'% (maj,min)
625-
returnrelease,version,csd,ptype
587+
# VER_NT_SERVER = 3
588+
ifgetattr(winver,'product_type',None)==3:
589+
release= (_WIN32_SERVER_RELEASES.get((maj,min))or
590+
_WIN32_SERVER_RELEASES.get((maj,None))or
591+
release)
626592

627-
# Open the registry key
593+
key=None
628594
try:
629-
keyCurVer=RegOpenKeyEx(HKEY_LOCAL_MACHINE,regkey)
630-
# Get a value to make sure the key exists...
631-
RegQueryValueEx(keyCurVer,'SystemRoot')
595+
key=OpenKeyEx(HKEY_LOCAL_MACHINE,
596+
r'SOFTWARE\Microsoft\Windows NT\CurrentVersion')
597+
ptype=QueryValueEx(key,'CurrentType')[0]
632598
except:
633-
returnrelease,version,csd,ptype
634-
635-
# Parse values
636-
#subversion = _win32_getvalue(keyCurVer,
637-
# 'SubVersionNumber',
638-
# ('',1))[0]
639-
#if subversion:
640-
# release = release + subversion # 95a, 95b, etc.
641-
build=_win32_getvalue(keyCurVer,
642-
'CurrentBuildNumber',
643-
('',1))[0]
644-
ptype=_win32_getvalue(keyCurVer,
645-
'CurrentType',
646-
(ptype,1))[0]
647-
648-
# Normalize version
649-
version=_norm_version(version,build)
650-
651-
# Close key
652-
RegCloseKey(keyCurVer)
599+
pass
600+
finally:
601+
ifkey:
602+
CloseKey(key)
603+
653604
returnrelease,version,csd,ptype
654605

606+
655607
def_mac_ver_xml():
656608
fn='/System/Library/CoreServices/SystemVersion.plist'
657609
ifnotos.path.exists(fn):

‎Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ Core and Builtins
1818
Library
1919
-------
2020

21+
- Issue #19143: platform module now reads Windows version from kernel32.dll to
22+
avoid compatibility shims.
23+
2124
- Issue #25092: Fix datetime.strftime() failure when errno was already set to
2225
EINVAL.
2326

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp