1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "mojo/edk/test/test_utils.h"
6
7#include <windows.h>
8#include <fcntl.h>
9#include <io.h>
10#include <stddef.h>
11#include <string.h>
12
13namespace mojo {
14namespace edk {
15namespace test {
16
17bool BlockingWrite(const PlatformHandle& handle,
18                   const void* buffer,
19                   size_t bytes_to_write,
20                   size_t* bytes_written) {
21  OVERLAPPED overlapped = {0};
22  DWORD bytes_written_dword = 0;
23
24  if (!WriteFile(handle.handle, buffer, static_cast<DWORD>(bytes_to_write),
25                 &bytes_written_dword, &overlapped)) {
26    if (GetLastError() != ERROR_IO_PENDING ||
27        !GetOverlappedResult(handle.handle, &overlapped, &bytes_written_dword,
28                             TRUE)) {
29      return false;
30    }
31  }
32
33  *bytes_written = bytes_written_dword;
34  return true;
35}
36
37bool BlockingRead(const PlatformHandle& handle,
38                  void* buffer,
39                  size_t buffer_size,
40                  size_t* bytes_read) {
41  OVERLAPPED overlapped = {0};
42  DWORD bytes_read_dword = 0;
43
44  if (!ReadFile(handle.handle, buffer, static_cast<DWORD>(buffer_size),
45                &bytes_read_dword, &overlapped)) {
46    if (GetLastError() != ERROR_IO_PENDING ||
47        !GetOverlappedResult(handle.handle, &overlapped, &bytes_read_dword,
48                             TRUE)) {
49      return false;
50    }
51  }
52
53  *bytes_read = bytes_read_dword;
54  return true;
55}
56
57bool NonBlockingRead(const PlatformHandle& handle,
58                     void* buffer,
59                     size_t buffer_size,
60                     size_t* bytes_read) {
61  OVERLAPPED overlapped = {0};
62  DWORD bytes_read_dword = 0;
63
64  if (!ReadFile(handle.handle, buffer, static_cast<DWORD>(buffer_size),
65                &bytes_read_dword, &overlapped)) {
66    if (GetLastError() != ERROR_IO_PENDING)
67      return false;
68
69    CancelIo(handle.handle);
70
71    if (!GetOverlappedResult(handle.handle, &overlapped, &bytes_read_dword,
72                             TRUE)) {
73      *bytes_read = 0;
74      return true;
75    }
76  }
77
78  *bytes_read = bytes_read_dword;
79  return true;
80}
81
82ScopedPlatformHandle PlatformHandleFromFILE(base::ScopedFILE fp) {
83  CHECK(fp);
84
85  HANDLE rv = INVALID_HANDLE_VALUE;
86  PCHECK(DuplicateHandle(
87      GetCurrentProcess(),
88      reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(fp.get()))),
89      GetCurrentProcess(), &rv, 0, TRUE, DUPLICATE_SAME_ACCESS))
90      << "DuplicateHandle";
91  return ScopedPlatformHandle(PlatformHandle(rv));
92}
93
94base::ScopedFILE FILEFromPlatformHandle(ScopedPlatformHandle h,
95                                        const char* mode) {
96  CHECK(h.is_valid());
97  // Microsoft's documentation for |_open_osfhandle()| only discusses these
98  // flags (and |_O_WTEXT|). Hmmm.
99  int flags = 0;
100  if (strchr(mode, 'a'))
101    flags |= _O_APPEND;
102  if (strchr(mode, 'r'))
103    flags |= _O_RDONLY;
104  if (strchr(mode, 't'))
105    flags |= _O_TEXT;
106  base::ScopedFILE rv(_fdopen(
107      _open_osfhandle(reinterpret_cast<intptr_t>(h.release().handle), flags),
108      mode));
109  PCHECK(rv) << "_fdopen";
110  return rv;
111}
112
113}  // namespace test
114}  // namespace edk
115}  // namespace mojo
116