views:

124

answers:

2

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;
};
+1  A: 

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.

Vinay
@Vinay: +1 your suggestion helped locate the problem - I'm grateful
Aaron
A: 

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.

Aaron