Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:26

0001 //
0002 // Copyright (c) 2015-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/beast
0008 //
0009 
0010 #ifndef BOOST_BEAST_CORE_IMPL_FILE_WIN32_IPP
0011 #define BOOST_BEAST_CORE_IMPL_FILE_WIN32_IPP
0012 
0013 #include <boost/beast/core/file_win32.hpp>
0014 
0015 #if BOOST_BEAST_USE_WIN32_FILE
0016 
0017 #include <boost/beast/core/detail/win32_unicode_path.hpp>
0018 #include <boost/core/exchange.hpp>
0019 #include <boost/winapi/access_rights.hpp>
0020 #include <boost/winapi/error_codes.hpp>
0021 #include <boost/winapi/get_last_error.hpp>
0022 #include <limits>
0023 #include <utility>
0024 
0025 namespace boost {
0026 namespace beast {
0027 
0028 namespace detail {
0029 
0030 // VFALCO Can't seem to get boost/detail/winapi to work with
0031 //        this so use the non-Ex version for now.
0032 BOOST_BEAST_DECL
0033 boost::winapi::BOOL_
0034 set_file_pointer_ex(
0035     boost::winapi::HANDLE_ hFile,
0036     boost::winapi::LARGE_INTEGER_ lpDistanceToMove,
0037     boost::winapi::PLARGE_INTEGER_ lpNewFilePointer,
0038     boost::winapi::DWORD_ dwMoveMethod)
0039 {
0040     auto dwHighPart = lpDistanceToMove.u.HighPart;
0041     auto dwLowPart = boost::winapi::SetFilePointer(
0042         hFile,
0043         lpDistanceToMove.u.LowPart,
0044         &dwHighPart,
0045         dwMoveMethod);
0046     if(dwLowPart == boost::winapi::INVALID_SET_FILE_POINTER_)
0047         return 0;
0048     if(lpNewFilePointer)
0049     {
0050         lpNewFilePointer->u.LowPart = dwLowPart;
0051         lpNewFilePointer->u.HighPart = dwHighPart;
0052     }
0053     return 1;
0054 }
0055 
0056 } // detail
0057 
0058 file_win32::
0059 ~file_win32()
0060 {
0061     if(h_ != boost::winapi::INVALID_HANDLE_VALUE_)
0062         boost::winapi::CloseHandle(h_);
0063 }
0064 
0065 file_win32::
0066 file_win32(file_win32&& other)
0067     : h_(boost::exchange(other.h_,
0068         boost::winapi::INVALID_HANDLE_VALUE_))
0069 {
0070 }
0071 
0072 file_win32&
0073 file_win32::
0074 operator=(file_win32&& other)
0075 {
0076     if(&other == this)
0077         return *this;
0078     if(h_)
0079         boost::winapi::CloseHandle(h_);
0080     h_ = other.h_;
0081     other.h_ = boost::winapi::INVALID_HANDLE_VALUE_;
0082     return *this;
0083 }
0084 
0085 void
0086 file_win32::
0087 native_handle(native_handle_type h)
0088 {
0089      if(h_ != boost::winapi::INVALID_HANDLE_VALUE_)
0090         boost::winapi::CloseHandle(h_);
0091     h_ = h;
0092 }
0093 
0094 void
0095 file_win32::
0096 close(error_code& ec)
0097 {
0098     if(h_ != boost::winapi::INVALID_HANDLE_VALUE_)
0099     {
0100         if(! boost::winapi::CloseHandle(h_))
0101             ec.assign(boost::winapi::GetLastError(),
0102                 system_category());
0103         else
0104             ec = {};
0105         h_ = boost::winapi::INVALID_HANDLE_VALUE_;
0106     }
0107     else
0108     {
0109         ec = {};
0110     }
0111 }
0112 
0113 void
0114 file_win32::
0115 open(char const* path, file_mode mode, error_code& ec)
0116 {
0117     if(h_ != boost::winapi::INVALID_HANDLE_VALUE_)
0118     {
0119         boost::winapi::CloseHandle(h_);
0120         h_ = boost::winapi::INVALID_HANDLE_VALUE_;
0121     }
0122     boost::winapi::DWORD_ share_mode = 0;
0123     boost::winapi::DWORD_ desired_access = 0;
0124     boost::winapi::DWORD_ creation_disposition = 0;
0125     boost::winapi::DWORD_ flags_and_attributes = 0;
0126 /*
0127                              |                    When the file...
0128     This argument:           |             Exists            Does not exist
0129     -------------------------+------------------------------------------------------
0130     CREATE_ALWAYS            |            Truncates             Creates
0131     CREATE_NEW         +-----------+        Fails               Creates
0132     OPEN_ALWAYS     ===| does this |===>    Opens               Creates
0133     OPEN_EXISTING      +-----------+        Opens                Fails
0134     TRUNCATE_EXISTING        |            Truncates              Fails
0135 */
0136     switch(mode)
0137     {
0138     default:
0139     case file_mode::read:
0140         desired_access = boost::winapi::GENERIC_READ_;
0141         share_mode = boost::winapi::FILE_SHARE_READ_;
0142         creation_disposition = boost::winapi::OPEN_EXISTING_;
0143         flags_and_attributes = 0x10000000; // FILE_FLAG_RANDOM_ACCESS
0144         break;
0145 
0146     case file_mode::scan:           
0147         desired_access = boost::winapi::GENERIC_READ_;
0148         share_mode = boost::winapi::FILE_SHARE_READ_;
0149         creation_disposition = boost::winapi::OPEN_EXISTING_;
0150         flags_and_attributes = 0x08000000; // FILE_FLAG_SEQUENTIAL_SCAN
0151         break;
0152 
0153     case file_mode::write:          
0154         desired_access = boost::winapi::GENERIC_READ_ |
0155                          boost::winapi::GENERIC_WRITE_;
0156         creation_disposition = boost::winapi::CREATE_ALWAYS_;
0157         flags_and_attributes = 0x10000000; // FILE_FLAG_RANDOM_ACCESS
0158         break;
0159 
0160     case file_mode::write_new:      
0161         desired_access = boost::winapi::GENERIC_READ_ |
0162                          boost::winapi::GENERIC_WRITE_;
0163         creation_disposition = boost::winapi::CREATE_NEW_;
0164         flags_and_attributes = 0x10000000; // FILE_FLAG_RANDOM_ACCESS
0165         break;
0166 
0167     case file_mode::write_existing: 
0168         desired_access = boost::winapi::GENERIC_READ_ |
0169                          boost::winapi::GENERIC_WRITE_;
0170         creation_disposition = boost::winapi::OPEN_EXISTING_;
0171         flags_and_attributes = 0x10000000; // FILE_FLAG_RANDOM_ACCESS
0172         break;
0173 
0174     case file_mode::append:         
0175         desired_access = boost::winapi::GENERIC_READ_ |
0176                          boost::winapi::GENERIC_WRITE_;
0177 
0178         creation_disposition = boost::winapi::OPEN_ALWAYS_;
0179         flags_and_attributes = 0x08000000; // FILE_FLAG_SEQUENTIAL_SCAN
0180         break;
0181 
0182     case file_mode::append_existing:
0183         desired_access = boost::winapi::GENERIC_READ_ |
0184                          boost::winapi::GENERIC_WRITE_;
0185         creation_disposition = boost::winapi::OPEN_EXISTING_;
0186         flags_and_attributes = 0x08000000; // FILE_FLAG_SEQUENTIAL_SCAN
0187         break;
0188     }
0189     
0190     detail::win32_unicode_path unicode_path(path, ec);
0191     if (ec)
0192         return;
0193     h_ = ::CreateFileW(
0194         unicode_path.c_str(),
0195         desired_access,
0196         share_mode,
0197         NULL,
0198         creation_disposition,
0199         flags_and_attributes,
0200         NULL);
0201     if (h_ == boost::winapi::INVALID_HANDLE_VALUE_)
0202     {
0203         ec.assign(boost::winapi::GetLastError(),
0204             system_category());
0205         return;
0206     }
0207     if (mode == file_mode::append ||
0208         mode == file_mode::append_existing)
0209     {
0210         boost::winapi::LARGE_INTEGER_ in;
0211         in.QuadPart = 0;
0212         if (!detail::set_file_pointer_ex(h_, in, 0,
0213             boost::winapi::FILE_END_))
0214         {
0215             ec.assign(boost::winapi::GetLastError(),
0216                 system_category());
0217             boost::winapi::CloseHandle(h_);
0218             h_ = boost::winapi::INVALID_HANDLE_VALUE_;
0219             return;
0220         }
0221     }
0222     ec = {};
0223 }
0224 
0225 std::uint64_t
0226 file_win32::
0227 size(error_code& ec) const
0228 {
0229     if(h_ == boost::winapi::INVALID_HANDLE_VALUE_)
0230     {
0231         ec = make_error_code(errc::bad_file_descriptor);
0232         return 0;
0233     }
0234     boost::winapi::LARGE_INTEGER_ fileSize;
0235     if(! boost::winapi::GetFileSizeEx(h_, &fileSize))
0236     {
0237         ec.assign(boost::winapi::GetLastError(),
0238             system_category());
0239         return 0;
0240     }
0241     ec = {};
0242     return fileSize.QuadPart;
0243 }
0244 
0245 std::uint64_t
0246 file_win32::
0247 pos(error_code& ec)
0248 {
0249     if(h_ == boost::winapi::INVALID_HANDLE_VALUE_)
0250     {
0251         ec = make_error_code(errc::bad_file_descriptor);
0252         return 0;
0253     }
0254     boost::winapi::LARGE_INTEGER_ in;
0255     boost::winapi::LARGE_INTEGER_ out;
0256     in.QuadPart = 0;
0257     if(! detail::set_file_pointer_ex(h_, in, &out,
0258         boost::winapi::FILE_CURRENT_))
0259     {
0260         ec.assign(boost::winapi::GetLastError(),
0261             system_category());
0262         return 0;
0263     }
0264     ec = {};
0265     return out.QuadPart;
0266 }
0267 
0268 void
0269 file_win32::
0270 seek(std::uint64_t offset, error_code& ec)
0271 {
0272     if(h_ == boost::winapi::INVALID_HANDLE_VALUE_)
0273     {
0274         ec = make_error_code(errc::bad_file_descriptor);
0275         return;
0276     }
0277     boost::winapi::LARGE_INTEGER_ in;
0278     in.QuadPart = offset;
0279     if(! detail::set_file_pointer_ex(h_, in, 0,
0280         boost::winapi::FILE_BEGIN_))
0281     {
0282         ec.assign(boost::winapi::GetLastError(),
0283             system_category());
0284         return;
0285     }
0286     ec = {};
0287 }
0288 
0289 std::size_t
0290 file_win32::
0291 read(void* buffer, std::size_t n, error_code& ec)
0292 {
0293     if(h_ == boost::winapi::INVALID_HANDLE_VALUE_)
0294     {
0295         ec = make_error_code(errc::bad_file_descriptor);
0296         return 0;
0297     }
0298     std::size_t nread = 0;
0299     while(n > 0)
0300     {
0301         boost::winapi::DWORD_ amount;
0302         if(n > (std::numeric_limits<
0303                 boost::winapi::DWORD_>::max)())
0304             amount = (std::numeric_limits<
0305                 boost::winapi::DWORD_>::max)();
0306         else
0307             amount = static_cast<
0308                 boost::winapi::DWORD_>(n);
0309         boost::winapi::DWORD_ bytesRead;
0310         if(! ::ReadFile(h_, buffer, amount, &bytesRead, 0))
0311         {
0312             auto const dwError = boost::winapi::GetLastError();
0313             if(dwError != boost::winapi::ERROR_HANDLE_EOF_)
0314                 ec.assign(dwError, system_category());
0315             else
0316                 ec = {};
0317             return nread;
0318         }
0319         if(bytesRead == 0)
0320             return nread;
0321         n -= bytesRead;
0322         nread += bytesRead;
0323         buffer = static_cast<char*>(buffer) + bytesRead;
0324     }
0325     ec = {};
0326     return nread;
0327 }
0328 
0329 std::size_t
0330 file_win32::
0331 write(void const* buffer, std::size_t n, error_code& ec)
0332 {
0333     if(h_ == boost::winapi::INVALID_HANDLE_VALUE_)
0334     {
0335         ec = make_error_code(errc::bad_file_descriptor);
0336         return 0;
0337     }
0338     std::size_t nwritten = 0;
0339     while(n > 0)
0340     {
0341         boost::winapi::DWORD_ amount;
0342         if(n > (std::numeric_limits<
0343                 boost::winapi::DWORD_>::max)())
0344             amount = (std::numeric_limits<
0345                 boost::winapi::DWORD_>::max)();
0346         else
0347             amount = static_cast<
0348                 boost::winapi::DWORD_>(n);
0349         boost::winapi::DWORD_ bytesWritten;
0350         if(! ::WriteFile(h_, buffer, amount, &bytesWritten, 0))
0351         {
0352             auto const dwError = boost::winapi::GetLastError();
0353             if(dwError != boost::winapi::ERROR_HANDLE_EOF_)
0354                 ec.assign(dwError, system_category());
0355             else
0356                 ec = {};
0357             return nwritten;
0358         }
0359         if(bytesWritten == 0)
0360             return nwritten;
0361         n -= bytesWritten;
0362         nwritten += bytesWritten;
0363         buffer = static_cast<char const*>(buffer) + bytesWritten;
0364     }
0365     ec = {};
0366     return nwritten;
0367 }
0368 
0369 } // beast
0370 } // boost
0371 
0372 #endif
0373 
0374 #endif