comtypes 1.4.8__zip → 1.4.10__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.8 → comtypes-1.4.10}/CHANGES.txt +40 -0
- {comtypes-1.4.8/comtypes.egg-info → comtypes-1.4.10}/PKG-INFO +4 -3
- {comtypes-1.4.8 → comtypes-1.4.10}/README.md +1 -1
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/GUID.py +38 -16
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/__init__.py +36 -16
- comtypes-1.4.10/comtypes/_comobject.py +562 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_memberspec.py +93 -13
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_meta.py +1 -0
- comtypes-1.4.10/comtypes/_post_coinit/_cominterface_meta_patcher.py +152 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_post_coinit/bstr.py +12 -5
- comtypes-1.4.8/comtypes/_py_instance_method.py → comtypes-1.4.10/comtypes/_post_coinit/instancemethod.py +1 -2
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_post_coinit/misc.py +60 -25
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_post_coinit/unknwn.py +26 -176
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_safearray.py +3 -4
- comtypes-1.4.10/comtypes/_vtbl.py +448 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/automation.py +46 -49
- comtypes-1.4.10/comtypes/client/__init__.py +42 -0
- comtypes-1.4.10/comtypes/client/_activeobj.py +46 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/_code_cache.py +10 -5
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/_constants.py +1 -1
- comtypes-1.4.10/comtypes/client/_create.py +147 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/_events.py +58 -13
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/_generate.py +7 -11
- comtypes-1.4.10/comtypes/client/_managing.py +114 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/dynamic.py +2 -3
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/lazybind.py +12 -13
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/connectionpoints.py +2 -1
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/errorinfo.py +22 -9
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/git.py +5 -5
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/hints.pyi +7 -15
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/logutil.py +15 -3
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/messageloop.py +1 -1
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/persist.py +3 -5
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/safearray.py +17 -5
- comtypes-1.4.10/comtypes/server/__init__.py +104 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/server/automation.py +1 -2
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/server/connectionpoints.py +5 -5
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/server/inprocserver.py +25 -17
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/server/localserver.py +49 -19
- comtypes-1.4.10/comtypes/server/register.py +478 -0
- comtypes-1.4.10/comtypes/server/w_getopt.py +48 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/shelllink.py +16 -33
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/stream.py +7 -4
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestComServer.py +6 -7
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestDispServer.py +4 -2
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/__init__.py +10 -12
- comtypes-1.4.10/comtypes/test/find_memleak.py +72 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/runtests.py +1 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/setup.py +2 -1
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_BSTR.py +10 -23
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_GUID.py +1 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_QueryService.py +1 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_agilent.py +4 -3
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_avmc.py +1 -1
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_basic.py +12 -6
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_casesensitivity.py +3 -5
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_clear_cache.py +1 -1
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_client.py +2 -2
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_client_dynamic.py +2 -2
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_client_regenerate_modules.py +2 -2
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_collections.py +4 -4
- comtypes-1.4.10/comtypes/test/test_comobject.py +146 -0
- comtypes-1.4.10/comtypes/test/test_comserver.py +349 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_createwrappers.py +2 -4
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_dispifc_records.py +1 -1
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_dispifc_safearrays.py +1 -1
- comtypes-1.4.10/comtypes/test/test_dispinterface.py +153 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_dyndispatch.py +1 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_excel.py +22 -12
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_findgendir.py +1 -2
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_getactiveobj.py +4 -4
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_ie.py +19 -9
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_ienum.py +2 -2
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_imfattributes.py +13 -3
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_inout_args.py +8 -5
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_midl_safearray_create.py +14 -4
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_monikers.py +23 -9
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_msscript.py +2 -1
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_npsupport.py +4 -4
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_outparam.py +37 -14
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_persist.py +2 -4
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_recordinfo.py +1 -1
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_safearray.py +1 -90
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_sapi.py +4 -1
- comtypes-1.4.10/comtypes/test/test_server.py +350 -0
- comtypes-1.4.10/comtypes/test/test_server_register.py +524 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_shelllink.py +2 -3
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_showevents.py +7 -17
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_storage.py +12 -6
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_stream.py +16 -5
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_subinterface.py +4 -2
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_typeannotator.py +1 -2
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_typeinfo.py +19 -7
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_urlhistory.py +7 -4
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_variant.py +3 -19
- comtypes-1.4.10/comtypes/test/test_w_getopt.py +29 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_win32com_interop.py +80 -36
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_wmi.py +0 -3
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_word.py +1 -1
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/codegenerator.py +166 -440
- comtypes-1.4.10/comtypes/tools/codegenerator/comments.py +79 -0
- comtypes-1.4.10/comtypes/tools/codegenerator/heads.py +192 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/helpers.py +11 -14
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/namespaces.py +13 -5
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/packing.py +4 -4
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/typeannotator.py +19 -9
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/tlbparser.py +22 -23
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/typedesc.py +4 -8
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/typedesc_base.py +2 -2
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/typeinfo.py +159 -63
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/viewobject.py +3 -9
- {comtypes-1.4.8 → comtypes-1.4.10/comtypes.egg-info}/PKG-INFO +4 -3
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes.egg-info/SOURCES.txt +11 -3
- {comtypes-1.4.8 → comtypes-1.4.10}/pyproject.toml +12 -19
- comtypes-1.4.8/comtypes/_comobject.py +0 -833
- comtypes-1.4.8/comtypes/_idl_stuff.py +0 -67
- comtypes-1.4.8/comtypes/client/__init__.py +0 -323
- comtypes-1.4.8/comtypes/server/__init__.py +0 -70
- comtypes-1.4.8/comtypes/server/register.py +0 -431
- comtypes-1.4.8/comtypes/server/w_getopt.py +0 -75
- comtypes-1.4.8/comtypes/test/find_memleak.py +0 -76
- comtypes-1.4.8/comtypes/test/test_comserver.py +0 -239
- comtypes-1.4.8/comtypes/test/test_dispinterface.py +0 -137
- comtypes-1.4.8/comtypes/test/test_propputref.py +0 -40
- comtypes-1.4.8/comtypes/test/test_server.py +0 -354
- {comtypes-1.4.8 → comtypes-1.4.10}/LICENSE.txt +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/MANIFEST.in +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_npsupport.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_post_coinit/__init__.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_tlib_version_checker.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/clear_cache.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/hresult.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/patcher.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestComServer.idl +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestComServer.tlb +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestDispServer.idl +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestDispServer.tlb +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/mylib.idl +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/mylib.tlb +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/mytypelib.idl +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_DISPPARAMS.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_dict.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_jscript.js +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_pump_events.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/urlhist.tlb +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/__init__.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/__init__.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/modulenamer.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/util.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes.egg-info/dependency_links.txt +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes.egg-info/entry_points.txt +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/comtypes.egg-info/top_level.txt +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/setup.cfg +0 -0
- {comtypes-1.4.8 → comtypes-1.4.10}/setup.py +0 -0
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from _ctypes import COMError
|
|
3
|
+
from ctypes import WINFUNCTYPE, Structure, c_void_p
|
|
4
|
+
from typing import (
|
|
5
|
+
TYPE_CHECKING,
|
|
6
|
+
Any,
|
|
7
|
+
Callable,
|
|
8
|
+
Dict,
|
|
9
|
+
Iterator,
|
|
10
|
+
List,
|
|
11
|
+
Optional,
|
|
12
|
+
Sequence,
|
|
13
|
+
Tuple,
|
|
14
|
+
Type,
|
|
15
|
+
)
|
|
16
|
+
from typing import Union as _UnionT
|
|
17
|
+
|
|
18
|
+
import comtypes
|
|
19
|
+
from comtypes import GUID, IUnknown, hresult
|
|
20
|
+
from comtypes._memberspec import _encode_idl
|
|
21
|
+
from comtypes.errorinfo import ReportError, ReportException
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from ctypes import _FuncPointer
|
|
25
|
+
|
|
26
|
+
from comtypes import hints # type: ignore
|
|
27
|
+
from comtypes._memberspec import _ArgSpecElmType, _DispMemberSpec, _ParamFlagType
|
|
28
|
+
|
|
29
|
+
logger = logging.getLogger(__name__)
|
|
30
|
+
_debug = logger.debug
|
|
31
|
+
_warning = logger.warning
|
|
32
|
+
_error = logger.error
|
|
33
|
+
|
|
34
|
+
################################################################
|
|
35
|
+
# COM object implementation
|
|
36
|
+
|
|
37
|
+
# so we don't have to import comtypes.automation
|
|
38
|
+
DISPATCH_METHOD = 1
|
|
39
|
+
DISPATCH_PROPERTYGET = 2
|
|
40
|
+
DISPATCH_PROPERTYPUT = 4
|
|
41
|
+
DISPATCH_PROPERTYPUTREF = 8
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class E_NotImplemented(Exception):
|
|
45
|
+
"""COM method is not implemented"""
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def HRESULT_FROM_WIN32(errcode: Optional[int]) -> int:
|
|
49
|
+
"Convert a Windows error code into a HRESULT value."
|
|
50
|
+
if errcode is None:
|
|
51
|
+
return 0x80000000
|
|
52
|
+
if errcode & 0x80000000:
|
|
53
|
+
return errcode
|
|
54
|
+
return (errcode & 0xFFFF) | 0x80070000
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def winerror(exc: Exception) -> int:
|
|
58
|
+
"""Return the windows error code from a WindowsError or COMError
|
|
59
|
+
instance."""
|
|
60
|
+
if isinstance(exc, COMError):
|
|
61
|
+
return exc.hresult
|
|
62
|
+
elif isinstance(exc, WindowsError):
|
|
63
|
+
code = exc.winerror
|
|
64
|
+
if isinstance(code, int):
|
|
65
|
+
return code
|
|
66
|
+
# Sometimes, a WindowsError instance has no error code. An access
|
|
67
|
+
# violation raised by ctypes has only text, for example. In this
|
|
68
|
+
# cases we return a generic error code.
|
|
69
|
+
return hresult.E_FAIL
|
|
70
|
+
raise TypeError(
|
|
71
|
+
f"Expected comtypes.COMERROR or WindowsError instance, got {type(exc).__name__}"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _do_implement(interface_name: str, method_name: str) -> Callable[..., int]:
|
|
76
|
+
def _not_implemented(*args):
|
|
77
|
+
"""Return E_NOTIMPL because the method is not implemented."""
|
|
78
|
+
_debug("unimplemented method %s_%s called", interface_name, method_name)
|
|
79
|
+
return hresult.E_NOTIMPL
|
|
80
|
+
|
|
81
|
+
return _not_implemented
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def catch_errors(
|
|
85
|
+
obj: "hints.COMObject",
|
|
86
|
+
mth: Callable[..., Any],
|
|
87
|
+
paramflags: Optional[Tuple["_ParamFlagType", ...]],
|
|
88
|
+
interface: Type[IUnknown],
|
|
89
|
+
mthname: str,
|
|
90
|
+
) -> Callable[..., Any]:
|
|
91
|
+
clsid = getattr(obj, "_reg_clsid_", None)
|
|
92
|
+
|
|
93
|
+
def call_with_this(*args, **kw):
|
|
94
|
+
try:
|
|
95
|
+
result = mth(*args, **kw)
|
|
96
|
+
except comtypes.ReturnHRESULT as err:
|
|
97
|
+
(hr, text) = err.args
|
|
98
|
+
return ReportError(text, iid=interface._iid_, clsid=clsid, hresult=hr)
|
|
99
|
+
except (COMError, WindowsError) as details:
|
|
100
|
+
_error(
|
|
101
|
+
"Exception in %s.%s implementation:",
|
|
102
|
+
interface.__name__,
|
|
103
|
+
mthname,
|
|
104
|
+
exc_info=True,
|
|
105
|
+
)
|
|
106
|
+
return HRESULT_FROM_WIN32(winerror(details))
|
|
107
|
+
except E_NotImplemented:
|
|
108
|
+
_warning("Unimplemented method %s.%s called", interface.__name__, mthname)
|
|
109
|
+
return hresult.E_NOTIMPL
|
|
110
|
+
except:
|
|
111
|
+
_error(
|
|
112
|
+
"Exception in %s.%s implementation:",
|
|
113
|
+
interface.__name__,
|
|
114
|
+
mthname,
|
|
115
|
+
exc_info=True,
|
|
116
|
+
)
|
|
117
|
+
return ReportException(hresult.E_FAIL, interface._iid_, clsid=clsid)
|
|
118
|
+
if result is None:
|
|
119
|
+
return hresult.S_OK
|
|
120
|
+
return result
|
|
121
|
+
|
|
122
|
+
if paramflags is None:
|
|
123
|
+
has_outargs = False
|
|
124
|
+
else:
|
|
125
|
+
has_outargs = bool([x[0] for x in paramflags if x[0] & 2])
|
|
126
|
+
call_with_this.has_outargs = has_outargs
|
|
127
|
+
return call_with_this
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
################################################################
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def hack(
|
|
134
|
+
inst: "hints.COMObject",
|
|
135
|
+
mth: Callable[..., Any],
|
|
136
|
+
paramflags: Optional[Tuple["_ParamFlagType", ...]],
|
|
137
|
+
interface: Type[IUnknown],
|
|
138
|
+
mthname: str,
|
|
139
|
+
) -> Callable[..., Any]:
|
|
140
|
+
if paramflags is None:
|
|
141
|
+
return catch_errors(inst, mth, paramflags, interface, mthname)
|
|
142
|
+
code = mth.__code__
|
|
143
|
+
if code.co_varnames[1:2] == ("this",):
|
|
144
|
+
return catch_errors(inst, mth, paramflags, interface, mthname)
|
|
145
|
+
dirflags = [f[0] for f in paramflags]
|
|
146
|
+
# An argument is an input arg either if flags are NOT set in the
|
|
147
|
+
# idl file, or if the flags contain 'in'. In other words, the
|
|
148
|
+
# direction flag is either exactly '0' or has the '1' bit set:
|
|
149
|
+
# Output arguments have flag '2'
|
|
150
|
+
|
|
151
|
+
args_out_idx = []
|
|
152
|
+
args_in_idx = []
|
|
153
|
+
for i, a in enumerate(dirflags):
|
|
154
|
+
if a & 2:
|
|
155
|
+
args_out_idx.append(i)
|
|
156
|
+
if a & 1 or a == 0:
|
|
157
|
+
args_in_idx.append(i)
|
|
158
|
+
args_out = len(args_out_idx)
|
|
159
|
+
|
|
160
|
+
## XXX Remove this:
|
|
161
|
+
# if args_in != code.co_argcount - 1:
|
|
162
|
+
# return catch_errors(inst, mth, interface, mthname)
|
|
163
|
+
|
|
164
|
+
clsid = getattr(inst, "_reg_clsid_", None)
|
|
165
|
+
|
|
166
|
+
def call_without_this(this, *args):
|
|
167
|
+
# Method implementations could check for and return E_POINTER
|
|
168
|
+
# themselves. Or an error will be raised when
|
|
169
|
+
# 'outargs[i][0] = value' is executed.
|
|
170
|
+
# for a in outargs:
|
|
171
|
+
# if not a:
|
|
172
|
+
# return E_POINTER
|
|
173
|
+
|
|
174
|
+
# make argument list for handler by index array built above
|
|
175
|
+
inargs = []
|
|
176
|
+
for a in args_in_idx:
|
|
177
|
+
inargs.append(args[a])
|
|
178
|
+
try:
|
|
179
|
+
result = mth(*inargs)
|
|
180
|
+
if args_out == 1:
|
|
181
|
+
args[args_out_idx[0]][0] = result
|
|
182
|
+
elif args_out != 0:
|
|
183
|
+
if len(result) != args_out:
|
|
184
|
+
msg = f"Method should have returned a {args_out}-tuple"
|
|
185
|
+
raise ValueError(msg)
|
|
186
|
+
for i, value in enumerate(result):
|
|
187
|
+
args[args_out_idx[i]][0] = value
|
|
188
|
+
except comtypes.ReturnHRESULT as err:
|
|
189
|
+
(hr, text) = err.args
|
|
190
|
+
return ReportError(text, iid=interface._iid_, clsid=clsid, hresult=hr)
|
|
191
|
+
except COMError as err:
|
|
192
|
+
(hr, text, details) = err.args
|
|
193
|
+
_error(
|
|
194
|
+
"Exception in %s.%s implementation:",
|
|
195
|
+
interface.__name__,
|
|
196
|
+
mthname,
|
|
197
|
+
exc_info=True,
|
|
198
|
+
)
|
|
199
|
+
try:
|
|
200
|
+
descr, source, helpfile, helpcontext, progid = details
|
|
201
|
+
except (ValueError, TypeError):
|
|
202
|
+
msg = str(details)
|
|
203
|
+
else:
|
|
204
|
+
msg = f"{source}: {descr}"
|
|
205
|
+
hr = HRESULT_FROM_WIN32(hr)
|
|
206
|
+
return ReportError(msg, iid=interface._iid_, clsid=clsid, hresult=hr)
|
|
207
|
+
except WindowsError as details:
|
|
208
|
+
_error(
|
|
209
|
+
"Exception in %s.%s implementation:",
|
|
210
|
+
interface.__name__,
|
|
211
|
+
mthname,
|
|
212
|
+
exc_info=True,
|
|
213
|
+
)
|
|
214
|
+
hr = HRESULT_FROM_WIN32(winerror(details))
|
|
215
|
+
return ReportException(hr, interface._iid_, clsid=clsid)
|
|
216
|
+
except E_NotImplemented:
|
|
217
|
+
_warning("Unimplemented method %s.%s called", interface.__name__, mthname)
|
|
218
|
+
return hresult.E_NOTIMPL
|
|
219
|
+
except:
|
|
220
|
+
_error(
|
|
221
|
+
"Exception in %s.%s implementation:",
|
|
222
|
+
interface.__name__,
|
|
223
|
+
mthname,
|
|
224
|
+
exc_info=True,
|
|
225
|
+
)
|
|
226
|
+
return ReportException(hresult.E_FAIL, interface._iid_, clsid=clsid)
|
|
227
|
+
return hresult.S_OK
|
|
228
|
+
|
|
229
|
+
if args_out:
|
|
230
|
+
call_without_this.has_outargs = True
|
|
231
|
+
return call_without_this
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class _MethodFinder(object):
|
|
235
|
+
def __init__(self, inst: "hints.COMObject") -> None:
|
|
236
|
+
self.inst = inst
|
|
237
|
+
# map lower case names to names with correct spelling.
|
|
238
|
+
self.names = dict([(n.lower(), n) for n in dir(inst)])
|
|
239
|
+
|
|
240
|
+
def get_impl(
|
|
241
|
+
self,
|
|
242
|
+
interface: Type[IUnknown],
|
|
243
|
+
mthname: str,
|
|
244
|
+
paramflags: Optional[Tuple["_ParamFlagType", ...]],
|
|
245
|
+
idlflags: Tuple[_UnionT[str, int], ...],
|
|
246
|
+
) -> Callable[..., Any]:
|
|
247
|
+
mth = self.find_impl(interface, mthname, paramflags, idlflags)
|
|
248
|
+
if mth is None:
|
|
249
|
+
return _do_implement(interface.__name__, mthname)
|
|
250
|
+
return hack(self.inst, mth, paramflags, interface, mthname)
|
|
251
|
+
|
|
252
|
+
def find_method(self, fq_name: str, mthname: str) -> Callable[..., Any]:
|
|
253
|
+
# Try to find a method, first with the fully qualified name
|
|
254
|
+
# ('IUnknown_QueryInterface'), if that fails try the simple
|
|
255
|
+
# name ('QueryInterface')
|
|
256
|
+
try:
|
|
257
|
+
return getattr(self.inst, fq_name)
|
|
258
|
+
except AttributeError:
|
|
259
|
+
pass
|
|
260
|
+
return getattr(self.inst, mthname)
|
|
261
|
+
|
|
262
|
+
def find_impl(
|
|
263
|
+
self,
|
|
264
|
+
interface: Type[IUnknown],
|
|
265
|
+
mthname: str,
|
|
266
|
+
paramflags: Optional[Tuple["_ParamFlagType", ...]],
|
|
267
|
+
idlflags: Tuple[_UnionT[str, int], ...],
|
|
268
|
+
) -> Optional[Callable[..., Any]]:
|
|
269
|
+
fq_name = f"{interface.__name__}_{mthname}"
|
|
270
|
+
if interface._case_insensitive_:
|
|
271
|
+
# simple name, like 'QueryInterface'
|
|
272
|
+
mthname = self.names.get(mthname.lower(), mthname)
|
|
273
|
+
# qualified name, like 'IUnknown_QueryInterface'
|
|
274
|
+
fq_name = self.names.get(fq_name.lower(), fq_name)
|
|
275
|
+
|
|
276
|
+
try:
|
|
277
|
+
return self.find_method(fq_name, mthname)
|
|
278
|
+
except AttributeError:
|
|
279
|
+
pass
|
|
280
|
+
propname = mthname[5:] # strip the '_get_' or '_set' prefix
|
|
281
|
+
if interface._case_insensitive_:
|
|
282
|
+
propname = self.names.get(propname.lower(), propname)
|
|
283
|
+
# propput and propget is done with 'normal' attribute access,
|
|
284
|
+
# but only for COM properties that do not take additional
|
|
285
|
+
# arguments:
|
|
286
|
+
|
|
287
|
+
if "propget" in idlflags and len(paramflags) == 1:
|
|
288
|
+
return self.getter(propname)
|
|
289
|
+
if "propput" in idlflags and len(paramflags) == 1:
|
|
290
|
+
return self.setter(propname)
|
|
291
|
+
_debug("%r: %s.%s not implemented", self.inst, interface.__name__, mthname)
|
|
292
|
+
return None
|
|
293
|
+
|
|
294
|
+
def setter(self, propname: str) -> Callable[[Any], Any]:
|
|
295
|
+
#
|
|
296
|
+
def set(self, value):
|
|
297
|
+
try:
|
|
298
|
+
# XXX this may not be correct is the object implements
|
|
299
|
+
# _get_PropName but not _set_PropName
|
|
300
|
+
setattr(self, propname, value)
|
|
301
|
+
except AttributeError:
|
|
302
|
+
raise E_NotImplemented()
|
|
303
|
+
|
|
304
|
+
return comtypes.instancemethod(set, self.inst, type(self.inst))
|
|
305
|
+
|
|
306
|
+
def getter(self, propname: str) -> Callable[[], Any]:
|
|
307
|
+
def get(self):
|
|
308
|
+
try:
|
|
309
|
+
return getattr(self, propname)
|
|
310
|
+
except AttributeError:
|
|
311
|
+
raise E_NotImplemented()
|
|
312
|
+
|
|
313
|
+
return comtypes.instancemethod(get, self.inst, type(self.inst))
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def _create_vtbl_type(
|
|
317
|
+
fields: Tuple[Tuple[str, Type["_FuncPointer"]], ...], itf: Type[IUnknown]
|
|
318
|
+
) -> Type[Structure]:
|
|
319
|
+
try:
|
|
320
|
+
return _vtbl_types[fields]
|
|
321
|
+
except KeyError:
|
|
322
|
+
|
|
323
|
+
class Vtbl(Structure):
|
|
324
|
+
_fields_ = fields
|
|
325
|
+
|
|
326
|
+
Vtbl.__name__ = f"Vtbl_{itf.__name__}"
|
|
327
|
+
_vtbl_types[fields] = Vtbl
|
|
328
|
+
return Vtbl
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
# Ugh. Another type cache to avoid leaking types.
|
|
332
|
+
_vtbl_types: Dict[Tuple[Tuple[str, Type["_FuncPointer"]], ...], Type[Structure]] = {}
|
|
333
|
+
|
|
334
|
+
################################################################
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def create_vtbl_mapping(
|
|
338
|
+
itf: Type[IUnknown], finder: _MethodFinder
|
|
339
|
+
) -> Tuple[Sequence[GUID], Structure]:
|
|
340
|
+
methods: List[Callable[..., Any]] = [] # method implementations
|
|
341
|
+
fields: List[Tuple[str, Type["_FuncPointer"]]] = [] # virtual function table
|
|
342
|
+
iids: List[GUID] = [] # interface identifiers.
|
|
343
|
+
# iterate over interface inheritance in reverse order to build the
|
|
344
|
+
# virtual function table, and leave out the 'object' base class.
|
|
345
|
+
for interface in itf.__mro__[-2::-1]:
|
|
346
|
+
iids.append(interface._iid_)
|
|
347
|
+
for m in interface._methods_:
|
|
348
|
+
restype, mthname, argtypes, paramflags, idlflags, helptext = m
|
|
349
|
+
proto = WINFUNCTYPE(restype, c_void_p, *argtypes)
|
|
350
|
+
fields.append((mthname, proto))
|
|
351
|
+
mth = finder.get_impl(interface, mthname, paramflags, idlflags)
|
|
352
|
+
methods.append(proto(mth))
|
|
353
|
+
Vtbl = _create_vtbl_type(tuple(fields), itf)
|
|
354
|
+
vtbl = Vtbl(*methods)
|
|
355
|
+
return (iids, vtbl)
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def create_dispimpl(
|
|
359
|
+
itf: Type[IUnknown], finder: _MethodFinder
|
|
360
|
+
) -> Dict[Tuple[int, int], Callable[..., Any]]:
|
|
361
|
+
dispimpl: Dict[Tuple[int, int], Callable[..., Any]] = {}
|
|
362
|
+
for m in itf._disp_methods_:
|
|
363
|
+
#################
|
|
364
|
+
# What we have:
|
|
365
|
+
#
|
|
366
|
+
# restypes is a ctypes type or None
|
|
367
|
+
# argspec is seq. of (['in'], paramtype, paramname) tuples (or
|
|
368
|
+
# lists?)
|
|
369
|
+
#################
|
|
370
|
+
# What we need:
|
|
371
|
+
#
|
|
372
|
+
# idlflags must contain 'propget', 'propset' and so on:
|
|
373
|
+
# Must be constructed by converting disptype
|
|
374
|
+
#
|
|
375
|
+
# paramflags must be a sequence
|
|
376
|
+
# of (F_IN|F_OUT|F_RETVAL, paramname[, default-value]) tuples
|
|
377
|
+
#
|
|
378
|
+
# comtypes has this function which helps:
|
|
379
|
+
# def _encode_idl(names):
|
|
380
|
+
# # convert to F_xxx and sum up "in", "out",
|
|
381
|
+
# # "retval" values found in _PARAMFLAGS, ignoring
|
|
382
|
+
# # other stuff.
|
|
383
|
+
# return sum([_PARAMFLAGS.get(n, 0) for n in names])
|
|
384
|
+
#################
|
|
385
|
+
|
|
386
|
+
if m.what == "DISPMETHOD":
|
|
387
|
+
dispimpl.update(_make_dispmthentry(itf, finder, m))
|
|
388
|
+
elif m.what == "DISPPROPERTY":
|
|
389
|
+
dispimpl.update(_make_disppropentry(itf, finder, m))
|
|
390
|
+
return dispimpl
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def _make_dispmthentry(
|
|
394
|
+
itf: Type[IUnknown], finder: _MethodFinder, m: "_DispMemberSpec"
|
|
395
|
+
) -> Iterator[Tuple[Tuple[int, int], Callable[..., Any]]]:
|
|
396
|
+
_, mthname, idlflags, restype, argspec = m
|
|
397
|
+
if "propget" in idlflags:
|
|
398
|
+
invkind = DISPATCH_PROPERTYGET
|
|
399
|
+
mthname = f"_get_{mthname}"
|
|
400
|
+
elif "propput" in idlflags:
|
|
401
|
+
invkind = DISPATCH_PROPERTYPUT
|
|
402
|
+
mthname = f"_set_{mthname}"
|
|
403
|
+
elif "propputref" in idlflags:
|
|
404
|
+
invkind = DISPATCH_PROPERTYPUTREF
|
|
405
|
+
mthname = f"_setref_{mthname}"
|
|
406
|
+
else:
|
|
407
|
+
invkind = DISPATCH_METHOD
|
|
408
|
+
if restype:
|
|
409
|
+
argspec = argspec + ((["out"], restype, ""),)
|
|
410
|
+
yield from _make_dispentry(finder, itf, mthname, idlflags, argspec, invkind)
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
def _make_disppropentry(
|
|
414
|
+
itf: Type[IUnknown], finder: _MethodFinder, m: "_DispMemberSpec"
|
|
415
|
+
) -> Iterator[Tuple[Tuple[int, int], Callable[..., Any]]]:
|
|
416
|
+
_, mthname, idlflags, restype, argspec = m
|
|
417
|
+
# DISPPROPERTY have implicit "out"
|
|
418
|
+
if restype:
|
|
419
|
+
argspec += ((["out"], restype, ""),)
|
|
420
|
+
yield from _make_dispentry(
|
|
421
|
+
finder, itf, f"_get_{mthname}", idlflags, argspec, DISPATCH_PROPERTYGET
|
|
422
|
+
)
|
|
423
|
+
if "readonly" not in idlflags:
|
|
424
|
+
yield from _make_dispentry(
|
|
425
|
+
finder, itf, f"_set_{mthname}", idlflags, argspec, DISPATCH_PROPERTYPUT
|
|
426
|
+
)
|
|
427
|
+
# Add DISPATCH_PROPERTYPUTREF also?
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
def _make_dispentry(
|
|
431
|
+
finder: _MethodFinder,
|
|
432
|
+
interface: Type[IUnknown],
|
|
433
|
+
mthname: str,
|
|
434
|
+
idlflags: Tuple[_UnionT[str, int], ...],
|
|
435
|
+
argspec: Tuple["_ArgSpecElmType", ...],
|
|
436
|
+
invkind: int,
|
|
437
|
+
) -> Iterator[Tuple[Tuple[int, int], Callable[..., Any]]]:
|
|
438
|
+
# We build a _dispmap_ entry now that maps invkind and dispid to
|
|
439
|
+
# implementations that the finder finds; IDispatch_Invoke will later call it.
|
|
440
|
+
paramflags = tuple(((_encode_idl(x[0]), x[1]) + tuple(x[3:])) for x in argspec)
|
|
441
|
+
# XXX can the dispid be at a different index? Check codegenerator.
|
|
442
|
+
dispid = idlflags[0]
|
|
443
|
+
impl = finder.get_impl(interface, mthname, paramflags, idlflags) # type: ignore
|
|
444
|
+
yield ((dispid, invkind), impl) # type: ignore
|
|
445
|
+
# invkind is really a set of flags; we allow both DISPATCH_METHOD and
|
|
446
|
+
# DISPATCH_PROPERTYGET (win32com uses this, maybe other languages too?)
|
|
447
|
+
if invkind in (DISPATCH_METHOD, DISPATCH_PROPERTYGET):
|
|
448
|
+
yield ((dispid, DISPATCH_METHOD | DISPATCH_PROPERTYGET), impl) # type: ignore
|
|
@@ -2,31 +2,26 @@
|
|
|
2
2
|
import array
|
|
3
3
|
import datetime
|
|
4
4
|
import decimal
|
|
5
|
-
import
|
|
5
|
+
from _ctypes import COMError, CopyComPointer
|
|
6
6
|
from ctypes import *
|
|
7
|
-
from ctypes import
|
|
8
|
-
from
|
|
7
|
+
from ctypes import Array as _CArrayType
|
|
8
|
+
from ctypes import _Pointer
|
|
9
9
|
from ctypes.wintypes import DWORD, LONG, UINT, VARIANT_BOOL, WCHAR, WORD
|
|
10
|
-
from typing import Any, ClassVar, Dict, List, Optional,
|
|
10
|
+
from typing import TYPE_CHECKING, Any, ClassVar, Dict, List, Optional, Type
|
|
11
11
|
|
|
12
|
-
from comtypes import _CData, BSTR, COMError, COMMETHOD, GUID, IID, IUnknown, STDMETHOD
|
|
13
|
-
from comtypes.hresult import *
|
|
14
|
-
from comtypes._memberspec import _DispMemberSpec
|
|
15
|
-
import comtypes.patcher
|
|
16
12
|
import comtypes
|
|
13
|
+
import comtypes.patcher
|
|
14
|
+
from comtypes import BSTR, COMMETHOD, GUID, IID, STDMETHOD, IUnknown, _CData, _safearray
|
|
15
|
+
from comtypes import hresult as hresult
|
|
16
|
+
from comtypes.safearray import _midlSAFEARRAY
|
|
17
17
|
|
|
18
18
|
if TYPE_CHECKING:
|
|
19
19
|
from ctypes import _CArgObject
|
|
20
|
+
|
|
20
21
|
from comtypes import hints # type: ignore
|
|
21
|
-
from comtypes import
|
|
22
|
+
from comtypes._memberspec import _DispMemberSpec
|
|
22
23
|
else:
|
|
23
24
|
_CArgObject = type(byref(c_int()))
|
|
24
|
-
try:
|
|
25
|
-
from comtypes import _safearray
|
|
26
|
-
except (ImportError, AttributeError):
|
|
27
|
-
|
|
28
|
-
class _safearray(object):
|
|
29
|
-
tagSAFEARRAY = None
|
|
30
25
|
|
|
31
26
|
|
|
32
27
|
LCID = DWORD
|
|
@@ -212,14 +207,14 @@ class tagVARIANT(Structure):
|
|
|
212
207
|
|
|
213
208
|
def __repr__(self):
|
|
214
209
|
if self.vt & VT_BYREF:
|
|
215
|
-
return "VARIANT(vt=0x
|
|
210
|
+
return f"VARIANT(vt=0x{self.vt:x}, byref({self[0]!r}))"
|
|
216
211
|
elif self is type(self).null:
|
|
217
212
|
return "VARIANT.null"
|
|
218
213
|
elif self is type(self).empty:
|
|
219
214
|
return "VARIANT.empty"
|
|
220
215
|
elif self is type(self).missing:
|
|
221
216
|
return "VARIANT.missing"
|
|
222
|
-
return "VARIANT(vt=0x
|
|
217
|
+
return f"VARIANT(vt=0x{self.vt:x}, {self.value!r})"
|
|
223
218
|
|
|
224
219
|
@classmethod
|
|
225
220
|
def from_param(cls, value):
|
|
@@ -428,7 +423,7 @@ class tagVARIANT(Structure):
|
|
|
428
423
|
else:
|
|
429
424
|
self.vt = _ctype_to_vartype[type(ref)] | VT_BYREF
|
|
430
425
|
else:
|
|
431
|
-
raise TypeError("Cannot put
|
|
426
|
+
raise TypeError(f"Cannot put {value!r} in VARIANT")
|
|
432
427
|
# buffer -> SAFEARRAY of VT_UI1 ?
|
|
433
428
|
|
|
434
429
|
# c:/sf/pywin32/com/win32com/src/oleargs.cpp 197
|
|
@@ -524,7 +519,7 @@ class tagVARIANT(Structure):
|
|
|
524
519
|
typ = _vartype_to_ctype[self.vt & ~VT_ARRAY]
|
|
525
520
|
return cast(self._.pparray, _midlSAFEARRAY(typ)).unpack()
|
|
526
521
|
else:
|
|
527
|
-
raise NotImplementedError("typecode
|
|
522
|
+
raise NotImplementedError(f"typecode {vt} = 0x{vt:x})")
|
|
528
523
|
|
|
529
524
|
def __getitem__(self, index):
|
|
530
525
|
if index != 0:
|
|
@@ -580,23 +575,29 @@ class tagVARIANT(Structure):
|
|
|
580
575
|
VARIANT = tagVARIANT
|
|
581
576
|
VARIANTARG = VARIANT
|
|
582
577
|
|
|
578
|
+
_oleaut32_nohresult = WinDLL("oleaut32")
|
|
579
|
+
|
|
580
|
+
_SysAllocStringLen = _oleaut32_nohresult.SysAllocStringLen
|
|
581
|
+
_SysAllocStringLen.argtypes = c_wchar_p, c_uint
|
|
582
|
+
_SysAllocStringLen.restype = c_void_p
|
|
583
|
+
|
|
583
584
|
_oleaut32 = OleDLL("oleaut32")
|
|
584
585
|
|
|
585
586
|
_VariantChangeType = _oleaut32.VariantChangeType
|
|
586
587
|
_VariantChangeType.argtypes = (POINTER(VARIANT), POINTER(VARIANT), c_ushort, VARTYPE)
|
|
588
|
+
_VariantChangeType.restype = HRESULT
|
|
587
589
|
|
|
588
590
|
_VariantClear = _oleaut32.VariantClear
|
|
589
591
|
_VariantClear.argtypes = (POINTER(VARIANT),)
|
|
590
|
-
|
|
591
|
-
_SysAllocStringLen = windll.oleaut32.SysAllocStringLen
|
|
592
|
-
_SysAllocStringLen.argtypes = c_wchar_p, c_uint
|
|
593
|
-
_SysAllocStringLen.restype = c_void_p
|
|
592
|
+
_VariantClear.restype = HRESULT
|
|
594
593
|
|
|
595
594
|
_VariantCopy = _oleaut32.VariantCopy
|
|
596
595
|
_VariantCopy.argtypes = POINTER(VARIANT), POINTER(VARIANT)
|
|
596
|
+
_VariantCopy.restype = HRESULT
|
|
597
597
|
|
|
598
598
|
_VariantCopyInd = _oleaut32.VariantCopyInd
|
|
599
599
|
_VariantCopyInd.argtypes = POINTER(VARIANT), POINTER(VARIANT)
|
|
600
|
+
_VariantCopyInd.restype = HRESULT
|
|
600
601
|
|
|
601
602
|
# some commonly used VARIANT instances
|
|
602
603
|
VARIANT.null = VARIANT(None)
|
|
@@ -714,17 +715,16 @@ class tagEXCEPINFO(Structure):
|
|
|
714
715
|
scode: int
|
|
715
716
|
|
|
716
717
|
def __repr__(self):
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
self.scode,
|
|
726
|
-
),
|
|
718
|
+
info = (
|
|
719
|
+
self.wCode,
|
|
720
|
+
self.bstrSource,
|
|
721
|
+
self.bstrDescription,
|
|
722
|
+
self.bstrHelpFile,
|
|
723
|
+
self.dwHelpContext,
|
|
724
|
+
self.pfnDeferredFillIn,
|
|
725
|
+
self.scode,
|
|
727
726
|
)
|
|
727
|
+
return f"<EXCEPINFO {info}>"
|
|
728
728
|
|
|
729
729
|
|
|
730
730
|
tagEXCEPINFO._fields_ = [
|
|
@@ -775,7 +775,7 @@ DISPID_COLLECT = -8
|
|
|
775
775
|
|
|
776
776
|
|
|
777
777
|
class IDispatch(IUnknown):
|
|
778
|
-
_disp_methods_: ClassVar[List[_DispMemberSpec]]
|
|
778
|
+
_disp_methods_: ClassVar[List["_DispMemberSpec"]]
|
|
779
779
|
|
|
780
780
|
_iid_ = GUID("{00020400-0000-0000-C000-000000000046}")
|
|
781
781
|
_methods_ = [
|
|
@@ -812,6 +812,10 @@ class IDispatch(IUnknown):
|
|
|
812
812
|
),
|
|
813
813
|
]
|
|
814
814
|
|
|
815
|
+
if TYPE_CHECKING:
|
|
816
|
+
|
|
817
|
+
def GetTypeInfoCount(self) -> int: ...
|
|
818
|
+
|
|
815
819
|
def GetTypeInfo(self, index: int, lcid: int = 0) -> "hints.ITypeInfo":
|
|
816
820
|
"""Return type information. Index 0 specifies typeinfo for IDispatch"""
|
|
817
821
|
import comtypes.typeinfo
|
|
@@ -894,8 +898,8 @@ class IDispatch(IUnknown):
|
|
|
894
898
|
byref(argerr),
|
|
895
899
|
)
|
|
896
900
|
except COMError as err:
|
|
897
|
-
(
|
|
898
|
-
if
|
|
901
|
+
(hr, text, details) = err.args
|
|
902
|
+
if hr == hresult.DISP_E_EXCEPTION:
|
|
899
903
|
details = (
|
|
900
904
|
excepinfo.bstrDescription,
|
|
901
905
|
excepinfo.bstrSource,
|
|
@@ -903,24 +907,22 @@ class IDispatch(IUnknown):
|
|
|
903
907
|
excepinfo.dwHelpContext,
|
|
904
908
|
excepinfo.scode,
|
|
905
909
|
)
|
|
906
|
-
raise COMError(
|
|
907
|
-
elif
|
|
910
|
+
raise COMError(hr, text, details)
|
|
911
|
+
elif hr == hresult.DISP_E_PARAMNOTFOUND:
|
|
908
912
|
# MSDN says: You get the error DISP_E_PARAMNOTFOUND
|
|
909
913
|
# when you try to set a property and you have not
|
|
910
914
|
# initialized the cNamedArgs and rgdispidNamedArgs
|
|
911
915
|
# elements of your DISPPARAMS structure.
|
|
912
916
|
#
|
|
913
917
|
# So, this looks like a bug.
|
|
914
|
-
raise COMError(
|
|
915
|
-
elif
|
|
918
|
+
raise COMError(hr, text, argerr.value)
|
|
919
|
+
elif hr == hresult.DISP_E_TYPEMISMATCH:
|
|
916
920
|
# MSDN: One or more of the arguments could not be
|
|
917
921
|
# coerced.
|
|
918
922
|
#
|
|
919
923
|
# Hm, should we raise TypeError, or COMError?
|
|
920
924
|
raise COMError(
|
|
921
|
-
|
|
922
|
-
text,
|
|
923
|
-
("TypeError: Parameter %s" % (argerr.value + 1), args),
|
|
925
|
+
hr, text, (f"TypeError: Parameter {argerr.value + 1}", args)
|
|
924
926
|
)
|
|
925
927
|
raise
|
|
926
928
|
return result._get_value(dynamic=True)
|
|
@@ -960,6 +962,7 @@ _ctype_to_vartype: Dict[Type[_CData], int] = {
|
|
|
960
962
|
c_ulonglong: VT_UI8,
|
|
961
963
|
VARIANT_BOOL: VT_BOOL,
|
|
962
964
|
BSTR: VT_BSTR,
|
|
965
|
+
HRESULT: VT_HRESULT,
|
|
963
966
|
VARIANT: VT_VARIANT,
|
|
964
967
|
# SAFEARRAY(VARIANT *)
|
|
965
968
|
#
|
|
@@ -991,12 +994,6 @@ _vartype_to_ctype[VT_UINT] = _vartype_to_ctype[VT_UI4]
|
|
|
991
994
|
_ctype_to_vartype[c_char] = VT_UI1
|
|
992
995
|
|
|
993
996
|
|
|
994
|
-
try:
|
|
995
|
-
from comtypes.safearray import _midlSAFEARRAY
|
|
996
|
-
except (ImportError, AttributeError):
|
|
997
|
-
pass
|
|
998
|
-
|
|
999
|
-
|
|
1000
997
|
# fmt: off
|
|
1001
998
|
__known_symbols__ = [
|
|
1002
999
|
"CURRENCY", "CY", "tagCY", "DECIMAL", "tagDEC", "DISPATCH_METHOD",
|