|
26 | 26 | # Betancourt, Randall Hopper, Karl Putland, John Farrell, Greg
|
27 | 27 | # Andruk, Just van Rossum, Thomas Heller, Mark R. Levinson, Mark
|
28 | 28 | # 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 |
30 | 31 | #
|
31 | 32 | # History:
|
32 | 33 | #
|
33 | 34 | # <see CVS and SVN checkin messages for history>
|
34 | 35 | #
|
| 36 | +# 1.0.8 - changed Windows support to read version from kernel32.dll |
35 | 37 | # 1.0.7 - added DEV_NULL
|
36 | 38 | # 1.0.6 - added linux_distribution()
|
37 | 39 | # 1.0.5 - fixed Java support to allow running the module on Jython
|
@@ -469,189 +471,139 @@ def _syscmd_ver(system='', release='', version='',
|
469 | 471 | version=_norm_version(version)
|
470 | 472 | returnsystem,release,version
|
471 | 473 |
|
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 | +} |
473 | 491 |
|
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", |
475 | 495 |
|
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 | +} |
477 | 502 |
|
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 |
490 | 561 |
|
491 | 562 | 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 |
492 | 568 |
|
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) |
504 | 572 |
|
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) |
508 | 576 |
|
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): |
526 | 581 | try:
|
527 |
| -sys.getwindowsversion |
| 582 | +csd='SP{}'.format(winver.service_pack_major) |
528 | 583 | 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:] |
620 | 586 |
|
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) |
626 | 592 |
|
627 |
| -# Open the registry key |
| 593 | +key=None |
628 | 594 | 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] |
632 | 598 | 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 | + |
653 | 604 | returnrelease,version,csd,ptype
|
654 | 605 |
|
| 606 | + |
655 | 607 | def_mac_ver_xml():
|
656 | 608 | fn='/System/Library/CoreServices/SystemVersion.plist'
|
657 | 609 | ifnotos.path.exists(fn):
|
|