/*--------------------------------------------------------------------*/
/* T c p E r r . c */
/* */
/* Part of BinkD project */
/* WinSock error's */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* Copyright (c) 1996 by Fydodor Ustinov */
/* FIDONet 2:5020/79 */
/* */
/* This program is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License as */
/* published by the Free Software Foundation; either version 2 of */
/* the License, or (at your option) any later version. See COPYING. */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* RCS Information */
/*--------------------------------------------------------------------*/
/*
* $Id: TCPErr.c,v 2.9.2.4 2003/08/05 05:38:43 hbrew Exp $
*
* Revision history:
* $Log: TCPErr.c,v $
* Revision 2.9.2.4 2003/08/05 05:38:43 hbrew
* 'static const char rcsid[]' removed
*
* Revision 2.9.2.3 2003/06/21 15:35:35 hbrew
* Fix running on Win9x-systems.
*
* Revision 2.9.2.2 2003/06/21 07:59:05 gul
* Fix typo in error report string
*
* Revision 2.9.2.1 2003/06/17 15:48:00 stas
* Prevent service operations on incompatible OS (NT and 9x)
*
* Revision 2.9 2003/06/05 11:40:19 stas
* Cosmetics
*
* Revision 2.8 2003/06/05 11:16:56 stas
* Fix warning; More accuracy errors strings list maintnance
*
* Revision 2.7 2003/06/04 10:36:59 stas
* Thread-safety tcperr() implementation on Win32
*
* Revision 2.6 2003/05/25 12:52:35 stas
* Replace CR and LF with spaces in system error messages
*
* Revision 2.5 2003/05/23 17:54:08 stas
* Display default text at unknown win32 error
*
* Revision 2.4 2003/05/23 09:11:13 stas
* Improve diagnostic: print Win32API error message on unknown error
*
* Revision 2.3 2003/05/23 07:55:23 stas
* Update error messages, add comments with messages published in MSDN
*
* Revision 2.2 2003/02/28 20:39:08 gul
* Code cleanup:
* change "()" to "(void)" in function declarations;
* change C++-style comments to C-style
*
* Revision 2.1 2003/02/13 19:44:44 gul
* Change \r\n -> \n
*
* Revision 2.0 2001/01/10 12:12:40 gul
* Binkd is under CVS again
*
* Revision 0.02 1996/12/15 18:58:09 ufm
* Fixed bug with wrong IP Errors numeration.
* For sample, Error "Connection refused" (61) says as
* "Too many levels of symbolic links" (62)
*
* Revision 0.01 1996/12/03 12:15:15 ufm
* First revision
*
*/
/*--------------------------------------------------------------------*/
/* System include files */
/*--------------------------------------------------------------------*/
#include <windows.h>
#include <winsock.h>
#include <stdio.h>
#include <stdlib.h>
/*--------------------------------------------------------------------*/
/* Local include files */
/*--------------------------------------------------------------------*/
#include "../sem.h"
/*--------------------------------------------------------------------*/
/* Global definitions */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* Global variables */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* Local variables */
/*--------------------------------------------------------------------*/
#ifdef BINKDW9X
/* Windows version test
* Parameter: Platform ID (VER_PLATFORM_WIN32_NT or VER_PLATFORM_WIN32_WINDOWS,
* see GetVersionEx() if MSDN)
* Return 0 if match OS, not zero (usually -1) if do not match OS,
* return 1 if can't retrieve OS version info.
*/
int W32_CheckOS(unsigned long PlatformId)
{ OSVERSIONINFO os_ver;
os_ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if( GetVersionEx(&os_ver) )
return os_ver.dwPlatformId != PlatformId;
return 1;
}
#endif
static char err_sem_init = 0;
static MUTEXSEM err_sem;
typedef struct s_StrErrList{
int code;
char *text;
struct s_StrErrList *next;
} *pStrErrList;
static pStrErrList errlist;
/*--------------------------------------------------------------------*/
/* Local functions prototypes */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* int tcperr(void) */
/* */
/* return string to winsock error. */
/*--------------------------------------------------------------------*/
/* Return error string for win32 API error
* return pointer to malloc'ed string or NULL
*/
char *W32APIstrerror(int errnum)
{ char *st, *cp=NULL;
int len;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
errnum,
0, /* Default language */
(LPTSTR) &cp,
0,
NULL
);
if( !cp || !(*cp) ){
st = malloc(40);
if(st) sprintf(st, "{%u} Unknown Win32API error", errnum);
}else{
len = strlen(cp)+15;
st=malloc(len);
if(st){
len = sprintf(st, "{%u} ",errnum);
AnsiToOem(cp,st+len);
LocalFree(cp); /* Win32 API free() implementation */
}else st=cp;
for(cp=st+len; *cp; cp++)
switch(*cp){ /* Replace '\r' and '\n' with space */
case '\r':
case '\n':
*cp=' ';
}
}
return st;
}
/* Store new error message taken from FormatMessage() to errlist
* Return message
* Lock semaphore err_sem before call newerrortolist() please!
*/
const char *newerrortolist(int err){
pStrErrList newe;
if( !(newe = malloc(sizeof(*newe))) ){
/* Log( 0, "Out of memory (malloc())" );*/
return NULL;
}
newe->code = err;
newe->text = W32APIstrerror(err);
newe->next = errlist;
errlist = newe;
if( newe->text )
return newe->text;
return "Unknown error"; /* Don't return NULL! */
}
/* Release memory from errlist, release semaphore
*/
void ReleaseErrorList(void){
pStrErrList el;
if( err_sem_init ){
if( errlist && !LockSem(&err_sem) ){
while(errlist){
if(errlist->text) free(errlist->text);
el = errlist;
errlist=errlist->next;
free(el);
}
ReleaseSem(&err_sem);
}
err_sem_init=0;
CleanSem(&err_sem);
}
}
/* Return error message from errlist
*/
const char *errorfromlist(int err){
pStrErrList el, sel;
const char *errmess="";
for( sel=el=errlist; el; el=el->next )
if( el->code==err )
return el->text;
if(!err_sem_init){ err_sem_init=1; InitSem(&err_sem); }
if( !LockSem(&err_sem) ){
if(sel!=errlist) /* List changed, check again */
for( el=errlist; el && (el!=sel); el=el->next )
if( el->code==err ){
errmess = el->text;
goto skip_newerrortolist;
}
errmess = newerrortolist(err);
skip_newerrortolist:
ReleaseSem(&err_sem);
}
return errmess;
}
/* Return error message
* (Massages taken from MSDN)
*/
const char *tcperr (int errnum) {
const char *Str;
switch( errnum ){
case 10004:
Str = "{10004} A blocking operation was interrupted by a call to WSACancelBlockingCall";
break;
/* Not in MSDN, not return by FormatMessage
case 10006:
Str = "{10006} No such device or address";
break; */
case 10009:
/* Str = "{10009} Bad file number";*/
Str = "{10009} The file handle supplied is not valid";
break;
case 10013:
/* Str = "{10013} Permission denied";*/
Str = "{10013} An attempt was made to access a socket in a way forbidden by its access permissions";
break;
case 10014:
/* Str = "{10014} Bad address";*/
Str = "{10014} The system detected an invalid pointer address in attempting to use a pointer argument in a call";
break;
case 10022:
/* Str = "{10022} Invalid argument";*/
Str = "{10022} An invalid argument was supplied";
break;
case 10024:
Str = "{10024} Too many open sockets";
break;
/* Not in MSDN, not return by FormatMessage
case 10032:
Str = "{10032} Broken pipe";
break;*/
case 10035:
/* Str = "{10035} Operation would block";*/
Str = "{10035} A non-blocking socket operation could not be completed immediately";
break;
case 10036:
/* Str = "{10036} Operation now in progress";*/
Str = "{10036} A blocking operation is currently executing";
break;
case 10037:
/* Str = "{10037} Operation already in progress";*/
Str = "{10037} An operation was attempted on a non-blocking socket that already had an operation in progress";
break;
case 10038:
/* Str = "{10038} Socket operation on non-socket";*/
Str = "{10038} An operation was attempted on something that is not a socket";
break;
case 10039:
/* Str = "{10039} Destination address required";*/
Str = "{10039} A required address was omitted from an operation on a socket";
break;
case 10040:
/* Str = "{10040} Message too long";*/
Str = "{10040} A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram into was smaller than the datagram itself";
break;
case 10041:
/* Str = "{10041} Protocol wrong type for socket";*/
Str = "{10041} A protocol was specified in the socket function call that does not support the semantics of the socket type requested";
break;
case 10042:
/* Str = "{10042} Protocol not available";*/
Str = "{10042} An unknown, invalid, or unsupported option or level was specified in a getsockopt or setsockopt call";
break;
case 10043:
/* Str = "{10043} Protocol not supported";*/
Str = "{10043} The requested protocol has not been configured into the system, or no implementation for it exists";
break;
case 10044:
/* Str = "{10044} Socket type not supported";*/
Str = "{10044} The support for the specified socket type does not exist in this address family";
break;
case 10045:
/* Str = "{10045} Operation not supported on socket";*/
Str = "{10045} The attempted operation is not supported for the type of object referenced";
break;
case 10046:
/* Str = "{10046} Protocol family not supported";*/
Str = "{10046} The protocol family has not been configured into the system or no implementation for it exists";
break;
case 10047:
/* Str = "{10047} Address family not supported by protocol family";*/
Str = "{10047} An address incompatible with the requested protocol was used";
break;
case 10048:
/* Str = "{10048} Address already in use";*/
Str = "{10048} Only one usage of each socket address (protocol/network address/port) is normally permitted";
break;
case 10049:
/* Str = "{10049} Can't assign requested address";*/
Str = "{10049} The requested address is not valid in its context";
break;
case 10050:
/* Str = "{10050} Network is down";*/
Str = "{10050} A socket operation encountered a dead network";
break;
case 10051:
/* Str = "{10052} Network is unreachable";*/
Str = "{10052} A socket operation was attempted to an unreachable network";
break;
case 10052:
/* Str = "{10052} Network dropped connection on reset";*/
Str = "{10052} The connection has been broken due to keep-alive activity detecting a failure while the operation was in progress";
break;
case 10053:
/* Str = "{10053} Software caused connection abort";*/
Str = "{10053} An established connection was aborted by the software in your host machine";
break;
case 10054:
/* Str = "{10054} Connection reset by peer";*/
Str = "{10054} An existing connection was forcibly closed by the remote host";
break;
case 10055:
Str = "{10055} No buffer space available";
/* Str = "{10055} An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full";*/
break;
case 10056:
/* Str = "{10056} Socket is already connected";*/
Str = "{10056} A connect request was made on an already connected socket";
break;
case 10057:
Str = "{10057} Socket is not connected";
/* Str = "{10057} A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied";*/
break;
case 10058:
Str = "{10058} Can't send after socket shutdown";
/* Str = "{10058} A request to send or receive data was disallowed because the socket had already been shut down in that direction with a previous shutdown call";*/
break;
case 10059:
/* Str = "{10059} Too many references: can't splice";*/
Str = "{10059} Too many references to some kernel object";
break;
case 10060:
Str = "{10060} Connection timed out";
/* Str = "{10060} A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond"; */
break;
case 10061:
Str = "{10061} Connection refused";
/* Str = "{10061} No connection could be made because the target machine actively refused it";*/
break;
case 10062:
/* Str = "{10062} Too many levels of symbolic links";*/
Str = "{10062} Cannot translate name";
break;
case 10063:
/* Str = "{10063} File name too long";*/
Str = "{10063} Name component or name was too long";
break;
case 10064:
/* Str = "{10064} Host is down";*/
Str = "{10064} A socket operation failed because the destination host was down";
break;
case 10065:
/* Str = "{10065} No route to host";*/
Str = "{10065} A socket operation was attempted to an unreachable host";
break;
case 10066:
/* Str = "{10066} Directory not empty";*/
Str = "{10066} Cannot remove a directory that is not empty";
break;
case 10067:
/* Str = "{10067} Applications limit reached";*/
Str = "{10067} A Windows Sockets implementation may have a limit on the number of applications that may use it simultaneously.";
break;
/* case 10068:
Str = "{10068} Ran out of quota.";
break;*/
case 10070:
Str = "{10070} File handle reference is no longer available.";
break;
case 10071:
Str = "{10071} Item is not available locally.";
break;
case 10091:
Str = "{10091} WSAStartup cannot function at this time because the underlying system it uses to provide network services is currently unavailable.";
break;
case 10092:
Str = "{10092} The Windows Sockets version requested is not supported.";
break;
case 10093:
Str = "{10093} Either the application has not called WSAStartup, or WSAStartup failed.";
break;
case 10101:
Str = "{10101} Returned by WSARecv or WSARecvFrom to indicate the remote party has initiated a graceful shutdown sequence.";
break;
case 11001:
Str = "{11001} No such host is known.";
break;
case 11002:
Str = "{11002} This is usually a temporary error during hostname resolution and means that the local server did not receive a response from an authoritative server.";
break;
default:
Str = errorfromlist(errnum);
}
return Str;
}
syntax highlighted by Code2HTML, v. 0.9.1