Click here to Skip to main content
15,867,997 members
Articles / Desktop Programming / MFC
Article

XWSAError - a DLL for Winsock error lookup

Rate me:
Please Sign up or sign in to vote.
4.89/5 (19 votes)
6 Jan 2005CPOL4 min read 54K   609   16   4
Add Winsock error lookup to your C++ or VB app with this DLL.

Introduction

Recently I was working on my umpteenth client/server app using Winsock, and once again I found myself embedding Winsock error descriptions in the app. Not being under the usual pressure (read: I hadn't missed the deadline yet) I decided to centralize the Winsock error descriptions in a handy DLL.

Looking around for some authoritative source for Winsock errors, I found a table on this page on MSDN: Windows Sockets Error Codes.

Here are the first few entries from that table:

Return code/valueDescription
WSAEINTR
10004
Interrupted function call.
A blocking operation was interrupted by a call to WSACancelBlockingCall.
WSAEACCES
10013
Permission denied.
An attempt was made to access a socket in a way forbidden by its access permissions. An example is using a broadcast address for sendto without broadcast permission being set using setsockopt(SO_BROADCAST).

Another possible reason for the WSAEACCES error is that when the bind function is called (on Windows NT 4 SP4 or later), another application, service, or kernel mode driver is bound to the same address with exclusive access. Such exclusive access is a new feature of Windows NT 4 SP4 and later, and is implemented by using the SO_EXCLUSIVEADDRUSE option.

WSAEFAULT
10014
Bad address.
The system detected an invalid pointer address in attempting to use a pointer argument of a call. This error occurs if an application passes an invalid pointer value, or if the length of the buffer is too small. For instance, if the length of an argument, which is a sockaddr structure, is smaller than the sizeof(sockaddr).

Looking at this table, it is clear that there are four items of interest for each error code:

  1. The error code - for example, WSAEFAULT.
  2. The numeric value of the error code - for example, 10014.
  3. A short description - for example, Bad address..
  4. A long description - a text string between 50 and 800 characters in length.
Note: the Winsock error codes are defined in winsock2.h.

XWSAError Functions

XWSAError.dll includes functions to retrieve the error code string (given the error code), the numeric error code (given the error code string), the short description, and the long description. Also included are functions to get the maximum length of the returned strings (if you are going to retrieve the long description, it may be simpler just to allocate one buffer for the long description string, and use that buffer for the other strings as well).

Here are the functions available in XWSAError.dll:

  • XWSA_GetErrorCode() - Retrieves error code from error code string.
    /////////////////////////////////////////////////////////////////////////////
    //
    // XWSA_GetErrorCode()
    //
    // Purpose:     Retrieve numeric error code associated with error code string.
    //              For example, calling XWSA_GetErrorCode() with an error code
    //              string of "WSAEINTR" will return the value 10004.
    //
    // Parameters:  lpszErrorString - [in] pointer to error code string
    //
    // Returns:     int - numeric value of error code
    //
  • XWSA_GetErrorString() - Retrieves error code string from error code.
    ////////////////////////////////////////////////////////////////////////////
    //
    // XWSA_GetErrorString()
    //
    // Purpose:     Retrieve the string associated with the error code. For
    //              example, calling XWSA_GetErrorString() with an error code
    //              of 10004 will return the string "WSAEINTR".
    //
    // Parameters:  nErrorCode - [in] Winsock error code
    //              lpszBuf    - [out] pointer to buffer that receives the string
    //              nBufSize   - [in] size of buffer in TCHARs
    //
    // Returns:     int - 1 if error code string found; 0 otherwise
    //
  • XWSA_GetLongDescription() - Retrieves long description.
    /////////////////////////////////////////////////////////////////////////////
    //
    // XWSA_GetLongDescription()
    //
    // Purpose:     Retrieve the long description string associated with the
    //              error code.
    //
    // Parameters:  nErrorCode - [in] Winsock error code
    //              lpszBuf    - [out] pointer to buffer that receives the string
    //              nBufSize   - [in] size of buffer in TCHARs
    //
    // Returns:     int - 1 if error code found; 0 otherwise
    //
  • XWSA_GetShortDescription() - Retrieves short description.
    ////////////////////////////////////////////////////////////////////////////
    //
    // XWSA_GetShortDescription()
    //
    // Purpose:     Retrieve the short description string associated with the
    //              error code.
    //
    // Parameters:  nErrorCode - [in] Winsock error code
    //              lpszBuf    - [out] pointer to buffer that receives the string
    //              nBufSize   - [in] size of buffer in TCHARs
    //
    // Returns:     int - 1 if error code found; 0 otherwise
    //
  • XWSA_GetErrorStringSize() - Retrieves max size of an error code string.
    //////////////////////////////////////////////////////////////////////////
    //
    // XWSA_GetErrorStringSize()
    //
    // Purpose:     Returns the maximum size in TCHARs of an error code string.
    //
    // Parameters:  none
    //
    // Returns:     int - maximum size in TCHARs of an error code string
    //
  • XWSA_GetLongDescriptionSize() - Retrieves max size of a long description.
    /////////////////////////////////////////////////////////////////////////
    //
    // XWSA_GetLongDescriptionSize()
    //
    // Purpose:     Returns the maximum size in TCHARs of a long description
    //              string.
    //
    // Parameters:  none
    //
    // Returns:     int - maximum size in TCHARs of a long description string
    //
  • XWSA_GetShortDescriptionSize() - Retrieves max size of a short description.
    //////////////////////////////////////////////////////////////////////////
    //
    // XWSA_GetShortDescriptionSize()
    //
    // Purpose:     Returns the maximum size in TCHARs of a short description
    //              string.
    //
    // Parameters:  none
    //
    // Returns:     int - maximum size in TCHARs of a short description string
    //

Sample Code

The following sample code - taken from the demo app - shows how to use the above functions.

// is this a numeric error code (10004) or an error string ("WSAEINTR")
if (bNumeric)
{
    int nCode = _ttoi(m_strError);

    m_Code.SetWindowText(m_strError);

    if (XWSA_GetErrorString(nCode, buf, XWSA_GetLongDescriptionSize()))
    {
        m_ID.SetWindowText(buf);
        if (XWSA_GetShortDescription(nCode, buf, XWSA_GetLongDescriptionSize()))
            m_ShortDescription.SetWindowText(buf);
        if (XWSA_GetLongDescription(nCode, buf, XWSA_GetLongDescriptionSize()))
            m_LongDescription.SetWindowText(buf);
    }
    else
    {
        m_ID.SetWindowText(_T("unknown error code"));
    }
}
else
{
    int nCode = XWSA_GetErrorCode(m_strError);

    if (nCode)
    {
        m_ID.SetWindowText(m_strError);

        CString s = _T("");
        s.Format(_T("%d"), nCode);

        m_Code.SetWindowText(s);

        if (XWSA_GetShortDescription(nCode, buf, XWSA_GetLongDescriptionSize()))
            m_ShortDescription.SetWindowText(buf);
        if (XWSA_GetLongDescription(nCode, buf, XWSA_GetLongDescriptionSize()))
            m_LongDescription.SetWindowText(buf);
    }
}

How To Use With Visual C++

To integrate XWSAError.dll into your app, you first need to add XWSAError.h to your project. XWSAError.h automatically links to XWSAError.lib, so all you have to do is, add the XWSAError.lib directory to your project (in VC 6.0, go to Project | Settings | Link | Input and add the directory to the Additional Library Path). Next insert the line

#include "XWSAError.h"

in the module where you want to call the functions. Finally, make sure the XWSAError.dll is in the same directory as the app's exe.

How To Use With Visual Basic

To get XWSAError.dll to work with VB apps, the first thing to do is define all the functions using the __stdcall calling convention:

XWSAERROR_API int __stdcall XWSA_GetErrorString(int nErrorCode, 
                             TCHAR * lpszBuf, int nBufSize);
XWSAERROR_API int __stdcall XWSA_GetErrorCode(const TCHAR * lpszErrorString);
XWSAERROR_API int __stdcall XWSA_GetErrorStringSize();
XWSAERROR_API int __stdcall XWSA_GetShortDescription(int nErrorCode, 
                             TCHAR * lpszBuf, int nBufSize);
XWSAERROR_API int __stdcall XWSA_GetShortDescriptionSize();
XWSAERROR_API int __stdcall XWSA_GetLongDescription(int nErrorCode, 
                            TCHAR * lpszBuf, int nBufSize);
XWSAERROR_API int __stdcall XWSA_GetLongDescriptionSize();

This, combined with the __declspec(dllexport) used in the XWSAERROR_API macro, causes the exported functions to have decorated names (as shown by dumpbin):

ordinal hint RVA      name

      1    0 0000100F _XWSA_GetErrorCode@4
      2    1 00001019 _XWSA_GetErrorString@12
      3    2 0000101E _XWSA_GetErrorStringSize@0
      4    3 00001014 _XWSA_GetLongDescription@12
      5    4 00001023 _XWSA_GetLongDescriptionSize@0
      6    5 00001028 _XWSA_GetShortDescription@12
      7    6 00001032 _XWSA_GetShortDescriptionSize@0

This means that VB programs would have to alias the exported names before calling any of these functions. This is nasty, but we can avoid this problem by adding a module definition file (XWSAError.def):

; XWSAError.def - module definition file
;
; The EXPORTS in this file remove the decoration from the function names,
; and so allow Visual Basic programs to call the XWSAError functions using
; the same names as VC++ programs.

LIBRARY XWSAError

DESCRIPTION "Winsock error lookup"

EXPORTS
  XWSA_GetErrorCode
  XWSA_GetErrorString
  XWSA_GetErrorStringSize
  XWSA_GetLongDescription
  XWSA_GetLongDescriptionSize
  XWSA_GetShortDescription
  XWSA_GetShortDescriptionSize

Now the undecorated function names are exported:

ordinal hint RVA      name

      1    0 0000100F XWSA_GetErrorCode
      2    1 00001019 XWSA_GetErrorString
      3    2 0000101E XWSA_GetErrorStringSize
      4    3 00001014 XWSA_GetLongDescription
      5    4 00001023 XWSA_GetLongDescriptionSize
      6    5 00001028 XWSA_GetShortDescription
      7    6 00001032 XWSA_GetShortDescriptionSize

Now VB programs can call these functions without any extra work, as shown in the following snippet (a sample VB program is included in the download):

VB
Private Declare Function XWSA_GetShortDescriptionSize Lib "XWSAError.dll" () _
                                                                    As Integer
Private Declare Function XWSA_GetShortDescription Lib "XWSAError.dll"
 (ByVal nerror%, ByVal sd$, ByVal sdsize%) As Integer

Private Sub Command1_Click()

    Dim nSize As Integer, rc As Integer, error As Integer
    Dim ErrorCode As String, ShortDesc As String

    nSize = XWSA_GetShortDescriptionSize()
    ShortDesc = String$(nSize, Chr$(0))
    ErrorCode = Form1.Text1.Text
    error = ErrorCode
    rc = XWSA_GetShortDescription(error, ShortDesc, Len(ShortDesc))
    Form1.Text2.Text = "XWSA_GetShortDescription() returned:  " + ShortDesc

End Sub

For more information on using DLL functions in VB, please see Q142840: Visual Basic Requirements for Exported DLL Functions.

The Demo App

The demo app displays the various strings when you enter an error code:

screenshot

Revision History

Version 1.0 - 2005 January 6

  • Initial public release.

Usage

This software is released into the public domain. You are free to use it in any way you like, except that you may not sell this source code. If you modify it or extend it, please to consider posting new code here for everyone to share. This software is provided "as is" with no expressed or implied warranty. I accept no liability for any damage or loss of business that this software may cause.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Hans Dietrich Software
United States United States
I attended St. Michael's College of the University of Toronto, with the intention of becoming a priest. A friend in the University's Computer Science Department got me interested in programming, and I have been hooked ever since.

Recently, I have moved to Los Angeles where I am doing consulting and development work.

For consulting and custom software development, please see www.hdsoft.org.






Comments and Discussions

 
GeneralQuestion... Pin
chifor6-Jan-05 22:02
chifor6-Jan-05 22:02 
i use this simple function for getting error description in my projects:

////////////////////////////////////////
//
void DisplayErrorText(DWORD dwLastError)
{
HMODULE hModule = NULL; // default to system source
LPSTR MessageBuffer;
DWORD dwBufferLength;

//
// if dwLastError is in the network range, load the message source
//
if(dwLastError >= WSABASEERR)
{
hModule = LoadLibraryEx(
TEXT("netmsg.dll"),
NULL,
LOAD_LIBRARY_AS_DATAFILE
);
}
// call FormatMessage() to allow for message text to be acquired
// from the system or the supplied module handle
//
if(dwBufferLength = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_FROM_SYSTEM | // always consider system table
((hModule != NULL) ? FORMAT_MESSAGE_FROM_HMODULE : 0),
hModule, // module to get message from (NULL == system)
dwLastError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
(LPSTR) &MessageBuffer,
0,
NULL
))
{
//
// Output message string on stderr
//
AfxMessageBox(MessageBuffer);
//
// free the buffer allocated by the system
//
LocalFree(MessageBuffer);
}

//
// if you loaded a message source, unload it
//
if(hModule != NULL)
FreeLibrary(hModule);
}
//------------------------------------------------
//////////////////////////////////////////////////
what are the benefits(advantages) of your function?

Constantin Chifor.
GeneralRe: Question... Pin
Hans Dietrich7-Jan-05 6:57
mentorHans Dietrich7-Jan-05 6:57 
QuestionMultilanguage? Pin
Uwe Keim6-Jan-05 18:14
sitebuilderUwe Keim6-Jan-05 18:14 
AnswerRe: Multilanguage? Pin
Hans Dietrich7-Jan-05 7:02
mentorHans Dietrich7-Jan-05 7:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.