ReactOS  0.4.14-dev-317-g96040ec
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 
85 void
87 {
88  if (!m_hReadPipe)
89  FATAL("Trying to close already closed read pipe\n");
91  m_hReadPipe = NULL;
92 }
93 
97 void
99 {
100  if (!m_hWritePipe)
101  FATAL("Trying to close already closed write pipe\n");
103  m_hWritePipe = NULL;
104 }
105 
128 bool
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 
159 DWORD
160 CPipe::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 
231 bool
232 CPipe::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 FATAL(Message)
Definition: precomp.h:57
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 TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
#define ERROR_SUCCESS
Definition: deptool.c:10
CPipe()
Definition: CPipe.cpp:17
BOOL WINAPI GetOverlappedResult(IN HANDLE hFile, IN LPOVERLAPPED lpOverlapped, OUT LPDWORD lpNumberOfBytesTransferred, IN BOOL bWait)
Definition: iocompl.c:204
#define PIPE_WAIT
Definition: winbase.h:171
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1642
#define ERROR_IO_PENDING
Definition: dderror.h:15
void CloseReadPipe()
Definition: CPipe.cpp:86
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
long LONG
Definition: pedump.c:60
#define GENERIC_WRITE
Definition: nt_native.h:90
void CloseWritePipe()
Definition: CPipe.cpp:98
#define PIPE_TYPE_BYTE
Definition: winbase.h:167
HANDLE hEvent
Definition: winbase.h:792
smooth NULL
Definition: ftsmooth.c:416
Definition: bufpool.h:45
DWORD Read(PVOID Buffer, DWORD NumberOfBytesToRead, PDWORD NumberOfBytesRead, DWORD TimeoutMilliseconds)
Definition: CPipe.cpp:160
#define OPEN_EXISTING
Definition: compat.h:426
#define WAIT_OBJECT_0
Definition: winbase.h:387
__wchar_t WCHAR
Definition: xmlstorage.h:180
OVERLAPPED m_ReadOverlapped
Definition: CPipe.h:14
#define MAX_PATH
Definition: compat.h:26
#define swprintf(buf, format,...)
Definition: sprintf.c:56
#define BufferSize
Definition: classpnp.h:419
unsigned long DWORD
Definition: ntddk_ex.h:95
#define ERROR_BROKEN_PIPE
Definition: winerror.h:183
static LONG m_lPipeCount
Definition: CPipe.h:12
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
static const WCHAR L[]
Definition: oid.c:1250
bool Peek(PVOID Buffer, DWORD BufferSize, PDWORD BytesRead, PDWORD TotalBytesAvailable)
Definition: CPipe.cpp:129
bool Write(LPCVOID Buffer, DWORD NumberOfBytesToWrite, PDWORD NumberOfBytesWritten)
Definition: CPipe.cpp:232
HANDLE m_hReadPipe
Definition: CPipe.h:15
#define InterlockedIncrement
Definition: armddk.h:53
LPVOID lpSecurityDescriptor
Definition: compat.h:181
#define PIPE_ACCESS_INBOUND
Definition: winbase.h:165
DWORD * PDWORD
Definition: pedump.c:68
#define CreateFileW
Definition: compat.h:400
HANDLE m_hWritePipe
Definition: CPipe.h:16
CONST void * LPCVOID
Definition: windef.h:191
~CPipe()
Definition: CPipe.cpp:74
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 FILE_FLAG_OVERLAPPED
Definition: disk.h:46
BOOL WINAPI ReadFile(IN HANDLE hFile, IN LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:123
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ FLT_IO_OPERATION_FLAGS _Out_opt_ PULONG BytesRead
Definition: fltkernel.h:1255
BOOL WINAPI PeekNamedPipe(HANDLE hNamedPipe, LPVOID lpBuffer, DWORD nBufferSize, LPDWORD lpBytesRead, LPDWORD lpTotalBytesAvail, LPDWORD lpBytesLeftThisMessage)
Definition: npipe.c:1214
#define PIPE_READMODE_BYTE
Definition: winbase.h:169