SQLOLEDB Example: Retrieving Error Information

This example obtains information from the various error interfaces exposed by SQLOLEDB.

////////////////////////////////////////////////////////////////////////
// DumpErrorInfo queries SQLOLEDB error interfaces, retrieving available
// status or error information.
void DumpErrorInfo
  (
  IUnknown* pObjectWithError,
  REFIID IID_InterfaceWithError
  )
  {
  
  // Interfaces used in the example.
  IErrorInfo*     pIErrorInfoAll    = NULL;
  IErrorInfo*     pIErrorInfoRecord   = NULL;
  IErrorRecords*    pIErrorRecords    = NULL;
  ISupportErrorInfo*  pISupportErrorInfo  = NULL;
  ISQLErrorInfo*    pISQLErrorInfo    = NULL;
  ISQLServerErrorInfo*  pISQLServerErrorInfo  = NULL;
  
  // Number of error records.
  ULONG       nRecs;
  ULONG       nRec;
  
  // Basic error information from GetBasicErrorInfo.
  ERRORINFO     errorinfo;
  
  // IErrorInfo values.
  BSTR        bstrDescription;
  BSTR        bstrSource;
  
  // ISQLErrorInfo parameters.
  BSTR        bstrSQLSTATE;
  LONG        lNativeError;
  
  // ISQLServerErrorInfo parameter pointers.
  SSERRORINFO*    pSSErrorInfo = NULL;
  OLECHAR*      pSSErrorStrings = NULL;
  
  // Hard-code an American English locale for the example.
  DWORD       MYLOCALEID = 0x0409;
  
  // Only try to obtain error information if the interface supports
  // it.
  if (FAILED(pObjectWithError->QueryInterface(IID_ISupportErrorInfo,
    (void**) &pISupportErrorInfo)) ||
    FAILED(pISupportErrorInfo->
    InterfaceSupportsErrorInfo(IID_InterfaceWithError)))
    {
    wprintf(L"ErrorInfo interface not supported on object");
    return;
    }
  
  // Don't bother to test the return of GetErrorInfo. It can succeed
  // AND return a NULL pointer in pIErrorInfoAll. Simply test the
  // pointer.
  GetErrorInfo(0, &pIErrorInfoAll);
  
  if (pIErrorInfoAll != NULL)
    {
    // Test to see if it's a valid OLE DB IErrorInfo exposing a list
    // of records.
    if (SUCCEEDED(pIErrorInfoAll->QueryInterface(IID_IErrorRecords,
    (void**) &pIErrorRecords)))
    {
    pIErrorRecords->GetRecordCount(&nRecs);
  
    // Within each record, retrieve information from each
    // of the defined interfaces.
    for (nRec = 0; nRec < nRecs; nRec++)
      {
      // From IErrorRecords, get the HRESULT and a reference
      // to the ISQLErrorInfo interface.
      pIErrorRecords->GetBasicErrorInfo(nRec, &errorinfo);
      pIErrorRecords->GetCustomErrorObject(nRec,
        IID_ISQLErrorInfo, (IUnknown**) &pISQLErrorInfo);
  
      // Display the HRESULT, then use the ISQLErrorInfo.
      wprintf(L"HRESULT:\t%#X\n", errorinfo.hrError);
  
      if (pISQLErrorInfo != NULL)
        {
        pISQLErrorInfo->GetSQLInfo(&bstrSQLSTATE, 
        &lNativeError);
  
        // Display the SQLSTATE and native error values.
        wprintf(L"SQLSTATE:\t%s\nNative Error:\t%ld\n",
        bstrSQLSTATE, lNativeError);
        
        // SysFree BSTR references.
        SysFreeString(bstrSQLSTATE);
  
        // Get the ISQLServerErrorInfo interface from
        // ISQLErrorInfo before releasing the reference.
        pISQLErrorInfo->QueryInterface(
        IID_ISQLServerErrorInfo,
        (void**) &pISQLServerErrorInfo);
  
        pISQLErrorInfo->Release();
        }
  
      // Test to ensure the reference is valid, then
      // get error information from ISQLServerErrorInfo.
      if (pISQLServerErrorInfo != NULL)
        {
        pISQLServerErrorInfo->GetErrorInfo(&pSSErrorInfo,
        &pSSErrorStrings);
  
        // ISQLServerErrorInfo::GetErrorInfo succeeds
        // even when it has nothing to return. Test the
        // pointers before using.
        if (pSSErrorInfo)
        {
        // Display the state and severity from the
        // returned information. The error message comes
        // from IErrorInfo::GetDescription.
        wprintf(L"Error state:\t%d\nSeverity:\t%d\n",
            pSSErrorInfo->bState,
            pSSErrorInfo->bClass);
  
        // IMalloc::Free needed to release references
        // on returned values. For the example, assume
        // the g_pIMalloc pointer is valid.
        g_pIMalloc->Free(pSSErrorStrings);
        g_pIMalloc->Free(pSSErrorInfo);
        }
  
        pISQLServerErrorInfo->Release();
        }
  
      if (SUCCEEDED(pIErrorRecords->GetErrorInfo(nRec,
        MYLOCALEID, &pIErrorInfoRecord)))
        {
        // Get the source and description (error message)
        // from the record's IErrorInfo.
        pIErrorInfoRecord->GetSource(&bstrSource);
        pIErrorInfoRecord->GetDescription(&bstrDescription);
  
        if (bstrSource != NULL)
        {
        wprintf(L"Source:\t\t%s\n", bstrSource);
        SysFreeString(bstrSource);
        }
        if (bstrDescription != NULL)
        {
        wprintf(L"Error message:\t%s\n",
          bstrDescription);
        SysFreeString(bstrDescription);
        }
  
        pIErrorInfoRecord->Release();
        }
      }
  
    pIErrorRecords->Release();
    }
    else
    {
    // IErrorInfo is valid, get the source and
    // description to see what it is.
    pIErrorInfoAll->GetSource(&bstrSource);
    pIErrorInfoAll->GetDescription(&bstrDescription);
  
    if (bstrSource != NULL)
      {
      wprintf(L"Source:\t\t%s\n", bstrSource);
      SysFreeString(bstrSource);
      }
    if (bstrDescription != NULL)
      {
      wprintf(L"Error message:\t%s\n", bstrDescription);
      SysFreeString(bstrDescription);
      }
    }
  
    pIErrorInfoAll->Release();
    }
  else
    {
    wprintf(L"GetErrorInfo failed.");
    }
  
  pISupportErrorInfo->Release();
  
  return;
  }