diff --git a/docs/source/conf.py b/docs/source/conf.py index 6de8c7d..a1c1370 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -80,7 +80,11 @@ copyright = u'2015-2020, Clement Rouault' # The short X.Y version. version = '1.0' # The full version, including alpha/beta/rc tags. +<<<<<<< HEAD release = '1.0.2' +======= +release = '1.0.3' +>>>>>>> d3ea0a2 (Add windows.system.display_version + update version number + doc) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/windows/__init__.py b/windows/__init__.py index a18228c..b5ffb6e 100644 --- a/windows/__init__.py +++ b/windows/__init__.py @@ -10,6 +10,7 @@ Exported: current_thread : :class:`windows.winobject.CurrentThread` """ +__version__ = "1.0.3" # check we are on windows import sys diff --git a/windows/rpc/client.py b/windows/rpc/client.py index 9a965e3..199c969 100644 --- a/windows/rpc/client.py +++ b/windows/rpc/client.py @@ -128,6 +128,10 @@ class RPCClient(object): :param str params: The mashalled parameters (NDR32) :param GUID ipid: The IPID for `ORPC calls `_ :returns: :class:`str` + + .. note:: + + Since `1.0.3` if the call is an ORPC call, the `ORPCTHAT` & `LOCALTHAT` present in the response are parsed and striped from the result. """ request = self.forge_alpc_request(IID, method_offset, params, ipid=ipid) response = self._send_request(request) diff --git a/windows/rpc/stubborn.py b/windows/rpc/stubborn.py index 550240a..9e10144 100644 --- a/windows/rpc/stubborn.py +++ b/windows/rpc/stubborn.py @@ -54,14 +54,17 @@ def stubborn_create_instance(clsid, iid): # TODO: a real analysis of which combase version change this structure ? # 6.1.7601.17514 -> 10.0.19041.4894 -> PPRIV_RESOLVER_INFO_LEGACY - # 10.0.22000.65 -> 10.0.26100.2454 -> PPRIV_RESOLVER + # 10.0.22000.65 -> 10.0.26100.2454 -> PPRIV_RESOLVER_INFO (Windows 11 & +) rpiv_infoptr = gdef.PPRIV_RESOLVER_INFO() # Structure may change on older windows and be PPRIV_RESOLVER_INFO_LEGACY propout_as_scmreply.GetResolverInfo(rpiv_infoptr) resolver_info = rpiv_infoptr[0] + # resolver_info.OxidInfo.containerVersion.version is part of OxidInfo.ipidRemUnknown on PPRIV_RESOLVER_INFO_LEGACY + # And this part of ipidRemUnknown is a PID + # So a good value to check for > 3 :) if resolver_info.OxidInfo.containerVersion.version > 3: # print("resolver_info.OxidInfo.containerVersion.version == {0}".format(resolver_info.OxidInfo.containerVersion.version)) - print("Probable bad structure ! -> cast to legacy !") + # print("Probable bad structure ! -> cast to legacy !") resolver_info = ctypes.cast(rpiv_infoptr, gdef.PPRIV_RESOLVER_INFO_LEGACY)[0] # print("") diff --git a/windows/winobject/system.py b/windows/winobject/system.py index f492ba3..c23afd3 100644 --- a/windows/winobject/system.py +++ b/windows/winobject/system.py @@ -465,8 +465,9 @@ class System(object): bufstr = ctypes.cast(bufptr, gdef.LPWSTR) return bufstr.value - @utils.fixedpropety + @utils.fixedproperty def build_number(self): + """Return the `CurrentBuildNumber`""" # Will only work on Windows 10 ? build = self.kuser_shared_data.NtBuildNumber if build: # 0 before windows 10 @@ -475,6 +476,17 @@ class System(object): key = windows.system.registry(r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion") return int(key["CurrentBuildNumber"].value) + @utils.fixedproperty + def display_version(self): + """Return the `DisplayVersion` (22H2, 23H2, ...) is it exists, else None""" + key = windows.system.registry(r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion") + try: + return key["DisplayVersion"].value + except WindowsError as e: + if not e.winerror == gdef.ERROR_FILE_NOT_FOUND: + raise + return None + @utils.fixedproperty def versionstr(self): # Best effort. use get_file_version if registry code fails