Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Poc on fork #38

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 26 additions & 30 deletions comtypes/client/_events.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import ctypes
import logging
import traceback
from ctypes import HRESULT, POINTER, WINFUNCTYPE, OleDLL, Structure, WinDLL
from _ctypes import COMError
from ctypes import HRESULT, POINTER, WINFUNCTYPE, OleDLL, Structure, WinDLL, byref
from ctypes.wintypes import (
BOOL,
DWORD,
Expand All @@ -13,12 +13,13 @@
ULONG,
)

import comtypes
import comtypes.automation
import comtypes.connectionpoints
import comtypes.hresult
import comtypes.typeinfo
from comtypes import com_coclass_registry, com_interface_registry
from comtypes._comobject import COMObject, _MethodFinder
from comtypes._post_coinit.instancemethod import instancemethod
from comtypes.automation import DISPATCH_METHOD, IDispatch
from comtypes.client._generate import GetModule
from comtypes.connectionpoints import IConnectionPointContainer
from comtypes.typeinfo import IProvideClassInfo2

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -66,8 +67,8 @@ def __init__(self, source, interface, receiver):
self._connect(source, interface, receiver)

def _connect(self, source, interface, receiver):
cpc = source.QueryInterface(comtypes.connectionpoints.IConnectionPointContainer)
self.cp = cpc.FindConnectionPoint(ctypes.byref(interface._iid_))
cpc = source.QueryInterface(IConnectionPointContainer)
self.cp = cpc.FindConnectionPoint(byref(interface._iid_))
logger.debug("Start advise %s", interface)
self.cookie = self.cp.Advise(receiver)
self.receiver = receiver
Expand All @@ -84,7 +85,7 @@ def __del__(self):
try:
if self.cookie is not None:
self.cp.Unadvise(self.cookie)
except (comtypes.COMError, WindowsError):
except (COMError, WindowsError):
# Are we sure we want to ignore errors here?
pass

Expand All @@ -94,19 +95,19 @@ def FindOutgoingInterface(source):
# If the COM object implements IProvideClassInfo2, it is easy to
# find the default outgoing interface.
try:
pci = source.QueryInterface(comtypes.typeinfo.IProvideClassInfo2)
pci = source.QueryInterface(IProvideClassInfo2)
guid = pci.GetGUID(1)
except comtypes.COMError:
except COMError:
pass
else:
# another try: block needed?
try:
interface = comtypes.com_interface_registry[str(guid)]
interface = com_interface_registry[str(guid)]
except KeyError:
tinfo = pci.GetClassInfo()
tlib, index = tinfo.GetContainingTypeLib()
GetModule(tlib)
interface = comtypes.com_interface_registry[str(guid)]
interface = com_interface_registry[str(guid)]
logger.debug("%s using sinkinterface %s", source, interface)
return interface

Expand All @@ -115,7 +116,7 @@ def FindOutgoingInterface(source):
# comtypes.client):
clsid = source.__dict__.get("__clsid")
try:
interface = comtypes.com_coclass_registry[clsid]._outgoing_interfaces_[0]
interface = com_coclass_registry[clsid]._outgoing_interfaces_[0]
except KeyError:
pass
else:
Expand All @@ -133,14 +134,14 @@ def find_single_connection_interface(source):
# Enumerate the connection interfaces. If we find a single one,
# return it, if there are more, we give up since we cannot
# determine which one to use.
cpc = source.QueryInterface(comtypes.connectionpoints.IConnectionPointContainer)
cpc = source.QueryInterface(IConnectionPointContainer)
enum = cpc.EnumConnectionPoints()
iid = enum.next().GetConnectionInterface()
try:
next(enum)
except StopIteration:
try:
interface = comtypes.com_interface_registry[str(iid)]
interface = com_interface_registry[str(iid)]
except KeyError:
return None
else:
Expand Down Expand Up @@ -177,9 +178,6 @@ def error_printer(*args, **kw):
return error_printer


from comtypes._comobject import _MethodFinder


class _SinkMethodFinder(_MethodFinder):
"""Special MethodFinder, for finding and decorating event handler
methods. Looks for methods on two objects. Also decorates the
Expand All @@ -202,7 +200,7 @@ def find_method(self, fq_name, mthname):
# decorate it with an error printer...
method = report_errors(im_func)
# and make a new bound method from it again.
return comtypes.instancemethod(method, im_self, type(im_self))
return instancemethod(method, im_self, type(im_self))
except AttributeError as details:
raise RuntimeError(details)

Expand All @@ -217,7 +215,7 @@ def _find_method(self, fq_name, mthname):


def CreateEventReceiver(interface, handler):
class Sink(comtypes.COMObject):
class Sink(COMObject):
_com_interfaces_ = [interface]

def _get_method_finder_(self, itf):
Expand All @@ -229,9 +227,7 @@ def _get_method_finder_(self, itf):

# Since our Sink object doesn't have typeinfo, it needs a
# _dispimpl_ dictionary to dispatch events received via Invoke.
if issubclass(interface, comtypes.automation.IDispatch) and not hasattr(
sink, "_dispimpl_"
):
if issubclass(interface, IDispatch) and not hasattr(sink, "_dispimpl_"):
finder = sink._get_method_finder_(interface)
dispimpl = sink._dispimpl_ = {}
for m in interface._methods_:
Expand All @@ -242,7 +238,7 @@ def _get_method_finder_(self, itf):
impl = finder.get_impl(interface, mthname, paramflags, idlflags)
# XXX Wouldn't work for 'propget', 'propput', 'propputref'
# methods - are they allowed on event interfaces?
dispimpl[(dispid, comtypes.automation.DISPATCH_METHOD)] = impl
dispimpl[(dispid, DISPATCH_METHOD)] = impl

return sink

Expand Down Expand Up @@ -276,7 +272,7 @@ def handler(self, this, *args, **kw):
args = (None,) + args
print(f"Event {name}({', '.join([repr(a) for a in args])})")

return comtypes.instancemethod(handler, self, EventDumper)
return instancemethod(handler, self, EventDumper)


def ShowEvents(source, interface=None):
Expand All @@ -285,13 +281,13 @@ def ShowEvents(source, interface=None):
outgoing interface, and will also print out the events when they
are fired.
"""
return comtypes.client.GetEvents(source, sink=EventDumper(), interface=interface)
return GetEvents(source, sink=EventDumper(), interface=interface)


# This type is used inside 'PumpEvents', but if we create the type
# afresh each time 'PumpEvents' is called we end up creating cyclic
# garbage for each call. So we define it here instead.
_handles_type = ctypes.c_void_p * 1
_handles_type = LPVOID * 1


def PumpEvents(timeout):
Expand Down Expand Up @@ -341,7 +337,7 @@ def HandlerRoutine(dwCtrlType):
int(timeout * 1000),
len(handles),
handles,
ctypes.byref(ctypes.c_ulong()),
byref(DWORD()),
)
except WindowsError as details:
if details.winerror != RPC_S_CALLPENDING: # timeout expired
Expand Down
3 changes: 2 additions & 1 deletion comtypes/client/dynamic.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import ctypes
from _ctypes import COMError
from typing import Any, Dict, Optional, Set, Type, TypeVar

from comtypes import GUID, COMError, IUnknown, _is_object, automation
from comtypes import GUID, IUnknown, _is_object, automation
from comtypes import hresult as hres
from comtypes.client import lazybind

Expand Down
5 changes: 2 additions & 3 deletions comtypes/connectionpoints.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import sys
from ctypes import *
from ctypes import POINTER, Structure, c_ulong

from comtypes import COMMETHOD, GUID, HRESULT, IUnknown, dispid
from comtypes import COMMETHOD, GUID, HRESULT, IUnknown

_GUID = GUID

Expand Down
4 changes: 2 additions & 2 deletions comtypes/errorinfo.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import sys
from ctypes import *
from ctypes import POINTER, OleDLL, byref, c_wchar_p
from ctypes.wintypes import DWORD, ULONG

from comtypes import BSTR, COMMETHOD, GUID, HRESULT, IUnknown
from comtypes.hresult import *
from comtypes.hresult import DISP_E_EXCEPTION, S_OK

LPCOLESTR = c_wchar_p

Expand Down
3 changes: 1 addition & 2 deletions comtypes/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@
between different threading appartments.
"""

from ctypes import *
from ctypes import POINTER
from ctypes.wintypes import DWORD

from comtypes import (
CLSCTX_INPROC_SERVER,
COMMETHOD,
GUID,
HRESULT,
STDMETHOD,
Expand Down
6 changes: 3 additions & 3 deletions comtypes/server/inprocserver.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import ctypes
import logging
import sys
import winreg
from ctypes import c_void_p, pointer
from typing import TYPE_CHECKING, Any, Literal, Optional, Type

from comtypes import GUID, COMObject, IUnknown, hresult
Expand Down Expand Up @@ -29,7 +29,7 @@ def IClassFactory_CreateInstance(
this: Any,
punkOuter: Optional[Type["_Pointer[IUnknown]"]],
riid: "_Pointer[GUID]",
ppv: ctypes.c_void_p,
ppv: c_void_p,
) -> int:
_debug("ClassFactory.CreateInstance(%s)", riid[0])
result = self._cls().IUnknown_QueryInterface(None, riid, ppv)
Expand Down Expand Up @@ -138,7 +138,7 @@ def DllGetClassObject(rclsid: int, riid: int, ppv: int) -> int:
return hresult.CLASS_E_CLASSNOTAVAILABLE

result = ClassFactory(cls).IUnknown_QueryInterface(
None, ctypes.pointer(iid), ctypes.c_void_p(ppv)
None, pointer(iid), c_void_p(ppv)
)
_debug("DllGetClassObject() -> %s", result)
return result
Expand Down
37 changes: 15 additions & 22 deletions comtypes/server/localserver.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
import logging
import queue
from ctypes import (
HRESULT,
POINTER,
OleDLL,
byref,
c_ulong,
c_void_p,
)
from ctypes import HRESULT, POINTER, OleDLL, byref, c_ulong, c_void_p
from ctypes.wintypes import DWORD, LPDWORD
from typing import TYPE_CHECKING, Any, Literal, Optional, Sequence, Type

import comtypes
from comtypes import GUID, hresult
from comtypes import CLSCTX_INPROC, GUID, COMObject, IUnknown
from comtypes.hresult import S_OK
from comtypes.server import IClassFactory

if TYPE_CHECKING:
Expand Down Expand Up @@ -40,18 +33,18 @@
_CoRevokeClassObject.restype = HRESULT


def run(classes: Sequence[Type[comtypes.COMObject]]) -> None:
def run(classes: Sequence[Type[COMObject]]) -> None:
classobjects = [ClassFactory(cls) for cls in classes]
comtypes.COMObject.__run_localserver__(classobjects)
COMObject.__run_localserver__(classobjects)


class ClassFactory(comtypes.COMObject):
class ClassFactory(COMObject):
_com_interfaces_ = [IClassFactory]
_locks: int = 0
_queue: Optional[queue.Queue] = None
regcls: int = REGCLS_MULTIPLEUSE

def __init__(self, cls: Type[comtypes.COMObject], *args, **kw) -> None:
def __init__(self, cls: Type[COMObject], *args, **kw) -> None:
super(ClassFactory, self).__init__()
self._cls = cls
self._register_class()
Expand All @@ -67,11 +60,11 @@ def IUnknown_Release(self, this: Any) -> int:
def _register_class(self) -> None:
regcls = getattr(self._cls, "_regcls_", self.regcls)
cookie = c_ulong()
ptr = self._com_pointers_[comtypes.IUnknown._iid_]
ptr = self._com_pointers_[IUnknown._iid_]
clsctx = self._cls._reg_clsctx_
clsctx &= ~comtypes.CLSCTX_INPROC # reset the inproc flags
clsctx &= ~CLSCTX_INPROC # reset the inproc flags
_CoRegisterClassObject(
byref(comtypes.GUID(self._cls._reg_clsid_)),
byref(GUID(self._cls._reg_clsid_)),
ptr,
clsctx,
regcls,
Expand All @@ -85,8 +78,8 @@ def _revoke_class(self) -> None:
def CreateInstance(
self,
this: Any,
punkOuter: Optional[Type["_Pointer[comtypes.IUnknown]"]],
riid: "_Pointer[comtypes.GUID]",
punkOuter: Optional[Type["_Pointer[IUnknown]"]],
riid: "_Pointer[GUID]",
ppv: c_void_p,
) -> int:
_debug("ClassFactory.CreateInstance(%s)", riid[0])
Expand All @@ -97,7 +90,7 @@ def CreateInstance(

def LockServer(self, this: Any, fLock: bool) -> Literal[0]:
if fLock:
comtypes.COMObject.__server__.Lock()
COMObject.__server__.Lock()
else:
comtypes.COMObject.__server__.Unlock()
return hresult.S_OK
COMObject.__server__.Unlock()
return S_OK
2 changes: 0 additions & 2 deletions comtypes/test/test_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from ctypes.wintypes import DWORD, PWCHAR
from pathlib import Path

import comtypes
import comtypes.client

with contextlib.redirect_stdout(None): # supress warnings
Expand All @@ -27,7 +26,6 @@

STG_E_PATHNOTFOUND = -2147287038


_ole32 = OleDLL("ole32")

_StgCreateDocfile = _ole32.StgCreateDocfile
Expand Down
3 changes: 2 additions & 1 deletion comtypes/tools/tlbparser.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import os
import sys
from _ctypes import COMError
from ctypes import alignment, c_void_p, sizeof, windll
from typing import Any, Dict, List, Optional, Tuple

from comtypes import BSTR, COMError, automation, typeinfo
from comtypes import automation, typeinfo
from comtypes.client._code_cache import _get_module_filename
from comtypes.tools import typedesc

Expand Down
13 changes: 12 additions & 1 deletion comtypes/viewobject.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# XXX need to find out what the share from comtypes.dataobject.
from ctypes import *
from ctypes import (
HRESULT,
POINTER,
Structure,
alignment,
c_int,
c_ubyte,
c_ulong,
c_ushort,
c_void_p,
sizeof,
)
from ctypes.wintypes import _RECTL, HDC, SIZEL, tagPOINT, tagRECT

from comtypes import COMMETHOD, GUID, IUnknown
Expand Down