The MFC library provides a series of classes for handling exceptions. For example, CFileException can be used for handling exceptions thrown from CFile methods, CMemoryException can be used for handling out-of-memory exceptions thrown by the new operator, and so on.

Sometimes you need to extend MFC by writing your own classes with corresponding exception classes. As long as usually you are using Windows API calls (like MFC generally does), an exception class for handling Windows API errors would be great.

First, let's take a fast look into CException.

CException class

CException is the base class for all other MFC exception classes.
It has two virtual functions:

  • GetErrorMessage - gets a string which describes the error;
  • ReportError - displays a message box showing the error message.
If derive from CException, then you can override one or both of these virtual functions to provide your own error descriptions and message boxes. Now, we can go further and implement the exception class for generic WinAPI errors.

A lite CWinAPIException class

class CWinAPIException : public CException  
   CWinAPIException(DWORD dwError) : m_dwErrorCode(dwError) {}
// Attributes
   DWORD m_dwErrorCode;    // error code given by Windows API 
// Overrides
   virtual BOOL GetErrorMessage(LPTSTR lpszError, UINT nMaxError,
      PUINT pnHelpContext = NULL);
   virtual int ReportError(UINT nType = MB_OK, UINT nMessageID = 0);
// ...
CWinAPIException overrides CException::GetErrorMessage and CException::ReportError (more info about implementation can be found in the attached sources). We could stop here, but no... CWinAPIException can do more.

An improved CWinAPIException class

Usually MFC exception classes only give the error description, as for example "Path not found". Sometimes is useful to have more information such as the exception source (source file name and code line number). CWinAPIException can provide this additional information at the programmer's request. Let's say, in a beta release of an application we can choose to get all the information, while later in a more stable version we can set to display only the error description. Here is the complete CWinAPIException class:

class CWinAPIException : public CException  
// Constructor
   CWinAPIException(DWORD dwError, LPCTSTR pszFile, UINT nLine, COleDateTime& odtTime);

// Attributes
   DWORD m_dwErrorCode;    // error code given by Windows API 
   CString m_strFile;      // the file from which the exception was thrown
   UINT m_nLine;           // the line from which the exception was thrown
   COleDateTime m_odtTime; // date/time when exception occurred
   // switches used for customizing displayed info 
   static bool m_bShowErrorCode, m_bShowTimestamp, m_bShowSource;
// Overrides
   virtual BOOL GetErrorMessage(LPTSTR lpszError, UINT nMaxError,
      PUINT pnHelpContext = NULL);
   virtual int ReportError(UINT nType = MB_OK, UINT nMessageID = 0);
// Operations
   // method for throwing exceptions
   // NOTE: Prefer below macros instead of directly CWinAPIException::Throw call!
   static void Throw(DWORD dwError, LPCTSTR pszFile, UINT nLine);
   // accessors for custom display switches
   static void ShowErrorCode(bool bShowErrorCode) {m_bShowErrorCode = bShowErrorCode;}
   static void ShowSource(bool bShowSource) {m_bShowSource = bShowSource;}
   static void ShowTimestamp(bool bShowTimestamp) {m_bShowTimestamp = bShowTimestamp;}
   static bool IsErrorCodeShown() {return m_bShowErrorCode;}
   static bool IsSourceShown() {return m_bShowSource;}
   static bool IsTimestampShown() {return m_bShowTimestamp;}
// Implementation
   void FormatMessage(CString& strText, LPCTSTR pszSep);
   void FormatMessageFromSystem(CString& strMessage);

There remains just few little things to add. When throwing an exception by calling CWinAPIException::Throw you have to pass the error code dwError, the source (full path and) file name pszFile, and the code line number nLine. The error code is usually retrieved with ::GetLastError. For source file name and line number can be passed the predefined macros __FILE__ and __LINE__, respectively. To make this task easier I have added the following macros to be used instead of CWinAPIException::Throw:

#define WINAPI_THROW_ERROR(e)          CWinAPIException::Throw(e, __FILE__, __LINE__)

// use this macro for functions which return 0 (FALSE) in case of failure
// use this macro for functions which returns NULL in case of failure 
// use this macro which return ERROR_SUCCESS in case of success and an error code otherwise


  • Using WINAPI_VERIFY_TRUE to throw an exception in case of failure (the function returns FALSE)
       BOOL bRet = ::AppendMenu(hMenu, MF_STRING, nID, pszNewItem);
  • Using WINAPI_VERIFY_NOT_NULL to throw an exception in case of failure (the function returns NULL)
       SC_HANDLE hSCManager = ::OpenSCManager(NULL, NULL, GENERIC_READ);
  • Using WINAPI_VERIFY_ERROR_SUCCESS to throw an exception in case of failure (the function returns an error code)
       UINT nRet = ::RegOpenKey(HKEY_LOCAL_MACHINE, pszPath, &hKey);
  • Catching CWinAPIException exceptions
          // some code which can throw CWinAPIException
       catch(CWinAPIException* e)
  • Prevent showing error code

Demo application

ExceptionDemo is a simple SDI application that demonstrates how to use CWinAPIException. You can choose which additional info has to be shown (error code, source, and timestamp), then push "Test exception" button and enjoy.

Related articles

About the Author

Ovidiu Cucu

Graduated at "Gh. Asachi" Technical University - Iasi, Romania. Programming in C++ using Microsoft technologies since 1995. Microsoft MVP awardee since 2006. Moderator and article reviewer at, the number one developer site. Co-founder of, a website dedicated to Romanian C++ developers.



  • Do Herb Erectile Dysfunction Pills Offer Stronger And Rock Hard Erection?

    Posted by adeeffifielm on 06/21/2013 06:48am

    Why To Use Erectile Dysfunction Herbal Cure For Treating Impotence Problems? If medical causes and medications are ruled out, many times hormonal therapy will be attempted [url= ] viagra while working out [/url] see much more Masturbation Erectile Dysfunction Cures

  • Good lookin exception class

    Posted by ahoodin on 07/27/2009 12:44pm

    Nice Ovi!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Anthony Christie, the Chief Marketing Officer for Level Communications, is responsible for customer experience, worldwide marketing and product management. In this informative asset, he shares his insights into why a private network connection to cloud-bases applications is the right decision for your enterprise. Download now to find out more.

  • Moving from an on-premises environment to Office 365 does not remove the need to plan for disruptions or reduce the business risk requirements for protecting email services. If anything, some risks increase with a move to the cloud. Read how to ease the transition every business faces if considering or already migrating to cloud email. This white paper discusses: Setting expectations when migrating to Office 365 Understanding the implications of relying solely on Exchange Online security Necessary archiving …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date