FreeRDP
Loading...
Searching...
No Matches
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
19static HANDLE ReadyEvent;
20
21static LPTSTR lpszPipeNameMt = _T("\\\\.\\pipe\\winpr_test_pipe_mt");
22static LPTSTR lpszPipeNameSt = _T("\\\\.\\pipe\\winpr_test_pipe_st");
23
24static BOOL testFailed = FALSE;
25
26static 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;
84out:
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
96static 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;
179out:
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
192static 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;
455out:
456
457 if (!bSuccess)
458 testFailed = TRUE;
459
460 return 0;
461}
462
463int 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}