|
|
//+---------------------------------------------------------------------------
//
// 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 <pch.cxx>
#pragma hdrstop
#include <dberror.hxx> // for IsCIError function
#include <vqdebug.hxx>
//+---------------------------------------------------------------------------
//
// 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<WCHAR> 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<ISupportErrorInfo> 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<IErrorInfo> xErrorInfo;
sc = GetErrorInfo(0, (IErrorInfo **)xErrorInfo.GetQIPointer()); if ( 0 == xErrorInfo.GetPointer() ) return sc;
//
// Get the IErrorRecord interface and get the count of errors.
//
XInterface<IErrorRecords> 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; }
|