int ErrorManager::GetNativeErrorCode(IErrorInfo *pIErrorInfo) { int iRetValue = 0; HRESULT hr = S_OK; IErrorRecords *pIErrorRecords = NULL; ERRORINFO errorInfo = { 0 }; IErrorInfo *pIErrorInfoRecord = NULL; try { hr = pIErrorInfo->QueryInterface(IID_IErrorRecords, (void **) &pIErrorRecords); if ( FAILED(hr) || NULL == pIErrorRecords ) return -1; pIErrorInfo->Release(); pIErrorInfo = NULL; ULONG ulNumErrorRecs = 0; hr = pIErrorRecords->GetRecordCount(&ulNumErrorRecs); if ( FAILED(hr) ) return -1; for (DWORD dwErrorIndex = 0; dwErrorIndex < ulNumErrorRecs; dwErrorIndex++) { hr = pIErrorRecords->GetBasicErrorInfo(dwErrorIndex, &errorInfo); if ( FAILED(hr) ) return -1; iRetValue = errorInfo.dwMinor; } } catch( ... ) { iRetValue = errorInfo.dwMinor; } if( pIErrorInfoRecord ) pIErrorInfoRecord->Release(); if ( pIErrorInfo ) pIErrorInfo->Release(); if ( pIErrorRecords ) pIErrorRecords->Release(); return iRetValue; }
/******************************************************************** SqlGetErrorInfo - gets error information from the last SQL function call NOTE: pbstrErrorSource and pbstrErrorDescription are optional ********************************************************************/ extern "C" HRESULT DAPI SqlGetErrorInfo( __in IUnknown* pObjectWithError, __in REFIID IID_InterfaceWithError, __in DWORD dwLocaleId, __out_opt BSTR* pbstrErrorSource, __out_opt BSTR* pbstrErrorDescription ) { HRESULT hr = S_OK; Assert(pObjectWithError); // interfaces needed to extract error information out ISupportErrorInfo* pISupportErrorInfo = NULL; IErrorInfo* pIErrorInfoAll = NULL; IErrorRecords* pIErrorRecords = NULL; IErrorInfo* pIErrorInfoRecord = NULL; // only ask for error information if the interface supports it. hr = pObjectWithError->QueryInterface(IID_ISupportErrorInfo,(void**)&pISupportErrorInfo); ExitOnFailure(hr, "No error information was found for object."); hr = pISupportErrorInfo->InterfaceSupportsErrorInfo(IID_InterfaceWithError); ExitOnFailure(hr, "InterfaceWithError is not supported for object with error"); // ignore the return of GetErrorInfo it can succeed and return a NULL pointer in pIErrorInfoAll anyway hr = ::GetErrorInfo(0, &pIErrorInfoAll); ExitOnFailure(hr, "failed to get error info"); if (S_OK == hr && pIErrorInfoAll) { // see if it's a valid OLE DB IErrorInfo interface that exposes a list of records hr = pIErrorInfoAll->QueryInterface(IID_IErrorRecords, (void**)&pIErrorRecords); if (SUCCEEDED(hr)) { ULONG cErrors = 0; pIErrorRecords->GetRecordCount(&cErrors); // get the error information for each record for (ULONG i = 0; i < cErrors; ++i) { hr = pIErrorRecords->GetErrorInfo(i, dwLocaleId, &pIErrorInfoRecord); if (SUCCEEDED(hr)) { if (pbstrErrorSource) { pIErrorInfoRecord->GetSource(pbstrErrorSource); } if (pbstrErrorDescription) { pIErrorInfoRecord->GetDescription(pbstrErrorDescription); } ReleaseNullObject(pIErrorInfoRecord); break; // TODO: return more than one error in the future! } } ReleaseNullObject(pIErrorRecords); } else // we have a simple error record { if (pbstrErrorSource) { pIErrorInfoAll->GetSource(pbstrErrorSource); } if (pbstrErrorDescription) { pIErrorInfoAll->GetDescription(pbstrErrorDescription); } } } else { hr = E_NOMOREITEMS; } LExit: ReleaseObject(pIErrorInfoRecord); ReleaseObject(pIErrorRecords); ReleaseObject(pIErrorInfoAll); ReleaseObject(pISupportErrorInfo); return hr; }
//Changed from //ms-help://MS.SSC.v35/MS.SSC.v35.EN/ssctechref/html/a25fafe1-e90a-4545-8836-749dd44135c0.htm CString SqlCeHelper::GetErrorsMessage() { static CString sErrIErrorInfo = L"IErrorInfo interface"; static CString sErrIErrorRecords = L"IErrorRecords interface"; static CString sErrRecordCount = L"error record count"; static CString sErrInfo = L"ERRORINFO structure"; static CString sErrStandardInfo = L"standard error info"; static CString sErrDescription = L"standard error description"; static CString sErrNoSource = L"error source"; HRESULT hr = S_OK; IErrorInfo *pIErrorInfo = NULL; IErrorRecords *pIErrorRecords = NULL; ERRORINFO errorInfo = { 0 }; IErrorInfo *pIErrorInfoRecord = NULL; CString message = L""; char str[255]; try { // This interface supports returning error information. // Get the error object from the system for the current // thread. hr = GetErrorInfo(0, &pIErrorInfo); if ( hr == S_FALSE ) { message = "No error occured."; return message; } if(FAILED(hr) || NULL == pIErrorInfo) throw sErrIErrorInfo; // The error records are retrieved from the IIErrorRecords // interface, which can be obtained from the IErrorInfo // interface. hr = pIErrorInfo->QueryInterface(IID_IErrorRecords, (void **) &pIErrorRecords); if ( FAILED(hr) || NULL == pIErrorRecords ) throw sErrIErrorRecords; // The IErrorInfo interface is no longer required because // we have the IErrorRecords interface, relase it. pIErrorInfo->Release(); pIErrorInfo = NULL; ULONG ulNumErrorRecs = 0; // Determine the number of records in this error object hr = pIErrorRecords->GetRecordCount(&ulNumErrorRecs); if ( FAILED(hr) ) throw sErrRecordCount; // Loop over each error record in the error object to display // information about each error. Errors are returned. for (DWORD dwErrorIndex = 0; dwErrorIndex < ulNumErrorRecs; dwErrorIndex++) { // Retrieve basic error information for this error. hr = pIErrorRecords->GetBasicErrorInfo(dwErrorIndex, &errorInfo); if ( FAILED(hr) ) throw sErrInfo; TCHAR szCLSID[64] = { 0 }; TCHAR szIID[64] = { 0 }; TCHAR szDISPID[64] = { 0 }; StringFromGUID2(errorInfo.clsid, (LPOLESTR)szCLSID, sizeof(szCLSID)); StringFromGUID2(errorInfo.iid, (LPOLESTR)szIID, sizeof(szIID)); sprintf(str, "HRESULT = %lx\n", errorInfo.hrError); message += str; sprintf(str, "clsid = %S\n", szCLSID); message += str; sprintf(str, "iid = %S\n", szIID); message += str; sprintf(str, "dispid = %ld\n", errorInfo.dispid); message += str; sprintf(str, "Native Error Code = %lx\n", errorInfo.dwMinor); message += str; // Retrieve standard error information for this error. hr = pIErrorRecords->GetErrorInfo(dwErrorIndex, NULL, &pIErrorInfoRecord); if ( FAILED(hr) ) throw sErrStandardInfo; BSTR bstrDescriptionOfError; BSTR bstrSourceOfError; // Get the description of the error. hr = pIErrorInfoRecord->GetDescription( &bstrDescriptionOfError); if ( FAILED(hr) ) throw sErrDescription; sprintf(str, "Description = %S\n", bstrDescriptionOfError); message += str; // Get the source of the error. hr = pIErrorInfoRecord->GetSource(&bstrSourceOfError); if ( FAILED(hr) ) throw sErrNoSource; sprintf(str, "Description = %S\n", bstrSourceOfError); message += str; // This interface variable will be used the next time // though this loop. In the last error case this interface // is no longer needed so we must release it. if(NULL != pIErrorInfoRecord) pIErrorInfoRecord->Release(); pIErrorInfoRecord = NULL; } } catch( CString& szMsg ) { message = L"Failed to retrieve " + szMsg; } if( pIErrorInfoRecord ) pIErrorInfoRecord->Release(); if ( pIErrorInfo ) pIErrorInfo->Release(); if ( pIErrorRecords ) pIErrorRecords->Release(); return message; }
//////////////////////////////////////////////////////////////////////// // myHandleResult // // This function is called as part of the XCHECK_HR macro; it takes a // HRESULT, which is returned by the method called in the XCHECK_HR // macro, and the file and line number where the method call was made. // If the method call failed, this function attempts to get and display // the extended error information for the call from the IErrorInfo, // IErrorRecords, and ISQLErrorInfo interfaces. // //////////////////////////////////////////////////////////////////////// HRESULT myHandleResult ( HRESULT hrReturned, LPCWSTR pwszFile, ULONG ulLine ) { HRESULT hr; IErrorInfo * pIErrorInfo = NULL; IErrorRecords * pIErrorRecords = NULL; ULONG cRecords; ULONG iErr; // If the method called as part of the XCHECK_HR macro failed, // we will attempt to get extended error information for the call if( FAILED(hrReturned) ) { // Obtain the current Error object, if any, by using the // OLE Automation GetErrorInfo function, which will give // us back an IErrorInfo interface pointer if successful hr = GetErrorInfo(0, &pIErrorInfo); // We've got the IErrorInfo interface pointer on the Error object if( SUCCEEDED(hr) && pIErrorInfo ) { // OLE DB extends the OLE Automation error model by allowing // Error objects to support the IErrorRecords interface; this // interface can expose information on multiple errors. hr = pIErrorInfo->QueryInterface(IID_IErrorRecords, (void**)&pIErrorRecords); if( SUCCEEDED(hr) ) { // Get the count of error records from the object CHECK_HR(hr = pIErrorRecords->GetRecordCount(&cRecords)); // Loop through the set of error records and // display the error information for each one for( iErr = 0; iErr < cRecords; iErr++ ) { myDisplayErrorRecord(hrReturned, iErr, pIErrorRecords, pwszFile, ulLine); } } // The object didn't support IErrorRecords; display // the error information for this single error else { myDisplayErrorInfo(hrReturned, pIErrorInfo, pwszFile, ulLine); } } // There was no Error object, so just display the HRESULT to the user else { wprintf(L"\nNo Error Info posted; HResult: 0x%08x\n" L"File: %s, Line: %d\n", hrReturned, pwszFile, ulLine); } } CLEANUP: if( pIErrorInfo ) pIErrorInfo->Release(); if( pIErrorRecords ) pIErrorRecords->Release(); return hrReturned; }