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>
17#define PIPE_BUFFER_SIZE 32
19static HANDLE ReadyEvent;
21static const char lpszPipeNameMt[] =
"\\\\.\\pipe\\winpr_test_pipe_mt";
22static const char lpszPipeNameSt[] =
"\\\\.\\pipe\\winpr_test_pipe_st";
24static BOOL testFailed = FALSE;
26static DWORD WINAPI named_pipe_client_thread(LPVOID arg)
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);
40 if (hNamedPipe == INVALID_HANDLE_VALUE)
42 printf(
"%s: Named Pipe CreateFile failure: INVALID_HANDLE_VALUE\n", __func__);
46 if (!(lpReadBuffer = (BYTE*)malloc(PIPE_BUFFER_SIZE)))
48 printf(
"%s: Error allocating read buffer\n", __func__);
52 if (!(lpWriteBuffer = (BYTE*)malloc(PIPE_BUFFER_SIZE)))
54 printf(
"%s: Error allocating write buffer\n", __func__);
58 lpNumberOfBytesWritten = 0;
59 nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
60 FillMemory(lpWriteBuffer, PIPE_BUFFER_SIZE, 0x59);
62 if (!WriteFile(hNamedPipe, lpWriteBuffer, nNumberOfBytesToWrite, &lpNumberOfBytesWritten,
64 lpNumberOfBytesWritten != nNumberOfBytesToWrite)
66 printf(
"%s: Client NamedPipe WriteFile failure\n", __func__);
70 lpNumberOfBytesRead = 0;
71 nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
72 ZeroMemory(lpReadBuffer, PIPE_BUFFER_SIZE);
74 if (!ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, &lpNumberOfBytesRead,
nullptr) ||
75 lpNumberOfBytesRead != nNumberOfBytesToRead)
77 printf(
"%s: Client NamedPipe ReadFile failure\n", __func__);
81 printf(
"Client ReadFile: %" PRIu32
" bytes\n", lpNumberOfBytesRead);
82 winpr_HexDump(
"pipe.test", WLOG_DEBUG, lpReadBuffer, lpNumberOfBytesRead);
87 (void)CloseHandle(hNamedPipe);
96static DWORD WINAPI named_pipe_server_thread(LPVOID arg)
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;
108 WCHAR* str = ConvertUtf8ToWCharAlloc(lpszPipeNameMt,
nullptr);
110 char* str = _strdup(lpszPipeNameMt);
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);
119 printf(
"%s: CreateNamedPipe failure: nullptr handle\n", __func__);
123 if (hNamedPipe == INVALID_HANDLE_VALUE)
125 printf(
"%s: CreateNamedPipe failure: INVALID_HANDLE_VALUE\n", __func__);
129 (void)SetEvent(ReadyEvent);
140 ConnectNamedPipe(hNamedPipe,
nullptr) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
144 printf(
"%s: ConnectNamedPipe failure\n", __func__);
148 if (!(lpReadBuffer = (BYTE*)calloc(1, PIPE_BUFFER_SIZE)))
150 printf(
"%s: Error allocating read buffer\n", __func__);
154 if (!(lpWriteBuffer = (BYTE*)malloc(PIPE_BUFFER_SIZE)))
156 printf(
"%s: Error allocating write buffer\n", __func__);
160 lpNumberOfBytesRead = 0;
161 nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
163 if (!ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, &lpNumberOfBytesRead,
nullptr) ||
164 lpNumberOfBytesRead != nNumberOfBytesToRead)
166 printf(
"%s: Server NamedPipe ReadFile failure\n", __func__);
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);
176 if (!WriteFile(hNamedPipe, lpWriteBuffer, nNumberOfBytesToWrite, &lpNumberOfBytesWritten,
178 lpNumberOfBytesWritten != nNumberOfBytesToWrite)
180 printf(
"%s: Server NamedPipe WriteFile failure\n", __func__);
188 (void)CloseHandle(hNamedPipe);
197#define TESTNUMPIPESST 16
198static DWORD WINAPI named_pipe_single_thread(LPVOID arg)
200 HANDLE servers[TESTNUMPIPESST] = WINPR_C_ARRAY_INIT;
201 HANDLE clients[TESTNUMPIPESST] = WINPR_C_ARRAY_INIT;
205 BOOL bSuccess = FALSE;
206 numPipes = TESTNUMPIPESST;
207 (void)WaitForSingleObject(ReadyEvent, INFINITE);
209 for (
int i = 0; i < numPipes; i++)
212 WCHAR* str = ConvertUtf8ToWCharAlloc(lpszPipeNameSt,
nullptr);
214 char* str = _strdup(lpszPipeNameSt);
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);
222 printf(
"%s: CreateNamedPipe #%d failed\n", __func__, i);
229 for (
int i = 0; i < numPipes; i++)
231 WINPR_NAMED_PIPE* p = (WINPR_NAMED_PIPE*)servers[i];
233 if (strcmp(lpszPipeNameSt, p->name) != 0)
235 printf(
"%s: Pipe name mismatch for pipe #%d ([%s] instead of [%s])\n", __func__, i,
236 p->name, lpszPipeNameSt);
240 if (p->clientfd != -1)
242 printf(
"%s: Unexpected client fd value for pipe #%d (%d instead of -1)\n", __func__, i,
249 printf(
"%s: Unexpected server fd value for pipe #%d (%d is not > 0)\n", __func__, i,
254 if (p->ServerMode == FALSE)
256 printf(
"%s: Unexpected ServerMode value for pipe #%d (0 instead of 1)\n", __func__, i);
263 for (
int i = 0; i < numPipes; i++)
266 if ((clients[i] = winpr_CreateFile(lpszPipeNameSt, GENERIC_READ | GENERIC_WRITE, 0,
nullptr,
267 OPEN_EXISTING, 0,
nullptr)) == INVALID_HANDLE_VALUE)
269 printf(
"%s: CreateFile #%d failed\n", __func__, i);
282 ConnectNamedPipe(servers[i],
nullptr) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
286 printf(
"%s: ConnectNamedPipe #%d failed. (%" PRIu32
")\n", __func__, i, GetLastError());
293 for (
int i = 0; i < numPipes; i++)
295 WINPR_NAMED_PIPE* p = servers[i];
299 printf(
"%s: Unexpected client fd value for pipe #%d (%d is not > 0)\n", __func__, i,
306 printf(
"%s: Unexpected ServerMode value for pipe #%d (1 instead of 0)\n", __func__, i);
311 for (
int i = 0; i < numPipes; i++)
314 char sndbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
315 char rcvbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
317 (void)sprintf_s(sndbuf,
sizeof(sndbuf),
"CLIENT->SERVER ON PIPE #%05d", i);
319 if (!WriteFile(clients[i], sndbuf,
sizeof(sndbuf), &dwWritten,
nullptr) ||
320 dwWritten !=
sizeof(sndbuf))
322 printf(
"%s: Error writing to client end of pipe #%d\n", __func__, i);
326 if (!ReadFile(servers[i], rcvbuf, dwWritten, &dwRead,
nullptr) || dwRead != dwWritten)
328 printf(
"%s: Error reading on server end of pipe #%d\n", __func__, i);
332 if (memcmp(sndbuf, rcvbuf,
sizeof(sndbuf)) != 0)
334 printf(
"%s: Error data read on server end of pipe #%d is corrupted\n", __func__, i);
340 char sndbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
341 char rcvbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
344 (void)sprintf_s(sndbuf,
sizeof(sndbuf),
"SERVER->CLIENT ON PIPE #%05d", i);
346 if (!WriteFile(servers[i], sndbuf,
sizeof(sndbuf), &dwWritten,
nullptr) ||
347 dwWritten !=
sizeof(sndbuf))
349 printf(
"%s: Error writing to server end of pipe #%d\n", __func__, i);
353 if (!ReadFile(clients[i], rcvbuf, dwWritten, &dwRead,
nullptr) || dwRead != dwWritten)
355 printf(
"%s: Error reading on client end of pipe #%d\n", __func__, i);
359 if (memcmp(sndbuf, rcvbuf,
sizeof(sndbuf)) != 0)
361 printf(
"%s: Error data read on client end of pipe #%d is corrupted\n", __func__, i);
372 int i = numPipes - 1;
373 DisconnectNamedPipe(servers[i]);
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))
379 printf(
"%s: Error ReadFile on client should have failed after DisconnectNamedPipe on "
385 if (WriteFile(clients[i], sndbuf,
sizeof(sndbuf), &dwWritten,
nullptr))
388 "%s: Error WriteFile on client end should have failed after DisconnectNamedPipe on "
394 (void)CloseHandle(servers[i]);
395 (void)CloseHandle(clients[i]);
402 (void)CloseHandle(servers[i]);
405 char sndbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
406 char rcvbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
408 if (ReadFile(clients[i], rcvbuf,
sizeof(rcvbuf), &dwRead,
nullptr))
411 "%s: Error ReadFile on client end should have failed after CloseHandle on server\n",
416 if (WriteFile(clients[i], sndbuf,
sizeof(sndbuf), &dwWritten,
nullptr))
418 printf(
"%s: Error WriteFile on client end should have failed after CloseHandle on "
424 (void)CloseHandle(clients[i]);
431 (void)CloseHandle(clients[i]);
434 char sndbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
435 char rcvbuf[PIPE_BUFFER_SIZE] = WINPR_C_ARRAY_INIT;
437 if (ReadFile(servers[i], rcvbuf,
sizeof(rcvbuf), &dwRead,
nullptr))
440 "%s: Error ReadFile on server end should have failed after CloseHandle on client\n",
445 if (WriteFile(servers[i], sndbuf,
sizeof(sndbuf), &dwWritten,
nullptr))
447 printf(
"%s: Error WriteFile on server end should have failed after CloseHandle on "
454 DisconnectNamedPipe(servers[i]);
455 (void)CloseHandle(servers[i]);
459 for (
int i = 0; i < numPipes; i++)
461 DisconnectNamedPipe(servers[i]);
462 (void)CloseHandle(servers[i]);
463 (void)CloseHandle(clients[i]);
475int TestPipeCreateNamedPipe(
int argc,
char* argv[])
477 HANDLE SingleThread =
nullptr;
478 HANDLE ClientThread =
nullptr;
479 HANDLE ServerThread =
nullptr;
480 HANDLE hPipe =
nullptr;
484 hPipe = CreateNamedPipeA(
nullptr, 0, 0, 0, 0, 0, 0,
nullptr);
485 if (hPipe != INVALID_HANDLE_VALUE)
487 printf(
"CreateNamedPipe unexpectedly returned %p instead of INVALID_HANDLE_VALUE (%p)\n",
488 hPipe, INVALID_HANDLE_VALUE);
493 (void)signal(SIGPIPE, SIG_IGN);
495 if (!(ReadyEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
497 printf(
"CreateEvent failure: (%" PRIu32
")\n", GetLastError());
500 if (!(SingleThread = CreateThread(
nullptr, 0, named_pipe_single_thread,
nullptr, 0,
nullptr)))
502 printf(
"CreateThread (SingleThread) failure: (%" PRIu32
")\n", GetLastError());
505 if (!(ClientThread = CreateThread(
nullptr, 0, named_pipe_client_thread,
nullptr, 0,
nullptr)))
507 printf(
"CreateThread (ClientThread) failure: (%" PRIu32
")\n", GetLastError());
510 if (!(ServerThread = CreateThread(
nullptr, 0, named_pipe_server_thread,
nullptr, 0,
nullptr)))
512 printf(
"CreateThread (ServerThread) failure: (%" PRIu32
")\n", GetLastError());
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);