ReactOS 0.4.15-dev-7958-gcd0bb1a
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
167 if (ReadFile(m_hReadPipe, Buffer, NumberOfBytesToRead, NumberOfBytesRead, &m_ReadOverlapped))
168 {
169 // The asynchronous read request could be satisfied immediately.
170 return ERROR_SUCCESS;
171 }
172
173 DWORD dwLastError = GetLastError();
174 if (dwLastError == ERROR_IO_PENDING)
175 {
176 // The asynchronous read request could not be satisfied immediately, so wait for it with the given timeout.
177 DWORD dwWaitResult = WaitForSingleObject(m_ReadOverlapped.hEvent, TimeoutMilliseconds);
178 if (dwWaitResult == WAIT_OBJECT_0)
179 {
180 // Fill NumberOfBytesRead.
181 if (GetOverlappedResult(m_hReadPipe, &m_ReadOverlapped, NumberOfBytesRead, FALSE))
182 {
183 // We successfully read NumberOfBytesRead bytes.
184 return ERROR_SUCCESS;
185 }
186
187 dwLastError = GetLastError();
188 if (dwLastError == ERROR_BROKEN_PIPE)
189 {
190 // The other end of the pipe has been closed.
191 return ERROR_BROKEN_PIPE;
192 }
193 else
194 {
195 // An unexpected error.
196 FATAL("GetOverlappedResult failed\n");
197 }
198 }
199 else
200 {
201 // This may be WAIT_TIMEOUT or an unexpected error.
202 return dwWaitResult;
203 }
204 }
205 else
206 {
207 // This may be ERROR_BROKEN_PIPE or an unexpected error.
208 return dwLastError;
209 }
210}
211
231bool
232CPipe::Write(LPCVOID Buffer, DWORD NumberOfBytesToWrite, PDWORD NumberOfBytesWritten)
233{
234 if (!m_hWritePipe)
235 FATAL("Trying to write to a closed write pipe\n");
236
237 return WriteFile(m_hWritePipe, Buffer, NumberOfBytesToWrite, NumberOfBytesWritten, NULL);
238}
#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:232
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
#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 LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
#define swprintf
Definition: precomp.h:40
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 FILE_FLAG_OVERLAPPED
Definition: disk.h:46
#define FATAL(Message)
Definition: precomp.h:57
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
#define L(x)
Definition: ntvdm.h:50
DWORD * PDWORD
Definition: pedump.c:68
long LONG
Definition: pedump.c:60
HANDLE hEvent
Definition: winbase.h:820
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:651
_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:165
#define ZeroMemory
Definition: winbase.h:1712
#define PIPE_READMODE_BYTE
Definition: winbase.h:169
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define PIPE_WAIT
Definition: winbase.h:171
#define PIPE_TYPE_BYTE
Definition: winbase.h:167
#define WAIT_OBJECT_0
Definition: winbase.h:406
CONST void * LPCVOID
Definition: windef.h:191
#define ERROR_BROKEN_PIPE
Definition: winerror.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180