FreeRDP
TestPipeCreateNamedPipeOverlapped.c
1 
2 #include <stdio.h>
3 #include <winpr/crt.h>
4 #include <winpr/pipe.h>
5 #include <winpr/file.h>
6 #include <winpr/tchar.h>
7 #include <winpr/winpr.h>
8 #include <winpr/wlog.h>
9 #include <winpr/print.h>
10 #include <winpr/synch.h>
11 #include <winpr/thread.h>
12 
13 #define PIPE_BUFFER_SIZE 32
14 #define PIPE_TIMEOUT_MS 20000 // 20 seconds
15 
16 static BYTE SERVER_MESSAGE[PIPE_BUFFER_SIZE];
17 static BYTE CLIENT_MESSAGE[PIPE_BUFFER_SIZE];
18 
19 static BOOL bClientSuccess = FALSE;
20 static BOOL bServerSuccess = FALSE;
21 
22 static HANDLE serverReadyEvent = NULL;
23 
24 static LPTSTR lpszPipeName = _T("\\\\.\\pipe\\winpr_test_pipe_overlapped");
25 
26 static DWORD WINAPI named_pipe_client_thread(LPVOID arg)
27 {
28  DWORD status = 0;
29  HANDLE hEvent = NULL;
30  HANDLE hNamedPipe = NULL;
31  BYTE* lpReadBuffer = NULL;
32  BOOL fSuccess = FALSE;
33  OVERLAPPED overlapped = { 0 };
34  DWORD nNumberOfBytesToRead = 0;
35  DWORD nNumberOfBytesToWrite = 0;
36  DWORD NumberOfBytesTransferred = 0;
37 
38  WINPR_UNUSED(arg);
39 
40  status = WaitForSingleObject(serverReadyEvent, PIPE_TIMEOUT_MS);
41  if (status != WAIT_OBJECT_0)
42  {
43  printf("client: failed to wait for server ready event: %" PRIu32 "\n", status);
44  goto finish;
45  }
46 
47  /* 1: initialize overlapped structure */
48  if (!(hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
49  {
50  printf("client: CreateEvent failure: %" PRIu32 "\n", GetLastError());
51  goto finish;
52  }
53  overlapped.hEvent = hEvent;
54 
55  /* 2: connect to server named pipe */
56 
57  hNamedPipe = CreateFile(lpszPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
58  FILE_FLAG_OVERLAPPED, NULL);
59 
60  if (hNamedPipe == INVALID_HANDLE_VALUE)
61  {
62  printf("client: Named Pipe CreateFile failure: %" PRIu32 "\n", GetLastError());
63  goto finish;
64  }
65 
66  /* 3: write to named pipe */
67 
68  nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
69  NumberOfBytesTransferred = 0;
70 
71  fSuccess = WriteFile(hNamedPipe, CLIENT_MESSAGE, nNumberOfBytesToWrite, NULL, &overlapped);
72 
73  if (!fSuccess)
74  fSuccess = (GetLastError() == ERROR_IO_PENDING);
75 
76  if (!fSuccess)
77  {
78  printf("client: NamedPipe WriteFile failure (initial): %" PRIu32 "\n", GetLastError());
79  goto finish;
80  }
81 
82  status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
83  if (status != WAIT_OBJECT_0)
84  {
85  printf("client: failed to wait for overlapped event (write): %" PRIu32 "\n", status);
86  goto finish;
87  }
88 
89  fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, FALSE);
90  if (!fSuccess)
91  {
92  printf("client: NamedPipe WriteFile failure (final): %" PRIu32 "\n", GetLastError());
93  goto finish;
94  }
95  printf("client: WriteFile transferred %" PRIu32 " bytes:\n", NumberOfBytesTransferred);
96 
97  /* 4: read from named pipe */
98 
99  if (!(lpReadBuffer = (BYTE*)calloc(1, PIPE_BUFFER_SIZE)))
100  {
101  printf("client: Error allocating read buffer\n");
102  goto finish;
103  }
104 
105  nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
106  NumberOfBytesTransferred = 0;
107 
108  fSuccess = ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, NULL, &overlapped);
109 
110  if (!fSuccess)
111  fSuccess = (GetLastError() == ERROR_IO_PENDING);
112 
113  if (!fSuccess)
114  {
115  printf("client: NamedPipe ReadFile failure (initial): %" PRIu32 "\n", GetLastError());
116  goto finish;
117  }
118 
119  status = WaitForMultipleObjects(1, &hEvent, FALSE, PIPE_TIMEOUT_MS);
120  if (status != WAIT_OBJECT_0)
121  {
122  printf("client: failed to wait for overlapped event (read): %" PRIu32 "\n", status);
123  goto finish;
124  }
125 
126  fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, TRUE);
127  if (!fSuccess)
128  {
129  printf("client: NamedPipe ReadFile failure (final): %" PRIu32 "\n", GetLastError());
130  goto finish;
131  }
132 
133  printf("client: ReadFile transferred %" PRIu32 " bytes:\n", NumberOfBytesTransferred);
134  winpr_HexDump("pipe.test", WLOG_DEBUG, lpReadBuffer, NumberOfBytesTransferred);
135 
136  if (NumberOfBytesTransferred != PIPE_BUFFER_SIZE ||
137  memcmp(lpReadBuffer, SERVER_MESSAGE, PIPE_BUFFER_SIZE) != 0)
138  {
139  printf("client: received unexpected data from server\n");
140  goto finish;
141  }
142 
143  printf("client: finished successfully\n");
144  bClientSuccess = TRUE;
145 
146 finish:
147  free(lpReadBuffer);
148  if (hNamedPipe)
149  (void)CloseHandle(hNamedPipe);
150  if (hEvent)
151  (void)CloseHandle(hEvent);
152 
153  return 0;
154 }
155 
156 static DWORD WINAPI named_pipe_server_thread(LPVOID arg)
157 {
158  DWORD status = 0;
159  HANDLE hEvent = NULL;
160  HANDLE hNamedPipe = NULL;
161  BYTE* lpReadBuffer = NULL;
162  OVERLAPPED overlapped = { 0 };
163  BOOL fSuccess = FALSE;
164  BOOL fConnected = FALSE;
165  DWORD nNumberOfBytesToRead = 0;
166  DWORD nNumberOfBytesToWrite = 0;
167  DWORD NumberOfBytesTransferred = 0;
168 
169  WINPR_UNUSED(arg);
170 
171  /* 1: initialize overlapped structure */
172  if (!(hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
173  {
174  printf("server: CreateEvent failure: %" PRIu32 "\n", GetLastError());
175  (void)SetEvent(serverReadyEvent); /* unblock client thread */
176  goto finish;
177  }
178  overlapped.hEvent = hEvent;
179 
180  /* 2: create named pipe and set ready event */
181 
182  hNamedPipe =
183  CreateNamedPipe(lpszPipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
184  PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
185  PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, 0, NULL);
186 
187  if (hNamedPipe == INVALID_HANDLE_VALUE)
188  {
189  printf("server: CreateNamedPipe failure: %" PRIu32 "\n", GetLastError());
190  (void)SetEvent(serverReadyEvent); /* unblock client thread */
191  goto finish;
192  }
193 
194  (void)SetEvent(serverReadyEvent);
195 
196  /* 3: connect named pipe */
197 
198 #if 0
199  /* This sleep will most certainly cause ERROR_PIPE_CONNECTED below */
200  Sleep(2000);
201 #endif
202 
203  fConnected = ConnectNamedPipe(hNamedPipe, &overlapped);
204  status = GetLastError();
205 
220  if (!fConnected)
221  fConnected = (status == ERROR_PIPE_CONNECTED);
222 
223  printf("server: ConnectNamedPipe status: %" PRIu32 "\n", status);
224 
225  if (!fConnected && status == ERROR_IO_PENDING)
226  {
227  DWORD dwDummy = 0;
228  printf("server: waiting up to %u ms for connection ...\n", PIPE_TIMEOUT_MS);
229  status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
230  if (status == WAIT_OBJECT_0)
231  fConnected = GetOverlappedResult(hNamedPipe, &overlapped, &dwDummy, FALSE);
232  else
233  printf("server: failed to wait for overlapped event (connect): %" PRIu32 "\n", status);
234  }
235 
236  if (!fConnected)
237  {
238  printf("server: ConnectNamedPipe failed: %" PRIu32 "\n", status);
239  goto finish;
240  }
241 
242  printf("server: named pipe successfully connected\n");
243 
244  /* 4: read from named pipe */
245 
246  if (!(lpReadBuffer = (BYTE*)calloc(1, PIPE_BUFFER_SIZE)))
247  {
248  printf("server: Error allocating read buffer\n");
249  goto finish;
250  }
251 
252  nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
253  NumberOfBytesTransferred = 0;
254 
255  fSuccess = ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, NULL, &overlapped);
256 
257  if (!fSuccess)
258  fSuccess = (GetLastError() == ERROR_IO_PENDING);
259 
260  if (!fSuccess)
261  {
262  printf("server: NamedPipe ReadFile failure (initial): %" PRIu32 "\n", GetLastError());
263  goto finish;
264  }
265 
266  status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
267  if (status != WAIT_OBJECT_0)
268  {
269  printf("server: failed to wait for overlapped event (read): %" PRIu32 "\n", status);
270  goto finish;
271  }
272 
273  fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, FALSE);
274  if (!fSuccess)
275  {
276  printf("server: NamedPipe ReadFile failure (final): %" PRIu32 "\n", GetLastError());
277  goto finish;
278  }
279 
280  printf("server: ReadFile transferred %" PRIu32 " bytes:\n", NumberOfBytesTransferred);
281  winpr_HexDump("pipe.test", WLOG_DEBUG, lpReadBuffer, NumberOfBytesTransferred);
282 
283  if (NumberOfBytesTransferred != PIPE_BUFFER_SIZE ||
284  memcmp(lpReadBuffer, CLIENT_MESSAGE, PIPE_BUFFER_SIZE) != 0)
285  {
286  printf("server: received unexpected data from client\n");
287  goto finish;
288  }
289 
290  /* 5: write to named pipe */
291 
292  nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
293  NumberOfBytesTransferred = 0;
294 
295  fSuccess = WriteFile(hNamedPipe, SERVER_MESSAGE, nNumberOfBytesToWrite, NULL, &overlapped);
296 
297  if (!fSuccess)
298  fSuccess = (GetLastError() == ERROR_IO_PENDING);
299 
300  if (!fSuccess)
301  {
302  printf("server: NamedPipe WriteFile failure (initial): %" PRIu32 "\n", GetLastError());
303  goto finish;
304  }
305 
306  status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
307  if (status != WAIT_OBJECT_0)
308  {
309  printf("server: failed to wait for overlapped event (write): %" PRIu32 "\n", status);
310  goto finish;
311  }
312 
313  fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, FALSE);
314  if (!fSuccess)
315  {
316  printf("server: NamedPipe WriteFile failure (final): %" PRIu32 "\n", GetLastError());
317  goto finish;
318  }
319 
320  printf("server: WriteFile transferred %" PRIu32 " bytes:\n", NumberOfBytesTransferred);
321  // winpr_HexDump("pipe.test", WLOG_DEBUG, lpWriteBuffer, NumberOfBytesTransferred);
322 
323  bServerSuccess = TRUE;
324  printf("server: finished successfully\n");
325 
326 finish:
327  (void)CloseHandle(hNamedPipe);
328  (void)CloseHandle(hEvent);
329  free(lpReadBuffer);
330  return 0;
331 }
332 
333 int TestPipeCreateNamedPipeOverlapped(int argc, char* argv[])
334 {
335  HANDLE ClientThread = NULL;
336  HANDLE ServerThread = NULL;
337  int result = -1;
338  WINPR_UNUSED(argc);
339  WINPR_UNUSED(argv);
340  FillMemory(SERVER_MESSAGE, PIPE_BUFFER_SIZE, 0xAA);
341  FillMemory(CLIENT_MESSAGE, PIPE_BUFFER_SIZE, 0xBB);
342 
343  if (!(serverReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
344  {
345  printf("CreateEvent failed: %" PRIu32 "\n", GetLastError());
346  goto out;
347  }
348  if (!(ClientThread = CreateThread(NULL, 0, named_pipe_client_thread, NULL, 0, NULL)))
349  {
350  printf("CreateThread (client) failed: %" PRIu32 "\n", GetLastError());
351  goto out;
352  }
353  if (!(ServerThread = CreateThread(NULL, 0, named_pipe_server_thread, NULL, 0, NULL)))
354  {
355  printf("CreateThread (server) failed: %" PRIu32 "\n", GetLastError());
356  goto out;
357  }
358 
359  if (WAIT_OBJECT_0 != WaitForSingleObject(ClientThread, INFINITE))
360  {
361  printf("%s: Failed to wait for client thread: %" PRIu32 "\n", __func__, GetLastError());
362  goto out;
363  }
364  if (WAIT_OBJECT_0 != WaitForSingleObject(ServerThread, INFINITE))
365  {
366  printf("%s: Failed to wait for server thread: %" PRIu32 "\n", __func__, GetLastError());
367  goto out;
368  }
369 
370  if (bClientSuccess && bServerSuccess)
371  result = 0;
372 
373 out:
374 
375  if (ClientThread)
376  (void)CloseHandle(ClientThread);
377  if (ServerThread)
378  (void)CloseHandle(ServerThread);
379  if (serverReadyEvent)
380  (void)CloseHandle(serverReadyEvent);
381 
382 #ifndef _WIN32
383  if (result == 0)
384  {
385  printf("%s: Error, this test is currently expected not to succeed on this platform.\n",
386  __func__);
387  result = -1;
388  }
389  else
390  {
391  printf("%s: This test is currently expected to fail on this platform.\n", __func__);
392  result = 0;
393  }
394 #endif
395 
396  return result;
397 }