File indexing completed on 2025-01-18 09:29:26
0001
0002
0003
0004
0005
0006
0007
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
0031
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 }
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
0128
0129
0130
0131
0132
0133
0134
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;
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;
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;
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;
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;
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;
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;
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 }
0370 }
0371
0372 #endif
0373
0374 #endif