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 char __syserr43[] = "Unknown/generic error"; 67 68 char *_sys_errlist[] = { 69 __syserr00, __syserr01, __syserr02, __syserr03, __syserr04, 70 __syserr05, __syserr06, __syserr07, __syserr08, __syserr09, 71 __syserr10, __syserr11, __syserr12, __syserr13, __syserr14, 72 __syserr15, __syserr16, __syserr17, __syserr18, __syserr19, 73 __syserr20, __syserr21, __syserr22, __syserr23, __syserr24, 74 __syserr25, __syserr26, __syserr27, __syserr28, __syserr29, 75 __syserr30, __syserr31, __syserr32, __syserr33, __syserr34, 76 __syserr35, __syserr36, __syserr37, __syserr38, __syserr39, 77 __syserr40, __syserr41, __syserr42, __syserr43 78 }; 79 80 int _sys_nerr = sizeof(_sys_errlist) / sizeof(_sys_errlist[0]) - 1; 81 82 /********************************************************************* 83 * strerror (MSVCRT.@) 84 */ 85 char* CDECL strerror(int err) 86 { 87 thread_data_t *data = msvcrt_get_thread_data(); 88 89 if (!data->strerror_buffer) 90 if (!(data->strerror_buffer = malloc(256))) return NULL; 91 92 if (err < 0 || err > _sys_nerr) err = _sys_nerr; 93 strcpy( data->strerror_buffer, _sys_errlist[err] ); 94 return data->strerror_buffer; 95 } 96 97 /********************************************************************** 98 * strerror_s (MSVCRT.@) 99 */ 100 int CDECL strerror_s(char *buffer, size_t numberOfElements, int errnum) 101 { 102 char *ptr; 103 104 if (!buffer || !numberOfElements) 105 { 106 *_errno() = EINVAL; 107 return EINVAL; 108 } 109 110 if (errnum < 0 || errnum > _sys_nerr) 111 errnum = _sys_nerr; 112 113 ptr = _sys_errlist[errnum]; 114 while (*ptr && numberOfElements > 1) 115 { 116 *buffer++ = *ptr++; 117 numberOfElements--; 118 } 119 120 *buffer = '\0'; 121 return 0; 122 } 123 124 /********************************************************************** 125 * _strerror (MSVCRT.@) 126 */ 127 char* CDECL _strerror(const char* str) 128 { 129 thread_data_t *data = msvcrt_get_thread_data(); 130 int err; 131 132 if (!data->strerror_buffer) 133 if (!(data->strerror_buffer = malloc(256))) return NULL; 134 135 err = data->thread_errno; 136 if (err < 0 || err > _sys_nerr) err = _sys_nerr; 137 138 if (str && *str) 139 sprintf( data->strerror_buffer, "%s: %s\n", str, _sys_errlist[err] ); 140 else 141 sprintf( data->strerror_buffer, "%s\n", _sys_errlist[err] ); 142 143 return data->strerror_buffer; 144 } 145 146 /********************************************************************* 147 * perror (MSVCRT.@) 148 */ 149 void CDECL perror(const char* str) 150 { 151 int err = *_errno(); 152 if (err < 0 || err > _sys_nerr) err = _sys_nerr; 153 154 if (str && *str) 155 { 156 _write( 2, str, strlen(str) ); 157 _write( 2, ": ", 2 ); 158 } 159 _write( 2, _sys_errlist[err], strlen(_sys_errlist[err]) ); 160 _write( 2, "\n", 1 ); 161 } 162 163 /********************************************************************* 164 * _wcserror_s (MSVCRT.@) 165 */ 166 int CDECL _wcserror_s(wchar_t* buffer, size_t nc, int err) 167 { 168 if (!MSVCRT_CHECK_PMT(buffer != NULL) || !MSVCRT_CHECK_PMT(nc > 0)) 169 { 170 _set_errno(EINVAL); 171 return EINVAL; 172 } 173 if (err < 0 || err > _sys_nerr) err = _sys_nerr; 174 MultiByteToWideChar(CP_ACP, 0, _sys_errlist[err], -1, buffer, nc); 175 return 0; 176 } 177 178 /********************************************************************* 179 * _wcserror (MSVCRT.@) 180 */ 181 wchar_t* CDECL _wcserror(int err) 182 { 183 thread_data_t *data = msvcrt_get_thread_data(); 184 185 if (!data->wcserror_buffer) 186 if (!(data->wcserror_buffer = malloc(256 * sizeof(wchar_t)))) return NULL; 187 _wcserror_s(data->wcserror_buffer, 256, err); 188 return data->wcserror_buffer; 189 } 190 191 /********************************************************************** 192 * __wcserror_s (MSVCRT.@) 193 */ 194 int CDECL __wcserror_s(wchar_t* buffer, size_t nc, const wchar_t* str) 195 { 196 int err; 197 static const WCHAR colonW[] = {':', ' ', '\0'}; 198 static const WCHAR nlW[] = {'\n', '\0'}; 199 size_t len; 200 201 err = *_errno(); 202 if (err < 0 || err > _sys_nerr) err = _sys_nerr; 203 204 len = MultiByteToWideChar(CP_ACP, 0, _sys_errlist[err], -1, NULL, 0) + 1 /* \n */; 205 if (str && *str) len += lstrlenW(str) + 2 /* ': ' */; 206 if (len > nc) 207 { 208 MSVCRT_INVALID_PMT("buffer[nc] is too small", 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 } 240