123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- // Windows implementation of system_error_category
- //
- // Copyright Beman Dawes 2002, 2006
- // Copyright (c) Microsoft Corporation 2014
- // Copyright 2018 Peter Dimov
- //
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- //
- // See library home page at http://www.boost.org/libs/system
- #include <boost/winapi/error_codes.hpp>
- #include <boost/winapi/error_handling.hpp>
- #include <boost/winapi/character_code_conversion.hpp>
- #include <boost/winapi/local_memory.hpp>
- #include <cstdio>
- //
- namespace boost
- {
- namespace system
- {
- namespace detail
- {
- #if ( defined(_MSC_VER) && _MSC_VER < 1900 ) || ( defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) )
- inline char const * unknown_message_win32( int ev, char * buffer, std::size_t len )
- {
- # if defined( BOOST_MSVC )
- # pragma warning( push )
- # pragma warning( disable: 4996 )
- # endif
- _snprintf( buffer, len - 1, "Unknown error (%d)", ev );
- buffer[ len - 1 ] = 0;
- return buffer;
- # if defined( BOOST_MSVC )
- # pragma warning( pop )
- # endif
- }
- #else
- inline char const * unknown_message_win32( int ev, char * buffer, std::size_t len )
- {
- std::snprintf( buffer, len, "Unknown error (%d)", ev );
- return buffer;
- }
- #endif
- inline boost::winapi::UINT_ message_cp_win32()
- {
- #if defined(BOOST_SYSTEM_USE_UTF8)
- return boost::winapi::CP_UTF8_;
- #else
- return boost::winapi::CP_ACP_;
- #endif
- }
- inline char const * system_category_message_win32( int ev, char * buffer, std::size_t len ) BOOST_NOEXCEPT
- {
- if( len == 0 )
- {
- return buffer;
- }
- if( len == 1 )
- {
- buffer[0] = 0;
- return buffer;
- }
- boost::winapi::UINT_ const code_page = message_cp_win32();
- int r = 0;
- #if !defined(BOOST_NO_ANSI_APIS)
- if( code_page == boost::winapi::CP_ACP_ )
- {
- using namespace boost::winapi;
- DWORD_ retval = boost::winapi::FormatMessageA(
- FORMAT_MESSAGE_FROM_SYSTEM_ | FORMAT_MESSAGE_IGNORE_INSERTS_,
- NULL,
- ev,
- MAKELANGID_( LANG_NEUTRAL_, SUBLANG_DEFAULT_ ), // Default language
- buffer,
- static_cast<DWORD_>( len ),
- NULL
- );
- r = static_cast<int>( retval );
- }
- else
- #endif
- {
- using namespace boost::winapi;
- wchar_t * lpMsgBuf = 0;
- DWORD_ retval = boost::winapi::FormatMessageW(
- FORMAT_MESSAGE_ALLOCATE_BUFFER_ | FORMAT_MESSAGE_FROM_SYSTEM_ | FORMAT_MESSAGE_IGNORE_INSERTS_,
- NULL,
- ev,
- MAKELANGID_( LANG_NEUTRAL_, SUBLANG_DEFAULT_ ), // Default language
- (LPWSTR_) &lpMsgBuf,
- 0,
- NULL
- );
- if( retval != 0 )
- {
- r = boost::winapi::WideCharToMultiByte( code_page, 0, lpMsgBuf, -1, buffer, static_cast<int>( len ), NULL, NULL );
- boost::winapi::LocalFree( lpMsgBuf );
- if ( r != 0 ) --r; // exclude null terminator
- }
- }
- if( r == 0 )
- {
- return unknown_message_win32( ev, buffer, len );
- }
- while( r > 0 && ( buffer[ r-1 ] == '\n' || buffer[ r-1 ] == '\r' ) )
- {
- buffer[ --r ] = 0;
- }
- if( r > 0 && buffer[ r-1 ] == '.' )
- {
- buffer[ --r ] = 0;
- }
- return buffer;
- }
- struct local_free
- {
- void * p_;
- ~local_free()
- {
- boost::winapi::LocalFree( p_ );
- }
- };
- inline std::string unknown_message_win32( int ev )
- {
- char buffer[ 38 ];
- return unknown_message_win32( ev, buffer, sizeof( buffer ) );
- }
- inline std::string system_category_message_win32( int ev )
- {
- using namespace boost::winapi;
- wchar_t * lpMsgBuf = 0;
- DWORD_ retval = boost::winapi::FormatMessageW(
- FORMAT_MESSAGE_ALLOCATE_BUFFER_ | FORMAT_MESSAGE_FROM_SYSTEM_ | FORMAT_MESSAGE_IGNORE_INSERTS_,
- NULL,
- ev,
- MAKELANGID_( LANG_NEUTRAL_, SUBLANG_DEFAULT_ ), // Default language
- (LPWSTR_) &lpMsgBuf,
- 0,
- NULL
- );
- if( retval == 0 )
- {
- return unknown_message_win32( ev );
- }
- local_free lf_ = { lpMsgBuf };
- (void)lf_;
- UINT_ const code_page = message_cp_win32();
- int r = boost::winapi::WideCharToMultiByte( code_page, 0, lpMsgBuf, -1, 0, 0, NULL, NULL );
- if( r == 0 )
- {
- return unknown_message_win32( ev );
- }
- std::string buffer( r, char() );
- r = boost::winapi::WideCharToMultiByte( code_page, 0, lpMsgBuf, -1, &buffer[0], r, NULL, NULL );
- if( r == 0 )
- {
- return unknown_message_win32( ev );
- }
- --r; // exclude null terminator
- while( r > 0 && ( buffer[ r-1 ] == '\n' || buffer[ r-1 ] == '\r' ) )
- {
- --r;
- }
- if( r > 0 && buffer[ r-1 ] == '.' )
- {
- --r;
- }
- buffer.resize( r );
- return buffer;
- }
- inline error_condition system_category_default_error_condition_win32( int ev ) BOOST_NOEXCEPT
- {
- // When using the Windows Runtime, most system errors are reported as HRESULTs.
- // We want to map the common Win32 errors to their equivalent error condition,
- // whether or not they are reported via an HRESULT.
- #define BOOST_SYSTEM_FAILED(hr) ((hr) < 0)
- #define BOOST_SYSTEM_HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff)
- #define BOOST_SYSTEM_HRESULT_CODE(hr) ((hr) & 0xFFFF)
- #define BOOST_SYSTEM_FACILITY_WIN32 7
- if( BOOST_SYSTEM_FAILED( ev ) && BOOST_SYSTEM_HRESULT_FACILITY( ev ) == BOOST_SYSTEM_FACILITY_WIN32 )
- {
- ev = BOOST_SYSTEM_HRESULT_CODE( ev );
- }
- #undef BOOST_SYSTEM_FAILED
- #undef BOOST_SYSTEM_HRESULT_FACILITY
- #undef BOOST_SYSTEM_HRESULT_CODE
- #undef BOOST_SYSTEM_FACILITY_WIN32
- using namespace boost::winapi;
- using namespace errc;
- // Windows system -> posix_errno decode table
- // see WinError.h comments for descriptions of errors
- switch ( ev )
- {
- case 0: return make_error_condition( success );
- case ERROR_ACCESS_DENIED_: return make_error_condition( permission_denied );
- case ERROR_ALREADY_EXISTS_: return make_error_condition( file_exists );
- case ERROR_BAD_UNIT_: return make_error_condition( no_such_device );
- case ERROR_BUFFER_OVERFLOW_: return make_error_condition( filename_too_long );
- case ERROR_BUSY_: return make_error_condition( device_or_resource_busy );
- case ERROR_BUSY_DRIVE_: return make_error_condition( device_or_resource_busy );
- case ERROR_CANNOT_MAKE_: return make_error_condition( permission_denied );
- case ERROR_CANTOPEN_: return make_error_condition( io_error );
- case ERROR_CANTREAD_: return make_error_condition( io_error );
- case ERROR_CANTWRITE_: return make_error_condition( io_error );
- case ERROR_CONNECTION_ABORTED_: return make_error_condition( connection_aborted );
- case ERROR_CURRENT_DIRECTORY_: return make_error_condition( permission_denied );
- case ERROR_DEV_NOT_EXIST_: return make_error_condition( no_such_device );
- case ERROR_DEVICE_IN_USE_: return make_error_condition( device_or_resource_busy );
- case ERROR_DIR_NOT_EMPTY_: return make_error_condition( directory_not_empty );
- case ERROR_DIRECTORY_: return make_error_condition( invalid_argument ); // WinError.h: "The directory name is invalid"
- case ERROR_DISK_FULL_: return make_error_condition( no_space_on_device );
- case ERROR_FILE_EXISTS_: return make_error_condition( file_exists );
- case ERROR_FILE_NOT_FOUND_: return make_error_condition( no_such_file_or_directory );
- case ERROR_HANDLE_DISK_FULL_: return make_error_condition( no_space_on_device );
- case ERROR_INVALID_ACCESS_: return make_error_condition( permission_denied );
- case ERROR_INVALID_DRIVE_: return make_error_condition( no_such_device );
- case ERROR_INVALID_FUNCTION_: return make_error_condition( function_not_supported );
- case ERROR_INVALID_HANDLE_: return make_error_condition( invalid_argument );
- case ERROR_INVALID_NAME_: return make_error_condition( invalid_argument );
- case ERROR_LOCK_VIOLATION_: return make_error_condition( no_lock_available );
- case ERROR_LOCKED_: return make_error_condition( no_lock_available );
- case ERROR_NEGATIVE_SEEK_: return make_error_condition( invalid_argument );
- case ERROR_NOACCESS_: return make_error_condition( permission_denied );
- case ERROR_NOT_ENOUGH_MEMORY_: return make_error_condition( not_enough_memory );
- case ERROR_NOT_READY_: return make_error_condition( resource_unavailable_try_again );
- case ERROR_NOT_SAME_DEVICE_: return make_error_condition( cross_device_link );
- case ERROR_OPEN_FAILED_: return make_error_condition( io_error );
- case ERROR_OPEN_FILES_: return make_error_condition( device_or_resource_busy );
- case ERROR_OPERATION_ABORTED_: return make_error_condition( operation_canceled );
- case ERROR_OUTOFMEMORY_: return make_error_condition( not_enough_memory );
- case ERROR_PATH_NOT_FOUND_: return make_error_condition( no_such_file_or_directory );
- case ERROR_READ_FAULT_: return make_error_condition( io_error );
- case ERROR_RETRY_: return make_error_condition( resource_unavailable_try_again );
- case ERROR_SEEK_: return make_error_condition( io_error );
- case ERROR_SHARING_VIOLATION_: return make_error_condition( permission_denied );
- case ERROR_TOO_MANY_OPEN_FILES_: return make_error_condition( too_many_files_open );
- case ERROR_WRITE_FAULT_: return make_error_condition( io_error );
- case ERROR_WRITE_PROTECT_: return make_error_condition( permission_denied );
- case WSAEACCES_: return make_error_condition( permission_denied );
- case WSAEADDRINUSE_: return make_error_condition( address_in_use );
- case WSAEADDRNOTAVAIL_: return make_error_condition( address_not_available );
- case WSAEAFNOSUPPORT_: return make_error_condition( address_family_not_supported );
- case WSAEALREADY_: return make_error_condition( connection_already_in_progress );
- case WSAEBADF_: return make_error_condition( bad_file_descriptor );
- case WSAECONNABORTED_: return make_error_condition( connection_aborted );
- case WSAECONNREFUSED_: return make_error_condition( connection_refused );
- case WSAECONNRESET_: return make_error_condition( connection_reset );
- case WSAEDESTADDRREQ_: return make_error_condition( destination_address_required );
- case WSAEFAULT_: return make_error_condition( bad_address );
- case WSAEHOSTUNREACH_: return make_error_condition( host_unreachable );
- case WSAEINPROGRESS_: return make_error_condition( operation_in_progress );
- case WSAEINTR_: return make_error_condition( interrupted );
- case WSAEINVAL_: return make_error_condition( invalid_argument );
- case WSAEISCONN_: return make_error_condition( already_connected );
- case WSAEMFILE_: return make_error_condition( too_many_files_open );
- case WSAEMSGSIZE_: return make_error_condition( message_size );
- case WSAENAMETOOLONG_: return make_error_condition( filename_too_long );
- case WSAENETDOWN_: return make_error_condition( network_down );
- case WSAENETRESET_: return make_error_condition( network_reset );
- case WSAENETUNREACH_: return make_error_condition( network_unreachable );
- case WSAENOBUFS_: return make_error_condition( no_buffer_space );
- case WSAENOPROTOOPT_: return make_error_condition( no_protocol_option );
- case WSAENOTCONN_: return make_error_condition( not_connected );
- case WSAENOTSOCK_: return make_error_condition( not_a_socket );
- case WSAEOPNOTSUPP_: return make_error_condition( operation_not_supported );
- case WSAEPROTONOSUPPORT_: return make_error_condition( protocol_not_supported );
- case WSAEPROTOTYPE_: return make_error_condition( wrong_protocol_type );
- case WSAETIMEDOUT_: return make_error_condition( timed_out );
- case WSAEWOULDBLOCK_: return make_error_condition( operation_would_block );
- default: return error_condition( ev, system_category() );
- }
- }
- } // namespace detail
- } // namespace system
- } // namespace boost
|