How a Consumer Retrieves an OLE DB Error Object

When a consumer wants to retrieve an error object in response to a return code it received, it performs the following steps:

  1. Calls QueryInterface on the component that returned the code to retrieve an ISupportErrorInfo interface pointer on that component. This interface must be supported by all components that create error objects.

  2. Calls the InterfaceSupportsErrorInfo method in this interface and passes it the IID of the interface containing the method that returned the code. The InterfaceSupportsErrorInfo method returns S_OK if the interface supports error objects (meaning the consumer should retrieve the current error object, if one exists) and S_FALSE if the interface does not support error objects (meaning the consumer should not retrieve the current error object because it applies to another interface and method).

  3. Calls the GetErrorInfo function in the Automation DLL. This function returns an IErrorInfo interface pointer on the current error object and releases its reference count on the error object, thus transferring ownership of the error object to the consumer.

  4. Calls QueryInterface to return an IErrorRecords interface pointer on the error object.

  5. Calls the methods in IErrorRecords to retrieve information from the error object. To retrieve the error message, source, Help file, or Help context ID from a particular record, it first calls IErrorRecords::GetErrorInfo to retrieve an IErrorInfo interface pointer for that record. (This interface pointer is different from the one retrieved in step 3 as it applies to a specific record.) The consumer then calls methods using this pointer.

  6. Calls Release on the error object to release it.

For example, the following code shows how a consumer might retrieve and use an OLE DB error object:

#include <oledb.h>
#include <stdio.h>
IUnknown *pMyObject;
extern GUID IID_IMyInterface;
DWORD   MYLOCALEID;
BSTR    bstrSourceOfError, bstrDescriptionOfError;

int main() {
 IErrorInfo    *pErrorInfo;
 IErrorInfo    *pErrorInfoRec;
 IErrorRecords   *pErrorRecords;
 ISupportErrorInfo *pSupportErrorInfo;
 HRESULT    hr, hrErr;
 ULONG      i, ulNumErrorRecs;
 ERRORINFO    ErrorInfo;

 // Error or warning occurs when calling method.  (Not shown.)
 if (!FAILED(hrErr))
  return (hrErr);

 // Check that the current interface supports error objects.
 hr = pMyObject->QueryInterface(IID_ISupportErrorInfo,
            (void**) &pSupportErrorInfo);

 if (SUCCEEDED(hr)) {
  hr = pSupportErrorInfo->InterfaceSupportsErrorInfo(IID_IMyInterface);
  if (hr == S_OK) {
   // Get the current error object. Return if no error object exists.
   GetErrorInfo(0,&pErrorInfo);
   if (!pErrorInfo) return (hrErr);

   // Get the IErrorRecord interface and get the count of error recs.
   pErrorInfo->QueryInterface(IID_IErrorRecords, (void**) &pErrorRecords);
   pErrorRecords->GetRecordCount(&ulNumErrorRecs);

   // Read through error records and display them.
   for (i = 0; i < ulNumErrorRecs; i++) {
    // Get basic error information.
    pErrorRecords->GetBasicErrorInfo(i, &ErrorInfo);

    // Get error description and source through the IErrorInfo interface
    // pointer on a particular record.
    pErrorRecords->GetErrorInfo(i, MYLOCALEID, &pErrorInfoRec);
    BSTR bstrDescriptionOfError = NULL;
    BSTR bstrSourceOfError = NULL;

    pErrorInfoRec->GetDescription(&bstrDescriptionOfError); 
    pErrorInfoRec->GetSource(&bstrSourceOfError);

    // At this point, you could call GetCustomErrorObject and query for
    // additional interfaces to determine what else happened.

    wprintf(
     OLESTR("HRESULT: %lx, Minor Code: %lu, Source: %s, Description: %s"),
     ErrorInfo.hrError,
     ErrorInfo.dwMinor,
     bstrSourceOfError,
     bstrDescriptionOfError);

    // Free the resources.
    SysFreeString(bstrDescriptionOfError);
    SysFreeString(bstrSourceOfError);
    pErrorInfoRec->Release();
   }

   // Release the error object.
   pErrorInfo->Release();
   pErrorRecords->Release();
  }
 }
 return (hrErr);
};