O metoda pentru a intercepta apelurile COM.
Cateodata e util (povestea lui “de ce” e prea lunga) sa se intercepteze apelurile care se fac intr-un server COM DLL 3rd party. Una dintre posibilele solutii la aceasta problema urmeaza:
(voi scurta detaliile, presupunand ca oricum daca nu stiti cum sa ajungeti aici, nu v-ati pus problema interceptiei COM anyway ).
1. New project, ATL project.
2. Cu ajutorul object viewerului, inspectati DLL-ul care va intereseaza; veti avea in COM Object Viewer IDL-ul serverului vizat. Copiati-l in proiectul nou.
3. Adaugati un obiect COM (simple COM object), care va implementa interfata/interfetele care va intereseaza.
4. Nu uitati sa actualizati resursele registry (rgs) cu UUID-urile din IDL-ul “pastat”.
5. Metodele FinalConstruct si Final Release din obiectul COM adaugat la punctul 3, ar putea arata asa:
(IMyInterface este interfata care se intercepteaza):
HMODULE m_hOriginalModule; // handle la DLL-ul interceptat
CComPtr
HRESULT FinalConstruct()
{
// incarca modulul de interceptat
m_hOriginalModule = CoLoadLibrary(_T(”
if(m_hOriginalModule != NULL)
{
// obtine ptr la IClassFactory
CComPtr
DllGetClassObjectFn fn = (DllGetClassObjectFn)GetProcAddress(m_hOriginalModule, “DllGetClassObject”);
if(fn != NULL)
{
// apel DllGetClassObject in modulul interceptat, pentru a obtine IClassFactory-ul
HRESULT hRes = fn(CLSID_MyInterfaceCoClass, IID_IClassFactory, (LPVOID *)&pFactory);
if(FAILED(hRes))
{
return hRes;
}
// apel CreateInstance pentru a obtine o interfata in implementarea originala
hRes = pFactory->CreateInstance(NULL, IID_IMyInterface, (LPVOID *)&m_pOriginalInterface);
if(FAILED(hRes))
{
return hRes;
}
}
}
return S_OK;
}
void FinalRelease()
{
if(m_hOriginalModule != NULL)
{
// release inainte de FreeLibrary
m_pOriginalInterface.Release();
CoFreeLibrary(m_hOriginalModule);
}
}
// se poate rescrie functia InternalQueryInterface pentru a loga ce apeluri QI se fac
static HRESULT InternalQueryInterface(void *pThis, const ATL::_ATL_INTMAP_ENTRY *pEntries, const IID &iid, void **ppvObject)
{
// log the thing
HRESULT hRes = CComObjectRootBase::InternalQueryInterface(pThis, pEntries, iid, ppvObject);
CLog log;
log.Write(”QI: {%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x} returned=%08x\r\n”,
iid.Data1, iid.Data2, iid.Data3, iid.Data4[0], iid.Data4[1], iid.Data4[2], iid.Data4[3],
iid.Data4[4], iid.Data4[5], iid.Data4[6], iid.Data4[7], hRes);
return hRes;
}
// se pot rescrie metodele din IMyInterface si loga parametrii
HRESULT MyMethod1(…. )
{
// log params
HRESULT hRes = m_pOriginalInterface->MyMethod1(…);
// log hRes, out params
return hRes;
}
… etc.




