diff options
Diffstat (limited to '3rdparty/asio/include/asio/detail/impl/win_iocp_handle_service.ipp')
-rw-r--r-- | 3rdparty/asio/include/asio/detail/impl/win_iocp_handle_service.ipp | 106 |
1 files changed, 100 insertions, 6 deletions
diff --git a/3rdparty/asio/include/asio/detail/impl/win_iocp_handle_service.ipp b/3rdparty/asio/include/asio/detail/impl/win_iocp_handle_service.ipp index 7e6fcb9015c..6136e27fb32 100644 --- a/3rdparty/asio/include/asio/detail/impl/win_iocp_handle_service.ipp +++ b/3rdparty/asio/include/asio/detail/impl/win_iocp_handle_service.ipp @@ -2,7 +2,7 @@ // detail/impl/win_iocp_handle_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -65,10 +65,10 @@ public: } }; -win_iocp_handle_service::win_iocp_handle_service( - asio::io_context& io_context) - : service_base<win_iocp_handle_service>(io_context), - iocp_service_(asio::use_service<win_iocp_io_context>(io_context)), +win_iocp_handle_service::win_iocp_handle_service(execution_context& context) + : execution_context_service_base<win_iocp_handle_service>(context), + iocp_service_(asio::use_service<win_iocp_io_context>(context)), + nt_set_info_(0), mutex_(), impl_list_(0) { @@ -183,11 +183,15 @@ asio::error_code win_iocp_handle_service::assign( if (is_open(impl)) { ec = asio::error::already_open; + ASIO_ERROR_LOCATION(ec); return ec; } if (iocp_service_.register_handle(handle, ec)) + { + ASIO_ERROR_LOCATION(ec); return ec; + } impl.handle_ = handle; ec = asio::error_code(); @@ -222,9 +226,47 @@ asio::error_code win_iocp_handle_service::close( ec = asio::error_code(); } + ASIO_ERROR_LOCATION(ec); return ec; } +win_iocp_handle_service::native_handle_type win_iocp_handle_service::release( + win_iocp_handle_service::implementation_type& impl, + asio::error_code& ec) +{ + if (!is_open(impl)) + return INVALID_HANDLE_VALUE; + + cancel(impl, ec); + if (ec) + { + ASIO_ERROR_LOCATION(ec); + return INVALID_HANDLE_VALUE; + } + + nt_set_info_fn fn = get_nt_set_info(); + if (fn == 0) + { + ec = asio::error::operation_not_supported; + ASIO_ERROR_LOCATION(ec); + return INVALID_HANDLE_VALUE; + } + + ULONG_PTR iosb[2] = { 0, 0 }; + void* info[2] = { 0, 0 }; + if (fn(impl.handle_, iosb, &info, sizeof(info), + 61 /* FileReplaceCompletionInformation */)) + { + ec = asio::error::operation_not_supported; + ASIO_ERROR_LOCATION(ec); + return INVALID_HANDLE_VALUE; + } + + native_handle_type tmp = impl.handle_; + impl.handle_ = INVALID_HANDLE_VALUE; + return tmp; +} + asio::error_code win_iocp_handle_service::cancel( win_iocp_handle_service::implementation_type& impl, asio::error_code& ec) @@ -232,6 +274,7 @@ asio::error_code win_iocp_handle_service::cancel( if (!is_open(impl)) { ec = asio::error::bad_descriptor; + ASIO_ERROR_LOCATION(ec); return ec; } @@ -243,7 +286,8 @@ asio::error_code win_iocp_handle_service::cancel( { // The version of Windows supports cancellation from any thread. typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED); - cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr; + cancel_io_ex_t cancel_io_ex = reinterpret_cast<cancel_io_ex_t>( + reinterpret_cast<void*>(cancel_io_ex_ptr)); if (!cancel_io_ex(impl.handle_, 0)) { DWORD last_error = ::GetLastError(); @@ -292,6 +336,7 @@ asio::error_code win_iocp_handle_service::cancel( ec = asio::error::operation_not_supported; } + ASIO_ERROR_LOCATION(ec); return ec; } @@ -302,6 +347,7 @@ size_t win_iocp_handle_service::do_write( if (!is_open(impl)) { ec = asio::error::bad_descriptor; + ASIO_ERROR_LOCATION(ec); return 0; } @@ -315,6 +361,7 @@ size_t win_iocp_handle_service::do_write( overlapped_wrapper overlapped(ec); if (ec) { + ASIO_ERROR_LOCATION(ec); return 0; } @@ -330,6 +377,7 @@ size_t win_iocp_handle_service::do_write( { ec = asio::error_code(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); return 0; } } @@ -343,6 +391,7 @@ size_t win_iocp_handle_service::do_write( DWORD last_error = ::GetLastError(); ec = asio::error_code(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); return 0; } @@ -394,6 +443,7 @@ size_t win_iocp_handle_service::do_read( if (!is_open(impl)) { ec = asio::error::bad_descriptor; + ASIO_ERROR_LOCATION(ec); return 0; } @@ -407,6 +457,7 @@ size_t win_iocp_handle_service::do_read( overlapped_wrapper overlapped(ec); if (ec) { + ASIO_ERROR_LOCATION(ec); return 0; } @@ -429,6 +480,7 @@ size_t win_iocp_handle_service::do_read( ec = asio::error_code(last_error, asio::error::get_system_category()); } + ASIO_ERROR_LOCATION(ec); return 0; } } @@ -449,6 +501,7 @@ size_t win_iocp_handle_service::do_read( ec = asio::error_code(last_error, asio::error::get_system_category()); } + ASIO_ERROR_LOCATION(ec); return (last_error == ERROR_MORE_DATA) ? bytes_transferred : 0; } @@ -515,6 +568,47 @@ void win_iocp_handle_service::close_for_destruction(implementation_type& impl) } } +win_iocp_handle_service::nt_set_info_fn +win_iocp_handle_service::get_nt_set_info() +{ + void* ptr = interlocked_compare_exchange_pointer(&nt_set_info_, 0, 0); + if (!ptr) + { + if (HMODULE h = ::GetModuleHandleA("NTDLL.DLL")) + ptr = reinterpret_cast<void*>(GetProcAddress(h, "NtSetInformationFile")); + + // On failure, set nt_set_info_ to a special value to indicate that the + // NtSetInformationFile function is unavailable. That way we won't bother + // trying to look it up again. + interlocked_exchange_pointer(&nt_set_info_, ptr ? ptr : this); + } + + return reinterpret_cast<nt_set_info_fn>(ptr == this ? 0 : ptr); +} + +void* win_iocp_handle_service::interlocked_compare_exchange_pointer( + void** dest, void* exch, void* cmp) +{ +#if defined(_M_IX86) + return reinterpret_cast<void*>(InterlockedCompareExchange( + reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(exch), + reinterpret_cast<LONG>(cmp))); +#else + return InterlockedCompareExchangePointer(dest, exch, cmp); +#endif +} + +void* win_iocp_handle_service::interlocked_exchange_pointer( + void** dest, void* val) +{ +#if defined(_M_IX86) + return reinterpret_cast<void*>(InterlockedExchange( + reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(val))); +#else + return InterlockedExchangePointer(dest, val); +#endif +} + } // namespace detail } // namespace asio |