Header And Logo

PostgreSQL
| The world's most advanced open source database.

win32.c

Go to the documentation of this file.
00001 /*
00002  * src/interfaces/libpq/win32.c
00003  *
00004  *
00005  *  FILE
00006  *      win32.c
00007  *
00008  *  DESCRIPTION
00009  *      Win32 support functions.
00010  *
00011  * Contains table and functions for looking up win32 socket error
00012  * descriptions. But will/may contain other win32 helper functions
00013  * for libpq.
00014  *
00015  * The error constants are taken from the Frambak Bakfram LGSOCKET
00016  * library guys who in turn took them from the Winsock FAQ.
00017  *
00018  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00019  * Portions Copyright (c) 1994, Regents of the University of California
00020  *
00021  */
00022 
00023 /* Make stuff compile faster by excluding not used stuff */
00024 
00025 #define VC_EXTRALEAN
00026 #ifndef __MINGW32__
00027 #define NOGDI
00028 #endif
00029 #define NOCRYPT
00030 
00031 #include "postgres_fe.h"
00032 
00033 #include "win32.h"
00034 
00035 /* Declared here to avoid pulling in all includes, which causes name collissions */
00036 #ifdef ENABLE_NLS
00037 extern char *
00038 libpq_gettext(const char *msgid)
00039 __attribute__((format_arg(1)));
00040 #else
00041 #define libpq_gettext(x) (x)
00042 #endif
00043 
00044 
00045 static struct WSErrorEntry
00046 {
00047     DWORD       error;
00048     const char *description;
00049 }   WSErrors[] =
00050 
00051 {
00052     {
00053         0, "No error"
00054     },
00055     {
00056         WSAEINTR, "Interrupted system call"
00057     },
00058     {
00059         WSAEBADF, "Bad file number"
00060     },
00061     {
00062         WSAEACCES, "Permission denied"
00063     },
00064     {
00065         WSAEFAULT, "Bad address"
00066     },
00067     {
00068         WSAEINVAL, "Invalid argument"
00069     },
00070     {
00071         WSAEMFILE, "Too many open sockets"
00072     },
00073     {
00074         WSAEWOULDBLOCK, "Operation would block"
00075     },
00076     {
00077         WSAEINPROGRESS, "Operation now in progress"
00078     },
00079     {
00080         WSAEALREADY, "Operation already in progress"
00081     },
00082     {
00083         WSAENOTSOCK, "Socket operation on non-socket"
00084     },
00085     {
00086         WSAEDESTADDRREQ, "Destination address required"
00087     },
00088     {
00089         WSAEMSGSIZE, "Message too long"
00090     },
00091     {
00092         WSAEPROTOTYPE, "Protocol wrong type for socket"
00093     },
00094     {
00095         WSAENOPROTOOPT, "Bad protocol option"
00096     },
00097     {
00098         WSAEPROTONOSUPPORT, "Protocol not supported"
00099     },
00100     {
00101         WSAESOCKTNOSUPPORT, "Socket type not supported"
00102     },
00103     {
00104         WSAEOPNOTSUPP, "Operation not supported on socket"
00105     },
00106     {
00107         WSAEPFNOSUPPORT, "Protocol family not supported"
00108     },
00109     {
00110         WSAEAFNOSUPPORT, "Address family not supported"
00111     },
00112     {
00113         WSAEADDRINUSE, "Address already in use"
00114     },
00115     {
00116         WSAEADDRNOTAVAIL, "Cannot assign requested address"
00117     },
00118     {
00119         WSAENETDOWN, "Network is down"
00120     },
00121     {
00122         WSAENETUNREACH, "Network is unreachable"
00123     },
00124     {
00125         WSAENETRESET, "Net connection reset"
00126     },
00127     {
00128         WSAECONNABORTED, "Software caused connection abort"
00129     },
00130     {
00131         WSAECONNRESET, "Connection reset by peer"
00132     },
00133     {
00134         WSAENOBUFS, "No buffer space available"
00135     },
00136     {
00137         WSAEISCONN, "Socket is already connected"
00138     },
00139     {
00140         WSAENOTCONN, "Socket is not connected"
00141     },
00142     {
00143         WSAESHUTDOWN, "Cannot send after socket shutdown"
00144     },
00145     {
00146         WSAETOOMANYREFS, "Too many references, cannot splice"
00147     },
00148     {
00149         WSAETIMEDOUT, "Connection timed out"
00150     },
00151     {
00152         WSAECONNREFUSED, "Connection refused"
00153     },
00154     {
00155         WSAELOOP, "Too many levels of symbolic links"
00156     },
00157     {
00158         WSAENAMETOOLONG, "File name too long"
00159     },
00160     {
00161         WSAEHOSTDOWN, "Host is down"
00162     },
00163     {
00164         WSAEHOSTUNREACH, "No route to host"
00165     },
00166     {
00167         WSAENOTEMPTY, "Directory not empty"
00168     },
00169     {
00170         WSAEPROCLIM, "Too many processes"
00171     },
00172     {
00173         WSAEUSERS, "Too many users"
00174     },
00175     {
00176         WSAEDQUOT, "Disc quota exceeded"
00177     },
00178     {
00179         WSAESTALE, "Stale NFS file handle"
00180     },
00181     {
00182         WSAEREMOTE, "Too many levels of remote in path"
00183     },
00184     {
00185         WSASYSNOTREADY, "Network system is unavailable"
00186     },
00187     {
00188         WSAVERNOTSUPPORTED, "Winsock version out of range"
00189     },
00190     {
00191         WSANOTINITIALISED, "WSAStartup not yet called"
00192     },
00193     {
00194         WSAEDISCON, "Graceful shutdown in progress"
00195     },
00196     {
00197         WSAHOST_NOT_FOUND, "Host not found"
00198     },
00199     {
00200         WSATRY_AGAIN, "NA Host not found / SERVFAIL"
00201     },
00202     {
00203         WSANO_RECOVERY, "Non recoverable FORMERR||REFUSED||NOTIMP"
00204     },
00205     {
00206         WSANO_DATA, "No host data of that type was found"
00207     },
00208     {
00209         0, 0
00210     }                           /* End of table */
00211 };
00212 
00213 
00214 /*
00215  * Returns 0 if not found, linear but who cares, at this moment
00216  * we're already in pain :)
00217  */
00218 
00219 static int
00220 LookupWSErrorMessage(DWORD err, char *dest)
00221 {
00222     struct WSErrorEntry *e;
00223 
00224     for (e = WSErrors; e->description; e++)
00225     {
00226         if (e->error == err)
00227         {
00228             strcpy(dest, e->description);
00229             return 1;
00230         }
00231     }
00232     return 0;
00233 }
00234 
00235 
00236 struct MessageDLL
00237 {
00238     const char *dll_name;
00239     void       *handle;
00240     int         loaded;         /* BOOL */
00241 }   dlls[] =
00242 
00243 {
00244     {
00245         "netmsg.dll", 0, 0
00246     },
00247     {
00248         "winsock.dll", 0, 0
00249     },
00250     {
00251         "wsock32.dll", 0, 0
00252     },
00253     {
00254         "ws2_32.dll", 0, 0
00255     },
00256     {
00257         "wsock32n.dll", 0, 0
00258     },
00259     {
00260         "mswsock.dll", 0, 0
00261     },
00262     {
00263         "ws2help.dll", 0, 0
00264     },
00265     {
00266         "ws2thk.dll", 0, 0
00267     },
00268     {
00269         0, 0, 1
00270     }                           /* Last one, no dll, always loaded */
00271 };
00272 
00273 #define DLLS_SIZE (sizeof(dlls)/sizeof(struct MessageDLL))
00274 
00275 /*
00276  * Returns a description of the socket error by first trying
00277  * to find it in the lookup table, and if that fails, tries
00278  * to load any of the winsock dlls to find that message.
00279  * The DLL thing works from Nt4 (spX ?) up, but some special
00280  * versions of winsock might have this as well (seen on Win98 SE
00281  * special install)            / Magnus Naeslund ([email protected])
00282  *
00283  */
00284 
00285 const char *
00286 winsock_strerror(int err, char *strerrbuf, size_t buflen)
00287 {
00288     unsigned long flags;
00289     int         offs,
00290                 i;
00291     int         success = LookupWSErrorMessage(err, strerrbuf);
00292 
00293     for (i = 0; !success && i < DLLS_SIZE; i++)
00294     {
00295 
00296         if (!dlls[i].loaded)
00297         {
00298             dlls[i].loaded = 1; /* Only load once */
00299             dlls[i].handle = (void *) LoadLibraryEx(
00300                                                     dlls[i].dll_name,
00301                                                     0,
00302                                                     LOAD_LIBRARY_AS_DATAFILE);
00303         }
00304 
00305         if (dlls[i].dll_name && !dlls[i].handle)
00306             continue;           /* Didn't load */
00307 
00308         flags = FORMAT_MESSAGE_FROM_SYSTEM
00309             | FORMAT_MESSAGE_IGNORE_INSERTS
00310             | (dlls[i].handle ? FORMAT_MESSAGE_FROM_HMODULE : 0);
00311 
00312         success = 0 != FormatMessage(
00313                                      flags,
00314                                      dlls[i].handle, err,
00315                                    MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
00316                                      strerrbuf, buflen - 64,
00317                                      0
00318             );
00319     }
00320 
00321     if (!success)
00322         sprintf(strerrbuf, libpq_gettext("unrecognized socket error: 0x%08X/%d"), err, err);
00323     else
00324     {
00325         strerrbuf[buflen - 1] = '\0';
00326         offs = strlen(strerrbuf);
00327         if (offs > (int) buflen - 64)
00328             offs = buflen - 64;
00329         sprintf(strerrbuf + offs, " (0x%08X/%d)", err, err);
00330     }
00331     return strerrbuf;
00332 }