xref: /minix3/external/bsd/bind/dist/lib/isc/win32/strerror.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1 /*	$NetBSD: strerror.c,v 1.4 2014/12/10 04:38:01 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (C) 2001, 2002  Internet Software Consortium.
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /* Id: strerror.c,v 1.8 2007/06/19 23:47:19 tbox Exp  */
21 
22 #include <config.h>
23 
24 #include <stdio.h>
25 #include <string.h>
26 #include <winsock2.h>
27 
28 #include <isc/mutex.h>
29 #include <isc/once.h>
30 #include <isc/print.h>
31 #include <isc/strerror.h>
32 #include <isc/util.h>
33 
34 /*
35  * Forward declarations
36  */
37 
38 char *
39 FormatError(int error);
40 
41 char *
42 GetWSAErrorMessage(int errval);
43 
44 char *
45 NTstrerror(int err, BOOL *bfreebuf);
46 
47 /*
48  * We need to do this this way for profiled locks.
49  */
50 
51 static isc_mutex_t isc_strerror_lock;
init_lock(void)52 static void init_lock(void) {
53 	RUNTIME_CHECK(isc_mutex_init(&isc_strerror_lock) == ISC_R_SUCCESS);
54 }
55 
56 /*
57  * This routine needs to free up any buffer allocated by FormatMessage
58  * if that routine gets used.
59  */
60 
61 void
isc__strerror(int num,char * buf,size_t size)62 isc__strerror(int num, char *buf, size_t size) {
63 	char *msg;
64 	BOOL freebuf;
65 	unsigned int unum = num;
66 	static isc_once_t once = ISC_ONCE_INIT;
67 
68 	REQUIRE(buf != NULL);
69 
70 	RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS);
71 
72 	LOCK(&isc_strerror_lock);
73 	freebuf = FALSE;
74 	msg = NTstrerror(num, &freebuf);
75 	if (msg != NULL)
76 		snprintf(buf, size, "%s", msg);
77 	else
78 		snprintf(buf, size, "Unknown error: %u", unum);
79 	if(freebuf && msg != NULL) {
80 		LocalFree(msg);
81 	}
82 	UNLOCK(&isc_strerror_lock);
83 }
84 
85 /*
86  * Note this will cause a memory leak unless the memory allocated here
87  * is freed by calling LocalFree.  isc__strerror does this before unlocking.
88  * This only gets called if there is a system type of error and will likely
89  * be an unusual event.
90  */
91 char *
FormatError(int error)92 FormatError(int error) {
93 	LPVOID lpMsgBuf = NULL;
94 	FormatMessage(
95 		FORMAT_MESSAGE_ALLOCATE_BUFFER |
96 		FORMAT_MESSAGE_FROM_SYSTEM |
97 		FORMAT_MESSAGE_IGNORE_INSERTS,
98 		NULL,
99 		error,
100 		/* Default language */
101 		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
102 		(LPTSTR) &lpMsgBuf,
103 		0,
104 		NULL);
105 
106 	return (lpMsgBuf);
107 }
108 
109 /*
110  * This routine checks the error value and calls the WSA Windows Sockets
111  * Error message function GetWSAErrorMessage below if it's within that range
112  * since those messages are not available in the system error messages.
113  */
114 char *
NTstrerror(int err,BOOL * bfreebuf)115 NTstrerror(int err, BOOL *bfreebuf) {
116 	char *retmsg = NULL;
117 
118 	/* Copy the error value first in case of other errors */
119 	DWORD errval = err;
120 
121 	*bfreebuf = FALSE;
122 
123 	/* Get the Winsock2 error messages */
124 	if (errval >= WSABASEERR && errval <= (WSABASEERR + 1015)) {
125 		retmsg = GetWSAErrorMessage(errval);
126 		if (retmsg != NULL)
127 			return (retmsg);
128 	}
129 	/*
130 	 * If it's not one of the standard Unix error codes,
131 	 * try a system error message
132 	 */
133 	if (errval > (DWORD) _sys_nerr) {
134 		*bfreebuf = TRUE;
135 		return (FormatError(errval));
136 	} else {
137 		return (strerror(errval));
138 	}
139 }
140 
141 /*
142  * This is a replacement for perror
143  */
144 void __cdecl
NTperror(char * errmsg)145 NTperror(char *errmsg) {
146 	/* Copy the error value first in case of other errors */
147 	int errval = errno;
148 	BOOL bfreebuf = FALSE;
149 	char *msg;
150 
151 	msg = NTstrerror(errval, &bfreebuf);
152 	fprintf(stderr, "%s: %s\n", errmsg, msg);
153 	if(bfreebuf == TRUE) {
154 		LocalFree(msg);
155 	}
156 
157 }
158 
159 /*
160  * Return the error string related to Winsock2 errors.
161  * This function is necessary since FormatMessage knows nothing about them
162  * and there is no function to get them.
163  */
164 char *
GetWSAErrorMessage(int errval)165 GetWSAErrorMessage(int errval) {
166 	char *msg;
167 
168 	switch (errval) {
169 
170 	case WSAEINTR:
171 		msg = "Interrupted system call";
172 		break;
173 
174 	case WSAEBADF:
175 		msg = "Bad file number";
176 		break;
177 
178 	case WSAEACCES:
179 		msg = "Permission denied";
180 		break;
181 
182 	case WSAEFAULT:
183 		msg = "Bad address";
184 		break;
185 
186 	case WSAEINVAL:
187 		msg = "Invalid argument";
188 		break;
189 
190 	case WSAEMFILE:
191 		msg = "Too many open sockets";
192 		break;
193 
194 	case WSAEWOULDBLOCK:
195 		msg = "Operation would block";
196 		break;
197 
198 	case WSAEINPROGRESS:
199 		msg = "Operation now in progress";
200 		break;
201 
202 	case WSAEALREADY:
203 		msg = "Operation already in progress";
204 		break;
205 
206 	case WSAENOTSOCK:
207 		msg = "Socket operation on non-socket";
208 		break;
209 
210 	case WSAEDESTADDRREQ:
211 		msg = "Destination address required";
212 		break;
213 
214 	case WSAEMSGSIZE:
215 		msg = "Message too long";
216 		break;
217 
218 	case WSAEPROTOTYPE:
219 		msg = "Protocol wrong type for socket";
220 		break;
221 
222 	case WSAENOPROTOOPT:
223 		msg = "Bad protocol option";
224 		break;
225 
226 	case WSAEPROTONOSUPPORT:
227 		msg = "Protocol not supported";
228 		break;
229 
230 	case WSAESOCKTNOSUPPORT:
231 		msg = "Socket type not supported";
232 		break;
233 
234 	case WSAEOPNOTSUPP:
235 		msg = "Operation not supported on socket";
236 		break;
237 
238 	case WSAEPFNOSUPPORT:
239 		msg = "Protocol family not supported";
240 		break;
241 
242 	case WSAEAFNOSUPPORT:
243 		msg = "Address family not supported";
244 		break;
245 
246 	case WSAEADDRINUSE:
247 		msg = "Address already in use";
248 		break;
249 
250 	case WSAEADDRNOTAVAIL:
251 		msg = "Can't assign requested address";
252 		break;
253 
254 	case WSAENETDOWN:
255 		msg = "Network is down";
256 		break;
257 
258 	case WSAENETUNREACH:
259 		msg = "Network is unreachable";
260 		break;
261 
262 	case WSAENETRESET:
263 		msg = "Net connection reset";
264 		break;
265 
266 	case WSAECONNABORTED:
267 		msg = "Software caused connection abort";
268 		break;
269 
270 	case WSAECONNRESET:
271 		msg = "Connection reset by peer";
272 		break;
273 
274 	case WSAENOBUFS:
275 		msg = "No buffer space available";
276 		break;
277 
278 	case WSAEISCONN:
279 		msg = "Socket is already connected";
280 		break;
281 
282 	case WSAENOTCONN:
283 		msg = "Socket is not connected";
284 		break;
285 
286 	case WSAESHUTDOWN:
287 		msg = "Can't send after socket shutdown";
288 		break;
289 
290 	case WSAETOOMANYREFS:
291 		msg = "Too many references: can't splice";
292 		break;
293 
294 	case WSAETIMEDOUT:
295 		msg = "Connection timed out";
296 		break;
297 
298 	case WSAECONNREFUSED:
299 		msg = "Connection refused";
300 		break;
301 
302 	case WSAELOOP:
303 		msg = "Too many levels of symbolic links";
304 		break;
305 
306 	case WSAENAMETOOLONG:
307 		msg = "File name too long";
308 		break;
309 
310 	case WSAEHOSTDOWN:
311 		msg = "Host is down";
312 		break;
313 
314 	case WSAEHOSTUNREACH:
315 		msg = "No route to host";
316 		break;
317 
318 	case WSAENOTEMPTY:
319 		msg = "Directory not empty";
320 		break;
321 
322 	case WSAEPROCLIM:
323 		msg = "Too many processes";
324 		break;
325 
326 	case WSAEUSERS:
327 		msg = "Too many users";
328 		break;
329 
330 	case WSAEDQUOT:
331 		msg = "Disc quota exceeded";
332 		break;
333 
334 	case WSAESTALE:
335 		msg = "Stale NFS file handle";
336 		break;
337 
338 	case WSAEREMOTE:
339 		msg = "Too many levels of remote in path";
340 		break;
341 
342 	case WSASYSNOTREADY:
343 		msg = "Network system is unavailable";
344 		break;
345 
346 	case WSAVERNOTSUPPORTED:
347 		msg = "Winsock version out of range";
348 		break;
349 
350 	case WSANOTINITIALISED:
351 		msg = "WSAStartup not yet called";
352 		break;
353 
354 	case WSAEDISCON:
355 		msg = "Graceful shutdown in progress";
356 		break;
357 /*
358 	case WSAHOST_NOT_FOUND:
359 		msg = "Host not found";
360 		break;
361 
362 	case WSANO_DATA:
363 		msg = "No host data of that type was found";
364 		break;
365 */
366 	default:
367 		msg = NULL;
368 		break;
369 	}
370 	return (msg);
371 }
372 
373 /*
374  * These error messages are more informative about CryptAPI Errors than the
375  * standard error messages
376  */
377 
378 char *
GetCryptErrorMessage(int errval)379 GetCryptErrorMessage(int errval) {
380 	char *msg;
381 
382 	switch (errval) {
383 
384 	case NTE_BAD_FLAGS:
385 		msg = "The dwFlags parameter has an illegal value.";
386 		break;
387 	case NTE_BAD_KEYSET:
388 		msg = "The Registry entry for the key container "
389 			"could not be opened and may not exist.";
390 		break;
391 	case NTE_BAD_KEYSET_PARAM:
392 		msg = "The pszContainer or pszProvider parameter "
393 			"is set to an illegal value.";
394 		break;
395 	case NTE_BAD_PROV_TYPE:
396 		msg = "The value of the dwProvType parameter is out "
397 			"of range. All provider types must be from "
398 			"1 to 999, inclusive.";
399 		break;
400 	case NTE_BAD_SIGNATURE:
401 		msg = "The provider DLL signature did not verify "
402 			"correctly. Either the DLL or the digital "
403 			"signature has been tampered with.";
404 		break;
405 	case NTE_EXISTS:
406 		msg = "The dwFlags parameter is CRYPT_NEWKEYSET, but the key"
407 		      " container already exists.";
408 		break;
409 	case NTE_KEYSET_ENTRY_BAD:
410 		msg = "The Registry entry for the pszContainer key container "
411 		      "was found (in the HKEY_CURRENT_USER window), but is "
412 		      "corrupt. See the section System Administration for "
413 		      " etails about CryptoAPI's Registry usage.";
414 		break;
415 	case NTE_KEYSET_NOT_DEF:
416 		msg = "No Registry entry exists in the HKEY_CURRENT_USER "
417 			"window for the key container specified by "
418 			"pszContainer.";
419 		break;
420 	case NTE_NO_MEMORY:
421 		msg = "The CSP ran out of memory during the operation.";
422 		break;
423 	case NTE_PROV_DLL_NOT_FOUND:
424 		msg = "The provider DLL file does not exist or is not on the "
425 		      "current path.";
426 		break;
427 	case NTE_PROV_TYPE_ENTRY_BAD:
428 		msg = "The Registry entry for the provider type specified by "
429 		      "dwProvType is corrupt. This error may relate to "
430 		      "either the user default CSP list or the machine "
431 		      "default CSP list. See the section System "
432 		      "Administration for details about CryptoAPI's "
433 		      "Registry usage.";
434 		break;
435 	case NTE_PROV_TYPE_NO_MATCH:
436 		msg = "The provider type specified by dwProvType does not "
437 		      "match the provider type found in the Registry. Note "
438 		      "that this error can only occur when pszProvider "
439 		      "specifies an actual CSP name.";
440 		break;
441 	case NTE_PROV_TYPE_NOT_DEF:
442 		msg = "No Registry entry exists for the provider type "
443 		      "specified by dwProvType.";
444 		break;
445 	case NTE_PROVIDER_DLL_FAIL:
446 		msg = "The provider DLL file could not be loaded, and "
447 		      "may not exist. If it exists, then the file is "
448 		      "not a valid DLL.";
449 		break;
450 	case NTE_SIGNATURE_FILE_BAD:
451 		msg = "An error occurred while loading the DLL file image, "
452 		      "prior to verifying its signature.";
453 		break;
454 
455 	default:
456 		msg = NULL;
457 		break;
458 	}
459 	return msg;
460 }
461 
462