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 const char lpszPipeNameMt[] = "\\\\.\\pipe\\winpr_test_pipe_mt";
22static const char lpszPipeNameSt[] = "\\\\.\\pipe\\winpr_test_pipe_st";
23
24static BOOL testFailed = FALSE;
25
26static DWORD WINAPI named_pipe_client_thread(LPVOID arg)
27{
28 HANDLE hNamedPipe = nullptr;
29 BYTE* lpReadBuffer = nullptr;
30 BYTE* lpWriteBuffer = nullptr;
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 = winpr_CreateFile(lpszPipeNameMt, GENERIC_READ | GENERIC_WRITE, 0, nullptr,
38 OPEN_EXISTING, 0, nullptr);
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 nullptr) ||
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, nullptr) ||
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 BYTE* lpReadBuffer = nullptr;
99 BYTE* lpWriteBuffer = nullptr;
100 BOOL fSuccess = FALSE;
101 BOOL fConnected = FALSE;
102 DWORD nNumberOfBytesToRead = 0;
103 DWORD nNumberOfBytesToWrite = 0;
104 DWORD lpNumberOfBytesRead = 0;
105 DWORD lpNumberOfBytesWritten = 0;
106
107#if defined(UNICODE)
108 WCHAR* str = ConvertUtf8ToWCharAlloc(lpszPipeNameMt, nullptr);
109#else
110 char* str = _strdup(lpszPipeNameMt);
111#endif
112
113 HANDLE hNamedPipe =
114 CreateNamedPipe(str, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
115 PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, 0, nullptr);
116 free(str);
117 if (!hNamedPipe)
118 {
119 printf("%s: CreateNamedPipe failure: nullptr handle\n", __func__);
120 goto out;
121 }
122
123 if (hNamedPipe == INVALID_HANDLE_VALUE)
124 {
125 printf("%s: CreateNamedPipe failure: INVALID_HANDLE_VALUE\n", __func__);
126 goto out;
127 }
128
129 (void)SetEvent(ReadyEvent);
130
139 fConnected =
140 ConnectNamedPipe(hNamedPipe, nullptr) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
141
142 if (!fConnected)
143 {
144 printf("%s: ConnectNamedPipe failure\n", __func__);
145 goto out;
146 }
147
148 if (!(lpReadBuffer = (BYTE*)calloc(1, PIPE_BUFFER_SIZE)))
149 {
150 printf("%s: Error allocating read buffer\n", __func__);
151 goto out;
152 }
153
154 if (!(lpWriteBuffer = (BYTE*)malloc(PIPE_BUFFER_SIZE)))
155 {
156 printf("%s: Error allocating write buffer\n", __func__);
157 goto out;
158 }
159
160 lpNumberOfBytesRead = 0;
161 nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
162
163 if (!ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, &lpNumberOfBytesRead, nullptr) ||
164 lpNumberOfBytesRead != nNumberOfBytesToRead)
165 {
166 printf("%s: Server NamedPipe ReadFile failure\n", __func__);
167 goto out;
168 }
169
170 printf("Server ReadFile: %" PRIu32 " bytes\n", lpNumberOfBytesRead);
171 winpr_HexDump("pipe.test", WLOG_DEBUG, lpReadBuffer, lpNumberOfBytesRead);
172 lpNumberOfBytesWritten = 0;
173 nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
174 FillMemory(lpWriteBuffer, PIPE_BUFFER_SIZE, 0x45);
175
176 if (!WriteFile(hNamedPipe, lpWriteBuffer, nNumberOfBytesToWrite, &lpNumberOfBytesWritten,
177 nullptr) ||
178 lpNumberOfBytesWritten != nNumberOfBytesToWrite)
179 {
180 printf("%s: Server NamedPipe WriteFile failure\n", __func__);
181 goto out;
182 }
183
184 fSuccess = TRUE;
185out:
186 free(lpReadBuffer);
187 free(lpWriteBuffer);
188 (void)CloseHandle(hNamedPipe);
189
190 if (!fSuccess)
191 testFailed = TRUE;
192
193 ExitThread(0);
194 return 0;
195}
196
197#define TESTNUMPIPESST 16
198static DWORD WINAPI named_pipe_single_thread(LPVOID arg)
199{
200 HANDLE servers[TESTNUMPIPESST] = WINPR_C_ARRAY_INIT;
201 HANDLE clients[TESTNUMPIPESST] = WINPR_C_ARRAY_INIT;
202 DWORD dwRead = 0;
203 DWORD dwWritten = 0;
204 int numPipes = 0;
205 BOOL bSuccess = FALSE;
206 numPipes = TESTNUMPIPESST;
207 (void)WaitForSingleObject(ReadyEvent, INFINITE);
208
209 for (int i = 0; i < numPipes; i++)
210 {
211#if defined(UNICODE)
212 WCHAR* str = ConvertUtf8ToWCharAlloc(lpszPipeNameSt, nullptr);
213#else
214 char* str = _strdup(lpszPipeNameSt);
215#endif
216 servers[i] = CreateNamedPipe(
217 str, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
218 PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, 0, nullptr);
219 free(str);
220 if (!servers[i])
221 {
222 printf("%s: CreateNamedPipe #%d failed\n", __func__, i);
223 goto out;
224 }
225 }
226
227#ifndef _WIN32
228
229 for (int i = 0; i < numPipes; i++)
230 {
231 WINPR_NAMED_PIPE* p = (WINPR_NAMED_PIPE*)servers[i];
232
233 if (strcmp(lpszPipeNameSt, p->name) != 0)
234 {
235 printf("%s: Pipe name mismatch for pipe #%d ([%s] instead of [%s])\n", __func__, i,
236 p->name, lpszPipeNameSt);
237 goto out;
238 }
239
240 if (p->clientfd != -1)
241 {
242 printf("%s: Unexpected client fd value for pipe #%d (%d instead of -1)\n", __func__, i,
243 p->clientfd);
244 goto out;
245 }
246
247 if (p->serverfd < 1)
248 {
249 printf("%s: Unexpected server fd value for pipe #%d (%d is not > 0)\n", __func__, i,
250 p->serverfd);
251 goto out;
252 }
253
254 if (p->ServerMode == FALSE)
255 {
256 printf("%s: Unexpected ServerMode value for pipe #%d (0 instead of 1)\n", __func__, i);
257 goto out;
258 }
259 }
260
261#endif
262
263 for (int i = 0; i < numPipes; i++)
264 {
265 BOOL fConnected = 0;
266 if ((clients[i] = winpr_CreateFile(lpszPipeNameSt, GENERIC_READ | GENERIC_WRITE, 0, nullptr,
267 OPEN_EXISTING, 0, nullptr)) == INVALID_HANDLE_VALUE)
268 {
269 printf("%s: CreateFile #%d failed\n", __func__, i);
270 goto out;
271 }
272
281 fConnected =
282 ConnectNamedPipe(servers[i], nullptr) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
283
284 if (!fConnected)
285 {
286 printf("%s: ConnectNamedPipe #%d failed. (%" PRIu32 ")\n", __func__, i, GetLastError());
287 goto out;
288 }
289 }
290
291#ifndef _WIN32
292
293 for (int i = 0; i < numPipes; i++)
294 {
295 WINPR_NAMED_PIPE* p = servers[i];
296
297 if (p->clientfd < 1)
298 {
299 printf("%s: Unexpected client fd value for pipe #%d (%d is not > 0)\n", __func__, i,
300 p->clientfd);
301 goto out;
302 }
303
304 if (p->ServerMode)
305 {
306 printf("%s: Unexpected ServerMode value for pipe #%d (1 instead of 0)\n", __func__, i);
307 goto out;
308 }
309 }
310
311 for (int i = 0; i < numPipes; i++)
312 {
313 {
314 char sndbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
315 char rcvbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
316 /* Test writing from clients to servers */
317 (void)sprintf_s(sndbuf, sizeof(sndbuf), "CLIENT->SERVER ON PIPE #%05d", i);
318
319 if (!WriteFile(clients[i], sndbuf, sizeof(sndbuf), &dwWritten, nullptr) ||
320 dwWritten != sizeof(sndbuf))
321 {
322 printf("%s: Error writing to client end of pipe #%d\n", __func__, i);
323 goto out;
324 }
325
326 if (!ReadFile(servers[i], rcvbuf, dwWritten, &dwRead, nullptr) || dwRead != dwWritten)
327 {
328 printf("%s: Error reading on server end of pipe #%d\n", __func__, i);
329 goto out;
330 }
331
332 if (memcmp(sndbuf, rcvbuf, sizeof(sndbuf)) != 0)
333 {
334 printf("%s: Error data read on server end of pipe #%d is corrupted\n", __func__, i);
335 goto out;
336 }
337 }
338 {
339
340 char sndbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
341 char rcvbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
342 /* Test writing from servers to clients */
343
344 (void)sprintf_s(sndbuf, sizeof(sndbuf), "SERVER->CLIENT ON PIPE #%05d", i);
345
346 if (!WriteFile(servers[i], sndbuf, sizeof(sndbuf), &dwWritten, nullptr) ||
347 dwWritten != sizeof(sndbuf))
348 {
349 printf("%s: Error writing to server end of pipe #%d\n", __func__, i);
350 goto out;
351 }
352
353 if (!ReadFile(clients[i], rcvbuf, dwWritten, &dwRead, nullptr) || dwRead != dwWritten)
354 {
355 printf("%s: Error reading on client end of pipe #%d\n", __func__, i);
356 goto out;
357 }
358
359 if (memcmp(sndbuf, rcvbuf, sizeof(sndbuf)) != 0)
360 {
361 printf("%s: Error data read on client end of pipe #%d is corrupted\n", __func__, i);
362 goto out;
363 }
364 }
365 }
366
367#endif
372 int i = numPipes - 1;
373 DisconnectNamedPipe(servers[i]);
374 {
375 char sndbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
376 char rcvbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
377 if (ReadFile(clients[i], rcvbuf, sizeof(rcvbuf), &dwRead, nullptr))
378 {
379 printf("%s: Error ReadFile on client should have failed after DisconnectNamedPipe on "
380 "server\n",
381 __func__);
382 goto out;
383 }
384
385 if (WriteFile(clients[i], sndbuf, sizeof(sndbuf), &dwWritten, nullptr))
386 {
387 printf(
388 "%s: Error WriteFile on client end should have failed after DisconnectNamedPipe on "
389 "server\n",
390 __func__);
391 goto out;
392 }
393 }
394 (void)CloseHandle(servers[i]);
395 (void)CloseHandle(clients[i]);
396 numPipes--;
401 i = numPipes - 1;
402 (void)CloseHandle(servers[i]);
403
404 {
405 char sndbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
406 char rcvbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
407
408 if (ReadFile(clients[i], rcvbuf, sizeof(rcvbuf), &dwRead, nullptr))
409 {
410 printf(
411 "%s: Error ReadFile on client end should have failed after CloseHandle on server\n",
412 __func__);
413 goto out;
414 }
415
416 if (WriteFile(clients[i], sndbuf, sizeof(sndbuf), &dwWritten, nullptr))
417 {
418 printf("%s: Error WriteFile on client end should have failed after CloseHandle on "
419 "server\n",
420 __func__);
421 goto out;
422 }
423 }
424 (void)CloseHandle(clients[i]);
425 numPipes--;
430 i = numPipes - 1;
431 (void)CloseHandle(clients[i]);
432
433 {
434 char sndbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
435 char rcvbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
436
437 if (ReadFile(servers[i], rcvbuf, sizeof(rcvbuf), &dwRead, nullptr))
438 {
439 printf(
440 "%s: Error ReadFile on server end should have failed after CloseHandle on client\n",
441 __func__);
442 goto out;
443 }
444
445 if (WriteFile(servers[i], sndbuf, sizeof(sndbuf), &dwWritten, nullptr))
446 {
447 printf("%s: Error WriteFile on server end should have failed after CloseHandle on "
448 "client\n",
449 __func__);
450 goto out;
451 }
452 }
453
454 DisconnectNamedPipe(servers[i]);
455 (void)CloseHandle(servers[i]);
456 numPipes--;
457
458 /* Close all remaining pipes */
459 for (int i = 0; i < numPipes; i++)
460 {
461 DisconnectNamedPipe(servers[i]);
462 (void)CloseHandle(servers[i]);
463 (void)CloseHandle(clients[i]);
464 }
465
466 bSuccess = TRUE;
467out:
468
469 if (!bSuccess)
470 testFailed = TRUE;
471
472 return 0;
473}
474
475int TestPipeCreateNamedPipe(int argc, char* argv[])
476{
477 HANDLE SingleThread = nullptr;
478 HANDLE ClientThread = nullptr;
479 HANDLE ServerThread = nullptr;
480 HANDLE hPipe = nullptr;
481 WINPR_UNUSED(argc);
482 WINPR_UNUSED(argv);
483 /* Verify that CreateNamedPipe returns INVALID_HANDLE_VALUE on failure */
484 hPipe = CreateNamedPipeA(nullptr, 0, 0, 0, 0, 0, 0, nullptr);
485 if (hPipe != INVALID_HANDLE_VALUE)
486 {
487 printf("CreateNamedPipe unexpectedly returned %p instead of INVALID_HANDLE_VALUE (%p)\n",
488 hPipe, INVALID_HANDLE_VALUE);
489 return -1;
490 }
491
492#ifndef _WIN32
493 (void)signal(SIGPIPE, SIG_IGN);
494#endif
495 if (!(ReadyEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr)))
496 {
497 printf("CreateEvent failure: (%" PRIu32 ")\n", GetLastError());
498 return -1;
499 }
500 if (!(SingleThread = CreateThread(nullptr, 0, named_pipe_single_thread, nullptr, 0, nullptr)))
501 {
502 printf("CreateThread (SingleThread) failure: (%" PRIu32 ")\n", GetLastError());
503 return -1;
504 }
505 if (!(ClientThread = CreateThread(nullptr, 0, named_pipe_client_thread, nullptr, 0, nullptr)))
506 {
507 printf("CreateThread (ClientThread) failure: (%" PRIu32 ")\n", GetLastError());
508 return -1;
509 }
510 if (!(ServerThread = CreateThread(nullptr, 0, named_pipe_server_thread, nullptr, 0, nullptr)))
511 {
512 printf("CreateThread (ServerThread) failure: (%" PRIu32 ")\n", GetLastError());
513 return -1;
514 }
515 (void)WaitForSingleObject(SingleThread, INFINITE);
516 (void)WaitForSingleObject(ClientThread, INFINITE);
517 (void)WaitForSingleObject(ServerThread, INFINITE);
518 (void)CloseHandle(SingleThread);
519 (void)CloseHandle(ClientThread);
520 (void)CloseHandle(ServerThread);
521 return testFailed;
522}