I am trying to subscribe to MBN Events. Here is my code:
void subscribeToMbnEvents()
{
dwError = CoInitializeEx(NULL, COINIT_MULTITHREADED);
SAFEARRAY* mbnInterfaces;
CComPtr<IMbnInterfaceManager> intMgr = NULL;
dwError = CoCreateInstance(CLSID_MbnInterfaceManager, NULL, CLSCTX_ALL, IID_IMbnInterfaceManager, (void**)&intMgr);
if (dwError != ERROR_SUCCESS)
{
CoUninitialize();
std::cout << getTimeStamp() << " failed to initialize IMbnInterfaceManager \n";
}
dwError = intMgr->GetInterfaces(&mbnInterfaces);
if (dwError != ERROR_SUCCESS)
{
CoUninitialize();
std::cout << getTimeStamp() << " failed to get MBN Interfaces \n";
}
if (dwError == ERROR_SUCCESS)
{
LONG indexOfFirstMBNInterface;
dwError = SafeArrayGetLBound(mbnInterfaces, 1, &indexOfFirstMBNInterface);
if (dwError != ERROR_SUCCESS)
{
std::cout << getTimeStamp() << " failed to get first index of MBN Interface \n";
}
CComPtr<IMbnInterface> MbnInt = NULL;
dwError = SafeArrayGetElement(mbnInterfaces, &indexOfFirstMBNInterface, (void*)(&MbnInt));
if (dwError != ERROR_SUCCESS)
{
std::cout << getTimeStamp() << " failed to get MBN Interface \n";
}
IConnectionPointContainer* icpc;
dwError = intMgr->QueryInterface(IID_IMbnInterfaceManager, (void**)&icpc);
if (dwError != ERROR_SUCCESS)
{
std::cout << "Error querying interface" << std::endl;
}
IConnectionPoint *icp;
dwError = icpc->FindConnectionPoint(IID_IMbnInterfaceEvents, &icp);
if (dwError != ERROR_SUCCESS)
{
std::cout << "Error finding connection point" << std::endl;
}
}
}
Since the documentation is (imho) a Little bit lacking i oriented myself at some code samples i found on the net. up until i call FindConnectionPoint everything works as it should. When calling FindConnectionPoint i get an Access Violation writing to Memory so i guess the Problem is with my IConnectionPoint pointer which is declared as in multiple code examples i found.
Hopefully someone with a Little bit more oversight is able to help with this. Thanks in advance
The code retrieving the
IConnectionPointContaineris wrong:This code returns an
IMbnInterfaceManagerinterface, but reinterprets it as anIConnectionPointContainer. When it continues to executeicpc->FindConnectionPointit really is calling a random interface method ofIMbnInterfaceManager1.To address this issue, the code needs to be changed to this:
It's easier and safer yet to use the IID_PPV_ARGS macro. It deduces the interface ID that matches the pointer type:
1 It's not entirely random.
FindConnectionPointis the second entry in theIConnectionPointContainerinterface, i.e. the fifth entry in the v-table (accounting for the 3IUnknownmethods). The same spot in theIMbnInterfaceManageris occupied by the GetInterfaces method. It's first argument is an [out] parameter, so that explains the access violation on write.