Partager via


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 must perform the following actions:

  1. If it does not already have an ISupportErrorInfo interface pointer on the component, the consumer can request one by calling QueryInterface on the component. ISupportErrorInfo must be supported by all components that create error objects.

  2. If it has not already determined whether the interface that returned the code supports error objects, the consumer can call ISupportErrorInfo::InterfaceSupportsErrorInfo and pass it the IID of the interface containing the method that returned the code. ISupportErrorInfo::InterfaceSupportsErrorInfo returns S_OK if the interface supports error objects (meaning the consumer should retrieve the current error object, if one exists) and returns 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. Call the GetErrorInfo function in the Automation DLL. This function returns an IErrorInfo interface pointer on the current error object (or NULL, if there is no current error object) and releases its reference count on the error object, transferring ownership of the error object to the consumer.

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

  5. Call 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, the consumer 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, because it applies to a specific record.) The consumer then calls methods using this pointer.

  6. Call Release on the error object to release all references to it.

The following code shows how a consumer might retrieve and use an OLE DB error object. (In the interest of clarity, some error checks and interface releases are not shown.)

#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;

   // (Not shown.) Error or warning occurs when calling method.
   // ...

   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);
};