comtypes 1.4.4__zip → 1.4.5__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.4 → comtypes-1.4.5}/CHANGES.txt +12 -0
- {comtypes-1.4.4/comtypes.egg-info → comtypes-1.4.5}/PKG-INFO +1 -1
- comtypes-1.4.5/comtypes/__init__.py +268 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/_comobject.py +2 -1
- comtypes-1.4.5/comtypes/_idl_stuff.py +67 -0
- comtypes-1.4.5/comtypes/_post_coinit/__init__.py +15 -0
- comtypes-1.4.5/comtypes/_post_coinit/bstr.py +30 -0
- comtypes-1.4.5/comtypes/_post_coinit/misc.py +385 -0
- comtypes-1.4.5/comtypes/_post_coinit/unknwn.py +537 -0
- comtypes-1.4.5/comtypes/_py_instance_method.py +13 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/_safearray.py +3 -2
- comtypes-1.4.5/comtypes/_tlib_version_checker.py +18 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/automation.py +22 -6
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/client/_generate.py +2 -1
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/hints.pyi +34 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/safearray.py +11 -4
- comtypes-1.4.5/comtypes/stream.py +65 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_client.py +11 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_dispifc_records.py +1 -1
- comtypes-1.4.5/comtypes/test/test_dispifc_safearrays.py +89 -0
- comtypes-1.4.5/comtypes/test/test_istream.py +53 -0
- comtypes-1.4.5/comtypes/test/test_midl_safearray_create.py +100 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_wmi.py +11 -18
- {comtypes-1.4.4 → comtypes-1.4.5/comtypes.egg-info}/PKG-INFO +1 -1
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes.egg-info/SOURCES.txt +11 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/setup.cfg +1 -0
- comtypes-1.4.4/comtypes/__init__.py +0 -1229
- {comtypes-1.4.4 → comtypes-1.4.5}/LICENSE.txt +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/MANIFEST.in +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/README.md +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/GUID.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/_memberspec.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/_meta.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/_npsupport.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/clear_cache.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/client/__init__.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/client/_code_cache.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/client/_constants.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/client/_events.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/client/dynamic.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/client/lazybind.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/connectionpoints.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/errorinfo.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/git.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/hresult.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/logutil.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/messageloop.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/patcher.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/persist.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/server/__init__.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/server/automation.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/server/connectionpoints.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/server/inprocserver.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/server/localserver.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/server/register.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/server/w_getopt.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/shelllink.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/TestComServer.idl +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/TestComServer.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/TestComServer.tlb +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/TestDispServer.idl +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/TestDispServer.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/TestDispServer.tlb +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/__init__.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/find_memleak.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/mylib.idl +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/mylib.tlb +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/mytypelib.idl +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/runtests.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/setup.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_BSTR.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_DISPPARAMS.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_GUID.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_QueryService.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_agilent.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_avmc.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_basic.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_casesensitivity.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_clear_cache.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_client_dynamic.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_client_regenerate_modules.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_collections.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_comserver.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_createwrappers.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_dict.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_dispinterface.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_dyndispatch.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_excel.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_findgendir.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_getactiveobj.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_ie.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_ienum.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_imfattributes.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_inout_args.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_jscript.js +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_msscript.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_npsupport.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_outparam.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_propputref.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_pump_events.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_safearray.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_sapi.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_server.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_showevents.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_subinterface.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_typeinfo.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_urlhistory.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_variant.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_win32com_interop.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/test_word.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/test/urlhist.tlb +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/tools/__init__.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/tools/codegenerator/__init__.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/tools/codegenerator/codegenerator.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/tools/codegenerator/helpers.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/tools/codegenerator/modulenamer.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/tools/codegenerator/namespaces.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/tools/codegenerator/packing.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/tools/codegenerator/typeannotator.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/tools/tlbparser.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/tools/typedesc.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/tools/typedesc_base.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/typeinfo.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/util.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes/viewobject.py +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes.egg-info/dependency_links.txt +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes.egg-info/entry_points.txt +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/comtypes.egg-info/top_level.txt +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/pyproject.toml +0 -0
- {comtypes-1.4.4 → comtypes-1.4.5}/setup.py +0 -0
|
@@ -1,1229 +0,0 @@
|
|
|
1
|
-
# comtypes version numbers follow semver (http://semver.org/) and PEP 440
|
|
2
|
-
__version__ = "1.4.4"
|
|
3
|
-
|
|
4
|
-
import atexit
|
|
5
|
-
from ctypes import *
|
|
6
|
-
from ctypes import _Pointer, _SimpleCData
|
|
7
|
-
|
|
8
|
-
try:
|
|
9
|
-
from _ctypes import COMError
|
|
10
|
-
except ImportError as e:
|
|
11
|
-
msg = "\n".join(
|
|
12
|
-
(
|
|
13
|
-
"COM technology not available (maybe it's the wrong platform).",
|
|
14
|
-
"Note that COM is only supported on Windows.",
|
|
15
|
-
"For more details, please check: "
|
|
16
|
-
"https://learn.microsoft.com/en-us/windows/win32/com",
|
|
17
|
-
)
|
|
18
|
-
)
|
|
19
|
-
raise ImportError(msg) from e
|
|
20
|
-
import logging
|
|
21
|
-
import os
|
|
22
|
-
import sys
|
|
23
|
-
import types
|
|
24
|
-
|
|
25
|
-
# fmt: off
|
|
26
|
-
from typing import (
|
|
27
|
-
Any, ClassVar, overload, TYPE_CHECKING, TypeVar,
|
|
28
|
-
# instead of `builtins`. see PEP585
|
|
29
|
-
Dict, List, Tuple, Type,
|
|
30
|
-
# instead of `collections.abc`. see PEP585
|
|
31
|
-
Callable, Iterable, Iterator,
|
|
32
|
-
# instead of `A | B` and `None | A`. see PEP604
|
|
33
|
-
Optional, Union as _UnionT, # avoiding confusion with `ctypes.Union`
|
|
34
|
-
)
|
|
35
|
-
# fmt: on
|
|
36
|
-
if TYPE_CHECKING:
|
|
37
|
-
from ctypes import _CData # only in `typeshed`, private in runtime
|
|
38
|
-
from comtypes import hints as hints # type: ignore
|
|
39
|
-
else:
|
|
40
|
-
_CData = _SimpleCData.__mro__[:-1][-1]
|
|
41
|
-
|
|
42
|
-
from comtypes.GUID import GUID
|
|
43
|
-
from comtypes import patcher
|
|
44
|
-
from comtypes._npsupport import interop as npsupport
|
|
45
|
-
from comtypes._memberspec import (
|
|
46
|
-
ComMemberGenerator,
|
|
47
|
-
_ComMemberSpec,
|
|
48
|
-
DispMemberGenerator,
|
|
49
|
-
_DispMemberSpec,
|
|
50
|
-
_encode_idl,
|
|
51
|
-
_resolve_argspec,
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
_all_slice = slice(None, None, None)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class NullHandler(logging.Handler):
|
|
59
|
-
"""A Handler that does nothing."""
|
|
60
|
-
|
|
61
|
-
def emit(self, record):
|
|
62
|
-
pass
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
logger = logging.getLogger(__name__)
|
|
66
|
-
|
|
67
|
-
# Add a NULL handler to the comtypes logger. This prevents getting a
|
|
68
|
-
# message like this:
|
|
69
|
-
# No handlers could be found for logger "comtypes"
|
|
70
|
-
# when logging is not configured and logger.error() is called.
|
|
71
|
-
logger.addHandler(NullHandler())
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def _check_version(actual, tlib_cached_mtime=None):
|
|
75
|
-
from comtypes.tools.codegenerator import version as required
|
|
76
|
-
|
|
77
|
-
if actual != required:
|
|
78
|
-
raise ImportError("Wrong version")
|
|
79
|
-
if not hasattr(sys, "frozen"):
|
|
80
|
-
g = sys._getframe(1).f_globals
|
|
81
|
-
tlb_path = g.get("typelib_path")
|
|
82
|
-
try:
|
|
83
|
-
tlib_curr_mtime = os.stat(tlb_path).st_mtime
|
|
84
|
-
except (OSError, TypeError):
|
|
85
|
-
return
|
|
86
|
-
if not tlib_cached_mtime or abs(tlib_curr_mtime - tlib_cached_mtime) >= 1:
|
|
87
|
-
raise ImportError("Typelib different than module")
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
pythonapi.PyInstanceMethod_New.argtypes = [py_object]
|
|
91
|
-
pythonapi.PyInstanceMethod_New.restype = py_object
|
|
92
|
-
PyInstanceMethod_Type = type(pythonapi.PyInstanceMethod_New(id))
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def instancemethod(func, inst, cls):
|
|
96
|
-
mth = PyInstanceMethod_Type(func)
|
|
97
|
-
if inst is None:
|
|
98
|
-
return mth
|
|
99
|
-
return mth.__get__(inst)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
class ReturnHRESULT(Exception):
|
|
103
|
-
"""ReturnHRESULT(hresult, text)
|
|
104
|
-
|
|
105
|
-
Return a hresult code from a COM method implementation
|
|
106
|
-
without logging an error.
|
|
107
|
-
"""
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
# class IDLWarning(UserWarning):
|
|
111
|
-
# "Warn about questionable type information"
|
|
112
|
-
|
|
113
|
-
_GUID = GUID
|
|
114
|
-
IID = GUID
|
|
115
|
-
DWORD = c_ulong
|
|
116
|
-
|
|
117
|
-
wireHWND = c_ulong
|
|
118
|
-
|
|
119
|
-
################################################################
|
|
120
|
-
# About COM apartments:
|
|
121
|
-
# http://blogs.msdn.com/larryosterman/archive/2004/04/28/122240.aspx
|
|
122
|
-
################################################################
|
|
123
|
-
|
|
124
|
-
################################################################
|
|
125
|
-
# constants for object creation
|
|
126
|
-
CLSCTX_INPROC_SERVER = 1
|
|
127
|
-
CLSCTX_INPROC_HANDLER = 2
|
|
128
|
-
CLSCTX_LOCAL_SERVER = 4
|
|
129
|
-
|
|
130
|
-
CLSCTX_INPROC = 3
|
|
131
|
-
CLSCTX_SERVER = 5
|
|
132
|
-
CLSCTX_ALL = 7
|
|
133
|
-
|
|
134
|
-
CLSCTX_INPROC_SERVER16 = 8
|
|
135
|
-
CLSCTX_REMOTE_SERVER = 16
|
|
136
|
-
CLSCTX_INPROC_HANDLER16 = 32
|
|
137
|
-
CLSCTX_RESERVED1 = 64
|
|
138
|
-
CLSCTX_RESERVED2 = 128
|
|
139
|
-
CLSCTX_RESERVED3 = 256
|
|
140
|
-
CLSCTX_RESERVED4 = 512
|
|
141
|
-
CLSCTX_NO_CODE_DOWNLOAD = 1024
|
|
142
|
-
CLSCTX_RESERVED5 = 2048
|
|
143
|
-
CLSCTX_NO_CUSTOM_MARSHAL = 4096
|
|
144
|
-
CLSCTX_ENABLE_CODE_DOWNLOAD = 8192
|
|
145
|
-
CLSCTX_NO_FAILURE_LOG = 16384
|
|
146
|
-
CLSCTX_DISABLE_AAA = 32768
|
|
147
|
-
CLSCTX_ENABLE_AAA = 65536
|
|
148
|
-
CLSCTX_FROM_DEFAULT_CONTEXT = 131072
|
|
149
|
-
|
|
150
|
-
tagCLSCTX = c_int # enum
|
|
151
|
-
CLSCTX = tagCLSCTX
|
|
152
|
-
|
|
153
|
-
# Constants for security setups
|
|
154
|
-
SEC_WINNT_AUTH_IDENTITY_UNICODE = 0x2
|
|
155
|
-
RPC_C_AUTHN_WINNT = 10
|
|
156
|
-
RPC_C_AUTHZ_NONE = 0
|
|
157
|
-
RPC_C_AUTHN_LEVEL_CONNECT = 2
|
|
158
|
-
RPC_C_IMP_LEVEL_IMPERSONATE = 3
|
|
159
|
-
EOAC_NONE = 0
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
################################################################
|
|
163
|
-
# Initialization and shutdown
|
|
164
|
-
_ole32 = oledll.ole32
|
|
165
|
-
_ole32_nohresult = windll.ole32 # use this for functions that don't return a HRESULT
|
|
166
|
-
|
|
167
|
-
COINIT_MULTITHREADED = 0x0
|
|
168
|
-
COINIT_APARTMENTTHREADED = 0x2
|
|
169
|
-
COINIT_DISABLE_OLE1DDE = 0x4
|
|
170
|
-
COINIT_SPEED_OVER_MEMORY = 0x8
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
def CoInitialize():
|
|
174
|
-
return CoInitializeEx(COINIT_APARTMENTTHREADED)
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
def CoInitializeEx(flags=None):
|
|
178
|
-
if flags is None:
|
|
179
|
-
flags = getattr(sys, "coinit_flags", COINIT_APARTMENTTHREADED)
|
|
180
|
-
logger.debug("CoInitializeEx(None, %s)", flags)
|
|
181
|
-
_ole32.CoInitializeEx(None, flags)
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
# COM is initialized automatically for the thread that imports this
|
|
185
|
-
# module for the first time. sys.coinit_flags is passed as parameter
|
|
186
|
-
# to CoInitializeEx, if defined, otherwise COINIT_APARTMENTTHREADED
|
|
187
|
-
# (COINIT_MULTITHREADED on Windows CE) is used.
|
|
188
|
-
#
|
|
189
|
-
# A shutdown function is registered with atexit, so that
|
|
190
|
-
# CoUninitialize is called when Python is shut down.
|
|
191
|
-
CoInitializeEx()
|
|
192
|
-
|
|
193
|
-
# We need to have CoUninitialize for multithreaded model where we have
|
|
194
|
-
# to initialize and uninitialize COM for every new thread (except main)
|
|
195
|
-
# in which we are using COM
|
|
196
|
-
def CoUninitialize():
|
|
197
|
-
logger.debug("CoUninitialize()")
|
|
198
|
-
_ole32_nohresult.CoUninitialize()
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
def _shutdown(
|
|
202
|
-
func=_ole32_nohresult.CoUninitialize,
|
|
203
|
-
_debug=logger.debug,
|
|
204
|
-
_exc_clear=getattr(sys, "exc_clear", lambda: None),
|
|
205
|
-
):
|
|
206
|
-
# Make sure no COM pointers stay in exception frames.
|
|
207
|
-
_exc_clear()
|
|
208
|
-
# Sometimes, CoUninitialize, running at Python shutdown,
|
|
209
|
-
# raises an exception. We suppress this when __debug__ is
|
|
210
|
-
# False.
|
|
211
|
-
_debug("Calling CoUninitialize()")
|
|
212
|
-
if __debug__:
|
|
213
|
-
func()
|
|
214
|
-
else:
|
|
215
|
-
try:
|
|
216
|
-
func()
|
|
217
|
-
except WindowsError:
|
|
218
|
-
pass
|
|
219
|
-
# Set the flag which means that calling obj.Release() is no longer
|
|
220
|
-
# needed.
|
|
221
|
-
if _cominterface_meta is not None:
|
|
222
|
-
_cominterface_meta._com_shutting_down = True
|
|
223
|
-
_debug("CoUninitialize() done.")
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
atexit.register(_shutdown)
|
|
227
|
-
|
|
228
|
-
################################################################
|
|
229
|
-
# global registries.
|
|
230
|
-
|
|
231
|
-
# allows to find interface classes by guid strings (iid)
|
|
232
|
-
com_interface_registry = {}
|
|
233
|
-
|
|
234
|
-
# allows to find coclasses by guid strings (clsid)
|
|
235
|
-
com_coclass_registry = {}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
def _is_object(obj):
|
|
239
|
-
"""This function determines if the argument is a COM object. It
|
|
240
|
-
is used in several places to determine whether propputref or
|
|
241
|
-
propput setters have to be used."""
|
|
242
|
-
from comtypes.automation import VARIANT
|
|
243
|
-
|
|
244
|
-
# A COM pointer is an 'Object'
|
|
245
|
-
if isinstance(obj, POINTER(IUnknown)):
|
|
246
|
-
return True
|
|
247
|
-
# A COM pointer in a VARIANT is an 'Object', too
|
|
248
|
-
elif isinstance(obj, VARIANT) and isinstance(obj.value, POINTER(IUnknown)):
|
|
249
|
-
return True
|
|
250
|
-
# It may be a dynamic dispatch object.
|
|
251
|
-
return hasattr(obj, "_comobj")
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
################################################################
|
|
255
|
-
# The metaclasses...
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
class _cominterface_meta(type):
|
|
259
|
-
"""Metaclass for COM interfaces. Automatically creates high level
|
|
260
|
-
methods from COMMETHOD lists.
|
|
261
|
-
"""
|
|
262
|
-
|
|
263
|
-
_case_insensitive_: bool
|
|
264
|
-
_iid_: GUID
|
|
265
|
-
_methods_: List[_ComMemberSpec]
|
|
266
|
-
_disp_methods_: List[_DispMemberSpec]
|
|
267
|
-
|
|
268
|
-
# This flag is set to True by the atexit handler which calls
|
|
269
|
-
# CoUninitialize.
|
|
270
|
-
_com_shutting_down = False
|
|
271
|
-
|
|
272
|
-
# Creates also a POINTER type for the newly created class.
|
|
273
|
-
def __new__(cls, name, bases, namespace):
|
|
274
|
-
methods = namespace.pop("_methods_", None)
|
|
275
|
-
dispmethods = namespace.pop("_disp_methods_", None)
|
|
276
|
-
new_cls = type.__new__(cls, name, bases, namespace)
|
|
277
|
-
|
|
278
|
-
if methods is not None:
|
|
279
|
-
new_cls._methods_ = methods
|
|
280
|
-
if dispmethods is not None:
|
|
281
|
-
new_cls._disp_methods_ = dispmethods
|
|
282
|
-
|
|
283
|
-
# If we sublass a COM interface, for example:
|
|
284
|
-
#
|
|
285
|
-
# class IDispatch(IUnknown):
|
|
286
|
-
# ....
|
|
287
|
-
#
|
|
288
|
-
# then we need to make sure that POINTER(IDispatch) is a
|
|
289
|
-
# subclass of POINTER(IUnknown) because of the way ctypes
|
|
290
|
-
# typechecks work.
|
|
291
|
-
if bases == (object,):
|
|
292
|
-
_ptr_bases = (new_cls, _compointer_base)
|
|
293
|
-
else:
|
|
294
|
-
_ptr_bases = (new_cls, POINTER(bases[0]))
|
|
295
|
-
|
|
296
|
-
# The interface 'new_cls' is used as a mixin.
|
|
297
|
-
p = type(_compointer_base)(
|
|
298
|
-
"POINTER(%s)" % new_cls.__name__,
|
|
299
|
-
_ptr_bases,
|
|
300
|
-
{"__com_interface__": new_cls, "_needs_com_addref_": None},
|
|
301
|
-
)
|
|
302
|
-
|
|
303
|
-
from ctypes import _pointer_type_cache
|
|
304
|
-
|
|
305
|
-
_pointer_type_cache[new_cls] = p
|
|
306
|
-
|
|
307
|
-
if new_cls._case_insensitive_:
|
|
308
|
-
|
|
309
|
-
@patcher.Patch(p)
|
|
310
|
-
class CaseInsensitive(object):
|
|
311
|
-
# case insensitive attributes for COM methods and properties
|
|
312
|
-
def __getattr__(self, name):
|
|
313
|
-
"""Implement case insensitive access to methods and properties"""
|
|
314
|
-
try:
|
|
315
|
-
fixed_name = self.__map_case__[name.lower()]
|
|
316
|
-
except KeyError:
|
|
317
|
-
raise AttributeError(name)
|
|
318
|
-
if fixed_name != name: # prevent unbounded recursion
|
|
319
|
-
return getattr(self, fixed_name)
|
|
320
|
-
raise AttributeError(name)
|
|
321
|
-
|
|
322
|
-
# __setattr__ is pretty heavy-weight, because it is called for
|
|
323
|
-
# EVERY attribute assignment. Settings a non-com attribute
|
|
324
|
-
# through this function takes 8.6 usec, while without this
|
|
325
|
-
# function it takes 0.7 sec - 12 times slower.
|
|
326
|
-
#
|
|
327
|
-
# How much faster would this be if implemented in C?
|
|
328
|
-
def __setattr__(self, name, value):
|
|
329
|
-
"""Implement case insensitive access to methods and properties"""
|
|
330
|
-
object.__setattr__(
|
|
331
|
-
self, self.__map_case__.get(name.lower(), name), value
|
|
332
|
-
)
|
|
333
|
-
|
|
334
|
-
@patcher.Patch(POINTER(p))
|
|
335
|
-
class ReferenceFix(object):
|
|
336
|
-
def __setitem__(self, index, value):
|
|
337
|
-
# We override the __setitem__ method of the
|
|
338
|
-
# POINTER(POINTER(interface)) type, so that the COM
|
|
339
|
-
# reference count is managed correctly.
|
|
340
|
-
#
|
|
341
|
-
# This is so that we can implement COM methods that have to
|
|
342
|
-
# return COM pointers more easily and consistent. Instead of
|
|
343
|
-
# using CopyComPointer in the method implementation, we can
|
|
344
|
-
# simply do:
|
|
345
|
-
#
|
|
346
|
-
# def GetTypeInfo(self, this, ..., pptinfo):
|
|
347
|
-
# if not pptinfo: return E_POINTER
|
|
348
|
-
# pptinfo[0] = a_com_interface_pointer
|
|
349
|
-
# return S_OK
|
|
350
|
-
if index != 0:
|
|
351
|
-
# CopyComPointer, which is in _ctypes, does only
|
|
352
|
-
# handle an index of 0. This code does what
|
|
353
|
-
# CopyComPointer should do if index != 0.
|
|
354
|
-
if bool(value):
|
|
355
|
-
value.AddRef()
|
|
356
|
-
super(POINTER(p), self).__setitem__(index, value)
|
|
357
|
-
return
|
|
358
|
-
from _ctypes import CopyComPointer
|
|
359
|
-
|
|
360
|
-
CopyComPointer(value, self)
|
|
361
|
-
|
|
362
|
-
return new_cls
|
|
363
|
-
|
|
364
|
-
def __setattr__(self, name, value):
|
|
365
|
-
if name == "_methods_":
|
|
366
|
-
# XXX I'm no longer sure why the code generator generates
|
|
367
|
-
# "_methods_ = []" in the interface definition, and later
|
|
368
|
-
# overrides this by "Interface._methods_ = [...]
|
|
369
|
-
# assert self.__dict__.get("_methods_", None) is None
|
|
370
|
-
self._make_methods(value)
|
|
371
|
-
self._make_specials()
|
|
372
|
-
elif name == "_disp_methods_":
|
|
373
|
-
assert self.__dict__.get("_disp_methods_", None) is None
|
|
374
|
-
self._make_dispmethods(value)
|
|
375
|
-
self._make_specials()
|
|
376
|
-
type.__setattr__(self, name, value)
|
|
377
|
-
|
|
378
|
-
def _make_specials(self):
|
|
379
|
-
# This call installs methods that forward the Python protocols
|
|
380
|
-
# to COM protocols.
|
|
381
|
-
|
|
382
|
-
def has_name(name):
|
|
383
|
-
# Determine whether a property or method named 'name'
|
|
384
|
-
# exists
|
|
385
|
-
if self._case_insensitive_:
|
|
386
|
-
return name.lower() in self.__map_case__
|
|
387
|
-
return hasattr(self, name)
|
|
388
|
-
|
|
389
|
-
# XXX These special methods should be generated by the code generator.
|
|
390
|
-
if has_name("Count"):
|
|
391
|
-
|
|
392
|
-
@patcher.Patch(self)
|
|
393
|
-
class _(object):
|
|
394
|
-
def __len__(self):
|
|
395
|
-
"Return the the 'self.Count' property."
|
|
396
|
-
return self.Count
|
|
397
|
-
|
|
398
|
-
if has_name("Item"):
|
|
399
|
-
|
|
400
|
-
@patcher.Patch(self)
|
|
401
|
-
class _(object):
|
|
402
|
-
# 'Item' is the 'default' value. Make it available by
|
|
403
|
-
# calling the instance (Not sure this makes sense, but
|
|
404
|
-
# win32com does this also).
|
|
405
|
-
def __call__(self, *args, **kw):
|
|
406
|
-
"Return 'self.Item(*args, **kw)'"
|
|
407
|
-
return self.Item(*args, **kw)
|
|
408
|
-
|
|
409
|
-
# does this make sense? It seems that all standard typelibs I've
|
|
410
|
-
# seen so far that support .Item also support ._NewEnum
|
|
411
|
-
@patcher.no_replace
|
|
412
|
-
def __getitem__(self, index):
|
|
413
|
-
"Return 'self.Item(index)'"
|
|
414
|
-
# Handle tuples and all-slice
|
|
415
|
-
if isinstance(index, tuple):
|
|
416
|
-
args = index
|
|
417
|
-
elif index == _all_slice:
|
|
418
|
-
args = ()
|
|
419
|
-
else:
|
|
420
|
-
args = (index,)
|
|
421
|
-
|
|
422
|
-
try:
|
|
423
|
-
result = self.Item(*args)
|
|
424
|
-
except COMError as err:
|
|
425
|
-
(hresult, text, details) = err.args
|
|
426
|
-
if hresult == -2147352565: # DISP_E_BADINDEX
|
|
427
|
-
raise IndexError("invalid index")
|
|
428
|
-
else:
|
|
429
|
-
raise
|
|
430
|
-
|
|
431
|
-
# Note that result may be NULL COM pointer. There is no way
|
|
432
|
-
# to interpret this properly, so it is returned as-is.
|
|
433
|
-
|
|
434
|
-
# Hm, should we call __ctypes_from_outparam__ on the
|
|
435
|
-
# result?
|
|
436
|
-
return result
|
|
437
|
-
|
|
438
|
-
@patcher.no_replace
|
|
439
|
-
def __setitem__(self, index, value):
|
|
440
|
-
"Attempt 'self.Item[index] = value'"
|
|
441
|
-
try:
|
|
442
|
-
self.Item[index] = value
|
|
443
|
-
except COMError as err:
|
|
444
|
-
(hresult, text, details) = err.args
|
|
445
|
-
if hresult == -2147352565: # DISP_E_BADINDEX
|
|
446
|
-
raise IndexError("invalid index")
|
|
447
|
-
else:
|
|
448
|
-
raise
|
|
449
|
-
except TypeError:
|
|
450
|
-
msg = "%r object does not support item assignment"
|
|
451
|
-
raise TypeError(msg % type(self))
|
|
452
|
-
|
|
453
|
-
if has_name("_NewEnum"):
|
|
454
|
-
|
|
455
|
-
@patcher.Patch(self)
|
|
456
|
-
class _(object):
|
|
457
|
-
def __iter__(self):
|
|
458
|
-
"Return an iterator over the _NewEnum collection."
|
|
459
|
-
# This method returns a pointer to _some_ _NewEnum interface.
|
|
460
|
-
# It relies on the fact that the code generator creates next()
|
|
461
|
-
# methods for them automatically.
|
|
462
|
-
#
|
|
463
|
-
# Better would maybe to return an object that
|
|
464
|
-
# implements the Python iterator protocol, and
|
|
465
|
-
# forwards the calls to the COM interface.
|
|
466
|
-
enum = self._NewEnum
|
|
467
|
-
if isinstance(enum, types.MethodType):
|
|
468
|
-
# _NewEnum should be a propget property, with dispid -4.
|
|
469
|
-
#
|
|
470
|
-
# Sometimes, however, it is a method.
|
|
471
|
-
enum = enum()
|
|
472
|
-
if hasattr(enum, "Next"):
|
|
473
|
-
return enum
|
|
474
|
-
# _NewEnum returns an IUnknown pointer, QueryInterface() it to
|
|
475
|
-
# IEnumVARIANT
|
|
476
|
-
from comtypes.automation import IEnumVARIANT
|
|
477
|
-
|
|
478
|
-
return enum.QueryInterface(IEnumVARIANT)
|
|
479
|
-
|
|
480
|
-
def _make_case_insensitive(self):
|
|
481
|
-
# The __map_case__ dictionary maps lower case names to the
|
|
482
|
-
# names in the original spelling to enable case insensitive
|
|
483
|
-
# method and attribute access.
|
|
484
|
-
try:
|
|
485
|
-
self.__dict__["__map_case__"]
|
|
486
|
-
except KeyError:
|
|
487
|
-
d = {}
|
|
488
|
-
d.update(getattr(self, "__map_case__", {}))
|
|
489
|
-
self.__map_case__ = d
|
|
490
|
-
|
|
491
|
-
def _make_dispmethods(self, methods: List[_DispMemberSpec]) -> None:
|
|
492
|
-
if self._case_insensitive_:
|
|
493
|
-
self._make_case_insensitive()
|
|
494
|
-
# create dispinterface methods and properties on the interface 'self'
|
|
495
|
-
member_gen = DispMemberGenerator(self.__name__)
|
|
496
|
-
for m in methods:
|
|
497
|
-
member_gen.add(m)
|
|
498
|
-
for name, func_or_prop, is_prop in member_gen.items():
|
|
499
|
-
setattr(self, name, func_or_prop)
|
|
500
|
-
# COM is case insensitive.
|
|
501
|
-
# For a method, this is the real name. For a property,
|
|
502
|
-
# this is the name WITHOUT the _set_ or _get_ prefix.
|
|
503
|
-
if self._case_insensitive_:
|
|
504
|
-
self.__map_case__[name.lower()] = name
|
|
505
|
-
if is_prop:
|
|
506
|
-
self.__map_case__[name[5:].lower()] = name[5:]
|
|
507
|
-
for name, accessor in member_gen.properties():
|
|
508
|
-
setattr(self, name, accessor)
|
|
509
|
-
# COM is case insensitive
|
|
510
|
-
if self._case_insensitive_:
|
|
511
|
-
self.__map_case__[name.lower()] = name
|
|
512
|
-
|
|
513
|
-
def __get_baseinterface_methodcount(self):
|
|
514
|
-
"Return the number of com methods in the base interfaces"
|
|
515
|
-
try:
|
|
516
|
-
result = 0
|
|
517
|
-
for itf in self.mro()[1:-1]:
|
|
518
|
-
result += len(itf.__dict__["_methods_"])
|
|
519
|
-
return result
|
|
520
|
-
except KeyError as err:
|
|
521
|
-
(name,) = err.args
|
|
522
|
-
if name == "_methods_":
|
|
523
|
-
raise TypeError("baseinterface '%s' has no _methods_" % itf.__name__)
|
|
524
|
-
raise
|
|
525
|
-
|
|
526
|
-
def _make_methods(self, methods: List[_ComMemberSpec]) -> None:
|
|
527
|
-
if self._case_insensitive_:
|
|
528
|
-
self._make_case_insensitive()
|
|
529
|
-
# register com interface. we insist on an _iid_ in THIS class!
|
|
530
|
-
try:
|
|
531
|
-
iid = self.__dict__["_iid_"]
|
|
532
|
-
except KeyError:
|
|
533
|
-
raise AttributeError("this class must define an _iid_")
|
|
534
|
-
else:
|
|
535
|
-
com_interface_registry[str(iid)] = self
|
|
536
|
-
# create members
|
|
537
|
-
vtbl_offset = self.__get_baseinterface_methodcount()
|
|
538
|
-
member_gen = ComMemberGenerator(self.__name__, vtbl_offset, self._iid_)
|
|
539
|
-
# create private low level, and public high level methods
|
|
540
|
-
for m in methods:
|
|
541
|
-
member_gen.add(m)
|
|
542
|
-
for name, func, raw_func, is_prop in member_gen.methods():
|
|
543
|
-
raw_mth = instancemethod(raw_func, None, self)
|
|
544
|
-
setattr(self, "_%s__com_%s" % (self.__name__, name), raw_mth)
|
|
545
|
-
mth = instancemethod(func, None, self)
|
|
546
|
-
if not is_prop:
|
|
547
|
-
# We install the method in the class, except when it's a property.
|
|
548
|
-
# And we make sure we don't overwrite a property that's already present.
|
|
549
|
-
mthname = name if not hasattr(self, name) else ("_%s" % name)
|
|
550
|
-
setattr(self, mthname, mth)
|
|
551
|
-
# For a method, this is the real name.
|
|
552
|
-
# For a property, this is the name WITHOUT the _set_ or _get_ prefix.
|
|
553
|
-
if self._case_insensitive_:
|
|
554
|
-
self.__map_case__[name.lower()] = name
|
|
555
|
-
if is_prop:
|
|
556
|
-
self.__map_case__[name[5:].lower()] = name[5:]
|
|
557
|
-
# create public properties / attribute accessors
|
|
558
|
-
for name, accessor in member_gen.properties():
|
|
559
|
-
# Again, we should not overwrite class attributes that are already present.
|
|
560
|
-
propname = name if not hasattr(self, name) else ("_%s" % name)
|
|
561
|
-
setattr(self, propname, accessor)
|
|
562
|
-
# COM is case insensitive
|
|
563
|
-
if self._case_insensitive_:
|
|
564
|
-
self.__map_case__[name.lower()] = name
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
################################################################
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
class _compointer_meta(type(c_void_p), _cominterface_meta):
|
|
571
|
-
"metaclass for COM interface pointer classes"
|
|
572
|
-
# no functionality, but needed to avoid a metaclass conflict
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
class _compointer_base(c_void_p, metaclass=_compointer_meta):
|
|
576
|
-
"base class for COM interface pointer classes"
|
|
577
|
-
|
|
578
|
-
def __del__(self, _debug=logger.debug):
|
|
579
|
-
"Release the COM refcount we own."
|
|
580
|
-
if self:
|
|
581
|
-
# comtypes calls CoUninitialize() when the atexit handlers
|
|
582
|
-
# runs. CoUninitialize() cleans up the COM objects that
|
|
583
|
-
# are still alive. Python COM pointers may still be
|
|
584
|
-
# present but we can no longer call Release() on them -
|
|
585
|
-
# this may give a protection fault. So we need the
|
|
586
|
-
# _com_shutting_down flag.
|
|
587
|
-
#
|
|
588
|
-
if not type(self)._com_shutting_down:
|
|
589
|
-
_debug("Release %s", self)
|
|
590
|
-
self.Release()
|
|
591
|
-
|
|
592
|
-
def __cmp__(self, other):
|
|
593
|
-
"""Compare pointers to COM interfaces."""
|
|
594
|
-
# COM identity rule
|
|
595
|
-
#
|
|
596
|
-
# XXX To compare COM interface pointers, should we
|
|
597
|
-
# automatically QueryInterface for IUnknown on both items, and
|
|
598
|
-
# compare the pointer values?
|
|
599
|
-
if not isinstance(other, _compointer_base):
|
|
600
|
-
return 1
|
|
601
|
-
|
|
602
|
-
# get the value property of the c_void_p baseclass, this is the pointer value
|
|
603
|
-
return cmp(
|
|
604
|
-
super(_compointer_base, self).value, super(_compointer_base, other).value
|
|
605
|
-
)
|
|
606
|
-
|
|
607
|
-
def __eq__(self, other):
|
|
608
|
-
if not isinstance(other, _compointer_base):
|
|
609
|
-
return False
|
|
610
|
-
# get the value property of the c_void_p baseclass, this is the pointer value
|
|
611
|
-
return (
|
|
612
|
-
super(_compointer_base, self).value == super(_compointer_base, other).value
|
|
613
|
-
)
|
|
614
|
-
|
|
615
|
-
def __hash__(self):
|
|
616
|
-
"""Return the hash value of the pointer."""
|
|
617
|
-
# hash the pointer values
|
|
618
|
-
return hash(super(_compointer_base, self).value)
|
|
619
|
-
|
|
620
|
-
# redefine the .value property; return the object itself.
|
|
621
|
-
def __get_value(self):
|
|
622
|
-
return self
|
|
623
|
-
|
|
624
|
-
value = property(__get_value, doc="""Return self.""")
|
|
625
|
-
|
|
626
|
-
def __repr__(self):
|
|
627
|
-
ptr = super(_compointer_base, self).value
|
|
628
|
-
return "<%s ptr=0x%x at %x>" % (self.__class__.__name__, ptr or 0, id(self))
|
|
629
|
-
|
|
630
|
-
# This fixes the problem when there are multiple python interface types
|
|
631
|
-
# wrapping the same COM interface. This could happen because some interfaces
|
|
632
|
-
# are contained in multiple typelibs.
|
|
633
|
-
#
|
|
634
|
-
# It also allows to pass a CoClass instance to an api
|
|
635
|
-
# expecting a COM interface.
|
|
636
|
-
@classmethod
|
|
637
|
-
def from_param(cls, value):
|
|
638
|
-
"""Convert 'value' into a COM pointer to the interface.
|
|
639
|
-
|
|
640
|
-
This method accepts a COM pointer, or a CoClass instance
|
|
641
|
-
which is QueryInterface()d."""
|
|
642
|
-
if value is None:
|
|
643
|
-
return None
|
|
644
|
-
# CLF: 2013-01-18
|
|
645
|
-
# A default value of 0, meaning null, can pass through to here.
|
|
646
|
-
if value == 0:
|
|
647
|
-
return None
|
|
648
|
-
if isinstance(value, cls):
|
|
649
|
-
return value
|
|
650
|
-
# multiple python interface types for the same COM interface.
|
|
651
|
-
# Do we need more checks here?
|
|
652
|
-
if cls._iid_ == getattr(value, "_iid_", None):
|
|
653
|
-
return value
|
|
654
|
-
# Accept an CoClass instance which exposes the interface required.
|
|
655
|
-
try:
|
|
656
|
-
table = value._com_pointers_
|
|
657
|
-
except AttributeError:
|
|
658
|
-
pass
|
|
659
|
-
else:
|
|
660
|
-
try:
|
|
661
|
-
# a kind of QueryInterface
|
|
662
|
-
return table[cls._iid_]
|
|
663
|
-
except KeyError:
|
|
664
|
-
raise TypeError("Interface %s not supported" % cls._iid_)
|
|
665
|
-
return value.QueryInterface(cls.__com_interface__)
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
################################################################
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
class BSTR(_SimpleCData):
|
|
672
|
-
"The windows BSTR data type"
|
|
673
|
-
_type_ = "X"
|
|
674
|
-
_needsfree = False
|
|
675
|
-
|
|
676
|
-
def __repr__(self):
|
|
677
|
-
return "%s(%r)" % (self.__class__.__name__, self.value)
|
|
678
|
-
|
|
679
|
-
def __ctypes_from_outparam__(self):
|
|
680
|
-
self._needsfree = True
|
|
681
|
-
return self.value
|
|
682
|
-
|
|
683
|
-
def __del__(self, _free=windll.oleaut32.SysFreeString):
|
|
684
|
-
# Free the string if self owns the memory
|
|
685
|
-
# or if instructed by __ctypes_from_outparam__.
|
|
686
|
-
if self._b_base_ is None or self._needsfree:
|
|
687
|
-
_free(self)
|
|
688
|
-
|
|
689
|
-
@classmethod
|
|
690
|
-
def from_param(cls, value):
|
|
691
|
-
"""Convert into a foreign function call parameter."""
|
|
692
|
-
if isinstance(value, cls):
|
|
693
|
-
return value
|
|
694
|
-
# Although the builtin SimpleCData.from_param call does the
|
|
695
|
-
# right thing, it doesn't ensure that SysFreeString is called
|
|
696
|
-
# on destruction.
|
|
697
|
-
return cls(value)
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
################################################################
|
|
701
|
-
# IDL stuff
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
class helpstring(str):
|
|
705
|
-
"Specifies the helpstring for a COM method or property."
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
class defaultvalue(object):
|
|
709
|
-
"Specifies the default value for parameters marked optional."
|
|
710
|
-
|
|
711
|
-
def __init__(self, value):
|
|
712
|
-
self.value = value
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
class dispid(int):
|
|
716
|
-
"Specifies the DISPID of a method or property."
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
# XXX STDMETHOD, COMMETHOD, DISPMETHOD, and DISPPROPERTY should return
|
|
720
|
-
# instances with more methods or properties, and should not behave as an unpackable.
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
def STDMETHOD(restype, name, argtypes=()) -> _ComMemberSpec:
|
|
724
|
-
"Specifies a COM method slot without idlflags"
|
|
725
|
-
return _ComMemberSpec(restype, name, argtypes, None, (), None)
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
def DISPMETHOD(idlflags, restype, name, *argspec) -> _DispMemberSpec:
|
|
729
|
-
"Specifies a method of a dispinterface"
|
|
730
|
-
return _DispMemberSpec("DISPMETHOD", name, tuple(idlflags), restype, argspec)
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
def DISPPROPERTY(idlflags, proptype, name) -> _DispMemberSpec:
|
|
734
|
-
"Specifies a property of a dispinterface"
|
|
735
|
-
return _DispMemberSpec("DISPPROPERTY", name, tuple(idlflags), proptype, ())
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
# tuple(idlflags) is for the method itself: (dispid, 'readonly')
|
|
739
|
-
|
|
740
|
-
# sample generated code:
|
|
741
|
-
# DISPPROPERTY([5, 'readonly'], OLE_YSIZE_HIMETRIC, 'Height'),
|
|
742
|
-
# DISPMETHOD(
|
|
743
|
-
# [6], None, 'Render', ([], c_int, 'hdc'), ([], c_int, 'x'), ([], c_int, 'y')
|
|
744
|
-
# )
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
def COMMETHOD(idlflags, restype, methodname, *argspec) -> _ComMemberSpec:
|
|
748
|
-
"""Specifies a COM method slot with idlflags.
|
|
749
|
-
|
|
750
|
-
XXX should explain the sematics of the arguments.
|
|
751
|
-
"""
|
|
752
|
-
# collect all helpstring instances
|
|
753
|
-
# We should suppress docstrings when Python is started with -OO
|
|
754
|
-
# join them together(does this make sense?) and replace by None if empty.
|
|
755
|
-
helptext = "".join(t for t in idlflags if isinstance(t, helpstring)) or None
|
|
756
|
-
paramflags, argtypes = _resolve_argspec(argspec)
|
|
757
|
-
if "propget" in idlflags:
|
|
758
|
-
name = "_get_%s" % methodname
|
|
759
|
-
elif "propput" in idlflags:
|
|
760
|
-
name = "_set_%s" % methodname
|
|
761
|
-
elif "propputref" in idlflags:
|
|
762
|
-
name = "_setref_%s" % methodname
|
|
763
|
-
else:
|
|
764
|
-
name = methodname
|
|
765
|
-
return _ComMemberSpec(
|
|
766
|
-
restype, name, argtypes, paramflags, tuple(idlflags), helptext
|
|
767
|
-
)
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
################################################################
|
|
771
|
-
# IUnknown, the root of all evil...
|
|
772
|
-
|
|
773
|
-
_T_IUnknown = TypeVar("_T_IUnknown", bound="IUnknown")
|
|
774
|
-
|
|
775
|
-
if TYPE_CHECKING:
|
|
776
|
-
|
|
777
|
-
class _IUnknown_Base(c_void_p, metaclass=_cominterface_meta): # type: ignore
|
|
778
|
-
"""This is workaround to avoid false-positive of static type checking.
|
|
779
|
-
|
|
780
|
-
`IUnknown` behaves as a ctypes type, and `POINTER` can take it.
|
|
781
|
-
This behavior is defined by some metaclasses in runtime.
|
|
782
|
-
|
|
783
|
-
In runtime, this symbol in the namespace is just alias for
|
|
784
|
-
`builtins.object`.
|
|
785
|
-
"""
|
|
786
|
-
|
|
787
|
-
...
|
|
788
|
-
|
|
789
|
-
else:
|
|
790
|
-
_IUnknown_Base = object
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
class IUnknown(_IUnknown_Base, metaclass=_cominterface_meta):
|
|
794
|
-
"""The most basic COM interface.
|
|
795
|
-
|
|
796
|
-
Each subclasses of IUnknown must define these class attributes:
|
|
797
|
-
|
|
798
|
-
_iid_ - a GUID instance defining the identifier of this interface
|
|
799
|
-
|
|
800
|
-
_methods_ - a list of methods for this interface.
|
|
801
|
-
|
|
802
|
-
The _methods_ list must in VTable order. Methods are specified
|
|
803
|
-
with STDMETHOD or COMMETHOD calls.
|
|
804
|
-
"""
|
|
805
|
-
|
|
806
|
-
_case_insensitive_: ClassVar[bool] = False
|
|
807
|
-
_iid_: ClassVar[GUID] = GUID("{00000000-0000-0000-C000-000000000046}")
|
|
808
|
-
_methods_: ClassVar[List[_ComMemberSpec]] = [
|
|
809
|
-
STDMETHOD(HRESULT, "QueryInterface", [POINTER(GUID), POINTER(c_void_p)]),
|
|
810
|
-
STDMETHOD(c_ulong, "AddRef"),
|
|
811
|
-
STDMETHOD(c_ulong, "Release"),
|
|
812
|
-
]
|
|
813
|
-
|
|
814
|
-
# NOTE: Why not `QueryInterface(T) -> _Pointer[T]`?
|
|
815
|
-
# Any static type checkers is not able to provide members of `T` from `_Pointer[T]`,
|
|
816
|
-
# regardless of the pointer is able to access members of contents in runtime.
|
|
817
|
-
# And if `isinstance(p, POINTER(T))` is `True`, then `isinstance(p, T)` is also `True`.
|
|
818
|
-
# So returning `T` is not a lie, and good way to know what members the class has.
|
|
819
|
-
def QueryInterface(
|
|
820
|
-
self, interface: Type[_T_IUnknown], iid: Optional[GUID] = None
|
|
821
|
-
) -> _T_IUnknown:
|
|
822
|
-
"""QueryInterface(interface) -> instance"""
|
|
823
|
-
p = POINTER(interface)()
|
|
824
|
-
if iid is None:
|
|
825
|
-
iid = interface._iid_
|
|
826
|
-
self.__com_QueryInterface(byref(iid), byref(p)) # type: ignore
|
|
827
|
-
clsid = self.__dict__.get("__clsid")
|
|
828
|
-
if clsid is not None:
|
|
829
|
-
p.__dict__["__clsid"] = clsid
|
|
830
|
-
return p # type: ignore
|
|
831
|
-
|
|
832
|
-
# these are only so that they get a docstring.
|
|
833
|
-
# XXX There should be other ways to install a docstring.
|
|
834
|
-
def AddRef(self) -> int:
|
|
835
|
-
"""Increase the internal refcount by one and return it."""
|
|
836
|
-
return self.__com_AddRef() # type: ignore
|
|
837
|
-
|
|
838
|
-
def Release(self) -> int:
|
|
839
|
-
"""Decrease the internal refcount by one and return it."""
|
|
840
|
-
return self.__com_Release() # type: ignore
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
################################################################
|
|
844
|
-
# IPersist is a trivial interface, which allows to ask an object about
|
|
845
|
-
# its clsid.
|
|
846
|
-
class IPersist(IUnknown):
|
|
847
|
-
_iid_ = GUID("{0000010C-0000-0000-C000-000000000046}")
|
|
848
|
-
_idlflags_ = []
|
|
849
|
-
_methods_ = [
|
|
850
|
-
COMMETHOD([], HRESULT, "GetClassID", (["out"], POINTER(GUID), "pClassID")),
|
|
851
|
-
]
|
|
852
|
-
if TYPE_CHECKING:
|
|
853
|
-
# Should this be "normal" method that calls `self._GetClassID`?
|
|
854
|
-
def GetClassID(self) -> GUID:
|
|
855
|
-
"""Returns the CLSID that uniquely represents an object class that
|
|
856
|
-
defines the code that can manipulate the object's data.
|
|
857
|
-
"""
|
|
858
|
-
...
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
class IServiceProvider(IUnknown):
|
|
862
|
-
_iid_ = GUID("{6D5140C1-7436-11CE-8034-00AA006009FA}")
|
|
863
|
-
_QueryService: Callable[[Any, Any, Any], int]
|
|
864
|
-
# Overridden QueryService to make it nicer to use (passing it an
|
|
865
|
-
# interface and it returns a pointer to that interface)
|
|
866
|
-
def QueryService(
|
|
867
|
-
self, serviceIID: GUID, interface: Type[_T_IUnknown]
|
|
868
|
-
) -> _T_IUnknown:
|
|
869
|
-
p = POINTER(interface)()
|
|
870
|
-
self._QueryService(byref(serviceIID), byref(interface._iid_), byref(p))
|
|
871
|
-
return p # type: ignore
|
|
872
|
-
|
|
873
|
-
_methods_ = [
|
|
874
|
-
COMMETHOD(
|
|
875
|
-
[],
|
|
876
|
-
HRESULT,
|
|
877
|
-
"QueryService",
|
|
878
|
-
(["in"], POINTER(GUID), "guidService"),
|
|
879
|
-
(["in"], POINTER(GUID), "riid"),
|
|
880
|
-
(["in"], POINTER(c_void_p), "ppvObject"),
|
|
881
|
-
)
|
|
882
|
-
]
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
################################################################
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
@overload
|
|
889
|
-
def CoGetObject(displayname: str, interface: None) -> IUnknown:
|
|
890
|
-
...
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
@overload
|
|
894
|
-
def CoGetObject(displayname: str, interface: Type[_T_IUnknown]) -> _T_IUnknown:
|
|
895
|
-
...
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
def CoGetObject(displayname: str, interface: Optional[Type[IUnknown]]) -> IUnknown:
|
|
899
|
-
"""Convert a displayname to a moniker, then bind and return the object
|
|
900
|
-
identified by the moniker."""
|
|
901
|
-
if interface is None:
|
|
902
|
-
interface = IUnknown
|
|
903
|
-
punk = POINTER(interface)()
|
|
904
|
-
# Do we need a way to specify the BIND_OPTS parameter?
|
|
905
|
-
_ole32.CoGetObject(str(displayname), None, byref(interface._iid_), byref(punk))
|
|
906
|
-
return punk # type: ignore
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
_pUnkOuter = Type["_Pointer[IUnknown]"]
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
@overload
|
|
913
|
-
def CoCreateInstance(
|
|
914
|
-
clsid: GUID,
|
|
915
|
-
interface: None = None,
|
|
916
|
-
clsctx: Optional[int] = None,
|
|
917
|
-
punkouter: Optional[_pUnkOuter] = None,
|
|
918
|
-
) -> IUnknown:
|
|
919
|
-
...
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
@overload
|
|
923
|
-
def CoCreateInstance(
|
|
924
|
-
clsid: GUID,
|
|
925
|
-
interface: Type[_T_IUnknown],
|
|
926
|
-
clsctx: Optional[int] = None,
|
|
927
|
-
punkouter: Optional[_pUnkOuter] = None,
|
|
928
|
-
) -> _T_IUnknown:
|
|
929
|
-
...
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
def CoCreateInstance(
|
|
933
|
-
clsid: GUID,
|
|
934
|
-
interface: Optional[Type[IUnknown]] = None,
|
|
935
|
-
clsctx: Optional[int] = None,
|
|
936
|
-
punkouter: Optional[_pUnkOuter] = None,
|
|
937
|
-
) -> IUnknown:
|
|
938
|
-
"""The basic windows api to create a COM class object and return a
|
|
939
|
-
pointer to an interface.
|
|
940
|
-
"""
|
|
941
|
-
if clsctx is None:
|
|
942
|
-
clsctx = CLSCTX_SERVER
|
|
943
|
-
if interface is None:
|
|
944
|
-
interface = IUnknown
|
|
945
|
-
p = POINTER(interface)()
|
|
946
|
-
iid = interface._iid_
|
|
947
|
-
_ole32.CoCreateInstance(byref(clsid), punkouter, clsctx, byref(iid), byref(p))
|
|
948
|
-
return p # type: ignore
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
if TYPE_CHECKING:
|
|
952
|
-
|
|
953
|
-
@overload
|
|
954
|
-
def CoGetClassObject(clsid, clsctx=None, pServerInfo=None, interface=None):
|
|
955
|
-
# type: (GUID, Optional[int], Optional[COSERVERINFO], None) -> hints.IClassFactory
|
|
956
|
-
pass
|
|
957
|
-
|
|
958
|
-
@overload
|
|
959
|
-
def CoGetClassObject(clsid, clsctx=None, pServerInfo=None, interface=None):
|
|
960
|
-
# type: (GUID, Optional[int], Optional[COSERVERINFO], Type[_T_IUnknown]) -> _T_IUnknown
|
|
961
|
-
pass
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
def CoGetClassObject(clsid, clsctx=None, pServerInfo=None, interface=None):
|
|
965
|
-
# type: (GUID, Optional[int], Optional[COSERVERINFO], Optional[Type[IUnknown]]) -> IUnknown
|
|
966
|
-
if clsctx is None:
|
|
967
|
-
clsctx = CLSCTX_SERVER
|
|
968
|
-
if interface is None:
|
|
969
|
-
import comtypes.server
|
|
970
|
-
|
|
971
|
-
interface = comtypes.server.IClassFactory
|
|
972
|
-
p = POINTER(interface)()
|
|
973
|
-
_CoGetClassObject(clsid, clsctx, pServerInfo, interface._iid_, byref(p))
|
|
974
|
-
return p # type: ignore
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
@overload
|
|
978
|
-
def GetActiveObject(clsid: GUID, interface: None = None) -> IUnknown:
|
|
979
|
-
...
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
@overload
|
|
983
|
-
def GetActiveObject(clsid: GUID, interface: Type[_T_IUnknown]) -> _T_IUnknown:
|
|
984
|
-
...
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
def GetActiveObject(
|
|
988
|
-
clsid: GUID, interface: Optional[Type[IUnknown]] = None
|
|
989
|
-
) -> IUnknown:
|
|
990
|
-
"""Retrieves a pointer to a running object"""
|
|
991
|
-
p = POINTER(IUnknown)()
|
|
992
|
-
oledll.oleaut32.GetActiveObject(byref(clsid), None, byref(p))
|
|
993
|
-
if interface is not None:
|
|
994
|
-
p = p.QueryInterface(interface) # type: ignore
|
|
995
|
-
return p # type: ignore
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
class MULTI_QI(Structure):
|
|
999
|
-
_fields_ = [("pIID", POINTER(GUID)), ("pItf", POINTER(c_void_p)), ("hr", HRESULT)]
|
|
1000
|
-
if TYPE_CHECKING:
|
|
1001
|
-
pIID: GUID
|
|
1002
|
-
pItf: _Pointer[c_void_p]
|
|
1003
|
-
hr: HRESULT
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
class _COAUTHIDENTITY(Structure):
|
|
1007
|
-
_fields_ = [
|
|
1008
|
-
("User", POINTER(c_ushort)),
|
|
1009
|
-
("UserLength", c_ulong),
|
|
1010
|
-
("Domain", POINTER(c_ushort)),
|
|
1011
|
-
("DomainLength", c_ulong),
|
|
1012
|
-
("Password", POINTER(c_ushort)),
|
|
1013
|
-
("PasswordLength", c_ulong),
|
|
1014
|
-
("Flags", c_ulong),
|
|
1015
|
-
]
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
COAUTHIDENTITY = _COAUTHIDENTITY
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
class _COAUTHINFO(Structure):
|
|
1022
|
-
_fields_ = [
|
|
1023
|
-
("dwAuthnSvc", c_ulong),
|
|
1024
|
-
("dwAuthzSvc", c_ulong),
|
|
1025
|
-
("pwszServerPrincName", c_wchar_p),
|
|
1026
|
-
("dwAuthnLevel", c_ulong),
|
|
1027
|
-
("dwImpersonationLevel", c_ulong),
|
|
1028
|
-
("pAuthIdentityData", POINTER(_COAUTHIDENTITY)),
|
|
1029
|
-
("dwCapabilities", c_ulong),
|
|
1030
|
-
]
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
COAUTHINFO = _COAUTHINFO
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
class _COSERVERINFO(Structure):
|
|
1037
|
-
_fields_ = [
|
|
1038
|
-
("dwReserved1", c_ulong),
|
|
1039
|
-
("pwszName", c_wchar_p),
|
|
1040
|
-
("pAuthInfo", POINTER(_COAUTHINFO)),
|
|
1041
|
-
("dwReserved2", c_ulong),
|
|
1042
|
-
]
|
|
1043
|
-
if TYPE_CHECKING:
|
|
1044
|
-
dwReserved1: int
|
|
1045
|
-
pwszName: Optional[str]
|
|
1046
|
-
pAuthInfo: _COAUTHINFO
|
|
1047
|
-
dwReserved2: int
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
COSERVERINFO = _COSERVERINFO
|
|
1051
|
-
_CoGetClassObject = _ole32.CoGetClassObject
|
|
1052
|
-
_CoGetClassObject.argtypes = [
|
|
1053
|
-
POINTER(GUID),
|
|
1054
|
-
DWORD,
|
|
1055
|
-
POINTER(COSERVERINFO),
|
|
1056
|
-
POINTER(GUID),
|
|
1057
|
-
POINTER(c_void_p),
|
|
1058
|
-
]
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
class tagBIND_OPTS(Structure):
|
|
1062
|
-
_fields_ = [
|
|
1063
|
-
("cbStruct", c_ulong),
|
|
1064
|
-
("grfFlags", c_ulong),
|
|
1065
|
-
("grfMode", c_ulong),
|
|
1066
|
-
("dwTickCountDeadline", c_ulong),
|
|
1067
|
-
]
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
# XXX Add __init__ which sets cbStruct?
|
|
1071
|
-
BIND_OPTS = tagBIND_OPTS
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
class tagBIND_OPTS2(Structure):
|
|
1075
|
-
_fields_ = [
|
|
1076
|
-
("cbStruct", c_ulong),
|
|
1077
|
-
("grfFlags", c_ulong),
|
|
1078
|
-
("grfMode", c_ulong),
|
|
1079
|
-
("dwTickCountDeadline", c_ulong),
|
|
1080
|
-
("dwTrackFlags", c_ulong),
|
|
1081
|
-
("dwClassContext", c_ulong),
|
|
1082
|
-
("locale", c_ulong),
|
|
1083
|
-
("pServerInfo", POINTER(_COSERVERINFO)),
|
|
1084
|
-
]
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
# XXX Add __init__ which sets cbStruct?
|
|
1088
|
-
BINDOPTS2 = tagBIND_OPTS2
|
|
1089
|
-
|
|
1090
|
-
# Structures for security setups
|
|
1091
|
-
#########################################
|
|
1092
|
-
class _SEC_WINNT_AUTH_IDENTITY(Structure):
|
|
1093
|
-
_fields_ = [
|
|
1094
|
-
("User", POINTER(c_ushort)),
|
|
1095
|
-
("UserLength", c_ulong),
|
|
1096
|
-
("Domain", POINTER(c_ushort)),
|
|
1097
|
-
("DomainLength", c_ulong),
|
|
1098
|
-
("Password", POINTER(c_ushort)),
|
|
1099
|
-
("PasswordLength", c_ulong),
|
|
1100
|
-
("Flags", c_ulong),
|
|
1101
|
-
]
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
SEC_WINNT_AUTH_IDENTITY = _SEC_WINNT_AUTH_IDENTITY
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
class _SOLE_AUTHENTICATION_INFO(Structure):
|
|
1108
|
-
_fields_ = [
|
|
1109
|
-
("dwAuthnSvc", c_ulong),
|
|
1110
|
-
("dwAuthzSvc", c_ulong),
|
|
1111
|
-
("pAuthInfo", POINTER(_SEC_WINNT_AUTH_IDENTITY)),
|
|
1112
|
-
]
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
SOLE_AUTHENTICATION_INFO = _SOLE_AUTHENTICATION_INFO
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
class _SOLE_AUTHENTICATION_LIST(Structure):
|
|
1119
|
-
_fields_ = [
|
|
1120
|
-
("cAuthInfo", c_ulong),
|
|
1121
|
-
("pAuthInfo", POINTER(_SOLE_AUTHENTICATION_INFO)),
|
|
1122
|
-
]
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
SOLE_AUTHENTICATION_LIST = _SOLE_AUTHENTICATION_LIST
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
@overload
|
|
1129
|
-
def CoCreateInstanceEx(
|
|
1130
|
-
clsid: GUID,
|
|
1131
|
-
interface: None = None,
|
|
1132
|
-
clsctx: Optional[int] = None,
|
|
1133
|
-
machine: Optional[str] = None,
|
|
1134
|
-
pServerInfo: Optional[COSERVERINFO] = None,
|
|
1135
|
-
) -> IUnknown:
|
|
1136
|
-
...
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
@overload
|
|
1140
|
-
def CoCreateInstanceEx(
|
|
1141
|
-
clsid: GUID,
|
|
1142
|
-
interface: Type[_T_IUnknown],
|
|
1143
|
-
clsctx: Optional[int] = None,
|
|
1144
|
-
machine: Optional[str] = None,
|
|
1145
|
-
pServerInfo: Optional[COSERVERINFO] = None,
|
|
1146
|
-
) -> _T_IUnknown:
|
|
1147
|
-
...
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
def CoCreateInstanceEx(
|
|
1151
|
-
clsid: GUID,
|
|
1152
|
-
interface: Optional[Type[IUnknown]] = None,
|
|
1153
|
-
clsctx: Optional[int] = None,
|
|
1154
|
-
machine: Optional[str] = None,
|
|
1155
|
-
pServerInfo: Optional[COSERVERINFO] = None,
|
|
1156
|
-
) -> IUnknown:
|
|
1157
|
-
"""The basic windows api to create a COM class object and return a
|
|
1158
|
-
pointer to an interface, possibly on another machine.
|
|
1159
|
-
|
|
1160
|
-
Passing both "machine" and "pServerInfo" results in a ValueError.
|
|
1161
|
-
|
|
1162
|
-
"""
|
|
1163
|
-
if clsctx is None:
|
|
1164
|
-
clsctx = CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER
|
|
1165
|
-
|
|
1166
|
-
if pServerInfo is not None:
|
|
1167
|
-
if machine is not None:
|
|
1168
|
-
msg = "Can not specify both machine name and server info"
|
|
1169
|
-
raise ValueError(msg)
|
|
1170
|
-
elif machine is not None:
|
|
1171
|
-
serverinfo = COSERVERINFO()
|
|
1172
|
-
serverinfo.pwszName = machine
|
|
1173
|
-
pServerInfo = byref(serverinfo) # type: ignore
|
|
1174
|
-
|
|
1175
|
-
if interface is None:
|
|
1176
|
-
interface = IUnknown
|
|
1177
|
-
multiqi = MULTI_QI()
|
|
1178
|
-
multiqi.pIID = pointer(interface._iid_) # type: ignore
|
|
1179
|
-
_ole32.CoCreateInstanceEx(
|
|
1180
|
-
byref(clsid), None, clsctx, pServerInfo, 1, byref(multiqi)
|
|
1181
|
-
)
|
|
1182
|
-
return cast(multiqi.pItf, POINTER(interface)) # type: ignore
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
################################################################
|
|
1186
|
-
from comtypes._comobject import COMObject
|
|
1187
|
-
|
|
1188
|
-
# What's a coclass?
|
|
1189
|
-
# a POINTER to a coclass is allowed as parameter in a function declaration:
|
|
1190
|
-
# http://msdn.microsoft.com/library/en-us/midl/midl/oleautomation.asp
|
|
1191
|
-
|
|
1192
|
-
from comtypes._meta import _coclass_meta
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
class CoClass(COMObject, metaclass=_coclass_meta):
|
|
1196
|
-
pass
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
################################################################
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
# fmt: off
|
|
1203
|
-
__known_symbols__ = [
|
|
1204
|
-
"BIND_OPTS", "tagBIND_OPTS", "BINDOPTS2", "tagBIND_OPTS2", "BSTR",
|
|
1205
|
-
"_check_version", "CLSCTX", "tagCLSCTX", "CLSCTX_ALL",
|
|
1206
|
-
"CLSCTX_DISABLE_AAA", "CLSCTX_ENABLE_AAA", "CLSCTX_ENABLE_CODE_DOWNLOAD",
|
|
1207
|
-
"CLSCTX_FROM_DEFAULT_CONTEXT", "CLSCTX_INPROC", "CLSCTX_INPROC_HANDLER",
|
|
1208
|
-
"CLSCTX_INPROC_HANDLER16", "CLSCTX_INPROC_SERVER",
|
|
1209
|
-
"CLSCTX_INPROC_SERVER16", "CLSCTX_LOCAL_SERVER", "CLSCTX_NO_CODE_DOWNLOAD",
|
|
1210
|
-
"CLSCTX_NO_CUSTOM_MARSHAL", "CLSCTX_NO_FAILURE_LOG",
|
|
1211
|
-
"CLSCTX_REMOTE_SERVER", "CLSCTX_RESERVED1", "CLSCTX_RESERVED2",
|
|
1212
|
-
"CLSCTX_RESERVED3", "CLSCTX_RESERVED4", "CLSCTX_RESERVED5",
|
|
1213
|
-
"CLSCTX_SERVER", "_COAUTHIDENTITY", "COAUTHIDENTITY", "_COAUTHINFO",
|
|
1214
|
-
"COAUTHINFO", "CoClass", "CoCreateInstance", "CoCreateInstanceEx",
|
|
1215
|
-
"_CoGetClassObject", "CoGetClassObject", "CoGetObject",
|
|
1216
|
-
"COINIT_APARTMENTTHREADED", "COINIT_DISABLE_OLE1DDE",
|
|
1217
|
-
"COINIT_MULTITHREADED", "COINIT_SPEED_OVER_MEMORY", "CoInitialize",
|
|
1218
|
-
"CoInitializeEx", "COMError", "COMMETHOD", "COMObject", "_COSERVERINFO",
|
|
1219
|
-
"COSERVERINFO", "CoUninitialize", "dispid", "DISPMETHOD", "DISPPROPERTY",
|
|
1220
|
-
"DWORD", "EOAC_NONE", "GetActiveObject", "_GUID", "GUID", "helpstring",
|
|
1221
|
-
"IID", "IPersist", "IServiceProvider", "IUnknown", "MULTI_QI",
|
|
1222
|
-
"ReturnHRESULT", "RPC_C_AUTHN_LEVEL_CONNECT", "RPC_C_AUTHN_WINNT",
|
|
1223
|
-
"RPC_C_AUTHZ_NONE", "RPC_C_IMP_LEVEL_IMPERSONATE",
|
|
1224
|
-
"_SEC_WINNT_AUTH_IDENTITY", "SEC_WINNT_AUTH_IDENTITY",
|
|
1225
|
-
"SEC_WINNT_AUTH_IDENTITY_UNICODE", "_SOLE_AUTHENTICATION_INFO",
|
|
1226
|
-
"SOLE_AUTHENTICATION_INFO", "_SOLE_AUTHENTICATION_LIST",
|
|
1227
|
-
"SOLE_AUTHENTICATION_LIST", "STDMETHOD", "wireHWND",
|
|
1228
|
-
]
|
|
1229
|
-
# fmt: on
|