Application Security Testing: An Integral Part of DevOps


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 Codeguru.com, the number one developer site. Co-founder of Codexpert.ro, a website dedicated to Romanian C++ developers.



  • Good lookin exception class

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

    Nice Ovi!

  • You must have javascript enabled in order to post comments.

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

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date
We have made updates to our Privacy Policy to reflect the implementation of the General Data Protection Regulation.