Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:35

0001 //
0002 // detail/impl/win_iocp_file_service.ipp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_FILE_SERVICE_IPP
0012 #define BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_FILE_SERVICE_IPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 
0020 #if defined(BOOST_ASIO_HAS_FILE) \
0021   && defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
0022 
0023 #include <cstring>
0024 #include <sys/stat.h>
0025 #include <boost/asio/detail/win_iocp_file_service.hpp>
0026 
0027 #include <boost/asio/detail/push_options.hpp>
0028 
0029 namespace boost {
0030 namespace asio {
0031 namespace detail {
0032 
0033 win_iocp_file_service::win_iocp_file_service(
0034     execution_context& context)
0035   : execution_context_service_base<win_iocp_file_service>(context),
0036     handle_service_(context),
0037     nt_flush_buffers_file_ex_(0)
0038 {
0039   if (FARPROC nt_flush_buffers_file_ex_ptr = ::GetProcAddress(
0040         ::GetModuleHandleA("NTDLL"), "NtFlushBuffersFileEx"))
0041   {
0042     nt_flush_buffers_file_ex_ = reinterpret_cast<nt_flush_buffers_file_ex_fn>(
0043         reinterpret_cast<void*>(nt_flush_buffers_file_ex_ptr));
0044   }
0045 }
0046 
0047 void win_iocp_file_service::shutdown()
0048 {
0049   handle_service_.shutdown();
0050 }
0051 
0052 boost::system::error_code win_iocp_file_service::open(
0053     win_iocp_file_service::implementation_type& impl,
0054     const char* path, file_base::flags open_flags,
0055     boost::system::error_code& ec)
0056 {
0057   if (is_open(impl))
0058   {
0059     ec = boost::asio::error::already_open;
0060     BOOST_ASIO_ERROR_LOCATION(ec);
0061     return ec;
0062   }
0063 
0064   DWORD access = 0;
0065   if ((open_flags & file_base::read_only) != 0)
0066     access = GENERIC_READ;
0067   else if ((open_flags & file_base::write_only) != 0)
0068     access = GENERIC_WRITE;
0069   else if ((open_flags & file_base::read_write) != 0)
0070     access = GENERIC_READ | GENERIC_WRITE;
0071 
0072   DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE;
0073 
0074   DWORD disposition = 0;
0075   if ((open_flags & file_base::create) != 0)
0076   {
0077     if ((open_flags & file_base::exclusive) != 0)
0078       disposition = CREATE_NEW;
0079     else
0080       disposition = OPEN_ALWAYS;
0081   }
0082   else
0083   {
0084     if ((open_flags & file_base::truncate) != 0)
0085       disposition = TRUNCATE_EXISTING;
0086     else
0087       disposition = OPEN_EXISTING;
0088   }
0089 
0090   DWORD flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
0091   if (impl.is_stream_)
0092     flags |= FILE_FLAG_SEQUENTIAL_SCAN;
0093   else
0094     flags |= FILE_FLAG_RANDOM_ACCESS;
0095   if ((open_flags & file_base::sync_all_on_write) != 0)
0096     flags |= FILE_FLAG_WRITE_THROUGH;
0097 
0098   HANDLE handle = ::CreateFileA(path, access, share, 0, disposition, flags, 0);
0099   if (handle != INVALID_HANDLE_VALUE)
0100   {
0101     if (disposition == OPEN_ALWAYS && (open_flags & file_base::truncate) != 0)
0102     {
0103       if (!::SetEndOfFile(handle))
0104       {
0105         DWORD last_error = ::GetLastError();
0106         ::CloseHandle(handle);
0107         ec.assign(last_error, boost::asio::error::get_system_category());
0108         BOOST_ASIO_ERROR_LOCATION(ec);
0109         return ec;
0110       }
0111     }
0112 
0113     handle_service_.assign(impl, handle, ec);
0114     if (ec)
0115       ::CloseHandle(handle);
0116     impl.offset_ = 0;
0117     BOOST_ASIO_ERROR_LOCATION(ec);
0118     return ec;
0119   }
0120   else
0121   {
0122     DWORD last_error = ::GetLastError();
0123     ec.assign(last_error, boost::asio::error::get_system_category());
0124     BOOST_ASIO_ERROR_LOCATION(ec);
0125     return ec;
0126   }
0127 }
0128 
0129 uint64_t win_iocp_file_service::size(
0130     const win_iocp_file_service::implementation_type& impl,
0131     boost::system::error_code& ec) const
0132 {
0133   LARGE_INTEGER result;
0134   if (::GetFileSizeEx(native_handle(impl), &result))
0135   {
0136     boost::asio::error::clear(ec);
0137     return static_cast<uint64_t>(result.QuadPart);
0138   }
0139   else
0140   {
0141     DWORD last_error = ::GetLastError();
0142     ec.assign(last_error, boost::asio::error::get_system_category());
0143     BOOST_ASIO_ERROR_LOCATION(ec);
0144     return 0;
0145   }
0146 }
0147 
0148 boost::system::error_code win_iocp_file_service::resize(
0149     win_iocp_file_service::implementation_type& impl,
0150     uint64_t n, boost::system::error_code& ec)
0151 {
0152   LARGE_INTEGER distance;
0153   distance.QuadPart = n;
0154   if (::SetFilePointerEx(native_handle(impl), distance, 0, FILE_BEGIN))
0155   {
0156     BOOL result = ::SetEndOfFile(native_handle(impl));
0157     DWORD last_error = ::GetLastError();
0158 
0159     distance.QuadPart = static_cast<LONGLONG>(impl.offset_);
0160     if (!::SetFilePointerEx(native_handle(impl), distance, 0, FILE_BEGIN))
0161     {
0162       result = FALSE;
0163       last_error = ::GetLastError();
0164     }
0165 
0166     if (result)
0167       boost::asio::error::clear(ec);
0168     else
0169       ec.assign(last_error, boost::asio::error::get_system_category());
0170     BOOST_ASIO_ERROR_LOCATION(ec);
0171     return ec;
0172   }
0173   else
0174   {
0175     DWORD last_error = ::GetLastError();
0176     ec.assign(last_error, boost::asio::error::get_system_category());
0177     BOOST_ASIO_ERROR_LOCATION(ec);
0178     return ec;
0179   }
0180 }
0181 
0182 boost::system::error_code win_iocp_file_service::sync_all(
0183     win_iocp_file_service::implementation_type& impl,
0184     boost::system::error_code& ec)
0185 {
0186   BOOL result = ::FlushFileBuffers(native_handle(impl));
0187   if (result)
0188   {
0189     boost::asio::error::clear(ec);
0190     return ec;
0191   }
0192   else
0193   {
0194     DWORD last_error = ::GetLastError();
0195     ec.assign(last_error, boost::asio::error::get_system_category());
0196     BOOST_ASIO_ERROR_LOCATION(ec);
0197     return ec;
0198   }
0199 }
0200 
0201 boost::system::error_code win_iocp_file_service::sync_data(
0202     win_iocp_file_service::implementation_type& impl,
0203     boost::system::error_code& ec)
0204 {
0205   if (nt_flush_buffers_file_ex_)
0206   {
0207     io_status_block status = {};
0208     if (!nt_flush_buffers_file_ex_(native_handle(impl),
0209           flush_flags_file_data_sync_only, 0, 0, &status))
0210     {
0211       boost::asio::error::clear(ec);
0212       return ec;
0213     }
0214   }
0215   return sync_all(impl, ec);
0216 }
0217 
0218 uint64_t win_iocp_file_service::seek(
0219     win_iocp_file_service::implementation_type& impl, int64_t offset,
0220     file_base::seek_basis whence, boost::system::error_code& ec)
0221 {
0222   DWORD method;
0223   switch (whence)
0224   {
0225   case file_base::seek_set:
0226     method = FILE_BEGIN;
0227     break;
0228   case file_base::seek_cur:
0229     method = FILE_BEGIN;
0230     offset = static_cast<int64_t>(impl.offset_) + offset;
0231     break;
0232   case file_base::seek_end:
0233     method = FILE_END;
0234     break;
0235   default:
0236     ec = boost::asio::error::invalid_argument;
0237     BOOST_ASIO_ERROR_LOCATION(ec);
0238     return 0;
0239   }
0240 
0241   LARGE_INTEGER distance, new_offset;
0242   distance.QuadPart = offset;
0243   if (::SetFilePointerEx(native_handle(impl), distance, &new_offset, method))
0244   {
0245     impl.offset_ = new_offset.QuadPart;
0246     boost::asio::error::clear(ec);
0247     return impl.offset_;
0248   }
0249   else
0250   {
0251     DWORD last_error = ::GetLastError();
0252     ec.assign(last_error, boost::asio::error::get_system_category());
0253     BOOST_ASIO_ERROR_LOCATION(ec);
0254     return 0;
0255   }
0256 }
0257 
0258 } // namespace detail
0259 } // namespace asio
0260 } // namespace boost
0261 
0262 #include <boost/asio/detail/pop_options.hpp>
0263 
0264 #endif // defined(BOOST_ASIO_HAS_FILE)
0265        //   && defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
0266 
0267 #endif // BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_FILE_SERVICE_IPP