Reactos
at master 146 lines 4.4 kB view raw
1// 2// strerror.cpp 3// 4// Copyright (c) Microsoft Corporation. All rights reserved. 5// 6// Defines the strerror() family of functions, which convert an errno error code 7// to a string representation. Note that there are legacy implementations of 8// these functions, prefixed with underscores, in _strerr.cpp. The functions in 9// this file are implemented per the C Standard Library specification. 10// 11#include <corecrt_internal.h> 12#include <malloc.h> 13#include <stddef.h> 14#include <stdlib.h> 15#include <string.h> 16 17 18 19// These functions return the error string to be used when we are unable to return 20// the actual error string. 21_Ret_z_ 22static char* get_failure_string(char) throw() 23{ 24 return const_cast<char*>("Visual C++ CRT: Not enough memory to complete call to strerror."); 25} 26 27_Ret_z_ 28static wchar_t* get_failure_string(wchar_t) throw() 29{ 30 return const_cast<wchar_t*>(L"Visual C++ CRT: Not enough memory to complete call to strerror."); 31} 32 33 34 35// These functions return a reference to the thread-local pointer to the buffer 36// to be used to store the error string. 37static char*& get_ptd_buffer(__acrt_ptd* const ptd, char) throw() 38{ 39 return ptd->_strerror_buffer; 40} 41 42static wchar_t*& get_ptd_buffer(__acrt_ptd* const ptd, wchar_t) throw() 43{ 44 return ptd->_wcserror_buffer; 45} 46 47 48 49// These functions copy the narrow string into the provided buffer. 50_Success_(return == 0) 51static errno_t copy_string_into_buffer( 52 _In_reads_or_z_(max_count) char const* const string, 53 _Out_writes_z_(buffer_count) char* const buffer, 54 size_t const buffer_count, 55 size_t const max_count 56 ) throw() 57{ 58 return strncpy_s(buffer, buffer_count, string, max_count); 59} 60 61_Success_(return == 0) 62static errno_t copy_string_into_buffer( 63 _In_reads_or_z_(max_count) char const* const string, 64 _Out_writes_z_(buffer_count) wchar_t* const buffer, 65 size_t const buffer_count, 66 size_t const max_count 67 ) throw() 68{ 69 return mbstowcs_s(nullptr, buffer, buffer_count, string, max_count); 70} 71 72 73 74// Maps an error number to an error message string. The error number should be 75// one of the errno values. The string is valid until the next call (on this 76// thread) to one of the strerror functions. The CRT owns the string. 77template <typename Character> 78_Ret_z_ 79static Character* __cdecl common_strerror(int const error_number) 80{ 81 __acrt_ptd* const ptd = __acrt_getptd_noexit(); 82 if (!ptd) 83 return get_failure_string(Character()); 84 85 Character*& buffer = get_ptd_buffer(ptd, Character()); 86 if (!buffer) 87 buffer = _calloc_crt_t(Character, strerror_buffer_count).detach(); 88 89 if (!buffer) 90 return get_failure_string(Character()); 91 92 _ERRCHECK(copy_string_into_buffer(_get_sys_err_msg(error_number), buffer, strerror_buffer_count, strerror_buffer_count - 1)); 93 return buffer; 94} 95 96extern "C" char* __cdecl strerror(int const error_number) 97{ 98 return common_strerror<char>(error_number); 99} 100 101extern "C" wchar_t* __cdecl _wcserror(int const error_number) 102{ 103 return common_strerror<wchar_t>(error_number); 104} 105 106 107 108// Maps an error number to an error message string. The error number should be 109// one of the errno values. The string is copied into the provided buffer. On 110// success or truncation, 0 is returned. Otherwise, an error code is returned. 111template <typename Character> 112static errno_t __cdecl common_strerror_s( 113 _Out_writes_z_(buffer_count) Character* const buffer, 114 size_t const buffer_count, 115 int const error_number 116 ) 117{ 118 _VALIDATE_RETURN_ERRCODE(buffer != nullptr, EINVAL); 119 _VALIDATE_RETURN_ERRCODE(buffer_count > 0, EINVAL); 120 121 errno_t const result = _ERRCHECK_EINVAL_ERANGE(copy_string_into_buffer( 122 _get_sys_err_msg(error_number), 123 buffer, 124 buffer_count, 125 _TRUNCATE)); 126 127 return result == STRUNCATE ? 0 : result; 128} 129 130extern "C" errno_t __cdecl strerror_s( 131 char* const buffer, 132 size_t const buffer_count, 133 int const error_number 134 ) 135{ 136 return common_strerror_s(buffer, buffer_count, error_number); 137} 138 139extern "C" errno_t __cdecl _wcserror_s( 140 wchar_t* const buffer, 141 size_t const buffer_count, 142 int const error_number 143 ) 144{ 145 return common_strerror_s(buffer, buffer_count, error_number); 146}