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