//--------------------------------------------------------------------------- // // 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 #pragma hdrstop #include // parser errors #include // IDS_ values of parser errors (mc generated header) //#include #define DBINITCONSTANTS #include #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 xErrorInfo; XInterface 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); }