//////////////////////////////////////////////////////////////////////////////// // // Filename : Excption.h // Purpose : To define the generic exception. // // Project : pqs // Component: Common // // Author : urib // // Log: // Jan 19 1997 urib Creation // Mar 2 1997 urib Add win32 error exception. // Jun 25 1997 urib Move definition of translator class to header. // Change name to CExceptionTranslatorSetter. // This is done because every thread needs to use // it as it enters our scope. // Sep 16 1997 urib Supply default parameter to CWin32ErrorException. // Oct 21 1997 urib Added macros to throw exceptions that know their // location. // Feb 12 1998 urib Print error information from within Hresult // Exception. // Feb 17 1998 urib Move translator code from cpp to header. // Jun 22 1998 yairh add GetFile & GetLine methods // Jul 19 1998 urib Specify calling convention on exception translator // function. // Aug 17 1998 urib Remove the ... catch clause. // Jan 10 1999 urib Support a throwing new. // Jan 21 1999 urib Fix THROW macros to force arguments to be WCHAR // string even in non UNICODE environment. // Feb 1 1999 urib Add null pointer exception. Add throwing new to // COM macros. // Mar 15 2000 urib Add missing "leaving function" trace. // Apr 12 2000 urib Move new manipulation to memory management module. // Sep 6 2000 urib Fix EnterLeave macros. // Oct 25 2000 urib Check allocation failure on Generic exception. // //////////////////////////////////////////////////////////////////////////////// #ifndef EXCPTION_H #define EXCPTION_H #include #include #include "Tracer.h" #include "AutoPtr.h" #include "FtfError.h" //////////////////////////////////////////////////////////////////////////////// // // CException class definition // //////////////////////////////////////////////////////////////////////////////// class CException { public: CException(PWSTR pwszFile = NULL, ULONG ulLine = 0) { m_pwszFile = pwszFile; m_ulLine = ulLine; Trace( elError, tagError,( "CException:" "on file %S, line %d", (pwszFile ? pwszFile : L"Fix this exception to return " L"a file and line"), ulLine)); } // Get an error string. virtual BOOL GetErrorMessage( PWSTR pwszError, UINT nMaxError, PUINT pnHelpContext = NULL ) = NULL; #if 0 // Notify via message box. virtual int ReportError( UINT nType = MB_OK, UINT nMessageID = 0 ) { UNREFERENCED_PARAMETER(nMessageID); WCHAR rwchErrorString[1000]; GetErrorMessage(rwchErrorString, 1000); return MessageBoxW( NULL, rwchErrorString, L"Exception occured", nType); } #endif virtual ~CException(){}; PWSTR GetFile() { return m_pwszFile; } ULONG GetLine() { return m_ulLine; } virtual void PrintErrorMsg( char* pszFunction, ULONG_PTR dwThis, char* pszFile, int iLine, TAG tag = 0) { WCHAR rwchError[1000]; GetErrorMessage(rwchError, sizeof(rwchError)/sizeof(WCHAR)); Trace( elError, tag,( "COM Exception Catcher:" "%s (this = %#x) threw an exception. " "Error is message\"%S\". " "Caught in file %s line %d.", pszFunction, dwThis, rwchError, pszFile, iLine)); } protected: PWSTR m_pwszFile; ULONG m_ulLine; }; //////////////////////////////////////////////////////////////////////////////// // // CStructuredException class definition // //////////////////////////////////////////////////////////////////////////////// class CStructuredException : public CException { public: CStructuredException(UINT uiSeCode) :m_uiSeCode(uiSeCode){}; // Get an error string. virtual BOOL GetErrorMessage( PWSTR pwszError, UINT nMaxError, PUINT pnHelpContext = NULL ) { UNREFERENCED_PARAMETER(pnHelpContext); int iRet; iRet = _snwprintf( pwszError, nMaxError, L"Structured exception %#X", GetExceptionCode()); pwszError[nMaxError - 1] = '\0'; return iRet; } // Return the exception code. UINT GetExceptionCode() { return m_uiSeCode; } // The translator. static void _cdecl Translator(UINT ui, EXCEPTION_POINTERS*) { throw CStructuredException(ui); } private: UINT m_uiSeCode; }; //////////////////////////////////////////////////////////////////////////////// // // CGenericException class definition // //////////////////////////////////////////////////////////////////////////////// class CGenericException : public CException { public: CGenericException(LPWSTR pwszTheError) { m_apwszTheError = _wcsdup(pwszTheError); if (!m_apwszTheError.IsValid()) { m_apwszTheError = L"Memory allocation failed in the exception object creation"; m_apwszTheError.Detach(); } } // Get an error string. virtual BOOL GetErrorMessage( PWSTR pwszError, UINT nMaxError, PUINT pnHelpContext = NULL ) { UNREFERENCED_PARAMETER(pnHelpContext); int iRet; iRet = _snwprintf( pwszError, nMaxError, L"%s", m_apwszTheError); pwszError[nMaxError - 1] = '\0'; return iRet; } private: CAutoMallocPointer m_apwszTheError; }; //////////////////////////////////////////////////////////////////////////////// // // CHresultException class definition // //////////////////////////////////////////////////////////////////////////////// class CHresultException : public CException { public: CHresultException(HRESULT hrResult = E_FAIL, PWSTR pwszFile = NULL, ULONG ulLine = 0) :m_hrResult(hrResult), CException(pwszFile, ulLine) { WCHAR rwchError[1000]; GetErrorMessage(rwchError, sizeof(rwchError)/sizeof(WCHAR)); Trace( elError, tagError,( "Exception:" "%S", rwchError)); } // Get an error string. virtual BOOL GetErrorMessage( PWSTR pwszError, UINT nMaxError, PUINT pnHelpContext = NULL ) { UNREFERENCED_PARAMETER(pnHelpContext); int iRet; iRet = _snwprintf( pwszError, nMaxError, L"HResult exception %#X", m_hrResult); pwszError[nMaxError - 1] = '\0'; return iRet; } operator HRESULT() { return m_hrResult; } virtual void PrintErrorMsg( char* pszFunction, ULONG_PTR dwThis, char* pszFile, int iLine, DWORD dwError, TAG tag = 0) { WCHAR rwchError[1000]; GetErrorMessage(rwchError, sizeof(rwchError)/sizeof(WCHAR)); Trace( elError, tag,( "COM Exception Catcher:" "%s (this = %#x) threw an hresult(%#x) exception. " "Error message is \"%S\". " "Caught in file %s line %d.", pszFunction, dwThis, dwError, rwchError, pszFile, iLine)); } protected: HRESULT m_hrResult; }; //////////////////////////////////////////////////////////////////////////////// // // CWin32ErrorException class definition // //////////////////////////////////////////////////////////////////////////////// class CWin32ErrorException : public CHresultException { public: CWin32ErrorException(LONG lResult = GetLastError(), PWSTR pwszFile = NULL, ULONG ulLine = 0) :CHresultException(MAKE_FTF_E(lResult), pwszFile, ulLine){} }; //////////////////////////////////////////////////////////////////////////////// // // CMemoryException class definition // //////////////////////////////////////////////////////////////////////////////// class CMemoryException : public CWin32ErrorException { public: CMemoryException(PWSTR pwszFile = NULL, ULONG ulLine = 0) :CWin32ErrorException(E_OUTOFMEMORY, pwszFile, ulLine){}; // Get an error string. virtual BOOL GetErrorMessage( PWSTR pwszError, UINT nMaxError, PUINT pnHelpContext = NULL ) { UNREFERENCED_PARAMETER(pnHelpContext); int iRet; iRet = _snwprintf(pwszError, nMaxError, L"Memory exception !!!"); pwszError[nMaxError - 1] = '\0'; return iRet; } }; //////////////////////////////////////////////////////////////////////////////// // // Macros for exception throwing and catching // //////////////////////////////////////////////////////////////////////////////// #define __PQWIDE(str) L##str #define PQWIDE(str) __PQWIDE(str) #define THROW_MEMORY_EXCEPTION() \ throw CMemoryException(PQWIDE(__FILE__), __LINE__) #define THROW_HRESULT_EXCEPTION(hr) \ throw CHresultException(hr, PQWIDE(__FILE__), __LINE__) #define THROW_WIN32ERROR_EXCEPTION(hr) \ throw CWin32ErrorException(hr, PQWIDE(__FILE__), __LINE__) #if (defined (DEBUG) && !defined(_NO_TRACER)) || defined(USE_TRACER) class CEnterLeavePrinting { public: CEnterLeavePrinting(TAG tag, char* pszFuncName, void* pThisPointer) :m_tag(tag) ,m_pszFuncName(pszFuncName) ,m_pThisPointer(pThisPointer) { Trace( elVerbose, m_tag,( "Entering %s (this = %#x):", m_pszFuncName, pThisPointer)); } ~CEnterLeavePrinting() { Trace( elVerbose, m_tag,( "Leaving %s (this = %#x):", m_pszFuncName, m_pThisPointer)); } protected: TAG m_tag; char* m_pszFuncName; void* m_pThisPointer; }; // // Use this macro at the beginning of an HRESULT COM method // #define BEGIN_STDMETHOD(function, tag) \ CEnterLeavePrinting print(tag, #function, this); \ try \ { // // Use this macro at the end of an HRESULT COM method // #define END_STDMETHOD(function, tag) \ } \ catch(CHresultException& hre) \ { \ hre.PrintErrorMsg( \ #function, \ (ULONG_PTR)this, \ __FILE__, \ __LINE__, \ (HRESULT)hre), \ tag; \ return hre; \ } \ catch(CException& e) \ { \ e.PrintErrorMsg( \ #function, \ (ULONG_PTR)this, \ __FILE__, \ __LINE__, \ tag); \ return E_FAIL; \ } // // Use this macro at the end of a void COM method // #define END_VOIDMETHOD(function, tag) \ } \ catch(CHresultException& hre) \ { \ hre.PrintErrorMsg( \ #function, \ (ULONG_PTR)this, \ __FILE__, \ __LINE__, \ tag, \ (HRESULT)hre); \ } \ catch(CException& e) \ { \ e.PrintErrorMsg( \ #function, \ (ULONG_PTR)this, \ __FILE__, \ __LINE__, \ tag \ ); \ } #else // // Use this macro at the beginning of an HRESULT COM method // #define BEGIN_STDMETHOD(function, tag) \ try \ { // // Use this macro at the end of an HRESULT COM method // #define END_STDMETHOD(function, tag) \ } \ catch(CHresultException& hre) \ { \ hre.PrintErrorMsg( \ #function, \ (ULONG_PTR)this, \ __FILE__, \ __LINE__, \ (HRESULT)hre); \ return hre; \ } \ catch(CException& e) \ { \ e.PrintErrorMsg( \ #function, \ (ULONG_PTR)this, \ __FILE__, \ __LINE__); \ return E_FAIL; \ } // // Use this macro at the end of a void COM method // #define END_VOIDMETHOD(function, tag) \ } \ catch(CHresultException& hre) \ { \ hre.PrintErrorMsg( \ #function, \ (ULONG_PTR)this, \ __FILE__, \ __LINE__, \ (HRESULT)hre); \ } \ catch(CException& e) \ { \ e.PrintErrorMsg( \ #function, \ (ULONG_PTR)this, \ __FILE__, \ __LINE__); \ } #endif // DEBUG #endif /* EXCPTION_H */