| 152 | |
| 153 | |
| 154 | static void handle_io(OVERLAPPED* overlapped_, DWORD bytes_transferred) |
| 155 | { |
| 156 | // Overlapped objects to passed to this function should have been contained |
| 157 | // inside a `IOOverlappedBase`. So, we can use the `CONTAINING_RECORD` macro |
| 158 | // to get the pointer to the `IOOverlappedBase` struct from the `OVERLAPPED` |
| 159 | // pointer. |
| 160 | IOOverlappedBase* overlapped_base = |
| 161 | CONTAINING_RECORD(overlapped_, IOOverlappedBase, overlapped); |
| 162 | |
| 163 | // Get the Win32 error code of the overlapped operation. The status code |
| 164 | // is actually in overlapped->overlapped->Internal, but it's the NT |
| 165 | // status code instead of the Win32 error. |
| 166 | DWORD error = ERROR_SUCCESS; |
| 167 | DWORD bytes; |
| 168 | const BOOL success = ::GetOverlappedResult( |
| 169 | overlapped_base->handle, &overlapped_base->overlapped, &bytes, FALSE); |
| 170 | |
| 171 | if (!success) { |
| 172 | error = ::GetLastError(); |
| 173 | } else { |
| 174 | // If the IO succeeded, these should be the same for sure. |
| 175 | CHECK_EQ(bytes, bytes_transferred); |
| 176 | } |
| 177 | |
| 178 | switch (overlapped_base->type) { |
| 179 | case IOType::READ: |
| 180 | case IOType::RECV: { |
| 181 | IOOverlappedReadWrite* io_read = |
| 182 | CONTAINING_RECORD(overlapped_base, IOOverlappedReadWrite, base); |
| 183 | |
| 184 | std::unique_ptr<Promise<size_t>> promise(io_read->promise); |
| 185 | |
| 186 | // For reads, we need to make sure we ignore the EOF errors. |
| 187 | if (error == ERROR_BROKEN_PIPE || error == ERROR_HANDLE_EOF) { |
| 188 | set_io_promise(promise.get(), static_cast<size_t>(0), ERROR_SUCCESS); |
| 189 | } else { |
| 190 | set_io_promise( |
| 191 | promise.get(), static_cast<size_t>(bytes_transferred), error); |
| 192 | } |
| 193 | return; |
| 194 | } |
| 195 | case IOType::WRITE: |
| 196 | case IOType::SEND: |
| 197 | case IOType::SENDFILE: { |
| 198 | IOOverlappedReadWrite* io_write = |
| 199 | CONTAINING_RECORD(overlapped_base, IOOverlappedReadWrite, base); |
| 200 | |
| 201 | std::unique_ptr<Promise<size_t>> promise(io_write->promise); |
| 202 | set_io_promise( |
| 203 | promise.get(), static_cast<size_t>(bytes_transferred), error); |
| 204 | return; |
| 205 | } |
| 206 | case IOType::CONNECT: { |
| 207 | IOOverlappedConnect* io_connect = |
| 208 | CONTAINING_RECORD(overlapped_base, IOOverlappedConnect, base); |
| 209 | |
| 210 | std::unique_ptr<Promise<Nothing>> promise(io_connect->promise); |
| 211 | set_io_promise(promise.get(), Nothing(), error); |
no test coverage detected