|
|
//+---------------------------------------------------------------------------
//
// Copyright (C) 1997-1998, Microsoft Corporation.
//
// File: ixserror.cxx
//
// Contents: SSO Error class
//
// History: 04 Apr 1997 Alanw Created
//
//----------------------------------------------------------------------------
#include "pch.cxx"
#pragma hdrstop
//-----------------------------------------------------------------------------
// Include Files
//-----------------------------------------------------------------------------
// debugging macros
#include "ssodebug.hxx"
// class declaration
#include "ixserror.hxx"
//-----------------------------------------------------------------------------
//
// Member: CixssoError::SetError - private
//
// Synopsis: Save error information
//
// Arguments: [scError] - Error code
// [iLine] - (optional) line number where error occurred
// [pwszFile] - (optional) file name where error occurred
// [pwszLoc] - Location from which error was generated
// [eErrClass] - error class, indicates error message file
//
// Notes:
//
// History: 07 Jan 1997 Alanw Created
//
//-----------------------------------------------------------------------------
extern HINSTANCE g_hInst; extern WCHAR * g_pwszErrorMsgFile;
#define ERROR_MESSAGE_SIZE 512
void CixssoError::SetError( SCODE scError, ULONG iLine, WCHAR const * pwszFile, WCHAR const * pwszLoc, unsigned eErrClass, LCID lcid) { // Has the error already been handled? If so, return.
if ( _sc != 0) return;
if ( QUERY_E_DUPLICATE_OUTPUT_COLUMN == scError ) { scError = MSG_IXSSO_DUPLICATE_COLUMN; eErrClass = eIxssoError; } else if ( QUERY_E_INVALID_OUTPUT_COLUMN == scError ) { scError = MSG_IXSSO_NO_SUCH_COLUMN_PROPERTY; eErrClass = eIxssoError; }
// Does this error (possibly transalted) already exist on the error stack?
// If it does, and it has a description, we shouldn't be doing anything else.
if (FALSE == NeedToSetError(scError)) return;
ixssoDebugOut(( DEB_ITRACE, "SetError: sc = %x, loc = %ws\n", scError, pwszLoc ));
WCHAR awcsErrorMessage[ERROR_MESSAGE_SIZE]; WCHAR *pwszErrorMessage = awcsErrorMessage; ULONG cchAvailMessage = ERROR_MESSAGE_SIZE;
//
// Generate the Win32 error code by removing the facility code (7) and
// the error bit.
//
ULONG Win32status = scError; if ( (Win32status & (FACILITY_WIN32 << 16)) == (FACILITY_WIN32 << 16) ) { Win32status &= ~( 0x80000000 | (FACILITY_WIN32 << 16) ); }
//
// 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);
// Precede the error message by the file/line if passed.
if (pwszFile != 0) { UINT_PTR args [] = { (UINT_PTR) pwszFile, (UINT_PTR) iLine, };
NTSTATUS MsgNum = MSG_IXSSO_FILE_MESSAGE; if (iLine != 0) { MsgNum = MSG_IXSSO_FILE_LINE_MESSAGE; }
ULONG cchMsg = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY, g_hInst, MsgNum, 0, pwszErrorMessage, cchAvailMessage, (va_list *) args ); pwszErrorMessage += cchMsg; cchAvailMessage -= cchMsg; }
BOOL fSystemError = FALSE;
switch (eErrClass) { case eIxssoError: if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE, g_hInst, scError, 0, pwszErrorMessage, cchAvailMessage, 0 ) ) { ixssoDebugOut(( DEB_ERROR, "Format message failed with error 0x%x\n", GetLastError() ));
swprintf( pwszErrorMessage, L"Error 0x%x caught while processing query\n", scError ); } break;
case ePlistError: case eParseError: if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE, GetModuleHandle(g_pwszErrorMsgFile), scError, 0, pwszErrorMessage, cchAvailMessage, 0 ) ) { ixssoDebugOut(( DEB_ERROR, "Format message failed with error 0x%x\n", GetLastError() ));
swprintf( pwszErrorMessage, L"Error 0x%x caught while parsing query or other fields\n", scError ); } break;
case eDefaultError: if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE, g_hInst, scError, 0, pwszErrorMessage, cchAvailMessage, 0 ) ) { if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE, GetModuleHandle(g_pwszErrorMsgFile), scError, 0, pwszErrorMessage, cchAvailMessage, 0 ) ) { //
// Try looking up the error in the Win32 list of error codes
//
if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE, GetModuleHandle(L"kernel32.dll"), Win32status, 0, pwszErrorMessage, cchAvailMessage, 0 ) ) { ixssoDebugOut(( DEB_ERROR, "Format message failed with error 0x%x\n", GetLastError() ));
swprintf( pwszErrorMessage, L"Error 0x%x caught while processing query\n", scError ); } else { fSystemError = TRUE; } } } break;
default: Win4Assert( !"Unrecognized error class" ); break; } SetThreadLocale(SaveLCID);
SetError( scError, pwszLoc, awcsErrorMessage ); }
//-----------------------------------------------------------------------------
//
// Member: CixssoError::SetError - private
//
// Synopsis: Save error information
//
// Arguments: [scError] - Error code
// [pwszLoc] - Location from which error was generated
// [pwszDescription] - Error description
//
// Notes:
//
// History: 06 May 1997 KrishnaN Created
//
//-----------------------------------------------------------------------------
void CixssoError::SetError( SCODE scError, WCHAR const * pwszLoc, WCHAR const * pwszDescription) { // Has the error on this object already been set?
if (_sc != 0) return;
// We should be here only if an error has NOT already been set.
Win4Assert(NeedToSetError(scError));
Win4Assert(pwszLoc && pwszDescription);
ixssoDebugOut(( DEB_ITRACE, "SetError: sc = %x, loc = %ws,\n\tdescription = %ws\n", scError, pwszLoc, pwszDescription ));
_fErr = TRUE; _sc = scError;
//
// Create an error info object giving the error message
//
ICreateErrorInfo * pErrorInfo; SCODE sc = CreateErrorInfo( &pErrorInfo ); if (SUCCEEDED( sc )) { XInterface<ICreateErrorInfo> pErr(pErrorInfo); pErrorInfo = 0;
pErr->SetDescription( (LPWSTR) pwszDescription ); pErr->SetGUID( _iid ); pErr->SetSource( (LPWSTR) pwszLoc ); // Cast ok. Never touched by anyone.
IErrorInfo * pErrInfo = 0; sc = pErr->QueryInterface( IID_IErrorInfo, (void **)&pErrInfo); if (SUCCEEDED(sc)) { SetErrorInfo(0, pErrInfo); pErrInfo->Release(); } } }
//-----------------------------------------------------------------------------
//
// Member: CixssoError::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
//
//-----------------------------------------------------------------------------
BOOL CixssoError::NeedToSetError(SCODE scError) { BOOL fFound = FALSE;
//
// Get the current error object. Return TRUE if none exists.
//
XInterface<IErrorInfo> xErrorInfo;
SCODE sc = GetErrorInfo(0, (IErrorInfo **)xErrorInfo.GetQIPointer()); if ( S_FALSE == sc ) { Win4Assert(0 == xErrorInfo.GetPointer()); return TRUE; }
// Get the IErrorRecord interface and get the count of errors.
XInterface<IErrorRecords> xErrorRecords; XBStr xDescription; BSTR pDescription = xDescription.GetPointer();
sc = xErrorInfo->QueryInterface(IID_IErrorRecords, xErrorRecords.GetQIPointer()); if (0 == xErrorRecords.GetPointer()) { // 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.
xErrorInfo->GetDescription(&pDescription); fFound = ( pDescription != 0 ) ; } else { ULONG cErrRecords; sc = xErrorRecords->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 = xErrorRecords->GetBasicErrorInfo(i, &ErrorInfo); Win4Assert(S_OK == sc);
if (scError == ErrorInfo.hrError) { xErrorInfo->GetDescription(&pDescription); fFound = ( 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, xErrorInfo.GetPointer()); return FALSE; }
|