Access violation writing memory when calling FindConnectionPoint

223 Views Asked by At

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

1

There are 1 best solutions below

0
IInspectable On BEST ANSWER

The code retrieving the IConnectionPointContainer is wrong:

IConnectionPointContainer* icpc;
dwError = intMgr->QueryInterface(IID_IMbnInterfaceManager, (void**)&icpc);
//                               ^^^^^^^^^^^^^^^^^^^^^^^^ wrong interface ID
if (dwError != ERROR_SUCCESS) 
{ 
    std::cout << "Error querying interface" << std::endl; 
}

This code returns an IMbnInterfaceManager interface, but reinterprets it as an IConnectionPointContainer. When it continues to execute icpc->FindConnectionPoint it really is calling a random interface method of IMbnInterfaceManager1.

To address this issue, the code needs to be changed to this:

IConnectionPointContainer* icpc = nullptr;
HRESULT hr = intMgr->QueryInterface(IID_ConnectionPointContainer, (void**)&icpc);
if (FAILED(hr)) 
{ 
    std::cout << "Error querying interface" << std::endl; 
}

It's easier and safer yet to use the IID_PPV_ARGS macro. It deduces the interface ID that matches the pointer type:

HRESULT hr = intMgr->QueryInterface(IID_PPV_ARGS(&icpc));


1 It's not entirely random. FindConnectionPoint is the second entry in the IConnectionPointContainer interface, i.e. the fifth entry in the v-table (accounting for the 3 IUnknown methods). The same spot in the IMbnInterfaceManager is occupied by the GetInterfaces method. It's first argument is an [out] parameter, so that explains the access violation on write.