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>
17 #define PIPE_BUFFER_SIZE 32
19 static HANDLE ReadyEvent;
21 static LPTSTR lpszPipeNameMt = _T(
"\\\\.\\pipe\\winpr_test_pipe_mt");
22 static LPTSTR lpszPipeNameSt = _T(
"\\\\.\\pipe\\winpr_test_pipe_st");
24 static BOOL testFailed = FALSE;
26 static DWORD WINAPI named_pipe_client_thread(LPVOID arg)
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);
38 CreateFile(lpszPipeNameMt, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
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, NULL) ||
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);
96 static DWORD WINAPI named_pipe_server_thread(LPVOID arg)
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);
113 printf(
"%s: CreateNamedPipe failure: NULL handle\n", __func__);
117 if (hNamedPipe == INVALID_HANDLE_VALUE)
119 printf(
"%s: CreateNamedPipe failure: INVALID_HANDLE_VALUE\n", __func__);
123 (void)SetEvent(ReadyEvent);
134 ConnectNamedPipe(hNamedPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
138 printf(
"%s: ConnectNamedPipe failure\n", __func__);
142 if (!(lpReadBuffer = (BYTE*)calloc(1, PIPE_BUFFER_SIZE)))
144 printf(
"%s: Error allocating read buffer\n", __func__);
148 if (!(lpWriteBuffer = (BYTE*)malloc(PIPE_BUFFER_SIZE)))
150 printf(
"%s: Error allocating write buffer\n", __func__);
154 lpNumberOfBytesRead = 0;
155 nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
157 if (!ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, &lpNumberOfBytesRead, NULL) ||
158 lpNumberOfBytesRead != nNumberOfBytesToRead)
160 printf(
"%s: Server NamedPipe ReadFile failure\n", __func__);
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);
170 if (!WriteFile(hNamedPipe, lpWriteBuffer, nNumberOfBytesToWrite, &lpNumberOfBytesWritten,
172 lpNumberOfBytesWritten != nNumberOfBytesToWrite)
174 printf(
"%s: Server NamedPipe WriteFile failure\n", __func__);
182 (void)CloseHandle(hNamedPipe);
191 #define TESTNUMPIPESST 16
192 static DWORD WINAPI named_pipe_single_thread(LPVOID arg)
194 HANDLE servers[TESTNUMPIPESST] = { 0 };
195 HANDLE clients[TESTNUMPIPESST] = { 0 };
199 BOOL bSuccess = FALSE;
200 numPipes = TESTNUMPIPESST;
201 (void)WaitForSingleObject(ReadyEvent, INFINITE);
203 for (
int i = 0; i < numPipes; i++)
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)))
210 printf(
"%s: CreateNamedPipe #%d failed\n", __func__, i);
217 for (
int i = 0; i < numPipes; i++)
219 WINPR_NAMED_PIPE* p = (WINPR_NAMED_PIPE*)servers[i];
221 if (strcmp(lpszPipeNameSt, p->name) != 0)
223 printf(
"%s: Pipe name mismatch for pipe #%d ([%s] instead of [%s])\n", __func__, i,
224 p->name, lpszPipeNameSt);
228 if (p->clientfd != -1)
230 printf(
"%s: Unexpected client fd value for pipe #%d (%d instead of -1)\n", __func__, i,
237 printf(
"%s: Unexpected server fd value for pipe #%d (%d is not > 0)\n", __func__, i,
242 if (p->ServerMode == FALSE)
244 printf(
"%s: Unexpected ServerMode value for pipe #%d (0 instead of 1)\n", __func__, i);
251 for (
int i = 0; i < numPipes; i++)
254 if ((clients[i] = CreateFile(lpszPipeNameSt, GENERIC_READ | GENERIC_WRITE, 0, NULL,
255 OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
257 printf(
"%s: CreateFile #%d failed\n", __func__, i);
270 ConnectNamedPipe(servers[i], NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
274 printf(
"%s: ConnectNamedPipe #%d failed. (%" PRIu32
")\n", __func__, i, GetLastError());
281 for (
int i = 0; i < numPipes; i++)
283 WINPR_NAMED_PIPE* p = servers[i];
287 printf(
"%s: Unexpected client fd value for pipe #%d (%d is not > 0)\n", __func__, i,
294 printf(
"%s: Unexpected ServerMode value for pipe #%d (1 instead of 0)\n", __func__, i);
299 for (
int i = 0; i < numPipes; i++)
302 char sndbuf[PIPE_BUFFER_SIZE] = { 0 };
303 char rcvbuf[PIPE_BUFFER_SIZE] = { 0 };
305 (void)sprintf_s(sndbuf,
sizeof(sndbuf),
"CLIENT->SERVER ON PIPE #%05d", i);
307 if (!WriteFile(clients[i], sndbuf,
sizeof(sndbuf), &dwWritten, NULL) ||
308 dwWritten !=
sizeof(sndbuf))
310 printf(
"%s: Error writing to client end of pipe #%d\n", __func__, i);
314 if (!ReadFile(servers[i], rcvbuf, dwWritten, &dwRead, NULL) || dwRead != dwWritten)
316 printf(
"%s: Error reading on server end of pipe #%d\n", __func__, i);
320 if (memcmp(sndbuf, rcvbuf,
sizeof(sndbuf)) != 0)
322 printf(
"%s: Error data read on server end of pipe #%d is corrupted\n", __func__, i);
328 char sndbuf[PIPE_BUFFER_SIZE] = { 0 };
329 char rcvbuf[PIPE_BUFFER_SIZE] = { 0 };
332 (void)sprintf_s(sndbuf,
sizeof(sndbuf),
"SERVER->CLIENT ON PIPE #%05d", i);
334 if (!WriteFile(servers[i], sndbuf,
sizeof(sndbuf), &dwWritten, NULL) ||
335 dwWritten !=
sizeof(sndbuf))
337 printf(
"%s: Error writing to server end of pipe #%d\n", __func__, i);
341 if (!ReadFile(clients[i], rcvbuf, dwWritten, &dwRead, NULL) || dwRead != dwWritten)
343 printf(
"%s: Error reading on client end of pipe #%d\n", __func__, i);
347 if (memcmp(sndbuf, rcvbuf,
sizeof(sndbuf)) != 0)
349 printf(
"%s: Error data read on client end of pipe #%d is corrupted\n", __func__, i);
360 int i = numPipes - 1;
361 DisconnectNamedPipe(servers[i]);
363 char sndbuf[PIPE_BUFFER_SIZE] = { 0 };
364 char rcvbuf[PIPE_BUFFER_SIZE] = { 0 };
365 if (ReadFile(clients[i], rcvbuf,
sizeof(rcvbuf), &dwRead, NULL))
367 printf(
"%s: Error ReadFile on client should have failed after DisconnectNamedPipe on "
373 if (WriteFile(clients[i], sndbuf,
sizeof(sndbuf), &dwWritten, NULL))
376 "%s: Error WriteFile on client end should have failed after DisconnectNamedPipe on "
382 (void)CloseHandle(servers[i]);
383 (void)CloseHandle(clients[i]);
390 (void)CloseHandle(servers[i]);
393 char sndbuf[PIPE_BUFFER_SIZE] = { 0 };
394 char rcvbuf[PIPE_BUFFER_SIZE] = { 0 };
396 if (ReadFile(clients[i], rcvbuf,
sizeof(rcvbuf), &dwRead, NULL))
399 "%s: Error ReadFile on client end should have failed after CloseHandle on server\n",
404 if (WriteFile(clients[i], sndbuf,
sizeof(sndbuf), &dwWritten, NULL))
406 printf(
"%s: Error WriteFile on client end should have failed after CloseHandle on "
412 (void)CloseHandle(clients[i]);
419 (void)CloseHandle(clients[i]);
422 char sndbuf[PIPE_BUFFER_SIZE] = { 0 };
423 char rcvbuf[PIPE_BUFFER_SIZE] = { 0 };
425 if (ReadFile(servers[i], rcvbuf,
sizeof(rcvbuf), &dwRead, NULL))
428 "%s: Error ReadFile on server end should have failed after CloseHandle on client\n",
433 if (WriteFile(servers[i], sndbuf,
sizeof(sndbuf), &dwWritten, NULL))
435 printf(
"%s: Error WriteFile on server end should have failed after CloseHandle on "
442 DisconnectNamedPipe(servers[i]);
443 (void)CloseHandle(servers[i]);
447 for (
int i = 0; i < numPipes; i++)
449 DisconnectNamedPipe(servers[i]);
450 (void)CloseHandle(servers[i]);
451 (void)CloseHandle(clients[i]);
463 int TestPipeCreateNamedPipe(
int argc,
char* argv[])
465 HANDLE SingleThread = NULL;
466 HANDLE ClientThread = NULL;
467 HANDLE ServerThread = NULL;
472 hPipe = CreateNamedPipeA(NULL, 0, 0, 0, 0, 0, 0, NULL);
473 if (hPipe != INVALID_HANDLE_VALUE)
475 printf(
"CreateNamedPipe unexpectedly returned %p instead of INVALID_HANDLE_VALUE (%p)\n",
476 hPipe, INVALID_HANDLE_VALUE);
481 (void)signal(SIGPIPE, SIG_IGN);
483 if (!(ReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
485 printf(
"CreateEvent failure: (%" PRIu32
")\n", GetLastError());
488 if (!(SingleThread = CreateThread(NULL, 0, named_pipe_single_thread, NULL, 0, NULL)))
490 printf(
"CreateThread (SingleThread) failure: (%" PRIu32
")\n", GetLastError());
493 if (!(ClientThread = CreateThread(NULL, 0, named_pipe_client_thread, NULL, 0, NULL)))
495 printf(
"CreateThread (ClientThread) failure: (%" PRIu32
")\n", GetLastError());
498 if (!(ServerThread = CreateThread(NULL, 0, named_pipe_server_thread, NULL, 0, NULL)))
500 printf(
"CreateThread (ServerThread) failure: (%" PRIu32
")\n", GetLastError());
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);