PostgreSQL Source Code  git master
win32.c
Go to the documentation of this file.
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-2024, 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
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 
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  */
275 
276 const char *
277 winsock_strerror(int err, char *strerrbuf, size_t buflen)
278 {
279  unsigned long flags;
280  int offs,
281  i;
282  int success = LookupWSErrorMessage(err, strerrbuf);
283 
284  for (i = 0; !success && i < DLLS_SIZE; i++)
285  {
286 
287  if (!dlls[i].loaded)
288  {
289  dlls[i].loaded = 1; /* Only load once */
290  dlls[i].handle = (void *) LoadLibraryEx(dlls[i].dll_name,
291  0,
292  LOAD_LIBRARY_AS_DATAFILE);
293  }
294 
295  if (dlls[i].dll_name && !dlls[i].handle)
296  continue; /* Didn't load */
297 
298  flags = FORMAT_MESSAGE_FROM_SYSTEM
299  | FORMAT_MESSAGE_IGNORE_INSERTS
300  | (dlls[i].handle ? FORMAT_MESSAGE_FROM_HMODULE : 0);
301 
302  success = 0 != FormatMessage(flags,
303  dlls[i].handle, err,
304  MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
305  strerrbuf, buflen - 64,
306  0);
307  }
308 
309  if (!success)
310  sprintf(strerrbuf, libpq_gettext("unrecognized socket error: 0x%08X/%d"), err, err);
311  else
312  {
313  strerrbuf[buflen - 1] = '\0';
314  offs = strlen(strerrbuf);
315  if (offs > (int) buflen - 64)
316  offs = buflen - 64;
317  sprintf(strerrbuf + offs, " (0x%08X/%d)", err, err);
318  }
319  return strerrbuf;
320 }
#define pg_attribute_format_arg(a)
Definition: c.h:190
void err(int eval, const char *fmt,...)
Definition: err.c:43
static bool success
Definition: initdb.c:186
int i
Definition: isn.c:73
#define sprintf
Definition: port.h:240
e
Definition: preproc-init.c:82
const char * dll_name
Definition: win32.c:236
void * handle
Definition: win32.c:237
int loaded
Definition: win32.c:238
DWORD error
Definition: win32.c:45
const char * description
Definition: win32.c:46
#define libpq_gettext(x)
Definition: win32.c:39
static int LookupWSErrorMessage(DWORD err, char *dest)
Definition: win32.c:218
#define DLLS_SIZE
Definition: win32.c:268
static struct WSErrorEntry WSErrors[]
struct MessageDLL dlls[]
const char * winsock_strerror(int err, char *strerrbuf, size_t buflen)
Definition: win32.c:277