views:

563

answers:

1

Environment: VS2008 (ATL), Borland Developer Studio 2006.

Hello all. I'm having some troubles with ActiveX control events.

Here is a brief description of my app architecture:

There is an inproc COM server which contains STA ActiveX control (aka control) and MTA COM object (aka object).

Here is the IDL definition of the control and object interfaces:

[
    object,
    uuid(2338CCAF-BBAF-4E29-929B-A67285B1E772),
    dual,
    nonextensible,
    pointer_default(unique)
]
interface IObject : IDispatch{
    [id(1)] HRESULT DoWork(void);
};

[
    object,
    uuid(1A0A1DA2-E33B-4DF4-99A9-9EAEF2281E7D),
    dual,
    nonextensible,
    pointer_default(unique)
]
interface IControl : IDispatch{
};


[
    uuid(BC27FABD-2794-4F9C-B3BD-C0C0628741FA),
    version(1.0),
    helpstring("AVRep 1.0 Type Library")
]

library ActiveXLib
{
    importlib("stdole2.tlb");
    [
     uuid(4B5575A7-E0FF-49B5-AE10-0D980CF49EB3)
    ]
    dispinterface _IControlEvents
    {
     properties:
     methods:
            [id(1)] HRESULT SomeEvent([in] IObject* obj);
        };
    [
     uuid(7C44F19E-6B71-434B-96F6-E29A3C66C794),
     control
    ]
    coclass Control
    {
     [default] interface IControl;
     [default, source] dispinterface _IControlEvents;
    };
    [
     uuid(17BDFAC0-DF21-4474-BCFF-846FE0075D68)
    ]
    coclass Object
    {
     [default] interface IObject;
    };
};

Client is a Delphi application with ActiveX control on the form which creates MTA object and calls its DoWork method

var
  mta : IObject;
begin
  mta := CreateOleObject('ActiveXLib.Object.1') as IObject;
  mta.DoWork();
end;

This method directly calls Fire_SomeEvent method of ActiveX control coclass and passes 'this' as a parameter (pointer to IObject interface). Delphi code successfully receives event but when it tries to access any IObject method or property (not shown in idl for simplicity) then access violation occured in oleaut32.dll.

One important note - I use ATLCPImplMT class to implement event firing from different threads (see http://support.microsoft.com/kb/280512 for details). This implementation allows to switch apartments when event fires (from MTA apartment of the object to STA Delphi forms apartment). I suggest that this problem is related to incorrect event parameter marshaling because when standard ATLCPImpl class is used all works fine.

Are there any restrictions for cross-apartment events? Maybe some special Delphi environment setup is required to work with activex objects correctly...

+1  A: 

Are you accessing objects that were created in the same thread as the event handler or were the COM object created in the main thread? If you are not in the same thread context in the eventhandler as the thread that created the object, you may get access violations when you try accessing the COM object.

A quick fix workaround can be to post a message to the main thread from the event handler, and have the main thread access the COM object in the main thread context, instead of directly in the COM event handler.

Threads and COM is not less complicated that threads without COM.

Lars Fosdal