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-2025, 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
37extern char *libpq_gettext(const char *msgid) pg_attribute_format_arg(1);
38#else
39#define libpq_gettext(x) (x)
40#endif
41
42
43static 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 */
210
211
212/*
213 * Returns 0 if not found, linear but who cares, at this moment
214 * we're already in pain :)
215 */
216
217static 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
234static 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 */
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
276const char *
277winsock_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:212
void err(int eval, const char *fmt,...)
Definition: err.c:43
static bool success
Definition: initdb.c:186
int i
Definition: isn.c:72
#define sprintf
Definition: port.h:241
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[]
const char * winsock_strerror(int err, char *strerrbuf, size_t buflen)
Definition: win32.c:277
static struct MessageDLL dlls[]