// WinException.h: interface for the CWinException class. // Copyright (C) Alexey Veremenko 2009. All rights reserved. // Overview: // // Use this class to track COM/Win32 errors. // It checks return value for failure and throws if an error occured. // Several kinds of 'wrap' functions provided, even MFC exception could be wrapped. // Typical use is: HR(pComPtr->SomeCall(...)), or WE(::CopyFile(...)) // Also exceptions with user messages allowed: USR_EX("My error"), // note that corresponding wrap functions ANSI and UNICODE supportable. // Look for more samples in TestCase() member function defined .cpp file // ////////////////////////////////////////////////////////////////////// #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #ifndef __WINEXCEPTION_H_ #define __WINEXCEPTION_H_ // ATL required #include <atlbase.h> // COM support header #include <comdef.h> // _tcsncpy() used #include <string.h> // Disable claims on throw() #pragma warning( disable : 4290 ) // Use MFC assertions if possible #ifndef ASSERT #define ASSERT ATLASSERT #endif class CWinException { // Attributes protected: // Maximum length of error describing string enum { DESC_LEN = 1024 }; // Error description string TCHAR m_szDescription[DESC_LEN]; // Exception types enum ErrorType { eWinError, eComError, eUserDefined, eUserResourceString }; // Type of this exception ErrorType m_eType; // Win32/COM error value union { HRESULT m_hrComError; DWORD m_dwWinError; UINT m_uResID; }; // Construction/Destruction protected: // Construct from Win32 error code inline CWinException(DWORD dwWinError) throw() { m_eType = eWinError; m_dwWinError = dwWinError; m_szDescription[0] = 0; ASSERT(CheckBreakPoint()); } // Construct from COM HRESULT value inline CWinException(HRESULT hrComError) throw() { m_eType = eComError; m_hrComError = hrComError; m_szDescription[0] = 0; ASSERT(CheckBreakPoint()); } // Construct from resource string inline CWinException(UINT uID) throw() { m_eType = eUserResourceString; m_uResID = uID; m_szDescription[0] = 0; ASSERT(CheckBreakPoint()); } // Construct from user provided description inline CWinException(LPCTSTR pszDesc) throw() { m_eType = eUserDefined; ASSERT(pszDesc != NULL); ::_tcsncpy(m_szDescription, pszDesc, DESC_LEN); m_szDescription[DESC_LEN-1] = 0; ASSERT(CheckBreakPoint()); } // Construct from _com_error exception inline CWinException(const _com_error& e) throw() { m_eType = eUserDefined; ::_tcsncpy(m_szDescription, e.ErrorMessage(), DESC_LEN); ASSERT(CheckBreakPoint()); } #ifdef __AFX_H__ // Construct from MFC exception inline CWinException(CException* p) throw() { m_eType = eUserDefined; ASSERT(p != NULL); p->GetErrorMessage(static_cast(m_szDescription), DESC_LEN); p->Delete(); ASSERT(CheckBreakPoint()); } #endif public: inline virtual ~CWinException() throw() {} // Operations public: // Handle COM result inline static void WrapComError(HRESULT hRes) throw(CWinException) { if (FAILED(hRes)) throw CWinException(hRes); } // Handle Win32 error inline static void WrapWinError(DWORD dwCode) throw(CWinException) { if (dwCode != NO_ERROR) throw CWinException(dwCode); } // Handle Win32 result inline static void WrapWinError(BOOL bRes) throw(CWinException) { if (bRes == FALSE) WrapWinError(::GetLastError()); } // Handle user exception from resource string inline static void WrapUserError(UINT uID) throw(CWinException) { throw CWinException(uID); } // Handle user exception from UNICODE string inline static void WrapUserError(LPCWSTR pszDesc) throw(CWinException) { USES_CONVERSION; if (pszDesc != NULL) throw CWinException(W2T(const_cast(pszDesc))); } // Handle user exception from ANSI string inline static void WrapUserError(LPCSTR pszDesc) throw(CWinException) { USES_CONVERSION; if (pszDesc != NULL) throw CWinException(A2T(const_cast(pszDesc))); } // Handle _com_error exception inline static void WrapComException(const _com_error& e) throw(CWinException) { throw CWinException(e); } #ifdef __AFX_H__ // Handle MFC exception inline static void WrapMfcError(CException* p) throw(CWinException) { if (p != NULL) throw CWinException(p); } #endif // Get error description inline LPCTSTR GetErrorMessage() { GetDescriptionFromCode(); // Prepare message return m_szDescription; } // Implementation protected: bool GetComMessage(HRESULT hrErr); bool GetWinMessage(DWORD dwErr); bool GetResMessage(UINT uID); bool GetErrorInfoMessage(); bool GetUnexpectedMessage(); void GetDescriptionFromCode(); // Diagnostic support private: // This function is called from any constructor. // Set a breakpoint inside and catch the source of any exception inline bool CheckBreakPoint() { return true; } public: // Show messagebox with description or write to console // Always returns true for convinient use in debug mode: ASSERT(e.Display()); bool Display(); // Sample usage static void TestCase(); }; // Synonym typedef CWinException CWEx; // Throw new exception macros #define HR(hRes) CWEx::WrapComError(hRes); #define WE(bRes) CWEx::WrapWinError(bRes); #define WE_CODE(dwRes) CWEx::WrapWinError((DWORD)dwRes); #define USR_EX(uID) CWEx::WrapUserError(uID); #endif // __WINEXCEPTION_H_