///////////////////////////////////////////////////////////////////////////// // // 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 #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()