Category Archives: C++

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 m_pOriginalInterface; // ptr la interfata originala

 HRESULT FinalConstruct()
 {

// incarca modulul de interceptat
  m_hOriginalModule = CoLoadLibrary(_T(““), FALSE);
  if(m_hOriginalModule != NULL)
  {

// obtine ptr la IClassFactory
   CComPtr pFactory;
   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.