WvStreams
|
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * A class for managing error numbers and strings. See wverror.h. 00006 */ 00007 #include "wverror.h" 00008 #include <assert.h> 00009 00010 #ifdef _WIN32 00011 #include "windows.h" 00012 00013 struct WvErrMap { 00014 int num; 00015 const char *str; 00016 }; 00017 00018 static WvErrMap wverrmap[] = { 00019 { WSAEINTR, "Interrupted" }, 00020 { WSAEBADF, "Bad file descriptor" }, 00021 { WSAEACCES, "Access denied" }, 00022 { WSAEFAULT, "Bad address" }, 00023 { WSAEINVAL, "Invalid argument" }, 00024 { WSAEMFILE, "Too many open files" }, 00025 { WSAEWOULDBLOCK, "Operation would block" }, 00026 { WSAEINPROGRESS, "Operation now in progress" }, 00027 { WSAEALREADY, "Operation already in progress" }, 00028 { WSAENOTSOCK, "Socket operation on non-socket" }, 00029 { WSAEDESTADDRREQ, "Destination address required" }, 00030 { WSAEMSGSIZE, "Message too long" }, 00031 { WSAEPROTOTYPE, "Protocol wrong type for socket" }, 00032 { WSAENOPROTOOPT, "Protocol not available" }, 00033 { WSAEPROTONOSUPPORT, "Protocol not supported" }, 00034 { WSAESOCKTNOSUPPORT, "Socket type not supported" }, 00035 { WSAEOPNOTSUPP, "Operation not supported on transport endpoint" }, 00036 { WSAEPFNOSUPPORT, "Protocol family not supported" }, 00037 { WSAEAFNOSUPPORT, "Address family not supported by protocol" }, 00038 { WSAEADDRINUSE, "Address already in use" }, 00039 { WSAEADDRNOTAVAIL, "Cannot assign requested address" }, 00040 { WSAENETDOWN, "Network is down" }, 00041 { WSAENETUNREACH, "Network is unreachable" }, 00042 { WSAENETRESET, "Network dropped connection because of reset" }, 00043 { WSAECONNABORTED, "Software caused connection abort" }, 00044 { WSAECONNRESET, "Connection reset by peer" }, 00045 { WSAENOBUFS, "No buffer space available" }, 00046 { WSAEISCONN, "Transport endpoint is already connected" }, 00047 { WSAENOTCONN, "Transport endpoint is not connected" }, 00048 { WSAESHUTDOWN, "Cannot send after transport endpoint shutdown" }, 00049 { WSAETOOMANYREFS, "Too many references: cannot splice" }, 00050 { WSAETIMEDOUT, "Connection timed out" }, 00051 { WSAECONNREFUSED, "Connection refused" }, 00052 { WSAELOOP, "Too many symbolic links encountered" }, 00053 { WSAENAMETOOLONG, "File name too long" }, 00054 { WSAEHOSTDOWN, "Host is down" }, 00055 { WSAEHOSTUNREACH, "No route to host" }, 00056 { WSAENOTEMPTY, "Directory not empty" }, 00057 { WSAEPROCLIM, "Process limit reached" }, 00058 { WSAEUSERS, "Too many users" }, 00059 { WSAEDQUOT, "Disk quota exceeded" }, 00060 { WSAESTALE, "Stale file handle" }, 00061 { WSAEREMOTE, "Object is remote" }, 00062 { WSAEDISCON, "Disconnected" }, 00063 { WSAENOMORE, "No more data" }, 00064 { WSAECANCELLED, "Operation cancelled" }, 00065 { WSAEINVALIDPROCTABLE, "Invalid process table" }, 00066 { WSAEINVALIDPROVIDER, "Invalid provider" }, 00067 { WSAEPROVIDERFAILEDINIT, "Provider failed to initialize" }, 00068 { WSAEREFUSED, "Operation refused" }, 00069 { 0, NULL } 00070 }; 00071 00072 static const char *wv_errmap(int errnum) 00073 { 00074 00075 for (WvErrMap *i = wverrmap; i->num; i++) 00076 if (i->num == errnum) 00077 return i->str; 00078 return NULL; 00079 } 00080 00081 #endif 00082 00083 WvErrorBase::~WvErrorBase() 00084 { 00085 // nothing special 00086 } 00087 00088 00089 // win32's strerror() function is incredibly weak, so we'll provide a better 00090 // one. 00091 WvString WvErrorBase::strerror(int errnum) 00092 { 00093 assert(errnum >= 0); 00094 00095 #ifndef _WIN32 00096 return ::strerror(errnum); 00097 #else 00098 const char *wverr = wv_errmap(errnum); 00099 if (wverr) 00100 return wverr; 00101 else if (errnum >= WSABASEERR && errnum < WSABASEERR+2000) 00102 { 00103 // otherwise, an unrecognized winsock error: try getting the error 00104 // message from win32. 00105 char msg[4096]; 00106 const HMODULE module = GetModuleHandle("winsock.dll"); 00107 DWORD result = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 00108 module, errnum, 0, msg, sizeof(msg), 0); 00109 if (result) 00110 return msg; 00111 00112 DWORD e = GetLastError(); 00113 return WvString("Unknown format %s for error %s", e, errnum); 00114 } 00115 else 00116 { 00117 const char *str = ::strerror(errnum); 00118 if (!strcmp(str, "Unknown error")) 00119 return WvString("Unknown win32 error #%s", errnum); 00120 else 00121 return str; 00122 } 00123 #endif 00124 } 00125 00126 00127 WvString WvErrorBase::errstr() const 00128 { 00129 int errnum = geterr(); 00130 00131 if (errnum < 0) 00132 { 00133 assert(!!errstring); 00134 return errstring; 00135 } 00136 else 00137 { 00138 if (!!errstring) return errstring; 00139 return WvErrorBase::strerror(errnum); 00140 } 00141 } 00142 00143 00144 void WvErrorBase::seterr(int _errnum) 00145 { 00146 if (!errnum) 00147 { 00148 assert(_errnum != -1 || !!errstring 00149 && "attempt to set errnum to -1 without also setting errstring"); 00150 #ifdef _WIN32 00151 if (_errnum == WSAECONNABORTED) 00152 _errnum = WSAECONNREFUSED; // work around WINE bug 00153 #endif 00154 errnum = _errnum; 00155 } 00156 } 00157 00158 00159 void WvErrorBase::seterr(WvStringParm specialerr) 00160 { 00161 assert(!!specialerr); 00162 if (!errnum) 00163 { 00164 errstring = specialerr; 00165 seterr(-1); 00166 } 00167 } 00168 00169 00170 void WvErrorBase::seterr(const WvErrorBase &err) 00171 { 00172 if (err.geterr() > 0) 00173 seterr(err.geterr()); 00174 else if (err.geterr() < 0) 00175 seterr(err.errstr()); 00176 } 00177 00178 00179 void WvErrorBase::seterr_both(int _errnum, WvStringParm specialerr) 00180 { 00181 assert(!!specialerr); 00182 if (!errnum) 00183 { 00184 errstring = specialerr; 00185 seterr(_errnum); 00186 } 00187 }