comtypes 1.4.8__zip → 1.4.9__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.9}/CHANGES.txt +21 -0
- {comtypes-1.4.8/comtypes.egg-info → comtypes-1.4.9}/PKG-INFO +2 -2
- {comtypes-1.4.8 → comtypes-1.4.9}/README.md +1 -1
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/GUID.py +6 -5
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/__init__.py +16 -5
- comtypes-1.4.9/comtypes/_comobject.py +507 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_memberspec.py +80 -8
- comtypes-1.4.9/comtypes/_post_coinit/_cominterface_meta_patcher.py +153 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_post_coinit/misc.py +1 -1
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_post_coinit/unknwn.py +25 -171
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_safearray.py +1 -2
- comtypes-1.4.9/comtypes/_vtbl.py +448 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/automation.py +36 -45
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/_code_cache.py +4 -4
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/_constants.py +1 -1
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/_events.py +1 -1
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/_generate.py +4 -8
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/lazybind.py +2 -2
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/errorinfo.py +3 -3
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/git.py +1 -2
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/hints.pyi +7 -15
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/safearray.py +10 -0
- comtypes-1.4.9/comtypes/server/__init__.py +86 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/server/inprocserver.py +22 -17
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/server/localserver.py +28 -16
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/server/register.py +61 -73
- comtypes-1.4.9/comtypes/server/w_getopt.py +48 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/shelllink.py +3 -26
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/__init__.py +9 -11
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_BSTR.py +4 -7
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_avmc.py +1 -1
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_casesensitivity.py +3 -5
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_collections.py +3 -3
- comtypes-1.4.9/comtypes/test/test_comobject.py +146 -0
- comtypes-1.4.9/comtypes/test/test_comserver.py +319 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_createwrappers.py +2 -4
- comtypes-1.4.9/comtypes/test/test_dispinterface.py +153 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_excel.py +22 -12
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_ie.py +2 -5
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_inout_args.py +7 -4
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_midl_safearray_create.py +9 -1
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_outparam.py +17 -10
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_safearray.py +1 -90
- comtypes-1.4.9/comtypes/test/test_server.py +350 -0
- comtypes-1.4.9/comtypes/test/test_server_register.py +536 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_showevents.py +7 -17
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_variant.py +0 -17
- comtypes-1.4.9/comtypes/test/test_w_getopt.py +29 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_win32com_interop.py +80 -36
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_wmi.py +0 -3
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/codegenerator.py +62 -68
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/helpers.py +8 -8
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/packing.py +4 -4
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/typeannotator.py +7 -7
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/typedesc.py +1 -6
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/typeinfo.py +11 -22
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/viewobject.py +1 -5
- {comtypes-1.4.8 → comtypes-1.4.9/comtypes.egg-info}/PKG-INFO +2 -2
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes.egg-info/SOURCES.txt +6 -3
- {comtypes-1.4.8 → comtypes-1.4.9}/pyproject.toml +1 -0
- comtypes-1.4.8/comtypes/_comobject.py +0 -833
- comtypes-1.4.8/comtypes/_idl_stuff.py +0 -67
- comtypes-1.4.8/comtypes/server/__init__.py +0 -70
- comtypes-1.4.8/comtypes/server/w_getopt.py +0 -75
- 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.9}/LICENSE.txt +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/MANIFEST.in +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_meta.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_npsupport.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_post_coinit/__init__.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_post_coinit/bstr.py +0 -0
- /comtypes-1.4.8/comtypes/_py_instance_method.py → /comtypes-1.4.9/comtypes/_post_coinit/instancemethod.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_tlib_version_checker.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/clear_cache.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/__init__.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/dynamic.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/connectionpoints.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/hresult.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/logutil.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/messageloop.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/patcher.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/persist.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/server/automation.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/server/connectionpoints.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/stream.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/TestComServer.idl +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/TestComServer.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/TestComServer.tlb +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/TestDispServer.idl +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/TestDispServer.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/TestDispServer.tlb +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/find_memleak.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/mylib.idl +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/mylib.tlb +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/mytypelib.idl +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/runtests.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/setup.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_DISPPARAMS.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_GUID.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_QueryService.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_agilent.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_basic.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_clear_cache.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_client.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_client_dynamic.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_client_regenerate_modules.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_dict.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_dispifc_records.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_dispifc_safearrays.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_dyndispatch.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_findgendir.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_getactiveobj.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_ienum.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_imfattributes.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_jscript.js +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_monikers.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_msscript.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_npsupport.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_persist.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_pump_events.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_recordinfo.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_sapi.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_shelllink.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_storage.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_stream.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_subinterface.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_typeannotator.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_typeinfo.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_urlhistory.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_word.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/urlhist.tlb +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/__init__.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/__init__.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/modulenamer.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/namespaces.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/tlbparser.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/typedesc_base.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/util.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes.egg-info/dependency_links.txt +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes.egg-info/entry_points.txt +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes.egg-info/top_level.txt +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/setup.cfg +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/setup.py +0 -0
|
@@ -1,833 +0,0 @@
|
|
|
1
|
-
from ctypes import (
|
|
2
|
-
FormatError,
|
|
3
|
-
POINTER,
|
|
4
|
-
Structure,
|
|
5
|
-
WINFUNCTYPE,
|
|
6
|
-
byref,
|
|
7
|
-
c_long,
|
|
8
|
-
c_void_p,
|
|
9
|
-
oledll,
|
|
10
|
-
pointer,
|
|
11
|
-
windll,
|
|
12
|
-
)
|
|
13
|
-
from _ctypes import CopyComPointer
|
|
14
|
-
import logging
|
|
15
|
-
import os
|
|
16
|
-
import queue
|
|
17
|
-
import sys
|
|
18
|
-
|
|
19
|
-
from comtypes import COMError, ReturnHRESULT, instancemethod
|
|
20
|
-
from comtypes._memberspec import _encode_idl
|
|
21
|
-
from comtypes.errorinfo import ISupportErrorInfo, ReportException, ReportError
|
|
22
|
-
from comtypes import IPersist
|
|
23
|
-
from comtypes.hresult import (
|
|
24
|
-
DISP_E_BADINDEX,
|
|
25
|
-
DISP_E_MEMBERNOTFOUND,
|
|
26
|
-
E_FAIL,
|
|
27
|
-
E_NOINTERFACE,
|
|
28
|
-
E_INVALIDARG,
|
|
29
|
-
E_NOTIMPL,
|
|
30
|
-
RPC_E_CHANGED_MODE,
|
|
31
|
-
S_FALSE,
|
|
32
|
-
S_OK,
|
|
33
|
-
)
|
|
34
|
-
from comtypes.typeinfo import IProvideClassInfo, IProvideClassInfo2
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
logger = logging.getLogger(__name__)
|
|
38
|
-
_debug = logger.debug
|
|
39
|
-
_warning = logger.warning
|
|
40
|
-
_error = logger.error
|
|
41
|
-
|
|
42
|
-
################################################################
|
|
43
|
-
# COM object implementation
|
|
44
|
-
|
|
45
|
-
# so we don't have to import comtypes.automation
|
|
46
|
-
DISPATCH_METHOD = 1
|
|
47
|
-
DISPATCH_PROPERTYGET = 2
|
|
48
|
-
DISPATCH_PROPERTYPUT = 4
|
|
49
|
-
DISPATCH_PROPERTYPUTREF = 8
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
class E_NotImplemented(Exception):
|
|
53
|
-
"""COM method is not implemented"""
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def HRESULT_FROM_WIN32(errcode):
|
|
57
|
-
"Convert a Windows error code into a HRESULT value."
|
|
58
|
-
if errcode is None:
|
|
59
|
-
return 0x80000000
|
|
60
|
-
if errcode & 0x80000000:
|
|
61
|
-
return errcode
|
|
62
|
-
return (errcode & 0xFFFF) | 0x80070000
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def winerror(exc):
|
|
66
|
-
"""Return the windows error code from a WindowsError or COMError
|
|
67
|
-
instance."""
|
|
68
|
-
if isinstance(exc, COMError):
|
|
69
|
-
return exc.hresult
|
|
70
|
-
elif isinstance(exc, WindowsError):
|
|
71
|
-
code = exc.winerror
|
|
72
|
-
if isinstance(code, int):
|
|
73
|
-
return code
|
|
74
|
-
# Sometimes, a WindowsError instance has no error code. An access
|
|
75
|
-
# violation raised by ctypes has only text, for example. In this
|
|
76
|
-
# cases we return a generic error code.
|
|
77
|
-
return E_FAIL
|
|
78
|
-
raise TypeError(
|
|
79
|
-
"Expected comtypes.COMERROR or WindowsError instance, got %s"
|
|
80
|
-
% type(exc).__name__
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
def _do_implement(interface_name, method_name):
|
|
85
|
-
def _not_implemented(*args):
|
|
86
|
-
"""Return E_NOTIMPL because the method is not implemented."""
|
|
87
|
-
_debug("unimplemented method %s_%s called", interface_name, method_name)
|
|
88
|
-
return E_NOTIMPL
|
|
89
|
-
|
|
90
|
-
return _not_implemented
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def catch_errors(obj, mth, paramflags, interface, mthname):
|
|
94
|
-
clsid = getattr(obj, "_reg_clsid_", None)
|
|
95
|
-
|
|
96
|
-
def call_with_this(*args, **kw):
|
|
97
|
-
try:
|
|
98
|
-
result = mth(*args, **kw)
|
|
99
|
-
except ReturnHRESULT as err:
|
|
100
|
-
(hresult, text) = err.args
|
|
101
|
-
return ReportError(text, iid=interface._iid_, clsid=clsid, hresult=hresult)
|
|
102
|
-
except (COMError, WindowsError) as details:
|
|
103
|
-
_error(
|
|
104
|
-
"Exception in %s.%s implementation:",
|
|
105
|
-
interface.__name__,
|
|
106
|
-
mthname,
|
|
107
|
-
exc_info=True,
|
|
108
|
-
)
|
|
109
|
-
return HRESULT_FROM_WIN32(winerror(details))
|
|
110
|
-
except E_NotImplemented:
|
|
111
|
-
_warning("Unimplemented method %s.%s called", interface.__name__, mthname)
|
|
112
|
-
return E_NOTIMPL
|
|
113
|
-
except:
|
|
114
|
-
_error(
|
|
115
|
-
"Exception in %s.%s implementation:",
|
|
116
|
-
interface.__name__,
|
|
117
|
-
mthname,
|
|
118
|
-
exc_info=True,
|
|
119
|
-
)
|
|
120
|
-
return ReportException(E_FAIL, interface._iid_, clsid=clsid)
|
|
121
|
-
if result is None:
|
|
122
|
-
return S_OK
|
|
123
|
-
return result
|
|
124
|
-
|
|
125
|
-
if paramflags is None:
|
|
126
|
-
has_outargs = False
|
|
127
|
-
else:
|
|
128
|
-
has_outargs = bool([x[0] for x in paramflags if x[0] & 2])
|
|
129
|
-
call_with_this.has_outargs = has_outargs
|
|
130
|
-
return call_with_this
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
################################################################
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
def hack(inst, mth, paramflags, interface, mthname):
|
|
137
|
-
if paramflags is None:
|
|
138
|
-
return catch_errors(inst, mth, paramflags, interface, mthname)
|
|
139
|
-
code = mth.__code__
|
|
140
|
-
if code.co_varnames[1:2] == ("this",):
|
|
141
|
-
return catch_errors(inst, mth, paramflags, interface, mthname)
|
|
142
|
-
dirflags = [f[0] for f in paramflags]
|
|
143
|
-
# An argument is an input arg either if flags are NOT set in the
|
|
144
|
-
# idl file, or if the flags contain 'in'. In other words, the
|
|
145
|
-
# direction flag is either exactly '0' or has the '1' bit set:
|
|
146
|
-
# Output arguments have flag '2'
|
|
147
|
-
|
|
148
|
-
args_out_idx = []
|
|
149
|
-
args_in_idx = []
|
|
150
|
-
for i, a in enumerate(dirflags):
|
|
151
|
-
if a & 2:
|
|
152
|
-
args_out_idx.append(i)
|
|
153
|
-
if a & 1 or a == 0:
|
|
154
|
-
args_in_idx.append(i)
|
|
155
|
-
args_out = len(args_out_idx)
|
|
156
|
-
|
|
157
|
-
## XXX Remove this:
|
|
158
|
-
# if args_in != code.co_argcount - 1:
|
|
159
|
-
# return catch_errors(inst, mth, interface, mthname)
|
|
160
|
-
|
|
161
|
-
clsid = getattr(inst, "_reg_clsid_", None)
|
|
162
|
-
|
|
163
|
-
def call_without_this(this, *args):
|
|
164
|
-
# Method implementations could check for and return E_POINTER
|
|
165
|
-
# themselves. Or an error will be raised when
|
|
166
|
-
# 'outargs[i][0] = value' is executed.
|
|
167
|
-
# for a in outargs:
|
|
168
|
-
# if not a:
|
|
169
|
-
# return E_POINTER
|
|
170
|
-
|
|
171
|
-
# make argument list for handler by index array built above
|
|
172
|
-
inargs = []
|
|
173
|
-
for a in args_in_idx:
|
|
174
|
-
inargs.append(args[a])
|
|
175
|
-
try:
|
|
176
|
-
result = mth(*inargs)
|
|
177
|
-
if args_out == 1:
|
|
178
|
-
args[args_out_idx[0]][0] = result
|
|
179
|
-
elif args_out != 0:
|
|
180
|
-
if len(result) != args_out:
|
|
181
|
-
msg = "Method should have returned a %s-tuple" % args_out
|
|
182
|
-
raise ValueError(msg)
|
|
183
|
-
for i, value in enumerate(result):
|
|
184
|
-
args[args_out_idx[i]][0] = value
|
|
185
|
-
except ReturnHRESULT as err:
|
|
186
|
-
(hresult, text) = err.args
|
|
187
|
-
return ReportError(text, iid=interface._iid_, clsid=clsid, hresult=hresult)
|
|
188
|
-
except COMError as err:
|
|
189
|
-
(hr, text, details) = err.args
|
|
190
|
-
_error(
|
|
191
|
-
"Exception in %s.%s implementation:",
|
|
192
|
-
interface.__name__,
|
|
193
|
-
mthname,
|
|
194
|
-
exc_info=True,
|
|
195
|
-
)
|
|
196
|
-
try:
|
|
197
|
-
descr, source, helpfile, helpcontext, progid = details
|
|
198
|
-
except (ValueError, TypeError):
|
|
199
|
-
msg = str(details)
|
|
200
|
-
else:
|
|
201
|
-
msg = "%s: %s" % (source, descr)
|
|
202
|
-
hr = HRESULT_FROM_WIN32(hr)
|
|
203
|
-
return ReportError(msg, iid=interface._iid_, clsid=clsid, hresult=hr)
|
|
204
|
-
except WindowsError as details:
|
|
205
|
-
_error(
|
|
206
|
-
"Exception in %s.%s implementation:",
|
|
207
|
-
interface.__name__,
|
|
208
|
-
mthname,
|
|
209
|
-
exc_info=True,
|
|
210
|
-
)
|
|
211
|
-
hr = HRESULT_FROM_WIN32(winerror(details))
|
|
212
|
-
return ReportException(hr, interface._iid_, clsid=clsid)
|
|
213
|
-
except E_NotImplemented:
|
|
214
|
-
_warning("Unimplemented method %s.%s called", interface.__name__, mthname)
|
|
215
|
-
return E_NOTIMPL
|
|
216
|
-
except:
|
|
217
|
-
_error(
|
|
218
|
-
"Exception in %s.%s implementation:",
|
|
219
|
-
interface.__name__,
|
|
220
|
-
mthname,
|
|
221
|
-
exc_info=True,
|
|
222
|
-
)
|
|
223
|
-
return ReportException(E_FAIL, interface._iid_, clsid=clsid)
|
|
224
|
-
return S_OK
|
|
225
|
-
|
|
226
|
-
if args_out:
|
|
227
|
-
call_without_this.has_outargs = True
|
|
228
|
-
return call_without_this
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
class _MethodFinder(object):
|
|
232
|
-
def __init__(self, inst):
|
|
233
|
-
self.inst = inst
|
|
234
|
-
# map lower case names to names with correct spelling.
|
|
235
|
-
self.names = dict([(n.lower(), n) for n in dir(inst)])
|
|
236
|
-
|
|
237
|
-
def get_impl(self, interface, mthname, paramflags, idlflags):
|
|
238
|
-
mth = self.find_impl(interface, mthname, paramflags, idlflags)
|
|
239
|
-
if mth is None:
|
|
240
|
-
return _do_implement(interface.__name__, mthname)
|
|
241
|
-
return hack(self.inst, mth, paramflags, interface, mthname)
|
|
242
|
-
|
|
243
|
-
def find_method(self, fq_name, mthname):
|
|
244
|
-
# Try to find a method, first with the fully qualified name
|
|
245
|
-
# ('IUnknown_QueryInterface'), if that fails try the simple
|
|
246
|
-
# name ('QueryInterface')
|
|
247
|
-
try:
|
|
248
|
-
return getattr(self.inst, fq_name)
|
|
249
|
-
except AttributeError:
|
|
250
|
-
pass
|
|
251
|
-
return getattr(self.inst, mthname)
|
|
252
|
-
|
|
253
|
-
def find_impl(self, interface, mthname, paramflags, idlflags):
|
|
254
|
-
fq_name = "%s_%s" % (interface.__name__, mthname)
|
|
255
|
-
if interface._case_insensitive_:
|
|
256
|
-
# simple name, like 'QueryInterface'
|
|
257
|
-
mthname = self.names.get(mthname.lower(), mthname)
|
|
258
|
-
# qualified name, like 'IUnknown_QueryInterface'
|
|
259
|
-
fq_name = self.names.get(fq_name.lower(), fq_name)
|
|
260
|
-
|
|
261
|
-
try:
|
|
262
|
-
return self.find_method(fq_name, mthname)
|
|
263
|
-
except AttributeError:
|
|
264
|
-
pass
|
|
265
|
-
propname = mthname[5:] # strip the '_get_' or '_set' prefix
|
|
266
|
-
if interface._case_insensitive_:
|
|
267
|
-
propname = self.names.get(propname.lower(), propname)
|
|
268
|
-
# propput and propget is done with 'normal' attribute access,
|
|
269
|
-
# but only for COM properties that do not take additional
|
|
270
|
-
# arguments:
|
|
271
|
-
|
|
272
|
-
if "propget" in idlflags and len(paramflags) == 1:
|
|
273
|
-
return self.getter(propname)
|
|
274
|
-
if "propput" in idlflags and len(paramflags) == 1:
|
|
275
|
-
return self.setter(propname)
|
|
276
|
-
_debug("%r: %s.%s not implemented", self.inst, interface.__name__, mthname)
|
|
277
|
-
return None
|
|
278
|
-
|
|
279
|
-
def setter(self, propname):
|
|
280
|
-
#
|
|
281
|
-
def set(self, value):
|
|
282
|
-
try:
|
|
283
|
-
# XXX this may not be correct is the object implements
|
|
284
|
-
# _get_PropName but not _set_PropName
|
|
285
|
-
setattr(self, propname, value)
|
|
286
|
-
except AttributeError:
|
|
287
|
-
raise E_NotImplemented()
|
|
288
|
-
|
|
289
|
-
return instancemethod(set, self.inst, type(self.inst))
|
|
290
|
-
|
|
291
|
-
def getter(self, propname):
|
|
292
|
-
def get(self):
|
|
293
|
-
try:
|
|
294
|
-
return getattr(self, propname)
|
|
295
|
-
except AttributeError:
|
|
296
|
-
raise E_NotImplemented()
|
|
297
|
-
|
|
298
|
-
return instancemethod(get, self.inst, type(self.inst))
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
def _create_vtbl_type(fields, itf):
|
|
302
|
-
try:
|
|
303
|
-
return _vtbl_types[fields]
|
|
304
|
-
except KeyError:
|
|
305
|
-
|
|
306
|
-
class Vtbl(Structure):
|
|
307
|
-
_fields_ = fields
|
|
308
|
-
|
|
309
|
-
Vtbl.__name__ = "Vtbl_%s" % itf.__name__
|
|
310
|
-
_vtbl_types[fields] = Vtbl
|
|
311
|
-
return Vtbl
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
# Ugh. Another type cache to avoid leaking types.
|
|
315
|
-
_vtbl_types = {}
|
|
316
|
-
|
|
317
|
-
################################################################
|
|
318
|
-
|
|
319
|
-
try:
|
|
320
|
-
_InterlockedIncrement = windll.kernel32.InterlockedIncrement
|
|
321
|
-
_InterlockedDecrement = windll.kernel32.InterlockedDecrement
|
|
322
|
-
except AttributeError:
|
|
323
|
-
import threading
|
|
324
|
-
|
|
325
|
-
_lock = threading.Lock()
|
|
326
|
-
_acquire = _lock.acquire
|
|
327
|
-
_release = _lock.release
|
|
328
|
-
# win 64 doesn't have these functions
|
|
329
|
-
|
|
330
|
-
def _InterlockedIncrement(ob):
|
|
331
|
-
_acquire()
|
|
332
|
-
refcnt = ob.value + 1
|
|
333
|
-
ob.value = refcnt
|
|
334
|
-
_release()
|
|
335
|
-
return refcnt
|
|
336
|
-
|
|
337
|
-
def _InterlockedDecrement(ob):
|
|
338
|
-
_acquire()
|
|
339
|
-
refcnt = ob.value - 1
|
|
340
|
-
ob.value = refcnt
|
|
341
|
-
_release()
|
|
342
|
-
return refcnt
|
|
343
|
-
|
|
344
|
-
else:
|
|
345
|
-
_InterlockedIncrement.argtypes = [POINTER(c_long)]
|
|
346
|
-
_InterlockedDecrement.argtypes = [POINTER(c_long)]
|
|
347
|
-
_InterlockedIncrement.restype = c_long
|
|
348
|
-
_InterlockedDecrement.restype = c_long
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
class LocalServer(object):
|
|
352
|
-
_queue = None
|
|
353
|
-
|
|
354
|
-
def run(self, classobjects):
|
|
355
|
-
# Use windll instead of oledll so that we don't get an
|
|
356
|
-
# exception on a FAILED hresult:
|
|
357
|
-
result = windll.ole32.CoInitialize(None)
|
|
358
|
-
if RPC_E_CHANGED_MODE == result:
|
|
359
|
-
# we're running in MTA: no message pump needed
|
|
360
|
-
_debug("Server running in MTA")
|
|
361
|
-
self.run_mta()
|
|
362
|
-
else:
|
|
363
|
-
# we're running in STA: need a message pump
|
|
364
|
-
_debug("Server running in STA")
|
|
365
|
-
if result >= 0:
|
|
366
|
-
# we need a matching CoUninitialize() call for a successful
|
|
367
|
-
# CoInitialize().
|
|
368
|
-
windll.ole32.CoUninitialize()
|
|
369
|
-
self.run_sta()
|
|
370
|
-
|
|
371
|
-
for obj in classobjects:
|
|
372
|
-
obj._revoke_class()
|
|
373
|
-
|
|
374
|
-
def run_sta(self):
|
|
375
|
-
from comtypes import messageloop
|
|
376
|
-
|
|
377
|
-
messageloop.run()
|
|
378
|
-
|
|
379
|
-
def run_mta(self):
|
|
380
|
-
self._queue = queue.Queue()
|
|
381
|
-
self._queue.get()
|
|
382
|
-
|
|
383
|
-
def Lock(self):
|
|
384
|
-
oledll.ole32.CoAddRefServerProcess()
|
|
385
|
-
|
|
386
|
-
def Unlock(self):
|
|
387
|
-
rc = oledll.ole32.CoReleaseServerProcess()
|
|
388
|
-
if rc == 0:
|
|
389
|
-
if self._queue:
|
|
390
|
-
self._queue.put(42)
|
|
391
|
-
else:
|
|
392
|
-
windll.user32.PostQuitMessage(0)
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
class InprocServer(object):
|
|
396
|
-
def __init__(self):
|
|
397
|
-
self.locks = c_long(0)
|
|
398
|
-
|
|
399
|
-
def Lock(self):
|
|
400
|
-
_InterlockedIncrement(self.locks)
|
|
401
|
-
|
|
402
|
-
def Unlock(self):
|
|
403
|
-
_InterlockedDecrement(self.locks)
|
|
404
|
-
|
|
405
|
-
def DllCanUnloadNow(self):
|
|
406
|
-
if self.locks.value:
|
|
407
|
-
return S_FALSE
|
|
408
|
-
if COMObject._instances_:
|
|
409
|
-
return S_FALSE
|
|
410
|
-
return S_OK
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
class COMObject(object):
|
|
414
|
-
_instances_ = {}
|
|
415
|
-
|
|
416
|
-
def __new__(cls, *args, **kw):
|
|
417
|
-
self = super(COMObject, cls).__new__(cls)
|
|
418
|
-
if isinstance(self, c_void_p):
|
|
419
|
-
# We build the VTables only for direct instances of
|
|
420
|
-
# CoClass, not for POINTERs to CoClass.
|
|
421
|
-
return self
|
|
422
|
-
if hasattr(self, "_com_interfaces_"):
|
|
423
|
-
self.__prepare_comobject()
|
|
424
|
-
return self
|
|
425
|
-
|
|
426
|
-
def __prepare_comobject(self):
|
|
427
|
-
# When a CoClass instance is created, COM pointers to all
|
|
428
|
-
# interfaces are created. Also, the CoClass must be kept alive as
|
|
429
|
-
# until the COM reference count drops to zero, even if no Python
|
|
430
|
-
# code keeps a reference to the object.
|
|
431
|
-
#
|
|
432
|
-
# The _com_pointers_ instance variable maps string interface iids
|
|
433
|
-
# to C compatible COM pointers.
|
|
434
|
-
self._com_pointers_ = {}
|
|
435
|
-
# COM refcount starts at zero.
|
|
436
|
-
self._refcnt = c_long(0)
|
|
437
|
-
|
|
438
|
-
# Some interfaces have a default implementation in COMObject:
|
|
439
|
-
# - ISupportErrorInfo
|
|
440
|
-
# - IPersist (if the subclass has a _reg_clsid_ attribute)
|
|
441
|
-
# - IProvideClassInfo (if the subclass has a _reg_clsid_ attribute)
|
|
442
|
-
# - IProvideClassInfo2 (if the subclass has a _outgoing_interfaces_
|
|
443
|
-
# attribute)
|
|
444
|
-
#
|
|
445
|
-
# Add these if they are not listed in _com_interfaces_.
|
|
446
|
-
interfaces = tuple(self._com_interfaces_)
|
|
447
|
-
if ISupportErrorInfo not in interfaces:
|
|
448
|
-
interfaces += (ISupportErrorInfo,)
|
|
449
|
-
if hasattr(self, "_reg_typelib_"):
|
|
450
|
-
from comtypes.typeinfo import LoadRegTypeLib
|
|
451
|
-
|
|
452
|
-
self._COMObject__typelib = LoadRegTypeLib(*self._reg_typelib_)
|
|
453
|
-
if hasattr(self, "_reg_clsid_"):
|
|
454
|
-
if IProvideClassInfo not in interfaces:
|
|
455
|
-
interfaces += (IProvideClassInfo,)
|
|
456
|
-
if (
|
|
457
|
-
hasattr(self, "_outgoing_interfaces_")
|
|
458
|
-
and IProvideClassInfo2 not in interfaces
|
|
459
|
-
):
|
|
460
|
-
interfaces += (IProvideClassInfo2,)
|
|
461
|
-
if hasattr(self, "_reg_clsid_"):
|
|
462
|
-
if IPersist not in interfaces:
|
|
463
|
-
interfaces += (IPersist,)
|
|
464
|
-
for itf in interfaces[::-1]:
|
|
465
|
-
self.__make_interface_pointer(itf)
|
|
466
|
-
|
|
467
|
-
def __make_interface_pointer(self, itf):
|
|
468
|
-
methods = [] # method implementations
|
|
469
|
-
fields = [] # (name, prototype) for virtual function table
|
|
470
|
-
iids = [] # interface identifiers.
|
|
471
|
-
# iterate over interface inheritance in reverse order to build the
|
|
472
|
-
# virtual function table, and leave out the 'object' base class.
|
|
473
|
-
finder = self._get_method_finder_(itf)
|
|
474
|
-
for interface in itf.__mro__[-2::-1]:
|
|
475
|
-
iids.append(interface._iid_)
|
|
476
|
-
for m in interface._methods_:
|
|
477
|
-
restype, mthname, argtypes, paramflags, idlflags, helptext = m
|
|
478
|
-
proto = WINFUNCTYPE(restype, c_void_p, *argtypes)
|
|
479
|
-
fields.append((mthname, proto))
|
|
480
|
-
mth = finder.get_impl(interface, mthname, paramflags, idlflags)
|
|
481
|
-
methods.append(proto(mth))
|
|
482
|
-
Vtbl = _create_vtbl_type(tuple(fields), itf)
|
|
483
|
-
vtbl = Vtbl(*methods)
|
|
484
|
-
for iid in iids:
|
|
485
|
-
self._com_pointers_[iid] = pointer(pointer(vtbl))
|
|
486
|
-
if hasattr(itf, "_disp_methods_"):
|
|
487
|
-
self._dispimpl_ = {}
|
|
488
|
-
for m in itf._disp_methods_:
|
|
489
|
-
what, mthname, idlflags, restype, argspec = m
|
|
490
|
-
#################
|
|
491
|
-
# What we have:
|
|
492
|
-
#
|
|
493
|
-
# restypes is a ctypes type or None
|
|
494
|
-
# argspec is seq. of (['in'], paramtype, paramname) tuples (or
|
|
495
|
-
# lists?)
|
|
496
|
-
#################
|
|
497
|
-
# What we need:
|
|
498
|
-
#
|
|
499
|
-
# idlflags must contain 'propget', 'propset' and so on:
|
|
500
|
-
# Must be constructed by converting disptype
|
|
501
|
-
#
|
|
502
|
-
# paramflags must be a sequence
|
|
503
|
-
# of (F_IN|F_OUT|F_RETVAL, paramname[, default-value]) tuples
|
|
504
|
-
#
|
|
505
|
-
# comtypes has this function which helps:
|
|
506
|
-
# def _encode_idl(names):
|
|
507
|
-
# # convert to F_xxx and sum up "in", "out",
|
|
508
|
-
# # "retval" values found in _PARAMFLAGS, ignoring
|
|
509
|
-
# # other stuff.
|
|
510
|
-
# return sum([_PARAMFLAGS.get(n, 0) for n in names])
|
|
511
|
-
#################
|
|
512
|
-
|
|
513
|
-
if what == "DISPMETHOD":
|
|
514
|
-
if "propget" in idlflags:
|
|
515
|
-
invkind = 2 # DISPATCH_PROPERTYGET
|
|
516
|
-
mthname = "_get_" + mthname
|
|
517
|
-
elif "propput" in idlflags:
|
|
518
|
-
invkind = 4 # DISPATCH_PROPERTYPUT
|
|
519
|
-
mthname = "_set_" + mthname
|
|
520
|
-
elif "propputref" in idlflags:
|
|
521
|
-
invkind = 8 # DISPATCH_PROPERTYPUTREF
|
|
522
|
-
mthname = "_setref_" + mthname
|
|
523
|
-
else:
|
|
524
|
-
invkind = 1 # DISPATCH_METHOD
|
|
525
|
-
if restype:
|
|
526
|
-
argspec = argspec + ((["out"], restype, ""),)
|
|
527
|
-
self.__make_dispentry(
|
|
528
|
-
finder, interface, mthname, idlflags, argspec, invkind
|
|
529
|
-
)
|
|
530
|
-
elif what == "DISPPROPERTY":
|
|
531
|
-
# DISPPROPERTY have implicit "out"
|
|
532
|
-
if restype:
|
|
533
|
-
argspec += ((["out"], restype, ""),)
|
|
534
|
-
self.__make_dispentry(
|
|
535
|
-
finder,
|
|
536
|
-
interface,
|
|
537
|
-
"_get_" + mthname,
|
|
538
|
-
idlflags,
|
|
539
|
-
argspec,
|
|
540
|
-
2, # DISPATCH_PROPERTYGET
|
|
541
|
-
)
|
|
542
|
-
if not "readonly" in idlflags:
|
|
543
|
-
self.__make_dispentry(
|
|
544
|
-
finder, interface, "_set_" + mthname, idlflags, argspec, 4
|
|
545
|
-
) # DISPATCH_PROPERTYPUT
|
|
546
|
-
# Add DISPATCH_PROPERTYPUTREF also?
|
|
547
|
-
|
|
548
|
-
def __make_dispentry(self, finder, interface, mthname, idlflags, argspec, invkind):
|
|
549
|
-
# We build a _dispmap_ entry now that maps invkind and
|
|
550
|
-
# dispid to implementations that the finder finds;
|
|
551
|
-
# IDispatch_Invoke will later call it.
|
|
552
|
-
paramflags = [((_encode_idl(x[0]), x[1]) + tuple(x[3:])) for x in argspec]
|
|
553
|
-
# XXX can the dispid be at a different index? Check codegenerator.
|
|
554
|
-
dispid = idlflags[0]
|
|
555
|
-
impl = finder.get_impl(interface, mthname, paramflags, idlflags)
|
|
556
|
-
self._dispimpl_[(dispid, invkind)] = impl
|
|
557
|
-
# invkind is really a set of flags; we allow both
|
|
558
|
-
# DISPATCH_METHOD and DISPATCH_PROPERTYGET (win32com uses
|
|
559
|
-
# this, maybe other languages too?)
|
|
560
|
-
if invkind in (1, 2):
|
|
561
|
-
self._dispimpl_[(dispid, 3)] = impl
|
|
562
|
-
|
|
563
|
-
def _get_method_finder_(self, itf):
|
|
564
|
-
# This method can be overridden to customize how methods are
|
|
565
|
-
# found.
|
|
566
|
-
return _MethodFinder(self)
|
|
567
|
-
|
|
568
|
-
################################################################
|
|
569
|
-
# LocalServer / InprocServer stuff
|
|
570
|
-
__server__ = None
|
|
571
|
-
|
|
572
|
-
@staticmethod
|
|
573
|
-
def __run_inprocserver__():
|
|
574
|
-
if COMObject.__server__ is None:
|
|
575
|
-
COMObject.__server__ = InprocServer()
|
|
576
|
-
elif isinstance(COMObject.__server__, InprocServer):
|
|
577
|
-
pass
|
|
578
|
-
else:
|
|
579
|
-
raise RuntimeError("Wrong server type")
|
|
580
|
-
|
|
581
|
-
@staticmethod
|
|
582
|
-
def __run_localserver__(classobjects):
|
|
583
|
-
assert COMObject.__server__ is None
|
|
584
|
-
# XXX Decide whether we are in STA or MTA
|
|
585
|
-
server = COMObject.__server__ = LocalServer()
|
|
586
|
-
server.run(classobjects)
|
|
587
|
-
COMObject.__server__ = None
|
|
588
|
-
|
|
589
|
-
@staticmethod
|
|
590
|
-
def __keep__(obj):
|
|
591
|
-
COMObject._instances_[obj] = None
|
|
592
|
-
_debug("%d active COM objects: Added %r", len(COMObject._instances_), obj)
|
|
593
|
-
if COMObject.__server__:
|
|
594
|
-
COMObject.__server__.Lock()
|
|
595
|
-
|
|
596
|
-
@staticmethod
|
|
597
|
-
def __unkeep__(obj):
|
|
598
|
-
try:
|
|
599
|
-
del COMObject._instances_[obj]
|
|
600
|
-
except AttributeError:
|
|
601
|
-
_debug("? active COM objects: Removed %r", obj)
|
|
602
|
-
else:
|
|
603
|
-
_debug("%d active COM objects: Removed %r", len(COMObject._instances_), obj)
|
|
604
|
-
_debug("Remaining: %s", list(COMObject._instances_.keys()))
|
|
605
|
-
if COMObject.__server__:
|
|
606
|
-
COMObject.__server__.Unlock()
|
|
607
|
-
|
|
608
|
-
#
|
|
609
|
-
################################################################
|
|
610
|
-
|
|
611
|
-
#########################################################
|
|
612
|
-
# IUnknown methods implementations
|
|
613
|
-
def IUnknown_AddRef(
|
|
614
|
-
self, this, __InterlockedIncrement=_InterlockedIncrement, _debug=_debug
|
|
615
|
-
):
|
|
616
|
-
result = __InterlockedIncrement(self._refcnt)
|
|
617
|
-
if result == 1:
|
|
618
|
-
self.__keep__(self)
|
|
619
|
-
_debug("%r.AddRef() -> %s", self, result)
|
|
620
|
-
return result
|
|
621
|
-
|
|
622
|
-
def _final_release_(self):
|
|
623
|
-
"""This method may be overridden in subclasses
|
|
624
|
-
to free allocated resources or so."""
|
|
625
|
-
pass
|
|
626
|
-
|
|
627
|
-
def IUnknown_Release(
|
|
628
|
-
self, this, __InterlockedDecrement=_InterlockedDecrement, _debug=_debug
|
|
629
|
-
):
|
|
630
|
-
# If this is called at COM shutdown, _InterlockedDecrement()
|
|
631
|
-
# must still be available, although module level variables may
|
|
632
|
-
# have been deleted already - so we supply it as default
|
|
633
|
-
# argument.
|
|
634
|
-
result = __InterlockedDecrement(self._refcnt)
|
|
635
|
-
_debug("%r.Release() -> %s", self, result)
|
|
636
|
-
if result == 0:
|
|
637
|
-
self._final_release_()
|
|
638
|
-
self.__unkeep__(self)
|
|
639
|
-
# Hm, why isn't this cleaned up by the cycle gc?
|
|
640
|
-
self._com_pointers_ = {}
|
|
641
|
-
return result
|
|
642
|
-
|
|
643
|
-
def IUnknown_QueryInterface(self, this, riid, ppvObj, _debug=_debug):
|
|
644
|
-
# XXX This is probably too slow.
|
|
645
|
-
# riid[0].hashcode() alone takes 33 us!
|
|
646
|
-
iid = riid[0]
|
|
647
|
-
ptr = self._com_pointers_.get(iid, None)
|
|
648
|
-
if ptr is not None:
|
|
649
|
-
# CopyComPointer(src, dst) calls AddRef!
|
|
650
|
-
_debug("%r.QueryInterface(%s) -> S_OK", self, iid)
|
|
651
|
-
return CopyComPointer(ptr, ppvObj)
|
|
652
|
-
_debug("%r.QueryInterface(%s) -> E_NOINTERFACE", self, iid)
|
|
653
|
-
return E_NOINTERFACE
|
|
654
|
-
|
|
655
|
-
def QueryInterface(self, interface):
|
|
656
|
-
"Query the object for an interface pointer"
|
|
657
|
-
# This method is NOT the implementation of
|
|
658
|
-
# IUnknown::QueryInterface, instead it is supposed to be
|
|
659
|
-
# called on an COMObject by user code. It allows to get COM
|
|
660
|
-
# interface pointers from COMObject instances.
|
|
661
|
-
ptr = self._com_pointers_.get(interface._iid_, None)
|
|
662
|
-
if ptr is None:
|
|
663
|
-
raise COMError(
|
|
664
|
-
E_NOINTERFACE, FormatError(E_NOINTERFACE), (None, None, 0, None, None)
|
|
665
|
-
)
|
|
666
|
-
# CopyComPointer(src, dst) calls AddRef!
|
|
667
|
-
result = POINTER(interface)()
|
|
668
|
-
CopyComPointer(ptr, byref(result))
|
|
669
|
-
return result
|
|
670
|
-
|
|
671
|
-
################################################################
|
|
672
|
-
# ISupportErrorInfo::InterfaceSupportsErrorInfo implementation
|
|
673
|
-
def ISupportErrorInfo_InterfaceSupportsErrorInfo(self, this, riid):
|
|
674
|
-
if riid[0] in self._com_pointers_:
|
|
675
|
-
return S_OK
|
|
676
|
-
return S_FALSE
|
|
677
|
-
|
|
678
|
-
################################################################
|
|
679
|
-
# IProvideClassInfo::GetClassInfo implementation
|
|
680
|
-
def IProvideClassInfo_GetClassInfo(self):
|
|
681
|
-
try:
|
|
682
|
-
self.__typelib
|
|
683
|
-
except AttributeError:
|
|
684
|
-
raise WindowsError(E_NOTIMPL)
|
|
685
|
-
return self.__typelib.GetTypeInfoOfGuid(self._reg_clsid_)
|
|
686
|
-
|
|
687
|
-
################################################################
|
|
688
|
-
# IProvideClassInfo2::GetGUID implementation
|
|
689
|
-
|
|
690
|
-
def IProvideClassInfo2_GetGUID(self, dwGuidKind):
|
|
691
|
-
# GUIDKIND_DEFAULT_SOURCE_DISP_IID = 1
|
|
692
|
-
if dwGuidKind != 1:
|
|
693
|
-
raise WindowsError(E_INVALIDARG)
|
|
694
|
-
return self._outgoing_interfaces_[0]._iid_
|
|
695
|
-
|
|
696
|
-
################################################################
|
|
697
|
-
# IDispatch methods
|
|
698
|
-
@property
|
|
699
|
-
def __typeinfo(self):
|
|
700
|
-
# XXX Looks like this better be a static property, set by the
|
|
701
|
-
# code that sets __typelib also...
|
|
702
|
-
iid = self._com_interfaces_[0]._iid_
|
|
703
|
-
return self.__typelib.GetTypeInfoOfGuid(iid)
|
|
704
|
-
|
|
705
|
-
def IDispatch_GetTypeInfoCount(self):
|
|
706
|
-
try:
|
|
707
|
-
self.__typelib
|
|
708
|
-
except AttributeError:
|
|
709
|
-
return 0
|
|
710
|
-
else:
|
|
711
|
-
return 1
|
|
712
|
-
|
|
713
|
-
def IDispatch_GetTypeInfo(self, this, itinfo, lcid, ptinfo):
|
|
714
|
-
if itinfo != 0:
|
|
715
|
-
return DISP_E_BADINDEX
|
|
716
|
-
try:
|
|
717
|
-
ptinfo[0] = self.__typeinfo
|
|
718
|
-
return S_OK
|
|
719
|
-
except AttributeError:
|
|
720
|
-
return E_NOTIMPL
|
|
721
|
-
|
|
722
|
-
def IDispatch_GetIDsOfNames(self, this, riid, rgszNames, cNames, lcid, rgDispId):
|
|
723
|
-
# This call uses windll instead of oledll so that a failed
|
|
724
|
-
# call to DispGetIDsOfNames will return a HRESULT instead of
|
|
725
|
-
# raising an error.
|
|
726
|
-
try:
|
|
727
|
-
tinfo = self.__typeinfo
|
|
728
|
-
except AttributeError:
|
|
729
|
-
return E_NOTIMPL
|
|
730
|
-
return windll.oleaut32.DispGetIDsOfNames(tinfo, rgszNames, cNames, rgDispId)
|
|
731
|
-
|
|
732
|
-
def IDispatch_Invoke(
|
|
733
|
-
self,
|
|
734
|
-
this,
|
|
735
|
-
dispIdMember,
|
|
736
|
-
riid,
|
|
737
|
-
lcid,
|
|
738
|
-
wFlags,
|
|
739
|
-
pDispParams,
|
|
740
|
-
pVarResult,
|
|
741
|
-
pExcepInfo,
|
|
742
|
-
puArgErr,
|
|
743
|
-
):
|
|
744
|
-
try:
|
|
745
|
-
self._dispimpl_
|
|
746
|
-
except AttributeError:
|
|
747
|
-
try:
|
|
748
|
-
tinfo = self.__typeinfo
|
|
749
|
-
except AttributeError:
|
|
750
|
-
# Hm, we pretend to implement IDispatch, but have no
|
|
751
|
-
# typeinfo, and so cannot fulfill the contract. Should we
|
|
752
|
-
# better return E_NOTIMPL or DISP_E_MEMBERNOTFOUND? Some
|
|
753
|
-
# clients call IDispatch_Invoke with 'known' DISPID_...'
|
|
754
|
-
# values, without going through GetIDsOfNames first.
|
|
755
|
-
return DISP_E_MEMBERNOTFOUND
|
|
756
|
-
# This call uses windll instead of oledll so that a failed
|
|
757
|
-
# call to DispInvoke will return a HRESULT instead of raising
|
|
758
|
-
# an error.
|
|
759
|
-
interface = self._com_interfaces_[0]
|
|
760
|
-
ptr = self._com_pointers_[interface._iid_]
|
|
761
|
-
return windll.oleaut32.DispInvoke(
|
|
762
|
-
ptr,
|
|
763
|
-
tinfo,
|
|
764
|
-
dispIdMember,
|
|
765
|
-
wFlags,
|
|
766
|
-
pDispParams,
|
|
767
|
-
pVarResult,
|
|
768
|
-
pExcepInfo,
|
|
769
|
-
puArgErr,
|
|
770
|
-
)
|
|
771
|
-
|
|
772
|
-
try:
|
|
773
|
-
# XXX Hm, wFlags should be considered a SET of flags...
|
|
774
|
-
mth = self._dispimpl_[(dispIdMember, wFlags)]
|
|
775
|
-
except KeyError:
|
|
776
|
-
return DISP_E_MEMBERNOTFOUND
|
|
777
|
-
|
|
778
|
-
# Unpack the parameters: It would be great if we could use the
|
|
779
|
-
# DispGetParam function - but we cannot since it requires that
|
|
780
|
-
# we pass a VARTYPE for each argument and we do not know that.
|
|
781
|
-
#
|
|
782
|
-
# Seems that n arguments have dispids (0, 1, ..., n-1).
|
|
783
|
-
# Unnamed arguments are packed into the DISPPARAMS array in
|
|
784
|
-
# reverse order (starting with the highest dispid), named
|
|
785
|
-
# arguments are packed in the order specified by the
|
|
786
|
-
# rgdispidNamedArgs array.
|
|
787
|
-
#
|
|
788
|
-
params = pDispParams[0]
|
|
789
|
-
|
|
790
|
-
if wFlags & (4 | 8):
|
|
791
|
-
# DISPATCH_PROPERTYPUT
|
|
792
|
-
# DISPATCH_PROPERTYPUTREF
|
|
793
|
-
#
|
|
794
|
-
# How are the parameters unpacked for propertyput
|
|
795
|
-
# operations with additional parameters? Can propput
|
|
796
|
-
# have additional args?
|
|
797
|
-
args = [
|
|
798
|
-
params.rgvarg[i].value for i in reversed(list(range(params.cNamedArgs)))
|
|
799
|
-
]
|
|
800
|
-
# MSDN: pVarResult is ignored if DISPATCH_PROPERTYPUT or
|
|
801
|
-
# DISPATCH_PROPERTYPUTREF is specified.
|
|
802
|
-
return mth(this, *args)
|
|
803
|
-
|
|
804
|
-
else:
|
|
805
|
-
# DISPATCH_METHOD
|
|
806
|
-
# DISPATCH_PROPERTYGET
|
|
807
|
-
# the positions of named arguments
|
|
808
|
-
#
|
|
809
|
-
# 2to3 has problems to translate 'range(...)[::-1]'
|
|
810
|
-
# correctly, so use 'list(range)[::-1]' instead (will be
|
|
811
|
-
# fixed in Python 3.1, probably):
|
|
812
|
-
named_indexes = [
|
|
813
|
-
params.rgdispidNamedArgs[i] for i in range(params.cNamedArgs)
|
|
814
|
-
]
|
|
815
|
-
# the positions of unnamed arguments
|
|
816
|
-
num_unnamed = params.cArgs - params.cNamedArgs
|
|
817
|
-
unnamed_indexes = list(reversed(list(range(num_unnamed))))
|
|
818
|
-
# It seems that this code calculates the indexes of the
|
|
819
|
-
# parameters in the params.rgvarg array correctly.
|
|
820
|
-
indexes = named_indexes + unnamed_indexes
|
|
821
|
-
args = [params.rgvarg[i].value for i in indexes]
|
|
822
|
-
|
|
823
|
-
if pVarResult and getattr(mth, "has_outargs", False):
|
|
824
|
-
args.append(pVarResult)
|
|
825
|
-
return mth(this, *args)
|
|
826
|
-
|
|
827
|
-
################################################################
|
|
828
|
-
# IPersist interface
|
|
829
|
-
def IPersist_GetClassID(self):
|
|
830
|
-
return self._reg_clsid_
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
__all__ = ["COMObject"]
|