xref: /reactos/sdk/lib/ucrt/misc/errno.cpp (revision 04e0dc4a)
1*04e0dc4aSTimo Kreuzer //
2*04e0dc4aSTimo Kreuzer // errno.cpp
3*04e0dc4aSTimo Kreuzer //
4*04e0dc4aSTimo Kreuzer //      Copyright (c) Microsoft Corporation.  All rights reserved.
5*04e0dc4aSTimo Kreuzer //
6*04e0dc4aSTimo Kreuzer // Defines _errno, _doserrno, and related functions
7*04e0dc4aSTimo Kreuzer //
8*04e0dc4aSTimo Kreuzer #define _ALLOW_OLD_VALIDATE_MACROS
9*04e0dc4aSTimo Kreuzer #include <corecrt_internal.h>
10*04e0dc4aSTimo Kreuzer #include <corecrt_internal_ptd_propagation.h>
11*04e0dc4aSTimo Kreuzer #include <errno.h>
12*04e0dc4aSTimo Kreuzer 
13*04e0dc4aSTimo Kreuzer 
14*04e0dc4aSTimo Kreuzer 
15*04e0dc4aSTimo Kreuzer // This is the error table that defines the mapping between OS error codes and
16*04e0dc4aSTimo Kreuzer // errno values.
17*04e0dc4aSTimo Kreuzer namespace
18*04e0dc4aSTimo Kreuzer {
19*04e0dc4aSTimo Kreuzer     struct errentry
20*04e0dc4aSTimo Kreuzer     {
21*04e0dc4aSTimo Kreuzer         unsigned long oscode; // OS return value
22*04e0dc4aSTimo Kreuzer         int errnocode;        // System V error code
23*04e0dc4aSTimo Kreuzer     };
24*04e0dc4aSTimo Kreuzer }
25*04e0dc4aSTimo Kreuzer 
26*04e0dc4aSTimo Kreuzer static errentry const errtable[]
27*04e0dc4aSTimo Kreuzer {
28*04e0dc4aSTimo Kreuzer     { ERROR_INVALID_FUNCTION,       EINVAL    },  //    1
29*04e0dc4aSTimo Kreuzer     { ERROR_FILE_NOT_FOUND,         ENOENT    },  //    2
30*04e0dc4aSTimo Kreuzer     { ERROR_PATH_NOT_FOUND,         ENOENT    },  //    3
31*04e0dc4aSTimo Kreuzer     { ERROR_TOO_MANY_OPEN_FILES,    EMFILE    },  //    4
32*04e0dc4aSTimo Kreuzer     { ERROR_ACCESS_DENIED,          EACCES    },  //    5
33*04e0dc4aSTimo Kreuzer     { ERROR_INVALID_HANDLE,         EBADF     },  //    6
34*04e0dc4aSTimo Kreuzer     { ERROR_ARENA_TRASHED,          ENOMEM    },  //    7
35*04e0dc4aSTimo Kreuzer     { ERROR_NOT_ENOUGH_MEMORY,      ENOMEM    },  //    8
36*04e0dc4aSTimo Kreuzer     { ERROR_INVALID_BLOCK,          ENOMEM    },  //    9
37*04e0dc4aSTimo Kreuzer     { ERROR_BAD_ENVIRONMENT,        E2BIG     },  //   10
38*04e0dc4aSTimo Kreuzer     { ERROR_BAD_FORMAT,             ENOEXEC   },  //   11
39*04e0dc4aSTimo Kreuzer     { ERROR_INVALID_ACCESS,         EINVAL    },  //   12
40*04e0dc4aSTimo Kreuzer     { ERROR_INVALID_DATA,           EINVAL    },  //   13
41*04e0dc4aSTimo Kreuzer     { ERROR_INVALID_DRIVE,          ENOENT    },  //   15
42*04e0dc4aSTimo Kreuzer     { ERROR_CURRENT_DIRECTORY,      EACCES    },  //   16
43*04e0dc4aSTimo Kreuzer     { ERROR_NOT_SAME_DEVICE,        EXDEV     },  //   17
44*04e0dc4aSTimo Kreuzer     { ERROR_NO_MORE_FILES,          ENOENT    },  //   18
45*04e0dc4aSTimo Kreuzer     { ERROR_LOCK_VIOLATION,         EACCES    },  //   33
46*04e0dc4aSTimo Kreuzer     { ERROR_BAD_NETPATH,            ENOENT    },  //   53
47*04e0dc4aSTimo Kreuzer     { ERROR_NETWORK_ACCESS_DENIED,  EACCES    },  //   65
48*04e0dc4aSTimo Kreuzer     { ERROR_BAD_NET_NAME,           ENOENT    },  //   67
49*04e0dc4aSTimo Kreuzer     { ERROR_FILE_EXISTS,            EEXIST    },  //   80
50*04e0dc4aSTimo Kreuzer     { ERROR_CANNOT_MAKE,            EACCES    },  //   82
51*04e0dc4aSTimo Kreuzer     { ERROR_FAIL_I24,               EACCES    },  //   83
52*04e0dc4aSTimo Kreuzer     { ERROR_INVALID_PARAMETER,      EINVAL    },  //   87
53*04e0dc4aSTimo Kreuzer     { ERROR_NO_PROC_SLOTS,          EAGAIN    },  //   89
54*04e0dc4aSTimo Kreuzer     { ERROR_DRIVE_LOCKED,           EACCES    },  //  108
55*04e0dc4aSTimo Kreuzer     { ERROR_BROKEN_PIPE,            EPIPE     },  //  109
56*04e0dc4aSTimo Kreuzer     { ERROR_DISK_FULL,              ENOSPC    },  //  112
57*04e0dc4aSTimo Kreuzer     { ERROR_INVALID_TARGET_HANDLE,  EBADF     },  //  114
58*04e0dc4aSTimo Kreuzer     { ERROR_WAIT_NO_CHILDREN,       ECHILD    },  //  128
59*04e0dc4aSTimo Kreuzer     { ERROR_CHILD_NOT_COMPLETE,     ECHILD    },  //  129
60*04e0dc4aSTimo Kreuzer     { ERROR_DIRECT_ACCESS_HANDLE,   EBADF     },  //  130
61*04e0dc4aSTimo Kreuzer     { ERROR_NEGATIVE_SEEK,          EINVAL    },  //  131
62*04e0dc4aSTimo Kreuzer     { ERROR_SEEK_ON_DEVICE,         EACCES    },  //  132
63*04e0dc4aSTimo Kreuzer     { ERROR_DIR_NOT_EMPTY,          ENOTEMPTY },  //  145
64*04e0dc4aSTimo Kreuzer     { ERROR_NOT_LOCKED,             EACCES    },  //  158
65*04e0dc4aSTimo Kreuzer     { ERROR_BAD_PATHNAME,           ENOENT    },  //  161
66*04e0dc4aSTimo Kreuzer     { ERROR_MAX_THRDS_REACHED,      EAGAIN    },  //  164
67*04e0dc4aSTimo Kreuzer     { ERROR_LOCK_FAILED,            EACCES    },  //  167
68*04e0dc4aSTimo Kreuzer     { ERROR_ALREADY_EXISTS,         EEXIST    },  //  183
69*04e0dc4aSTimo Kreuzer     { ERROR_FILENAME_EXCED_RANGE,   ENOENT    },  //  206
70*04e0dc4aSTimo Kreuzer     { ERROR_NESTING_NOT_ALLOWED,    EAGAIN    },  //  215
71*04e0dc4aSTimo Kreuzer     { ERROR_NO_UNICODE_TRANSLATION, EILSEQ    },  // 1113
72*04e0dc4aSTimo Kreuzer     { ERROR_NOT_ENOUGH_QUOTA,       ENOMEM    }   // 1816
73*04e0dc4aSTimo Kreuzer };
74*04e0dc4aSTimo Kreuzer 
75*04e0dc4aSTimo Kreuzer // Number of elements in the table
76*04e0dc4aSTimo Kreuzer #define ERRTABLECOUNT (sizeof(errtable) / sizeof(errtable[0]))
77*04e0dc4aSTimo Kreuzer 
78*04e0dc4aSTimo Kreuzer // The following two constants must be the minimum and maximum
79*04e0dc4aSTimo Kreuzer // values in the (contiguous) range of Exec Failure errors.
80*04e0dc4aSTimo Kreuzer #define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG
81*04e0dc4aSTimo Kreuzer #define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN
82*04e0dc4aSTimo Kreuzer 
83*04e0dc4aSTimo Kreuzer // These are the low and high value in the range of errors that are
84*04e0dc4aSTimo Kreuzer // access violations
85*04e0dc4aSTimo Kreuzer #define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
86*04e0dc4aSTimo Kreuzer #define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED
87*04e0dc4aSTimo Kreuzer 
88*04e0dc4aSTimo Kreuzer 
89*04e0dc4aSTimo Kreuzer 
90*04e0dc4aSTimo Kreuzer // These map Windows error codes into errno error codes
__acrt_errno_map_os_error(unsigned long const oserrno)91*04e0dc4aSTimo Kreuzer extern "C" void __cdecl __acrt_errno_map_os_error(unsigned long const oserrno)
92*04e0dc4aSTimo Kreuzer {
93*04e0dc4aSTimo Kreuzer     _doserrno = oserrno;
94*04e0dc4aSTimo Kreuzer     errno     = __acrt_errno_from_os_error(oserrno);
95*04e0dc4aSTimo Kreuzer }
96*04e0dc4aSTimo Kreuzer 
__acrt_errno_map_os_error_ptd(unsigned long const oserrno,__crt_cached_ptd_host & ptd)97*04e0dc4aSTimo Kreuzer extern "C" void __cdecl __acrt_errno_map_os_error_ptd(unsigned long const oserrno, __crt_cached_ptd_host& ptd)
98*04e0dc4aSTimo Kreuzer {
99*04e0dc4aSTimo Kreuzer     ptd.get_doserrno().set(oserrno);
100*04e0dc4aSTimo Kreuzer     ptd.get_errno().set(__acrt_errno_from_os_error(oserrno));
101*04e0dc4aSTimo Kreuzer }
102*04e0dc4aSTimo Kreuzer 
__acrt_errno_from_os_error(unsigned long const oserrno)103*04e0dc4aSTimo Kreuzer extern "C" int __cdecl __acrt_errno_from_os_error(unsigned long const oserrno)
104*04e0dc4aSTimo Kreuzer {
105*04e0dc4aSTimo Kreuzer     // Check the table for the OS error code
106*04e0dc4aSTimo Kreuzer     for (unsigned i{0}; i < ERRTABLECOUNT; ++i)
107*04e0dc4aSTimo Kreuzer     {
108*04e0dc4aSTimo Kreuzer         if (oserrno == errtable[i].oscode)
109*04e0dc4aSTimo Kreuzer             return errtable[i].errnocode;
110*04e0dc4aSTimo Kreuzer     }
111*04e0dc4aSTimo Kreuzer 
112*04e0dc4aSTimo Kreuzer     // The error code wasn't in the table.  We check for a range of
113*04e0dc4aSTimo Kreuzer     // EACCES errors or exec failure errors (ENOEXEC).  Otherwise
114*04e0dc4aSTimo Kreuzer     // EINVAL is returned.
115*04e0dc4aSTimo Kreuzer     if (oserrno >= MIN_EACCES_RANGE && oserrno <= MAX_EACCES_RANGE)
116*04e0dc4aSTimo Kreuzer     {
117*04e0dc4aSTimo Kreuzer         return EACCES;
118*04e0dc4aSTimo Kreuzer     }
119*04e0dc4aSTimo Kreuzer     else if (oserrno >= MIN_EXEC_ERROR && oserrno <= MAX_EXEC_ERROR)
120*04e0dc4aSTimo Kreuzer     {
121*04e0dc4aSTimo Kreuzer         return ENOEXEC;
122*04e0dc4aSTimo Kreuzer     }
123*04e0dc4aSTimo Kreuzer     else
124*04e0dc4aSTimo Kreuzer     {
125*04e0dc4aSTimo Kreuzer         return EINVAL;
126*04e0dc4aSTimo Kreuzer     }
127*04e0dc4aSTimo Kreuzer }
128*04e0dc4aSTimo Kreuzer 
129*04e0dc4aSTimo Kreuzer 
130*04e0dc4aSTimo Kreuzer 
131*04e0dc4aSTimo Kreuzer // These safely set and get the value of the calling thread's errno
_set_errno(int const value)132*04e0dc4aSTimo Kreuzer extern "C" errno_t _set_errno(int const value)
133*04e0dc4aSTimo Kreuzer {
134*04e0dc4aSTimo Kreuzer     __acrt_ptd* const ptd{__acrt_getptd_noexit()};
135*04e0dc4aSTimo Kreuzer     if (!ptd)
136*04e0dc4aSTimo Kreuzer         return ENOMEM;
137*04e0dc4aSTimo Kreuzer 
138*04e0dc4aSTimo Kreuzer     errno = value;
139*04e0dc4aSTimo Kreuzer     return 0;
140*04e0dc4aSTimo Kreuzer }
141*04e0dc4aSTimo Kreuzer 
_get_errno(int * const result)142*04e0dc4aSTimo Kreuzer extern "C" errno_t _get_errno(int* const result)
143*04e0dc4aSTimo Kreuzer {
144*04e0dc4aSTimo Kreuzer     _VALIDATE_RETURN_NOERRNO(result != nullptr, EINVAL);
145*04e0dc4aSTimo Kreuzer 
146*04e0dc4aSTimo Kreuzer     // Unlike most of our globals, this one is guaranteed to give some answer
147*04e0dc4aSTimo Kreuzer     *result = errno;
148*04e0dc4aSTimo Kreuzer     return 0;
149*04e0dc4aSTimo Kreuzer }
150*04e0dc4aSTimo Kreuzer 
151*04e0dc4aSTimo Kreuzer 
152*04e0dc4aSTimo Kreuzer 
153*04e0dc4aSTimo Kreuzer // These safely set and get the value of the calling thread's doserrno
_set_doserrno(unsigned long const value)154*04e0dc4aSTimo Kreuzer extern "C" errno_t _set_doserrno(unsigned long const value)
155*04e0dc4aSTimo Kreuzer {
156*04e0dc4aSTimo Kreuzer     __acrt_ptd* const ptd{__acrt_getptd_noexit()};
157*04e0dc4aSTimo Kreuzer     if (!ptd)
158*04e0dc4aSTimo Kreuzer         return ENOMEM;
159*04e0dc4aSTimo Kreuzer 
160*04e0dc4aSTimo Kreuzer     _doserrno = value;
161*04e0dc4aSTimo Kreuzer     return 0;
162*04e0dc4aSTimo Kreuzer }
163*04e0dc4aSTimo Kreuzer 
_get_doserrno(unsigned long * const result)164*04e0dc4aSTimo Kreuzer extern "C" errno_t _get_doserrno(unsigned long* const result)
165*04e0dc4aSTimo Kreuzer {
166*04e0dc4aSTimo Kreuzer     _VALIDATE_RETURN_NOERRNO(result != nullptr, EINVAL);
167*04e0dc4aSTimo Kreuzer 
168*04e0dc4aSTimo Kreuzer     // Unlike most of our globals, this one is guaranteed to give some answer:
169*04e0dc4aSTimo Kreuzer     *result = _doserrno;
170*04e0dc4aSTimo Kreuzer     return 0;
171*04e0dc4aSTimo Kreuzer }
172*04e0dc4aSTimo Kreuzer 
173*04e0dc4aSTimo Kreuzer 
174*04e0dc4aSTimo Kreuzer 
175*04e0dc4aSTimo Kreuzer // These return pointers to the calling thread's errno and doserrno values,
176*04e0dc4aSTimo Kreuzer // respectively, and are used to implement errno and _doserrno in the header.
177*04e0dc4aSTimo Kreuzer static int           errno_no_memory   {ENOMEM};
178*04e0dc4aSTimo Kreuzer static unsigned long doserrno_no_memory{ERROR_NOT_ENOUGH_MEMORY};
179*04e0dc4aSTimo Kreuzer 
_errno()180*04e0dc4aSTimo Kreuzer extern "C" int* __cdecl _errno()
181*04e0dc4aSTimo Kreuzer {
182*04e0dc4aSTimo Kreuzer     __acrt_ptd* const ptd{__acrt_getptd_noexit()};
183*04e0dc4aSTimo Kreuzer     if (!ptd)
184*04e0dc4aSTimo Kreuzer     {
185*04e0dc4aSTimo Kreuzer         return &errno_no_memory;
186*04e0dc4aSTimo Kreuzer     }
187*04e0dc4aSTimo Kreuzer 
188*04e0dc4aSTimo Kreuzer     return &ptd->_terrno;
189*04e0dc4aSTimo Kreuzer }
190*04e0dc4aSTimo Kreuzer 
__doserrno()191*04e0dc4aSTimo Kreuzer extern "C" unsigned long* __cdecl __doserrno()
192*04e0dc4aSTimo Kreuzer {
193*04e0dc4aSTimo Kreuzer     __acrt_ptd* const ptd{__acrt_getptd_noexit()};
194*04e0dc4aSTimo Kreuzer     if (!ptd)
195*04e0dc4aSTimo Kreuzer     {
196*04e0dc4aSTimo Kreuzer         return &doserrno_no_memory;
197*04e0dc4aSTimo Kreuzer     }
198*04e0dc4aSTimo Kreuzer 
199*04e0dc4aSTimo Kreuzer     return &ptd->_tdoserrno;
200*04e0dc4aSTimo Kreuzer }
201