//////////////////////////////////////////////////////////////////////// // 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) { //IErrorRecords may not be supported on the existing error object. //Some other things could have posted an error object (VB) for example... QTESTC(hr = pIErrorInfo->QueryInterface(IID_IErrorRecords, (void**)ppIErrorRecords)); XTESTC(hr = (*ppIErrorRecords)->GetRecordCount(pcRecords)); } CLEANUP: SAFE_RELEASE(pISupportErrorInfo); SAFE_RELEASE(pIErrorInfo); return hr; }
/******************************************************************** 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; }
// Info: Gets both unrestricted and restricted error info // Parameters: scriptContext - the script context // pexcepinfo - the exception info of the error (unrestricted) // proerrstr - the winrt specific error strings (restricted) // pperrinfo - the IErrorInfo object // Returns: Failed HRESULT - if GetErrorInfo or QI fail // Success - otherwise HRESULT JavascriptErrorDebug::GetExcepAndErrorInfo(ScriptContext* scriptContext, HRESULT hrReturned, EXCEPINFO *pexcepinfo, RestrictedErrorStrings * proerrstr, IErrorInfo ** pperrinfo) { HRESULT hr; HRESULT hrResult; bool errorInfoMatch = false; memset(pexcepinfo, 0, sizeof(*pexcepinfo)); memset(proerrstr, 0, sizeof(*proerrstr)); *pperrinfo = nullptr; // GetErrorInfo returns S_FALSE if there is no rich error info // and S_OK if there is. IErrorInfo * perrinfo; if(NOERROR != (hr = GetErrorInfo(0L, &perrinfo))) { return hr; } // Fill Exception info perrinfo->GetSource(&pexcepinfo->bstrSource); perrinfo->GetDescription(&pexcepinfo->bstrDescription); perrinfo->GetHelpFile(&pexcepinfo->bstrHelpFile); perrinfo->GetHelpContext(&pexcepinfo->dwHelpContext); // Initialize restricted strings proerrstr->restrictedErrStr = nullptr; proerrstr->referenceStr = nullptr; proerrstr->capabilitySid = nullptr; BSTR bstrErr = nullptr; BSTR bstrRestrictedErr = nullptr; BSTR bstrCapabilitySid = nullptr; BSTR bstrReference = nullptr; IRestrictedErrorInfo * pROErrorInfo = nullptr; _Exception * pCLRException = nullptr; hr = perrinfo->QueryInterface(__uuidof(IRestrictedErrorInfo), reinterpret_cast<void**>(&pROErrorInfo)); if (SUCCEEDED(hr)) { // Get restricted error strings from IRestrictedErrorInfo HRESULT hrErr = S_OK; hrResult = pROErrorInfo->GetErrorDetails(&bstrErr, &hrErr, &bstrRestrictedErr, &bstrCapabilitySid); if (SUCCEEDED(hrResult)) { errorInfoMatch = (hrErr == hrReturned); if (errorInfoMatch) { if (nullptr != bstrRestrictedErr) { proerrstr->restrictedErrStr = bstrRestrictedErr; bstrRestrictedErr = nullptr; } if (nullptr != bstrCapabilitySid) { proerrstr->capabilitySid = bstrCapabilitySid; bstrCapabilitySid = nullptr; } } } hrResult = pROErrorInfo->GetReference(&bstrReference); if (SUCCEEDED(hrResult) && errorInfoMatch) { if (nullptr != bstrReference) { proerrstr->referenceStr = bstrReference; bstrReference = nullptr; } } } else { hr = perrinfo->QueryInterface(__uuidof(_Exception), reinterpret_cast<void**>(&pCLRException)); if(FAILED(hr)) { perrinfo->Release(); return hr; } hrResult = pCLRException->get_Message(&bstrRestrictedErr); if (SUCCEEDED(hrResult)) { errorInfoMatch = true; if (nullptr != bstrRestrictedErr) { proerrstr->restrictedErrStr = bstrRestrictedErr; bstrRestrictedErr = nullptr; } } } if (nullptr != bstrErr) { SysFreeString(bstrErr); bstrErr = nullptr; } if (nullptr != bstrRestrictedErr) { SysFreeString(bstrRestrictedErr); bstrRestrictedErr = nullptr; } if (nullptr != bstrCapabilitySid) { SysFreeString(bstrCapabilitySid); bstrCapabilitySid = nullptr; } if (nullptr != bstrReference) { SysFreeString(bstrReference); bstrReference = nullptr; } if (!errorInfoMatch) { if (nullptr != pexcepinfo->bstrSource) { SysFreeString(pexcepinfo->bstrSource); pexcepinfo->bstrSource = nullptr; } if (nullptr != pexcepinfo->bstrDescription) { SysFreeString(pexcepinfo->bstrDescription); pexcepinfo->bstrDescription = nullptr; } if (nullptr != pexcepinfo->bstrHelpFile) { SysFreeString(pexcepinfo->bstrHelpFile); pexcepinfo->bstrHelpFile = nullptr; } perrinfo->Release(); perrinfo = nullptr; hr = S_FALSE; } if (nullptr != pROErrorInfo) { pROErrorInfo->Release(); } if (nullptr != pCLRException) { pCLRException->Release(); } *pperrinfo = perrinfo; return hr; }
//*************************************************************************** // Function: PrintError // Purpose: Formats and prints the error message //*************************************************************************** void PrintError(char *pszFailureReason, SCODE psc, DWORD dwMode) { VARIANT varString; SCODE sc; IWbemClassObject *pErrorObject = NULL; IErrorInfo* pEI = NULL; fprintf(stdout, "%s\n", pszFailureReason); fprintf(stdout, "FunctionReturn: %S(0x%08lx)\n", WbemErrorString(psc), psc); if (GetErrorInfo(0, &pEI) == S_OK) { pEI->QueryInterface(IID_IWbemClassObject, (void**)&pErrorObject); pEI->Release(); } if (pErrorObject != NULL) { VariantInit(&varString); if (dwMode == ERROR_MODE_PRINTFIELDS) { if (pErrorObject->InheritsFrom(L"__NotifyStatus") != WBEM_NO_ERROR) { fprintf(stdout, "Unrecognized Error Object type\n"); } else if (pErrorObject->InheritsFrom(L"__ExtendedStatus") == WBEM_NO_ERROR) { sc = pErrorObject->Get(L"Description", 0L, &varString, NULL, NULL); if (sc != S_OK) { fprintf(stdout, "Can't get Description: %d\n", sc); } else if (V_VT(&varString) == VT_BSTR) { FWPRINTF(stdout, L"Description: %wS\n", V_BSTR(&varString)); } VariantClear(&varString); pErrorObject->Get(L"Operation", 0L, &varString, NULL, NULL); if (sc != S_OK) { fprintf(stdout, "Can't get Operation: %d\n", sc); } else if (V_VT(&varString) == VT_BSTR) { FWPRINTF(stdout, L"Operation: %wS\n", V_BSTR(&varString)); } VariantClear(&varString); pErrorObject->Get(L"ParameterInfo", 0L, &varString, NULL, NULL); if (sc != S_OK) { fprintf(stdout, "Can't get ParameterInfo: %d\n", sc); } else if (V_VT(&varString) == VT_BSTR) { FWPRINTF(stdout, L"ParameterInfo: %wS\n", V_BSTR(&varString)); } VariantClear(&varString); pErrorObject->Get(L"ProviderName", 0L, &varString, NULL, NULL); if (sc != S_OK) { fprintf(stdout, "Can't get ProviderName: %d\n", sc); } else if (V_VT(&varString) == VT_BSTR) { FWPRINTF(stdout, L"ProviderName: %wS\n", V_BSTR(&varString)); } VariantClear(&varString); } } else { BSTR bstrObjectText = NULL; if (SUCCEEDED(pErrorObject->GetObjectText(0, &bstrObjectText))) { fprintf(stdout, "%wS", bstrObjectText); SysFreeString(bstrObjectText); } } RELEASE(pErrorObject); } }
//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; }