8d0eced6a8b2412230fbcc5c3c69a243716b3fac
[reactos.git] / reactos / lib / sdk / crt / string / strerror.c
1 /*
2 * msvcrt.dll errno functions
3 *
4 * Copyright 2000 Jon Griffiths
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include <precomp.h>
22
23 char __syserr00[] = "No Error";
24 char __syserr01[] = "Operation not permitted (EPERM)";
25 char __syserr02[] = "No such file or directory (ENOENT)";
26 char __syserr03[] = "No such process (ESRCH)";
27 char __syserr04[] = "Interrupted system call (EINTR)";
28 char __syserr05[] = "Input or output error (EIO)";
29 char __syserr06[] = "No such device or address (ENXIO)";
30 char __syserr07[] = "Argument list too long (E2BIG)";
31 char __syserr08[] = "Unable to execute file (ENOEXEC)";
32 char __syserr09[] = "Bad file descriptor (EBADF)";
33 char __syserr10[] = "No child processes (ECHILD)";
34 char __syserr11[] = "Resource temporarily unavailable (EAGAIN)";
35 char __syserr12[] = "Not enough memory (ENOMEM)";
36 char __syserr13[] = "Permission denied (EACCES)";
37 char __syserr14[] = "Bad address (EFAULT)";
38 char __syserr15[] = "Unknown Error: 15";
39 char __syserr16[] = "Resource busy (EBUSY)";
40 char __syserr17[] = "File exists (EEXIST)";
41 char __syserr18[] = "Improper link (EXDEV)";
42 char __syserr19[] = "No such device (ENODEV)";
43 char __syserr20[] = "Not a directory (ENOTDIR)";
44 char __syserr21[] = "Is a directory (EISDIR)";
45 char __syserr22[] = "Invalid argument (EINVAL)";
46 char __syserr23[] = "Too many open files in system (ENFILE)";
47 char __syserr24[] = "Too many open files (EMFILE)";
48 char __syserr25[] = "Inappropriate I/O control operation (ENOTTY)";
49 char __syserr26[] = "Unknown error: 26";
50 char __syserr27[] = "File too large (EFBIG)";
51 char __syserr28[] = "No space left on drive (ENOSPC)";
52 char __syserr29[] = "Invalid seek (ESPIPE)";
53 char __syserr30[] = "Read-only file system (EROFS)";
54 char __syserr31[] = "Too many links (EMLINK)";
55 char __syserr32[] = "Broken pipe (EPIPE)";
56 char __syserr33[] = "Input to function out of range (EDOM)";
57 char __syserr34[] = "Output of function out of range (ERANGE)";
58 char __syserr35[] = "Unknown error: 35";
59 char __syserr36[] = "Resource deadlock avoided (EDEADLK)";
60 char __syserr37[] = "Unknown error: 37";
61 char __syserr38[] = "File name too long (ENAMETOOLONG)";
62 char __syserr39[] = "No locks available (ENOLCK)";
63 char __syserr40[] = "Function not implemented (ENOSYS)";
64 char __syserr41[] = "Directory not empty (ENOTEMPTY)";
65 char __syserr42[] = "Illegal byte sequence (EILSEQ)";
66
67 char *_sys_errlist[] = {
68 __syserr00, __syserr01, __syserr02, __syserr03, __syserr04,
69 __syserr05, __syserr06, __syserr07, __syserr08, __syserr09,
70 __syserr10, __syserr11, __syserr12, __syserr13, __syserr14,
71 __syserr15, __syserr16, __syserr17, __syserr18, __syserr19,
72 __syserr20, __syserr21, __syserr22, __syserr23, __syserr24,
73 __syserr25, __syserr26, __syserr27, __syserr28, __syserr29,
74 __syserr30, __syserr31, __syserr32, __syserr33, __syserr34,
75 __syserr35, __syserr36, __syserr37, __syserr38, __syserr39,
76 __syserr40, __syserr41, __syserr42
77 };
78
79 int _sys_nerr = sizeof(_sys_errlist) / sizeof(_sys_errlist[0]) - 1;
80
81 /*********************************************************************
82 * strerror (MSVCRT.@)
83 */
84 char* CDECL strerror(int err)
85 {
86 thread_data_t *data = msvcrt_get_thread_data();
87
88 if (!data->strerror_buffer)
89 if (!(data->strerror_buffer = malloc(256))) return NULL;
90
91 if (err < 0 || err > _sys_nerr) err = _sys_nerr;
92 strcpy( data->strerror_buffer, _sys_errlist[err] );
93 return data->strerror_buffer;
94 }
95
96 /**********************************************************************
97 * strerror_s (MSVCRT.@)
98 */
99 int CDECL strerror_s(char *buffer, size_t numberOfElements, int errnum)
100 {
101 char *ptr;
102
103 if (!buffer || !numberOfElements)
104 {
105 *_errno() = EINVAL;
106 return EINVAL;
107 }
108
109 if (errnum < 0 || errnum > _sys_nerr)
110 errnum = _sys_nerr;
111
112 ptr = _sys_errlist[errnum];
113 while (*ptr && numberOfElements > 1)
114 {
115 *buffer++ = *ptr++;
116 numberOfElements--;
117 }
118
119 *buffer = '\0';
120 return 0;
121 }
122
123 /**********************************************************************
124 * _strerror (MSVCRT.@)
125 */
126 char* CDECL _strerror(const char* str)
127 {
128 thread_data_t *data = msvcrt_get_thread_data();
129 int err;
130
131 if (!data->strerror_buffer)
132 if (!(data->strerror_buffer = malloc(256))) return NULL;
133
134 err = data->thread_errno;
135 if (err < 0 || err > _sys_nerr) err = _sys_nerr;
136
137 if (str && *str)
138 sprintf( data->strerror_buffer, "%s: %s\n", str, _sys_errlist[err] );
139 else
140 sprintf( data->strerror_buffer, "%s\n", _sys_errlist[err] );
141
142 return data->strerror_buffer;
143 }
144
145 /*********************************************************************
146 * perror (MSVCRT.@)
147 */
148 void CDECL perror(const char* str)
149 {
150 int err = *_errno();
151 if (err < 0 || err > _sys_nerr) err = _sys_nerr;
152
153 if (str && *str)
154 {
155 _write( 2, str, strlen(str) );
156 _write( 2, ": ", 2 );
157 }
158 _write( 2, _sys_errlist[err], strlen(_sys_errlist[err]) );
159 _write( 2, "\n", 1 );
160 }
161
162 /*********************************************************************
163 * _wcserror_s (MSVCRT.@)
164 */
165 int CDECL _wcserror_s(wchar_t* buffer, size_t nc, int err)
166 {
167 if (!MSVCRT_CHECK_PMT(buffer != NULL) || !MSVCRT_CHECK_PMT(nc > 0))
168 {
169 _set_errno(EINVAL);
170 return EINVAL;
171 }
172 if (err < 0 || err > _sys_nerr) err = _sys_nerr;
173 MultiByteToWideChar(CP_ACP, 0, _sys_errlist[err], -1, buffer, nc);
174 return 0;
175 }
176
177 /*********************************************************************
178 * _wcserror (MSVCRT.@)
179 */
180 wchar_t* CDECL _wcserror(int err)
181 {
182 thread_data_t *data = msvcrt_get_thread_data();
183
184 if (!data->wcserror_buffer)
185 if (!(data->wcserror_buffer = malloc(256 * sizeof(wchar_t)))) return NULL;
186 _wcserror_s(data->wcserror_buffer, 256, err);
187 return data->wcserror_buffer;
188 }
189
190 /**********************************************************************
191 * __wcserror_s (MSVCRT.@)
192 */
193 int CDECL __wcserror_s(wchar_t* buffer, size_t nc, const wchar_t* str)
194 {
195 int err;
196 static const WCHAR colonW[] = {':', ' ', '\0'};
197 static const WCHAR nlW[] = {'\n', '\0'};
198 size_t len;
199
200 err = *_errno();
201 if (err < 0 || err > _sys_nerr) err = _sys_nerr;
202
203 len = MultiByteToWideChar(CP_ACP, 0, _sys_errlist[err], -1, NULL, 0) + 1 /* \n */;
204 if (str && *str) len += lstrlenW(str) + 2 /* ': ' */;
205 if (len > nc)
206 {
207 MSVCRT_INVALID_PMT("buffer[nc] is too small");
208 _set_errno(ERANGE);
209 return ERANGE;
210 }
211 if (str && *str)
212 {
213 lstrcpyW(buffer, str);
214 lstrcatW(buffer, colonW);
215 }
216 else buffer[0] = '\0';
217 len = lstrlenW(buffer);
218 MultiByteToWideChar(CP_ACP, 0, _sys_errlist[err], -1, buffer + len, 256 - len);
219 lstrcatW(buffer, nlW);
220
221 return 0;
222 }
223
224 /**********************************************************************
225 * __wcserror (MSVCRT.@)
226 */
227 wchar_t* CDECL __wcserror(const wchar_t* str)
228 {
229 thread_data_t *data = msvcrt_get_thread_data();
230 int err;
231
232 if (!data->wcserror_buffer)
233 if (!(data->wcserror_buffer = malloc(256 * sizeof(wchar_t)))) return NULL;
234
235 err = __wcserror_s(data->wcserror_buffer, 256, str);
236 if (err) FIXME("bad wcserror call (%d)\n", err);
237
238 return data->wcserror_buffer;
239 }