6 #include <winapi/buffer.hpp>
8 #include <winapi/handle.hpp>
9 #include <winapi/utils.hpp>
23 std::runtime_error write_file_incomplete(std::size_t expected, std::size_t actual) {
24 std::ostringstream oss;
25 oss <<
"WriteFile could only write " << actual <<
" bytes instead of " << expected;
26 return std::runtime_error{oss.str()};
29 bool is_std_handle(HANDLE handle) {
30 return handle == ::GetStdHandle(STD_INPUT_HANDLE) ||
31 handle == ::GetStdHandle(STD_OUTPUT_HANDLE) ||
32 handle == ::GetStdHandle(STD_ERROR_HANDLE);
37 Handle::Handle(HANDLE impl) : m_impl{impl} {}
39 bool Handle::is_valid()
const {
40 return m_impl && is_valid(m_impl.get());
43 bool Handle::is_valid(HANDLE handle) {
44 return handle != NULL && handle != INVALID_HANDLE_VALUE;
47 void Handle::close() {
51 bool Handle::is_std()
const {
52 return is_std_handle(m_impl.get());
56 return Handle{::GetStdHandle(STD_INPUT_HANDLE)};
60 return Handle{::GetStdHandle(STD_OUTPUT_HANDLE)};
64 return Handle{::GetStdHandle(STD_ERROR_HANDLE)};
67 bool Handle::read_chunk(
Buffer& buffer)
const {
68 buffer.resize(max_chunk_size);
71 if (buffer.size() > std::numeric_limits<DWORD>::max())
72 throw std::range_error{
"Read buffer is too large"};
74 ::ReadFile(m_impl.get(), buffer.data(),
static_cast<DWORD
>(buffer.size()), &nb_read, NULL);
76 buffer.resize(nb_read);
82 const auto ec = GetLastError();
85 case ERROR_BROKEN_PIPE:
89 throw error::windows(ec,
"ReadFile");
98 const auto next = read_chunk(chunk);
109 void Handle::write(
const void* data, std::size_t nb)
const {
110 DWORD nb_written = 0;
112 if (nb > std::numeric_limits<DWORD>::max())
113 throw std::range_error{
"Write buffer is too large"};
114 const auto ret = ::WriteFile(m_impl.get(), data,
static_cast<DWORD
>(nb), &nb_written, NULL);
117 throw error::windows(GetLastError(),
"WriteFile");
120 if (nb != nb_written) {
121 throw write_file_incomplete(nb, nb_written);
125 void Handle::write(
const Buffer& buffer)
const {
126 write(buffer.data(), buffer.size());
129 void Handle::inherit(
bool yes)
const {
130 if (!::SetHandleInformation(m_impl.get(), HANDLE_FLAG_INHERIT, yes ? 1 : 0)) {
131 throw error::windows(GetLastError(),
"SetHandleInformation");
135 void Handle::Close::operator()(HANDLE impl)
const {
136 if (!is_valid(impl) || is_std_handle(impl))
138 const auto ret = ::CloseHandle(impl);
140 WINAPI_UNUSED_PARAMETER(ret);
void add(const Buffer &src)
Make std::system_error work with GetLastError().