//+--------------------------------------------------------------------------- // // Copyright (C) 1994, Microsoft Corporation. // // File: util.cxx // // Contents: global utilities and data for Content Index Test 'Q' // // History: 27-Dec-94 dlee Created from pieces of Q // 18-Jan-95 t-colinb Added suppport for COMMAND_GETLASTQUERY_FAILED // 02-Mar-95 t-colinb Removed unnecessary IMPLEMENT_UNWIND // //---------------------------------------------------------------------------- #include #pragma hdrstop #include // for IsCIError function #include //+--------------------------------------------------------------------------- // // Function: OpenFileFromPath // // Synopsis: Searches the current path for the specified file and // opens it for reading. // // Arguments: [wcsFile] -- filename to open // // History: 17-Jun-94 t-jeffc Created // //---------------------------------------------------------------------------- FILE * OpenFileFromPath( WCHAR const * wcsFile ) { unsigned int cwcPath = 256; XArray wcsPath( cwcPath ); WCHAR * wcsFilePart; for( ;; ) { DWORD rc = SearchPath( NULL, wcsFile, NULL, cwcPath, wcsPath.GetPointer(), &wcsFilePart ); if( rc == 0 ) return NULL; else if( rc >= cwcPath ) { delete [] wcsPath.Acquire(); cwcPath = rc + 1; wcsPath.Init( cwcPath ); } else break; } return _wfopen( wcsPath.GetPointer(), L"r" ); } //----------------------------------------------------------------------------- // // Function: GetOleDBErrorInfo // // Synopsis: Retrieves the secondary error from Ole DB error object // // Arguments: [pErrSrc] - Pointer to object that posted the error. // [riid] - Interface that posted the error. // [lcid] - Locale in which the text is desired. // [pErrorInfo] - Pointer to memory where ERRORINFO should be. // [ppIErrorInfo] - Holds the returning IErrorInfo. Caller should // release this. // // Notes: The caller should use the contents of *ppIErrorInfo only if the return // is >= 0 (SUCCEEDED(return value)) AND *ppIErrorInfo is not NULL. // // History: 05 May 1997 KrishnaN Created // //----------------------------------------------------------------------------- SCODE GetOleDBErrorInfo(IUnknown *pErrSrc, REFIID riid, LCID lcid, unsigned eDesiredDetail, ERRORINFO *pErrorInfo, IErrorInfo **ppIErrorInfo) { if (0 == pErrSrc || 0 == pErrorInfo || 0 == ppIErrorInfo) return E_INVALIDARG; *ppIErrorInfo = 0; SCODE sc = S_OK; XInterface xSupportErrorInfo; sc = pErrSrc->QueryInterface(IID_ISupportErrorInfo, xSupportErrorInfo.GetQIPointer()); if (FAILED(sc)) return sc; sc = xSupportErrorInfo->InterfaceSupportsErrorInfo(riid); if (FAILED(sc)) return sc; // // Get the current error object. Return if none exists. // XInterface xErrorInfo; sc = GetErrorInfo(0, (IErrorInfo **)xErrorInfo.GetQIPointer()); if ( 0 == xErrorInfo.GetPointer() ) return sc; // // Get the IErrorRecord interface and get the count of errors. // XInterface xErrorRecords; sc = xErrorInfo->QueryInterface(IID_IErrorRecords, xErrorRecords.GetQIPointer()); if (FAILED(sc)) return sc; ULONG cErrRecords; sc = xErrorRecords->GetRecordCount(&cErrRecords); if (0 == cErrRecords) return sc; // // We will first look for what the user desires. // If we can't find what they desire, then we // return the closest we can. // ULONG ulRecord = 0; long i; // This has to be signed to keep the loop test simple switch (eDesiredDetail) { case eMostGeneric: ulRecord = 0; break; case eDontCare: case eMostDetailed: ulRecord = cErrRecords - 1; break; case eMostDetailedOleDBError: // Find the last (starting from 0) non-CI error ulRecord = cErrRecords - 1; for (i = (long) cErrRecords - 1; i >= 0 ; i--) { xErrorRecords->GetBasicErrorInfo(i, pErrorInfo); // if it not a CI error, it is a Ole DB error if (!IsCIError(pErrorInfo->hrError)) { ulRecord = i; break; } } break; case eMostDetailedCIError: // Find the last (starting from 0) non-CI error ulRecord = cErrRecords - 1; for (i = (long) cErrRecords - 1; i >= 0 ; i--) { xErrorRecords->GetBasicErrorInfo(i, pErrorInfo); if (IsCIError(pErrorInfo->hrError)) { ulRecord = i; break; } } break; case eMostGenericOleDBError: // Find the first (starting from 0) non-CI error ulRecord = 0; for (i = 0; i < (long)cErrRecords; i++) { xErrorRecords->GetBasicErrorInfo(i, pErrorInfo); // if it not a CI error, it is a Ole DB error if (!IsCIError(pErrorInfo->hrError)) { ulRecord = i; break; } } break; case eMostGenericCIError: // Find the first (starting from 0) non-CI error ulRecord = 0; for (i = 0; i < (long)cErrRecords; i++) { xErrorRecords->GetBasicErrorInfo(i, pErrorInfo); // if it not a CI error, it is a Ole DB error if (IsCIError(pErrorInfo->hrError)) { ulRecord = i; break; } } break; default: Win4Assert(!"Unrecognized error detail option!"); ulRecord = 0; break; } // Get basic error information Win4Assert( ulRecord < cErrRecords ); sc = xErrorRecords->GetBasicErrorInfo(ulRecord, pErrorInfo); Win4Assert(sc != DB_E_BADRECORDNUM); sc = xErrorRecords->GetErrorInfo(ulRecord, lcid, ppIErrorInfo); Win4Assert(sc != DB_E_BADRECORDNUM); #if CIDBG // // Get error description and source through the IErrorInfo // interface pointer on a particular record. // BSTR bstrErrorDescription = 0; BSTR bstrErrorSource = 0; (*ppIErrorInfo)->GetDescription(&bstrErrorDescription); (*ppIErrorInfo)->GetSource(&bstrErrorSource); // // At this point we could call GetCustomErrorObject and query for additional // interfaces to determine what else happened. Currently no custom errors are // supported, so nothing to do. // if (bstrErrorSource && bstrErrorDescription) { WCHAR wszBuff[1024]; swprintf(wszBuff, L"HRESULT: %lx, Minor Code: %lu, Source: %ws\nDescription: %ws\n", pErrorInfo->hrError, pErrorInfo->dwMinor, bstrErrorSource, bstrErrorDescription); vqDebugOut((DEB_IERROR, "%ws", wszBuff)); } // // Free the resources // SysFreeString(bstrErrorDescription); SysFreeString(bstrErrorSource); #endif // CIDBG return sc; }