mirror of
https://github.com/reactos/reactos.git
synced 2025-06-06 18:00:41 +00:00

Imported from https://www.nuget.org/packages/Microsoft.Windows.SDK.CRTSource/10.0.22621.3 License: MIT
200 lines
6.3 KiB
C++
200 lines
6.3 KiB
C++
//
|
|
// errno.cpp
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// Defines _errno, _doserrno, and related functions
|
|
//
|
|
#define _ALLOW_OLD_VALIDATE_MACROS
|
|
#include <corecrt_internal.h>
|
|
#include <corecrt_internal_ptd_propagation.h>
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
// This is the error table that defines the mapping between OS error codes and
|
|
// errno values.
|
|
namespace
|
|
{
|
|
struct errentry
|
|
{
|
|
unsigned long oscode; // OS return value
|
|
int errnocode; // System V error code
|
|
};
|
|
}
|
|
|
|
static errentry const errtable[]
|
|
{
|
|
{ ERROR_INVALID_FUNCTION, EINVAL }, // 1
|
|
{ ERROR_FILE_NOT_FOUND, ENOENT }, // 2
|
|
{ ERROR_PATH_NOT_FOUND, ENOENT }, // 3
|
|
{ ERROR_TOO_MANY_OPEN_FILES, EMFILE }, // 4
|
|
{ ERROR_ACCESS_DENIED, EACCES }, // 5
|
|
{ ERROR_INVALID_HANDLE, EBADF }, // 6
|
|
{ ERROR_ARENA_TRASHED, ENOMEM }, // 7
|
|
{ ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, // 8
|
|
{ ERROR_INVALID_BLOCK, ENOMEM }, // 9
|
|
{ ERROR_BAD_ENVIRONMENT, E2BIG }, // 10
|
|
{ ERROR_BAD_FORMAT, ENOEXEC }, // 11
|
|
{ ERROR_INVALID_ACCESS, EINVAL }, // 12
|
|
{ ERROR_INVALID_DATA, EINVAL }, // 13
|
|
{ ERROR_INVALID_DRIVE, ENOENT }, // 15
|
|
{ ERROR_CURRENT_DIRECTORY, EACCES }, // 16
|
|
{ ERROR_NOT_SAME_DEVICE, EXDEV }, // 17
|
|
{ ERROR_NO_MORE_FILES, ENOENT }, // 18
|
|
{ ERROR_LOCK_VIOLATION, EACCES }, // 33
|
|
{ ERROR_BAD_NETPATH, ENOENT }, // 53
|
|
{ ERROR_NETWORK_ACCESS_DENIED, EACCES }, // 65
|
|
{ ERROR_BAD_NET_NAME, ENOENT }, // 67
|
|
{ ERROR_FILE_EXISTS, EEXIST }, // 80
|
|
{ ERROR_CANNOT_MAKE, EACCES }, // 82
|
|
{ ERROR_FAIL_I24, EACCES }, // 83
|
|
{ ERROR_INVALID_PARAMETER, EINVAL }, // 87
|
|
{ ERROR_NO_PROC_SLOTS, EAGAIN }, // 89
|
|
{ ERROR_DRIVE_LOCKED, EACCES }, // 108
|
|
{ ERROR_BROKEN_PIPE, EPIPE }, // 109
|
|
{ ERROR_DISK_FULL, ENOSPC }, // 112
|
|
{ ERROR_INVALID_TARGET_HANDLE, EBADF }, // 114
|
|
{ ERROR_WAIT_NO_CHILDREN, ECHILD }, // 128
|
|
{ ERROR_CHILD_NOT_COMPLETE, ECHILD }, // 129
|
|
{ ERROR_DIRECT_ACCESS_HANDLE, EBADF }, // 130
|
|
{ ERROR_NEGATIVE_SEEK, EINVAL }, // 131
|
|
{ ERROR_SEEK_ON_DEVICE, EACCES }, // 132
|
|
{ ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, // 145
|
|
{ ERROR_NOT_LOCKED, EACCES }, // 158
|
|
{ ERROR_BAD_PATHNAME, ENOENT }, // 161
|
|
{ ERROR_MAX_THRDS_REACHED, EAGAIN }, // 164
|
|
{ ERROR_LOCK_FAILED, EACCES }, // 167
|
|
{ ERROR_ALREADY_EXISTS, EEXIST }, // 183
|
|
{ ERROR_FILENAME_EXCED_RANGE, ENOENT }, // 206
|
|
{ ERROR_NESTING_NOT_ALLOWED, EAGAIN }, // 215
|
|
{ ERROR_NO_UNICODE_TRANSLATION, EILSEQ }, // 1113
|
|
{ ERROR_NOT_ENOUGH_QUOTA, ENOMEM } // 1816
|
|
};
|
|
|
|
// Number of elements in the table
|
|
#define ERRTABLECOUNT (sizeof(errtable) / sizeof(errtable[0]))
|
|
|
|
// The following two constants must be the minimum and maximum
|
|
// values in the (contiguous) range of Exec Failure errors.
|
|
#define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG
|
|
#define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN
|
|
|
|
// These are the low and high value in the range of errors that are
|
|
// access violations
|
|
#define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
|
|
#define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED
|
|
|
|
|
|
|
|
// These map Windows error codes into errno error codes
|
|
extern "C" void __cdecl __acrt_errno_map_os_error(unsigned long const oserrno)
|
|
{
|
|
_doserrno = oserrno;
|
|
errno = __acrt_errno_from_os_error(oserrno);
|
|
}
|
|
|
|
extern "C" void __cdecl __acrt_errno_map_os_error_ptd(unsigned long const oserrno, __crt_cached_ptd_host& ptd)
|
|
{
|
|
ptd.get_doserrno().set(oserrno);
|
|
ptd.get_errno().set(__acrt_errno_from_os_error(oserrno));
|
|
}
|
|
|
|
extern "C" int __cdecl __acrt_errno_from_os_error(unsigned long const oserrno)
|
|
{
|
|
// Check the table for the OS error code
|
|
for (unsigned i{0}; i < ERRTABLECOUNT; ++i)
|
|
{
|
|
if (oserrno == errtable[i].oscode)
|
|
return errtable[i].errnocode;
|
|
}
|
|
|
|
// The error code wasn't in the table. We check for a range of
|
|
// EACCES errors or exec failure errors (ENOEXEC). Otherwise
|
|
// EINVAL is returned.
|
|
if (oserrno >= MIN_EACCES_RANGE && oserrno <= MAX_EACCES_RANGE)
|
|
{
|
|
return EACCES;
|
|
}
|
|
else if (oserrno >= MIN_EXEC_ERROR && oserrno <= MAX_EXEC_ERROR)
|
|
{
|
|
return ENOEXEC;
|
|
}
|
|
else
|
|
{
|
|
return EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// These safely set and get the value of the calling thread's errno
|
|
extern "C" errno_t _set_errno(int const value)
|
|
{
|
|
__acrt_ptd* const ptd{__acrt_getptd_noexit()};
|
|
if (!ptd)
|
|
return ENOMEM;
|
|
|
|
errno = value;
|
|
return 0;
|
|
}
|
|
|
|
extern "C" errno_t _get_errno(int* const result)
|
|
{
|
|
_VALIDATE_RETURN_NOERRNO(result != nullptr, EINVAL);
|
|
|
|
// Unlike most of our globals, this one is guaranteed to give some answer
|
|
*result = errno;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
// These safely set and get the value of the calling thread's doserrno
|
|
extern "C" errno_t _set_doserrno(unsigned long const value)
|
|
{
|
|
__acrt_ptd* const ptd{__acrt_getptd_noexit()};
|
|
if (!ptd)
|
|
return ENOMEM;
|
|
|
|
_doserrno = value;
|
|
return 0;
|
|
}
|
|
|
|
extern "C" errno_t _get_doserrno(unsigned long* const result)
|
|
{
|
|
_VALIDATE_RETURN_NOERRNO(result != nullptr, EINVAL);
|
|
|
|
// Unlike most of our globals, this one is guaranteed to give some answer:
|
|
*result = _doserrno;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
// These return pointers to the calling thread's errno and doserrno values,
|
|
// respectively, and are used to implement errno and _doserrno in the header.
|
|
static int errno_no_memory {ENOMEM};
|
|
static unsigned long doserrno_no_memory{ERROR_NOT_ENOUGH_MEMORY};
|
|
|
|
extern "C" int* __cdecl _errno()
|
|
{
|
|
__acrt_ptd* const ptd{__acrt_getptd_noexit()};
|
|
if (!ptd)
|
|
{
|
|
return &errno_no_memory;
|
|
}
|
|
|
|
return &ptd->_terrno;
|
|
}
|
|
|
|
extern "C" unsigned long* __cdecl __doserrno()
|
|
{
|
|
__acrt_ptd* const ptd{__acrt_getptd_noexit()};
|
|
if (!ptd)
|
|
{
|
|
return &doserrno_no_memory;
|
|
}
|
|
|
|
return &ptd->_tdoserrno;
|
|
}
|