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 if (!DisconnectNamedPipe(servers[i]))
374 goto out;
375 {
376 char sndbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
377 char rcvbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
378 if (ReadFile(clients[i], rcvbuf, sizeof(rcvbuf), &dwRead, nullptr))
379 {
380 printf("%s: Error ReadFile on client should have failed after DisconnectNamedPipe on "
381 "server\n",
382 __func__);
383 goto out;
384 }
385
386 if (WriteFile(clients[i], sndbuf, sizeof(sndbuf), &dwWritten, nullptr))
387 {
388 printf(
389 "%s: Error WriteFile on client end should have failed after DisconnectNamedPipe on "
390 "server\n",
391 __func__);
392 goto out;
393 }
394 }
395 if (!CloseHandle(servers[i]))
396 goto out;
397 if (!CloseHandle(clients[i]))
398 goto out;
399 numPipes--;
404 i = numPipes - 1;
405 (void)CloseHandle(servers[i]);
406
407 {
408 char sndbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
409 char rcvbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
410
411 if (ReadFile(clients[i], rcvbuf, sizeof(rcvbuf), &dwRead, nullptr))
412 {
413 printf(
414 "%s: Error ReadFile on client end should have failed after CloseHandle on server\n",
415 __func__);
416 goto out;
417 }
418
419 if (WriteFile(clients[i], sndbuf, sizeof(sndbuf), &dwWritten, nullptr))
420 {
421 printf("%s: Error WriteFile on client end should have failed after CloseHandle on "
422 "server\n",
423 __func__);
424 goto out;
425 }
426 }
427 (void)CloseHandle(clients[i]);
428 numPipes--;
433 i = numPipes - 1;
434 (void)CloseHandle(clients[i]);
435
436 {
437 char sndbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
438 char rcvbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
439
440 if (ReadFile(servers[i], rcvbuf, sizeof(rcvbuf), &dwRead, nullptr))
441 {
442 printf(
443 "%s: Error ReadFile on server end should have failed after CloseHandle on client\n",
444 __func__);
445 goto out;
446 }
447
448 if (WriteFile(servers[i], sndbuf, sizeof(sndbuf), &dwWritten, nullptr))
449 {
450 printf("%s: Error WriteFile on server end should have failed after CloseHandle on "
451 "client\n",
452 __func__);
453 goto out;
454 }
455 }
456
457 if (!DisconnectNamedPipe(servers[i]))
458 goto out;
459 if (!CloseHandle(servers[i]))
460 goto out;
461 numPipes--;
462
463 /* Close all remaining pipes */
464 for (int i = 0; i < numPipes; i++)
465 {
466 if (!DisconnectNamedPipe(servers[i]))
467 goto out;
468 if (!CloseHandle(servers[i]))
469 goto out;
470 if (!CloseHandle(clients[i]))
471 goto out;
472 }
473
474 bSuccess = TRUE;
475out:
476
477 if (!bSuccess)
478 testFailed = TRUE;
479
480 return 0;
481}
482
483int TestPipeCreateNamedPipe(int argc, char* argv[])
484{
485 HANDLE SingleThread = nullptr;
486 HANDLE ClientThread = nullptr;
487 HANDLE ServerThread = nullptr;
488 HANDLE hPipe = nullptr;
489 WINPR_UNUSED(argc);
490 WINPR_UNUSED(argv);
491 /* Verify that CreateNamedPipe returns INVALID_HANDLE_VALUE on failure */
492 hPipe = CreateNamedPipeA(nullptr, 0, 0, 0, 0, 0, 0, nullptr);
493 if (hPipe != INVALID_HANDLE_VALUE)
494 {
495 printf("CreateNamedPipe unexpectedly returned %p instead of INVALID_HANDLE_VALUE (%p)\n",
496 hPipe, INVALID_HANDLE_VALUE);
497 return -1;
498 }
499
500#ifndef _WIN32
501 (void)signal(SIGPIPE, SIG_IGN);
502#endif
503 if (!(ReadyEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr)))
504 {
505 printf("CreateEvent failure: (%" PRIu32 ")\n", GetLastError());
506 return -1;
507 }
508 if (!(SingleThread = CreateThread(nullptr, 0, named_pipe_single_thread, nullptr, 0, nullptr)))
509 {
510 printf("CreateThread (SingleThread) failure: (%" PRIu32 ")\n", GetLastError());
511 return -1;
512 }
513 if (!(ClientThread = CreateThread(nullptr, 0, named_pipe_client_thread, nullptr, 0, nullptr)))
514 {
515 printf("CreateThread (ClientThread) failure: (%" PRIu32 ")\n", GetLastError());
516 return -1;
517 }
518 if (!(ServerThread = CreateThread(nullptr, 0, named_pipe_server_thread, nullptr, 0, nullptr)))
519 {
520 printf("CreateThread (ServerThread) failure: (%" PRIu32 ")\n", GetLastError());
521 return -1;
522 }
523 (void)WaitForSingleObject(SingleThread, INFINITE);
524 (void)WaitForSingleObject(ClientThread, INFINITE);
525 (void)WaitForSingleObject(ServerThread, INFINITE);
526 (void)CloseHandle(SingleThread);
527 (void)CloseHandle(ClientThread);
528 (void)CloseHandle(ServerThread);
529 return testFailed;
530}