1 /* 2 * src/interfaces/libpq/win32.c 3 * 4 * 5 * FILE 6 * win32.c 7 * 8 * DESCRIPTION 9 * Win32 support functions. 10 * 11 * Contains table and functions for looking up win32 socket error 12 * descriptions. But will/may contain other win32 helper functions 13 * for libpq. 14 * 15 * The error constants are taken from the Frambak Bakfram LGSOCKET 16 * library guys who in turn took them from the Winsock FAQ. 17 * 18 * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group 19 * Portions Copyright (c) 1994, Regents of the University of California 20 * 21 */ 22 23 /* Make stuff compile faster by excluding not used stuff */ 24 25 #define VC_EXTRALEAN 26 #ifndef __MINGW32__ 27 #define NOGDI 28 #endif 29 #define NOCRYPT 30 31 #include "postgres_fe.h" 32 33 #include "win32.h" 34 35 /* Declared here to avoid pulling in all includes, which causes name collisions */ 36 #ifdef ENABLE_NLS 37 extern char *libpq_gettext(const char *msgid) pg_attribute_format_arg(1); 38 #else 39 #define libpq_gettext(x) (x) 40 #endif 41 42 43 static struct WSErrorEntry 44 { 45 DWORD error; 46 const char *description; 47 } WSErrors[] = 48 49 { 50 { 51 0, "No error" 52 }, 53 { 54 WSAEINTR, "Interrupted system call" 55 }, 56 { 57 WSAEBADF, "Bad file number" 58 }, 59 { 60 WSAEACCES, "Permission denied" 61 }, 62 { 63 WSAEFAULT, "Bad address" 64 }, 65 { 66 WSAEINVAL, "Invalid argument" 67 }, 68 { 69 WSAEMFILE, "Too many open sockets" 70 }, 71 { 72 WSAEWOULDBLOCK, "Operation would block" 73 }, 74 { 75 WSAEINPROGRESS, "Operation now in progress" 76 }, 77 { 78 WSAEALREADY, "Operation already in progress" 79 }, 80 { 81 WSAENOTSOCK, "Socket operation on non-socket" 82 }, 83 { 84 WSAEDESTADDRREQ, "Destination address required" 85 }, 86 { 87 WSAEMSGSIZE, "Message too long" 88 }, 89 { 90 WSAEPROTOTYPE, "Protocol wrong type for socket" 91 }, 92 { 93 WSAENOPROTOOPT, "Bad protocol option" 94 }, 95 { 96 WSAEPROTONOSUPPORT, "Protocol not supported" 97 }, 98 { 99 WSAESOCKTNOSUPPORT, "Socket type not supported" 100 }, 101 { 102 WSAEOPNOTSUPP, "Operation not supported on socket" 103 }, 104 { 105 WSAEPFNOSUPPORT, "Protocol family not supported" 106 }, 107 { 108 WSAEAFNOSUPPORT, "Address family not supported" 109 }, 110 { 111 WSAEADDRINUSE, "Address already in use" 112 }, 113 { 114 WSAEADDRNOTAVAIL, "Cannot assign requested address" 115 }, 116 { 117 WSAENETDOWN, "Network is down" 118 }, 119 { 120 WSAENETUNREACH, "Network is unreachable" 121 }, 122 { 123 WSAENETRESET, "Net connection reset" 124 }, 125 { 126 WSAECONNABORTED, "Software caused connection abort" 127 }, 128 { 129 WSAECONNRESET, "Connection reset by peer" 130 }, 131 { 132 WSAENOBUFS, "No buffer space available" 133 }, 134 { 135 WSAEISCONN, "Socket is already connected" 136 }, 137 { 138 WSAENOTCONN, "Socket is not connected" 139 }, 140 { 141 WSAESHUTDOWN, "Cannot send after socket shutdown" 142 }, 143 { 144 WSAETOOMANYREFS, "Too many references, cannot splice" 145 }, 146 { 147 WSAETIMEDOUT, "Connection timed out" 148 }, 149 { 150 WSAECONNREFUSED, "Connection refused" 151 }, 152 { 153 WSAELOOP, "Too many levels of symbolic links" 154 }, 155 { 156 WSAENAMETOOLONG, "File name too long" 157 }, 158 { 159 WSAEHOSTDOWN, "Host is down" 160 }, 161 { 162 WSAEHOSTUNREACH, "No route to host" 163 }, 164 { 165 WSAENOTEMPTY, "Directory not empty" 166 }, 167 { 168 WSAEPROCLIM, "Too many processes" 169 }, 170 { 171 WSAEUSERS, "Too many users" 172 }, 173 { 174 WSAEDQUOT, "Disc quota exceeded" 175 }, 176 { 177 WSAESTALE, "Stale NFS file handle" 178 }, 179 { 180 WSAEREMOTE, "Too many levels of remote in path" 181 }, 182 { 183 WSASYSNOTREADY, "Network system is unavailable" 184 }, 185 { 186 WSAVERNOTSUPPORTED, "Winsock version out of range" 187 }, 188 { 189 WSANOTINITIALISED, "WSAStartup not yet called" 190 }, 191 { 192 WSAEDISCON, "Graceful shutdown in progress" 193 }, 194 { 195 WSAHOST_NOT_FOUND, "Host not found" 196 }, 197 { 198 WSATRY_AGAIN, "NA Host not found / SERVFAIL" 199 }, 200 { 201 WSANO_RECOVERY, "Non recoverable FORMERR||REFUSED||NOTIMP" 202 }, 203 { 204 WSANO_DATA, "No host data of that type was found" 205 }, 206 { 207 0, 0 208 } /* End of table */ 209 }; 210 211 212 /* 213 * Returns 0 if not found, linear but who cares, at this moment 214 * we're already in pain :) 215 */ 216 217 static int 218 LookupWSErrorMessage(DWORD err, char *dest) 219 { 220 struct WSErrorEntry *e; 221 222 for (e = WSErrors; e->description; e++) 223 { 224 if (e->error == err) 225 { 226 strcpy(dest, e->description); 227 return 1; 228 } 229 } 230 return 0; 231 } 232 233 234 struct MessageDLL 235 { 236 const char *dll_name; 237 void *handle; 238 int loaded; /* BOOL */ 239 } dlls[] = 240 241 { 242 { 243 "netmsg.dll", 0, 0 244 }, 245 { 246 "winsock.dll", 0, 0 247 }, 248 { 249 "ws2_32.dll", 0, 0 250 }, 251 { 252 "wsock32n.dll", 0, 0 253 }, 254 { 255 "mswsock.dll", 0, 0 256 }, 257 { 258 "ws2help.dll", 0, 0 259 }, 260 { 261 "ws2thk.dll", 0, 0 262 }, 263 { 264 0, 0, 1 265 } /* Last one, no dll, always loaded */ 266 }; 267 268 #define DLLS_SIZE (sizeof(dlls)/sizeof(struct MessageDLL)) 269 270 /* 271 * Returns a description of the socket error by first trying 272 * to find it in the lookup table, and if that fails, tries 273 * to load any of the winsock dlls to find that message. 274 * The DLL thing works from Nt4 (spX ?) up, but some special 275 * versions of winsock might have this as well (seen on Win98 SE 276 * special install) / Magnus Naeslund (mag@fbab.net) 277 * 278 */ 279 280 const char * 281 winsock_strerror(int err, char *strerrbuf, size_t buflen) 282 { 283 unsigned long flags; 284 int offs, 285 i; 286 int success = LookupWSErrorMessage(err, strerrbuf); 287 288 for (i = 0; !success && i < DLLS_SIZE; i++) 289 { 290 291 if (!dlls[i].loaded) 292 { 293 dlls[i].loaded = 1; /* Only load once */ 294 dlls[i].handle = (void *) LoadLibraryEx( 295 dlls[i].dll_name, 296 0, 297 LOAD_LIBRARY_AS_DATAFILE); 298 } 299 300 if (dlls[i].dll_name && !dlls[i].handle) 301 continue; /* Didn't load */ 302 303 flags = FORMAT_MESSAGE_FROM_SYSTEM 304 | FORMAT_MESSAGE_IGNORE_INSERTS 305 | (dlls[i].handle ? FORMAT_MESSAGE_FROM_HMODULE : 0); 306 307 success = 0 != FormatMessage( 308 flags, 309 dlls[i].handle, err, 310 MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), 311 strerrbuf, buflen - 64, 312 0 313 ); 314 } 315 316 if (!success) 317 sprintf(strerrbuf, libpq_gettext("unrecognized socket error: 0x%08X/%d"), err, err); 318 else 319 { 320 strerrbuf[buflen - 1] = '\0'; 321 offs = strlen(strerrbuf); 322 if (offs > (int) buflen - 64) 323 offs = buflen - 64; 324 sprintf(strerrbuf + offs, " (0x%08X/%d)", err, err); 325 } 326 return strerrbuf; 327 } 328