How should I use FormatMessage() properly in C++?

Here’s the proper way to get an error message back from the system for an HRESULT (named hresult in this case, or you can replace it with GetLastError()):

LPTSTR errorText = NULL;

FormatMessage(
   // use system message tables to retrieve error text
   FORMAT_MESSAGE_FROM_SYSTEM
   // allocate buffer on local heap for error text
   |FORMAT_MESSAGE_ALLOCATE_BUFFER
   // Important! will fail otherwise, since we're not 
   // (and CANNOT) pass insertion parameters
   |FORMAT_MESSAGE_IGNORE_INSERTS,  
   NULL,    // unused with FORMAT_MESSAGE_FROM_SYSTEM
   hresult,
   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
   (LPTSTR)&errorText,  // output 
   0, // minimum size for output buffer
   NULL);   // arguments - see note 
   
if ( NULL != errorText )
{
   // ... do something with the string `errorText` - log it, display it to the user, etc.

   // release memory allocated by FormatMessage()
   LocalFree(errorText);
   errorText = NULL;
}

The key difference between this and David Hanak’s answer is the use of the FORMAT_MESSAGE_IGNORE_INSERTS flag. MSDN is a bit unclear on how insertions should be used, but Raymond Chen notes that you should never use them when retrieving a system message, as you’ve no way of knowing which insertions the system expects.

FWIW, if you’re using Visual C++ you can make your life a bit easier by using the _com_error class:

{
   _com_error error(hresult);
   LPCTSTR errorText = error.ErrorMessage();
   
   // do something with the error...

   //automatic cleanup when error goes out of scope
}

Not part of MFC or ATL directly as far as I’m aware.

Leave a Comment