0
votes

Problem:

  • Event notifications (From COM object - Server) are not received as listed in the Sink (class) implementation.

  • One event notification is received (Event_one), however, others are not received accordingly

  • If order is changed - in IDispatch::Invoke, that is:

    • if Event_one is swapped to Event_two then Event_two notification received but Event_one and others neglected accordingly

Question:

  • Better way to implement, IDispatch::Invoke or QI?
  • Using the wrong logic or approach?

Note:

  • No MFC
  • No ATL
  • Pure C++
  • using message loop: GetMessage()
  • STA model ( Coinitialize() )
  • Call to IDispatch::Advise successful (HRESULT from call S_OK)
  • After above, COM object method calls as normal (with interface pointer)
  • Single call to Advise
  • Type library generated from MIDL compiler

For instance (example):

Illustration of IDispatch::Invoke - taken from Sink Class:

HRESULT STDMETHODCALLTYPE Invoke(
{
//omitted parameters

// The riid parameter is always supposed to be IID_NULL
        if (riid != IID_NULL)
            return DISP_E_UNKNOWNINTERFACE;

if (pDispParams) //DISPID dispIdMember
    {
        switch (dispIdMember) { 
        case 1:
            return Event_one();
        case 2:
            return Event_two();
        case 3:
            return Event_three();
        default:
            return E_NOTIMPL;
        }
    }
    return E_NOTIMPL;
}

Illustration of QueryInterface:

STDMETHOD (QueryInterface)(
//omitted parameters
{
    if (iid == IID_IUnknown || iid == __uuidof(IEvents))
    {
        *ppvObject = (IEvents *)this;
    } else {
        *ppvObject = NULL;
        return E_NOINTERFACE;
    }
    m_dwRefCount++;
    return S_OK;
};
2

2 Answers

1
votes

Since you are receiving the notification for first method of the sink interface, I suspect, events are not sent on other methods from Server. If you have code of the server, just check the connection point class which throws the notifications.

You can also put a breakpoint in Invoke method of client application to check what are all the events it is receiving.

0
votes

SOLVED:

After reviewing the corresponding IDL FILE (generated by the MIDL compiler), it was evident that each method contained in the IEvent interface, has a unique ID. For instance, Event_one has an ID of 2. For example:

methods:
    [id(0x00000002)]
    HRESULT Event_one();

Therefore, making a change as followings - in the IDispatch::invoke implementation (illustrated in the above question):

//omitted


if (pDispParams) //DISPID dispIdMember
        {
            switch (dispIdMember) { 
            case 2:
                    return Event_one();

//omitted 

Now when invoked accordingly, the desired/correct method is now executed.