1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 #include "cmDebuggerWindowsPipeConnection.h"
11 namespace cmDebugger
{
15 DuplexPipe_WIN32::DuplexPipe_WIN32(HANDLE pipe
)
18 readOp
.Offset
= readOp
.OffsetHigh
= 0;
19 readOp
.hEvent
= CreateEvent(NULL
, true, false, NULL
);
20 writeOp
.Offset
= readOp
.OffsetHigh
= 0;
21 writeOp
.hEvent
= CreateEvent(NULL
, true, false, NULL
);
24 DuplexPipe_WIN32::~DuplexPipe_WIN32()
29 size_t DuplexPipe_WIN32::read(void* buffer
, size_t n
)
31 if (hPipe
!= INVALID_HANDLE_VALUE
) {
32 readOp
.Offset
= readOp
.OffsetHigh
= 0;
33 ResetEvent(readOp
.hEvent
);
34 auto r
= ReadFile(hPipe
, buffer
, n
, NULL
, &readOp
);
35 auto err
= GetLastError();
36 if (r
|| err
== ERROR_IO_PENDING
) {
38 if (GetOverlappedResult(hPipe
, &readOp
, &nRead
, true)) {
47 bool DuplexPipe_WIN32::write(void const* buffer
, size_t n
)
49 if (hPipe
!= INVALID_HANDLE_VALUE
) {
50 writeOp
.Offset
= writeOp
.OffsetHigh
= 0;
51 ResetEvent(writeOp
.hEvent
);
52 auto w
= WriteFile(hPipe
, buffer
, n
, NULL
, &writeOp
);
53 auto err
= GetLastError();
54 if (w
|| err
== ERROR_IO_PENDING
) {
56 if (GetOverlappedResult(hPipe
, &writeOp
, &nWrite
, true)) {
65 void DuplexPipe_WIN32::close()
68 hPipe
= INVALID_HANDLE_VALUE
;
69 CloseHandle(readOp
.hEvent
);
70 CloseHandle(writeOp
.hEvent
);
71 readOp
.hEvent
= writeOp
.hEvent
= INVALID_HANDLE_VALUE
;
74 bool DuplexPipe_WIN32::WaitForConnection()
76 auto connect
= ConnectNamedPipe(hPipe
, &readOp
);
77 auto err
= GetLastError();
78 if (!connect
&& err
== ERROR_IO_PENDING
) {
80 if (GetOverlappedResult(hPipe
, &readOp
, &ignored
, true)) {
85 return connect
|| err
== ERROR_PIPE_CONNECTED
;
88 cmDebuggerPipeConnection_WIN32::cmDebuggerPipeConnection_WIN32(
90 : PipeName(std::move(name
))
95 cmDebuggerPipeConnection_WIN32::~cmDebuggerPipeConnection_WIN32()
102 bool cmDebuggerPipeConnection_WIN32::StartListening(std::string
& errorMessage
)
106 auto hPipe
= CreateNamedPipeA(
108 PIPE_ACCESS_DUPLEX
| FILE_FLAG_FIRST_PIPE_INSTANCE
| FILE_FLAG_OVERLAPPED
,
109 PIPE_TYPE_BYTE
| PIPE_READMODE_BYTE
| PIPE_REJECT_REMOTE_CLIENTS
, 1,
110 1024 * 16, 1024 * 16, NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
112 if (hPipe
== INVALID_HANDLE_VALUE
) {
113 auto err
= GetLastError();
114 errorMessage
= GetErrorMessage(err
);
119 pipes
= std::make_unique
<DuplexPipe_WIN32
>(hPipe
);
122 StartedListening
.set_value();
126 std::string
cmDebuggerPipeConnection_WIN32::GetErrorMessage(DWORD errorCode
)
128 LPSTR message
= nullptr;
129 DWORD size
= FormatMessageA(
130 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
|
131 FORMAT_MESSAGE_IGNORE_INSERTS
,
132 nullptr, errorCode
, MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
133 (LPSTR
)&message
, 0, nullptr);
134 std::string errorMessage
= "Internal Error with " + this->PipeName
+ ": " +
135 std::string(message
, size
);
140 std::shared_ptr
<dap::Reader
> cmDebuggerPipeConnection_WIN32::GetReader()
142 return std::static_pointer_cast
<dap::Reader
>(shared_from_this());
145 std::shared_ptr
<dap::Writer
> cmDebuggerPipeConnection_WIN32::GetWriter()
147 return std::static_pointer_cast
<dap::Writer
>(shared_from_this());
150 bool cmDebuggerPipeConnection_WIN32::isOpen()
152 return pipes
!= nullptr;
155 void cmDebuggerPipeConnection_WIN32::close()
160 void cmDebuggerPipeConnection_WIN32::CloseConnection()
168 void cmDebuggerPipeConnection_WIN32::WaitForConnection()
174 if (pipes
->WaitForConnection()) {
181 size_t cmDebuggerPipeConnection_WIN32::read(void* buffer
, size_t n
)
185 result
= pipes
->read(buffer
, n
);
194 bool cmDebuggerPipeConnection_WIN32::write(void const* buffer
, size_t n
)
198 result
= pipes
->write(buffer
, n
);
207 cmDebuggerPipeClient_WIN32::cmDebuggerPipeClient_WIN32(std::string name
)
208 : PipeName(std::move(name
))
212 cmDebuggerPipeClient_WIN32::~cmDebuggerPipeClient_WIN32()
217 void cmDebuggerPipeClient_WIN32::WaitForConnection()
220 auto hPipe
= CreateFileA(PipeName
.c_str(), GENERIC_READ
| GENERIC_WRITE
, 0,
221 NULL
, OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, NULL
);
222 if (hPipe
== INVALID_HANDLE_VALUE
) {
223 auto err
= GetLastError();
224 throw std::runtime_error(std::string("CreateFile failed for pipe ") +
225 GetErrorMessage(err
));
228 pipes
= std::make_unique
<DuplexPipe_WIN32
>(hPipe
);
232 std::string
cmDebuggerPipeClient_WIN32::GetErrorMessage(DWORD errorCode
)
234 LPSTR message
= nullptr;
235 DWORD size
= FormatMessageA(
236 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
|
237 FORMAT_MESSAGE_IGNORE_INSERTS
,
238 nullptr, errorCode
, MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
239 (LPSTR
)&message
, 0, nullptr);
240 std::string errorMessage
=
241 this->PipeName
+ ": " + std::string(message
, size
);
246 bool cmDebuggerPipeClient_WIN32::isOpen()
248 return pipes
!= nullptr;
251 void cmDebuggerPipeClient_WIN32::close()
259 size_t cmDebuggerPipeClient_WIN32::read(void* buffer
, size_t n
)
263 result
= pipes
->read(buffer
, n
);
272 bool cmDebuggerPipeClient_WIN32::write(void const* buffer
, size_t n
)
276 result
= pipes
->write(buffer
, n
);
287 } // namespace cmDebugger