comtypes 1.4.10__zip → 1.4.11__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {comtypes-1.4.10 → comtypes-1.4.11}/CHANGES.txt +22 -0
- {comtypes-1.4.10/comtypes.egg-info → comtypes-1.4.11}/PKG-INFO +3 -2
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/__init__.py +4 -4
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_comobject.py +23 -25
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_memberspec.py +100 -74
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_meta.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_post_coinit/_cominterface_meta_patcher.py +3 -5
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_post_coinit/unknwn.py +29 -20
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_vtbl.py +52 -55
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/automation.py +9 -10
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/_code_cache.py +9 -23
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/_events.py +87 -49
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/_generate.py +0 -2
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/connectionpoints.py +37 -3
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/errorinfo.py +53 -15
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/hints.pyi +15 -2
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/hresult.py +16 -6
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/messageloop.py +14 -12
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/server/connectionpoints.py +68 -67
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/server/inprocserver.py +8 -5
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/server/localserver.py +14 -20
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/server/register.py +2 -2
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_GUID.py +6 -7
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_basic.py +6 -3
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_collections.py +6 -3
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_comobject.py +19 -6
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_comserver.py +25 -2
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_dict.py +2 -1
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_dyndispatch.py +4 -2
- comtypes-1.4.11/comtypes/test/test_errorinfo.py +115 -0
- comtypes-1.4.11/comtypes/test/test_hresult.py +48 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_inout_args.py +9 -2
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_safearray.py +2 -1
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_server_register.py +2 -1
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_typeinfo.py +19 -2
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_variant.py +2 -1
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_w_getopt.py +4 -4
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/tlbparser.py +7 -6
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/typeinfo.py +14 -9
- {comtypes-1.4.10 → comtypes-1.4.11/comtypes.egg-info}/PKG-INFO +3 -2
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes.egg-info/SOURCES.txt +2 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/pyproject.toml +1 -6
- {comtypes-1.4.10 → comtypes-1.4.11}/LICENSE.txt +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/MANIFEST.in +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/README.md +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/GUID.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_npsupport.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_post_coinit/__init__.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_post_coinit/bstr.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_post_coinit/instancemethod.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_post_coinit/misc.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_safearray.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_tlib_version_checker.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/clear_cache.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/__init__.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/_activeobj.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/_constants.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/_create.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/_managing.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/dynamic.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/lazybind.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/git.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/logutil.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/patcher.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/persist.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/safearray.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/server/__init__.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/server/automation.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/server/w_getopt.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/shelllink.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/stream.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/TestComServer.idl +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/TestComServer.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/TestComServer.tlb +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/TestDispServer.idl +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/TestDispServer.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/TestDispServer.tlb +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/__init__.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/find_memleak.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/mylib.idl +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/mylib.tlb +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/mytypelib.idl +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/runtests.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/setup.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_BSTR.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_DISPPARAMS.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_QueryService.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_agilent.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_avmc.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_casesensitivity.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_clear_cache.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_client.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_client_dynamic.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_client_regenerate_modules.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_createwrappers.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_dispifc_records.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_dispifc_safearrays.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_dispinterface.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_excel.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_findgendir.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_getactiveobj.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_ie.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_ienum.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_imfattributes.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_jscript.js +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_midl_safearray_create.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_monikers.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_msscript.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_npsupport.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_outparam.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_persist.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_pump_events.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_recordinfo.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_sapi.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_server.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_shelllink.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_showevents.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_storage.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_stream.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_subinterface.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_typeannotator.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_urlhistory.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_win32com_interop.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_wmi.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_word.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/urlhist.tlb +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/__init__.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/codegenerator/__init__.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/codegenerator/codegenerator.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/codegenerator/comments.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/codegenerator/heads.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/codegenerator/helpers.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/codegenerator/modulenamer.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/codegenerator/namespaces.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/codegenerator/packing.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/codegenerator/typeannotator.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/typedesc.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/typedesc_base.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/util.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/viewobject.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes.egg-info/dependency_links.txt +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes.egg-info/entry_points.txt +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/comtypes.egg-info/top_level.txt +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/setup.cfg +0 -0
- {comtypes-1.4.10 → comtypes-1.4.11}/setup.py +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import ctypes
|
|
2
2
|
import logging
|
|
3
3
|
import traceback
|
|
4
|
-
from
|
|
4
|
+
from _ctypes import COMError
|
|
5
|
+
from ctypes import HRESULT, POINTER, WINFUNCTYPE, OleDLL, Structure, WinDLL, byref
|
|
5
6
|
from ctypes.wintypes import (
|
|
6
7
|
BOOL,
|
|
7
8
|
DWORD,
|
|
@@ -12,13 +13,16 @@ from ctypes.wintypes import (
|
|
|
12
13
|
LPVOID,
|
|
13
14
|
ULONG,
|
|
14
15
|
)
|
|
16
|
+
from typing import Any, Callable, Optional, Type
|
|
17
|
+
from typing import Union as _UnionT
|
|
15
18
|
|
|
16
19
|
import comtypes
|
|
17
|
-
import
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
import comtypes.typeinfo
|
|
20
|
+
from comtypes import COMObject, IUnknown, hresult
|
|
21
|
+
from comtypes._comobject import _MethodFinder
|
|
22
|
+
from comtypes.automation import DISPATCH_METHOD, IDispatch
|
|
21
23
|
from comtypes.client._generate import GetModule
|
|
24
|
+
from comtypes.connectionpoints import IConnectionPoint, IConnectionPointContainer
|
|
25
|
+
from comtypes.typeinfo import GUIDKIND_DEFAULT_SOURCE_DISP_IID, IProvideClassInfo2
|
|
22
26
|
|
|
23
27
|
logger = logging.getLogger(__name__)
|
|
24
28
|
|
|
@@ -57,46 +61,62 @@ _CloseHandle = _kernel32.CloseHandle
|
|
|
57
61
|
_CloseHandle.argtypes = [HANDLE]
|
|
58
62
|
_CloseHandle.restype = BOOL
|
|
59
63
|
|
|
64
|
+
_ReceiverType = _UnionT[COMObject, IUnknown]
|
|
65
|
+
|
|
60
66
|
|
|
61
67
|
class _AdviseConnection(object):
|
|
62
|
-
|
|
68
|
+
cp: Optional[IConnectionPoint]
|
|
69
|
+
cookie: Optional[int]
|
|
70
|
+
receiver: Optional[_ReceiverType]
|
|
71
|
+
|
|
72
|
+
def __init__(
|
|
73
|
+
self, source: IUnknown, interface: Type[IUnknown], receiver: _ReceiverType
|
|
74
|
+
) -> None:
|
|
75
|
+
# Pre-initializing attributes to avoid AttributeError after failed connection.
|
|
63
76
|
self.cp = None
|
|
64
77
|
self.cookie = None
|
|
65
78
|
self.receiver = None
|
|
66
79
|
self._connect(source, interface, receiver)
|
|
67
80
|
|
|
68
|
-
def _connect(
|
|
69
|
-
|
|
70
|
-
|
|
81
|
+
def _connect(
|
|
82
|
+
self, source: IUnknown, interface: Type[IUnknown], receiver: _ReceiverType
|
|
83
|
+
) -> None:
|
|
84
|
+
cpc = source.QueryInterface(IConnectionPointContainer)
|
|
85
|
+
self.cp = cpc.FindConnectionPoint(byref(interface._iid_))
|
|
71
86
|
logger.debug("Start advise %s", interface)
|
|
72
|
-
|
|
87
|
+
# Since `POINTER(IUnknown).from_param`(`_compointer_base.from_param`)
|
|
88
|
+
# can accept a `COMObject` instance, `IConnectionPoint.Advise` can
|
|
89
|
+
# take either a COM object or a COM interface pointer.
|
|
90
|
+
self.cookie = self.cp.Advise(receiver) # type: ignore
|
|
73
91
|
self.receiver = receiver
|
|
74
92
|
|
|
75
|
-
def disconnect(self):
|
|
93
|
+
def disconnect(self) -> None:
|
|
76
94
|
if self.cookie:
|
|
95
|
+
assert self.cp is not None
|
|
77
96
|
self.cp.Unadvise(self.cookie)
|
|
78
97
|
logger.debug("Unadvised %s", self.cp)
|
|
79
98
|
self.cp = None
|
|
80
99
|
self.cookie = None
|
|
81
100
|
del self.receiver
|
|
82
101
|
|
|
83
|
-
def __del__(self):
|
|
102
|
+
def __del__(self) -> None:
|
|
84
103
|
try:
|
|
85
104
|
if self.cookie is not None:
|
|
105
|
+
assert self.cp is not None
|
|
86
106
|
self.cp.Unadvise(self.cookie)
|
|
87
|
-
except (
|
|
107
|
+
except (COMError, WindowsError):
|
|
88
108
|
# Are we sure we want to ignore errors here?
|
|
89
109
|
pass
|
|
90
110
|
|
|
91
111
|
|
|
92
|
-
def FindOutgoingInterface(source):
|
|
112
|
+
def FindOutgoingInterface(source: IUnknown) -> Type[IUnknown]:
|
|
93
113
|
"""XXX Describe the strategy that is used..."""
|
|
94
114
|
# If the COM object implements IProvideClassInfo2, it is easy to
|
|
95
115
|
# find the default outgoing interface.
|
|
96
116
|
try:
|
|
97
|
-
pci = source.QueryInterface(
|
|
98
|
-
guid = pci.GetGUID(
|
|
99
|
-
except
|
|
117
|
+
pci = source.QueryInterface(IProvideClassInfo2)
|
|
118
|
+
guid = pci.GetGUID(GUIDKIND_DEFAULT_SOURCE_DISP_IID)
|
|
119
|
+
except COMError:
|
|
100
120
|
pass
|
|
101
121
|
else:
|
|
102
122
|
# another try: block needed?
|
|
@@ -115,7 +135,7 @@ def FindOutgoingInterface(source):
|
|
|
115
135
|
# comtypes.client):
|
|
116
136
|
clsid = source.__dict__.get("__clsid")
|
|
117
137
|
try:
|
|
118
|
-
interface = comtypes.com_coclass_registry[clsid]._outgoing_interfaces_[0]
|
|
138
|
+
interface = comtypes.com_coclass_registry[clsid]._outgoing_interfaces_[0] # type: ignore
|
|
119
139
|
except KeyError:
|
|
120
140
|
pass
|
|
121
141
|
else:
|
|
@@ -133,7 +153,7 @@ def find_single_connection_interface(source):
|
|
|
133
153
|
# Enumerate the connection interfaces. If we find a single one,
|
|
134
154
|
# return it, if there are more, we give up since we cannot
|
|
135
155
|
# determine which one to use.
|
|
136
|
-
cpc = source.QueryInterface(
|
|
156
|
+
cpc = source.QueryInterface(IConnectionPointContainer)
|
|
137
157
|
enum = cpc.EnumConnectionPoints()
|
|
138
158
|
iid = enum.next().GetConnectionInterface()
|
|
139
159
|
try:
|
|
@@ -152,32 +172,33 @@ def find_single_connection_interface(source):
|
|
|
152
172
|
return None
|
|
153
173
|
|
|
154
174
|
|
|
155
|
-
def report_errors(func):
|
|
175
|
+
def report_errors(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
156
176
|
# This decorator preserves parts of the decorated function
|
|
157
177
|
# signature, so that the comtypes special-casing for the 'this'
|
|
158
178
|
# parameter still works.
|
|
159
179
|
if func.__code__.co_varnames[:2] == ("self", "this"):
|
|
160
180
|
|
|
161
|
-
def
|
|
181
|
+
def with_this(self, this, *args, **kw):
|
|
162
182
|
try:
|
|
163
183
|
return func(self, this, *args, **kw)
|
|
164
184
|
except:
|
|
165
185
|
traceback.print_exc()
|
|
166
186
|
raise
|
|
167
187
|
|
|
188
|
+
error_printer = with_this
|
|
189
|
+
|
|
168
190
|
else:
|
|
169
191
|
|
|
170
|
-
def
|
|
192
|
+
def without_this(*args, **kw):
|
|
171
193
|
try:
|
|
172
194
|
return func(*args, **kw)
|
|
173
195
|
except:
|
|
174
196
|
traceback.print_exc()
|
|
175
197
|
raise
|
|
176
198
|
|
|
177
|
-
|
|
178
|
-
|
|
199
|
+
error_printer = without_this
|
|
179
200
|
|
|
180
|
-
|
|
201
|
+
return error_printer
|
|
181
202
|
|
|
182
203
|
|
|
183
204
|
class _SinkMethodFinder(_MethodFinder):
|
|
@@ -187,11 +208,11 @@ class _SinkMethodFinder(_MethodFinder):
|
|
|
187
208
|
event handlers.
|
|
188
209
|
"""
|
|
189
210
|
|
|
190
|
-
def __init__(self, inst, sink):
|
|
211
|
+
def __init__(self, inst: COMObject, sink: Any) -> None:
|
|
191
212
|
super(_SinkMethodFinder, self).__init__(inst)
|
|
192
213
|
self.sink = sink
|
|
193
214
|
|
|
194
|
-
def find_method(self, fq_name, mthname):
|
|
215
|
+
def find_method(self, fq_name: str, mthname: str) -> Callable[..., Any]:
|
|
195
216
|
impl = self._find_method(fq_name, mthname)
|
|
196
217
|
# Caller of this method catches AttributeError,
|
|
197
218
|
# so we need to be careful in the following code
|
|
@@ -206,7 +227,7 @@ class _SinkMethodFinder(_MethodFinder):
|
|
|
206
227
|
except AttributeError as details:
|
|
207
228
|
raise RuntimeError(details)
|
|
208
229
|
|
|
209
|
-
def _find_method(self, fq_name, mthname):
|
|
230
|
+
def _find_method(self, fq_name: str, mthname: str) -> Callable[..., Any]:
|
|
210
231
|
try:
|
|
211
232
|
return super(_SinkMethodFinder, self).find_method(fq_name, mthname)
|
|
212
233
|
except AttributeError:
|
|
@@ -216,11 +237,11 @@ class _SinkMethodFinder(_MethodFinder):
|
|
|
216
237
|
return getattr(self.sink, mthname)
|
|
217
238
|
|
|
218
239
|
|
|
219
|
-
def CreateEventReceiver(interface, handler):
|
|
220
|
-
class Sink(
|
|
240
|
+
def CreateEventReceiver(interface: Type[IUnknown], handler: Any) -> COMObject:
|
|
241
|
+
class Sink(COMObject):
|
|
221
242
|
_com_interfaces_ = [interface]
|
|
222
243
|
|
|
223
|
-
def _get_method_finder_(self, itf):
|
|
244
|
+
def _get_method_finder_(self, itf: Type[IUnknown]) -> _MethodFinder:
|
|
224
245
|
# Use a special MethodFinder that will first try 'self',
|
|
225
246
|
# then the sink.
|
|
226
247
|
return _SinkMethodFinder(self, handler)
|
|
@@ -229,25 +250,25 @@ def CreateEventReceiver(interface, handler):
|
|
|
229
250
|
|
|
230
251
|
# Since our Sink object doesn't have typeinfo, it needs a
|
|
231
252
|
# _dispimpl_ dictionary to dispatch events received via Invoke.
|
|
232
|
-
if issubclass(interface,
|
|
233
|
-
sink, "_dispimpl_"
|
|
234
|
-
):
|
|
253
|
+
if issubclass(interface, IDispatch) and not hasattr(sink, "_dispimpl_"):
|
|
235
254
|
finder = sink._get_method_finder_(interface)
|
|
236
255
|
dispimpl = sink._dispimpl_ = {}
|
|
237
256
|
for m in interface._methods_:
|
|
238
|
-
restype, mthname, argtypes, paramflags, idlflags, helptext = m
|
|
239
257
|
# Can dispid be at a different index? Should check code generator...
|
|
240
258
|
# ...but hand-written code should also work...
|
|
241
|
-
dispid = idlflags[0]
|
|
242
|
-
|
|
259
|
+
dispid = m.idlflags[0]
|
|
260
|
+
assert isinstance(dispid, comtypes.dispid)
|
|
261
|
+
impl = finder.get_impl(interface, m.name, m.paramflags, m.idlflags)
|
|
243
262
|
# XXX Wouldn't work for 'propget', 'propput', 'propputref'
|
|
244
263
|
# methods - are they allowed on event interfaces?
|
|
245
|
-
dispimpl[(dispid,
|
|
264
|
+
dispimpl[(dispid, DISPATCH_METHOD)] = impl
|
|
246
265
|
|
|
247
266
|
return sink
|
|
248
267
|
|
|
249
268
|
|
|
250
|
-
def GetEvents(
|
|
269
|
+
def GetEvents(
|
|
270
|
+
source: IUnknown, sink: Any, interface: Optional[Type[IUnknown]] = None
|
|
271
|
+
) -> _AdviseConnection:
|
|
251
272
|
"""Receive COM events from 'source'. Events will call methods on
|
|
252
273
|
the 'sink' object. 'interface' is the source interface to use.
|
|
253
274
|
"""
|
|
@@ -265,7 +286,7 @@ def GetEvents(source, sink, interface=None):
|
|
|
265
286
|
class EventDumper(object):
|
|
266
287
|
"""Universal sink for COM events."""
|
|
267
288
|
|
|
268
|
-
def __getattr__(self, name):
|
|
289
|
+
def __getattr__(self, name: str) -> Callable[..., Any]:
|
|
269
290
|
"Create event handler methods on demand"
|
|
270
291
|
if name.startswith("__") and name.endswith("__"):
|
|
271
292
|
raise AttributeError(name)
|
|
@@ -279,13 +300,15 @@ class EventDumper(object):
|
|
|
279
300
|
return comtypes.instancemethod(handler, self, EventDumper)
|
|
280
301
|
|
|
281
302
|
|
|
282
|
-
def ShowEvents(
|
|
303
|
+
def ShowEvents(
|
|
304
|
+
source: IUnknown, interface: Optional[Type[IUnknown]] = None
|
|
305
|
+
) -> _AdviseConnection:
|
|
283
306
|
"""Receive COM events from 'source'. A special event sink will be
|
|
284
307
|
used that first prints the names of events that are found in the
|
|
285
308
|
outgoing interface, and will also print out the events when they
|
|
286
309
|
are fired.
|
|
287
310
|
"""
|
|
288
|
-
return
|
|
311
|
+
return GetEvents(source, sink=EventDumper(), interface=interface)
|
|
289
312
|
|
|
290
313
|
|
|
291
314
|
# This type is used inside 'PumpEvents', but if we create the type
|
|
@@ -293,8 +316,24 @@ def ShowEvents(source, interface=None):
|
|
|
293
316
|
# garbage for each call. So we define it here instead.
|
|
294
317
|
_handles_type = ctypes.c_void_p * 1
|
|
295
318
|
|
|
319
|
+
# The type of control signal received by the handler.
|
|
320
|
+
CTRL_C_EVENT = 0
|
|
321
|
+
CTRL_BREAK_EVENT = 1
|
|
322
|
+
CTRL_CLOSE_EVENT = 2
|
|
323
|
+
CTRL_LOGOFF_EVENT = 5
|
|
324
|
+
CTRL_SHUTDOWN_EVENT = 6
|
|
325
|
+
|
|
326
|
+
# Specifiers for the behavior of the CoWaitForMultipleHandles function.
|
|
327
|
+
# tagCOWAIT_FLAGS = ctypes.c_int
|
|
328
|
+
COWAIT_DEFAULT = 0
|
|
329
|
+
COWAIT_WAITALL = 1
|
|
330
|
+
COWAIT_ALERTABLE = 2
|
|
331
|
+
COWAIT_INPUTAVAILABLE = 4
|
|
332
|
+
COWAIT_DISPATCH_CALLS = 8
|
|
333
|
+
COWAIT_DISPATCH_WINDOW_MESSAGES = 16
|
|
334
|
+
|
|
296
335
|
|
|
297
|
-
def PumpEvents(timeout):
|
|
336
|
+
def PumpEvents(timeout: Any) -> None:
|
|
298
337
|
"""This following code waits for 'timeout' seconds in the way
|
|
299
338
|
required for COM, internally doing the correct things depending
|
|
300
339
|
on the COM appartment of the current thread. It is possible to
|
|
@@ -323,11 +362,10 @@ def PumpEvents(timeout):
|
|
|
323
362
|
|
|
324
363
|
hevt = _CreateEventA(None, True, False, None)
|
|
325
364
|
handles = _handles_type(hevt)
|
|
326
|
-
RPC_S_CALLPENDING = -2147417835
|
|
327
365
|
|
|
328
366
|
# @ctypes.WINFUNCTYPE(BOOL, DWORD)
|
|
329
367
|
def HandlerRoutine(dwCtrlType):
|
|
330
|
-
if dwCtrlType ==
|
|
368
|
+
if dwCtrlType == CTRL_C_EVENT: # CTRL+C
|
|
331
369
|
_SetEvent(hevt)
|
|
332
370
|
return 1
|
|
333
371
|
return 0
|
|
@@ -336,15 +374,15 @@ def PumpEvents(timeout):
|
|
|
336
374
|
|
|
337
375
|
try:
|
|
338
376
|
try:
|
|
339
|
-
|
|
340
|
-
|
|
377
|
+
_CoWaitForMultipleHandles(
|
|
378
|
+
COWAIT_DEFAULT,
|
|
341
379
|
int(timeout * 1000),
|
|
342
380
|
len(handles),
|
|
343
381
|
handles,
|
|
344
|
-
|
|
382
|
+
byref(ctypes.c_ulong()),
|
|
345
383
|
)
|
|
346
384
|
except WindowsError as details:
|
|
347
|
-
if details.winerror != RPC_S_CALLPENDING: # timeout expired
|
|
385
|
+
if details.winerror != hresult.RPC_S_CALLPENDING: # timeout expired
|
|
348
386
|
raise
|
|
349
387
|
else:
|
|
350
388
|
raise KeyboardInterrupt
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
from
|
|
1
|
+
from ctypes import POINTER, Structure, c_ulong
|
|
2
|
+
from typing import TYPE_CHECKING, Tuple
|
|
3
|
+
from typing import Union as _UnionT
|
|
3
4
|
|
|
4
|
-
from comtypes import COMMETHOD, GUID, HRESULT, IUnknown
|
|
5
|
+
from comtypes import COMMETHOD, GUID, HRESULT, IUnknown
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from ctypes import _CArgObject, _Pointer
|
|
9
|
+
|
|
10
|
+
from comtypes import hints # noqa # type: ignore
|
|
11
|
+
|
|
12
|
+
REFIID = _UnionT[_Pointer[GUID], _CArgObject]
|
|
5
13
|
|
|
6
14
|
_GUID = GUID
|
|
7
15
|
|
|
@@ -22,16 +30,35 @@ class IConnectionPointContainer(IUnknown):
|
|
|
22
30
|
_iid_ = GUID("{B196B284-BAB4-101A-B69C-00AA00341D07}")
|
|
23
31
|
_idlflags_ = []
|
|
24
32
|
|
|
33
|
+
if TYPE_CHECKING:
|
|
34
|
+
|
|
35
|
+
def EnumConnectionPoints(self) -> "IEnumConnectionPoints": ...
|
|
36
|
+
def FindConnectionPoint(self, riid: REFIID) -> "IConnectionPoint": ...
|
|
37
|
+
|
|
25
38
|
|
|
26
39
|
class IConnectionPoint(IUnknown):
|
|
27
40
|
_iid_ = GUID("{B196B286-BAB4-101A-B69C-00AA00341D07}")
|
|
28
41
|
_idlflags_ = []
|
|
29
42
|
|
|
43
|
+
if TYPE_CHECKING:
|
|
44
|
+
|
|
45
|
+
def GetConnectionPointContainer(self) -> IConnectionPointContainer: ...
|
|
46
|
+
def Advise(self, pUnkSink: IUnknown) -> int: ...
|
|
47
|
+
def Unadvise(self, dwCookie: int) -> hints.Hresult: ...
|
|
48
|
+
def EnumConnections(self) -> "IEnumConnections": ...
|
|
49
|
+
|
|
30
50
|
|
|
31
51
|
class IEnumConnections(IUnknown):
|
|
32
52
|
_iid_ = GUID("{B196B287-BAB4-101A-B69C-00AA00341D07}")
|
|
33
53
|
_idlflags_ = []
|
|
34
54
|
|
|
55
|
+
if TYPE_CHECKING:
|
|
56
|
+
|
|
57
|
+
def Next(self, cConnections: int) -> Tuple[tagCONNECTDATA, int]: ...
|
|
58
|
+
def Skip(self, cConnections: int) -> hints.Hresult: ...
|
|
59
|
+
def Reset(self) -> hints.Hresult: ...
|
|
60
|
+
def Clone(self) -> "IEnumConnections": ...
|
|
61
|
+
|
|
35
62
|
def __iter__(self):
|
|
36
63
|
return self
|
|
37
64
|
|
|
@@ -46,6 +73,13 @@ class IEnumConnectionPoints(IUnknown):
|
|
|
46
73
|
_iid_ = GUID("{B196B285-BAB4-101A-B69C-00AA00341D07}")
|
|
47
74
|
_idlflags_ = []
|
|
48
75
|
|
|
76
|
+
if TYPE_CHECKING:
|
|
77
|
+
|
|
78
|
+
def Next(self, cConnections: int) -> Tuple[IConnectionPoint, int]: ...
|
|
79
|
+
def Skip(self, cConnections: int) -> hints.Hresult: ...
|
|
80
|
+
def Reset(self) -> hints.Hresult: ...
|
|
81
|
+
def Clone(self) -> "IEnumConnectionPoints": ...
|
|
82
|
+
|
|
49
83
|
def __iter__(self):
|
|
50
84
|
return self
|
|
51
85
|
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import sys
|
|
2
|
-
from ctypes import
|
|
2
|
+
from ctypes import POINTER, OleDLL, byref, c_wchar_p
|
|
3
3
|
from ctypes.wintypes import DWORD, ULONG
|
|
4
|
+
from typing import TYPE_CHECKING, Optional
|
|
5
|
+
from typing import Union as _UnionT
|
|
4
6
|
|
|
5
7
|
from comtypes import BSTR, COMMETHOD, GUID, HRESULT, IUnknown
|
|
6
|
-
from comtypes.hresult import
|
|
8
|
+
from comtypes.hresult import DISP_E_EXCEPTION, S_OK
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from comtypes import hints # type: ignore
|
|
7
12
|
|
|
8
13
|
LPCOLESTR = c_wchar_p
|
|
9
14
|
|
|
@@ -17,6 +22,13 @@ class ICreateErrorInfo(IUnknown):
|
|
|
17
22
|
COMMETHOD([], HRESULT, "SetHelpFile", (["in"], LPCOLESTR, "szHelpFile")),
|
|
18
23
|
COMMETHOD([], HRESULT, "SetHelpContext", (["in"], DWORD, "dwHelpContext")),
|
|
19
24
|
]
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
|
|
27
|
+
def SetGUID(self, rguid: GUID) -> hints.Hresult: ...
|
|
28
|
+
def SetSource(self, szSource: str) -> hints.Hresult: ...
|
|
29
|
+
def SetDescription(self, szDescription: str) -> hints.Hresult: ...
|
|
30
|
+
def SetHelpFile(self, szHelpFile: str) -> hints.Hresult: ...
|
|
31
|
+
def SetHelpContext(self, dwHelpContext: int) -> hints.Hresult: ...
|
|
20
32
|
|
|
21
33
|
|
|
22
34
|
class IErrorInfo(IUnknown):
|
|
@@ -34,6 +46,13 @@ class IErrorInfo(IUnknown):
|
|
|
34
46
|
[], HRESULT, "GetHelpContext", (["out"], POINTER(DWORD), "pdwHelpContext")
|
|
35
47
|
),
|
|
36
48
|
]
|
|
49
|
+
if TYPE_CHECKING:
|
|
50
|
+
|
|
51
|
+
def GetGUID(self) -> GUID: ...
|
|
52
|
+
def GetSource(self) -> str: ...
|
|
53
|
+
def GetDescription(self) -> str: ...
|
|
54
|
+
def GetHelpFile(self) -> str: ...
|
|
55
|
+
def GetHelpContext(self) -> int: ...
|
|
37
56
|
|
|
38
57
|
|
|
39
58
|
class ISupportErrorInfo(IUnknown):
|
|
@@ -43,6 +62,9 @@ class ISupportErrorInfo(IUnknown):
|
|
|
43
62
|
[], HRESULT, "InterfaceSupportsErrorInfo", (["in"], POINTER(GUID), "riid")
|
|
44
63
|
)
|
|
45
64
|
]
|
|
65
|
+
if TYPE_CHECKING:
|
|
66
|
+
|
|
67
|
+
def InterfaceSupportsErrorInfo(self, riid: GUID) -> hints.Hresult: ...
|
|
46
68
|
|
|
47
69
|
|
|
48
70
|
################################################################
|
|
@@ -61,28 +83,36 @@ _SetErrorInfo.argtypes = [ULONG, POINTER(IErrorInfo)]
|
|
|
61
83
|
_SetErrorInfo.restype = HRESULT
|
|
62
84
|
|
|
63
85
|
|
|
64
|
-
def CreateErrorInfo():
|
|
86
|
+
def CreateErrorInfo() -> ICreateErrorInfo:
|
|
87
|
+
"""Creates an instance of a generic error object."""
|
|
65
88
|
cei = POINTER(ICreateErrorInfo)()
|
|
66
89
|
_CreateErrorInfo(byref(cei))
|
|
67
|
-
return cei
|
|
90
|
+
return cei # type: ignore
|
|
68
91
|
|
|
69
92
|
|
|
70
|
-
def GetErrorInfo():
|
|
93
|
+
def GetErrorInfo() -> Optional[IErrorInfo]:
|
|
71
94
|
"""Get the error information for the current thread."""
|
|
72
95
|
errinfo = POINTER(IErrorInfo)()
|
|
73
96
|
if S_OK == _GetErrorInfo(0, byref(errinfo)):
|
|
74
|
-
return errinfo
|
|
97
|
+
return errinfo # type: ignore
|
|
75
98
|
return None
|
|
76
99
|
|
|
77
100
|
|
|
78
|
-
def SetErrorInfo(errinfo):
|
|
101
|
+
def SetErrorInfo(errinfo: _UnionT[IErrorInfo, ICreateErrorInfo]) -> "hints.Hresult":
|
|
79
102
|
"""Set error information for the current thread."""
|
|
103
|
+
# ICreateErrorInfo can QueryInterface with IErrorInfo, so both types are
|
|
104
|
+
# accepted, thanks to the magic of from_param.
|
|
80
105
|
return _SetErrorInfo(0, errinfo)
|
|
81
106
|
|
|
82
107
|
|
|
83
108
|
def ReportError(
|
|
84
|
-
text
|
|
85
|
-
|
|
109
|
+
text: str,
|
|
110
|
+
iid: GUID,
|
|
111
|
+
clsid: _UnionT[None, str, GUID] = None,
|
|
112
|
+
helpfile: Optional[str] = None,
|
|
113
|
+
helpcontext: Optional[int] = 0,
|
|
114
|
+
hresult: int = DISP_E_EXCEPTION,
|
|
115
|
+
) -> int:
|
|
86
116
|
"""Report a COM error. Returns the passed in hresult value."""
|
|
87
117
|
ei = CreateErrorInfo()
|
|
88
118
|
ei.SetDescription(text)
|
|
@@ -99,21 +129,29 @@ def ReportError(
|
|
|
99
129
|
except WindowsError:
|
|
100
130
|
pass
|
|
101
131
|
else:
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
_SetErrorInfo(0, ei)
|
|
132
|
+
# progid for the class or application that created the error
|
|
133
|
+
ei.SetSource(progid)
|
|
134
|
+
SetErrorInfo(ei)
|
|
106
135
|
return hresult
|
|
107
136
|
|
|
108
137
|
|
|
109
138
|
def ReportException(
|
|
110
|
-
hresult
|
|
111
|
-
|
|
139
|
+
hresult: int,
|
|
140
|
+
iid: GUID,
|
|
141
|
+
clsid: _UnionT[None, str, GUID] = None,
|
|
142
|
+
helpfile: Optional[str] = None,
|
|
143
|
+
helpcontext: Optional[int] = None,
|
|
144
|
+
stacklevel: Optional[int] = None,
|
|
145
|
+
) -> int:
|
|
112
146
|
"""Report a COM exception. Returns the passed in hresult value."""
|
|
113
147
|
typ, value, tb = sys.exc_info()
|
|
114
148
|
if stacklevel is not None:
|
|
115
149
|
for _ in range(stacklevel):
|
|
150
|
+
if tb is None:
|
|
151
|
+
raise ValueError("'stacklevel' exceeds the available depth.")
|
|
116
152
|
tb = tb.tb_next
|
|
153
|
+
if tb is None:
|
|
154
|
+
raise ValueError("'stacklevel' is specified, but no error information.")
|
|
117
155
|
line = tb.tb_frame.f_lineno
|
|
118
156
|
name = tb.tb_frame.f_globals["__name__"]
|
|
119
157
|
text = f"{typ}: {value} ({name}, line {line:d})"
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
# - utilities for type hints.
|
|
4
4
|
import ctypes
|
|
5
5
|
import sys
|
|
6
|
+
from ctypes import _CData, _CDataType
|
|
6
7
|
from typing import Any as Any, ClassVar, Generic, NoReturn, Protocol, TypeVar, overload
|
|
7
8
|
from typing import Optional, Union as _UnionT
|
|
8
|
-
from typing import Tuple as Tuple, Type
|
|
9
|
+
from typing import List, Tuple as Tuple, Type
|
|
9
10
|
from typing import Callable, Iterator, Sequence
|
|
10
11
|
|
|
11
12
|
if sys.version_info >= (3, 9):
|
|
@@ -20,8 +21,10 @@ else:
|
|
|
20
21
|
from typing_extensions import TypeGuard as TypeGuard
|
|
21
22
|
if sys.version_info >= (3, 11):
|
|
22
23
|
from typing import Self as Self
|
|
24
|
+
from typing import Unpack as Unpack
|
|
23
25
|
else:
|
|
24
26
|
from typing_extensions import Self as Self
|
|
27
|
+
from typing_extensions import Unpack as Unpack
|
|
25
28
|
|
|
26
29
|
import comtypes
|
|
27
30
|
from comtypes import IUnknown as IUnknown, COMObject as COMObject, GUID as GUID
|
|
@@ -41,7 +44,10 @@ Hresult: TypeAlias = int
|
|
|
41
44
|
arguments and with `HRESULT` as its return type in its COM method definition.
|
|
42
45
|
"""
|
|
43
46
|
|
|
44
|
-
|
|
47
|
+
LP_LP_Vtbl: TypeAlias = ctypes._Pointer[ctypes._Pointer[ctypes.Structure]]
|
|
48
|
+
"""A pointer to a pointer to a virtual function table."""
|
|
49
|
+
|
|
50
|
+
_CT = TypeVar("_CT", bound=_CData)
|
|
45
51
|
_T_IUnknown = TypeVar("_T_IUnknown", bound=IUnknown)
|
|
46
52
|
_T_Struct = TypeVar("_T_Struct", bound=ctypes.Structure)
|
|
47
53
|
|
|
@@ -285,3 +291,10 @@ def to_dunder_setitem(
|
|
|
285
291
|
) -> Callable[Concatenate[_T_Inst, _P_Set], Any]: ...
|
|
286
292
|
@overload
|
|
287
293
|
def to_dunder_setitem(item: Any) -> Callable[..., NoReturn]: ...
|
|
294
|
+
|
|
295
|
+
_PosParamFlagType: TypeAlias = Tuple[int, Optional[str]]
|
|
296
|
+
_OptParamFlagType: TypeAlias = Tuple[int, Optional[str], Any]
|
|
297
|
+
ParamFlagType: TypeAlias = _UnionT[_PosParamFlagType, _OptParamFlagType]
|
|
298
|
+
_PosArgSpecElmType: TypeAlias = Tuple[List[str], Type[_CDataType], str]
|
|
299
|
+
_OptArgSpecElmType: TypeAlias = Tuple[List[str], Type[_CDataType], str, Any]
|
|
300
|
+
ArgSpecElmType: TypeAlias = _UnionT[_PosArgSpecElmType, _OptArgSpecElmType]
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
#
|
|
4
4
|
# Note that the codes should be written in decimal notation!
|
|
5
5
|
|
|
6
|
+
from ctypes import c_long
|
|
7
|
+
|
|
6
8
|
S_OK = 0
|
|
7
9
|
S_FALSE = 1
|
|
8
10
|
|
|
@@ -53,13 +55,15 @@ DISP_E_UNKNOWNINTERFACE = -2147352575 # 0x80020001
|
|
|
53
55
|
RPC_E_CHANGED_MODE = -2147417850 # 0x80010106
|
|
54
56
|
RPC_E_SERVERFAULT = -2147417851 # 0x80010105
|
|
55
57
|
|
|
58
|
+
RPC_E_NO_SYNC = -2147417824 # 0x80010120
|
|
59
|
+
RPC_S_CALLPENDING = -2147417835 # 0x80010115
|
|
60
|
+
|
|
56
61
|
# 'macros' and constants to create your own HRESULT values:
|
|
57
62
|
|
|
58
63
|
|
|
59
|
-
def MAKE_HRESULT(sev, fac, code):
|
|
64
|
+
def MAKE_HRESULT(sev: int, fac: int, code: int) -> int:
|
|
65
|
+
"""Creates an HRESULT value from its component pieces."""
|
|
60
66
|
# A hresult is SIGNED in comtypes
|
|
61
|
-
from ctypes import c_long
|
|
62
|
-
|
|
63
67
|
return c_long((sev << 31 | fac << 16 | code)).value
|
|
64
68
|
|
|
65
69
|
|
|
@@ -70,12 +74,18 @@ FACILITY_ITF = 4
|
|
|
70
74
|
FACILITY_WIN32 = 7
|
|
71
75
|
|
|
72
76
|
|
|
73
|
-
def HRESULT_FROM_WIN32(x):
|
|
77
|
+
def HRESULT_FROM_WIN32(x: int) -> int:
|
|
78
|
+
"""Converts a system error code to an HRESULT value."""
|
|
74
79
|
# make signed
|
|
75
|
-
from ctypes import c_long
|
|
76
|
-
|
|
77
80
|
x = c_long(x).value
|
|
78
81
|
if x < 0:
|
|
79
82
|
return x
|
|
80
83
|
# 0x80000000 | FACILITY_WIN32 << 16 | x & 0xFFFF
|
|
81
84
|
return c_long(0x80070000 | (x & 0xFFFF)).value
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# Win32 error codes are defined as unsigned 32-bit integers. However, to
|
|
88
|
+
# ensure compatibility with COM and other HRESULT-based APIs, Windows converts
|
|
89
|
+
# them into HRESULT values by setting the high bit, ensuring a consistent way
|
|
90
|
+
# to indicate failure across these APIs.
|
|
91
|
+
RPC_S_SERVER_UNAVAILABLE = -2147023174 # 0x800706BA (WIN32: 1722 0x6BA)
|
|
@@ -1,31 +1,33 @@
|
|
|
1
1
|
import ctypes
|
|
2
2
|
from ctypes import WinDLL, WinError, byref
|
|
3
3
|
from ctypes.wintypes import MSG
|
|
4
|
+
from typing import TYPE_CHECKING, List, SupportsIndex
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from ctypes import _CArgObject
|
|
8
|
+
from typing import Any, Callable, Iterable
|
|
9
|
+
|
|
10
|
+
_FilterCallable = Callable[["_CArgObject"], Iterable[Any]] # type: ignore
|
|
4
11
|
|
|
5
12
|
_user32 = WinDLL("user32")
|
|
6
13
|
|
|
7
14
|
GetMessage = _user32.GetMessageA
|
|
8
|
-
GetMessage.argtypes = [
|
|
9
|
-
ctypes.c_void_p,
|
|
10
|
-
ctypes.c_void_p,
|
|
11
|
-
ctypes.c_uint,
|
|
12
|
-
ctypes.c_uint,
|
|
13
|
-
]
|
|
15
|
+
GetMessage.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint, ctypes.c_uint]
|
|
14
16
|
TranslateMessage = _user32.TranslateMessage
|
|
15
17
|
DispatchMessage = _user32.DispatchMessageA
|
|
16
18
|
|
|
17
19
|
|
|
18
20
|
class _MessageLoop(object):
|
|
19
|
-
def __init__(self):
|
|
20
|
-
self._filters = []
|
|
21
|
+
def __init__(self) -> None:
|
|
22
|
+
self._filters: List["_FilterCallable"] = []
|
|
21
23
|
|
|
22
|
-
def insert_filter(self, obj, index
|
|
24
|
+
def insert_filter(self, obj: "_FilterCallable", index: SupportsIndex = -1) -> None:
|
|
23
25
|
self._filters.insert(index, obj)
|
|
24
26
|
|
|
25
|
-
def remove_filter(self, obj):
|
|
27
|
+
def remove_filter(self, obj: "_FilterCallable") -> None:
|
|
26
28
|
self._filters.remove(obj)
|
|
27
29
|
|
|
28
|
-
def run(self):
|
|
30
|
+
def run(self) -> None:
|
|
29
31
|
msg = MSG()
|
|
30
32
|
lpmsg = byref(msg)
|
|
31
33
|
while 1:
|
|
@@ -38,7 +40,7 @@ class _MessageLoop(object):
|
|
|
38
40
|
TranslateMessage(lpmsg)
|
|
39
41
|
DispatchMessage(lpmsg)
|
|
40
42
|
|
|
41
|
-
def filter_message(self, lpmsg):
|
|
43
|
+
def filter_message(self, lpmsg: "_CArgObject") -> bool:
|
|
42
44
|
return any(list(filter(lpmsg)) for filter in self._filters)
|
|
43
45
|
|
|
44
46
|
|