Source code for platformids.dist.nt.windows_subprocess_reg_exe

# -*- coding: utf-8 -*-
"""Reads the MS-Windows registry by calling a subprocess for reg.exe.

This is a fallback solution when neither *winreg* / *_winreg*, nor in case 
of Jython the Java APIs such as *WindowsPref*, *JNA*, or *JNI* are not
available.
This works also on *Cygwin*, when e.g. the path for *kernel32.dll* does not
match for the *ctypes*.

Avoid using it due to serious performance impact compared to 
the others - but do when nothing else helps and the 
version information matters. 
"""
from __future__ import absolute_import

import re

from subprocess import Popen, PIPE

from platformids import PlatformIDsError
from platformids.dist.windows import VER_NT_SERVER, VER_NT_WORKSTATION, \
    VER_NT_DOMAIN_CONTROLLER, VER_NT_IOT, VER_NT_GENERIC


__author__ = 'Arno-Can Uestuensoez'
__license__ = "Artistic-License-2.0 + Forced-Fairplay-Constraints"
__copyright__ = "Copyright (C) 2010-2018 Arno-Can Uestuensoez" \
                " @Ingenieurbuero Arno-Can Uestuensoez"
__version__ = '0.1.2'
__uuid__ = "7add5ded-c39b-4b6e-8c87-1b3a1c150ee9"

__docformat__ = "restructuredtext en"


[docs]class PlatformIDsReadRegExeError(PlatformIDsError): pass
[docs]class RegistryByExe(object): """Registry read access by *reg.exe* to :: "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion" """
[docs] def __init__(self): #: used as cache for following calls #: the cache represents this platform, so may not be altered self.result = {} # cached product type self.product_type = None
[docs] def read_CurrentVersion(self): """Reads the constant - thus hardcoded - key from :: "HKLM\Software\Microsoft\Windows NT\CurrentVersion" Args: None Returns: The dictionary of the *CurrentVersion*. Raises: PlatformIDsReadRegExeError pass-through """ cmd = 'c:\Windows\\system32\\reg.exe query ' cmd += '"HKLM\Software\Microsoft\Windows NT\CurrentVersion"' p = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE) out = p.communicate() if not out[0]: raise PlatformIDsReadRegExeError("read registry failed: " + str(out)) for k,v in re.findall('^ *([^ ]+) *REG_[^ ]* *(.*)[\r][\n]*$', out[0], flags=re.MULTILINE): # @UndefinedVariable try: self.result[k] = int(v) except ValueError: try: self.result[k] = int(v, 16) except ValueError: self.result[k] = v return self.result
[docs] def get_win32_OSProductInfo(self): """Estimates the product type, because this is a fallback when nothing else is available. Args: None Returns: The estimated product type as a reduction of the original "pdwReturnedProductType" Raises: pass-through """ if not self.result: # set cache self.read_CurrentVersion() if self.product_type != None: # use cached product type return self.product_type try: # # for NT >= 6.0 # eid = self.resultp['EditionID'] if re.match(r'.*[Ss]erver', eid): self.product_type = VER_NT_SERVER # 0x0000003 #: see wProductType return VER_NT_SERVER elif self.resultp['InstallationType'] == 'Client': # has to be present when *EditionID* is self.product_type = VER_NT_WORKSTATION # 0x0000001 #: see wProductType return VER_NT_WORKSTATION elif re.match(r'.*[Dd]omain', eid): self.product_type = VER_NT_DOMAIN_CONTROLLER # 0x0000002 #: see wProductType return VER_NT_DOMAIN_CONTROLLER elif re.match(r'.*[Ii][Oo][Tt]', eid): self.product_type = VER_NT_IOT # 0x0000004 #: non standard enum return VER_NT_IOT else: self.product_type = VER_NT_GENERIC # 0x0000000 #: non standard enum return VER_NT_GENERIC except: # # for NT < 6.0 # # do not want spend much effort for legacy has past EOL, so... # pnam = self.resultp['ProductName'] if re.match(r'.*XP', pnam): # WindowsXP self.product_type = VER_NT_WORKSTATION # 0x0000001 #: see wProductType return VER_NT_WORKSTATION elif re.match(r'.*SERVER', self.resultp['SourcePath']): # not reliable... # WindowsXP self.product_type = VER_NT_SERVER # 0x0000003 #: see wProductType return VER_NT_SERVER else: # # may match a lot... # self.product_type = VER_NT_GENERIC # 0x0000000 #: non standard enum return VER_NT_GENERIC