1// 2// impl/error_code.ipp 3// ~~~~~~~~~~~~~~~~~~~ 4// 5// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6// 7// Distributed under the Boost Software License, Version 1.0. (See accompanying 8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9// 10 11#ifndef ASIO_IMPL_ERROR_CODE_IPP 12#define ASIO_IMPL_ERROR_CODE_IPP 13 14#if defined(_MSC_VER) && (_MSC_VER >= 1200) 15# pragma once 16#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18#include "asio/detail/config.hpp" 19#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 20# include <winerror.h> 21#elif defined(ASIO_WINDOWS_RUNTIME) 22# include <windows.h> 23#else 24# include <cerrno> 25# include <cstring> 26# include <string> 27#endif 28#include "asio/detail/local_free_on_block_exit.hpp" 29#include "asio/detail/socket_types.hpp" 30#include "asio/error_code.hpp" 31 32#include "asio/detail/push_options.hpp" 33 34namespace clmdep_asio { 35namespace detail { 36 37class system_category : public error_category 38{ 39public: 40 const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT 41 { 42 return "asio.system"; 43 } 44 45 std::string message(int value) const 46 { 47#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) 48 char* msg = 0; 49 DWORD length = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER 50 | FORMAT_MESSAGE_FROM_SYSTEM 51 | FORMAT_MESSAGE_IGNORE_INSERTS, 0, value, 52 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); 53 detail::local_free_on_block_exit local_free_obj(msg); 54 if (length && msg[length - 1] == '\n') 55 msg[--length] = '\0'; 56 if (length && msg[length - 1] == '\r') 57 msg[--length] = '\0'; 58 if (length) 59 return msg; 60 else 61 return "asio.system error"; 62#elif defined(ASIO_WINDOWS_RUNTIME) 63 std::wstring wmsg(128, wchar_t()); 64 for (;;) 65 { 66 DWORD wlength = ::FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM 67 | FORMAT_MESSAGE_IGNORE_INSERTS, 0, value, 68 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &wmsg[0], wmsg.size(), 0); 69 if (wlength == 0 && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) 70 { 71 wmsg.resize(wmsg.size() + wmsg.size() / 2); 72 continue; 73 } 74 if (wlength && wmsg[wlength - 1] == '\n') 75 --wlength; 76 if (wlength && wmsg[wlength - 1] == '\r') 77 --wlength; 78 if (wlength) 79 { 80 std::string msg(wlength * 2, char()); 81 int length = ::WideCharToMultiByte(CP_ACP, 0, 82 wmsg.c_str(), static_cast<int>(wlength), 83 &msg[0], static_cast<int>(wlength * 2), 0, 0); 84 if (length <= 0) 85 return "asio.system error"; 86 msg.resize(static_cast<std::size_t>(length)); 87 return msg; 88 } 89 else 90 return "asio.system error"; 91 } 92#else // defined(ASIO_WINDOWS) 93#if !defined(__sun) 94 if (value == ECANCELED) 95 return "Operation aborted."; 96#endif // !defined(__sun) 97#if defined(__sun) || defined(__QNX__) || defined(__SYMBIAN32__) 98 using namespace std; 99 return strerror(value); 100#elif defined(__MACH__) && defined(__APPLE__) \ 101 || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) \ 102 || defined(_AIX) || defined(__hpux) || defined(__osf__) \ 103 || defined(__ANDROID__) 104 char buf[256] = ""; 105 using namespace std; 106 strerror_r(value, buf, sizeof(buf)); 107 return buf; 108#else 109 char buf[256] = ""; 110 return strerror_r(value, buf, sizeof(buf)); 111#endif 112#endif // defined(ASIO_WINDOWS) 113 } 114}; 115 116} // namespace detail 117 118const error_category& system_category() 119{ 120 static detail::system_category instance; 121 return instance; 122} 123 124} // namespace clmdep_asio 125 126#include "asio/detail/pop_options.hpp" 127 128#endif // ASIO_IMPL_ERROR_CODE_IPP 129