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 = nullptr;
23
24static const char lpszPipeName[] = "\\\\.\\pipe\\winpr_test_pipe_overlapped";
25
26static DWORD WINAPI named_pipe_client_thread(LPVOID arg)
27{
28 DWORD status = 0;
29 HANDLE hEvent = nullptr;
30 HANDLE hNamedPipe = nullptr;
31 BYTE* lpReadBuffer = nullptr;
32 BOOL fSuccess = FALSE;
33 OVERLAPPED overlapped = WINPR_C_ARRAY_INIT;
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(nullptr, TRUE, FALSE, nullptr)))
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 = winpr_CreateFile(lpszPipeName, GENERIC_READ | GENERIC_WRITE, 0, nullptr,
58 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);
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, nullptr, &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, nullptr, &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 = nullptr;
160 HANDLE hNamedPipe = nullptr;
161 BYTE* lpReadBuffer = nullptr;
162 OVERLAPPED overlapped = WINPR_C_ARRAY_INIT;
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(nullptr, TRUE, FALSE, nullptr)))
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#if defined(UNICODE)
183 WCHAR* str = ConvertUtf8ToWCharAlloc(lpszPipeName, nullptr);
184#else
185 char* str = _strdup(lpszPipeName);
186#endif
187 hNamedPipe =
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);
191 free(str);
192 if (hNamedPipe == INVALID_HANDLE_VALUE)
193 {
194 printf("server: CreateNamedPipe failure: %" PRIu32 "\n", GetLastError());
195 (void)SetEvent(serverReadyEvent); /* unblock client thread */
196 goto finish;
197 }
198
199 (void)SetEvent(serverReadyEvent);
200
201 /* 3: connect named pipe */
202
203 fConnected = ConnectNamedPipe(hNamedPipe, &overlapped);
204 status = GetLastError();
205
220 if (!fConnected)
221 fConnected = (status == ERROR_PIPE_CONNECTED);
222
223 printf("server: ConnectNamedPipe status: %" PRIu32 "\n", status);
224
225 if (!fConnected && status == ERROR_IO_PENDING)
226 {
227 DWORD dwDummy = 0;
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);
232 else
233 printf("server: failed to wait for overlapped event (connect): %" PRIu32 "\n", status);
234 }
235
236 if (!fConnected)
237 {
238 printf("server: ConnectNamedPipe failed: %" PRIu32 "\n", status);
239 goto finish;
240 }
241
242 printf("server: named pipe successfully connected\n");
243
244 /* 4: read from named pipe */
245
246 if (!(lpReadBuffer = (BYTE*)calloc(1, PIPE_BUFFER_SIZE)))
247 {
248 printf("server: Error allocating read buffer\n");
249 goto finish;
250 }
251
252 nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
253 NumberOfBytesTransferred = 0;
254
255 fSuccess = ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, nullptr, &overlapped);
256
257 if (!fSuccess)
258 fSuccess = (GetLastError() == ERROR_IO_PENDING);
259
260 if (!fSuccess)
261 {
262 printf("server: NamedPipe ReadFile failure (initial): %" PRIu32 "\n", GetLastError());
263 goto finish;
264 }
265
266 status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
267 if (status != WAIT_OBJECT_0)
268 {
269 printf("server: failed to wait for overlapped event (read): %" PRIu32 "\n", status);
270 goto finish;
271 }
272
273 fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, FALSE);
274 if (!fSuccess)
275 {
276 printf("server: NamedPipe ReadFile failure (final): %" PRIu32 "\n", GetLastError());
277 goto finish;
278 }
279
280 printf("server: ReadFile transferred %" PRIu32 " bytes:\n", NumberOfBytesTransferred);
281 winpr_HexDump("pipe.test", WLOG_DEBUG, lpReadBuffer, NumberOfBytesTransferred);
282
283 if (NumberOfBytesTransferred != PIPE_BUFFER_SIZE ||
284 memcmp(lpReadBuffer, CLIENT_MESSAGE, PIPE_BUFFER_SIZE) != 0)
285 {
286 printf("server: received unexpected data from client\n");
287 goto finish;
288 }
289
290 /* 5: write to named pipe */
291
292 nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
293 NumberOfBytesTransferred = 0;
294
295 fSuccess = WriteFile(hNamedPipe, SERVER_MESSAGE, nNumberOfBytesToWrite, nullptr, &overlapped);
296
297 if (!fSuccess)
298 fSuccess = (GetLastError() == ERROR_IO_PENDING);
299
300 if (!fSuccess)
301 {
302 printf("server: NamedPipe WriteFile failure (initial): %" PRIu32 "\n", GetLastError());
303 goto finish;
304 }
305
306 status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
307 if (status != WAIT_OBJECT_0)
308 {
309 printf("server: failed to wait for overlapped event (write): %" PRIu32 "\n", status);
310 goto finish;
311 }
312
313 fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, FALSE);
314 if (!fSuccess)
315 {
316 printf("server: NamedPipe WriteFile failure (final): %" PRIu32 "\n", GetLastError());
317 goto finish;
318 }
319
320 printf("server: WriteFile transferred %" PRIu32 " bytes:\n", NumberOfBytesTransferred);
321 // winpr_HexDump("pipe.test", WLOG_DEBUG, lpWriteBuffer, NumberOfBytesTransferred);
322
323 bServerSuccess = TRUE;
324 printf("server: finished successfully\n");
325
326finish:
327 (void)CloseHandle(hNamedPipe);
328 (void)CloseHandle(hEvent);
329 free(lpReadBuffer);
330 return 0;
331}
332
333int TestPipeCreateNamedPipeOverlapped(int argc, char* argv[])
334{
335 HANDLE ClientThread = nullptr;
336 HANDLE ServerThread = nullptr;
337 int result = -1;
338 WINPR_UNUSED(argc);
339 WINPR_UNUSED(argv);
340 FillMemory(SERVER_MESSAGE, PIPE_BUFFER_SIZE, 0xAA);
341 FillMemory(CLIENT_MESSAGE, PIPE_BUFFER_SIZE, 0xBB);
342
343 if (!(serverReadyEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr)))
344 {
345 printf("CreateEvent failed: %" PRIu32 "\n", GetLastError());
346 goto out;
347 }
348 if (!(ClientThread = CreateThread(nullptr, 0, named_pipe_client_thread, nullptr, 0, nullptr)))
349 {
350 printf("CreateThread (client) failed: %" PRIu32 "\n", GetLastError());
351 goto out;
352 }
353 if (!(ServerThread = CreateThread(nullptr, 0, named_pipe_server_thread, nullptr, 0, nullptr)))
354 {
355 printf("CreateThread (server) failed: %" PRIu32 "\n", GetLastError());
356 goto out;
357 }
358
359 if (WAIT_OBJECT_0 != WaitForSingleObject(ClientThread, INFINITE))
360 {
361 printf("%s: Failed to wait for client thread: %" PRIu32 "\n", __func__, GetLastError());
362 goto out;
363 }
364 if (WAIT_OBJECT_0 != WaitForSingleObject(ServerThread, INFINITE))
365 {
366 printf("%s: Failed to wait for server thread: %" PRIu32 "\n", __func__, GetLastError());
367 goto out;
368 }
369
370 if (bClientSuccess && bServerSuccess)
371 result = 0;
372
373out:
374
375 if (ClientThread)
376 (void)CloseHandle(ClientThread);
377 if (ServerThread)
378 (void)CloseHandle(ServerThread);
379 if (serverReadyEvent)
380 (void)CloseHandle(serverReadyEvent);
381
382#ifndef _WIN32
383 if (result == 0)
384 {
385 printf("%s: Error, this test is currently expected not to succeed on this platform.\n",
386 __func__);
387 result = -1;
388 }
389 else
390 {
391 printf("%s: This test is currently expected to fail on this platform.\n", __func__);
392 result = 0;
393 }
394#endif
395
396 return result;
397}