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

1144 lines
34 KiB
C++

//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997 - 2000.
//
// File: DBERROR.CXX
//
// Contents: Ole DB Error implementation for CI
//
// History: 28-Apr-97 KrishnaN Created
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <mssql.h> // parser errors
#include <parserr.h> // IDS_ values of parser errors (mc generated header)
//#include <initguid.h>
#define DBINITCONSTANTS
#include <msdaguid.h>
#define ERROR_MESSAGE_SIZE 512
extern long gulcInstances;
// Implementation of CCIOleDBError
//+---------------------------------------------------------------------------
//
// Member: CCIOleDBError::CCIOleDBError, public
//
// Synopsis: Constructor. Gets the class factory for error object.
//
// Arguments: [rUnknown] - Controlling unknown.
//
// History: 28-Apr-97 KrishnaN Created
//----------------------------------------------------------------------------
//
CCIOleDBError::CCIOleDBError ( IUnknown & rUnknown, CMutexSem & mutex ) :
_mutex( mutex ),
_rUnknown(rUnknown),
_pErrClassFact (0)
{
}
//+---------------------------------------------------------------------------
//
// Member: CCIOleDBError::~CCIOleDBError, public
//
// Synopsis: Releases class factory.
//
// Arguments:
//
// History: 05-May-97 KrishnaN Created
//----------------------------------------------------------------------------
CCIOleDBError::~CCIOleDBError()
{
if ( 0 != _pErrClassFact )
_pErrClassFact->Release();
}
//+---------------------------------------------------------------------------
//
// Member: CCIOleDBError::QueryInterface, public
//
// Synopsis: Supports IID_IUnknown and IID_ISupportErrorInfo
//
// History: 28-Apr-97 KrishnaN Created
//----------------------------------------------------------------------------
STDMETHODIMP CCIOleDBError::QueryInterface(REFIID riid, void **ppvObject)
{
return _rUnknown.QueryInterface(riid, ppvObject);
} //QueryInterface
//+---------------------------------------------------------------------------
//
// Member: CCIOleDBError::AddRef, public
//
// History: 17-Mar-97 KrishnaN Created
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CCIOleDBError::AddRef()
{
return _rUnknown.AddRef();
} //AddRef
//+---------------------------------------------------------------------------
//
// Member: CCIOleDBError::Release, public
//
// History: 17-Mar-97 KrishnaN Created
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CCIOleDBError::Release()
{
return _rUnknown.Release();
} //Release
// ISupportErrorInfo method
//+---------------------------------------------------------------------------
//
// Member: CCIOleDBError::InterfaceSupportsErrorInfo, public
//
// Synopsis: Checks if error reporting on the specified interface is supported
//
// Arguments: [riid] - The interface in question
//
// History: 28-Apr-97 KrishnaN Created
//----------------------------------------------------------------------------
STDMETHODIMP CCIOleDBError::InterfaceSupportsErrorInfo(REFIID riid)
{
ULONG ul;
// See if the interface asked about, actually
// creates an error object.
for(ul=0; ul < _cErrInt; ul++)
{
if( *(_rgpErrInt[ul]) == riid )
return S_OK;
}
return S_FALSE;
} // InterfaceSupportsErrorInfo
//+---------------------------------------------------------------------------
//
// Member: CCIOleDBError::GetErrorInterfaces, private
//
// Synopsis: Gets the error interfaces, IErrorInfo and IErrorRecords.
//
// Arguments: [ppIErrorInfo] - Pointer to hold IErrorInfo i/f pointer
// [ppIErrorRecords] - Pointer to hold IErrorRecords i/f pointer
//
// History: 28-Apr-97 KrishnaN Created
//----------------------------------------------------------------------------
//
HRESULT CCIOleDBError::GetErrorInterfaces(IErrorInfo** ppIErrorInfo,
IErrorRecords** ppIErrorRecords)
{
if (0 == ppIErrorInfo || 0 == ppIErrorRecords)
return E_INVALIDARG;
*ppIErrorInfo = 0;
*ppIErrorRecords = 0;
if FAILED(_GetErrorClassFact())
return E_NOINTERFACE;
//
// Do we have a class factory on CLSID_EXTENDEDERROR ?
//
if (0 == _pErrClassFact)
return E_NOINTERFACE;
HRESULT hr = S_OK;
//
// Obtain the error object or create a new one if none exists
//
GetErrorInfo(0, ppIErrorInfo);
if ( !*ppIErrorInfo )
{
if( FAILED(hr = _pErrClassFact->CreateInstance(NULL,
IID_IErrorInfo, (LPVOID*)ppIErrorInfo)) )
return hr;
}
//
// Obtain the IErrorRecord Interface
//
hr = (*ppIErrorInfo)->QueryInterface(IID_IErrorRecords,
(LPVOID*)ppIErrorRecords);
//
// On a failure retrieving IErrorRecords, we need to release
// the IErrorInfo interface
//
if( FAILED(hr) && *ppIErrorInfo )
{
(*ppIErrorInfo)->Release();
*ppIErrorInfo = NULL;
}
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: CCIOleDBError::PostHResult, public
//
// Synopsis: Post an HRESULT to be looked up in ole-db sdk's error
// collection OR CI provided error lookup service.
//
// Arguments: [hrErr] - Code returned by the method that caused the error.
// [piid] - Interface where the error occurred.
//
// Returns: The incoming hrErr is echoed back to simplify error reporting
// in the calling code. So the caller can simply say something like
// "return PostHResult(E_INVALIDARG, &IID_ICommand);" instead of:
// "PostHResult(E_INVALIDARG, &IID_ICommand); return E_INVALIDARG;".
//
// History: 28-Apr-97 KrishnaN Created
//----------------------------------------------------------------------------
HRESULT CCIOleDBError::PostHResult(HRESULT hrErr, const IID & refiid)
{
SCODE hr = S_OK;
ERRORINFO ErrorInfo;
//
// Obtain the error object or create a new one if none exists
//
XInterface<IErrorInfo> xErrorInfo;
XInterface<IErrorRecords> xErrorRecords;
hr = GetErrorInterfaces((IErrorInfo **)xErrorInfo.GetQIPointer(),
(IErrorRecords **)xErrorRecords.GetQIPointer());
if (FAILED(hr))
return hrErr;
//
// Content Index methods sometimes throw NTSTATUS errors. So check for
// those and translate them to HRESULTs, just as is done in GetOleError()
//
switch (hrErr)
{
case STATUS_NO_MEMORY:
case HRESULT_FROM_WIN32( ERROR_COMMITMENT_LIMIT ):
case HRESULT_FROM_WIN32( ERROR_NO_SYSTEM_RESOURCES ):
case STG_E_TOOMANYOPENFILES:
case STG_E_INSUFFICIENTMEMORY:
case STATUS_INSUFFICIENT_RESOURCES:
hrErr = E_OUTOFMEMORY;
break;
case HRESULT_FROM_WIN32( ERROR_SEM_TIMEOUT ):
case HRESULT_FROM_WIN32( ERROR_PIPE_BUSY ):
hrErr = CI_E_TIMEOUT;
break;
case HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ):
hrErr = CI_E_NOT_RUNNING;
break;
case STATUS_NOT_FOUND:
hrErr = CI_E_NOT_FOUND;
break;
case STATUS_INVALID_PARAMETER:
hrErr = E_INVALIDARG;
break;
case STATUS_ACCESS_DENIED:
hrErr = E_ACCESSDENIED;
break;
case STATUS_INVALID_PARAMETER_MIX:
default:
break;
}
//
// Check to see if we have already posted this error
//
if ( NeedToSetError(hrErr, xErrorInfo.GetPointer(), xErrorRecords.GetPointer()) )
{
//
// Assign static information across each error record added
//
ErrorInfo.clsid = CLSID_CI_PROVIDER;
ErrorInfo.dispid = NULL;
ErrorInfo.hrError = hrErr;
ErrorInfo.iid = refiid;
ErrorInfo.dwMinor = 0;
//
// If this is a CI error, then add it with the lookup code IDENTIFIER_CI_ERROR
// If not, then it must be a Ole DB error or a Windows error. In either
// case, the default Ole DB sdk error lookup service will handle it. So
// post non-CI errors with IDENTIFIER_SDK_ERROR lookup id.
//
DWORD dwLookupId = IsCIError(hrErr) ? IDENTIFIER_CI_ERROR : IDENTIFIER_SDK_ERROR;
//
// Add the record to the Error Service Object
//
hr = xErrorRecords->AddErrorRecord(&ErrorInfo, dwLookupId, NULL, NULL, 0);
//
// Pass the error object to the Ole Automation DLL
//
if (SUCCEEDED(hr))
{
hr = SetErrorInfo(0, xErrorInfo.GetPointer());
}
}
//
// Release the interfaces to transfer ownership to
// the Ole Automation DLL. This will happen when
// xErrorInfo and xErrorRecords destruct, at the
// exit point of this method.
//
return hrErr;
}
//+---------------------------------------------------------------------------
//
// Member: CCIOleDBError::PostHResult, public
//
// Synopsis: Post an HRESULT to be looked up in ole-db sdk's error
// collection OR CI provided error lookup service.
//
// Arguments: [e] - CException object containing error code.
// [piid] - Interface where the error occurred.
//
// Returns: The incoming hrErr is echoed back to simplify error reporting
// in the calling code. So the caller can simply say something like
// "return PostHResult(E_INVALIDARG, &IID_ICommand);" instead of:
// "PostHResult(E_INVALIDARG, &IID_ICommand); return E_INVALIDARG;".
//
// This override allows for posting two error records in the case
// where the SCODE is converted into a less informative error code
// such as E_FAIL.
//
// History: 01-04-97 DanLeg Created
//----------------------------------------------------------------------------
HRESULT CCIOleDBError::PostHResult(CException &e, const IID & refiid)
{
SCODE sc = e.GetErrorCode();
SCODE scOLE = GetOleError(e);
if ( sc != scOLE )
{
PostHResult( sc, refiid );
sc = scOLE;
}
PostHResult( sc, refiid );
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CCIOleDBError::PostParserError, public
//
// Synopsis: This method is used to post static strings and DISPPARAMS to
// the error objects. The static strings are stored in the resource
// fork, and thus an id needs to be specified. This method receives
// in dwIds Monarch's error ids. Needs to change them to our
// resource ids (dwIdPostError). dwIdPost error is marked with flag
// (ERR_MONARCH_STATIC), so that GetErrorDescription may take the
// proper parameters.
//
// NOTE: If the error object is not our implementation of IID_IErrorInfo,
// we will not be able to load IErrorRecord and add our records.
//
// Arguments: [hrErr] - HRESULT to associate
// [dwIds] - string ID
// [ppdispparams] - dispatch params
//
// Returns: HResult indicating status
// S_OK | Success
// E_FAIL | OLE DB Error service object missing
//
//
// History: 11-03-97 danleg Created from Monarch
//----------------------------------------------------------------------------
HRESULT CCIOleDBError::PostParserError
(
HRESULT hrErr, //@parm IN | HResult to associate
DWORD dwIds, //@parm IN | String id
DISPPARAMS **ppdispparams //@parm IN/OUT | Dispatch Params
)
{
SCODE sc = S_OK;
DWORD dwIdPostError;
// Translation array from MONSQL values to IDS values
static const UINT s_rgTranslate[] = {
IDS_MON_PARSE_ERR_2_PARAM, // MONSQL_PARSE_ERROR w/ 2 parameter
IDS_MON_PARSE_ERR_1_PARAM, // MONSQL_PARSE_ERROR w/ 1 parameter
IDS_MON_ILLEGAL_PASSTHROUGH, // MONSQL_CITEXTTOSELECTTREE_FAILED
IDS_MON_DEFAULT_ERROR, // MONSQL_PARSE_STACK_OVERFLOW
IDS_MON_DEFAULT_ERROR, // MONSQL_CANNOT_BACKUP_PARSER
IDS_MON_SEMI_COLON, // MONSQL_SEMI_COLON
IDS_MON_ORDINAL_OUT_OF_RANGE, // MONSQL_ORDINAL_OUT_OF_RANGE
IDS_MON_VIEW_NOT_DEFINED, // MONSQL_VIEW_NOT_DEFINED
IDS_MON_BUILTIN_VIEW, // MONSQL_BUILTIN_VIEW
IDS_MON_COLUMN_NOT_DEFINED, // MONSQL_COLUMN_NOT_DEFINED
IDS_MON_OUT_OF_MEMORY, // MONSQL_OUT_OF_MEMORY
IDS_MON_SELECT_STAR, // MONSQL_SELECT_STAR
IDS_MON_OR_NOT, // MONSQL_OR_NOT
IDS_MON_CANNOT_CONVERT, // MONSQL_CANNOT_CONVERT
IDS_MON_OUT_OF_RANGE, // MONSQL_OUT_OF_RANGE
IDS_MON_RELATIVE_INTERVAL, // MONSQL_RELATIVE_INTERVAL
IDS_MON_NOT_COLUMN_OF_VIEW, // MONSQL_NOT_COLUMN_OF_VIEW
IDS_MON_BUILTIN_PROPERTY, // MONSQL_BUILTIN_PROPERTY
IDS_MON_WEIGHT_OUT_OF_RANGE, // MONSQL_WEIGHT_OUT_OF_RANGE
IDS_MON_MATCH_STRING, // MONSQL_MATCH_STRING
IDS_MON_PROPERTY_NAME_IN_VIEW, // MONSQL_PROPERTY_NAME_IN_VIEW
IDS_MON_VIEW_ALREADY_DEFINED, // MONSQL_VIEW_ALREADY_DEFINED
IDS_MON_INVALID_CATALOG, // MONSQL_INVALID_CATALOG
};
Win4Assert( ppdispparams );
// special fixup for MONSQL_PARSE_ERROR
if ( dwIds == MONSQL_PARSE_ERROR )
{
Win4Assert( *ppdispparams && (((*ppdispparams)->cArgs == 1) || ((*ppdispparams)->cArgs == 2)) );
if ( ((*ppdispparams) != NULL) &&
((*ppdispparams)->cArgs == 2) )
{
dwIds = 0; //Change to point to index of 2 parameter parse error
}
}
if ( dwIds < NUMELEM( s_rgTranslate ) )
dwIdPostError = s_rgTranslate[dwIds];
else
dwIdPostError= IDS_MON_DEFAULT_ERROR;
sc = PostError(hrErr, IID_ICommandText, dwIdPostError, *ppdispparams);
// free dispparams in case of error
if ( (*ppdispparams) != NULL )
{
if ( ((*ppdispparams)->cArgs > 0) &&
((*ppdispparams)->rgvarg!= NULL) )
{
for (ULONG ul=0; ul<(*ppdispparams)->cArgs; ul++)
VariantClear(&((*ppdispparams)->rgvarg[ul]));
CoTaskMemFree(((*ppdispparams)->rgvarg));
(*ppdispparams)->rgvarg= NULL;
(*ppdispparams)->cArgs = 0;
};
CoTaskMemFree((*ppdispparams));
*ppdispparams = NULL;
}
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CCIOleDBError::PostError, public
//
// Synopsis: This method is used to post static strings to the error objects.
// The static strings are stored in the resource fork, and thus an
// id needs to be specified.
//
// @devnote If the error object is not our implementation of
// IID_IErrorInfo, we will not be able to load IErrorRecord and add
// our records.
//
//
// Arguments: [hrErr] - HRESULT to associate
// [refiid] - IID of interface with error.
// [dwIds] - String id
// [pdispparams] - Parameters for the static string
//
// Returns: HResult indicating status
// S_OK | Success
// E_FAIL | OLE DB Error service object missing
//
//
// History: 11-03-97 danleg Created from Monarch
//----------------------------------------------------------------------------//-----------------------------------------------------------------------------
//
// @mfunc
// @rdesc HResult indicating status
// @flags S_OK | Success
// @flags E_FAIL | OLE DB Error service object missing
//
HRESULT CCIOleDBError::PostError
(
HRESULT hrErr,
const IID & refiid,
DWORD dwIds,
DISPPARAMS* pdispparams
)
{
SCODE sc = S_OK;
ERRORINFO ErrorInfo;
IErrorInfo* pIErrorInfo = NULL;
IErrorRecords* pIErrorRecords = NULL;
// Obtain the error object or create a new one if none exists
sc = GetErrorInterfaces( &pIErrorInfo, &pIErrorRecords );
if ( FAILED(sc) )
goto EXIT_PROCESS_ERRORS;
// Assign static information across each error record added
ErrorInfo.clsid = CLSID_CI_PROVIDER;
ErrorInfo.hrError = hrErr;
ErrorInfo.iid = refiid;
ErrorInfo.dispid = NULL;
ErrorInfo.dwMinor = 0;
// Add the record to the Error Service Object
sc = pIErrorRecords->AddErrorRecord( &ErrorInfo,
dwIds,
pdispparams,
NULL,
0 );
if ( FAILED(sc) )
goto EXIT_PROCESS_ERRORS;
// Pass the error object to the Ole Automation DLL
sc = SetErrorInfo(0, pIErrorInfo);
// Release the interfaces to transfer ownership to
// the Ole Automation DLL
EXIT_PROCESS_ERRORS:
if ( pIErrorRecords )
pIErrorRecords->Release();
if ( pIErrorInfo )
pIErrorInfo->Release();
return sc;
}
//-----------------------------------------------------------------------------
//
// Member: CCIOleDBError::NeedToSetError - private
//
// Synopsis: Determine if error needs to be set.
//
// Arguments: [scError] - Error code to look for
//
// Returns: TRUE if the error needs to be set. FALSE, if it already
// exists and has a valid description string.
//
// Notes:
//
// History: 15 Jan 1998 KrishnaN Created
// 03-01-98 danleg adopted from ixsso with few changes
//
//-----------------------------------------------------------------------------
BOOL CCIOleDBError::NeedToSetError
(
SCODE scError,
IErrorInfo * pErrorInfo,
IErrorRecords * pErrorRecords
)
{
BOOL fFound = FALSE;
if ( 0 == pErrorInfo )
return TRUE;
XBStr xDescription;
BSTR pDescription = xDescription.GetPointer();
if (0 == pErrorRecords)
{
// No error records. Do we at least have the top level description set?
// If so, that indicates an automation client called SetErrorInfo before us
// and we should not overwrite them.
pErrorInfo->GetDescription(&pDescription);
fFound = (BOOL)(pDescription != 0);
}
else
{
ULONG cErrRecords;
SCODE sc = pErrorRecords->GetRecordCount(&cErrRecords);
Win4Assert(!fFound);
// look for the target error code. stop when one is found
ERRORINFO ErrorInfo;
for (ULONG i = 0; i < cErrRecords; i++)
{
sc = pErrorRecords->GetBasicErrorInfo(i, &ErrorInfo);
Win4Assert(S_OK == sc);
if (scError == ErrorInfo.hrError)
{
pErrorInfo->GetDescription(&pDescription);
fFound = (BOOL)(pDescription != 0);
break;
}
}
}
if (!fFound)
return TRUE;
// we found the error code and it has a description.
// no need to set this error again, but we have to
// put this error info back so the client can find it.
SetErrorInfo(0, pErrorInfo);
return FALSE;
}
//+---------------------------------------------------------------------------
//
// Member: CCIOleDBError::_GetErrorClassFact, private
//
// Synopsis: Initializes error class factory.
//
// Returns: Success code.
//
// History: 28-Apr-97 KrishnaN Created
//----------------------------------------------------------------------------
SCODE CCIOleDBError::_GetErrorClassFact()
{
SCODE sc = S_OK;
CLock lck( _mutex );
//
// If we have failed once, we should not be
// attempting again. No point in doing that.
//
if ( 0 == _pErrClassFact )
{
//
// We don't have an error class factory.
//
sc = CoGetClassObject(CLSID_EXTENDEDERRORINFO,
CLSCTX_INPROC_SERVER,
NULL,
IID_IClassFactory,
(void **) &_pErrClassFact);
if (FAILED(sc))
{
vqDebugOut((DEB_ITRACE, "No class factory is available "
" for CLSID_EXTENDEDERROR.\n"));
}
}
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CErrorLookup::QueryInterface, public
//
// Synopsis: Supports IID_IUnknown and IID_IErrorLookup
//
// History: 28-Apr-97 KrishnaN Created
// 01-30-98 danleg E_INVALIDARG if ppvObject is bad
//----------------------------------------------------------------------------
STDMETHODIMP CErrorLookup::QueryInterface(REFIID riid, void **ppvObject)
{
if ( !ppvObject )
return E_INVALIDARG;
if (IID_IUnknown == riid)
{
*ppvObject = (void *)((IUnknown *)this);
AddRef();
return S_OK;
}
else if (IID_IErrorLookup == riid)
{
*ppvObject = (void *)((IErrorLookup *)this);
AddRef();
return S_OK;
}
else
{
*ppvObject = 0;
return E_NOINTERFACE;
}
} //QueryInterface
//+---------------------------------------------------------------------------
//
// Member: CErrorLookup::AddRef, public
//
// History: 17-Mar-97 KrishnaN Created
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CErrorLookup::AddRef()
{
InterlockedIncrement(&_cRefs);
return _cRefs;
} //AddRef
//+---------------------------------------------------------------------------
//
// Member: CErrorLookup::Release, public
//
// History: 17-Mar-97 KrishnaN Created
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CErrorLookup::Release()
{
Win4Assert(_cRefs > 0);
LONG refCount = InterlockedDecrement(&_cRefs);
if ( refCount <= 0 )
delete this;
return refCount;
} //Release
// IErrorLookup methods
//+---------------------------------------------------------------------------
//
// Member: CErrorLookup::GetErrorDescription, public
//
// Synopsis: Composes the error description for the specifed error.
//
// Arguments: [hrError] - Code returned by the method that caused
// the error.
// [dwLookupId] - Provider-specific number of the error.
// [pdispparams] - Params of the error. If there are no
// params, this is a NULL pointer.
// [lcid] - Locale ID for which to return the
// description and the sources.
// [pbstrSource] - Pointer to memory in which to return a
// pointer to the name of the component
// that generated the error.
// [pbstrDescription]- Pointer to memory in which to return a
// string that describes the error.
//
// History: 28-Apr-97 KrishnaN Created
//----------------------------------------------------------------------------
STDMETHODIMP CErrorLookup::GetErrorDescription (HRESULT hrError,
DWORD dwLookupId,
DISPPARAMS* pdispparams,
LCID lcid,
BSTR* pbstrSource,
BSTR* pbstrDescription)
{
SCODE sc = S_OK;
// Check the Arguments
if( 0 == pbstrSource || 0 == pbstrDescription )
return E_INVALIDARG;
*pbstrSource = *pbstrDescription = 0;
TRANSLATE_EXCEPTIONS;
TRY
{
//
// If we encounter IDENTIFIER_SDK_ERROR, make sure we return S_OK;
//
BOOL fGetDescription = (IDENTIFIER_SDK_ERROR != dwLookupId);
BOOL fGetSource = TRUE;
XBStr xbstrDescription;
XBStr xbstrSource;
// We only support lookup of CI generated errors and those handled
// by the default error lookup service!
if ( (IDENTIFIER_SDK_ERROR != dwLookupId) && !IsCIError(hrError) )
{
if( IsParserError(dwLookupId) )
{
hrError = dwLookupId;
}
else
{
fGetDescription = fGetSource = FALSE;
sc = DB_E_BADHRESULT;
}
}
if (fGetSource)
{
// Fix for bug# 83593: Set source string even when the default
// lookup service is providing the description
xbstrSource.SetText( L"Microsoft OLE DB Provider for Indexing Service" );
}
if (fGetDescription)
{
DWORD_PTR rgdwArguments[2];
DWORD dwFlags = FORMAT_MESSAGE_FROM_HMODULE;
if (pdispparams)
{
dwFlags |= FORMAT_MESSAGE_ARGUMENT_ARRAY;
Win4Assert(pdispparams->cArgs == 2 || pdispparams->cArgs == 1 || pdispparams->cArgs == 0);
for (UINT c=0; c < pdispparams->cArgs; c++)
{
rgdwArguments[c] = (DWORD_PTR)(LPWSTR)pdispparams->rgvarg[c].bstrVal;
}
}
else
{
RtlZeroMemory( rgdwArguments, sizeof(rgdwArguments) );
}
//
// Load the error string from the appropriate DLL
//
WCHAR wszBuffer[ERROR_MESSAGE_SIZE];
//
// Don't pass a specific lang id to FormatMessage since it will
// fail if there's no message in that language. Instead set
// the thread locale, which will get FormatMessage to use a search
// algorithm to find a message of the appropriate language or
// use a reasonable fallback msg if there's none.
//
LCID SaveLCID = GetThreadLocale();
SetThreadLocale(lcid);
// CLEANCODE: Since we could have differently named dlls (query.dll
// or oquery.dll) we should be able to look up in the registry
// and determine which one to get. Or just get the module name.
// All messages are in querymsg.mc, which is in query.dll.
HMODULE hModule = GetModuleHandle(L"query.dll");
if (! FormatMessage( dwFlags | FORMAT_MESSAGE_MAX_WIDTH_MASK,
hModule,
hrError,
0,
wszBuffer,
ERROR_MESSAGE_SIZE,
(va_list*) rgdwArguments ) )
{
vqDebugOut(( DEB_ERROR, "Format message failed with error 0x%x\n", GetLastError() ));
swprintf( wszBuffer,
L"Unable to format message for error 0x%X caught in Indexing Service.\n",
hrError );
}
SetThreadLocale(SaveLCID);
//
// Convert the loaded string to a BSTR
//
xbstrDescription.SetText(wszBuffer);
}
*pbstrSource = xbstrSource.GetPointer();
*pbstrDescription = xbstrDescription.GetPointer();
xbstrSource.Acquire();
xbstrDescription.Acquire();
}
CATCH( CException, e )
{
vqDebugOut(( DEB_ERROR, "Exception %08x in CCIOleDBError::GetErrorDescription \n",
e.GetErrorCode() ));
sc = GetOleError(e);
}
END_CATCH
UNTRANSLATE_EXCEPTIONS;
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CErrorLookup::GetHelpInfo, public
//
// Synopsis: Composes the error description for the specifed error.
//
// Arguments: [hrError] - Code returned by the method that caused
// the error.
// [dwLookupId] - Provider-specific number of the error.
// [lcid] - Locale Id for which to return the Help
// file path and Context ID.
// [pbstrHelpFile] - Pointer to memory in which to return a
// pointer the fully path of the Help file.
//
// [pdwHelpContext]- Pointer to memory in which to return the
// Help Context ID for the error.
//
// History: 28-Apr-97 KrishnaN Created
//----------------------------------------------------------------------------
STDMETHODIMP CErrorLookup::GetHelpInfo (HRESULT hrError,
DWORD dwLookupId,
LCID lcid,
BSTR* pbstrHelpFile,
DWORD* pdwHelpContext)
{
if ( 0 == pbstrHelpFile || 0 == pdwHelpContext )
return E_INVALIDARG;
*pbstrHelpFile = 0;
*pdwHelpContext = 0;
//
// Currently we do not return any help file
// context or names, so we will just return S_OK
//
// NEWFEATURE: We can, if we choose to, return help file
// and context for the query project.
if ( lcid != GetUserDefaultLCID() )
return DB_E_NOLOCALE;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CErrorLookup::ReleaseErrors, public
//
// Synopsis: Releases dynamic errors.
//
// Arguments: [dwDynamicErrorId] - ID of the dynamic error info to release.
//
// History: 28-Apr-97 KrishnaN Created
//----------------------------------------------------------------------------
STDMETHODIMP CErrorLookup::ReleaseErrors (const DWORD dwDynamicErrorId)
{
Win4Assert(!"Currently we don't support dynamic errors.");
if (0 == dwDynamicErrorId)
return E_INVALIDARG;
//
// We don't support dynamic errors, so nothing to do.
//
return S_OK;
}
//+-------------------------------------------------------------------------
//
// Method: CErrorLookupCF::CErrorLookupCF, public
//
// Synopsis: CErrorLookup class factory constructor
//
// History: 25-Mar-1997 KrishnaN Created
//
//--------------------------------------------------------------------------
CErrorLookupCF::CErrorLookupCF()
: _cRefs( 1 )
{
InterlockedIncrement( &gulcInstances );
}
//+-------------------------------------------------------------------------
//
// Method: CErrorLookupCF::~CErrorLookupCF
//
// Synopsis: Text IFilter class factory constructor
//
// History: 25-Mar-1997 KrishnaN Created
//
//--------------------------------------------------------------------------
CErrorLookupCF::~CErrorLookupCF()
{
InterlockedDecrement( &gulcInstances );
}
//+-------------------------------------------------------------------------
//
// Method: CErrorLookupCF::QueryInterface, public
//
// Synopsis: Rebind to other interface
//
// Arguments: [riid] -- IID of new interface
// [ppvObject] -- New interface * returned here
//
// Returns: S_OK if bind succeeded, E_NOINTERFACE if bind failed
//
// History: 25-Mar-1997 KrishnaN Created
// 01-31-98 danleg E_INVALIDARG for bad ppvObject
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE CErrorLookupCF::QueryInterface( REFIID riid,
void ** ppvObject )
{
if ( 0 == ppvObject )
return E_INVALIDARG;
*ppvObject = 0;
SCODE sc = S_OK;
if ( IID_IClassFactory == riid )
*ppvObject = (IUnknown *)(IClassFactory *)this;
else if ( IID_IUnknown == riid )
*ppvObject = (IUnknown *)this;
else if ( IID_ITypeLib == riid )
sc = E_NOINTERFACE;
else
sc = E_NOINTERFACE;
if ( SUCCEEDED( sc ) )
AddRef();
return sc;
}
//+-------------------------------------------------------------------------
//
// Method: CErrorLookupCF::AddRef, public
//
// Synopsis: Increments refcount
//
// History: 25-Mar-1997 KrishnaN Created
//
//--------------------------------------------------------------------------
ULONG STDMETHODCALLTYPE CErrorLookupCF::AddRef()
{
return InterlockedIncrement( &_cRefs );
}
//+-------------------------------------------------------------------------
//
// Method: CErrorLookupCF::Release, public
//
// Synopsis: Decrement refcount. Delete if necessary.
//
// History: 25-Mar-1997 KrishnaN Created
//
//--------------------------------------------------------------------------
ULONG STDMETHODCALLTYPE CErrorLookupCF::Release()
{
unsigned long uTmp = InterlockedDecrement( &_cRefs );
if ( 0 == uTmp )
delete this;
return(uTmp);
}
//+-------------------------------------------------------------------------
//
// Method: CErrorLookupCF::CreateInstance, public
//
// Synopsis: Creates new CIndexer object
//
// Arguments: [pUnkOuter] -- 'Outer' IUnknown
// [riid] -- Interface to bind
// [ppvObject] -- Interface returned here
//
// History: 25-Mar-1997 KrishnaN Created
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE CErrorLookupCF::CreateInstance( IUnknown * pUnkOuter,
REFIID riid,
void * * ppvObject )
{
CErrorLookup * pIUnk = 0;
SCODE sc = S_OK;
TRY
{
pIUnk = new CErrorLookup();
sc = pIUnk->QueryInterface( riid , ppvObject );
pIUnk->Release(); // Release extra refcount from QueryInterface
}
CATCH( CException, e )
{
Win4Assert( 0 == pIUnk );
sc = GetOleError(e);
}
END_CATCH
return (sc);
}
//+-------------------------------------------------------------------------
//
// Method: CErrorLookupCF::LockServer, public
//
// Synopsis: Force class factory to remain loaded
//
// Arguments: [fLock] -- TRUE if locking, FALSE if unlocking
//
// Returns: S_OK
//
// History: 25-Mar-1997 KrishnaN Created
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE CErrorLookupCF::LockServer(BOOL fLock)
{
if(fLock)
InterlockedIncrement( &gulcInstances );
else
InterlockedDecrement( &gulcInstances );
return(S_OK);
}