windows-nt/Source/XPSP1/NT/inetsrv/query/qutil/querylib/util.cxx
2020-09-26 16:20:57 +08:00

263 lines
7.7 KiB
C++

//+---------------------------------------------------------------------------
//
// 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;
}