[ctypes-commit] ctypes/comtypes logutil.py,NONE,1.1.2.1 git.py,NONE,1.1.2.1 errorinfo.py,NONE,1.1.2.
Brought to you by:
theller
From: Thomas H. <th...@us...> - 2006-01-02 19:11:34
|
Update of /cvsroot/ctypes/ctypes/comtypes In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4656 Modified Files: Tag: branch_1_0 typeinfo.py safearray.py persist.py hresult.py connectionpoints.py automation.py _comobject.py __init__.py GUID.py Added Files: Tag: branch_1_0 logutil.py git.py errorinfo.py Log Message: Sync with upstream version. --- NEW FILE: logutil.py --- # logutil.py import logging, ctypes class NTDebugHandler(logging.Handler): def emit(self, record, writeA=ctypes.windll.kernel32.OutputDebugStringA, writeW=ctypes.windll.kernel32.OutputDebugStringW): text = self.format(record) if isinstance(text, str): writeA(text + "\n") else: writeW(text + u"\n") logging.NTDebugHandler = NTDebugHandler def setup_logging(*pathnames): import ConfigParser parser = ConfigParser.ConfigParser() parser.optionxform = str # use case sensitive option names! parser.read(pathnames) DEFAULTS = {"handler": "StreamHandler()", "format": "%(levelname)s:%(name)s:%(message)s", "level": "WARNING"} def get(section, option): try: return parser.get(section, option, True) except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): return DEFAULTS[option] levelname = get("logging", "level") format = get("logging", "format") handlerclass = get("logging", "handler") # convert level name to level value level = getattr(logging, levelname) # create the handler instance handler = eval(handlerclass, vars(logging)) formatter = logging.Formatter(format) handler.setFormatter(formatter) logging.root.addHandler(handler) logging.root.setLevel(level) try: for name, value in parser.items("logging.levels", True): value = getattr(logging, value) logging.getLogger(name).setLevel(value) except ConfigParser.NoSectionError: pass Index: hresult.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/comtypes/Attic/hresult.py,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -C2 -d -r1.1.2.1 -r1.1.2.2 *** hresult.py 23 Aug 2005 19:40:24 -0000 1.1.2.1 --- hresult.py 2 Jan 2006 19:11:25 -0000 1.1.2.2 *************** *** 18,23 **** CLASS_E_CLASSNOTAVAILABLE = -2147221231 #0x80040111L - TYPE_E_ELEMENTNOTFOUND = -2147352077 #0x8002802BL - CO_E_CLASSSTRING = -2147221005 #0x800401F3L --- 18,21 ---- *************** *** 27,29 **** CONNECT_E_NOCONNECTION = -2147220992 ! # DISP_E_... constants are in comtypes.automation --- 25,50 ---- CONNECT_E_NOCONNECTION = -2147220992 ! TYPE_E_ELEMENTNOTFOUND = -2147352077 #0x8002802BL ! ! TYPE_E_REGISTRYACCESS = -2147319780 #0x8002801CL ! TYPE_E_CANTLOADLIBRARY = -2147312566 #0x80029C4AL ! ! # all the DISP_E_ values from windows.h ! DISP_E_BUFFERTOOSMALL = -2147352557 ! DISP_E_DIVBYZERO = -2147352558 ! DISP_E_NOTACOLLECTION = -2147352559 ! DISP_E_BADCALLEE = -2147352560 ! DISP_E_PARAMNOTOPTIONAL = -2147352561 ! DISP_E_BADPARAMCOUNT = -2147352562 ! DISP_E_ARRAYISLOCKED = -2147352563 ! DISP_E_UNKNOWNLCID = -2147352564 ! DISP_E_BADINDEX = -2147352565 ! DISP_E_OVERFLOW = -2147352566 ! DISP_E_EXCEPTION = -2147352567 ! DISP_E_BADVARTYPE = -2147352568 ! DISP_E_NONAMEDARGS = -2147352569 ! DISP_E_UNKNOWNNAME = -2147352570 ! DISP_E_TYPEMISMATCH = -2147352571 ! DISP_E_PARAMNOTFOUND = -2147352572 ! DISP_E_MEMBERNOTFOUND = -2147352573 ! DISP_E_UNKNOWNINTERFACE = -2147352575 Index: GUID.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/comtypes/GUID.py,v retrieving revision 1.6.2.5 retrieving revision 1.6.2.6 diff -C2 -d -r1.6.2.5 -r1.6.2.6 *** GUID.py 29 Sep 2005 13:11:16 -0000 1.6.2.5 --- GUID.py 2 Jan 2006 19:11:25 -0000 1.6.2.6 *************** *** 12,18 **** _CLSIDFromString = _ole32.CLSIDFromString _CLSIDFromProgID = _ole32.CLSIDFromProgID - _IsEqualGUID = _ole32.IsEqualGUID _CoCreateGuid = _ole32.CoCreateGuid class GUID(Structure): _fields_ = [("Data1", DWORD), --- 12,20 ---- _CLSIDFromString = _ole32.CLSIDFromString _CLSIDFromProgID = _ole32.CLSIDFromProgID _CoCreateGuid = _ole32.CoCreateGuid + # Note: Comparing GUID instances by comparing their buffers + # is slightly faster than using ole32.IsEqualGUID. + class GUID(Structure): _fields_ = [("Data1", DWORD), *************** *** 25,34 **** _CLSIDFromString(unicode(name), byref(self)) - def hashcode(self): - # hashcode returns a hashable object that uniquely identifies - # the GUID. GUID instances itself are unhashable because they - # are mutable. - return unicode(self) - def __repr__(self): return u'GUID("%s")' % unicode(self) --- 27,30 ---- *************** *** 44,48 **** def __cmp__(self, other): if isinstance(other, GUID): ! return not _IsEqualGUID(byref(self), byref(other)) return -1 --- 40,44 ---- def __cmp__(self, other): if isinstance(other, GUID): ! return cmp(buffer(self), buffer(other)) return -1 *************** *** 52,59 **** def __eq__(self, other): return isinstance(other, GUID) and \ ! _IsEqualGUID(byref(self), byref(other)) ! ## def __hash__(self): ! ## return hash(repr(self)) def copy(self): --- 48,56 ---- def __eq__(self, other): return isinstance(other, GUID) and \ ! buffer(self) == buffer(other) ! def __hash__(self): ! # We make GUID instances hashable, although they are mutable. ! return hash(buffer(self)) def copy(self): Index: _comobject.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/comtypes/Attic/_comobject.py,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -C2 -d -r1.1.2.2 -r1.1.2.3 *** _comobject.py 7 Dec 2005 19:41:57 -0000 1.1.2.2 --- _comobject.py 2 Jan 2006 19:11:25 -0000 1.1.2.3 *************** *** 3,6 **** --- 3,9 ---- import logging + logger = logging.getLogger(__name__) + _debug = logger.debug + _warning = logger.warning ################################################################ *************** *** 8,14 **** from _ctypes import CopyComPointer - def _not_impl(*args): - return -2147467263 # E_NOTIMPL, 0x80004001L - def prepare_comobject(inst): # When a CoClass instance is created, COM pointers to all --- 11,14 ---- *************** *** 25,37 **** make_interface_pointer(inst, itf) def make_interface_pointer(inst, itf, ! _debug=logging.getLogger("comtypes.impl").debug): methods = [] # method implementations fields = [] # (name, prototype) for virtual function table ! iids = [] # hashcode for interface identifiers. # iterate over interface inheritance in reverse order to build the # virtual function table, and leave out the 'object' base class. for interface in itf.__mro__[-2::-1]: ! iids.append(interface._iid_.hashcode()) for m in interface._methods_: restype, mthname, argtypes, paramflags, idlflags, helptext = m --- 25,56 ---- make_interface_pointer(inst, itf) + from comtypes.errorinfo import ReportException + + def catch_errors(obj, mth, interface): + iid = interface._iid_ + clsid = getattr(obj, "_reg_clsid_", None) + def func(*args, **kw): + try: + return mth(*args, **kw) + except Exception: + _warning("%s", interface, exc_info=True) + return ReportException(E_FAIL, iid, clsid=clsid) + return func + + def _do_implement(interface_name, method_name): + def mth(*args): + _debug("unimplemented method %s_%s called", interface_name, method_name) + return E_NOTIMPL + return mth + def make_interface_pointer(inst, itf, ! _debug=_debug): methods = [] # method implementations fields = [] # (name, prototype) for virtual function table ! iids = [] # interface identifiers. # iterate over interface inheritance in reverse order to build the # virtual function table, and leave out the 'object' base class. for interface in itf.__mro__[-2::-1]: ! iids.append(interface._iid_) for m in interface._methods_: restype, mthname, argtypes, paramflags, idlflags, helptext = m *************** *** 42,48 **** if mth is None: # qualified name, like 'IUnknown_QueryInterface' ! mth = getattr(inst, "%s_%s" % (interface.__name__, mthname), _not_impl) ! if mth is _not_impl: _debug("%r: %s.%s not implemented", inst, interface.__name__, mthname) methods.append(proto(mth)) class Vtbl(Structure): --- 61,71 ---- if mth is None: # qualified name, like 'IUnknown_QueryInterface' ! mth = getattr(inst, "%s_%s" % (interface.__name__, mthname), None) ! if mth is None: ! mth = _do_implement(interface.__name__, mthname) ! # XXX Should we try harder for case-insensitive lookup of methods? _debug("%r: %s.%s not implemented", inst, interface.__name__, mthname) + else: + mth = catch_errors(inst, mth, interface) methods.append(proto(mth)) class Vtbl(Structure): *************** *** 50,55 **** Vtbl.__name__ = "Vtbl_%s" % itf.__name__ vtbl = Vtbl(*methods) ! for hashcode in iids: ! inst._com_pointers_[hashcode] = pointer(pointer(vtbl)) ################################################################ --- 73,78 ---- Vtbl.__name__ = "Vtbl_%s" % itf.__name__ vtbl = Vtbl(*methods) ! for iid in iids: ! inst._com_pointers_[iid] = pointer(pointer(vtbl)) ################################################################ *************** *** 77,82 **** # IUnknown methods implementations def IUnknown_AddRef(self, this, ! _debug=logging.getLogger("comtypes.refcount").debug): ! result = _InterlockedIncrement(byref(self._refcnt)) if result == 1: # keep reference to the object in a class variable. --- 100,106 ---- # IUnknown methods implementations def IUnknown_AddRef(self, this, ! __InterlockedIncrement=_InterlockedIncrement, ! _debug=_debug): ! result = __InterlockedIncrement(byref(self._refcnt)) if result == 1: # keep reference to the object in a class variable. *************** *** 87,102 **** def IUnknown_Release(self, this, ! InterlockedDecrement=_InterlockedDecrement, _byref=byref, ! _debug=logging.getLogger("comtypes.refcount").debug): # If this is called at COM shutdown, byref() and # _InterlockedDecrement() must still be available, although # module level variables may have been deleted already - so we # supply them as default arguments. ! result = InterlockedDecrement(_byref(self._refcnt)) _debug("%r.Release() -> %s", self, result) if result == 0: ! del COMObject._instances_[self] ! _debug("%d active COM objects: Removed %r", len(COMObject._instances_), self) if self._factory is not None: self._factory.LockServer(None, 0) --- 111,132 ---- def IUnknown_Release(self, this, ! __InterlockedDecrement=_InterlockedDecrement, _byref=byref, ! _debug=_debug): # If this is called at COM shutdown, byref() and # _InterlockedDecrement() must still be available, although # module level variables may have been deleted already - so we # supply them as default arguments. ! result = __InterlockedDecrement(_byref(self._refcnt)) _debug("%r.Release() -> %s", self, result) if result == 0: ! # For whatever reasons, at cleanup it may be that ! # COMObject is already cleaned (set to None) ! try: ! del COMObject._instances_[self] ! except AttributeError: ! _debug("? active COM objects: Removed %r", self) ! else: ! _debug("%d active COM objects: Removed %r", len(COMObject._instances_), self) if self._factory is not None: self._factory.LockServer(None, 0) *************** *** 104,110 **** def IUnknown_QueryInterface(self, this, riid, ppvObj, ! _debug=logging.getLogger("comtypes.QueryInterface").debug): iid = riid[0] ! ptr = self._com_pointers_.get(iid.hashcode(), None) if ptr is not None: # CopyComPointer(src, dst) calls AddRef! --- 134,142 ---- def IUnknown_QueryInterface(self, this, riid, ppvObj, ! _debug=_debug): ! # XXX This is probably too slow. ! # riid[0].hashcode() alone takes 33 us! iid = riid[0] ! ptr = self._com_pointers_.get(iid, None) if ptr is not None: # CopyComPointer(src, dst) calls AddRef! *************** *** 114,116 **** --- 146,155 ---- return E_NOINTERFACE + ################################################################ + # ISupportErrorInfo method implementation + def ISupportErrorInfo_InterfaceSupportsErrorInfo(self, this, riid): + if riid[0] in self._com_pointers_: + return S_OK + return S_FALSE + __all__ = ["COMObject"] Index: automation.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/comtypes/automation.py,v retrieving revision 1.12.2.16 retrieving revision 1.12.2.17 diff -C2 -d -r1.12.2.16 -r1.12.2.17 *** automation.py 29 Sep 2005 12:48:17 -0000 1.12.2.16 --- automation.py 2 Jan 2006 19:11:25 -0000 1.12.2.17 *************** *** 2,6 **** from ctypes import * from _ctypes import CopyComPointer ! from comtypes import IUnknown, GUID, IID, STDMETHOD, BSTR, COMMETHOD, dispid, COMError import datetime # for VT_DATE, standard in Python 2.3 and up import array --- 2,7 ---- from ctypes import * from _ctypes import CopyComPointer ! from comtypes import IUnknown, GUID, IID, STDMETHOD, BSTR, COMMETHOD, COMError ! from comtypes.hresult import * import datetime # for VT_DATE, standard in Python 2.3 and up import array *************** *** 219,230 **** elif isinstance(value, (list, tuple)): from comtypes.safearray import SafeArray_FromSequence ! self._.c_void_p = SafeArray_FromSequence(value) self.vt = VT_ARRAY | VT_VARIANT elif isinstance(value, array.array): from comtypes.safearray import SafeArray_FromArray ! typecode, self._.c_void_p = SafeArray_FromArray(value) self.vt = VT_ARRAY | typecode else: ! raise "NYI", value # buffer -> SAFEARRAY of VT_UI1 ? --- 220,232 ---- elif isinstance(value, (list, tuple)): from comtypes.safearray import SafeArray_FromSequence ! self._.c_void_p = cast(SafeArray_FromSequence(value), c_void_p) self.vt = VT_ARRAY | VT_VARIANT elif isinstance(value, array.array): from comtypes.safearray import SafeArray_FromArray ! typecode, psa = SafeArray_FromArray(value) ! self._.c_void_p = cast(psa, c_void_p) self.vt = VT_ARRAY | typecode else: ! raise "VARIANT _set_value, NYI", value # buffer -> SAFEARRAY of VT_UI1 ? *************** *** 273,280 **** # from the __repr__ of it. return None # XXX? ! ptr = cast(val, POINTER(IUnknown)).__ctypes_from_outparam__() # cast doesn't call AddRef (it should, imo!) ptr.AddRef() ! return ptr elif vt == VT_DISPATCH: val = self._.c_void_p --- 275,282 ---- # from the __repr__ of it. return None # XXX? ! ptr = cast(val, POINTER(IUnknown)) # cast doesn't call AddRef (it should, imo!) ptr.AddRef() ! return ptr.__ctypes_from_outparam__() elif vt == VT_DISPATCH: val = self._.c_void_p *************** *** 282,289 **** # See above. return None # XXX? ! ptr = cast(val, POINTER(IDispatch)).__ctypes_from_outparam__() # cast doesn't call AddRef (it should, imo!) ptr.AddRef() ! return ptr # see also c:/sf/pywin32/com/win32com/src/oleargs.cpp elif vt == VT_BYREF|VT_VARIANT: --- 284,291 ---- # See above. return None # XXX? ! ptr = cast(val, POINTER(IDispatch)) # cast doesn't call AddRef (it should, imo!) ptr.AddRef() ! return ptr.__ctypes_from_outparam__() # see also c:/sf/pywin32/com/win32com/src/oleargs.cpp elif vt == VT_BYREF|VT_VARIANT: *************** *** 330,334 **** def __ctypes_from_outparam__(self): ! return self.value VARIANT = tagVARIANT --- 332,345 ---- def __ctypes_from_outparam__(self): ! # XXX Manual resource management, because of the VARIANT bug: ! result = self.value ! self.value = None ! return result ! ! def ChangeType(self, typecode): ! oledll.oleaut32.VariantChangeType(byref(self), ! byref(self), ! 0, ! typecode) VARIANT = tagVARIANT *************** *** 381,394 **** def next(self): ! var = VARIANT() ! fetched = self.Next(1, byref(var)) if fetched: ! result = var.value ! # XXX workaround for a bug in VARIANT.__del__ ! var.value = None ! return result raise StopIteration def __getitem__(self, index): var = VARIANT() self.Reset() --- 392,405 ---- def next(self): ! item, fetched = self.Next(1) if fetched: ! # XXX This should read 'return item[0]', since Next() ! # always returns a pointer to an array. ! # Oder wie oder was... ! return item raise StopIteration def __getitem__(self, index): + # XXX Simplify me!!! var = VARIANT() self.Reset() *************** *** 399,412 **** raise IndexError, index - from comtypes.automation import VARIANT IEnumVARIANT._methods_ = [ ! COMMETHOD([dispid(1610678272)], HRESULT, 'Next', ( ['in'], c_ulong, 'celt' ), ! ( ['in'], POINTER(VARIANT), 'rgvar' ), ( ['out'], POINTER(c_ulong), 'pceltFetched' )), ! COMMETHOD([dispid(1610678273)], HRESULT, 'Skip', ( ['in'], c_ulong, 'celt' )), ! COMMETHOD([dispid(1610678274)], HRESULT, 'Reset'), ! COMMETHOD([dispid(1610678275)], HRESULT, 'Clone', ( ['out'], POINTER(POINTER(IEnumVARIANT)), 'ppenum' )), ] --- 410,422 ---- raise IndexError, index IEnumVARIANT._methods_ = [ ! COMMETHOD([], HRESULT, 'Next', ( ['in'], c_ulong, 'celt' ), ! ( ['out'], POINTER(VARIANT), 'rgvar' ), ( ['out'], POINTER(c_ulong), 'pceltFetched' )), ! COMMETHOD([], HRESULT, 'Skip', ( ['in'], c_ulong, 'celt' )), ! COMMETHOD([], HRESULT, 'Reset'), ! COMMETHOD([], HRESULT, 'Clone', ( ['out'], POINTER(POINTER(IEnumVARIANT)), 'ppenum' )), ] *************** *** 518,533 **** argerr = c_uint() ! if _invkind == DISPATCH_METHOD: ! array = (VARIANT * len(args))() ! ! for i, a in enumerate(args[::-1]): ! array[i].value = a ! dp = DISPPARAMS() ! dp.cArgs = len(args) ! dp.cNamedArgs = 0 ! dp.rgvarg = array ! ! elif _invkind == DISPATCH_PROPERTYGET: array = (VARIANT * len(args))() --- 528,539 ---- argerr = c_uint() ! if _invkind == DISPATCH_PROPERTYPUT: # propput ! assert len(args) == 1 dp = DISPPARAMS() ! dp.cArgs = 1 ! dp.cNamedArgs = 1 ! dp.rgvarg = pointer(VARIANT(args[0])) ! dp.rgdispidNamedArgs = pointer(DISPID(DISPID_PROPERTYPUT)) ! else: array = (VARIANT * len(args))() *************** *** 539,550 **** dp.cNamedArgs = 0 dp.rgvarg = array - - elif _invkind == DISPATCH_PROPERTYPUT: # propput - assert len(args) == 1 - dp = DISPPARAMS() - dp.cArgs = 1 - dp.cNamedArgs = 1 - dp.rgvarg = pointer(VARIANT(args[0])) - dp.rgdispidNamedArgs = pointer(DISPID(DISPID_PROPERTYPUT)) try: --- 545,548 ---- *************** *** 578,600 **** # XXX Would separate methods for _METHOD, _PROPERTYGET and _PROPERTYPUT be better? - # all the DISP_E_ values from windows.h - DISP_E_BUFFERTOOSMALL = -2147352557 - DISP_E_DIVBYZERO = -2147352558 - DISP_E_NOTACOLLECTION = -2147352559 - DISP_E_BADCALLEE = -2147352560 - DISP_E_PARAMNOTOPTIONAL = -2147352561 - DISP_E_BADPARAMCOUNT = -2147352562 - DISP_E_ARRAYISLOCKED = -2147352563 - DISP_E_UNKNOWNLCID = -2147352564 - DISP_E_BADINDEX = -2147352565 - DISP_E_OVERFLOW = -2147352566 - DISP_E_EXCEPTION = -2147352567 - DISP_E_BADVARTYPE = -2147352568 - DISP_E_NONAMEDARGS = -2147352569 - DISP_E_UNKNOWNNAME = -2147352570 - DISP_E_TYPEMISMATCH = -2147352571 - DISP_E_PARAMNOTFOUND = -2147352572 - DISP_E_MEMBERNOTFOUND = -2147352573 - DISP_E_UNKNOWNINTERFACE = -2147352575 VT2CTYPE = { --- 576,579 ---- Index: __init__.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/comtypes/__init__.py,v retrieving revision 1.25.2.36 retrieving revision 1.25.2.37 diff -C2 -d -r1.25.2.36 -r1.25.2.37 *** __init__.py 8 Nov 2005 20:42:09 -0000 1.25.2.36 --- __init__.py 2 Jan 2006 19:11:25 -0000 1.25.2.37 *************** *** 1,3 **** ! # requires ctypes 0.9.9.0 or later import new ##import warnings --- 1,3 ---- ! # requires ctypes 0.9.8 or later import new ##import warnings *************** *** 6,22 **** from ctypes import * - from ctypes import __version__ as _ctypes_version from _ctypes import COMError - __version__ = "0.1.1" - - _ctypes_required = "0.9.9.0" - - if _ctypes_version.split(".") < _ctypes_required.split("."): - raise ImportError("requires ctypes %s or later, not %s" % (_ctypes_required, _ctypes_version)) - import logging ! logger = logging.getLogger("comtypes") ! ##class IDLWarning(UserWarning): --- 6,13 ---- from ctypes import * from _ctypes import COMError import logging ! logger = logging.getLogger(__name__) ##class IDLWarning(UserWarning): *************** *** 28,31 **** --- 19,24 ---- DWORD = c_ulong + wireHWND = c_ulong + from comtypes.hresult import E_NOINTERFACE *************** *** 77,100 **** COINIT_SPEED_OVER_MEMORY = 0x8 ! _ole32.CoInitializeEx(None, getattr(sys, "coinit_flags", COINIT_APARTMENTTHREADED)) ! class _Cleaner(object): ! def __del__(self, func=_ole32.CoUninitialize): ! # Sometimes, CoUnititialize, running at Python shutdown, ! # raises an exception. We suppress this when __debug__ is ! # False. ! if __debug__: ! func() else: ! try: func() ! except WindowsError: pass ! __cleaner = _Cleaner() ! del _Cleaner ! # Make sure no COM pointers stay in exception frames at first step of ! # shutdown. ! import atexit ! atexit.register(sys.exc_clear) ################################################################ --- 70,120 ---- COINIT_SPEED_OVER_MEMORY = 0x8 ! def CoInitialize(): ! return CoInitializeEx(COINIT_APARTMENTTHREADED) ! # Yet another try at COM shutdown. ! ! # XXX Does currently not support multiple appartments, ! # because it relies on global, thread-shared data. ! def CoInitializeEx(flags=None): ! global __inited ! if __inited: ! return ! if flags is None: ! flags = getattr(sys, "coinit_flags", COINIT_APARTMENTTHREADED) ! __inited = True ! logger.debug("CoInitializeEx(None, %s)", flags) ! try: ! _ole32.CoInitializeEx(None, flags) ! except WindowsError, details: ! if details.errno != -2147417850: ! logger.debug("CoInitializeEx(): WindowsError, %s", details) ! raise else: ! logger.debug("CoInitializeEx(): RPC_CHANGED_MODE ignored") ! else: ! def shutdown(func=_ole32.CoUninitialize, ! _debug=logger.debug): ! # Make sure no COM pointers stay in exception frames. ! sys.exc_clear() ! # Sometimes, CoUnititialize, running at Python shutdown, ! # raises an exception. We suppress this when __debug__ is ! # False. ! _debug("Calling CoUnititialize()") ! if __debug__: ! func() ! else: ! try: func() ! except WindowsError: pass ! global __inited ! __inited = False ! _debug("CoUnititialize() done.") ! import atexit ! atexit.register(shutdown) ! __inited = False ! ! CoInitializeEx() ################################################################ *************** *** 165,184 **** try: # a kind of QueryInterface ! return table[str(klass._iid_)] except KeyError: raise TypeError("Interface %s not supported" % klass._iid_) return value.QueryInterface(cls) ! def __ctypes_from_outparam__(self): ! return self # The interface 'cls' is used as a mixin. p = type(_compointer_base)("POINTER(%s)" % cls.__name__, _ptr_bases, ! {"__ctypes_from_outparam__": __ctypes_from_outparam__, ! "from_param": classmethod(from_param), ! "__com_interface__": cls}) from ctypes import _pointer_type_cache _pointer_type_cache[cls] = p return cls --- 185,256 ---- try: # a kind of QueryInterface ! return table[klass._iid_] except KeyError: raise TypeError("Interface %s not supported" % klass._iid_) return value.QueryInterface(cls) ! # case insensitive attributes for COM methods and properties ! def __getattr__(self, name): ! try: ! name = self.__map_case__[name.lower()] ! except KeyError: ! raise AttributeError(name) ! else: ! return getattr(self, name) ! ! # XXX __setattr__ is pretty heavy-weight, because it is called for ! # EVERY attribute assignment. Settings a non-com attribute ! # through this function takes 8.6 usec, while without this ! # function it takes 0.7 sec - 12 times slower. Maybe there should ! # be a way to enable this method only for code that needs it ! # (i.e., generated from a typelib)? ! # ! # Maybe triggered by a special attribute __case_insensitive__ ? ! # ! # How much faster would this be if implemented in C? ! def __setattr__(self, name, value): ! object.__setattr__(self, ! self.__map_case__.get(name.lower(), name), ! value) ! ! namespace = {"from_param": classmethod(from_param), ! "__com_interface__": cls, ! "_needs_com_addref_": None} ! ! CASE_INSENSITIVE = getattr(cls, "_case_insensitive_", False) ! ! if CASE_INSENSITIVE: ! namespace["__setattr__"] = __setattr__ ! namespace["__getattr__"] = __getattr__ # The interface 'cls' is used as a mixin. p = type(_compointer_base)("POINTER(%s)" % cls.__name__, _ptr_bases, ! namespace) from ctypes import _pointer_type_cache _pointer_type_cache[cls] = p + + # XXX These changes break something, unfortunately. + # XXX Find out what! + ## # This looks more and more weird. We override the + ## # __setitem__ method of the POINTER(POINTER(interface)) type. + ## # + ## # This is so that we can implement COM methods that have to + ## # return COM pointers more easily and consistent. Instead of + ## # using CopyComPointer in the method implementation, we can + ## # simply do: + ## # + ## # def GetTypeInfo(self, this, ..., pptinfo): + ## # if not pptinfo: return E_POINTER + ## # pptinfo[0] = a_com_interface_pointer + ## # return S_OK + + ## from _ctypes import CopyComPointer + ## def ppi_setitem(self, index, value): + ## if index != 0: + ## raise IndexError("Invalid index %s, must be 0" % index) + ## CopyComPointer(value, self) + ## POINTER(p).__setitem__ = ppi_setitem + return cls *************** *** 433,438 **** def __del__(self): "Release the COM refcount we own." ! if self: # calls __nonzero__ ! self.Release() def __cmp__(self, other): --- 505,520 ---- def __del__(self): "Release the COM refcount we own." ! if self: ! # XXX comtypes now calls CoUnititialize() when the atexit ! # handlers run. OTOH, the __main__ namespace (and maybe ! # others) may still have instances of com pointers around. ! # CoUnititialize() has finalized them when it returns, so ! # these com pointers are stale. Catching the WindowsError ! # here gets rid of error messages during shutting of Python. ! try: ! self.Release() ! except WindowsError: ! if __inited: ! raise def __cmp__(self, other): *************** *** 462,488 **** def __repr__(self): ! return "<%s instance at %x>" % (self.__class__.__name__, id(self)) ! ! # case insensitive attributes for COM methods and properties ! def __getattr__(self, name): ! try: ! name = self.__map_case__[name.lower()] ! except KeyError: ! raise AttributeError(name) ! else: ! return getattr(self, name) ! ! # XXX __setattr__ is pretty heavy-weight, because it is called for ! # EVERY attribute assignment. Settings a non-com attribute ! # through this function takes 8.6 usec, while without this ! # function it takes 0.7 sec - 12 times slower. Maybe there should ! # be a way to enable this method only for code that needs it ! # (i.e., generated from a typelib)? ! # ! # Maybe triggered by a special attribute __case_insensitive__ ? ! def __setattr__(self, name, value): ! object.__setattr__(self, ! self.__map_case__.get(name.lower(), name), ! value) ################################################################ --- 544,548 ---- def __repr__(self): ! return "<%s object %x>" % (self.__class__.__name__, id(self)) ################################################################ Index: persist.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/comtypes/Attic/persist.py,v retrieving revision 1.1.2.3 retrieving revision 1.1.2.4 diff -C2 -d -r1.1.2.3 -r1.1.2.4 *** persist.py 20 Oct 2005 17:13:42 -0000 1.1.2.3 --- persist.py 2 Jan 2006 19:11:25 -0000 1.1.2.4 *************** *** 1,2 **** --- 1,14 ---- + """This module defines the following interfaces: + + IErrorLog + IPersist + IPropertyBag + IPersistPropertyBag + IPropertyBag2 + IPersistPropertyBag2 + + The 'DictPropertyBag' class is a class implementing the IPropertyBag + interface, useful in client code. + """ from ctypes import * from comtypes import GUID, IUnknown, COMMETHOD, HRESULT, dispid *************** *** 4,8 **** # XXX Replace by canonical solution!!! ! POINTER_c_wchar = c_wchar_p class IErrorLog(IUnknown): --- 16,20 ---- # XXX Replace by canonical solution!!! ! WSTRING = c_wchar_p class IErrorLog(IUnknown): *************** *** 11,15 **** _methods_ = [ COMMETHOD([], HRESULT, 'AddError', ! ( ['in'], POINTER_c_wchar, 'pszPropName' ), ( ['in'], POINTER(tagEXCEPINFO), 'pExcepInfo' )), ] --- 23,27 ---- _methods_ = [ COMMETHOD([], HRESULT, 'AddError', ! ( ['in'], WSTRING, 'pszPropName' ), ( ['in'], POINTER(tagEXCEPINFO), 'pExcepInfo' )), ] *************** *** 27,36 **** _idlflags_ = [] _methods_ = [ COMMETHOD([], HRESULT, 'Read', ! ( ['in'], POINTER_c_wchar, 'pszPropName' ), ! ( ['out'], POINTER(VARIANT), 'pVar' ), ( ['in'], POINTER(IErrorLog), 'pErrorLog' )), COMMETHOD([], HRESULT, 'Write', ! ( ['in'], POINTER_c_wchar, 'pszPropName' ), ( ['in'], POINTER(VARIANT), 'pVar' )), ] --- 39,53 ---- _idlflags_ = [] _methods_ = [ + # XXX Note: According to MSDN, pVar and pErrorLog are ['in', 'out'] parameters. + # + # XXX ctypes does NOT yet accept POINTER(IErrorLog) as 'out' parameter: + # TypeError: 'out' parameter 3 must be a pointer type, not POINTER(IErrorLog) COMMETHOD([], HRESULT, 'Read', ! ( ['in'], WSTRING, 'pszPropName' ), ! ( ['in', 'out'], POINTER(VARIANT), 'pVar' ), ( ['in'], POINTER(IErrorLog), 'pErrorLog' )), + ## ( ['in', 'out'], POINTER(IErrorLog), 'pErrorLog' )), COMMETHOD([], HRESULT, 'Write', ! ( ['in'], WSTRING, 'pszPropName' ), ( ['in'], POINTER(VARIANT), 'pVar' )), ] *************** *** 67,71 **** ('cfType', CLIPFORMAT), ('dwHint', c_ulong), ! ('pstrName', POINTER_c_wchar), ('clsid', GUID), ] --- 84,88 ---- ('cfType', CLIPFORMAT), ('dwHint', c_ulong), ! ('pstrName', WSTRING), ('clsid', GUID), ] *************** *** 95,99 **** ( ['out'], POINTER(c_ulong), 'pcProperties' )), COMMETHOD([], HRESULT, 'LoadObject', ! ( ['in'], POINTER_c_wchar, 'pstrName' ), ( ['in'], c_ulong, 'dwHint' ), ( ['in'], POINTER(IUnknown), 'punkObject' ), --- 112,116 ---- ( ['out'], POINTER(c_ulong), 'pcProperties' )), COMMETHOD([], HRESULT, 'LoadObject', ! ( ['in'], WSTRING, 'pstrName' ), ( ['in'], c_ulong, 'dwHint' ), ( ['in'], POINTER(IUnknown), 'punkObject' ), *************** *** 116,117 **** --- 133,169 ---- ] + + from comtypes import COMObject + from comtypes.hresult import * + class DictPropertyBag(COMObject): + """An object implementing the IProperty interface on a dictionary. + + Pass named values in the constructor for the client to Read(), or + retrieve from the .values instance variable after the client has + called Load(). + """ + _com_interfaces_ = [IPropertyBag] + + def __init__(self, **kw): + super(DictPropertyBag, self).__init__() + self.values = kw + + def Read(self, this, name, pVar, errorlog): + try: + val = self.values[name] + except KeyError: + return E_INVALIDARG + # The caller did provide info about the type that is expected + # with the pVar[0].vt typecode, except when this is VT_EMPTY. + var = pVar[0] + typecode = var.vt + var.value = val + if typecode: + var.ChangeType(typecode) + return S_OK + + def Write(self, this, name, var): + val = var[0].value + self.values[name] = val + return S_OK + --- NEW FILE: git.py --- """comtypes.git - access the process wide global interface table The global interface table provides a way to marshal interface pointers between different threading appartments. """ from ctypes import * from comtypes import IUnknown, STDMETHOD, COMMETHOD, \ GUID, HRESULT, CoCreateInstance, CLSCTX_INPROC_SERVER DWORD = c_ulong class IGlobalInterfaceTable(IUnknown): _iid_ = GUID("{00000146-0000-0000-C000-000000000046}") _methods_ = [ STDMETHOD(HRESULT, "RegisterInterfaceInGlobal", [POINTER(IUnknown), POINTER(GUID), POINTER(DWORD)]), STDMETHOD(HRESULT, "RevokeInterfaceFromGlobal", [DWORD]), STDMETHOD(HRESULT, "GetInterfaceFromGlobal", [DWORD, POINTER(GUID), POINTER(POINTER(IUnknown))]), ] def RegisterInterfaceInGlobal(self, obj): cookie = DWORD() self.__com_RegisterInterfaceInGlobal(obj, obj._iid_, cookie) return cookie.value def GetInterfaceFromGlobal(self, cookie, interface=IUnknown): ptr = POINTER(interface)() self.__com_GetInterfaceFromGlobal(cookie, interface._iid_, ptr) return ptr def RevokeInterfaceFromGlobal(self, cookie): self.__com_RevokeInterfaceFromGlobal(cookie) # It was a pain to get this CLSID: it's neither in the registry, nor # in any header files. I had to compile a C program, and find it out # with the debugger. Apparently it is in uuid.lib. CLSID_StdGlobalInterfaceTable = GUID("{00000323-0000-0000-C000-000000000046}") git = CoCreateInstance(CLSID_StdGlobalInterfaceTable, interface=IGlobalInterfaceTable, clsctx=CLSCTX_INPROC_SERVER) RevokeInterfaceFromGlobal = git.RevokeInterfaceFromGlobal RegisterInterfaceInGlobal = git.RegisterInterfaceInGlobal GetInterfaceFromGlobal = git.GetInterfaceFromGlobal __all__ = ["RegisterInterfaceInGlobal", "RevokeInterfaceFromGlobal", "GetInterfaceFromGlobal"] if __name__ == "__main__": from comtypes.typeinfo import CreateTypeLib, ICreateTypeLib tlib = CreateTypeLib("foo.bar") # we don not save it later assert (tlib.AddRef(), tlib.Release()) == (2, 1) cookie = RegisterInterfaceInGlobal(tlib) assert (tlib.AddRef(), tlib.Release()) == (3, 2) GetInterfaceFromGlobal(cookie, ICreateTypeLib) GetInterfaceFromGlobal(cookie, ICreateTypeLib) GetInterfaceFromGlobal(cookie) assert (tlib.AddRef(), tlib.Release()) == (3, 2) RevokeInterfaceFromGlobal(cookie) assert (tlib.AddRef(), tlib.Release()) == (2, 1) Index: safearray.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/comtypes/Attic/safearray.py,v retrieving revision 1.1.2.4 retrieving revision 1.1.2.5 diff -C2 -d -r1.1.2.4 -r1.1.2.5 *** safearray.py 18 Aug 2005 14:42:04 -0000 1.1.2.4 --- safearray.py 2 Jan 2006 19:11:25 -0000 1.1.2.5 *************** *** 44,52 **** # BTW: A C program has the same behaviour. def SafeArray_FromSequence(seq): """Create a one dimensional safearray of type VT_VARIANT from a sequence of Python objects """ ! psa = oledll.oleaut32.SafeArrayCreateVectorEx(VT_VARIANT, 0, len(seq), None) for index, elem in enumerate(seq): oledll.oleaut32.SafeArrayPutElement(psa, byref(c_long(index)), byref(VARIANT(elem))) --- 44,54 ---- # BTW: A C program has the same behaviour. + windll.oleaut32.SafeArrayCreateVectorEx.restype = POINTER(SAFEARRAY) + def SafeArray_FromSequence(seq): """Create a one dimensional safearray of type VT_VARIANT from a sequence of Python objects """ ! psa = windll.oleaut32.SafeArrayCreateVectorEx(VT_VARIANT, 0, len(seq), None) for index, elem in enumerate(seq): oledll.oleaut32.SafeArrayPutElement(psa, byref(c_long(index)), byref(VARIANT(elem))) Index: typeinfo.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/comtypes/typeinfo.py,v retrieving revision 1.3.2.9 retrieving revision 1.3.2.10 diff -C2 -d -r1.3.2.9 -r1.3.2.10 *** typeinfo.py 19 Aug 2005 18:51:26 -0000 1.3.2.9 --- typeinfo.py 2 Jan 2006 19:11:25 -0000 1.3.2.10 *************** *** 376,380 **** "Load a registered type library" tlib = POINTER(ITypeLib)() ! LoadRegTypeLib._api_(byref(guid), wVerMajor, wVerMinor, lcid, byref(tlib)) return tlib LoadRegTypeLib = stdcall(HRESULT, 'oleaut32', --- 376,380 ---- "Load a registered type library" tlib = POINTER(ITypeLib)() ! LoadRegTypeLib._api_(byref(GUID(guid)), wVerMajor, wVerMinor, lcid, byref(tlib)) return tlib LoadRegTypeLib = stdcall(HRESULT, 'oleaut32', *************** *** 397,401 **** def UnRegisterTypeLib(libID, wVerMajor, wVerMinor, lcid=0, syskind=SYS_WIN32): "Unregister a registered type library" ! return UnRegisterTypeLib._api_(byref(libID), wVerMajor, wVerMinor, lcid, syskind) UnRegisterTypeLib = stdcall(HRESULT, 'oleaut32', [POINTER(GUID), c_ushort, c_ushort, c_ulong, tagSYSKIND]) (UnRegisterTypeLib) --- 397,401 ---- def UnRegisterTypeLib(libID, wVerMajor, wVerMinor, lcid=0, syskind=SYS_WIN32): "Unregister a registered type library" ! return UnRegisterTypeLib._api_(byref(GUID(libID)), wVerMajor, wVerMinor, lcid, syskind) UnRegisterTypeLib = stdcall(HRESULT, 'oleaut32', [POINTER(GUID), c_ushort, c_ushort, c_ulong, tagSYSKIND]) (UnRegisterTypeLib) *************** *** 418,422 **** "Return the path of a registered type library" pathname = BSTR() ! QueryPathOfRegTypeLib._api_(byref(libid), wVerMajor, wVerMinor, lcid, byref(pathname)) return pathname.value QueryPathOfRegTypeLib = stdcall(HRESULT, 'oleaut32', --- 418,422 ---- "Return the path of a registered type library" pathname = BSTR() ! QueryPathOfRegTypeLib._api_(byref(GUID(libid)), wVerMajor, wVerMinor, lcid, byref(pathname)) return pathname.value QueryPathOfRegTypeLib = stdcall(HRESULT, 'oleaut32', Index: connectionpoints.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/comtypes/Attic/connectionpoints.py,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -C2 -d -r1.1.2.2 -r1.1.2.3 *** connectionpoints.py 18 Aug 2005 14:42:04 -0000 1.1.2.2 --- connectionpoints.py 2 Jan 2006 19:11:25 -0000 1.1.2.3 *************** *** 49,55 **** IConnectionPointContainer._methods_ = [ ! COMMETHOD([dispid(1610678272)], HRESULT, 'EnumConnectionPoints', ( ['out'], POINTER(POINTER(IEnumConnectionPoints)), 'ppEnum' )), ! COMMETHOD([dispid(1610678273)], HRESULT, 'FindConnectionPoint', ( ['in'], POINTER(_GUID), 'riid' ), ( ['out'], POINTER(POINTER(IConnectionPoint)), 'ppCP' )), --- 49,55 ---- IConnectionPointContainer._methods_ = [ ! COMMETHOD([], HRESULT, 'EnumConnectionPoints', ( ['out'], POINTER(POINTER(IEnumConnectionPoints)), 'ppEnum' )), ! COMMETHOD([], HRESULT, 'FindConnectionPoint', ( ['in'], POINTER(_GUID), 'riid' ), ( ['out'], POINTER(POINTER(IConnectionPoint)), 'ppCP' )), *************** *** 57,94 **** IConnectionPoint._methods_ = [ ! COMMETHOD([dispid(1610678272)], HRESULT, 'GetConnectionInterface', ( ['out'], POINTER(_GUID), 'pIID' )), ! COMMETHOD([dispid(1610678273)], HRESULT, 'GetConnectionPointContainer', ( ['out'], POINTER(POINTER(IConnectionPointContainer)), 'ppCPC' )), ! COMMETHOD([dispid(1610678274)], HRESULT, 'Advise', ( ['in'], POINTER(IUnknown), 'pUnkSink' ), ( ['out'], POINTER(c_ulong), 'pdwCookie' )), ! COMMETHOD([dispid(1610678275)], HRESULT, 'Unadvise', ( ['in'], c_ulong, 'dwCookie' )), ! COMMETHOD([dispid(1610678276)], HRESULT, 'EnumConnections', ( ['out'], POINTER(POINTER(IEnumConnections)), 'ppEnum' )), ] IEnumConnections._methods_ = [ ! COMMETHOD([dispid(1610678272)], HRESULT, 'Next', ( ['in'], c_ulong, 'cConnections' ), ( ['out'], POINTER(tagCONNECTDATA), 'rgcd' ), ( ['out'], POINTER(c_ulong), 'pcFetched' )), ! COMMETHOD([dispid(1610678273)], HRESULT, 'Skip', ( ['in'], c_ulong, 'cConnections' )), ! COMMETHOD([dispid(1610678274)], HRESULT, 'Reset'), ! COMMETHOD([dispid(1610678275)], HRESULT, 'Clone', ( ['out'], POINTER(POINTER(IEnumConnections)), 'ppEnum' )), ] IEnumConnectionPoints._methods_ = [ ! COMMETHOD([dispid(1610678272)], HRESULT, 'Next', ( ['in'], c_ulong, 'cConnections' ), ( ['out'], POINTER(POINTER(IConnectionPoint)), 'ppCP' ), ( ['out'], POINTER(c_ulong), 'pcFetched' )), ! COMMETHOD([dispid(1610678273)], HRESULT, 'Skip', ( ['in'], c_ulong, 'cConnections' )), ! COMMETHOD([dispid(1610678274)], HRESULT, 'Reset'), ! COMMETHOD([dispid(1610678275)], HRESULT, 'Clone', ( ['out'], POINTER(POINTER(IEnumConnectionPoints)), 'ppEnum' )), ] --- 57,94 ---- IConnectionPoint._methods_ = [ ! COMMETHOD([], HRESULT, 'GetConnectionInterface', ( ['out'], POINTER(_GUID), 'pIID' )), ! COMMETHOD([], HRESULT, 'GetConnectionPointContainer', ( ['out'], POINTER(POINTER(IConnectionPointContainer)), 'ppCPC' )), ! COMMETHOD([], HRESULT, 'Advise', ( ['in'], POINTER(IUnknown), 'pUnkSink' ), ( ['out'], POINTER(c_ulong), 'pdwCookie' )), ! COMMETHOD([], HRESULT, 'Unadvise', ( ['in'], c_ulong, 'dwCookie' )), ! COMMETHOD([], HRESULT, 'EnumConnections', ( ['out'], POINTER(POINTER(IEnumConnections)), 'ppEnum' )), ] IEnumConnections._methods_ = [ ! COMMETHOD([], HRESULT, 'Next', ( ['in'], c_ulong, 'cConnections' ), ( ['out'], POINTER(tagCONNECTDATA), 'rgcd' ), ( ['out'], POINTER(c_ulong), 'pcFetched' )), ! COMMETHOD([], HRESULT, 'Skip', ( ['in'], c_ulong, 'cConnections' )), ! COMMETHOD([], HRESULT, 'Reset'), ! COMMETHOD([], HRESULT, 'Clone', ( ['out'], POINTER(POINTER(IEnumConnections)), 'ppEnum' )), ] IEnumConnectionPoints._methods_ = [ ! COMMETHOD([], HRESULT, 'Next', ( ['in'], c_ulong, 'cConnections' ), ( ['out'], POINTER(POINTER(IConnectionPoint)), 'ppCP' ), ( ['out'], POINTER(c_ulong), 'pcFetched' )), ! COMMETHOD([], HRESULT, 'Skip', ( ['in'], c_ulong, 'cConnections' )), ! COMMETHOD([], HRESULT, 'Reset'), ! COMMETHOD([], HRESULT, 'Clone', ( ['out'], POINTER(POINTER(IEnumConnectionPoints)), 'ppEnum' )), ] --- NEW FILE: errorinfo.py --- import sys from ctypes import * from comtypes import IUnknown, HRESULT, COMMETHOD, GUID, BSTR from comtypes.hresult import * LPCOLESTR = c_wchar_p DWORD = c_ulong class ICreateErrorInfo(IUnknown): _iid_ = GUID("{22F03340-547D-101B-8E65-08002B2BD119}") _methods_ = [ COMMETHOD([], HRESULT, 'SetGUID', (['in'], POINTER(GUID), "rguid")), COMMETHOD([], HRESULT, 'SetSource', (['in'], LPCOLESTR, "szSource")), COMMETHOD([], HRESULT, 'SetDescription', (['in'], LPCOLESTR, "szDescription")), COMMETHOD([], HRESULT, 'SetHelpFile', (['in'], LPCOLESTR, "szHelpFile")), COMMETHOD([], HRESULT, 'SetHelpContext', (['in'], DWORD, "dwHelpContext")) ] class IErrorInfo(IUnknown): _iid_ = GUID("{1CF2B120-547D-101B-8E65-08002B2BD119}") _methods_ = [ COMMETHOD([], HRESULT, 'GetGUID', (['out'], POINTER(GUID), "pGUID")), COMMETHOD([], HRESULT, 'GetSource', (['out'], POINTER(BSTR), "pBstrSource")), COMMETHOD([], HRESULT, 'GetDescription', (['out'], POINTER(BSTR), "pBstrDescription")), COMMETHOD([], HRESULT, 'GetHelpFile', (['out'], POINTER(BSTR), "pBstrHelpFile")), COMMETHOD([], HRESULT, 'GetHelpContext', (['out'], POINTER(DWORD), "pdwHelpContext")), ] class ISupportErrorInfo(IUnknown): _iid_ = GUID("{DF0B3D60-548F-101B-8E65-08002B2BD119}") _methods_ = [ COMMETHOD([], HRESULT, 'InterfaceSupportsErrorInfo', (['in'], POINTER(GUID), 'riid')) ] ################################################################ _oleaut32 = oledll.oleaut32 def CreateErrorInfo(): cei = POINTER(ICreateErrorInfo)() _oleaut32.CreateErrorInfo(byref(cei)) return cei def GetErrorInfo(): """Get the error information for the current thread.""" errinfo = POINTER(IErrorInfo)() if S_OK == _oleaut32.GetErrorInfo(0, byref(errinfo)): return errinfo return None def SetErrorInfo(errinfo): """Set error information for the current thread.""" return _oleaut32.SetErrorInfo(0, errinfo) def ReportError(text, iid, clsid=None, helpfile=None, helpcontext=0, hresult=DISP_E_EXCEPTION): """Report a COM error. Returns the passed in hresult value.""" ei = CreateErrorInfo() ei.SetDescription(text) ei.SetGUID(iid) if helpfile is not None: ei.SetHelpFile(helpfile) if helpcontext is not None: ei.SetHelpContext(helpcontext) if clsid is not None: if isinstance(clsid, basestring): clsid = GUID(clsid) try: progid = clsid.as_progid() except WindowsError: pass else: ei.SetSource(progid) # progid for the class or application that created the error _oleaut32.SetErrorInfo(0, ei) return hresult def ReportException(hresult, iid, clsid=None, helpfile=None, helpcontext=None): """Report a COM exception. Returns the passed in hresult value.""" text = u"%s: %s" % sys.exc_info()[:2] return ReportError(text, iid, clsid=clsid, helpfile=helpfile, helpcontext=helpcontext) __all__ = ["ICreateErrorInfo", "IErrorInfo", "ISupportErrorInfo", "ReportError", "ReportException", "SetErrorInfo", "GetErrorInfo", "CreateErrorInfo"] |