system_category_win32.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. // Windows implementation of system_error_category
  2. //
  3. // Copyright Beman Dawes 2002, 2006
  4. // Copyright (c) Microsoft Corporation 2014
  5. // Copyright 2018 Peter Dimov
  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. // See library home page at http://www.boost.org/libs/system
  11. #include <boost/winapi/error_codes.hpp>
  12. #include <boost/winapi/error_handling.hpp>
  13. #include <boost/winapi/character_code_conversion.hpp>
  14. #include <boost/winapi/local_memory.hpp>
  15. #include <cstdio>
  16. //
  17. namespace boost
  18. {
  19. namespace system
  20. {
  21. namespace detail
  22. {
  23. #if ( defined(_MSC_VER) && _MSC_VER < 1900 ) || ( defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) )
  24. inline char const * unknown_message_win32( int ev, char * buffer, std::size_t len )
  25. {
  26. # if defined( BOOST_MSVC )
  27. # pragma warning( push )
  28. # pragma warning( disable: 4996 )
  29. # endif
  30. _snprintf( buffer, len - 1, "Unknown error (%d)", ev );
  31. buffer[ len - 1 ] = 0;
  32. return buffer;
  33. # if defined( BOOST_MSVC )
  34. # pragma warning( pop )
  35. # endif
  36. }
  37. #else
  38. inline char const * unknown_message_win32( int ev, char * buffer, std::size_t len )
  39. {
  40. std::snprintf( buffer, len, "Unknown error (%d)", ev );
  41. return buffer;
  42. }
  43. #endif
  44. inline boost::winapi::UINT_ message_cp_win32()
  45. {
  46. #if defined(BOOST_SYSTEM_USE_UTF8)
  47. return boost::winapi::CP_UTF8_;
  48. #else
  49. return boost::winapi::CP_ACP_;
  50. #endif
  51. }
  52. inline char const * system_category_message_win32( int ev, char * buffer, std::size_t len ) BOOST_NOEXCEPT
  53. {
  54. if( len == 0 )
  55. {
  56. return buffer;
  57. }
  58. if( len == 1 )
  59. {
  60. buffer[0] = 0;
  61. return buffer;
  62. }
  63. boost::winapi::UINT_ const code_page = message_cp_win32();
  64. int r = 0;
  65. #if !defined(BOOST_NO_ANSI_APIS)
  66. if( code_page == boost::winapi::CP_ACP_ )
  67. {
  68. using namespace boost::winapi;
  69. DWORD_ retval = boost::winapi::FormatMessageA(
  70. FORMAT_MESSAGE_FROM_SYSTEM_ | FORMAT_MESSAGE_IGNORE_INSERTS_,
  71. NULL,
  72. ev,
  73. MAKELANGID_( LANG_NEUTRAL_, SUBLANG_DEFAULT_ ), // Default language
  74. buffer,
  75. static_cast<DWORD_>( len ),
  76. NULL
  77. );
  78. r = static_cast<int>( retval );
  79. }
  80. else
  81. #endif
  82. {
  83. using namespace boost::winapi;
  84. wchar_t * lpMsgBuf = 0;
  85. DWORD_ retval = boost::winapi::FormatMessageW(
  86. FORMAT_MESSAGE_ALLOCATE_BUFFER_ | FORMAT_MESSAGE_FROM_SYSTEM_ | FORMAT_MESSAGE_IGNORE_INSERTS_,
  87. NULL,
  88. ev,
  89. MAKELANGID_( LANG_NEUTRAL_, SUBLANG_DEFAULT_ ), // Default language
  90. (LPWSTR_) &lpMsgBuf,
  91. 0,
  92. NULL
  93. );
  94. if( retval != 0 )
  95. {
  96. r = boost::winapi::WideCharToMultiByte( code_page, 0, lpMsgBuf, -1, buffer, static_cast<int>( len ), NULL, NULL );
  97. boost::winapi::LocalFree( lpMsgBuf );
  98. if ( r != 0 ) --r; // exclude null terminator
  99. }
  100. }
  101. if( r == 0 )
  102. {
  103. return unknown_message_win32( ev, buffer, len );
  104. }
  105. while( r > 0 && ( buffer[ r-1 ] == '\n' || buffer[ r-1 ] == '\r' ) )
  106. {
  107. buffer[ --r ] = 0;
  108. }
  109. if( r > 0 && buffer[ r-1 ] == '.' )
  110. {
  111. buffer[ --r ] = 0;
  112. }
  113. return buffer;
  114. }
  115. struct local_free
  116. {
  117. void * p_;
  118. ~local_free()
  119. {
  120. boost::winapi::LocalFree( p_ );
  121. }
  122. };
  123. inline std::string unknown_message_win32( int ev )
  124. {
  125. char buffer[ 38 ];
  126. return unknown_message_win32( ev, buffer, sizeof( buffer ) );
  127. }
  128. inline std::string system_category_message_win32( int ev )
  129. {
  130. using namespace boost::winapi;
  131. wchar_t * lpMsgBuf = 0;
  132. DWORD_ retval = boost::winapi::FormatMessageW(
  133. FORMAT_MESSAGE_ALLOCATE_BUFFER_ | FORMAT_MESSAGE_FROM_SYSTEM_ | FORMAT_MESSAGE_IGNORE_INSERTS_,
  134. NULL,
  135. ev,
  136. MAKELANGID_( LANG_NEUTRAL_, SUBLANG_DEFAULT_ ), // Default language
  137. (LPWSTR_) &lpMsgBuf,
  138. 0,
  139. NULL
  140. );
  141. if( retval == 0 )
  142. {
  143. return unknown_message_win32( ev );
  144. }
  145. local_free lf_ = { lpMsgBuf };
  146. (void)lf_;
  147. UINT_ const code_page = message_cp_win32();
  148. int r = boost::winapi::WideCharToMultiByte( code_page, 0, lpMsgBuf, -1, 0, 0, NULL, NULL );
  149. if( r == 0 )
  150. {
  151. return unknown_message_win32( ev );
  152. }
  153. std::string buffer( r, char() );
  154. r = boost::winapi::WideCharToMultiByte( code_page, 0, lpMsgBuf, -1, &buffer[0], r, NULL, NULL );
  155. if( r == 0 )
  156. {
  157. return unknown_message_win32( ev );
  158. }
  159. --r; // exclude null terminator
  160. while( r > 0 && ( buffer[ r-1 ] == '\n' || buffer[ r-1 ] == '\r' ) )
  161. {
  162. --r;
  163. }
  164. if( r > 0 && buffer[ r-1 ] == '.' )
  165. {
  166. --r;
  167. }
  168. buffer.resize( r );
  169. return buffer;
  170. }
  171. inline error_condition system_category_default_error_condition_win32( int ev ) BOOST_NOEXCEPT
  172. {
  173. // When using the Windows Runtime, most system errors are reported as HRESULTs.
  174. // We want to map the common Win32 errors to their equivalent error condition,
  175. // whether or not they are reported via an HRESULT.
  176. #define BOOST_SYSTEM_FAILED(hr) ((hr) < 0)
  177. #define BOOST_SYSTEM_HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff)
  178. #define BOOST_SYSTEM_HRESULT_CODE(hr) ((hr) & 0xFFFF)
  179. #define BOOST_SYSTEM_FACILITY_WIN32 7
  180. if( BOOST_SYSTEM_FAILED( ev ) && BOOST_SYSTEM_HRESULT_FACILITY( ev ) == BOOST_SYSTEM_FACILITY_WIN32 )
  181. {
  182. ev = BOOST_SYSTEM_HRESULT_CODE( ev );
  183. }
  184. #undef BOOST_SYSTEM_FAILED
  185. #undef BOOST_SYSTEM_HRESULT_FACILITY
  186. #undef BOOST_SYSTEM_HRESULT_CODE
  187. #undef BOOST_SYSTEM_FACILITY_WIN32
  188. using namespace boost::winapi;
  189. using namespace errc;
  190. // Windows system -> posix_errno decode table
  191. // see WinError.h comments for descriptions of errors
  192. switch ( ev )
  193. {
  194. case 0: return make_error_condition( success );
  195. case ERROR_ACCESS_DENIED_: return make_error_condition( permission_denied );
  196. case ERROR_ALREADY_EXISTS_: return make_error_condition( file_exists );
  197. case ERROR_BAD_UNIT_: return make_error_condition( no_such_device );
  198. case ERROR_BUFFER_OVERFLOW_: return make_error_condition( filename_too_long );
  199. case ERROR_BUSY_: return make_error_condition( device_or_resource_busy );
  200. case ERROR_BUSY_DRIVE_: return make_error_condition( device_or_resource_busy );
  201. case ERROR_CANNOT_MAKE_: return make_error_condition( permission_denied );
  202. case ERROR_CANTOPEN_: return make_error_condition( io_error );
  203. case ERROR_CANTREAD_: return make_error_condition( io_error );
  204. case ERROR_CANTWRITE_: return make_error_condition( io_error );
  205. case ERROR_CONNECTION_ABORTED_: return make_error_condition( connection_aborted );
  206. case ERROR_CURRENT_DIRECTORY_: return make_error_condition( permission_denied );
  207. case ERROR_DEV_NOT_EXIST_: return make_error_condition( no_such_device );
  208. case ERROR_DEVICE_IN_USE_: return make_error_condition( device_or_resource_busy );
  209. case ERROR_DIR_NOT_EMPTY_: return make_error_condition( directory_not_empty );
  210. case ERROR_DIRECTORY_: return make_error_condition( invalid_argument ); // WinError.h: "The directory name is invalid"
  211. case ERROR_DISK_FULL_: return make_error_condition( no_space_on_device );
  212. case ERROR_FILE_EXISTS_: return make_error_condition( file_exists );
  213. case ERROR_FILE_NOT_FOUND_: return make_error_condition( no_such_file_or_directory );
  214. case ERROR_HANDLE_DISK_FULL_: return make_error_condition( no_space_on_device );
  215. case ERROR_INVALID_ACCESS_: return make_error_condition( permission_denied );
  216. case ERROR_INVALID_DRIVE_: return make_error_condition( no_such_device );
  217. case ERROR_INVALID_FUNCTION_: return make_error_condition( function_not_supported );
  218. case ERROR_INVALID_HANDLE_: return make_error_condition( invalid_argument );
  219. case ERROR_INVALID_NAME_: return make_error_condition( invalid_argument );
  220. case ERROR_LOCK_VIOLATION_: return make_error_condition( no_lock_available );
  221. case ERROR_LOCKED_: return make_error_condition( no_lock_available );
  222. case ERROR_NEGATIVE_SEEK_: return make_error_condition( invalid_argument );
  223. case ERROR_NOACCESS_: return make_error_condition( permission_denied );
  224. case ERROR_NOT_ENOUGH_MEMORY_: return make_error_condition( not_enough_memory );
  225. case ERROR_NOT_READY_: return make_error_condition( resource_unavailable_try_again );
  226. case ERROR_NOT_SAME_DEVICE_: return make_error_condition( cross_device_link );
  227. case ERROR_OPEN_FAILED_: return make_error_condition( io_error );
  228. case ERROR_OPEN_FILES_: return make_error_condition( device_or_resource_busy );
  229. case ERROR_OPERATION_ABORTED_: return make_error_condition( operation_canceled );
  230. case ERROR_OUTOFMEMORY_: return make_error_condition( not_enough_memory );
  231. case ERROR_PATH_NOT_FOUND_: return make_error_condition( no_such_file_or_directory );
  232. case ERROR_READ_FAULT_: return make_error_condition( io_error );
  233. case ERROR_RETRY_: return make_error_condition( resource_unavailable_try_again );
  234. case ERROR_SEEK_: return make_error_condition( io_error );
  235. case ERROR_SHARING_VIOLATION_: return make_error_condition( permission_denied );
  236. case ERROR_TOO_MANY_OPEN_FILES_: return make_error_condition( too_many_files_open );
  237. case ERROR_WRITE_FAULT_: return make_error_condition( io_error );
  238. case ERROR_WRITE_PROTECT_: return make_error_condition( permission_denied );
  239. case WSAEACCES_: return make_error_condition( permission_denied );
  240. case WSAEADDRINUSE_: return make_error_condition( address_in_use );
  241. case WSAEADDRNOTAVAIL_: return make_error_condition( address_not_available );
  242. case WSAEAFNOSUPPORT_: return make_error_condition( address_family_not_supported );
  243. case WSAEALREADY_: return make_error_condition( connection_already_in_progress );
  244. case WSAEBADF_: return make_error_condition( bad_file_descriptor );
  245. case WSAECONNABORTED_: return make_error_condition( connection_aborted );
  246. case WSAECONNREFUSED_: return make_error_condition( connection_refused );
  247. case WSAECONNRESET_: return make_error_condition( connection_reset );
  248. case WSAEDESTADDRREQ_: return make_error_condition( destination_address_required );
  249. case WSAEFAULT_: return make_error_condition( bad_address );
  250. case WSAEHOSTUNREACH_: return make_error_condition( host_unreachable );
  251. case WSAEINPROGRESS_: return make_error_condition( operation_in_progress );
  252. case WSAEINTR_: return make_error_condition( interrupted );
  253. case WSAEINVAL_: return make_error_condition( invalid_argument );
  254. case WSAEISCONN_: return make_error_condition( already_connected );
  255. case WSAEMFILE_: return make_error_condition( too_many_files_open );
  256. case WSAEMSGSIZE_: return make_error_condition( message_size );
  257. case WSAENAMETOOLONG_: return make_error_condition( filename_too_long );
  258. case WSAENETDOWN_: return make_error_condition( network_down );
  259. case WSAENETRESET_: return make_error_condition( network_reset );
  260. case WSAENETUNREACH_: return make_error_condition( network_unreachable );
  261. case WSAENOBUFS_: return make_error_condition( no_buffer_space );
  262. case WSAENOPROTOOPT_: return make_error_condition( no_protocol_option );
  263. case WSAENOTCONN_: return make_error_condition( not_connected );
  264. case WSAENOTSOCK_: return make_error_condition( not_a_socket );
  265. case WSAEOPNOTSUPP_: return make_error_condition( operation_not_supported );
  266. case WSAEPROTONOSUPPORT_: return make_error_condition( protocol_not_supported );
  267. case WSAEPROTOTYPE_: return make_error_condition( wrong_protocol_type );
  268. case WSAETIMEDOUT_: return make_error_condition( timed_out );
  269. case WSAEWOULDBLOCK_: return make_error_condition( operation_would_block );
  270. default: return error_condition( ev, system_category() );
  271. }
  272. }
  273. } // namespace detail
  274. } // namespace system
  275. } // namespace boost