ID: Q190901
The information in this article applies to:
ADOEvts.exe is a sample that demonstrates how to capture events from Microsoft Active Data Objects (ADO). The ADO events in this sample were added with ADO version 2.0.
The following file is available for download from the Microsoft Software Library:
 ~ ADOEvts.exe (size: 32798 bytes) 
For more information about downloading files from the Microsoft Software Library, please see the following article in the Microsoft Knowledge Base:
   ARTICLE-ID: Q119591
   TITLE : How to Obtain Microsoft Support Files from Online Services
You need to make a DataSource called "AccessTest" on the system that is pointing to the Test.mdb file provided with this sample.
After you run the console application, the events are shown in the Visual C++ Output window.
Follow these steps to capture ADO events in Visual C++:
1. Create classes derived from RecordsetEventsVt and ConnectionEventsVt.
   These classes define the sink object for the events.
   for each of the classes.
   the object to the appropriate ADO connection point.
The first step to handling ADO events is to create the sink classes that will handle the events. To do this, you must create a Visual C++ class derived from either RecordsetEventsVt or ConnectionEventsVt, depending upon the events you want to capture. The RecordsetEventsVt and ConnectionEventsVt interfaces are defined in ADOInt.h, which comes with the Microsoft Data Access SDK or Visual Studio version 6.0.
The sample shows both of the classes in ADOConnEvts.h and ADORSEvts.h. They are called CADOConnectionEvents and CADORecordsetEvents respectively. Following is the connection event class:
   ********
   #include <adoint.h>
   class CADOConnectionEvents : public ConnectionEventsVt
   {
   public :
      ULONG m_ulRefCount;
      CADOConnectionEvents():m_ulRefCount(1){}
      STDMETHOD(QueryInterface)(REFIID iid, LPVOID * ppvObject)
      {
        if (IsEqualIID(__uuidof(IUnknown), iid) ||
            IsEqualIID(__uuidof(ConnectionEventsVt), iid))
        {
          *ppvObject = this;
          return S_OK;
        }
        else
          return E_NOINTERFACE;
      }
      STDMETHOD_(ULONG, AddRef)()
      {
        return m_ulRefCount++;
      }
      STDMETHOD_(ULONG, Release)()
      {
        if (--m_ulRefCount == 0)
        {
          delete this;
          return 0;
        }
        else
          return m_ulRefCount;
      }
      STDMETHOD(InfoMessage)(
               ADOError * pError,
               EventStatusEnum * adStatus,
               _ADOConnection * pConnection)
      {
        *adStatus = adStatusUnwantedEvent;
        return S_OK;
      }
      STDMETHOD(BeginTransComplete)(
               LONG TransactionLevel,
               ADOError * pError,
               EventStatusEnum * adStatus,
               _ADOConnection * pConnection)
      {
        *adStatus = adStatusUnwantedEvent;
        return S_OK;
      }
      STDMETHOD(CommitTransComplete)(
               ADOError * pError,
               EventStatusEnum * adStatus,
               _ADOConnection * pConnection)
      {
         *adStatus = adStatusUnwantedEvent;
         return S_OK;
      }
      STDMETHOD(RollbackTransComplete)(
               ADOError * pError,
               EventStatusEnum * adStatus,
               _ADOConnection * pConnection)
      {
        *adStatus = adStatusUnwantedEvent;
        return S_OK;
      }
      STDMETHOD(WillExecute)(
               BSTR * Source,
               CursorTypeEnum * CursorType,
               LockTypeEnum * LockType,
               long * Options,
               EventStatusEnum * adStatus,
               _ADOCommand * pCommand,
               _ADORecordset * pRecordset,
               _ADOConnection * pConnection)
      {
         *adStatus = adStatusUnwantedEvent;
         return S_OK;
      }
      STDMETHOD(ExecuteComplete)(
               LONG RecordsAffected,
               ADOError * pError,
               EventStatusEnum * adStatus,
               _ADOCommand * pCommand,
               _ADORecordset * pRecordset,
               _ADOConnection * pConnection)
      {
        *adStatus = adStatusUnwantedEvent;
        return S_OK;
      }
      STDMETHOD(WillConnect)(
               BSTR * ConnectionString,
               BSTR * UserID,
               BSTR * Password,
               long * Options,
               EventStatusEnum * adStatus,
               _ADOConnection  *pConnection)
      {
        *adStatus = adStatusUnwantedEvent;
        return S_OK;
      }
      STDMETHOD(ConnectComplete)(
               ADOError * pError,
               EventStatusEnum * adStatus,
               _ADOConnection * pConnection)
      {
        *adStatus = adStatusUnwantedEvent;
        return S_OK;
      }
      STDMETHOD(Disconnect)(
               EventStatusEnum * adStatus,
               _ADOConnection * pConnection)
      {
        *adStatus = adStatusUnwantedEvent;
        return S_OK;
      }
   };
   ********
The ADOEvts.cpp file demonstrates how to connect an event object to an ADO connection or recordset. Four functions are defined: SetConnectionEvents(), SetRSEvents(), ClearRSEvents(), and ClearConnectionEvents(). Following is and example of how the functions are used in the main() function:
   *****
   int main(int argc, char* argv[])
   {
      CoInitialize(NULL);
      ADODB::_ConnectionPtr spConn(__uuidof(ADODB::Connection));
      ADODB::_RecordsetPtr spRS(__uuidof(ADODB::Recordset));
      SetConnectionEvents(spConn);
      spConn->Open(L"DSN=AccessTest", L"", L"", -1L);
      SetRSEvents(spRS);
      spRS->Open(L"Select * from Table1", spConn.GetInterfacePtr(),
                      ADODB::adOpenKeyset, ADODB::adLockOptimistic, -1);
      spRS->MoveFirst();
      spRS->MoveNext();
      spRS->Close();
      spConn->Close();
      ClearRSEvents(spRS);
      ClearConnectionEvents(spConn);
      return 0;
   }
   *****
Following is the code for SetConnectionEvents():
   *****
   DWORD  gdwCnEvents;
   HRESULT SetConnectionEvents(ADODB::_ConnectionPtr & spConn)
   {
      IConnectionPointContainer   *pCPC = NULL;
      IConnectionPoint            *pCP = NULL;
      HRESULT hr;
      hr = spConn->QueryInterface(IID_IConnectionPointContainer,
                                  (LPVOID *) &pCPC);
      if (FAILED(hr))
        return hr;
      hr = pCPC->FindConnectionPoint(__uuidof(ConnectionEvents), &pCP);
      pCPC->Release();
      if (FAILED(hr))
        return hr;
      hr = pCP->Advise(new CCnEvents, &gdwCnEvents);
      pCP->Release();
      return hr;
   }
   *****
Also, further notice that the pointer, "new CCnEvents", is passed directly to the Advise call. The event object is freed when its Release() method is called in the connection point Unadvise() call in ClearConnectionEvents().
Additional query words:
Keywords          : kbfile kbsample kbADO200 kbDatabase kbSDKDataAc 
Version           : WINDOWS:2.0; WINNT:5.0,5.0sp1,5.0sp2,5.0sp3
Platform          : WINDOWS winntLast Reviewed: August 8, 1998