From def5c50960eea4c112647f88361a3ae7155901a8 Mon Sep 17 00:00:00 2001 From: egor-tensin Date: Tue, 4 Jul 2023 00:48:00 +0000 Subject: =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20egor-tensin/wina?= =?UTF-8?q?pi-common@0c196cbe8b4927c78c02b2c7312fc69a507db845=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- handle_8cpp_source.html | 225 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 handle_8cpp_source.html (limited to 'handle_8cpp_source.html') diff --git a/handle_8cpp_source.html b/handle_8cpp_source.html new file mode 100644 index 0000000..f27d365 --- /dev/null +++ b/handle_8cpp_source.html @@ -0,0 +1,225 @@ + + + + + + + +winapi_common: src/handle.cpp Source File + + + + + + + + + +
+
+ + + + + + +
+
winapi_common +
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
handle.cpp
+
+
+
1 // Copyright (c) 2020 Egor Tensin <Egor.Tensin@gmail.com>
+
2 // This file is part of the "winapi-common" project.
+
3 // For details, see https://github.com/egor-tensin/winapi-common.
+
4 // Distributed under the MIT License.
+
5 
+
6 #include <winapi/buffer.hpp>
+
7 #include <winapi/error.hpp>
+
8 #include <winapi/handle.hpp>
+
9 #include <winapi/utils.hpp>
+
10 
+
11 #include <windows.h>
+
12 
+
13 #include <cassert>
+
14 #include <cstddef>
+
15 #include <limits>
+
16 #include <sstream>
+
17 #include <stdexcept>
+
18 #include <utility>
+
19 
+
20 namespace winapi {
+
21 namespace {
+
22 
+
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()};
+
27 }
+
28 
+
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);
+
33 }
+
34 
+
35 } // namespace
+
36 
+
37 Handle::Handle(HANDLE impl) : m_impl{impl} {}
+
38 
+
39 bool Handle::is_valid() const {
+
40  return m_impl && is_valid(m_impl.get());
+
41 }
+
42 
+
43 bool Handle::is_valid(HANDLE handle) {
+
44  return handle != NULL && handle != INVALID_HANDLE_VALUE;
+
45 }
+
46 
+
47 void Handle::close() {
+
48  m_impl.reset();
+
49 }
+
50 
+
51 bool Handle::is_std() const {
+
52  return is_std_handle(m_impl.get());
+
53 }
+
54 
+
55 Handle Handle::std_in() {
+
56  return Handle{::GetStdHandle(STD_INPUT_HANDLE)};
+
57 }
+
58 
+
59 Handle Handle::std_out() {
+
60  return Handle{::GetStdHandle(STD_OUTPUT_HANDLE)};
+
61 }
+
62 
+
63 Handle Handle::std_err() {
+
64  return Handle{::GetStdHandle(STD_ERROR_HANDLE)};
+
65 }
+
66 
+
67 bool Handle::read_chunk(Buffer& buffer) const {
+
68  buffer.resize(max_chunk_size);
+
69  DWORD nb_read = 0;
+
70 
+
71  if (buffer.size() > std::numeric_limits<DWORD>::max())
+
72  throw std::range_error{"Read buffer is too large"};
+
73  const auto ret =
+
74  ::ReadFile(m_impl.get(), buffer.data(), static_cast<DWORD>(buffer.size()), &nb_read, NULL);
+
75 
+
76  buffer.resize(nb_read);
+
77 
+
78  if (ret) {
+
79  return nb_read != 0;
+
80  }
+
81 
+
82  const auto ec = GetLastError();
+
83 
+
84  switch (ec) {
+
85  case ERROR_BROKEN_PIPE:
+
86  // We've been reading from an anonymous pipe, and it's been closed.
+
87  return false;
+
88  default:
+
89  throw error::windows(ec, "ReadFile");
+
90  }
+
91 }
+
92 
+
93 Buffer Handle::read() const {
+
94  Buffer buffer;
+
95 
+
96  while (true) {
+
97  Buffer chunk;
+
98  const auto next = read_chunk(chunk);
+
99  buffer.add(chunk);
+
100 
+
101  if (!next) {
+
102  break;
+
103  }
+
104  }
+
105 
+
106  return buffer;
+
107 }
+
108 
+
109 void Handle::write(const void* data, std::size_t nb) const {
+
110  DWORD nb_written = 0;
+
111 
+
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);
+
115 
+
116  if (!ret) {
+
117  throw error::windows(GetLastError(), "WriteFile");
+
118  }
+
119 
+
120  if (nb != nb_written) {
+
121  throw write_file_incomplete(nb, nb_written);
+
122  }
+
123 }
+
124 
+
125 void Handle::write(const Buffer& buffer) const {
+
126  write(buffer.data(), buffer.size());
+
127 }
+
128 
+
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");
+
132  }
+
133 }
+
134 
+
135 void Handle::Close::operator()(HANDLE impl) const {
+
136  if (!is_valid(impl) || is_std_handle(impl))
+
137  return;
+
138  const auto ret = ::CloseHandle(impl);
+
139  assert(ret);
+
140  WINAPI_UNUSED_PARAMETER(ret);
+
141 }
+
142 
+
143 } // namespace winapi
+
Binary data container.
Definition: buffer.hpp:24
+
void add(const Buffer &src)
Definition: buffer.hpp:79
+
HANDLE wrapper.
Definition: handle.hpp:25
+
Make std::system_error work with GetLastError().
+
+ + + + -- cgit v1.2.3