ReactOS 0.4.17-dev-470-gf9e3448
CPipe.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Automatic Testing Utility
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Class that manages an unidirectional anonymous byte stream pipe
5 * COPYRIGHT: Copyright 2015 Thomas Faber (thomas.faber@reactos.org)
6 * Copyright 2019 Colin Finck (colin@reactos.org)
7 */
8
9#include "precomp.h"
10
12
13
18{
19 SECURITY_ATTRIBUTES SecurityAttributes;
20
21 SecurityAttributes.nLength = sizeof(SecurityAttributes);
22 SecurityAttributes.bInheritHandle = TRUE;
23 SecurityAttributes.lpSecurityDescriptor = NULL;
24
25 // Construct a unique pipe name.
26 WCHAR wszPipeName[MAX_PATH];
28 _swprintf(wszPipeName, L"\\\\.\\pipe\\TestmanPipe%ld", m_lPipeCount);
29
30 // Create a named pipe with the default settings, but overlapped (asynchronous) operations.
31 // Latter feature is why we can't simply use CreatePipe.
32 const DWORD dwDefaultBufferSize = 4096;
33 const DWORD dwDefaultTimeoutMilliseconds = 120000;
34
35 m_hReadPipe = CreateNamedPipeW(wszPipeName,
38 1,
39 dwDefaultBufferSize,
40 dwDefaultBufferSize,
41 dwDefaultTimeoutMilliseconds,
42 &SecurityAttributes);
44 {
45 FATAL("CreateNamedPipe failed\n");
46 }
47
48 // Use CreateFileW to get the write handle to the pipe.
49 // Writing is done synchronously, so no FILE_FLAG_OVERLAPPED here!
50 m_hWritePipe = CreateFileW(wszPipeName,
52 0,
53 &SecurityAttributes,
56 NULL);
58 {
59 FATAL("CreateFileW failed\n");
60 }
61
62 // Prepare the OVERLAPPED structure for reading.
66 {
67 FATAL("CreateEvent failed\n");
68 }
69}
70
75{
76 if (m_hReadPipe)
78 if (m_hWritePipe)
80}
81
85void
87{
88 if (!m_hReadPipe)
89 FATAL("Trying to close already closed read pipe\n");
92}
93
97void
99{
100 if (!m_hWritePipe)
101 FATAL("Trying to close already closed write pipe\n");
104}
105
128bool
130{
131 if (!m_hReadPipe)
132 FATAL("Trying to peek from a closed read pipe\n");
133
134 return PeekNamedPipe(m_hReadPipe, Buffer, BufferSize, BytesRead, TotalBytesAvailable, NULL);
135}
136
159DWORD
160CPipe::Read(PVOID Buffer, DWORD NumberOfBytesToRead, PDWORD NumberOfBytesRead, DWORD TimeoutMilliseconds)
161{
162 if (!m_hReadPipe)
163 {
164 FATAL("Trying to read from a closed read pipe\n");
165 }
166
169
170 if (ReadFile(m_hReadPipe, Buffer, NumberOfBytesToRead, NumberOfBytesRead, &m_ReadOverlapped))
171 {
172 // The asynchronous read request could be satisfied immediately.
173 return ERROR_SUCCESS;
174 }
175
176 DWORD dwLastError = GetLastError();
177 if (dwLastError == ERROR_IO_PENDING)
178 {
179 // The asynchronous read request could not be satisfied immediately, so wait for it with the given timeout.
180 DWORD dwWaitResult = WaitForSingleObject(m_ReadOverlapped.hEvent, TimeoutMilliseconds);
181 if (dwWaitResult == WAIT_OBJECT_0)
182 {
183 // Fill NumberOfBytesRead.
184 if (GetOverlappedResult(m_hReadPipe, &m_ReadOverlapped, NumberOfBytesRead, FALSE))
185 {
186 // We successfully read NumberOfBytesRead bytes.
187 return ERROR_SUCCESS;
188 }
189
190 dwLastError = GetLastError();
191 if (dwLastError == ERROR_BROKEN_PIPE)
192 {
193 // The other end of the pipe has been closed.
194 return ERROR_BROKEN_PIPE;
195 }
196 else
197 {
198 // An unexpected error.
199 FATAL("GetOverlappedResult failed\n");
200 }
201 }
202 else
203 {
204 // This may be WAIT_TIMEOUT or an unexpected error.
206 return dwWaitResult;
207 }
208 }
209 else
210 {
211 // This may be ERROR_BROKEN_PIPE or an unexpected error.
212 return dwLastError;
213 }
214}
215
235bool
236CPipe::Write(LPCVOID Buffer, DWORD NumberOfBytesToWrite, PDWORD NumberOfBytesWritten)
237{
238 if (!m_hWritePipe)
239 FATAL("Trying to write to a closed write pipe\n");
240
241 return WriteFile(m_hWritePipe, Buffer, NumberOfBytesToWrite, NumberOfBytesWritten, NULL);
242}
#define InterlockedIncrement
Definition: armddk.h:53
Definition: bufpool.h:45
HANDLE m_hWritePipe
Definition: CPipe.h:16
bool Write(LPCVOID Buffer, DWORD NumberOfBytesToWrite, PDWORD NumberOfBytesWritten)
Definition: CPipe.cpp:236
DWORD Read(PVOID Buffer, DWORD NumberOfBytesToRead, PDWORD NumberOfBytesRead, DWORD TimeoutMilliseconds)
Definition: CPipe.cpp:160
void CloseWritePipe()
Definition: CPipe.cpp:98
~CPipe()
Definition: CPipe.cpp:74
bool Peek(PVOID Buffer, DWORD BufferSize, PDWORD BytesRead, PDWORD TotalBytesAvailable)
Definition: CPipe.cpp:129
static LONG m_lPipeCount
Definition: CPipe.h:12
OVERLAPPED m_ReadOverlapped
Definition: CPipe.h:14
CPipe()
Definition: CPipe.cpp:17
void CloseReadPipe()
Definition: CPipe.cpp:86
HANDLE m_hReadPipe
Definition: CPipe.h:15
#define ERROR_IO_PENDING
Definition: dderror.h:15
#define ERROR_SUCCESS
Definition: deptool.c:10
BOOL WINAPI CancelIo(IN HANDLE hFile)
Definition: deviceio.c:293
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
#define OPEN_EXISTING
Definition: compat.h:775
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define MAX_PATH
Definition: compat.h:34
#define CreateFileW
Definition: compat.h:741
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
BOOL WINAPI WriteFile(_In_ HANDLE hFile, _In_reads_bytes_opt_(nNumberOfBytesToWrite) LPCVOID lpBuffer, _In_ DWORD nNumberOfBytesToWrite, _Out_opt_ LPDWORD lpNumberOfBytesWritten, _Inout_opt_ LPOVERLAPPED lpOverlapped)
Definition: rw.c:25
#define L(x)
Definition: resources.c:13
unsigned long DWORD
Definition: ntddk_ex.h:95
BOOL WINAPI GetOverlappedResult(IN HANDLE hFile, IN LPOVERLAPPED lpOverlapped, OUT LPDWORD lpNumberOfBytesTransferred, IN BOOL bWait)
Definition: iocompl.c:221
#define ZeroMemory
Definition: minwinbase.h:31
CONST void * LPCVOID
Definition: minwindef.h:164
#define FILE_FLAG_OVERLAPPED
Definition: disk.h:46
#define _swprintf(buf, format,...)
Definition: sprintf.c:56
#define FATAL(Message)
Definition: precomp.h:59
static HANDLE hEvent
Definition: comm.c:54
BOOL WINAPI PeekNamedPipe(HANDLE hNamedPipe, LPVOID lpBuffer, DWORD nBufferSize, LPDWORD lpBytesRead, LPDWORD lpTotalBytesAvail, LPDWORD lpBytesLeftThisMessage)
Definition: npipe.c:1214
HANDLE WINAPI CreateNamedPipeW(LPCWSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: npipe.c:246
#define GENERIC_WRITE
Definition: nt_native.h:90
short WCHAR
Definition: pedump.c:58
DWORD * PDWORD
Definition: pedump.c:68
long LONG
Definition: pedump.c:60
HANDLE hEvent
Definition: minwinbase.h:230
LPVOID lpSecurityDescriptor
Definition: compat.h:193
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:587
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:650
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesRead
Definition: wdfiotarget.h:870
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
#define PIPE_ACCESS_INBOUND
Definition: winbase.h:168
#define PIPE_READMODE_BYTE
Definition: winbase.h:172
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define PIPE_WAIT
Definition: winbase.h:174
#define PIPE_TYPE_BYTE
Definition: winbase.h:170
#define WAIT_OBJECT_0
Definition: winbase.h:383
#define ERROR_BROKEN_PIPE
Definition: winerror.h:305