ERROR.CPP
//----------------------------------------------------------------------------- 
// Microsoft OLE DB TABLECOPY Sample 
// Copyright 1996 - 1998 Microsoft Corporation. 
// 
// @doc 
// 
// @module ERROR.CPP 
// 
//----------------------------------------------------------------------------- 
 
//////////////////////////////////////////////////////////////////////// 
// Includes 
// 
//////////////////////////////////////////////////////////////////////// 
 
#define OLEDBVER 0x0200 
 
#include "WinMain.h" 
#include "Error.h" 
 
#include <olectl.h>  // IConnectionPoints interface 
 
 
//////////////////////////////////////////////////////////////////////// 
// Defines 
// 
//////////////////////////////////////////////////////////////////////// 
 
//Displays values like VALUE as   VALUE , L"VALUE" 
#define VALUE_WCHAR(value) value, L#value 
 
 
typedef struct _INTERFACEMAP 
{ 
const IID*pIID;// The sql type value 
WCHAR*pwszInterface;// Name for display 
} INTERFACEMAP; 
 
 
INTERFACEMAP rgInterfaceMap[] = 
{ 
//IUnknown 
& VALUE_WCHAR(IID_IUnknown), 
 
//TEnumerator 
& VALUE_WCHAR(IID_IParseDisplayName), 
& VALUE_WCHAR(IID_ISourcesRowset), 
 
//TDataSource 
& VALUE_WCHAR(IID_IDBInitialize), 
& VALUE_WCHAR(IID_IDBProperties), 
& VALUE_WCHAR(IID_IDBCreateSession), 
& VALUE_WCHAR(IID_IDBInfo), 
& VALUE_WCHAR(IID_IPersist), 
& VALUE_WCHAR(IID_IDBDataSourceAdmin), 
& VALUE_WCHAR(IID_IPersistFile), 
& VALUE_WCHAR(IID_ISupportErrorInfo), 
 
//TSession 
& VALUE_WCHAR(IID_IGetDataSource), 
& VALUE_WCHAR(IID_IOpenRowset), 
& VALUE_WCHAR(IID_ISessionProperties), 
& VALUE_WCHAR(IID_IDBCreateCommand), 
& VALUE_WCHAR(IID_IDBSchemaRowset), 
& VALUE_WCHAR(IID_IIndexDefinition), 
& VALUE_WCHAR(IID_ITableDefinition), 
& VALUE_WCHAR(IID_ITransactionJoin), 
& VALUE_WCHAR(IID_ITransactionLocal), 
& VALUE_WCHAR(IID_ITransactionObject), 
 
//TCommand 
& VALUE_WCHAR(IID_IAccessor), 
& VALUE_WCHAR(IID_IColumnsInfo), 
& VALUE_WCHAR(IID_ICommand), 
& VALUE_WCHAR(IID_ICommandProperties), 
& VALUE_WCHAR(IID_ICommandText), 
& VALUE_WCHAR(IID_IConvertType), 
& VALUE_WCHAR(IID_IColumnsRowset), 
& VALUE_WCHAR(IID_ICommandPrepare), 
& VALUE_WCHAR(IID_ICommandWithParameters), 
 
//TRowset 
& VALUE_WCHAR(IID_IRowset), 
& VALUE_WCHAR(IID_IRowsetInfo), 
& VALUE_WCHAR(IID_IColumnsRowset), 
& VALUE_WCHAR(IID_IConnectionPointContainer), 
& VALUE_WCHAR(IID_IRowsetChange), 
& VALUE_WCHAR(IID_IRowsetIdentity), 
& VALUE_WCHAR(IID_IRowsetLocate), 
& VALUE_WCHAR(IID_IRowsetResynch), 
& VALUE_WCHAR(IID_IRowsetScroll), 
& VALUE_WCHAR(IID_IRowsetUpdate), 
 
//TIndex 
& VALUE_WCHAR(IID_IRowsetIndex), 
 
//TError 
& VALUE_WCHAR(IID_IErrorInfo), 
& VALUE_WCHAR(IID_IErrorRecords), 
& VALUE_WCHAR(IID_ISQLErrorInfo), 
}; 
 
 
//////////////////////////////////////////////////////////////////////// 
// WCHAR* GetInterfaceName 
// 
//////////////////////////////////////////////////////////////////////// 
WCHAR* GetInterfaceName(REFIID riid) 
{ 
for(ULONG i=0; i<NUMELE(rgInterfaceMap); i++) 
{ 
if(riid == *(rgInterfaceMap[i].pIID))  
return rgInterfaceMap[i].pwszInterface; 
} 
 
//Otherwise just return IUnknown 
return rgInterfaceMap[0].pwszInterface; 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
// ERRORMAP 
// 
//////////////////////////////////////////////////////////////////////// 
typedef struct _ERRORMAP 
{ 
HRESULThr;// HRESULT 
WCHAR*pwszError;// Name 
} ERRORMAP; 
 
ERRORMAP rgErrorMap[] = 
{ 
 VALUE_WCHAR(NULL), 
 
 //System Errors 
 VALUE_WCHAR(E_FAIL), 
 VALUE_WCHAR(E_INVALIDARG), 
 VALUE_WCHAR(E_OUTOFMEMORY), 
 VALUE_WCHAR(E_NOINTERFACE), 
 VALUE_WCHAR(REGDB_E_CLASSNOTREG), 
 VALUE_WCHAR(CLASS_E_NOAGGREGATION), 
 
 //OLE DB Errors 
     VALUE_WCHAR(DB_E_BADACCESSORHANDLE), 
     VALUE_WCHAR(DB_E_ROWLIMITEXCEEDED), 
     VALUE_WCHAR(DB_E_READONLYACCESSOR), 
     VALUE_WCHAR(DB_E_SCHEMAVIOLATION), 
     VALUE_WCHAR(DB_E_BADROWHANDLE), 
     VALUE_WCHAR(DB_E_OBJECTOPEN), 
     VALUE_WCHAR(DB_E_CANTCONVERTVALUE), 
     VALUE_WCHAR(DB_E_BADBINDINFO), 
     VALUE_WCHAR(DB_SEC_E_PERMISSIONDENIED), 
     VALUE_WCHAR(DB_E_NOTAREFERENCECOLUMN), 
     VALUE_WCHAR(DB_E_NOCOMMAND), 
     VALUE_WCHAR(DB_E_BADBOOKMARK), 
     VALUE_WCHAR(DB_E_BADLOCKMODE), 
     VALUE_WCHAR(DB_E_PARAMNOTOPTIONAL), 
     VALUE_WCHAR(DB_E_BADCOLUMNID), 
     VALUE_WCHAR(DB_E_BADRATIO), 
     VALUE_WCHAR(DB_E_ERRORSINCOMMAND), 
     VALUE_WCHAR(DB_E_CANTCANCEL), 
     VALUE_WCHAR(DB_E_DIALECTNOTSUPPORTED), 
     VALUE_WCHAR(DB_E_DUPLICATEDATASOURCE), 
     VALUE_WCHAR(DB_E_CANNOTRESTART), 
     VALUE_WCHAR(DB_E_NOTFOUND), 
     VALUE_WCHAR(DB_E_CANNOTFREE), 
     VALUE_WCHAR(DB_E_NEWLYINSERTED), 
     VALUE_WCHAR(DB_E_UNSUPPORTEDCONVERSION), 
     VALUE_WCHAR(DB_E_BADSTARTPOSITION), 
     VALUE_WCHAR(DB_E_NOTREENTRANT), 
     VALUE_WCHAR(DB_E_ERRORSOCCURRED), 
     VALUE_WCHAR(DB_E_NOAGGREGATION), 
     VALUE_WCHAR(DB_E_DELETEDROW), 
     VALUE_WCHAR(DB_E_CANTFETCHBACKWARDS), 
     VALUE_WCHAR(DB_E_ROWSNOTRELEASED), 
     VALUE_WCHAR(DB_E_BADSTORAGEFLAG), 
     VALUE_WCHAR(DB_E_BADSTATUSVALUE), 
     VALUE_WCHAR(DB_E_CANTSCROLLBACKWARDS), 
     VALUE_WCHAR(DB_E_MULTIPLESTATEMENTS), 
     VALUE_WCHAR(DB_E_INTEGRITYVIOLATION), 
     VALUE_WCHAR(DB_E_ABORTLIMITREACHED), 
     VALUE_WCHAR(DB_E_ROWSETINCOMMAND), 
     VALUE_WCHAR(DB_E_DUPLICATEINDEXID), 
     VALUE_WCHAR(DB_E_NOINDEX), 
     VALUE_WCHAR(DB_E_INDEXINUSE), 
     VALUE_WCHAR(DB_E_NOTABLE), 
     VALUE_WCHAR(DB_E_CONCURRENCYVIOLATION), 
     VALUE_WCHAR(DB_E_BADCOPY), 
     VALUE_WCHAR(DB_E_BADPRECISION), 
     VALUE_WCHAR(DB_E_BADSCALE), 
     VALUE_WCHAR(DB_E_BADID), 
     VALUE_WCHAR(DB_E_BADTYPE), 
     VALUE_WCHAR(DB_E_DUPLICATECOLUMNID), 
     VALUE_WCHAR(DB_E_DUPLICATETABLEID), 
     VALUE_WCHAR(DB_E_TABLEINUSE), 
     VALUE_WCHAR(DB_E_NOLOCALE), 
     VALUE_WCHAR(DB_E_BADRECORDNUM), 
     VALUE_WCHAR(DB_E_BOOKMARKSKIPPED), 
     VALUE_WCHAR(DB_E_BADPROPERTYVALUE), 
     VALUE_WCHAR(DB_E_INVALID), 
     VALUE_WCHAR(DB_E_BADACCESSORFLAGS), 
     VALUE_WCHAR(DB_E_BADSTORAGEFLAGS), 
     VALUE_WCHAR(DB_E_BYREFACCESSORNOTSUPPORTED), 
     VALUE_WCHAR(DB_E_NULLACCESSORNOTSUPPORTED), 
     VALUE_WCHAR(DB_E_NOTPREPARED), 
     VALUE_WCHAR(DB_E_BADACCESSORTYPE), 
     VALUE_WCHAR(DB_E_WRITEONLYACCESSOR), 
     VALUE_WCHAR(DB_SEC_E_AUTH_FAILED), 
     VALUE_WCHAR(DB_E_CANCELED), 
     VALUE_WCHAR(DB_E_BADSOURCEHANDLE), 
     VALUE_WCHAR(DB_E_PARAMUNAVAILABLE), 
     VALUE_WCHAR(DB_E_ALREADYINITIALIZED), 
     VALUE_WCHAR(DB_E_NOTSUPPORTED), 
     VALUE_WCHAR(DB_E_MAXPENDCHANGESEXCEEDED), 
     VALUE_WCHAR(DB_E_BADORDINAL), 
     VALUE_WCHAR(DB_E_PENDINGCHANGES), 
     VALUE_WCHAR(DB_E_DATAOVERFLOW), 
     VALUE_WCHAR(DB_E_BADHRESULT), 
     VALUE_WCHAR(DB_E_BADLOOKUPID), 
     VALUE_WCHAR(DB_E_BADDYNAMICERRORID), 
     VALUE_WCHAR(DB_E_PENDINGINSERT), 
     VALUE_WCHAR(DB_E_BADCONVERTFLAG), 
     VALUE_WCHAR(DB_S_ROWLIMITEXCEEDED), 
     VALUE_WCHAR(DB_S_COLUMNTYPEMISMATCH), 
     VALUE_WCHAR(DB_S_TYPEINFOOVERRIDDEN), 
     VALUE_WCHAR(DB_S_BOOKMARKSKIPPED), 
     VALUE_WCHAR(DB_S_ENDOFROWSET), 
     VALUE_WCHAR(DB_S_COMMANDREEXECUTED), 
     VALUE_WCHAR(DB_S_BUFFERFULL), 
     VALUE_WCHAR(DB_S_NORESULT), 
     VALUE_WCHAR(DB_S_CANTRELEASE), 
     VALUE_WCHAR(DB_S_DIALECTIGNORED), 
     VALUE_WCHAR(DB_S_UNWANTEDPHASE), 
     VALUE_WCHAR(DB_S_UNWANTEDREASON), 
     VALUE_WCHAR(DB_S_COLUMNSCHANGED), 
     VALUE_WCHAR(DB_S_ERRORSRETURNED), 
     VALUE_WCHAR(DB_S_BADROWHANDLE), 
     VALUE_WCHAR(DB_S_DELETEDROW), 
     VALUE_WCHAR(DB_S_STOPLIMITREACHED), 
     VALUE_WCHAR(DB_S_LOCKUPGRADED), 
     VALUE_WCHAR(DB_S_PROPERTIESCHANGED), 
     VALUE_WCHAR(DB_S_ERRORSOCCURRED), 
     VALUE_WCHAR(DB_S_PARAMUNAVAILABLE), 
     VALUE_WCHAR(DB_S_MULTIPLECHANGES), 
}; 
 
 
//////////////////////////////////////////////////////////////////////// 
// WCHAR* GetErrorName 
// 
//////////////////////////////////////////////////////////////////////// 
WCHAR* GetErrorName(HRESULT hr) 
{ 
for(ULONG i=0; i<NUMELE(rgErrorMap); i++) 
{ 
if(hr == rgErrorMap[i].hr)  
return rgErrorMap[i].pwszError; 
} 
 
//Otherwise just return Unknown 
return rgErrorMap[0].pwszError; 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
// HRESULT GetErrorRecords 
// 
// Get the error message generated by an OLE DB object 
///////////////////////////////////////////////////////////////////////////// 
HRESULT GetErrorRecords(ULONG* pcRecords, IErrorRecords** ppIErrorRecords) 
{ 
ASSERT(pcRecords && ppIErrorRecords); 
HRESULT hr; 
 
//NULL output params 
*pcRecords = 0; 
*ppIErrorRecords = NULL; 
 
ISupportErrorInfo* pISupportErrorInfo = NULL; 
IErrorInfo* pIErrorInfo = NULL; 
 
//See if this interface supports ErrorInfo 
//If not there is no reason to display any error 
if((hr = GetErrorInfo(0, &pIErrorInfo))==S_OK && pIErrorInfo) 
{ 
TESTC(hr = pIErrorInfo->QueryInterface(IID_IErrorRecords, (void**)ppIErrorRecords)); 
TESTC(hr = (*ppIErrorRecords)->GetRecordCount(pcRecords)); 
} 
 
CLEANUP: 
SAFE_RELEASE(pISupportErrorInfo); 
SAFE_RELEASE(pIErrorInfo); 
return hr; 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
// HRESULT GetErrorInfo 
// 
// Get the error message generated by an OLE DB object 
///////////////////////////////////////////////////////////////////////////// 
HRESULT GetErrorInfo(BSTR* pBstr) 
{ 
ASSERT(pBstr); 
HRESULT hr; 
 
ULONG cRecords = 0; 
IErrorRecords* pIErrorRecords = NULL; 
 
//Try to display Extened ErrorInfo 
if((hr = GetErrorRecords(&cRecords, &pIErrorRecords))==S_OK)  
{ 
//GetErrorInfo, just for the first error, (ie: 0) 
TESTC(hr = GetErrorInfo(0, pIErrorRecords, pBstr)); 
} 
 
CLEANUP: 
SAFE_RELEASE(pIErrorRecords); 
return hr; 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
// HRESULT GetErrorInfo 
// 
// Get the error message generated by an OLE DB object 
///////////////////////////////////////////////////////////////////////////// 
HRESULT GetErrorInfo(ULONG iRecord, IErrorRecords* pIErrorRecords, BSTR* pBstr) 
{ 
ASSERT(pBstr); 
HRESULT hr = S_OK; 
 
IErrorInfo* pIErrorInfo = NULL; 
LCID lcid = GetSystemDefaultLCID();  
 
//Get the Error Records 
if(pIErrorRecords) 
{ 
//If there is ErrorInfo, GetSQLInfo for the desired record 
TESTC(hr = pIErrorRecords->GetErrorInfo(iRecord,lcid,&pIErrorInfo)); 
 
//If there was a CustomErrorObject 
if(pIErrorInfo) 
TESTC(hr = pIErrorInfo->GetDescription(pBstr)); 
} 
 
CLEANUP: 
SAFE_RELEASE(pIErrorInfo); 
return hr; 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
// HRESULT GetSqlErrorInfo 
// 
// Get the error message generated by an OLE DB object 
///////////////////////////////////////////////////////////////////////////// 
HRESULT GetSqlErrorInfo(BSTR* pBstr) 
{ 
ASSERT(pBstr); 
HRESULT hr; 
 
ULONG cRecords = 0; 
IErrorRecords* pIErrorRecords = NULL; 
 
//Get the Error Records 
if((hr = GetErrorRecords(&cRecords, &pIErrorRecords))==S_OK) 
{ 
//Deletegate to SqlErrorInfo 
//Just get the first record 
TESTC(hr = GetSqlErrorInfo(0, pIErrorRecords, pBstr)); 
} 
 
 
CLEANUP: 
SAFE_RELEASE(pIErrorRecords); 
return hr; 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
// HRESULT GetSqlErrorInfo 
// 
// Get the error message generated by an OLE DB object 
///////////////////////////////////////////////////////////////////////////// 
HRESULT GetSqlErrorInfo(ULONG iRecord, IErrorRecords* pIErrorRecords, BSTR* pBstr) 
{ 
ASSERT(pBstr); 
HRESULT hr = S_OK; 
 
ISQLErrorInfo* pISQLErrorInfo = NULL; 
LONG lNativeError = 0; 
 
//Get the Error Records 
if(pIErrorRecords) 
{ 
//If there is ErrorInfo, GetSQLInfo for the desired record 
TESTC(hr = pIErrorRecords->GetCustomErrorObject(iRecord, IID_ISQLErrorInfo, (IUnknown**)&pISQLErrorInfo)); 
 
//If there was a CustomErrorObject 
if(pISQLErrorInfo) 
hr = pISQLErrorInfo->GetSQLInfo(pBstr, &lNativeError); 
} 
 
CLEANUP: 
SAFE_RELEASE(pISQLErrorInfo); 
return hr; 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
// HRESULT DisplayAllErrors 
// 
///////////////////////////////////////////////////////////////////////////// 
HRESULT DisplayAllErrors(HWND hWnd, HRESULT Actualhr, REFIID riid, WCHAR* pwsz) 
{ 
HRESULT hr = S_OK; 
 
ULONG cRecords = 0; 
IErrorRecords* pIErrorRecords = NULL; 
 
//Try to display Extened ErrorInfo 
if((hr = GetErrorRecords(&cRecords, &pIErrorRecords))==S_OK)  
{ 
hr = DisplayErrorRecords(hWnd, cRecords, pIErrorRecords); 
} 
//If not available, display MSG Box with info 
else 
{ 
//display the Error 
wMessageBox(hWnd, MB_ICONEXCLAMATION | MB_OK, wsz_ERRORINFO,  
L"Interface: %s\nResult: %x = %s\n\n%s\n",  
GetInterfaceName(riid), Actualhr, GetErrorName(Actualhr), pwsz ? pwsz : L""); 
} 
 
 
SAFE_RELEASE(pIErrorRecords); 
return hr; 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
// HRESULT DisplayErrorRecords 
// 
///////////////////////////////////////////////////////////////////////////// 
HRESULT DisplayErrorRecords(HWND hWnd) 
{ 
HRESULT hr; 
 
ULONG cRecords = 0; 
IErrorRecords* pIErrorRecords = NULL; 
 
//Get the Error Records 
if((hr = GetErrorRecords(&cRecords, &pIErrorRecords))==S_OK)  
hr = DisplayErrorRecords(hWnd, cRecords, pIErrorRecords); 
 
SAFE_RELEASE(pIErrorRecords); 
return hr; 
} 
 
 
 
//////////////////////////////////////////////////////////////////////// 
// HRESULT DisplayErrorRecords 
// 
///////////////////////////////////////////////////////////////////////////// 
HRESULT DisplayErrorRecords(HWND hWnd, ULONG cRecords, IErrorRecords* pIErrorRecords) 
{ 
HRESULT hr = S_OK; 
 
IErrorInfo* pIErrorInfo = NULL; 
BSTR bstrErrorInfo = NULL; 
BSTR bstrSQLInfo = NULL; 
 
LCID lcid = GetSystemDefaultLCID();  
 
//Get the Error Records 
if(cRecords && pIErrorRecords) 
{ 
WCHAR wszError[MAX_QUERY_LEN*2]; 
LONG lNativeError = 0; 
ERRORINFO ErrorInfo; 
 
//Loop through the records 
for(ULONG i=0; i<cRecords; i++) 
{ 
//GetErrorInfo 
TESTC(hr = pIErrorRecords->GetErrorInfo(i,lcid,&pIErrorInfo)); 
 
//Get the Description 
TESTC(hr = pIErrorInfo->GetDescription(&bstrErrorInfo)); 
 
//Get the Basic ErrorInfo 
TESTC(hr = pIErrorRecords->GetBasicErrorInfo(i,&ErrorInfo)); 
 
//Get the SQL Info 
TESTC(hr = GetSqlErrorInfo(i, pIErrorRecords, &bstrSQLInfo)); 
 
//Display the Error 
if(bstrSQLInfo) 
swprintf(wszError,  L"Interface: %s\nResult: %x = %s\n\nIErrorInfo: [%s] %s\n", GetInterfaceName(ErrorInfo.iid), ErrorInfo.hrError, GetErrorName(ErrorInfo.hrError), bstrSQLInfo, bstrErrorInfo); 
else 
swprintf(wszError,  L"Interface: %s\nResult: %x = %s\n\nIErrorInfo: %s\n", GetInterfaceName(ErrorInfo.iid), ErrorInfo.hrError, GetErrorName(ErrorInfo.hrError), bstrErrorInfo); 
 
wMessageBox(hWnd, MB_ICONEXCLAMATION | MB_OK, wsz_ERRORINFO, wszError); 
 
SAFE_RELEASE(pIErrorInfo); 
SAFE_SYSFREE(bstrErrorInfo); 
SAFE_SYSFREE(bstrSQLInfo); 
} 
} 
 
 
CLEANUP: 
SAFE_RELEASE(pIErrorInfo); 
SAFE_SYSFREE(bstrErrorInfo); 
SAFE_SYSFREE(bstrSQLInfo); 
return hr; 
}