FreeRDP
Loading...
Searching...
No Matches
TestPipeCreateNamedPipeOverlapped.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/wlog.h>
9#include <winpr/print.h>
10#include <winpr/synch.h>
11#include <winpr/thread.h>
12
13#define PIPE_BUFFER_SIZE 32
14#define PIPE_TIMEOUT_MS 20000 // 20 seconds
15
16static BYTE SERVER_MESSAGE[PIPE_BUFFER_SIZE];
17static BYTE CLIENT_MESSAGE[PIPE_BUFFER_SIZE];
18
19static BOOL bClientSuccess = FALSE;
20static BOOL bServerSuccess = FALSE;
21
22static HANDLE serverReadyEvent = NULL;
23
24static LPTSTR lpszPipeName = _T("\\\\.\\pipe\\winpr_test_pipe_overlapped");
25
26static DWORD WINAPI named_pipe_client_thread(LPVOID arg)
27{
28 DWORD status = 0;
29 HANDLE hEvent = NULL;
30 HANDLE hNamedPipe = NULL;
31 BYTE* lpReadBuffer = NULL;
32 BOOL fSuccess = FALSE;
33 OVERLAPPED overlapped = { 0 };
34 DWORD nNumberOfBytesToRead = 0;
35 DWORD nNumberOfBytesToWrite = 0;
36 DWORD NumberOfBytesTransferred = 0;
37
38 WINPR_UNUSED(arg);
39
40 status = WaitForSingleObject(serverReadyEvent, PIPE_TIMEOUT_MS);
41 if (status != WAIT_OBJECT_0)
42 {
43 printf("client: failed to wait for server ready event: %" PRIu32 "\n", status);
44 goto finish;
45 }
46
47 /* 1: initialize overlapped structure */
48 if (!(hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
49 {
50 printf("client: CreateEvent failure: %" PRIu32 "\n", GetLastError());
51 goto finish;
52 }
53 overlapped.hEvent = hEvent;
54
55 /* 2: connect to server named pipe */
56
57 hNamedPipe = CreateFile(lpszPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
58 FILE_FLAG_OVERLAPPED, NULL);
59
60 if (hNamedPipe == INVALID_HANDLE_VALUE)
61 {
62 printf("client: Named Pipe CreateFile failure: %" PRIu32 "\n", GetLastError());
63 goto finish;
64 }
65
66 /* 3: write to named pipe */
67
68 nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
69 NumberOfBytesTransferred = 0;
70
71 fSuccess = WriteFile(hNamedPipe, CLIENT_MESSAGE, nNumberOfBytesToWrite, NULL, &overlapped);
72
73 if (!fSuccess)
74 fSuccess = (GetLastError() == ERROR_IO_PENDING);
75
76 if (!fSuccess)
77 {
78 printf("client: NamedPipe WriteFile failure (initial): %" PRIu32 "\n", GetLastError());
79 goto finish;
80 }
81
82 status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
83 if (status != WAIT_OBJECT_0)
84 {
85 printf("client: failed to wait for overlapped event (write): %" PRIu32 "\n", status);
86 goto finish;
87 }
88
89 fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, FALSE);
90 if (!fSuccess)
91 {
92 printf("client: NamedPipe WriteFile failure (final): %" PRIu32 "\n", GetLastError());
93 goto finish;
94 }
95 printf("client: WriteFile transferred %" PRIu32 " bytes:\n", NumberOfBytesTransferred);
96
97 /* 4: read from named pipe */
98
99 if (!(lpReadBuffer = (BYTE*)calloc(1, PIPE_BUFFER_SIZE)))
100 {
101 printf("client: Error allocating read buffer\n");
102 goto finish;
103 }
104
105 nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
106 NumberOfBytesTransferred = 0;
107
108 fSuccess = ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, NULL, &overlapped);
109
110 if (!fSuccess)
111 fSuccess = (GetLastError() == ERROR_IO_PENDING);
112
113 if (!fSuccess)
114 {
115 printf("client: NamedPipe ReadFile failure (initial): %" PRIu32 "\n", GetLastError());
116 goto finish;
117 }
118
119 status = WaitForMultipleObjects(1, &hEvent, FALSE, PIPE_TIMEOUT_MS);
120 if (status != WAIT_OBJECT_0)
121 {
122 printf("client: failed to wait for overlapped event (read): %" PRIu32 "\n", status);
123 goto finish;
124 }
125
126 fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, TRUE);
127 if (!fSuccess)
128 {
129 printf("client: NamedPipe ReadFile failure (final): %" PRIu32 "\n", GetLastError());
130 goto finish;
131 }
132
133 printf("client: ReadFile transferred %" PRIu32 " bytes:\n", NumberOfBytesTransferred);
134 winpr_HexDump("pipe.test", WLOG_DEBUG, lpReadBuffer, NumberOfBytesTransferred);
135
136 if (NumberOfBytesTransferred != PIPE_BUFFER_SIZE ||
137 memcmp(lpReadBuffer, SERVER_MESSAGE, PIPE_BUFFER_SIZE) != 0)
138 {
139 printf("client: received unexpected data from server\n");
140 goto finish;
141 }
142
143 printf("client: finished successfully\n");
144 bClientSuccess = TRUE;
145
146finish:
147 free(lpReadBuffer);
148 if (hNamedPipe)
149 (void)CloseHandle(hNamedPipe);
150 if (hEvent)
151 (void)CloseHandle(hEvent);
152
153 return 0;
154}
155
156static DWORD WINAPI named_pipe_server_thread(LPVOID arg)
157{
158 DWORD status = 0;
159 HANDLE hEvent = NULL;
160 HANDLE hNamedPipe = NULL;
161 BYTE* lpReadBuffer = NULL;
162 OVERLAPPED overlapped = { 0 };
163 BOOL fSuccess = FALSE;
164 BOOL fConnected = FALSE;
165 DWORD nNumberOfBytesToRead = 0;
166 DWORD nNumberOfBytesToWrite = 0;
167 DWORD NumberOfBytesTransferred = 0;
168
169 WINPR_UNUSED(arg);
170
171 /* 1: initialize overlapped structure */
172 if (!(hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
173 {
174 printf("server: CreateEvent failure: %" PRIu32 "\n", GetLastError());
175 (void)SetEvent(serverReadyEvent); /* unblock client thread */
176 goto finish;
177 }
178 overlapped.hEvent = hEvent;
179
180 /* 2: create named pipe and set ready event */
181
182 hNamedPipe =
183 CreateNamedPipe(lpszPipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
184 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
185 PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, 0, NULL);
186
187 if (hNamedPipe == INVALID_HANDLE_VALUE)
188 {
189 printf("server: CreateNamedPipe failure: %" PRIu32 "\n", GetLastError());
190 (void)SetEvent(serverReadyEvent); /* unblock client thread */
191 goto finish;
192 }
193
194 (void)SetEvent(serverReadyEvent);
195
196 /* 3: connect named pipe */
197
198 fConnected = ConnectNamedPipe(hNamedPipe, &overlapped);
199 status = GetLastError();
200
215 if (!fConnected)
216 fConnected = (status == ERROR_PIPE_CONNECTED);
217
218 printf("server: ConnectNamedPipe status: %" PRIu32 "\n", status);
219
220 if (!fConnected && status == ERROR_IO_PENDING)
221 {
222 DWORD dwDummy = 0;
223 printf("server: waiting up to %u ms for connection ...\n", PIPE_TIMEOUT_MS);
224 status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
225 if (status == WAIT_OBJECT_0)
226 fConnected = GetOverlappedResult(hNamedPipe, &overlapped, &dwDummy, FALSE);
227 else
228 printf("server: failed to wait for overlapped event (connect): %" PRIu32 "\n", status);
229 }
230
231 if (!fConnected)
232 {
233 printf("server: ConnectNamedPipe failed: %" PRIu32 "\n", status);
234 goto finish;
235 }
236
237 printf("server: named pipe successfully connected\n");
238
239 /* 4: read from named pipe */
240
241 if (!(lpReadBuffer = (BYTE*)calloc(1, PIPE_BUFFER_SIZE)))
242 {
243 printf("server: Error allocating read buffer\n");
244 goto finish;
245 }
246
247 nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
248 NumberOfBytesTransferred = 0;
249
250 fSuccess = ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, NULL, &overlapped);
251
252 if (!fSuccess)
253 fSuccess = (GetLastError() == ERROR_IO_PENDING);
254
255 if (!fSuccess)
256 {
257 printf("server: NamedPipe ReadFile failure (initial): %" PRIu32 "\n", GetLastError());
258 goto finish;
259 }
260
261 status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
262 if (status != WAIT_OBJECT_0)
263 {
264 printf("server: failed to wait for overlapped event (read): %" PRIu32 "\n", status);
265 goto finish;
266 }
267
268 fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, FALSE);
269 if (!fSuccess)
270 {
271 printf("server: NamedPipe ReadFile failure (final): %" PRIu32 "\n", GetLastError());
272 goto finish;
273 }
274
275 printf("server: ReadFile transferred %" PRIu32 " bytes:\n", NumberOfBytesTransferred);
276 winpr_HexDump("pipe.test", WLOG_DEBUG, lpReadBuffer, NumberOfBytesTransferred);
277
278 if (NumberOfBytesTransferred != PIPE_BUFFER_SIZE ||
279 memcmp(lpReadBuffer, CLIENT_MESSAGE, PIPE_BUFFER_SIZE) != 0)
280 {
281 printf("server: received unexpected data from client\n");
282 goto finish;
283 }
284
285 /* 5: write to named pipe */
286
287 nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
288 NumberOfBytesTransferred = 0;
289
290 fSuccess = WriteFile(hNamedPipe, SERVER_MESSAGE, nNumberOfBytesToWrite, NULL, &overlapped);
291
292 if (!fSuccess)
293 fSuccess = (GetLastError() == ERROR_IO_PENDING);
294
295 if (!fSuccess)
296 {
297 printf("server: NamedPipe WriteFile failure (initial): %" PRIu32 "\n", GetLastError());
298 goto finish;
299 }
300
301 status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
302 if (status != WAIT_OBJECT_0)
303 {
304 printf("server: failed to wait for overlapped event (write): %" PRIu32 "\n", status);
305 goto finish;
306 }
307
308 fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, FALSE);
309 if (!fSuccess)
310 {
311 printf("server: NamedPipe WriteFile failure (final): %" PRIu32 "\n", GetLastError());
312 goto finish;
313 }
314
315 printf("server: WriteFile transferred %" PRIu32 " bytes:\n", NumberOfBytesTransferred);
316 // winpr_HexDump("pipe.test", WLOG_DEBUG, lpWriteBuffer, NumberOfBytesTransferred);
317
318 bServerSuccess = TRUE;
319 printf("server: finished successfully\n");
320
321finish:
322 (void)CloseHandle(hNamedPipe);
323 (void)CloseHandle(hEvent);
324 free(lpReadBuffer);
325 return 0;
326}
327
328int TestPipeCreateNamedPipeOverlapped(int argc, char* argv[])
329{
330 HANDLE ClientThread = NULL;
331 HANDLE ServerThread = NULL;
332 int result = -1;
333 WINPR_UNUSED(argc);
334 WINPR_UNUSED(argv);
335 FillMemory(SERVER_MESSAGE, PIPE_BUFFER_SIZE, 0xAA);
336 FillMemory(CLIENT_MESSAGE, PIPE_BUFFER_SIZE, 0xBB);
337
338 if (!(serverReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
339 {
340 printf("CreateEvent failed: %" PRIu32 "\n", GetLastError());
341 goto out;
342 }
343 if (!(ClientThread = CreateThread(NULL, 0, named_pipe_client_thread, NULL, 0, NULL)))
344 {
345 printf("CreateThread (client) failed: %" PRIu32 "\n", GetLastError());
346 goto out;
347 }
348 if (!(ServerThread = CreateThread(NULL, 0, named_pipe_server_thread, NULL, 0, NULL)))
349 {
350 printf("CreateThread (server) failed: %" PRIu32 "\n", GetLastError());
351 goto out;
352 }
353
354 if (WAIT_OBJECT_0 != WaitForSingleObject(ClientThread, INFINITE))
355 {
356 printf("%s: Failed to wait for client thread: %" PRIu32 "\n", __func__, GetLastError());
357 goto out;
358 }
359 if (WAIT_OBJECT_0 != WaitForSingleObject(ServerThread, INFINITE))
360 {
361 printf("%s: Failed to wait for server thread: %" PRIu32 "\n", __func__, GetLastError());
362 goto out;
363 }
364
365 if (bClientSuccess && bServerSuccess)
366 result = 0;
367
368out:
369
370 if (ClientThread)
371 (void)CloseHandle(ClientThread);
372 if (ServerThread)
373 (void)CloseHandle(ServerThread);
374 if (serverReadyEvent)
375 (void)CloseHandle(serverReadyEvent);
376
377#ifndef _WIN32
378 if (result == 0)
379 {
380 printf("%s: Error, this test is currently expected not to succeed on this platform.\n",
381 __func__);
382 result = -1;
383 }
384 else
385 {
386 printf("%s: This test is currently expected to fail on this platform.\n", __func__);
387 result = 0;
388 }
389#endif
390
391 return result;
392}