c++winapicommobile-broadband-apiconnection-points

Access violation writing memory when calling FindConnectionPoint


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


Solution

  • 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.