- Implemented the Sink Class - to receive event notifications from COM Server
- Event Interface derives from IDispatch
I have an issue whereby an IConnectionPoint::Advise call returns E_NOTIMPL. This could be because the connection point only allows one connection - MSDN.
Note:
- COM Server is out-of-process
- Pure C++ implementation
EDIT:
S8.tlh: C++ source equivalent of Win32 type library S8.tlb:
struct __declspec(uuid("090910c3-28c3-45fe-861d-edcf11aa9788"))
IS8SimulationEvents : IDispatch
{
// Methods:
HRESULT S8SimulationReset ( );
HRESULT S8SimulationEndRun ( );
HRESULT S8SimulationCustomEvent (
BSTR * TextInfo );
HRESULT S8SimulationOpened ( );
HRESULT S8SimulationEndTrial ( );
HRESULT S8SimulationOEMEvent (
BSTR * TextInfo );
HRESULT S8SimulationReadyToClose ( );
HRESULT S8SimulationUserMessage (
long * Answer,
BSTR * TextMsg,
long ValidAnswers );
};
Implementation of Class Sink - to handle event notifications:
class Sink : public IS8SimulationEvents
{
public:
Sink(){
m_dwRefCount = 0;
};
~Sink(){};
/*
* IS8SimulationEvent interface functions
*/
HRESULT S8SimulationEndTrial()
{
cout << "Simulation complete." << endl;
return S_OK;;
};
HRESULT S8SimulationOpened()
{
cout << "Simulation open." << endl;
return S_OK;
};
HRESULT S8SimulationReadyToClose()
{
cout << "Simulation ready to close" << endl;
return S_OK;
};
ULONG STDMETHODCALLTYPE AddRef()
{
m_dwRefCount++;
return m_dwRefCount;
};
ULONG STDMETHODCALLTYPE Release()
{
ULONG l;
l = m_dwRefCount--;
if (0 == m_dwRefCount)
{
delete this;
}
return m_dwRefCount;
};
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID iid ,
void **ppvObject)
{
m_dwRefCount++;
*ppvObject = (void *)this;
return S_OK;
};
HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *pctinfo)
{
return E_NOTIMPL;
};
HRESULT STDMETHODCALLTYPE GetIDsOfNames(
REFIID riid,
LPOLESTR *rgszNames,
UINT cNames,
LCID lcid,
DISPID *rgDispId)
{
return E_NOTIMPL;
};
HRESULT STDMETHODCALLTYPE GetTypeInfo(
unsigned int iTInfo,
LCID lcid,
ITypeInfo FAR* FAR* ppTInfo)
{
return E_NOTIMPL;
};
HRESULT STDMETHODCALLTYPE Invoke(
DISPID dispIdMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS FAR* pDispParams,
VARIANT FAR* pVarResult,
EXCEPINFO FAR* pExcepInfo,
unsigned int FAR* puArgErr)
{
HRESULT hresult = S_OK;
if (pDispParams)
{
switch (dispIdMember) {
case 1:
return S8SimulationEndTrial();
case 2:
return S8SimulationOpened();
case 3:
return S8SimulationReadyToClose();
default:
return E_NOTIMPL;
}
}
return E_NOTIMPL;
}
private:
DWORD m_dwRefCount;
public:
void SetupConnectionPoint (IS8Simulation *pis8)
{
HRESULT hresult;
IConnectionPointContainer *pContainer = NULL;
IConnectionPoint *pConnection = NULL;
IUnknown *pSinkUnk = NULL;
Sink *pSink = NULL;
DWORD dwAdvise;
dwAdvise = 0;
hresult = pis8->QueryInterface(
__uuidof(IConnectionPointContainer),
(void **) &pContainer);
if (SUCCEEDED(hresult))
{
cout << "IConnectionPointContainer inteface supported." << endl;
} else {
cerr << "Error: No such interface supported." << endl;
exit (hresult);
}
__uuidof(IS8SimulationEvents),
&pConnection);
switch (HRESULT_CODE(hresult)) {
case NOERROR:
cout << "Obtained valid interface pointer." << endl;
break;
case E_POINTER:
cerr << "Invalid pointer: the address is not valid." << endl;
exit (hresult);
break;
case CONNECT_E_NOCONNECTION:
cerr << "This connectable object not support the "
"outgoing interface specified." << endl;
exit (hresult);
break;
case E_UNEXPECTED:
default:
cerr << "Catastrophic failure." << endl;
exit (hresult);
break;
}
pContainer->Release();
hresult = pSink->QueryInterface(
__uuidof(IUnknown),
(void **)&pSinkUnk);
if (FAILED(hresult))
{
exit (EXIT_FAILURE);
}
hresult = pConnection->Advise(
pSinkUnk,
&dwAdvise);
switch (HRESULT_CODE(hresult)) {
case NOERROR:
cout << "The connection has been established and "
"*dwAdvise has the connection token." << endl;
break;
case E_POINTER:
cerr << "Invalid pointer: "
"the value pSinkUnk or dwAdvise is not valid." << endl;
exit (hresult);
break;
case CONNECT_E_ADVISELIMIT:
cerr << "The connection point has already reached "
"its limit of connections and cannot accept "
"any more." << endl;
exit (hresult);
break;
case CONNECT_E_CANNOTCONNECT:
cerr << "The sink does not support the interface "
"required by this connection point." << endl;
exit (hresult);
break;
case E_NOTIMPL:
break;
case E_UNEXPECTED:
default:
cerr << "Catastrophic failure." << endl;
exit (hresult);
break;
}
return;
}
};
EDIT:
Implementation of IUnknown Interface in Sink Class
ULONG STDMETHODCALLTYPE AddRef()
{
m_dwRefCount++;
return m_dwRefCount;
};
ULONG STDMETHODCALLTYPE Release()
{
ULONG l;
l = m_dwRefCount--;
if (0 == m_dwRefCount)
{
delete this;
}
return m_dwRefCount;
};
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject)
{
m_dwRefCount++;
*ppvObject = (void *)this;
return S_OK;
};
Question:
- How to check if a container supports multiple connections?
- If more information is required, please comment accordingly.