Converting a CInternetException to a printable string

Home
Back To Tips Page

 I have recently been doing some Internet programming with the MFC classes, such as CInternetSession. One problem I had to deal with was the fact that these classes will sometimes throw exceptions, and I wanted a printable representation of the error. A bit of forensics showed that wininet.dll contains a MESSAGETABLE resource, although to discover this you have to know that a MESSAGETABLE is resource type 11. So I set up a function to convert WinInet error codes, as encoded in the CInternetException, to a CString.

For example, the OpenURL operation can throw an exception. To handle this, I use a TRY/CATCH construct:

CInternetSession session;
CStdioFile * file;
TRY {
      file = session.OpenURL(URL);
     }
 CATCH(CInternetException, e)
     {
      CString s = getInetError(e->m_dwError);
      // here I add the error message to a CListBox
      c_Status.AddString(s);
      return;
     }

The function getInetError uses FormatMessage to convert the message

CString getInetError(DWORD err)
    {
     HANDLE h = ::GetModuleHandle(_T("WinINet.dll"));
     if(h != NULL)
	{ /* got module */
	 LPTSTR p;
	 if(::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
			    FORMAT_MESSAGE_FROM_HMODULE,
			    (LPCVOID)h,
			    err,
			    0, // default language
			    (LPTSTR)&p,
			    0,
			    NULL) != 0)
	    { /* format succeeded */
	     CString s(p);
	     s.Replace(_T("\r\n"), _T(""));
	     return s;
	    } /* format succeeded */
	} /* got module */

     CString s;
     s.Format(_T("%d"), err);
     return s;
    } // getInetError

The explanation of the code is as follows:

The WinInet.dll module is already mapped into the address space (else I would not see the exception being thrown or otherwise have a CInternetException. So I use GetModuleHandle (instead of LoadLibrary, which would increment the reference count) to get the module handle. If this is successful, I call FormatMessage using FORMAT_MESSAGE_FROM_HMODULE and this handle to format the error code. If the error code is a valid WinINet error, FormatMessage will succeed. In this case, I want to remove the gratuitous newline that FormatMessage  insists on appending, so I replace "\r\n" with the empty string.

If the module handle cannot be obtained, or the FormatMessage fails, the code drops down to formatting the error code as a decimal integer. A LoadString operation could be used to get a nicer formatting string from the STRINGTABLE, e.g.,

CString fmt;
fmt.LoadString(IDS_NICE_ERROR_MESSAGE); // "WinINet error %d"
CString s;
s.Format(fmt, err);
return s;

[Dividing Line Image]

The views expressed in these essays are those of the author, and in no way represent, nor are they endorsed by, Microsoft.

Send mail to newcomer@flounder.com with questions or comments about this web site.
Copyright © 1999-2003 The Joseph M. Newcomer Co. All Rights Reserved.
Last modified: May 14, 2011