#include <winsock.h>
#include <stdio.h>
#include <string.h>

#include "wslib.h"


char *ws_strerror(void)
{
       static char *err_str = NULL;
       int err;
       char *tmp;

       err = WSAGetLastError();

       switch (err) {
               case WSAEINTR:
                       tmp = "Interrupted function call";
                       break;
               case WSAEACCES:
                       tmp = "Permission denied";
                       break;
               case WSAEBADF:
                       tmp = "Bad file handle";
                       break;
               case WSAEFAULT:
                       tmp = "Bad address";
                       break;
               case WSAEINVAL:
                       tmp = "Invalid argument";
                       break;
               case WSAEMFILE:
                       tmp = "Too many open files";
                       break;
               case WSAEWOULDBLOCK:
                       tmp = "Resource temporarily unavailable";
                       break;
               case WSAEINPROGRESS:
                       tmp = "Operation now in progress";
                       break;
               case WSAEALREADY:
                       tmp = "Operation already in progress";
                       break;
               case WSAENOTSOCK:
                       tmp = "Socket operation on non-socket";
                       break;
               case WSAEDESTADDRREQ:
                       tmp = "Destination address required";
                       break;
               case WSAEMSGSIZE:
                       tmp = "Message too long";
                       break;
               case WSAEPROTOTYPE:
                       tmp = "Protocol wrong type for socket";
                       break;
               case WSAENOPROTOOPT:
                       tmp = "Bad protocol option";
                       break;
               case WSAEPROTONOSUPPORT:
                       tmp = "Protocol not supported";
                       break;
               case WSAESOCKTNOSUPPORT:
                       tmp = "Socket type not supported";
                       break;
               case WSAEOPNOTSUPP:
                       tmp = "Operation not supported";
                       break;
               case WSAEPFNOSUPPORT:
                       tmp = "Protocol family not supported";
                       break;
               case WSAEAFNOSUPPORT:
                       tmp = "Address family not supported by protocol family";
                       break;
               case WSAEADDRINUSE:
                       tmp = "Address already in use";
                       break;
               case WSAEADDRNOTAVAIL:
                       tmp = "Cannot assign requested address";
                       break;
               case WSAENETDOWN:
                       tmp = "Network is down";
                       break;
               case WSAENETUNREACH:
                       tmp = "Network is unreachable";
                       break;
               case WSAENETRESET:
                       tmp = "Network dropped connection on reset";
                       break;
               case WSAECONNABORTED:
                       tmp = "Software caused connection abort";
                       break;
               case WSAECONNRESET:
                       tmp = "Connection reset by peer";
                       break;
               case WSAENOBUFS:
                       tmp = "No buffer space available";
                       break;
               case WSAEISCONN:
                       tmp = "Socket is already connected";
                       break;
               case WSAENOTCONN:
                       tmp = "Socket not connected";
                       break;
               case WSAESHUTDOWN:
                       tmp = "Cannot send after socket shutdown";
                       break;
               case WSAETIMEDOUT:
                       tmp = "Connection timed out";
                       break;
               case WSAECONNREFUSED:
                       tmp = "Connection refused";
                       break;
               case WSAEHOSTDOWN:
                       tmp = "Host is down";
                       break;
               case WSAEHOSTUNREACH:
                       tmp = "No route to host";
                       break;
               case WSASYSNOTREADY:
                       tmp = "Network subsystem is unavailable";
                       break;
               case WSAVERNOTSUPPORTED:
                       tmp = "WINSOCK.DLL version out of range";
                       break;
               case WSANOTINITIALISED:
                       tmp = "Successful WSAStartup not yet performed";
                       break;
               case WSAHOST_NOT_FOUND:
                       tmp = "Host not found";
                       break;
               case WSATRY_AGAIN:
                       tmp = "Non-authoritative host not found";
                       break;
               case WSANO_RECOVERY:
                       tmp = "This is a non-recoverable error";
                       break;
               case WSANO_DATA:
                       tmp = "Valid name, no data record of requested type";
                       break;

/*
               case WSAEPROCLIM:
                       tmp = "Too many processes";
                       break;
               case WSA_INVALID_HANDLE:
                       tmp = "Invalid handle";
                       break;
               case WSA_INVALID_PARAMETER:
                       tmp = "One or more parameters are invalid";
                       break;
               case WSAINVALIDPROCTABLE:
                       tmp = "Invalid procedure table from service provider";
                       break;
               case WSAINVALIDPROVIDER:
                       tmp = "Invalid service provider versoin number";
                       break;
               case WSA_IO_PENDING:
                       tmp = "Overlapped operations will complete later";
                       break;
               case WSA_IO_INCOMPLETE:
                       tmp = "Overlapped I/O event object not i signaled state";
                       break;
               case WSA_NOT_ENOUGH_MEMORY:
                       tmp = "Insufficient memory available";
                       break;
               case WSAPROVIDERFAILEDINIT:
                       tmp = "Unable to initialize a service provider";
                       break;
               case WSASYSCALLFAILURE:
                       tmp = "System call failure";
                       break;
               case WSAEDISCON:
                       tmp = "Graceful shutdown in progress";
                       break;
               case WSA_OPERATION_ABORTED:
                       tmp = "Overlapped operation aborted";
                       break;
*/
               default:
                       tmp = "Unknown error";
       }

       if (err_str)
               free(err_str);
       err_str = (char*)malloc(strlen(tmp) + sizeof("[00000] ") + 1);
       sprintf(err_str, "[%d] %s", err, tmp);
       return err_str;
}