ws2_32/tests: Add tests for IOCTL_AFD_POLL.
[wine.git] / dlls / ws2_32 / tests / afd.c
blob97b35e1f3ea7edf14b503eded620640c2f7f599b
1 /*
2 * Unit tests for AFD device ioctls
4 * Copyright 2021 Zebediah Figura for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <limits.h>
22 #include <stdarg.h>
23 #include "ntstatus.h"
24 #define WIN32_NO_STATUS
25 #include "windef.h"
26 #include "winternl.h"
27 #include "winioctl.h"
28 #include "winsock2.h"
29 #include "ws2tcpip.h"
30 #include "mswsock.h"
31 #include "wine/afd.h"
32 #include "wine/test.h"
34 static void tcp_socketpair(SOCKET *src, SOCKET *dst)
36 SOCKET server = INVALID_SOCKET;
37 struct sockaddr_in addr;
38 int len, ret;
40 *src = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
41 ok(*src != INVALID_SOCKET, "failed to create socket, error %u\n", WSAGetLastError());
43 server = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
44 ok(server != INVALID_SOCKET, "failed to create socket, error %u\n", WSAGetLastError());
46 memset(&addr, 0, sizeof(addr));
47 addr.sin_family = AF_INET;
48 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
49 ret = bind(server, (struct sockaddr *)&addr, sizeof(addr));
50 ok(!ret, "failed to bind socket, error %u\n", WSAGetLastError());
52 len = sizeof(addr);
53 ret = getsockname(server, (struct sockaddr *)&addr, &len);
54 ok(!ret, "failed to get address, error %u\n", WSAGetLastError());
56 ret = listen(server, 1);
57 ok(!ret, "failed to listen, error %u\n", WSAGetLastError());
59 ret = connect(*src, (struct sockaddr *)&addr, sizeof(addr));
60 ok(!ret, "failed to connect, error %u\n", WSAGetLastError());
62 len = sizeof(addr);
63 *dst = accept(server, (struct sockaddr *)&addr, &len);
64 ok(*dst != INVALID_SOCKET, "failed to accept socket, error %u\n", WSAGetLastError());
66 closesocket(server);
69 static void set_blocking(SOCKET s, ULONG blocking)
71 int ret;
72 blocking = !blocking;
73 ret = ioctlsocket(s, FIONBIO, &blocking);
74 ok(!ret, "got error %u\n", WSAGetLastError());
77 static void test_open_device(void)
79 OBJECT_BASIC_INFORMATION info;
80 OBJECT_ATTRIBUTES attr;
81 UNICODE_STRING string;
82 IO_STATUS_BLOCK io;
83 HANDLE handle;
84 SOCKET s;
85 int ret;
87 RtlInitUnicodeString(&string, L"\\Device\\Afd");
88 InitializeObjectAttributes(&attr, &string, 0, NULL, NULL);
89 ret = NtOpenFile(&handle, SYNCHRONIZE, &attr, &io, 0, 0);
90 ok(!ret, "got %#x\n", ret);
91 CloseHandle(handle);
93 RtlInitUnicodeString(&string, L"\\Device\\Afd\\");
94 InitializeObjectAttributes(&attr, &string, 0, NULL, NULL);
95 ret = NtOpenFile(&handle, SYNCHRONIZE, &attr, &io, 0, 0);
96 ok(!ret, "got %#x\n", ret);
97 CloseHandle(handle);
99 RtlInitUnicodeString(&string, L"\\Device\\Afd\\foobar");
100 InitializeObjectAttributes(&attr, &string, 0, NULL, NULL);
101 ret = NtOpenFile(&handle, SYNCHRONIZE, &attr, &io, 0, 0);
102 ok(!ret, "got %#x\n", ret);
103 CloseHandle(handle);
105 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
106 ret = NtQueryObject((HANDLE)s, ObjectBasicInformation, &info, sizeof(info), NULL);
107 ok(!ret, "got %#x\n", ret);
108 todo_wine ok(info.Attributes == OBJ_INHERIT, "got attributes %#x\n", info.Attributes);
109 todo_wine ok(info.GrantedAccess == (FILE_GENERIC_READ | FILE_GENERIC_WRITE | WRITE_DAC), "got access %#x\n", info.GrantedAccess);
111 closesocket(s);
114 #define check_poll(a, b, c) check_poll_(__LINE__, a, b, c, FALSE)
115 #define check_poll_todo(a, b, c) check_poll_(__LINE__, a, b, c, TRUE)
116 static void check_poll_(int line, SOCKET s, HANDLE event, int expect, BOOL todo)
118 struct afd_poll_params in_params = {0}, out_params = {0};
119 IO_STATUS_BLOCK io;
120 NTSTATUS ret;
122 in_params.timeout = -1000 * 10000;
123 in_params.count = 1;
124 in_params.sockets[0].socket = s;
125 in_params.sockets[0].flags = ~0;
126 in_params.sockets[0].status = 0xdeadbeef;
128 ret = NtDeviceIoControlFile((HANDLE)s, event, NULL, NULL, &io,
129 IOCTL_AFD_POLL, &in_params, sizeof(in_params), &out_params, sizeof(out_params));
130 ok_(__FILE__, line)(!ret, "got %#x\n", ret);
131 ok_(__FILE__, line)(!io.Status, "got %#x\n", io.Status);
132 ok_(__FILE__, line)(io.Information == sizeof(out_params), "got %#Ix\n", io.Information);
133 ok_(__FILE__, line)(out_params.timeout == in_params.timeout, "got timeout %I64d\n", out_params.timeout);
134 ok_(__FILE__, line)(out_params.count == 1, "got count %u\n", out_params.count);
135 ok_(__FILE__, line)(out_params.sockets[0].socket == s, "got socket %#Ix\n", out_params.sockets[0].socket);
136 todo_wine_if (todo) ok_(__FILE__, line)(out_params.sockets[0].flags == expect, "got flags %#x\n", out_params.sockets[0].flags);
137 ok_(__FILE__, line)(!out_params.sockets[0].status, "got status %#x\n", out_params.sockets[0].status);
140 static void test_poll(void)
142 const struct sockaddr_in bind_addr = {.sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_LOOPBACK)};
143 char in_buffer[offsetof(struct afd_poll_params, sockets[3])];
144 char out_buffer[offsetof(struct afd_poll_params, sockets[3])];
145 struct afd_poll_params *in_params = (struct afd_poll_params *)in_buffer;
146 struct afd_poll_params *out_params = (struct afd_poll_params *)out_buffer;
147 int large_buffer_size = 1024 * 1024;
148 SOCKET client, server, listener;
149 struct sockaddr_in addr;
150 char *large_buffer;
151 IO_STATUS_BLOCK io;
152 LARGE_INTEGER now;
153 ULONG params_size;
154 HANDLE event;
155 int ret, len;
157 large_buffer = malloc(large_buffer_size);
158 memset(in_buffer, 0, sizeof(in_buffer));
159 memset(out_buffer, 0, sizeof(out_buffer));
160 event = CreateEventW(NULL, TRUE, FALSE, NULL);
162 listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
163 ret = bind(listener, (const struct sockaddr *)&bind_addr, sizeof(bind_addr));
164 ok(!ret, "got error %u\n", WSAGetLastError());
165 ret = listen(listener, 1);
166 ok(!ret, "got error %u\n", WSAGetLastError());
167 len = sizeof(addr);
168 ret = getsockname(listener, (struct sockaddr *)&addr, &len);
169 ok(!ret, "got error %u\n", WSAGetLastError());
171 params_size = offsetof(struct afd_poll_params, sockets[1]);
172 in_params->count = 1;
174 /* out_size must be at least as large as in_size. */
176 ret = NtDeviceIoControlFile((HANDLE)listener, event, NULL, NULL, &io,
177 IOCTL_AFD_POLL, in_params, params_size, NULL, 0);
178 ok(ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret);
180 ret = NtDeviceIoControlFile((HANDLE)listener, event, NULL, NULL, &io,
181 IOCTL_AFD_POLL, NULL, 0, out_params, params_size);
182 ok(ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret);
184 ret = NtDeviceIoControlFile((HANDLE)listener, event, NULL, NULL, &io,
185 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size + 1);
186 ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret);
188 ret = NtDeviceIoControlFile((HANDLE)listener, event, NULL, NULL, &io,
189 IOCTL_AFD_POLL, in_params, params_size + 1, out_params, params_size);
190 ok(ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret);
192 ret = NtDeviceIoControlFile((HANDLE)listener, event, NULL, NULL, &io,
193 IOCTL_AFD_POLL, in_params, params_size - 1, out_params, params_size - 1);
194 ok(ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret);
196 ret = NtDeviceIoControlFile((HANDLE)listener, event, NULL, NULL, &io,
197 IOCTL_AFD_POLL, in_params, params_size + 1, out_params, params_size + 1);
198 ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret);
200 in_params->count = 0;
201 ret = NtDeviceIoControlFile((HANDLE)listener, event, NULL, NULL, &io,
202 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
203 ok(ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret);
205 /* Basic semantics of the ioctl. */
207 in_params->timeout = 0;
208 in_params->count = 1;
209 in_params->sockets[0].socket = listener;
210 in_params->sockets[0].flags = ~0;
211 in_params->sockets[0].status = 0xdeadbeef;
213 memset(out_params, 0, params_size);
214 ret = NtDeviceIoControlFile((HANDLE)listener, event, NULL, NULL, &io,
215 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
216 ok(!ret, "got %#x\n", ret);
217 ok(!io.Status, "got %#x\n", io.Status);
218 ok(io.Information == offsetof(struct afd_poll_params, sockets[0]), "got %#Ix\n", io.Information);
219 ok(!out_params->timeout, "got timeout %#I64x\n", out_params->timeout);
220 ok(!out_params->count, "got count %u\n", out_params->count);
221 ok(!out_params->sockets[0].socket, "got socket %#Ix\n", out_params->sockets[0].socket);
222 ok(!out_params->sockets[0].flags, "got flags %#x\n", out_params->sockets[0].flags);
223 ok(!out_params->sockets[0].status, "got status %#x\n", out_params->sockets[0].status);
225 NtQuerySystemTime(&now);
226 in_params->timeout = now.QuadPart;
228 ret = NtDeviceIoControlFile((HANDLE)listener, event, NULL, NULL, &io,
229 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
230 ok(ret == STATUS_PENDING, "got %#x\n", ret);
231 ret = WaitForSingleObject(event, 100);
232 ok(!ret, "got %#x\n", ret);
233 ok(io.Status == STATUS_TIMEOUT, "got %#x\n", io.Status);
234 ok(io.Information == offsetof(struct afd_poll_params, sockets[0]), "got %#Ix\n", io.Information);
235 ok(out_params->timeout == now.QuadPart, "got timeout %#I64x\n", out_params->timeout);
236 ok(!out_params->count, "got count %u\n", out_params->count);
238 in_params->timeout = -1000 * 10000;
240 ret = NtDeviceIoControlFile((HANDLE)listener, event, NULL, NULL, &io,
241 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
242 ok(ret == STATUS_PENDING, "got %#x\n", ret);
244 client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
245 set_blocking(client, FALSE);
246 ret = connect(client, (struct sockaddr *)&addr, sizeof(addr));
247 ok(!ret || WSAGetLastError() == WSAEWOULDBLOCK, "got error %u\n", WSAGetLastError());
249 ret = WaitForSingleObject(event, 100);
250 ok(!ret, "got %#x\n", ret);
251 ok(!io.Status, "got %#x\n", io.Status);
252 ok(io.Information == offsetof(struct afd_poll_params, sockets[1]), "got %#Ix\n", io.Information);
253 ok(out_params->timeout == -1000 * 10000, "got timeout %#I64x\n", out_params->timeout);
254 ok(out_params->count == 1, "got count %u\n", out_params->count);
255 ok(out_params->sockets[0].socket == listener, "got socket %#Ix\n", out_params->sockets[0].socket);
256 ok(out_params->sockets[0].flags == AFD_POLL_ACCEPT, "got flags %#x\n", out_params->sockets[0].flags);
257 ok(!out_params->sockets[0].status, "got status %#x\n", out_params->sockets[0].status);
259 ret = NtDeviceIoControlFile((HANDLE)listener, event, NULL, NULL, &io,
260 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
261 ok(!ret, "got %#x\n", ret);
262 ok(!io.Status, "got %#x\n", io.Status);
263 ok(io.Information == offsetof(struct afd_poll_params, sockets[1]), "got %#Ix\n", io.Information);
264 ok(out_params->timeout == -1000 * 10000, "got timeout %#I64x\n", out_params->timeout);
265 ok(out_params->count == 1, "got count %u\n", out_params->count);
266 ok(out_params->sockets[0].socket == listener, "got socket %#Ix\n", out_params->sockets[0].socket);
267 ok(out_params->sockets[0].flags == AFD_POLL_ACCEPT, "got flags %#x\n", out_params->sockets[0].flags);
268 ok(!out_params->sockets[0].status, "got status %#x\n", out_params->sockets[0].status);
270 in_params->timeout = now.QuadPart;
271 in_params->sockets[0].flags = (~0) & ~AFD_POLL_ACCEPT;
273 ret = NtDeviceIoControlFile((HANDLE)listener, event, NULL, NULL, &io,
274 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
275 ok(ret == STATUS_PENDING, "got %#x\n", ret);
276 ret = WaitForSingleObject(event, 100);
277 ok(!ret, "got %#x\n", ret);
278 ok(io.Status == STATUS_TIMEOUT, "got %#x\n", io.Status);
279 ok(io.Information == offsetof(struct afd_poll_params, sockets[0]), "got %#Ix\n", io.Information);
280 ok(!out_params->count, "got count %u\n", out_params->count);
282 server = accept(listener, NULL, NULL);
283 ok(server != -1, "got error %u\n", WSAGetLastError());
284 set_blocking(server, FALSE);
286 /* Test flags exposed by connected sockets. */
288 check_poll(client, event, AFD_POLL_WRITE | AFD_POLL_CONNECT);
289 check_poll(server, event, AFD_POLL_WRITE | AFD_POLL_CONNECT);
291 /* It is valid to poll on a socket other than the one passed to
292 * NtDeviceIoControlFile(). */
294 in_params->count = 1;
295 in_params->sockets[0].socket = server;
296 in_params->sockets[0].flags = ~0;
298 ret = NtDeviceIoControlFile((HANDLE)listener, event, NULL, NULL, &io,
299 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
300 ok(!ret, "got %#x\n", ret);
301 ok(!io.Status, "got %#x\n", io.Status);
302 ok(io.Information == offsetof(struct afd_poll_params, sockets[1]), "got %#Ix\n", io.Information);
303 ok(out_params->count == 1, "got count %u\n", out_params->count);
304 ok(out_params->sockets[0].socket == server, "got socket %#Ix\n", out_params->sockets[0].socket);
305 ok(out_params->sockets[0].flags == (AFD_POLL_WRITE | AFD_POLL_CONNECT),
306 "got flags %#x\n", out_params->sockets[0].flags);
307 ok(!out_params->sockets[0].status, "got status %#x\n", out_params->sockets[0].status);
309 /* Test sending data. */
311 ret = send(server, "data", 5, 0);
312 ok(ret == 5, "got %d\n", ret);
314 check_poll(client, event, AFD_POLL_WRITE | AFD_POLL_CONNECT | AFD_POLL_READ);
315 check_poll(server, event, AFD_POLL_WRITE | AFD_POLL_CONNECT);
317 while (send(server, large_buffer, large_buffer_size, 0) == large_buffer_size);
319 check_poll(client, event, AFD_POLL_WRITE | AFD_POLL_CONNECT | AFD_POLL_READ);
320 check_poll(server, event, AFD_POLL_CONNECT);
322 /* Test sending out-of-band data. */
324 ret = send(client, "a", 1, MSG_OOB);
325 ok(ret == 1, "got %d\n", ret);
327 check_poll(client, event, AFD_POLL_WRITE | AFD_POLL_CONNECT | AFD_POLL_READ);
328 check_poll(server, event, AFD_POLL_CONNECT | AFD_POLL_OOB);
330 ret = recv(server, large_buffer, 1, MSG_OOB);
331 ok(ret == 1, "got %d\n", ret);
333 check_poll(client, event, AFD_POLL_WRITE | AFD_POLL_CONNECT | AFD_POLL_READ);
334 check_poll(server, event, AFD_POLL_CONNECT);
336 ret = 1;
337 ret = setsockopt(server, SOL_SOCKET, SO_OOBINLINE, (char *)&ret, sizeof(ret));
338 ok(!ret, "got error %u\n", WSAGetLastError());
340 ret = send(client, "a", 1, MSG_OOB);
341 ok(ret == 1, "got %d\n", ret);
343 check_poll(client, event, AFD_POLL_WRITE | AFD_POLL_CONNECT | AFD_POLL_READ);
344 check_poll(server, event, AFD_POLL_CONNECT | AFD_POLL_READ);
346 closesocket(client);
347 closesocket(server);
349 /* Test shutdown. */
351 client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
352 ret = connect(client, (struct sockaddr *)&addr, sizeof(addr));
353 ok(!ret, "got error %u\n", WSAGetLastError());
354 server = accept(listener, NULL, NULL);
355 ok(server != -1, "got error %u\n", WSAGetLastError());
357 ret = shutdown(client, SD_RECEIVE);
358 ok(!ret, "got error %u\n", WSAGetLastError());
360 check_poll(client, event, AFD_POLL_WRITE | AFD_POLL_CONNECT);
361 check_poll(server, event, AFD_POLL_WRITE | AFD_POLL_CONNECT);
363 ret = shutdown(client, SD_SEND);
364 ok(!ret, "got error %u\n", WSAGetLastError());
366 check_poll(client, event, AFD_POLL_WRITE | AFD_POLL_CONNECT);
367 check_poll(server, event, AFD_POLL_WRITE | AFD_POLL_CONNECT | AFD_POLL_HUP);
369 closesocket(client);
370 closesocket(server);
372 /* Test shutdown with data in the pipe. */
374 client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
375 ret = connect(client, (struct sockaddr *)&addr, sizeof(addr));
376 ok(!ret, "got error %u\n", WSAGetLastError());
377 server = accept(listener, NULL, NULL);
378 ok(server != -1, "got error %u\n", WSAGetLastError());
380 ret = send(client, "data", 5, 0);
381 ok(ret == 5, "got %d\n", ret);
383 check_poll(client, event, AFD_POLL_WRITE | AFD_POLL_CONNECT);
384 check_poll(server, event, AFD_POLL_WRITE | AFD_POLL_CONNECT | AFD_POLL_READ);
386 ret = shutdown(client, SD_SEND);
387 ok(!ret, "got error %u\n", WSAGetLastError());
389 check_poll(client, event, AFD_POLL_WRITE | AFD_POLL_CONNECT);
390 check_poll_todo(server, event, AFD_POLL_WRITE | AFD_POLL_CONNECT | AFD_POLL_READ | AFD_POLL_HUP);
392 /* Test closing a socket while polling on it. Note that AFD_POLL_CLOSE
393 * is always returned, regardless of whether it's polled for. */
395 in_params->timeout = -1000 * 10000;
396 in_params->count = 1;
397 in_params->sockets[0].socket = client;
398 in_params->sockets[0].flags = 0;
400 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
401 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
402 ok(ret == STATUS_PENDING, "got %#x\n", ret);
404 closesocket(client);
406 ret = WaitForSingleObject(event, 100);
407 ok(!ret, "got %#x\n", ret);
408 ok(!io.Status, "got %#x\n", io.Status);
409 ok(io.Information == offsetof(struct afd_poll_params, sockets[1]), "got %#Ix\n", io.Information);
410 ok(out_params->count == 1, "got count %u\n", out_params->count);
411 ok(out_params->sockets[0].socket == client, "got socket %#Ix\n", out_params->sockets[0].socket);
412 ok(out_params->sockets[0].flags == AFD_POLL_CLOSE,
413 "got flags %#x\n", out_params->sockets[0].flags);
414 ok(!out_params->sockets[0].status, "got status %#x\n", out_params->sockets[0].status);
416 closesocket(server);
418 /* Test a failed connection.
420 * The following poll works even where the equivalent WSAPoll() call fails.
421 * However, it can take over 2 seconds to complete on the testbot. */
423 if (winetest_interactive)
425 client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
426 set_blocking(client, FALSE);
428 in_params->timeout = -10000 * 10000;
429 in_params->count = 1;
430 in_params->sockets[0].socket = client;
431 in_params->sockets[0].flags = ~0;
433 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
434 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
435 ok(ret == STATUS_PENDING, "got %#x\n", ret);
437 addr.sin_port = 255;
438 ret = connect(client, (struct sockaddr *)&addr, sizeof(addr));
439 ok(!ret || WSAGetLastError() == WSAEWOULDBLOCK, "got error %u\n", WSAGetLastError());
441 ret = WaitForSingleObject(event, 10000);
442 ok(!ret, "got %#x\n", ret);
443 ok(!io.Status, "got %#x\n", io.Status);
444 ok(io.Information == offsetof(struct afd_poll_params, sockets[1]), "got %#Ix\n", io.Information);
445 ok(out_params->count == 1, "got count %u\n", out_params->count);
446 ok(out_params->sockets[0].socket == client, "got socket %#Ix\n", out_params->sockets[0].socket);
447 ok(out_params->sockets[0].flags == AFD_POLL_CONNECT_ERR, "got flags %#x\n", out_params->sockets[0].flags);
448 ok(out_params->sockets[0].status == STATUS_CONNECTION_REFUSED, "got status %#x\n", out_params->sockets[0].status);
450 closesocket(client);
453 /* Test supplying multiple handles to the ioctl. */
455 len = sizeof(addr);
456 ret = getsockname(listener, (struct sockaddr *)&addr, &len);
457 ok(!ret, "got error %u\n", WSAGetLastError());
459 client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
460 ret = connect(client, (struct sockaddr *)&addr, sizeof(addr));
461 ok(!ret, "got error %u\n", WSAGetLastError());
462 server = accept(listener, NULL, NULL);
463 ok(server != -1, "got error %u\n", WSAGetLastError());
465 in_params->count = 2;
466 in_params->sockets[0].socket = client;
467 in_params->sockets[0].flags = AFD_POLL_READ;
468 in_params->sockets[1].socket = server;
469 in_params->sockets[1].flags = AFD_POLL_READ;
471 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
472 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
473 ok(ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret);
475 params_size = offsetof(struct afd_poll_params, sockets[2]);
477 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
478 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
479 ok(ret == STATUS_PENDING, "got %#x\n", ret);
481 ret = send(client, "data", 5, 0);
482 ok(ret == 5, "got %d\n", ret);
484 ret = WaitForSingleObject(event, 100);
485 ok(!ret, "got %#x\n", ret);
486 ok(!io.Status, "got %#x\n", io.Status);
487 ok(io.Information == offsetof(struct afd_poll_params, sockets[1]), "got %#Ix\n", io.Information);
488 ok(out_params->count == 1, "got count %u\n", out_params->count);
489 ok(out_params->sockets[0].socket == server, "got socket %#Ix\n", out_params->sockets[0].socket);
490 ok(out_params->sockets[0].flags == AFD_POLL_READ, "got flags %#x\n", out_params->sockets[0].flags);
491 ok(!out_params->sockets[0].status, "got status %#x\n", out_params->sockets[0].status);
493 in_params->count = 2;
494 in_params->sockets[0].socket = client;
495 in_params->sockets[0].flags = AFD_POLL_READ | AFD_POLL_WRITE;
496 in_params->sockets[1].socket = server;
497 in_params->sockets[1].flags = AFD_POLL_READ | AFD_POLL_WRITE;
499 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
500 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
501 ok(!ret, "got %#x\n", ret);
502 ok(!io.Status, "got %#x\n", io.Status);
503 ok(io.Information == offsetof(struct afd_poll_params, sockets[2]), "got %#Ix\n", io.Information);
504 ok(out_params->count == 2, "got count %u\n", out_params->count);
505 ok(out_params->sockets[0].socket == client, "got socket %#Ix\n", out_params->sockets[0].socket);
506 ok(out_params->sockets[0].flags == AFD_POLL_WRITE, "got flags %#x\n", out_params->sockets[0].flags);
507 ok(!out_params->sockets[0].status, "got status %#x\n", out_params->sockets[0].status);
508 ok(out_params->sockets[1].socket == server, "got socket %#Ix\n", out_params->sockets[1].socket);
509 ok(out_params->sockets[1].flags == (AFD_POLL_READ | AFD_POLL_WRITE),
510 "got flags %#x\n", out_params->sockets[1].flags);
511 ok(!out_params->sockets[1].status, "got status %#x\n", out_params->sockets[1].status);
513 in_params->count = 2;
514 in_params->sockets[0].socket = client;
515 in_params->sockets[0].flags = AFD_POLL_READ | AFD_POLL_WRITE;
516 in_params->sockets[1].socket = server;
517 in_params->sockets[1].flags = AFD_POLL_READ | AFD_POLL_WRITE;
519 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
520 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
521 ok(!ret, "got %#x\n", ret);
522 ok(!io.Status, "got %#x\n", io.Status);
523 ok(io.Information == offsetof(struct afd_poll_params, sockets[2]), "got %#Ix\n", io.Information);
524 ok(out_params->count == 2, "got count %u\n", out_params->count);
525 ok(out_params->sockets[0].socket == client, "got socket %#Ix\n", out_params->sockets[0].socket);
526 ok(out_params->sockets[0].flags == AFD_POLL_WRITE, "got flags %#x\n", out_params->sockets[0].flags);
527 ok(!out_params->sockets[0].status, "got status %#x\n", out_params->sockets[0].status);
528 ok(out_params->sockets[1].socket == server, "got socket %#Ix\n", out_params->sockets[1].socket);
529 ok(out_params->sockets[1].flags == (AFD_POLL_READ | AFD_POLL_WRITE),
530 "got flags %#x\n", out_params->sockets[1].flags);
531 ok(!out_params->sockets[1].status, "got status %#x\n", out_params->sockets[1].status);
533 /* Close a socket while polling on another. */
535 in_params->timeout = -100 * 10000;
536 in_params->count = 1;
537 in_params->sockets[0].socket = client;
538 in_params->sockets[0].flags = AFD_POLL_READ;
539 params_size = offsetof(struct afd_poll_params, sockets[1]);
541 ret = NtDeviceIoControlFile((HANDLE)server, event, NULL, NULL, &io,
542 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
543 ok(ret == STATUS_PENDING, "got %#x\n", ret);
545 closesocket(server);
547 ret = WaitForSingleObject(event, 1000);
548 ok(!ret, "got %#x\n", ret);
549 todo_wine ok(io.Status == STATUS_TIMEOUT, "got %#x\n", io.Status);
550 todo_wine ok(io.Information == offsetof(struct afd_poll_params, sockets[0]), "got %#Ix\n", io.Information);
551 todo_wine ok(!out_params->count, "got count %u\n", out_params->count);
553 closesocket(client);
555 closesocket(listener);
557 /* Test UDP sockets. */
559 client = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
560 server = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
562 check_poll(client, event, AFD_POLL_WRITE);
563 check_poll(server, event, AFD_POLL_WRITE);
565 ret = bind(client, (const struct sockaddr *)&bind_addr, sizeof(bind_addr));
566 ok(!ret, "got error %u\n", WSAGetLastError());
567 len = sizeof(addr);
568 ret = getsockname(listener, (struct sockaddr *)&addr, &len);
569 ok(!ret, "got error %u\n", WSAGetLastError());
571 check_poll(client, event, AFD_POLL_WRITE);
572 check_poll(server, event, AFD_POLL_WRITE);
574 in_params->timeout = -1000 * 10000;
575 in_params->count = 1;
576 in_params->sockets[0].socket = client;
577 in_params->sockets[0].flags = (~0) & ~AFD_POLL_WRITE;
578 params_size = offsetof(struct afd_poll_params, sockets[1]);
580 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
581 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
582 ok(ret == STATUS_PENDING, "got %#x\n", ret);
584 ret = sendto(server, "data", 5, 0, (struct sockaddr *)&addr, sizeof(addr));
585 ok(ret == 5, "got %d\n", ret);
587 ret = WaitForSingleObject(event, 100);
588 ok(!ret, "got %#x\n", ret);
589 ok(!io.Status, "got %#x\n", io.Status);
590 ok(io.Information == offsetof(struct afd_poll_params, sockets[1]), "got %#Ix\n", io.Information);
591 ok(out_params->count == 1, "got count %u\n", out_params->count);
592 ok(out_params->sockets[0].socket == client, "got socket %#Ix\n", out_params->sockets[0].socket);
593 ok(out_params->sockets[0].flags == AFD_POLL_READ, "got flags %#x\n", out_params->sockets[0].flags);
594 ok(!out_params->sockets[0].status, "got status %#x\n", out_params->sockets[0].status);
596 closesocket(client);
597 closesocket(server);
599 /* Passing any invalid sockets yields STATUS_INVALID_HANDLE.
601 * Note however that WSAPoll() happily accepts invalid sockets. It seems
602 * user-side cached data is used: closing a handle with CloseHandle() before
603 * passing it to WSAPoll() yields ENOTSOCK. */
605 tcp_socketpair(&client, &server);
607 in_params->count = 2;
608 in_params->sockets[0].socket = 0xabacab;
609 in_params->sockets[0].flags = AFD_POLL_READ | AFD_POLL_WRITE;
610 in_params->sockets[1].socket = client;
611 in_params->sockets[1].flags = AFD_POLL_READ | AFD_POLL_WRITE;
612 params_size = offsetof(struct afd_poll_params, sockets[2]);
614 memset(&io, 0, sizeof(io));
615 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
616 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
617 ok(ret == STATUS_INVALID_HANDLE, "got %#x\n", ret);
618 todo_wine ok(!io.Status, "got %#x\n", io.Status);
619 ok(!io.Information, "got %#Ix\n", io.Information);
621 /* Test passing the same handle twice. */
623 in_params->count = 3;
624 in_params->sockets[0].socket = client;
625 in_params->sockets[0].flags = AFD_POLL_READ | AFD_POLL_WRITE;
626 in_params->sockets[1].socket = client;
627 in_params->sockets[1].flags = AFD_POLL_READ | AFD_POLL_WRITE;
628 in_params->sockets[2].socket = client;
629 in_params->sockets[2].flags = AFD_POLL_READ | AFD_POLL_WRITE | AFD_POLL_CONNECT;
630 params_size = offsetof(struct afd_poll_params, sockets[3]);
632 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
633 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
634 ok(!ret, "got %#x\n", ret);
635 ok(!io.Status, "got %#x\n", io.Status);
636 ok(io.Information == offsetof(struct afd_poll_params, sockets[3]), "got %#Ix\n", io.Information);
637 ok(out_params->count == 3, "got count %u\n", out_params->count);
638 ok(out_params->sockets[0].socket == client, "got socket %#Ix\n", out_params->sockets[0].socket);
639 ok(out_params->sockets[0].flags == AFD_POLL_WRITE, "got flags %#x\n", out_params->sockets[0].flags);
640 ok(!out_params->sockets[0].status, "got status %#x\n", out_params->sockets[0].status);
641 ok(out_params->sockets[1].socket == client, "got socket %#Ix\n", out_params->sockets[1].socket);
642 ok(out_params->sockets[1].flags == AFD_POLL_WRITE, "got flags %#x\n", out_params->sockets[1].flags);
643 ok(!out_params->sockets[1].status, "got status %#x\n", out_params->sockets[1].status);
644 ok(out_params->sockets[2].socket == client, "got socket %#Ix\n", out_params->sockets[2].socket);
645 ok(out_params->sockets[2].flags == (AFD_POLL_WRITE | AFD_POLL_CONNECT),
646 "got flags %#x\n", out_params->sockets[2].flags);
647 ok(!out_params->sockets[2].status, "got status %#x\n", out_params->sockets[2].status);
649 in_params->count = 2;
650 in_params->sockets[0].socket = client;
651 in_params->sockets[0].flags = AFD_POLL_READ;
652 in_params->sockets[1].socket = client;
653 in_params->sockets[1].flags = AFD_POLL_READ;
654 params_size = offsetof(struct afd_poll_params, sockets[2]);
656 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
657 IOCTL_AFD_POLL, in_params, params_size, out_params, params_size);
658 ok(ret == STATUS_PENDING, "got %#x\n", ret);
660 ret = send(server, "data", 5, 0);
661 ok(ret == 5, "got %d\n", ret);
663 ret = WaitForSingleObject(event, 100);
664 ok(!ret, "got %#x\n", ret);
665 ok(!io.Status, "got %#x\n", io.Status);
666 ok(io.Information == offsetof(struct afd_poll_params, sockets[1]), "got %#Ix\n", io.Information);
667 ok(out_params->count == 1, "got count %u\n", out_params->count);
668 ok(out_params->sockets[0].socket == client, "got socket %#Ix\n", out_params->sockets[0].socket);
669 ok(out_params->sockets[0].flags == AFD_POLL_READ, "got flags %#x\n", out_params->sockets[0].flags);
670 ok(!out_params->sockets[0].status, "got status %#x\n", out_params->sockets[0].status);
672 closesocket(client);
673 closesocket(server);
675 CloseHandle(event);
676 free(large_buffer);
679 static void test_poll_completion_port(void)
681 struct afd_poll_params params = {0};
682 LARGE_INTEGER zero = {{0}};
683 SOCKET client, server;
684 ULONG_PTR key, value;
685 IO_STATUS_BLOCK io;
686 HANDLE event, port;
687 int ret;
689 event = CreateEventW(NULL, TRUE, FALSE, NULL);
690 tcp_socketpair(&client, &server);
691 port = CreateIoCompletionPort((HANDLE)client, NULL, 0, 0);
693 params.timeout = -100 * 10000;
694 params.count = 1;
695 params.sockets[0].socket = client;
696 params.sockets[0].flags = AFD_POLL_WRITE;
697 params.sockets[0].status = 0xdeadbeef;
699 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
700 IOCTL_AFD_POLL, &params, sizeof(params), &params, sizeof(params));
701 ok(!ret, "got %#x\n", ret);
703 ret = NtRemoveIoCompletion(port, &key, &value, &io, &zero);
704 ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);
706 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, (void *)0xdeadbeef, &io,
707 IOCTL_AFD_POLL, &params, sizeof(params), &params, sizeof(params));
708 ok(!ret, "got %#x\n", ret);
710 ret = NtRemoveIoCompletion(port, &key, &value, &io, &zero);
711 ok(!ret, "got %#x\n", ret);
712 ok(!key, "got key %#Ix\n", key);
713 ok(value == 0xdeadbeef, "got value %#Ix\n", value);
715 params.timeout = 0;
716 params.count = 1;
717 params.sockets[0].socket = client;
718 params.sockets[0].flags = AFD_POLL_READ;
719 params.sockets[0].status = 0xdeadbeef;
721 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, (void *)0xdeadbeef, &io,
722 IOCTL_AFD_POLL, &params, sizeof(params), &params, sizeof(params));
723 ok(!ret, "got %#x\n", ret);
725 ret = NtRemoveIoCompletion(port, &key, &value, &io, &zero);
726 ok(!ret, "got %#x\n", ret);
727 ok(!key, "got key %#Ix\n", key);
728 ok(value == 0xdeadbeef, "got value %#Ix\n", value);
730 /* Close a socket while polling on another. */
732 params.timeout = -100 * 10000;
733 params.count = 1;
734 params.sockets[0].socket = server;
735 params.sockets[0].flags = AFD_POLL_READ;
736 params.sockets[0].status = 0xdeadbeef;
738 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, (void *)0xdeadbeef, &io,
739 IOCTL_AFD_POLL, &params, sizeof(params), &params, sizeof(params));
740 ok(ret == STATUS_PENDING, "got %#x\n", ret);
742 closesocket(client);
744 ret = WaitForSingleObject(event, 1000);
745 ok(!ret, "got %#x\n", ret);
746 todo_wine ok(io.Status == STATUS_TIMEOUT, "got %#x\n", io.Status);
747 todo_wine ok(io.Information == offsetof(struct afd_poll_params, sockets[0]), "got %#Ix\n", io.Information);
748 todo_wine ok(!params.count, "got count %u\n", params.count);
750 ret = NtRemoveIoCompletion(port, &key, &value, &io, &zero);
751 ok(!ret, "got %#x\n", ret);
752 ok(!key, "got key %#Ix\n", key);
753 ok(value == 0xdeadbeef, "got value %#Ix\n", value);
755 CloseHandle(port);
756 closesocket(server);
757 CloseHandle(event);
760 static void test_recv(void)
762 const struct sockaddr_in bind_addr = {.sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_LOOPBACK)};
763 struct afd_recv_params params = {0};
764 SOCKET client, server, listener;
765 struct sockaddr addr;
766 IO_STATUS_BLOCK io;
767 WSABUF wsabufs[2];
768 char buffer[8];
769 HANDLE event;
770 int ret, len;
772 event = CreateEventW(NULL, TRUE, FALSE, NULL);
774 listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
775 ret = bind(listener, (const struct sockaddr *)&bind_addr, sizeof(bind_addr));
776 ok(!ret, "got error %u\n", WSAGetLastError());
777 ret = listen(listener, 1);
778 ok(!ret, "got error %u\n", WSAGetLastError());
779 len = sizeof(addr);
780 ret = getsockname(listener, (struct sockaddr *)&addr, &len);
781 ok(!ret, "got error %u\n", WSAGetLastError());
783 memset(&io, 0, sizeof(io));
784 ret = NtDeviceIoControlFile((HANDLE)listener, event, NULL, NULL, &io, IOCTL_AFD_RECV, NULL, 0, NULL, 0);
785 todo_wine ok(ret == STATUS_INVALID_CONNECTION, "got %#x\n", ret);
786 todo_wine ok(!io.Status, "got status %#x\n", io.Status);
787 ok(!io.Information, "got information %#Ix\n", io.Information);
789 client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
790 ret = connect(client, (struct sockaddr *)&addr, sizeof(addr));
791 ok(!ret, "got error %u\n", WSAGetLastError());
792 server = accept(listener, NULL, NULL);
793 ok(server != -1, "got error %u\n", WSAGetLastError());
795 memset(&io, 0, sizeof(io));
796 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io, IOCTL_AFD_RECV, NULL, 0, NULL, 0);
797 ok(ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret);
798 todo_wine ok(!io.Status, "got status %#x\n", io.Status);
799 ok(!io.Information, "got information %#Ix\n", io.Information);
801 wsabufs[0].len = sizeof(buffer);
802 wsabufs[0].buf = buffer;
803 params.buffers = wsabufs;
804 params.count = 1;
805 params.msg_flags = AFD_MSG_NOT_OOB;
807 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
808 IOCTL_AFD_RECV, &params, sizeof(params) - 1, NULL, 0);
809 ok(ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret);
811 memset(&io, 0, sizeof(io));
812 memset(buffer, 0xcc, sizeof(buffer));
813 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
814 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
815 ok(ret == STATUS_PENDING, "got %#x\n", ret);
816 ok(!io.Status, "got status %#x\n", io.Status);
817 ok(!io.Information, "got information %#Ix\n", io.Information);
819 /* These structures need not remain valid. */
820 memset(&params, 0xcc, sizeof(params));
821 memset(wsabufs, 0xcc, sizeof(wsabufs));
823 ret = send(server, "data", 5, 0);
824 ok(ret == 5, "got %d\n", ret);
826 ret = WaitForSingleObject(event, 200);
827 ok(!ret, "wait timed out\n");
828 ok(!io.Status, "got %#x\n", io.Status);
829 ok(io.Information == 5, "got %#Ix\n", io.Information);
830 ok(!strcmp(buffer, "data"), "got %s\n", debugstr_an(buffer, io.Information));
832 /* Test with multiple buffers. */
834 wsabufs[0].len = 2;
835 wsabufs[0].buf = buffer;
836 wsabufs[1].len = 4;
837 wsabufs[1].buf = buffer + 3;
838 memset(&params, 0, sizeof(params));
839 params.buffers = wsabufs;
840 params.count = 2;
841 params.msg_flags = AFD_MSG_NOT_OOB;
843 memset(&io, 0, sizeof(io));
844 memset(buffer, 0xcc, sizeof(buffer));
845 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
846 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
847 ok(ret == STATUS_PENDING, "got %#x\n", ret);
848 ok(!io.Status, "got status %#x\n", io.Status);
849 ok(!io.Information, "got information %#Ix\n", io.Information);
851 ret = send(server, "data", 5, 0);
852 ok(ret == 5, "got %d\n", ret);
854 ret = WaitForSingleObject(event, 200);
855 ok(!ret, "wait timed out\n");
856 ok(!io.Status, "got %#x\n", io.Status);
857 ok(io.Information == 5, "got %#Ix\n", io.Information);
858 ok(!strcmp(buffer, "da\xccta"), "got %s\n", debugstr_an(buffer, io.Information));
860 /* Test synchronous return. */
862 ret = send(server, "data", 5, 0);
863 ok(ret == 5, "got %d\n", ret);
865 memset(&io, 0xcc, sizeof(io));
866 memset(buffer, 0xcc, sizeof(buffer));
867 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
868 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
869 ok(!ret, "got %#x\n", ret);
870 ok(!io.Status, "got %#x\n", io.Status);
871 ok(io.Information == 5, "got %#Ix\n", io.Information);
872 ok(!strcmp(buffer, "da\xccta"), "got %s\n", debugstr_an(buffer, io.Information));
874 /* Test nonblocking mode. */
876 set_blocking(client, FALSE);
878 memset(&io, 0, sizeof(io));
879 memset(buffer, 0xcc, sizeof(buffer));
880 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
881 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
882 ok(ret == STATUS_DEVICE_NOT_READY, "got %#x\n", ret);
883 todo_wine ok(!io.Status, "got status %#x\n", io.Status);
884 ok(!io.Information, "got information %#Ix\n", io.Information);
886 ret = send(server, "data", 5, 0);
887 ok(ret == 5, "got %d\n", ret);
889 memset(&io, 0xcc, sizeof(io));
890 memset(buffer, 0xcc, sizeof(buffer));
891 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
892 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
893 ok(!ret, "got %#x\n", ret);
894 ok(!io.Status, "got %#x\n", io.Status);
895 ok(io.Information == 5, "got %#Ix\n", io.Information);
896 ok(!strcmp(buffer, "da\xccta"), "got %s\n", debugstr_an(buffer, io.Information));
898 params.recv_flags = AFD_RECV_FORCE_ASYNC;
900 memset(&io, 0, sizeof(io));
901 memset(buffer, 0xcc, sizeof(buffer));
902 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
903 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
904 ok(ret == STATUS_PENDING, "got %#x\n", ret);
905 todo_wine ok(!io.Status, "got status %#x\n", io.Status);
906 todo_wine ok(!io.Information, "got information %#Ix\n", io.Information);
908 ret = send(server, "data", 5, 0);
909 ok(ret == 5, "got %d\n", ret);
911 ret = WaitForSingleObject(event, 200);
912 ok(!ret, "wait timed out\n");
913 ok(!io.Status, "got %#x\n", io.Status);
914 ok(io.Information == 5, "got %#Ix\n", io.Information);
915 ok(!strcmp(buffer, "da\xccta"), "got %s\n", debugstr_an(buffer, io.Information));
917 params.recv_flags = 0;
919 set_blocking(client, TRUE);
921 /* Test flags. */
923 ret = send(server, "a", 1, MSG_OOB);
924 ok(ret == 1, "got %d\n", ret);
926 ret = send(server, "data", 5, 0);
927 ok(ret == 5, "got %d\n", ret);
929 memset(&io, 0xcc, sizeof(io));
930 memset(buffer, 0xcc, sizeof(buffer));
931 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
932 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
933 ok(!ret, "got %#x\n", ret);
934 ok(!io.Status, "got %#x\n", io.Status);
935 ok(io.Information == 5, "got %#Ix\n", io.Information);
936 ok(!strcmp(buffer, "da\xccta"), "got %s\n", debugstr_an(buffer, io.Information));
938 params.msg_flags = 0;
940 io.Status = 0xdeadbeef;
941 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
942 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
943 ok(ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret);
944 todo_wine ok(io.Status == 0xdeadbeef, "got %#x\n", io.Status);
946 params.msg_flags = AFD_MSG_OOB | AFD_MSG_NOT_OOB;
948 io.Status = 0xdeadbeef;
949 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
950 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
951 ok(ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret);
952 todo_wine ok(io.Status == 0xdeadbeef, "got %#x\n", io.Status);
954 params.msg_flags = AFD_MSG_OOB;
956 memset(buffer, 0xcc, sizeof(buffer));
957 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
958 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
959 todo_wine ok(!ret, "got %#x\n", ret);
960 todo_wine ok(!io.Status, "got %#x\n", io.Status);
961 todo_wine ok(io.Information == 1, "got %#Ix\n", io.Information);
962 todo_wine ok(buffer[0] == 'a', "got %s\n", debugstr_an(buffer, io.Information));
964 params.msg_flags = AFD_MSG_NOT_OOB | AFD_MSG_PEEK;
966 ret = send(server, "data", 4, 0);
967 ok(ret == 4, "got %d\n", ret);
969 memset(buffer, 0xcc, sizeof(buffer));
970 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
971 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
972 ok(!ret, "got %#x\n", ret);
973 ok(!io.Status, "got %#x\n", io.Status);
974 ok(io.Information == 4, "got %#Ix\n", io.Information);
975 ok(!memcmp(buffer, "da\xccta", 5), "got %s\n", debugstr_an(buffer, io.Information));
977 memset(buffer, 0xcc, sizeof(buffer));
978 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
979 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
980 ok(!ret, "got %#x\n", ret);
981 ok(!io.Status, "got %#x\n", io.Status);
982 ok(io.Information == 4, "got %#Ix\n", io.Information);
983 ok(!memcmp(buffer, "da\xccta", 5), "got %s\n", debugstr_an(buffer, io.Information));
985 params.msg_flags = AFD_MSG_NOT_OOB | AFD_MSG_WAITALL;
987 memset(buffer, 0xcc, sizeof(buffer));
988 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
989 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
990 todo_wine ok(ret == STATUS_PENDING, "got %#x\n", ret);
992 if (ret == STATUS_PENDING)
994 ret = send(server, "s", 2, 0);
995 ok(ret == 2, "got %d\n", ret);
997 ret = WaitForSingleObject(event, 200);
998 ok(!ret, "wait timed out\n");
999 ok(!io.Status, "got %#x\n", io.Status);
1000 ok(io.Information == 6, "got %#Ix\n", io.Information);
1001 ok(!strcmp(buffer, "da\xcctas"), "got %s\n", debugstr_an(buffer, io.Information));
1004 params.msg_flags = AFD_MSG_NOT_OOB;
1006 /* Test shutdown. */
1008 memset(buffer, 0xcc, sizeof(buffer));
1009 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
1010 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
1011 ok(ret == STATUS_PENDING, "got %#x\n", ret);
1013 closesocket(server);
1015 ret = WaitForSingleObject(event, 200);
1016 ok(!ret, "wait timed out\n");
1017 ok(!io.Status, "got %#x\n", io.Status);
1018 ok(!io.Information, "got %#Ix\n", io.Information);
1020 ret = shutdown(client, SD_RECEIVE);
1021 ok(!ret, "got error %u\n", WSAGetLastError());
1023 memset(&io, 0, sizeof(io));
1024 memset(buffer, 0xcc, sizeof(buffer));
1025 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
1026 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
1027 todo_wine ok(ret == STATUS_PIPE_DISCONNECTED, "got %#x\n", ret);
1028 ok(!io.Status, "got status %#x\n", io.Status);
1029 ok(!io.Information, "got information %#Ix\n", io.Information);
1031 closesocket(client);
1032 closesocket(listener);
1034 /* Test UDP datagrams. */
1036 client = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
1037 server = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
1039 memset(buffer, 0xcc, sizeof(buffer));
1040 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
1041 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
1042 todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret);
1043 if (ret == STATUS_PENDING)
1044 CancelIo((HANDLE)client);
1046 ret = bind(client, (const struct sockaddr *)&bind_addr, sizeof(bind_addr));
1047 ok(!ret, "got error %u\n", WSAGetLastError());
1048 len = sizeof(addr);
1049 ret = getsockname(listener, (struct sockaddr *)&addr, &len);
1050 ok(!ret, "got error %u\n", WSAGetLastError());
1052 memset(buffer, 0xcc, sizeof(buffer));
1053 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
1054 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
1055 ok(ret == STATUS_PENDING, "got %#x\n", ret);
1057 ret = sendto(server, "data", 5, 0, (struct sockaddr *)&addr, sizeof(addr));
1058 ok(ret == 5, "got %d\n", ret);
1060 ret = WaitForSingleObject(event, 200);
1061 ok(!ret, "wait timed out\n");
1062 ok(!io.Status, "got %#x\n", io.Status);
1063 ok(io.Information == 5, "got %#Ix\n", io.Information);
1064 ok(!strcmp(buffer, "da\xccta"), "got %s\n", debugstr_an(buffer, io.Information));
1066 /* Test a short read of a UDP datagram. */
1068 memset(buffer, 0xcc, sizeof(buffer));
1069 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
1070 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
1071 ok(ret == STATUS_PENDING, "got %#x\n", ret);
1073 ret = sendto(server, "moredata", 9, 0, (struct sockaddr *)&addr, sizeof(addr));
1074 ok(ret == 9, "got %d\n", ret);
1076 ret = WaitForSingleObject(event, 200);
1077 ok(!ret, "wait timed out\n");
1078 ok(io.Status == STATUS_BUFFER_OVERFLOW, "got %#x\n", io.Status);
1079 ok(io.Information == 6, "got %#Ix\n", io.Information);
1080 ok(!memcmp(buffer, "mo\xccreda\xcc", 7), "got %s\n", debugstr_an(buffer, io.Information));
1082 ret = sendto(server, "moredata", 9, 0, (struct sockaddr *)&addr, sizeof(addr));
1083 ok(ret == 9, "got %d\n", ret);
1085 memset(&io, 0, sizeof(io));
1086 memset(buffer, 0xcc, sizeof(buffer));
1087 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
1088 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
1089 ok(ret == STATUS_BUFFER_OVERFLOW, "got %#x\n", ret);
1090 ok(io.Status == STATUS_BUFFER_OVERFLOW, "got %#x\n", io.Status);
1091 ok(io.Information == 6, "got %#Ix\n", io.Information);
1092 ok(!memcmp(buffer, "mo\xccreda\xcc", 7), "got %s\n", debugstr_an(buffer, io.Information));
1094 /* Test closing a socket during an async. */
1096 memset(buffer, 0xcc, sizeof(buffer));
1097 ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
1098 IOCTL_AFD_RECV, &params, sizeof(params), NULL, 0);
1099 ok(ret == STATUS_PENDING, "got %#x\n", ret);
1101 closesocket(client);
1103 ret = WaitForSingleObject(event, 200);
1104 ok(!ret, "wait timed out\n");
1105 todo_wine ok(io.Status == STATUS_CANCELLED, "got %#x\n", io.Status);
1106 ok(!io.Information, "got %#Ix\n", io.Information);
1108 closesocket(server);
1109 CloseHandle(event);
1112 START_TEST(afd)
1114 WSADATA data;
1116 WSAStartup(MAKEWORD(2, 2), &data);
1118 test_open_device();
1119 test_poll();
1120 test_poll_completion_port();
1121 test_recv();
1123 WSACleanup();