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
24 #define WIN32_NO_STATUS
32 #include "wine/test.h"
34 static void tcp_socketpair(SOCKET
*src
, SOCKET
*dst
)
36 SOCKET server
= INVALID_SOCKET
;
37 struct sockaddr_in addr
;
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());
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());
63 *dst
= accept(server
, (struct sockaddr
*)&addr
, &len
);
64 ok(*dst
!= INVALID_SOCKET
, "failed to accept socket, error %u\n", WSAGetLastError());
69 static void set_blocking(SOCKET s
, ULONG 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
;
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
);
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
);
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
);
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
);
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};
122 in_params
.timeout
= -1000 * 10000;
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
;
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());
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
);
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
);
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
);
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
);
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
);
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
);
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
);
453 /* Test supplying multiple handles to the ioctl. */
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
);
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
);
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());
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
);
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
);
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
;
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;
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
, ¶ms
, sizeof(params
), ¶ms
, 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
, ¶ms
, sizeof(params
), ¶ms
, 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
);
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
, ¶ms
, sizeof(params
), ¶ms
, 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;
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
, ¶ms
, sizeof(params
), ¶ms
, sizeof(params
));
740 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
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
);
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
;
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());
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
;
805 params
.msg_flags
= AFD_MSG_NOT_OOB
;
807 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
808 IOCTL_AFD_RECV
, ¶ms
, 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
, ¶ms
, 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(¶ms
, 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. */
835 wsabufs
[0].buf
= buffer
;
837 wsabufs
[1].buf
= buffer
+ 3;
838 memset(¶ms
, 0, sizeof(params
));
839 params
.buffers
= wsabufs
;
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
, ¶ms
, 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
, ¶ms
, 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
, ¶ms
, 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
, ¶ms
, 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
, ¶ms
, 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
);
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
, ¶ms
, 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
, ¶ms
, 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
, ¶ms
, 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
, ¶ms
, 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
, ¶ms
, 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
, ¶ms
, 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
, ¶ms
, 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
, ¶ms
, 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
, ¶ms
, 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
, ¶ms
, 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());
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
, ¶ms
, 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
, ¶ms
, 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
, ¶ms
, 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
, ¶ms
, 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
);
1116 WSAStartup(MAKEWORD(2, 2), &data
);
1120 test_poll_completion_port();