FreeRDP
TestPipeCreateNamedPipe.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/print.h>
9 #include <winpr/synch.h>
10 #include <winpr/wlog.h>
11 #include <winpr/thread.h>
12 #ifndef _WIN32
13 #include <signal.h>
14 #endif
15 #include "../pipe.h"
16 
17 #define PIPE_BUFFER_SIZE 32
18 
19 static HANDLE ReadyEvent;
20 
21 static LPTSTR lpszPipeNameMt = _T("\\\\.\\pipe\\winpr_test_pipe_mt");
22 static LPTSTR lpszPipeNameSt = _T("\\\\.\\pipe\\winpr_test_pipe_st");
23 
24 static BOOL testFailed = FALSE;
25 
26 static DWORD WINAPI named_pipe_client_thread(LPVOID arg)
27 {
28  HANDLE hNamedPipe = NULL;
29  BYTE* lpReadBuffer = NULL;
30  BYTE* lpWriteBuffer = NULL;
31  BOOL fSuccess = FALSE;
32  DWORD nNumberOfBytesToRead = 0;
33  DWORD nNumberOfBytesToWrite = 0;
34  DWORD lpNumberOfBytesRead = 0;
35  DWORD lpNumberOfBytesWritten = 0;
36  (void)WaitForSingleObject(ReadyEvent, INFINITE);
37  hNamedPipe =
38  CreateFile(lpszPipeNameMt, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
39 
40  if (hNamedPipe == INVALID_HANDLE_VALUE)
41  {
42  printf("%s: Named Pipe CreateFile failure: INVALID_HANDLE_VALUE\n", __func__);
43  goto out;
44  }
45 
46  if (!(lpReadBuffer = (BYTE*)malloc(PIPE_BUFFER_SIZE)))
47  {
48  printf("%s: Error allocating read buffer\n", __func__);
49  goto out;
50  }
51 
52  if (!(lpWriteBuffer = (BYTE*)malloc(PIPE_BUFFER_SIZE)))
53  {
54  printf("%s: Error allocating write buffer\n", __func__);
55  goto out;
56  }
57 
58  lpNumberOfBytesWritten = 0;
59  nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
60  FillMemory(lpWriteBuffer, PIPE_BUFFER_SIZE, 0x59);
61 
62  if (!WriteFile(hNamedPipe, lpWriteBuffer, nNumberOfBytesToWrite, &lpNumberOfBytesWritten,
63  NULL) ||
64  lpNumberOfBytesWritten != nNumberOfBytesToWrite)
65  {
66  printf("%s: Client NamedPipe WriteFile failure\n", __func__);
67  goto out;
68  }
69 
70  lpNumberOfBytesRead = 0;
71  nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
72  ZeroMemory(lpReadBuffer, PIPE_BUFFER_SIZE);
73 
74  if (!ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, &lpNumberOfBytesRead, NULL) ||
75  lpNumberOfBytesRead != nNumberOfBytesToRead)
76  {
77  printf("%s: Client NamedPipe ReadFile failure\n", __func__);
78  goto out;
79  }
80 
81  printf("Client ReadFile: %" PRIu32 " bytes\n", lpNumberOfBytesRead);
82  winpr_HexDump("pipe.test", WLOG_DEBUG, lpReadBuffer, lpNumberOfBytesRead);
83  fSuccess = TRUE;
84 out:
85  free(lpReadBuffer);
86  free(lpWriteBuffer);
87  (void)CloseHandle(hNamedPipe);
88 
89  if (!fSuccess)
90  testFailed = TRUE;
91 
92  ExitThread(0);
93  return 0;
94 }
95 
96 static DWORD WINAPI named_pipe_server_thread(LPVOID arg)
97 {
98  HANDLE hNamedPipe = NULL;
99  BYTE* lpReadBuffer = NULL;
100  BYTE* lpWriteBuffer = NULL;
101  BOOL fSuccess = FALSE;
102  BOOL fConnected = FALSE;
103  DWORD nNumberOfBytesToRead = 0;
104  DWORD nNumberOfBytesToWrite = 0;
105  DWORD lpNumberOfBytesRead = 0;
106  DWORD lpNumberOfBytesWritten = 0;
107  hNamedPipe = CreateNamedPipe(
108  lpszPipeNameMt, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
109  PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, 0, NULL);
110 
111  if (!hNamedPipe)
112  {
113  printf("%s: CreateNamedPipe failure: NULL handle\n", __func__);
114  goto out;
115  }
116 
117  if (hNamedPipe == INVALID_HANDLE_VALUE)
118  {
119  printf("%s: CreateNamedPipe failure: INVALID_HANDLE_VALUE\n", __func__);
120  goto out;
121  }
122 
123  (void)SetEvent(ReadyEvent);
124 
133  fConnected =
134  ConnectNamedPipe(hNamedPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
135 
136  if (!fConnected)
137  {
138  printf("%s: ConnectNamedPipe failure\n", __func__);
139  goto out;
140  }
141 
142  if (!(lpReadBuffer = (BYTE*)calloc(1, PIPE_BUFFER_SIZE)))
143  {
144  printf("%s: Error allocating read buffer\n", __func__);
145  goto out;
146  }
147 
148  if (!(lpWriteBuffer = (BYTE*)malloc(PIPE_BUFFER_SIZE)))
149  {
150  printf("%s: Error allocating write buffer\n", __func__);
151  goto out;
152  }
153 
154  lpNumberOfBytesRead = 0;
155  nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
156 
157  if (!ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, &lpNumberOfBytesRead, NULL) ||
158  lpNumberOfBytesRead != nNumberOfBytesToRead)
159  {
160  printf("%s: Server NamedPipe ReadFile failure\n", __func__);
161  goto out;
162  }
163 
164  printf("Server ReadFile: %" PRIu32 " bytes\n", lpNumberOfBytesRead);
165  winpr_HexDump("pipe.test", WLOG_DEBUG, lpReadBuffer, lpNumberOfBytesRead);
166  lpNumberOfBytesWritten = 0;
167  nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
168  FillMemory(lpWriteBuffer, PIPE_BUFFER_SIZE, 0x45);
169 
170  if (!WriteFile(hNamedPipe, lpWriteBuffer, nNumberOfBytesToWrite, &lpNumberOfBytesWritten,
171  NULL) ||
172  lpNumberOfBytesWritten != nNumberOfBytesToWrite)
173  {
174  printf("%s: Server NamedPipe WriteFile failure\n", __func__);
175  goto out;
176  }
177 
178  fSuccess = TRUE;
179 out:
180  free(lpReadBuffer);
181  free(lpWriteBuffer);
182  (void)CloseHandle(hNamedPipe);
183 
184  if (!fSuccess)
185  testFailed = TRUE;
186 
187  ExitThread(0);
188  return 0;
189 }
190 
191 #define TESTNUMPIPESST 16
192 static DWORD WINAPI named_pipe_single_thread(LPVOID arg)
193 {
194  HANDLE servers[TESTNUMPIPESST] = { 0 };
195  HANDLE clients[TESTNUMPIPESST] = { 0 };
196  DWORD dwRead = 0;
197  DWORD dwWritten = 0;
198  int numPipes = 0;
199  BOOL bSuccess = FALSE;
200  numPipes = TESTNUMPIPESST;
201  (void)WaitForSingleObject(ReadyEvent, INFINITE);
202 
203  for (int i = 0; i < numPipes; i++)
204  {
205  if (!(servers[i] = CreateNamedPipe(lpszPipeNameSt, PIPE_ACCESS_DUPLEX,
206  PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
207  PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE,
208  PIPE_BUFFER_SIZE, 0, NULL)))
209  {
210  printf("%s: CreateNamedPipe #%d failed\n", __func__, i);
211  goto out;
212  }
213  }
214 
215 #ifndef _WIN32
216 
217  for (int i = 0; i < numPipes; i++)
218  {
219  WINPR_NAMED_PIPE* p = (WINPR_NAMED_PIPE*)servers[i];
220 
221  if (strcmp(lpszPipeNameSt, p->name) != 0)
222  {
223  printf("%s: Pipe name mismatch for pipe #%d ([%s] instead of [%s])\n", __func__, i,
224  p->name, lpszPipeNameSt);
225  goto out;
226  }
227 
228  if (p->clientfd != -1)
229  {
230  printf("%s: Unexpected client fd value for pipe #%d (%d instead of -1)\n", __func__, i,
231  p->clientfd);
232  goto out;
233  }
234 
235  if (p->serverfd < 1)
236  {
237  printf("%s: Unexpected server fd value for pipe #%d (%d is not > 0)\n", __func__, i,
238  p->serverfd);
239  goto out;
240  }
241 
242  if (p->ServerMode == FALSE)
243  {
244  printf("%s: Unexpected ServerMode value for pipe #%d (0 instead of 1)\n", __func__, i);
245  goto out;
246  }
247  }
248 
249 #endif
250 
251  for (int i = 0; i < numPipes; i++)
252  {
253  BOOL fConnected = 0;
254  if ((clients[i] = CreateFile(lpszPipeNameSt, GENERIC_READ | GENERIC_WRITE, 0, NULL,
255  OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
256  {
257  printf("%s: CreateFile #%d failed\n", __func__, i);
258  goto out;
259  }
260 
269  fConnected =
270  ConnectNamedPipe(servers[i], NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
271 
272  if (!fConnected)
273  {
274  printf("%s: ConnectNamedPipe #%d failed. (%" PRIu32 ")\n", __func__, i, GetLastError());
275  goto out;
276  }
277  }
278 
279 #ifndef _WIN32
280 
281  for (int i = 0; i < numPipes; i++)
282  {
283  WINPR_NAMED_PIPE* p = servers[i];
284 
285  if (p->clientfd < 1)
286  {
287  printf("%s: Unexpected client fd value for pipe #%d (%d is not > 0)\n", __func__, i,
288  p->clientfd);
289  goto out;
290  }
291 
292  if (p->ServerMode)
293  {
294  printf("%s: Unexpected ServerMode value for pipe #%d (1 instead of 0)\n", __func__, i);
295  goto out;
296  }
297  }
298 
299  for (int i = 0; i < numPipes; i++)
300  {
301  {
302  char sndbuf[PIPE_BUFFER_SIZE] = { 0 };
303  char rcvbuf[PIPE_BUFFER_SIZE] = { 0 };
304  /* Test writing from clients to servers */
305  (void)sprintf_s(sndbuf, sizeof(sndbuf), "CLIENT->SERVER ON PIPE #%05d", i);
306 
307  if (!WriteFile(clients[i], sndbuf, sizeof(sndbuf), &dwWritten, NULL) ||
308  dwWritten != sizeof(sndbuf))
309  {
310  printf("%s: Error writing to client end of pipe #%d\n", __func__, i);
311  goto out;
312  }
313 
314  if (!ReadFile(servers[i], rcvbuf, dwWritten, &dwRead, NULL) || dwRead != dwWritten)
315  {
316  printf("%s: Error reading on server end of pipe #%d\n", __func__, i);
317  goto out;
318  }
319 
320  if (memcmp(sndbuf, rcvbuf, sizeof(sndbuf)) != 0)
321  {
322  printf("%s: Error data read on server end of pipe #%d is corrupted\n", __func__, i);
323  goto out;
324  }
325  }
326  {
327 
328  char sndbuf[PIPE_BUFFER_SIZE] = { 0 };
329  char rcvbuf[PIPE_BUFFER_SIZE] = { 0 };
330  /* Test writing from servers to clients */
331 
332  (void)sprintf_s(sndbuf, sizeof(sndbuf), "SERVER->CLIENT ON PIPE #%05d", i);
333 
334  if (!WriteFile(servers[i], sndbuf, sizeof(sndbuf), &dwWritten, NULL) ||
335  dwWritten != sizeof(sndbuf))
336  {
337  printf("%s: Error writing to server end of pipe #%d\n", __func__, i);
338  goto out;
339  }
340 
341  if (!ReadFile(clients[i], rcvbuf, dwWritten, &dwRead, NULL) || dwRead != dwWritten)
342  {
343  printf("%s: Error reading on client end of pipe #%d\n", __func__, i);
344  goto out;
345  }
346 
347  if (memcmp(sndbuf, rcvbuf, sizeof(sndbuf)) != 0)
348  {
349  printf("%s: Error data read on client end of pipe #%d is corrupted\n", __func__, i);
350  goto out;
351  }
352  }
353  }
354 
355 #endif
360  int i = numPipes - 1;
361  DisconnectNamedPipe(servers[i]);
362  {
363  char sndbuf[PIPE_BUFFER_SIZE] = { 0 };
364  char rcvbuf[PIPE_BUFFER_SIZE] = { 0 };
365  if (ReadFile(clients[i], rcvbuf, sizeof(rcvbuf), &dwRead, NULL))
366  {
367  printf("%s: Error ReadFile on client should have failed after DisconnectNamedPipe on "
368  "server\n",
369  __func__);
370  goto out;
371  }
372 
373  if (WriteFile(clients[i], sndbuf, sizeof(sndbuf), &dwWritten, NULL))
374  {
375  printf(
376  "%s: Error WriteFile on client end should have failed after DisconnectNamedPipe on "
377  "server\n",
378  __func__);
379  goto out;
380  }
381  }
382  (void)CloseHandle(servers[i]);
383  (void)CloseHandle(clients[i]);
384  numPipes--;
389  i = numPipes - 1;
390  (void)CloseHandle(servers[i]);
391 
392  {
393  char sndbuf[PIPE_BUFFER_SIZE] = { 0 };
394  char rcvbuf[PIPE_BUFFER_SIZE] = { 0 };
395 
396  if (ReadFile(clients[i], rcvbuf, sizeof(rcvbuf), &dwRead, NULL))
397  {
398  printf(
399  "%s: Error ReadFile on client end should have failed after CloseHandle on server\n",
400  __func__);
401  goto out;
402  }
403 
404  if (WriteFile(clients[i], sndbuf, sizeof(sndbuf), &dwWritten, NULL))
405  {
406  printf("%s: Error WriteFile on client end should have failed after CloseHandle on "
407  "server\n",
408  __func__);
409  goto out;
410  }
411  }
412  (void)CloseHandle(clients[i]);
413  numPipes--;
418  i = numPipes - 1;
419  (void)CloseHandle(clients[i]);
420 
421  {
422  char sndbuf[PIPE_BUFFER_SIZE] = { 0 };
423  char rcvbuf[PIPE_BUFFER_SIZE] = { 0 };
424 
425  if (ReadFile(servers[i], rcvbuf, sizeof(rcvbuf), &dwRead, NULL))
426  {
427  printf(
428  "%s: Error ReadFile on server end should have failed after CloseHandle on client\n",
429  __func__);
430  goto out;
431  }
432 
433  if (WriteFile(servers[i], sndbuf, sizeof(sndbuf), &dwWritten, NULL))
434  {
435  printf("%s: Error WriteFile on server end should have failed after CloseHandle on "
436  "client\n",
437  __func__);
438  goto out;
439  }
440  }
441 
442  DisconnectNamedPipe(servers[i]);
443  (void)CloseHandle(servers[i]);
444  numPipes--;
445 
446  /* Close all remaining pipes */
447  for (int i = 0; i < numPipes; i++)
448  {
449  DisconnectNamedPipe(servers[i]);
450  (void)CloseHandle(servers[i]);
451  (void)CloseHandle(clients[i]);
452  }
453 
454  bSuccess = TRUE;
455 out:
456 
457  if (!bSuccess)
458  testFailed = TRUE;
459 
460  return 0;
461 }
462 
463 int TestPipeCreateNamedPipe(int argc, char* argv[])
464 {
465  HANDLE SingleThread = NULL;
466  HANDLE ClientThread = NULL;
467  HANDLE ServerThread = NULL;
468  HANDLE hPipe = NULL;
469  WINPR_UNUSED(argc);
470  WINPR_UNUSED(argv);
471  /* Verify that CreateNamedPipe returns INVALID_HANDLE_VALUE on failure */
472  hPipe = CreateNamedPipeA(NULL, 0, 0, 0, 0, 0, 0, NULL);
473  if (hPipe != INVALID_HANDLE_VALUE)
474  {
475  printf("CreateNamedPipe unexpectedly returned %p instead of INVALID_HANDLE_VALUE (%p)\n",
476  hPipe, INVALID_HANDLE_VALUE);
477  return -1;
478  }
479 
480 #ifndef _WIN32
481  (void)signal(SIGPIPE, SIG_IGN);
482 #endif
483  if (!(ReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
484  {
485  printf("CreateEvent failure: (%" PRIu32 ")\n", GetLastError());
486  return -1;
487  }
488  if (!(SingleThread = CreateThread(NULL, 0, named_pipe_single_thread, NULL, 0, NULL)))
489  {
490  printf("CreateThread (SingleThread) failure: (%" PRIu32 ")\n", GetLastError());
491  return -1;
492  }
493  if (!(ClientThread = CreateThread(NULL, 0, named_pipe_client_thread, NULL, 0, NULL)))
494  {
495  printf("CreateThread (ClientThread) failure: (%" PRIu32 ")\n", GetLastError());
496  return -1;
497  }
498  if (!(ServerThread = CreateThread(NULL, 0, named_pipe_server_thread, NULL, 0, NULL)))
499  {
500  printf("CreateThread (ServerThread) failure: (%" PRIu32 ")\n", GetLastError());
501  return -1;
502  }
503  (void)WaitForSingleObject(SingleThread, INFINITE);
504  (void)WaitForSingleObject(ClientThread, INFINITE);
505  (void)WaitForSingleObject(ServerThread, INFINITE);
506  (void)CloseHandle(SingleThread);
507  (void)CloseHandle(ClientThread);
508  (void)CloseHandle(ServerThread);
509  return testFailed;
510 }