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