Вопрос в следующем:
мне нужно написать объект, который бы перехватывал обычные event'ы через IConnectionPoint и запускал бы их на переданном мне IDispatch. Я загружаю tlb, вычитываю оттуда нужный мне интерфейс, выполняю advise на объекте-источнике событий. Но возникает проблема: если посмотреть в код метода advise в ATL реализации, то там есть такой кусок:
hRes = pUnkSink->QueryInterface(iid, (void**)&p);
if (SUCCEEDED(hRes))
{
pT->Lock();
*pdwCookie = m_vec.Add(p);
hRes = (*pdwCookie != NULL) ? S_OK : CONNECT_E_ADVISELIMIT;
pT->Unlock();
if (hRes != S_OK)
p->Release();
}
else if (hRes == E_NOINTERFACE)
hRes = CONNECT_E_CANNOTCONNECT;
if (FAILED(hRes))
*pdwCookie = 0;
где iid — CLSID интерфейса-источника событий (для определенности дальше я буду его называть IID_Event), для которого я говорю advise.
Т.е получается, что ATL делает дополнительную проверку и проверяет, действительно ли переданный ему указатель на интерфейс поддерживает интерфейс-источник событий (IID_Event).
И вроде бы все хорошо, но я ( и другие языки, поддерживающие позднее связывание) не могу в QueryInterface ответить, что я поддерживаю на двоичном уровне IID_Event. Я могу честно ответить, что я поддерживаю IUnknown и IDispatch.
Дальше если посмотреть исходники запуска событий в ATL будет все равно видно, что события вызываются через IDispatch.
Т.е. я могу формально подправить QueryInterface и добавить туда строчку, что я поддерживаю IID_Event, но если вдруг объект-источник событий решит вызвать через указатель методы IID_Event напрямую, не через IDispatch, то тут же получит ошибку доступа к памяти.
Я поискал по интернету, но наткнулся лишь на одну статью с borland'a, где они решают похожую задачу, так там они действительно в QueryInterface объявляют о поддержке IID_Event, но возвращают просто указатель на IDispatch.
Может быть есть какие-нибудь соглашения о вызове методов на [default,source] интерфейсах?
Или нужна какая-нибудь дополнительная обработка?