33

I'm porting some sockets code from Linux to Windows.

In Linux, I could use strerror() to convert an errno code into a human-readable string.

MSDN documentation shows equivalent strings for each error code returned from WSAGetLastError(), but I don't see anything about how to retrieve those strings. Will strerror() work here too?

How can I retrieve human-readable error strings from Winsock?

Drew Hall
  • 28,429
  • 12
  • 61
  • 81

3 Answers3

43
wchar_t *s = NULL;
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 
               NULL, WSAGetLastError(),
               MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
               (LPWSTR)&s, 0, NULL);
fprintf(stderr, "%S\n", s);
LocalFree(s);
Stefan Profanter
  • 6,458
  • 6
  • 41
  • 73
mxcl
  • 26,392
  • 12
  • 99
  • 98
21

As the documentation for WSAGetLastError says you can use FormatMessage to obtain a text version of the error message.

You need to set FORMAT_MESSAGE_FROM_SYSTEM in the dwFlags parameter and pass the error code as the dwMessage parameter.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • 1
    Thanks--I just discovered that myself. I need to remember to look at the online MSDN (vs. the off-line copy installed on my laptop!). – Drew Hall Aug 03 '10 at 21:49
11

A slightly simpler version of mxcl's answer, which removes the need for malloc/free and the risks implicit therein, and which handles the case where no message text is available (since Microsoft doesn't document what happens then):

int
   err;

char
   msgbuf [256];   // for a message up to 255 bytes.


msgbuf [0] = '\0';    // Microsoft doesn't guarantee this on man page.

err = WSAGetLastError ();

FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,   // flags
               NULL,                // lpsource
               err,                 // message id
               MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),    // languageid
               msgbuf,              // output buffer
               sizeof (msgbuf),     // size of msgbuf, bytes
               NULL);               // va_list of arguments

if (! *msgbuf)
   sprintf (msgbuf, "%d", err);  // provide error # if no string available
Stan Sieler
  • 729
  • 7
  • 16