545 lines
14 KiB
C++
545 lines
14 KiB
C++
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Copyright (c) 1996 Microsoft Corporation
|
||
|
//
|
||
|
// Module Name:
|
||
|
// ExcOper.cpp
|
||
|
//
|
||
|
// Abstract:
|
||
|
// Implementation of exception classes.
|
||
|
//
|
||
|
// Author:
|
||
|
// David Potter (davidp) May 20, 1996
|
||
|
//
|
||
|
// Revision History:
|
||
|
//
|
||
|
// Notes:
|
||
|
// stdafx.h, TraceTag.h, and resource.h are all pulled from the project
|
||
|
// directory.
|
||
|
//
|
||
|
// stdafx.h must have an IDS typedef and disable some W4 warnings.
|
||
|
//
|
||
|
// TraceTag.h must define TraceError.
|
||
|
//
|
||
|
// resource.h must define IDS_UNKNOWN_ERROR, and the string must be
|
||
|
// defined something like "Error %d (0x%08.8x)." in the resource file.
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#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
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CExceptionWithOper
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
IMPLEMENT_DYNAMIC(CExceptionWithOper, CException)
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//++
|
||
|
//
|
||
|
// CExceptionWithOper::CExceptionWithOper
|
||
|
//
|
||
|
// 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.
|
||
|
//
|
||
|
//--
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
CExceptionWithOper::CExceptionWithOper(
|
||
|
IN IDS idsOperation,
|
||
|
IN LPCTSTR pszOperArg1,
|
||
|
IN LPCTSTR pszOperArg2
|
||
|
)
|
||
|
{
|
||
|
SetOperation(idsOperation, pszOperArg1, pszOperArg2);
|
||
|
|
||
|
} //*** CExceptionWithOper::CExceptionWithOper()
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//++
|
||
|
//
|
||
|
// CExceptionWithOper::CExceptionWithOper
|
||
|
//
|
||
|
// 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.
|
||
|
// bAutoDelete [IN] Auto-delete the exception in Delete().
|
||
|
//
|
||
|
// Return Value:
|
||
|
// None.
|
||
|
//
|
||
|
//--
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
CExceptionWithOper::CExceptionWithOper(
|
||
|
IN IDS idsOperation,
|
||
|
IN LPCTSTR pszOperArg1,
|
||
|
IN LPCTSTR pszOperArg2,
|
||
|
IN BOOL bAutoDelete
|
||
|
) : CException(bAutoDelete)
|
||
|
{
|
||
|
SetOperation(idsOperation, pszOperArg1, pszOperArg2);
|
||
|
|
||
|
} //*** CExceptionWithOper::CExceptionWithOper()
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//++
|
||
|
//
|
||
|
// CExceptionWithOper::~CExceptionWithOper
|
||
|
//
|
||
|
// Routine Description:
|
||
|
// Destructor.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// None.
|
||
|
//
|
||
|
// Return Value:
|
||
|
// None.
|
||
|
//
|
||
|
//--
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
CExceptionWithOper::~CExceptionWithOper(void)
|
||
|
{
|
||
|
} //*** CExceptionWithOper::~CExceptionWithOper()
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//++
|
||
|
//
|
||
|
// CExceptionWithOper::GetErrorMessage
|
||
|
//
|
||
|
// 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.
|
||
|
// pnHelpContext [OUT] Help context for the error message.
|
||
|
//
|
||
|
// Return Value:
|
||
|
// None.
|
||
|
//
|
||
|
//--
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
BOOL CExceptionWithOper::GetErrorMessage(
|
||
|
LPTSTR lpszError,
|
||
|
UINT nMaxError,
|
||
|
PUINT pnHelpContext
|
||
|
)
|
||
|
{
|
||
|
// Format the operation string.
|
||
|
FormatWithOperation(lpszError, nMaxError, NULL);
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
} //*** CExceptionWithOper::GetErrorMessage()
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//++
|
||
|
//
|
||
|
// 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:
|
||
|
// None.
|
||
|
//
|
||
|
//--
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
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 = AfxMessageBox(szErrorMessage, nType, nHelpContext);
|
||
|
else
|
||
|
{
|
||
|
if (nError == 0)
|
||
|
nError = AFX_IDP_NO_ERROR_AVAILABLE;
|
||
|
nDisposition = AfxMessageBox(nError, nType, nHelpContext);
|
||
|
}
|
||
|
return nDisposition;
|
||
|
|
||
|
} //*** CExceptionWithOper::ReportError()
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//++
|
||
|
//
|
||
|
// 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 IDS idsOperation,
|
||
|
IN LPCTSTR pszOperArg1,
|
||
|
IN LPCTSTR pszOperArg2
|
||
|
)
|
||
|
{
|
||
|
m_idsOperation = idsOperation;
|
||
|
|
||
|
if (pszOperArg1 == NULL)
|
||
|
m_szOperArg1[0] = _T('\0');
|
||
|
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');
|
||
|
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(AfxGetApp()->m_hInstance, 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
|
||
|
);
|
||
|
// ::_sntprintf(szFmtOperation, (sizeof(szFmtOperation) / sizeof(TCHAR)) - 1, szOperation, m_szOperArg1, m_szOperArg2);
|
||
|
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);
|
||
|
else
|
||
|
::_tcsncpy(lpszError, szFmtOperation, nMaxError - 1);
|
||
|
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');
|
||
|
} // else: no operation string specified
|
||
|
|
||
|
} //*** CExceptionWithOper::FormatWithOperation()
|
||
|
|
||
|
|
||
|
//***************************************************************************
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CException
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
IMPLEMENT_DYNAMIC(CNTException, CExceptionWithOper)
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//++
|
||
|
//
|
||
|
// CNTException::CNTException
|
||
|
//
|
||
|
// Routine Description:
|
||
|
// Constructor.
|
||
|
//
|
||
|
// 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.
|
||
|
//
|
||
|
// Return Value:
|
||
|
// None.
|
||
|
//
|
||
|
//--
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
CNTException::CNTException(
|
||
|
IN SC sc,
|
||
|
IN IDS idsOperation,
|
||
|
IN LPCTSTR pszOperArg1,
|
||
|
IN LPCTSTR pszOperArg2
|
||
|
) : CExceptionWithOper(idsOperation, pszOperArg1, pszOperArg2)
|
||
|
{
|
||
|
m_sc = sc;
|
||
|
|
||
|
} //*** CNTException::CNTException()
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//++
|
||
|
//
|
||
|
// CNTException::CNTException
|
||
|
//
|
||
|
// Routine Description:
|
||
|
// Constructor.
|
||
|
//
|
||
|
// 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.
|
||
|
// bAutoDelete [IN] Auto-delete the exception in Delete().
|
||
|
//
|
||
|
// Return Value:
|
||
|
// None.
|
||
|
//
|
||
|
//--
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
CNTException::CNTException(
|
||
|
IN SC sc,
|
||
|
IN IDS idsOperation,
|
||
|
IN LPCTSTR pszOperArg1,
|
||
|
IN LPCTSTR pszOperArg2,
|
||
|
IN BOOL bAutoDelete
|
||
|
) : CExceptionWithOper(idsOperation, pszOperArg1, pszOperArg2, bAutoDelete)
|
||
|
{
|
||
|
m_sc = sc;
|
||
|
|
||
|
} //*** CNTException::CNTException()
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//++
|
||
|
//
|
||
|
// CNTException::~CNTException
|
||
|
//
|
||
|
// Routine Description:
|
||
|
// Destructor.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// None.
|
||
|
//
|
||
|
// Return Value:
|
||
|
// None.
|
||
|
//
|
||
|
//--
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
CNTException::~CNTException(void)
|
||
|
{
|
||
|
} //*** CNTException::~CNTException()
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//++
|
||
|
//
|
||
|
// CNTException::GetErrorMessage
|
||
|
//
|
||
|
// 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.
|
||
|
// pnHelpContext [OUT] Help context for the error message.
|
||
|
//
|
||
|
// Return Value:
|
||
|
// TRUE Message available.
|
||
|
// FALSE No message available.
|
||
|
//
|
||
|
//--
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
BOOL CNTException::GetErrorMessage(
|
||
|
LPTSTR lpszError,
|
||
|
UINT nMaxError,
|
||
|
PUINT pnHelpContext
|
||
|
)
|
||
|
{
|
||
|
DWORD dwResult;
|
||
|
TCHAR szNtMsg[128];
|
||
|
|
||
|
|
||
|
// Format the NT status code from the system.
|
||
|
dwResult = ::FormatMessage(
|
||
|
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||
|
NULL,
|
||
|
m_sc,
|
||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
|
||
|
szNtMsg,
|
||
|
sizeof(szNtMsg) / sizeof(TCHAR),
|
||
|
0
|
||
|
);
|
||
|
if (dwResult == 0)
|
||
|
{
|
||
|
// Format the NT status code from NTDLL since this hasn't been
|
||
|
// integrated into the system yet.
|
||
|
dwResult = ::FormatMessage(
|
||
|
FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||
|
::GetModuleHandle(_T("NTDLL.DLL")),
|
||
|
m_sc,
|
||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
|
||
|
szNtMsg,
|
||
|
sizeof(szNtMsg) / sizeof(TCHAR),
|
||
|
0
|
||
|
);
|
||
|
if (dwResult == 0)
|
||
|
{
|
||
|
TCHAR szErrorFmt[EXCEPT_MAX_OPER_ARG_LENGTH];
|
||
|
|
||
|
dwResult = ::LoadString(AfxGetApp()->m_hInstance, IDS_UNKNOWN_ERROR, szErrorFmt, (sizeof(szErrorFmt) / sizeof(TCHAR)));
|
||
|
ASSERT(dwResult != 0);
|
||
|
::_sntprintf(szNtMsg, sizeof(szNtMsg) / sizeof(TCHAR), szErrorFmt, m_sc, m_sc);
|
||
|
} // if: error formatting status code from NTDLL
|
||
|
} // if: error formatting status code from system
|
||
|
|
||
|
// Format the message with the operation string.
|
||
|
FormatWithOperation(lpszError, nMaxError, szNtMsg);
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
} //*** CNTException::GetErrorMessage()
|
||
|
|
||
|
|
||
|
//***************************************************************************
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// 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 IDS 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 IDS idsOperation,
|
||
|
IN LPCTSTR pszOperArg1,
|
||
|
IN LPCTSTR pszOperArg2
|
||
|
)
|
||
|
{
|
||
|
gs_ewo.SetOperation(idsOperation, pszOperArg1, pszOperArg2);
|
||
|
TraceError(gs_ewo);
|
||
|
throw &gs_ewo;
|
||
|
|
||
|
} //*** ThrowStaticException()
|