6#include <winpr/tchar.h>
7#include <winpr/winpr.h>
9#include <winpr/print.h>
10#include <winpr/synch.h>
11#include <winpr/thread.h>
13#define PIPE_BUFFER_SIZE 32
14#define PIPE_TIMEOUT_MS 20000
16static BYTE SERVER_MESSAGE[PIPE_BUFFER_SIZE];
17static BYTE CLIENT_MESSAGE[PIPE_BUFFER_SIZE];
19static BOOL bClientSuccess = FALSE;
20static BOOL bServerSuccess = FALSE;
22static HANDLE serverReadyEvent =
nullptr;
24static const char lpszPipeName[] =
"\\\\.\\pipe\\winpr_test_pipe_overlapped";
26static DWORD WINAPI named_pipe_client_thread(LPVOID arg)
29 HANDLE hEvent =
nullptr;
30 HANDLE hNamedPipe =
nullptr;
31 BYTE* lpReadBuffer =
nullptr;
32 BOOL fSuccess = FALSE;
34 DWORD nNumberOfBytesToRead = 0;
35 DWORD nNumberOfBytesToWrite = 0;
36 DWORD NumberOfBytesTransferred = 0;
40 status = WaitForSingleObject(serverReadyEvent, PIPE_TIMEOUT_MS);
41 if (status != WAIT_OBJECT_0)
43 printf(
"client: failed to wait for server ready event: %" PRIu32
"\n", status);
48 if (!(hEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
50 printf(
"client: CreateEvent failure: %" PRIu32
"\n", GetLastError());
53 overlapped.hEvent = hEvent;
57 hNamedPipe = winpr_CreateFile(lpszPipeName, GENERIC_READ | GENERIC_WRITE, 0,
nullptr,
58 OPEN_EXISTING, FILE_FLAG_OVERLAPPED,
nullptr);
60 if (hNamedPipe == INVALID_HANDLE_VALUE)
62 printf(
"client: Named Pipe CreateFile failure: %" PRIu32
"\n", GetLastError());
68 nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
69 NumberOfBytesTransferred = 0;
71 fSuccess = WriteFile(hNamedPipe, CLIENT_MESSAGE, nNumberOfBytesToWrite,
nullptr, &overlapped);
74 fSuccess = (GetLastError() == ERROR_IO_PENDING);
78 printf(
"client: NamedPipe WriteFile failure (initial): %" PRIu32
"\n", GetLastError());
82 status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
83 if (status != WAIT_OBJECT_0)
85 printf(
"client: failed to wait for overlapped event (write): %" PRIu32
"\n", status);
89 fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, FALSE);
92 printf(
"client: NamedPipe WriteFile failure (final): %" PRIu32
"\n", GetLastError());
95 printf(
"client: WriteFile transferred %" PRIu32
" bytes:\n", NumberOfBytesTransferred);
99 if (!(lpReadBuffer = (BYTE*)calloc(1, PIPE_BUFFER_SIZE)))
101 printf(
"client: Error allocating read buffer\n");
105 nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
106 NumberOfBytesTransferred = 0;
108 fSuccess = ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead,
nullptr, &overlapped);
111 fSuccess = (GetLastError() == ERROR_IO_PENDING);
115 printf(
"client: NamedPipe ReadFile failure (initial): %" PRIu32
"\n", GetLastError());
119 status = WaitForMultipleObjects(1, &hEvent, FALSE, PIPE_TIMEOUT_MS);
120 if (status != WAIT_OBJECT_0)
122 printf(
"client: failed to wait for overlapped event (read): %" PRIu32
"\n", status);
126 fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, TRUE);
129 printf(
"client: NamedPipe ReadFile failure (final): %" PRIu32
"\n", GetLastError());
133 printf(
"client: ReadFile transferred %" PRIu32
" bytes:\n", NumberOfBytesTransferred);
134 winpr_HexDump(
"pipe.test", WLOG_DEBUG, lpReadBuffer, NumberOfBytesTransferred);
136 if (NumberOfBytesTransferred != PIPE_BUFFER_SIZE ||
137 memcmp(lpReadBuffer, SERVER_MESSAGE, PIPE_BUFFER_SIZE) != 0)
139 printf(
"client: received unexpected data from server\n");
143 printf(
"client: finished successfully\n");
144 bClientSuccess = TRUE;
149 (void)CloseHandle(hNamedPipe);
151 (void)CloseHandle(hEvent);
156static DWORD WINAPI named_pipe_server_thread(LPVOID arg)
159 HANDLE hEvent =
nullptr;
160 HANDLE hNamedPipe =
nullptr;
161 BYTE* lpReadBuffer =
nullptr;
163 BOOL fSuccess = FALSE;
164 BOOL fConnected = FALSE;
165 DWORD nNumberOfBytesToRead = 0;
166 DWORD nNumberOfBytesToWrite = 0;
167 DWORD NumberOfBytesTransferred = 0;
172 if (!(hEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
174 printf(
"server: CreateEvent failure: %" PRIu32
"\n", GetLastError());
175 (void)SetEvent(serverReadyEvent);
178 overlapped.hEvent = hEvent;
183 WCHAR* str = ConvertUtf8ToWCharAlloc(lpszPipeName,
nullptr);
185 char* str = _strdup(lpszPipeName);
188 CreateNamedPipe(str, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
189 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
190 PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, 0,
nullptr);
192 if (hNamedPipe == INVALID_HANDLE_VALUE)
194 printf(
"server: CreateNamedPipe failure: %" PRIu32
"\n", GetLastError());
195 (void)SetEvent(serverReadyEvent);
199 (void)SetEvent(serverReadyEvent);
203 fConnected = ConnectNamedPipe(hNamedPipe, &overlapped);
204 status = GetLastError();
221 fConnected = (status == ERROR_PIPE_CONNECTED);
223 printf(
"server: ConnectNamedPipe status: %" PRIu32
"\n", status);
225 if (!fConnected && status == ERROR_IO_PENDING)
228 printf(
"server: waiting up to %u ms for connection ...\n", PIPE_TIMEOUT_MS);
229 status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
230 if (status == WAIT_OBJECT_0)
231 fConnected = GetOverlappedResult(hNamedPipe, &overlapped, &dwDummy, FALSE);
233 printf(
"server: failed to wait for overlapped event (connect): %" PRIu32
"\n", status);
238 printf(
"server: ConnectNamedPipe failed: %" PRIu32
"\n", status);
242 printf(
"server: named pipe successfully connected\n");
246 if (!(lpReadBuffer = (BYTE*)calloc(1, PIPE_BUFFER_SIZE)))
248 printf(
"server: Error allocating read buffer\n");
252 nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
253 NumberOfBytesTransferred = 0;
255 fSuccess = ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead,
nullptr, &overlapped);
258 fSuccess = (GetLastError() == ERROR_IO_PENDING);
262 printf(
"server: NamedPipe ReadFile failure (initial): %" PRIu32
"\n", GetLastError());
266 status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
267 if (status != WAIT_OBJECT_0)
269 printf(
"server: failed to wait for overlapped event (read): %" PRIu32
"\n", status);
273 fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, FALSE);
276 printf(
"server: NamedPipe ReadFile failure (final): %" PRIu32
"\n", GetLastError());
280 printf(
"server: ReadFile transferred %" PRIu32
" bytes:\n", NumberOfBytesTransferred);
281 winpr_HexDump(
"pipe.test", WLOG_DEBUG, lpReadBuffer, NumberOfBytesTransferred);
283 if (NumberOfBytesTransferred != PIPE_BUFFER_SIZE ||
284 memcmp(lpReadBuffer, CLIENT_MESSAGE, PIPE_BUFFER_SIZE) != 0)
286 printf(
"server: received unexpected data from client\n");
292 nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
293 NumberOfBytesTransferred = 0;
295 fSuccess = WriteFile(hNamedPipe, SERVER_MESSAGE, nNumberOfBytesToWrite,
nullptr, &overlapped);
298 fSuccess = (GetLastError() == ERROR_IO_PENDING);
302 printf(
"server: NamedPipe WriteFile failure (initial): %" PRIu32
"\n", GetLastError());
306 status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
307 if (status != WAIT_OBJECT_0)
309 printf(
"server: failed to wait for overlapped event (write): %" PRIu32
"\n", status);
313 fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, FALSE);
316 printf(
"server: NamedPipe WriteFile failure (final): %" PRIu32
"\n", GetLastError());
320 printf(
"server: WriteFile transferred %" PRIu32
" bytes:\n", NumberOfBytesTransferred);
323 bServerSuccess = TRUE;
324 printf(
"server: finished successfully\n");
327 (void)CloseHandle(hNamedPipe);
328 (void)CloseHandle(hEvent);
333int TestPipeCreateNamedPipeOverlapped(
int argc,
char* argv[])
335 HANDLE ClientThread =
nullptr;
336 HANDLE ServerThread =
nullptr;
340 FillMemory(SERVER_MESSAGE, PIPE_BUFFER_SIZE, 0xAA);
341 FillMemory(CLIENT_MESSAGE, PIPE_BUFFER_SIZE, 0xBB);
343 if (!(serverReadyEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
345 printf(
"CreateEvent failed: %" PRIu32
"\n", GetLastError());
348 if (!(ClientThread = CreateThread(
nullptr, 0, named_pipe_client_thread,
nullptr, 0,
nullptr)))
350 printf(
"CreateThread (client) failed: %" PRIu32
"\n", GetLastError());
353 if (!(ServerThread = CreateThread(
nullptr, 0, named_pipe_server_thread,
nullptr, 0,
nullptr)))
355 printf(
"CreateThread (server) failed: %" PRIu32
"\n", GetLastError());
359 if (WAIT_OBJECT_0 != WaitForSingleObject(ClientThread, INFINITE))
361 printf(
"%s: Failed to wait for client thread: %" PRIu32
"\n", __func__, GetLastError());
364 if (WAIT_OBJECT_0 != WaitForSingleObject(ServerThread, INFINITE))
366 printf(
"%s: Failed to wait for server thread: %" PRIu32
"\n", __func__, GetLastError());
370 if (bClientSuccess && bServerSuccess)
376 (void)CloseHandle(ClientThread);
378 (void)CloseHandle(ServerThread);
379 if (serverReadyEvent)
380 (void)CloseHandle(serverReadyEvent);
385 printf(
"%s: Error, this test is currently expected not to succeed on this platform.\n",
391 printf(
"%s: This test is currently expected to fail on this platform.\n", __func__);