summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asio/include/asio/detail/impl/win_iocp_handle_service.ipp
diff options
context:
space:
mode:
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.ipp106
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