ADO with Visual C++ Extensions Example

Microsoft ActiveX Data Objects (ADO)

ADO with Visual C++ Extensions Example

This program shows how values are retrieved from fields and converted to C/C++ variables.

This example also takes advantage of "smart pointers," which automatically handle the COM-specific details of calling QueryInterface and reference counting for the IADORecordBinding interface.

Without smart pointers, you would code:

IADORecordBinding   *picRs = NULL;
...
TESTHR(pRs->QueryInterface(
          __uuidof(IADORecordBinding), (LPVOID*)&picRs));
...
if (picRs) picRs->Release();

With smart pointers, you derive the IADORecordBindingPtr type from the IADORecordBinding interface with this statement:

_COM_SMARTPTR_TYPEDEF(IADORecordBinding, __uuidof(IADORecordBinding));

And instantiate the pointer like this:

IADORecordBindingPtr picRs(pRs);

Because the Visual C++ Extensions are implemented by the Recordset object, the constructor for the smart pointer, picRs, takes the _RecordsetPtr pointer, pRs. The constructor calls QueryInterface using pRs to find the IADORecordBinding interface.

// Visual C++ Extensions Example
#import "c:\Program Files\Common Files\System\ADO\msado15.dll" \
   no_namespace rename("EOF", "EndOfFile")

#include <stdio.h>
#include <icrsint.h>
_COM_SMARTPTR_TYPEDEF(IADORecordBinding, __uuidof(IADORecordBinding));

inline void TESTHR(HRESULT _hr) { if FAILED(_hr) _com_issue_error(_hr); }

class CCustomRs : public CADORecordBinding
{
BEGIN_ADO_BINDING(CCustomRs)
   ADO_VARIABLE_LENGTH_ENTRY2(2, adVarChar, m_ch_fname, 
                        sizeof(m_ch_fname), m_ul_fnameStatus, false)
   ADO_VARIABLE_LENGTH_ENTRY2(4, adVarChar, m_ch_lname, 
                        sizeof(m_ch_lname), m_ul_lnameStatus, false)
END_ADO_BINDING()
public:
   CHAR    m_ch_fname[22];
   CHAR    m_ch_lname[32];
   ULONG   m_ul_fnameStatus;
   ULONG   m_ul_lnameStatus;
};

void main(void)
{
   ::CoInitialize(NULL);
   try 
      {
      _RecordsetPtr pRs("ADODB.Recordset");
      CCustomRs rs;
      IADORecordBindingPtr picRs(pRs);
      
      pRs->Open("SELECT * FROM Employee ORDER BY lname", 
         "dsn=pubs;uid=sa;pwd=;", 
         adOpenStatic, adLockOptimistic, adCmdText);
      
      TESTHR(picRs->BindToRecordset(&rs));

      while (!pRs->EndOfFile)
         {
      // Process data in the CCustomRs C++ instance variables.
         printf("Name = %s %s\n",
            (rs.m_ul_fnameStatus == adFldOK ? rs.m_ch_fname: "<Error>"), 
            (rs.m_ul_lnameStatus == adFldOK ? rs.m_ch_lname: "<Error>"));

      // Move to the next row of the Recordset. 
      // Fields in the new row will automatically be 
      // placed in the CCustomRs C++ instance variables.
   
         pRs->MoveNext();
         }
      }
   catch (_com_error &e )
      {
      printf("Error:\n");
      printf("Code = %08lx\n", e.Error());
      printf("Meaning = %s\n", e.ErrorMessage());
      printf("Source = %s\n", (LPCSTR) e.Source());
      printf("Description = %s\n", (LPCSTR) e.Description());
      }
   ::CoUninitialize();
}