windows-nt/Source/XPSP1/NT/base/cluster/admin/common/excoper.cpp

584 lines
16 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1996-2000 Microsoft Corporation
//
// Module Name:
// ExcOper.cpp
//
// Abstract:
// Implementation of exception classes.
//
// Author:
// David Potter (davidp) May 20, 1996
//
// Revision History:
//
// Notes:
// TraceTag.h and resource.h are pulled from the project directory.
//
// stdafx.h must disable some W4 warnings.
//
// TraceTag.h must define TraceError.
//
// resource.h must define IDS_ERROR_MSG_ID, and the string must be
// defined something like "\n\nError ID: %d (%08.8x)." in the resource file.
//
// IDP_NO_ERROR_AVAILABLE must defined as a string for displaying when
// no error code is available.
//
// EXC_AppMessageBox(LPCTSTR...) and EXC_AppMessageBox(UINT...) must be
// defined and implemented.
//
// EXC_GetResourceInstance must be defined and implemented to return the
// resource instance handle of the application or DLL.
//
/////////////////////////////////////////////////////////////////////////////
#include <string.h>
#include "ExcOper.h"
#include "TraceTag.h"
#include "resource.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// class CException
/////////////////////////////////////////////////////////////////////////////
#ifndef __AFX_H__
/////////////////////////////////////////////////////////////////////////////
//++
//
// CException::ReportError
//
// Routine Description:
// Report an error from the exception. Overriding to get a bigger
// error message buffer.
//
// Arguments:
// nType [IN] Type of message box.
// nError [IN] ID of a mesage to display if exception has no message.
//
// Return Value:
// Return value from MessageBox.
//
//--
/////////////////////////////////////////////////////////////////////////////
int CException::ReportError( UINT nType /* = MB_OK */, UINT nError /* = 0 */ )
{
TCHAR szErrorMessage[128];
int nDisposition;
UINT nHelpContext;
if ( GetErrorMessage(szErrorMessage, sizeof( szErrorMessage ) / sizeof( TCHAR ), &nHelpContext ) )
{
nDisposition = EXC_AppMessageBox( szErrorMessage, nType, nHelpContext );
} // if: error message retrieved successfully
else
{
if ( nError == 0 )
{
nError = IDP_NO_ERROR_AVAILABLE;
} // if: no error code
nDisposition = EXC_AppMessageBox( nError, nType, nHelpContext );
} // else: error retrieving error message
return nDisposition;
} //*** CException::ReportError()
#endif // __AFX_H__
/////////////////////////////////////////////////////////////////////////////
// class CExceptionWithOper
/////////////////////////////////////////////////////////////////////////////
#ifdef __AFX_H__
IMPLEMENT_DYNAMIC(CExceptionWithOper, CException)
#endif // __AFX_H__
/////////////////////////////////////////////////////////////////////////////
//++
//
// CExceptionWithOper::ReportError
//
// Routine Description:
// Report an error from the exception. Overriding to get a bigger
// error message buffer.
//
// Arguments:
// nType [IN] Type of message box.
// nError [IN] ID of a mesage to display if exception has no message.
//
// Return Value:
// Return value from MessageBox.
//
//--
/////////////////////////////////////////////////////////////////////////////
int CExceptionWithOper::ReportError(
UINT nType /* = MB_OK */,
UINT nError /* = 0 */
)
{
TCHAR szErrorMessage[EXCEPT_MAX_OPER_ARG_LENGTH * 3];
int nDisposition;
UINT nHelpContext;
if ( GetErrorMessage( szErrorMessage, sizeof( szErrorMessage ) / sizeof( TCHAR ), &nHelpContext ) )
{
nDisposition = EXC_AppMessageBox( szErrorMessage, nType, nHelpContext );
} // if: error message retrieved successfully
else
{
if ( nError == 0 )
{
nError = IDP_NO_ERROR_AVAILABLE;
} // if: no error code
nDisposition = EXC_AppMessageBox( nError, nType, nHelpContext );
} // else: error retrieving error message
return nDisposition;
} //*** CExceptionWithOper::ReportError()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CExceptionWithOper::ReportError
//
// Routine Description:
// Report an error from the exception. This method should be used from
// all threads except the main thread.
//
// Arguments:
// pfnMsgBox [IN] Message box function pointer.
// dwParam [IN] Parameter to pass to the message box function.
// nType [IN] Type of message box.
// nError [IN] ID of a mesage to display if exception has no message.
//
// Return Value:
// Return value from MessageBox.
//
//--
/////////////////////////////////////////////////////////////////////////////
int CExceptionWithOper::ReportError(
PFNMSGBOX pfnMsgBox,
DWORD dwParam,
UINT nType /* = MB_OK */,
UINT nError /* = 0 */
)
{
TCHAR szErrorMessage[EXCEPT_MAX_OPER_ARG_LENGTH * 3];
int nDisposition;
UINT nHelpContext;
ASSERT( pfnMsgBox != NULL );
if ( GetErrorMessage( szErrorMessage, sizeof( szErrorMessage ) / sizeof( TCHAR ), &nHelpContext ) )
{
nDisposition = (*pfnMsgBox)( dwParam, szErrorMessage, nType, nHelpContext );
} // if: error message retrieved successfully
else
{
if ( nError == 0 )
{
nError = IDP_NO_ERROR_AVAILABLE;
} // if: no error code
CString strMsg;
strMsg.LoadString( nError );
nDisposition = (*pfnMsgBox)( dwParam, strMsg, nType, nHelpContext );
} // else: error retrieving error message
return nDisposition;
} //*** CExceptionWithOper::ReportError( pfnMsgBox )
/////////////////////////////////////////////////////////////////////////////
//++
//
// CExceptionWithOper::ReportError
//
// Routine Description:
// Report an error from the exception. This method should be used from
// all threads except the main thread.
//
// Arguments:
// hwndParent [IN] Parent window.
// nType [IN] Type of message box.
// nError [IN] ID of a mesage to display if exception has no message.
//
// Return Value:
// Return value from MessageBox.
//
//--
/////////////////////////////////////////////////////////////////////////////
int CExceptionWithOper::ReportError(
HWND hwndParent,
UINT nType /* = MB_OK */,
UINT nError /* = 0 */
)
{
ASSERT(hwndParent != NULL);
TCHAR szErrorMessage[EXCEPT_MAX_OPER_ARG_LENGTH * 3];
int nDisposition;
UINT nHelpContext;
if ( GetErrorMessage( szErrorMessage, sizeof( szErrorMessage ) / sizeof( TCHAR ), &nHelpContext ) )
{
nDisposition = EXC_AppMessageBox( hwndParent, szErrorMessage, nType, nHelpContext );
} // if: error message retrieved successfully
else
{
if ( nError == 0 )
{
nError = IDP_NO_ERROR_AVAILABLE;
} // if: no error code
CString strMsg;
strMsg.LoadString( nError );
nDisposition = EXC_AppMessageBox( hwndParent, szErrorMessage, nType, nHelpContext );
} // else: error retrieving error message
return nDisposition;
} //*** CExceptionWithOper::ReportError( pfnMsgBox )
/////////////////////////////////////////////////////////////////////////////
//++
//
// CExceptionWithOper::SetOperation
//
// Routine Description:
// Constructor.
//
// Arguments:
// idsOperation [IN] String ID for operation occurring during exception.
// pszOperArg1 [IN] 1st argument to operation string.
// pszOperArg2 [IN] 2nd argument to operation string.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CExceptionWithOper::SetOperation(
IN UINT idsOperation,
IN LPCTSTR pszOperArg1,
IN LPCTSTR pszOperArg2
)
{
m_idsOperation = idsOperation;
if ( pszOperArg1 == NULL )
{
m_szOperArg1[0] = _T('\0');
} // if: first argument not specified
else
{
::_tcsncpy( m_szOperArg1, pszOperArg1, (sizeof( m_szOperArg1 ) / sizeof( TCHAR )) - 1 );
m_szOperArg1[(sizeof( m_szOperArg1 ) / sizeof( TCHAR ))- 1] = _T('\0');
} // else: first argument specified
if ( pszOperArg2 == NULL )
{
m_szOperArg2[0] = _T('\0');
} // if: second argument not specified
else
{
::_tcsncpy( m_szOperArg2, pszOperArg2, (sizeof( m_szOperArg2 ) / sizeof( TCHAR )) - 1 );
m_szOperArg2[(sizeof( m_szOperArg2 ) / sizeof( TCHAR )) - 1] = _T('\0');
} // else: second argument specified
} //*** CExceptionWithOper::SetOperation()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CExceptionWithOper::FormatWithOperation
//
// Routine Description:
// Get the error message represented by the exception.
//
// Arguments:
// lpszError [OUT] String in which to return the error message.
// nMaxError [IN] Maximum length of the output string.
// pszMsg [IN] Message to format with the operation string.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CExceptionWithOper::FormatWithOperation(
OUT LPTSTR lpszError,
IN UINT nMaxError,
IN LPCTSTR pszMsg
)
{
DWORD dwResult;
TCHAR szOperation[EXCEPT_MAX_OPER_ARG_LENGTH];
TCHAR szFmtOperation[EXCEPT_MAX_OPER_ARG_LENGTH * 3];
ASSERT( lpszError != NULL );
ASSERT( nMaxError > 0 );
// Format the operation string.
if ( m_idsOperation )
{
void * rgpvArgs[2] = { m_szOperArg1, m_szOperArg2 };
// Load the operation string.
dwResult = ::LoadString( EXC_GetResourceInstance(), m_idsOperation, szOperation, (sizeof( szOperation ) / sizeof( TCHAR )) );
ASSERT( dwResult != 0 );
// Format the operation string.
::FormatMessage(
FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
szOperation,
0,
MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ),
szFmtOperation,
sizeof( szFmtOperation ) / sizeof( TCHAR ),
(va_list *) rgpvArgs
);
szFmtOperation[(sizeof( szFmtOperation ) / sizeof( TCHAR )) - 1] = _T('\0');
// Format the final error message.
if ( pszMsg != NULL )
{
::_sntprintf( lpszError, nMaxError - 1, _T("%s\n\n%s"), szFmtOperation, pszMsg );
} // if: additional message specified
else
{
::_tcsncpy(lpszError, szFmtOperation, nMaxError - 1);
} // else: no additional message specified
lpszError[nMaxError - 1] = _T('\0');
} // if: operation string specified
else
{
if ( pszMsg != NULL )
{
::_tcsncpy( lpszError, pszMsg, nMaxError - 1 );
lpszError[nMaxError - 1] = _T('\0');
} // if: additional message specified
else
{
lpszError[0] = _T('\0');
} // if: no additional message specified
} // else: no operation string specified
} //*** CExceptionWithOper::FormatWithOperation()
//***************************************************************************
/////////////////////////////////////////////////////////////////////////////
// class CNTException
/////////////////////////////////////////////////////////////////////////////
#ifdef __AFX_H__
IMPLEMENT_DYNAMIC( CNTException, CExceptionWithOper )
#endif // __AFX_H__
/////////////////////////////////////////////////////////////////////////////
//++
//
// CNTException::FormatErrorMessage
//
// Routine Description:
// Format the error message represented by the exception.
//
// Arguments:
// lpszError [OUT] String in which to return the error message.
// nMaxError [IN] Maximum length of the output string.
// pnHelpContext [OUT] Help context for the error message.
// bIncludeID [IN] Include the ID in the message.
//
// Return Value:
// TRUE Message available.
// FALSE No message available.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CNTException::FormatErrorMessage(
LPTSTR lpszError,
UINT nMaxError,
PUINT pnHelpContext,
BOOL bIncludeID
)
{
DWORD dwResult;
TCHAR szNtMsg[1024];
// Format the NT status code.
::FormatErrorMessage( m_sc, szNtMsg, sizeof( szNtMsg ) / sizeof( TCHAR ) );
// Format the message with the operation string.
FormatWithOperation( lpszError, nMaxError, szNtMsg );
// Add the error ID.
if ( bIncludeID )
{
UINT nMsgLength = _tcslen( lpszError );
TCHAR szErrorFmt[EXCEPT_MAX_OPER_ARG_LENGTH];
if ( nMsgLength - 1 < nMaxError )
{
dwResult = ::LoadString( EXC_GetResourceInstance(), IDS_ERROR_MSG_ID, szErrorFmt, (sizeof( szErrorFmt ) / sizeof( TCHAR )) );
ASSERT( dwResult != 0 );
::_sntprintf( &lpszError[nMsgLength], nMaxError - nMsgLength - 1, szErrorFmt, m_sc, m_sc );
} // if: there is room for the error ID
} // if: error ID should be included
return TRUE;
} //*** CNTException::FormatErrorMessage()
//***************************************************************************
/////////////////////////////////////////////////////////////////////////////
// Global Functions
/////////////////////////////////////////////////////////////////////////////
static CNTException gs_nte( ERROR_SUCCESS, NULL, NULL, NULL, FALSE );
static CExceptionWithOper gs_ewo( NULL, NULL, NULL, FALSE );
/////////////////////////////////////////////////////////////////////////////
//++
//
// ThrowStaticException
//
// Purpose:
// Throw the static NT Exception.
//
// Arguments:
// sc [IN] NT status code.
// idsOperation [IN] String ID for operation occurring during exception.
// pszOperArg1 [IN] 1st argument to operation string.
// pszOperArg2 [IN] 2nd argument to operation string.
//
// Returns:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void ThrowStaticException(
IN SC sc,
IN UINT idsOperation,
IN LPCTSTR pszOperArg1,
IN LPCTSTR pszOperArg2
)
{
gs_nte.SetOperation( sc, idsOperation, pszOperArg1, pszOperArg2 );
TraceError( gs_nte );
throw &gs_nte;
} //*** ThrowStaticException()
/////////////////////////////////////////////////////////////////////////////
//++
//
// ThrowStaticException
//
// Purpose:
// Throw the static Cluster Administrator Exception.
//
// Arguments:
// idsOperation [IN] String ID for operation occurring during exception.
// pszOperArg1 [IN] 1st argument to operation string.
// pszOperArg2 [IN] 2nd argument to operation string.
//
// Returns:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void ThrowStaticException(
IN UINT idsOperation,
IN LPCTSTR pszOperArg1,
IN LPCTSTR pszOperArg2
)
{
gs_ewo.SetOperation( idsOperation, pszOperArg1, pszOperArg2 );
TraceError( gs_ewo );
throw &gs_ewo;
} //*** ThrowStaticException()
/////////////////////////////////////////////////////////////////////////////
//++
//
// FormatErrorMessage
//
// Routine Description:
// Format the error message represented by the exception.
//
// Arguments:
// sc [IN] Status code.
// lpszError [OUT] String in which to return the error message.
// nMaxError [IN] Maximum length of the output string.
//
// Return Value:
// TRUE Message available.
// FALSE No message available.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL FormatErrorMessage(
DWORD sc,
LPTSTR lpszError,
UINT nMaxError
)
{
DWORD _cch;
// Format the NT status code from the system.
_cch = FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
sc,
MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ),
lpszError,
nMaxError,
0
);
if ( _cch == 0 )
{
Trace( g_tagError, _T("Error %d getting message from system for error code %d"), GetLastError(), sc );
// Format the NT status code from NTDLL since this hasn't been
// integrated into the system yet.
_cch = FormatMessage(
FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS,
GetModuleHandle( _T("NTDLL.DLL") ),
sc,
MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ),
lpszError,
nMaxError,
0
);
if ( _cch == 0 )
{
#ifdef _DEBUG
DWORD _sc = GetLastError();
_sc=_sc;
Trace( g_tagError, _T("Error %d getting message from NTDLL.DLL for error code %d"), _sc, sc );
#endif
lpszError[0] = _T('\0');
} // if: error formatting status code from NTDLL
} // if: error formatting status code from system
return TRUE;
} //*** FormatErrorMessage()