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, ~0, c, FALSE)
115 #define check_poll_mask(a, b, c, d) check_poll_(__LINE__, a, b, c, d, FALSE)
116 #define check_poll_todo(a, b, c) check_poll_(__LINE__, a, b, ~0, c, TRUE)
117 static void check_poll_(int line
, SOCKET s
, HANDLE event
, int mask
, int expect
, BOOL todo
)
119 struct afd_poll_params in_params
= {0}, out_params
= {0};
123 in_params
.timeout
= -1000 * 10000;
125 in_params
.sockets
[0].socket
= s
;
126 in_params
.sockets
[0].flags
= mask
;
127 in_params
.sockets
[0].status
= 0xdeadbeef;
129 ret
= NtDeviceIoControlFile((HANDLE
)s
, event
, NULL
, NULL
, &io
,
130 IOCTL_AFD_POLL
, &in_params
, sizeof(in_params
), &out_params
, sizeof(out_params
));
131 ok_(__FILE__
, line
)(!ret
|| ret
== STATUS_PENDING
, "got %#x\n", ret
);
132 if (ret
== STATUS_PENDING
)
134 ret
= WaitForSingleObject(event
, 1000);
135 ok_(__FILE__
, line
)(!ret
, "wait timed out\n");
137 ok_(__FILE__
, line
)(!io
.Status
, "got %#x\n", io
.Status
);
138 ok_(__FILE__
, line
)(io
.Information
== sizeof(out_params
), "got %#Ix\n", io
.Information
);
139 ok_(__FILE__
, line
)(out_params
.timeout
== in_params
.timeout
, "got timeout %I64d\n", out_params
.timeout
);
140 ok_(__FILE__
, line
)(out_params
.count
== 1, "got count %u\n", out_params
.count
);
141 ok_(__FILE__
, line
)(out_params
.sockets
[0].socket
== s
, "got socket %#Ix\n", out_params
.sockets
[0].socket
);
142 todo_wine_if (todo
) ok_(__FILE__
, line
)(out_params
.sockets
[0].flags
== expect
, "got flags %#x\n", out_params
.sockets
[0].flags
);
143 ok_(__FILE__
, line
)(!out_params
.sockets
[0].status
, "got status %#x\n", out_params
.sockets
[0].status
);
146 static void test_poll(void)
148 const struct sockaddr_in bind_addr
= {.sin_family
= AF_INET
, .sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
)};
149 char in_buffer
[offsetof(struct afd_poll_params
, sockets
[3])];
150 char out_buffer
[offsetof(struct afd_poll_params
, sockets
[3])];
151 struct afd_poll_params
*in_params
= (struct afd_poll_params
*)in_buffer
;
152 struct afd_poll_params
*out_params
= (struct afd_poll_params
*)out_buffer
;
153 int large_buffer_size
= 1024 * 1024;
154 SOCKET client
, server
, listener
;
155 struct sockaddr_in addr
;
163 large_buffer
= malloc(large_buffer_size
);
164 memset(in_buffer
, 0, sizeof(in_buffer
));
165 memset(out_buffer
, 0, sizeof(out_buffer
));
166 event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
168 listener
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
169 ret
= bind(listener
, (const struct sockaddr
*)&bind_addr
, sizeof(bind_addr
));
170 ok(!ret
, "got error %u\n", WSAGetLastError());
171 ret
= listen(listener
, 1);
172 ok(!ret
, "got error %u\n", WSAGetLastError());
174 ret
= getsockname(listener
, (struct sockaddr
*)&addr
, &len
);
175 ok(!ret
, "got error %u\n", WSAGetLastError());
177 params_size
= offsetof(struct afd_poll_params
, sockets
[1]);
178 in_params
->count
= 1;
180 /* out_size must be at least as large as in_size. */
182 ret
= NtDeviceIoControlFile((HANDLE
)listener
, event
, NULL
, NULL
, &io
,
183 IOCTL_AFD_POLL
, in_params
, params_size
, NULL
, 0);
184 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
186 ret
= NtDeviceIoControlFile((HANDLE
)listener
, event
, NULL
, NULL
, &io
,
187 IOCTL_AFD_POLL
, NULL
, 0, out_params
, params_size
);
188 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
190 ret
= NtDeviceIoControlFile((HANDLE
)listener
, event
, NULL
, NULL
, &io
,
191 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
+ 1);
192 ok(ret
== STATUS_INVALID_HANDLE
, "got %#x\n", ret
);
194 ret
= NtDeviceIoControlFile((HANDLE
)listener
, event
, NULL
, NULL
, &io
,
195 IOCTL_AFD_POLL
, in_params
, params_size
+ 1, out_params
, params_size
);
196 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
198 ret
= NtDeviceIoControlFile((HANDLE
)listener
, event
, NULL
, NULL
, &io
,
199 IOCTL_AFD_POLL
, in_params
, params_size
- 1, out_params
, params_size
- 1);
200 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
202 ret
= NtDeviceIoControlFile((HANDLE
)listener
, event
, NULL
, NULL
, &io
,
203 IOCTL_AFD_POLL
, in_params
, params_size
+ 1, out_params
, params_size
+ 1);
204 ok(ret
== STATUS_INVALID_HANDLE
, "got %#x\n", ret
);
206 in_params
->count
= 0;
207 ret
= NtDeviceIoControlFile((HANDLE
)listener
, event
, NULL
, NULL
, &io
,
208 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
209 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
211 /* Basic semantics of the ioctl. */
213 in_params
->timeout
= 0;
214 in_params
->count
= 1;
215 in_params
->sockets
[0].socket
= listener
;
216 in_params
->sockets
[0].flags
= ~0;
217 in_params
->sockets
[0].status
= 0xdeadbeef;
219 memset(out_params
, 0, params_size
);
220 ret
= NtDeviceIoControlFile((HANDLE
)listener
, event
, NULL
, NULL
, &io
,
221 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
222 ok(!ret
, "got %#x\n", ret
);
223 ok(!io
.Status
, "got %#x\n", io
.Status
);
224 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[0]), "got %#Ix\n", io
.Information
);
225 ok(!out_params
->timeout
, "got timeout %#I64x\n", out_params
->timeout
);
226 ok(!out_params
->count
, "got count %u\n", out_params
->count
);
227 ok(!out_params
->sockets
[0].socket
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
228 ok(!out_params
->sockets
[0].flags
, "got flags %#x\n", out_params
->sockets
[0].flags
);
229 ok(!out_params
->sockets
[0].status
, "got status %#x\n", out_params
->sockets
[0].status
);
231 NtQuerySystemTime(&now
);
232 in_params
->timeout
= now
.QuadPart
;
234 ret
= NtDeviceIoControlFile((HANDLE
)listener
, event
, NULL
, NULL
, &io
,
235 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
236 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
237 ret
= WaitForSingleObject(event
, 100);
238 ok(!ret
, "got %#x\n", ret
);
239 ok(io
.Status
== STATUS_TIMEOUT
, "got %#x\n", io
.Status
);
240 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[0]), "got %#Ix\n", io
.Information
);
241 ok(out_params
->timeout
== now
.QuadPart
, "got timeout %#I64x\n", out_params
->timeout
);
242 ok(!out_params
->count
, "got count %u\n", out_params
->count
);
244 in_params
->timeout
= -1000 * 10000;
246 ret
= NtDeviceIoControlFile((HANDLE
)listener
, event
, NULL
, NULL
, &io
,
247 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
248 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
250 client
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
251 set_blocking(client
, FALSE
);
252 ret
= connect(client
, (struct sockaddr
*)&addr
, sizeof(addr
));
253 ok(!ret
|| WSAGetLastError() == WSAEWOULDBLOCK
, "got error %u\n", WSAGetLastError());
255 ret
= WaitForSingleObject(event
, 100);
256 ok(!ret
, "got %#x\n", ret
);
257 ok(!io
.Status
, "got %#x\n", io
.Status
);
258 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[1]), "got %#Ix\n", io
.Information
);
259 ok(out_params
->timeout
== -1000 * 10000, "got timeout %#I64x\n", out_params
->timeout
);
260 ok(out_params
->count
== 1, "got count %u\n", out_params
->count
);
261 ok(out_params
->sockets
[0].socket
== listener
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
262 ok(out_params
->sockets
[0].flags
== AFD_POLL_ACCEPT
, "got flags %#x\n", out_params
->sockets
[0].flags
);
263 ok(!out_params
->sockets
[0].status
, "got status %#x\n", out_params
->sockets
[0].status
);
265 ret
= NtDeviceIoControlFile((HANDLE
)listener
, event
, NULL
, NULL
, &io
,
266 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
267 ok(!ret
, "got %#x\n", ret
);
268 ok(!io
.Status
, "got %#x\n", io
.Status
);
269 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[1]), "got %#Ix\n", io
.Information
);
270 ok(out_params
->timeout
== -1000 * 10000, "got timeout %#I64x\n", out_params
->timeout
);
271 ok(out_params
->count
== 1, "got count %u\n", out_params
->count
);
272 ok(out_params
->sockets
[0].socket
== listener
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
273 ok(out_params
->sockets
[0].flags
== AFD_POLL_ACCEPT
, "got flags %#x\n", out_params
->sockets
[0].flags
);
274 ok(!out_params
->sockets
[0].status
, "got status %#x\n", out_params
->sockets
[0].status
);
276 in_params
->timeout
= now
.QuadPart
;
277 in_params
->sockets
[0].flags
= (~0) & ~AFD_POLL_ACCEPT
;
279 ret
= NtDeviceIoControlFile((HANDLE
)listener
, event
, NULL
, NULL
, &io
,
280 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
281 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
282 ret
= WaitForSingleObject(event
, 100);
283 ok(!ret
, "got %#x\n", ret
);
284 ok(io
.Status
== STATUS_TIMEOUT
, "got %#x\n", io
.Status
);
285 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[0]), "got %#Ix\n", io
.Information
);
286 ok(!out_params
->count
, "got count %u\n", out_params
->count
);
288 server
= accept(listener
, NULL
, NULL
);
289 ok(server
!= -1, "got error %u\n", WSAGetLastError());
290 set_blocking(server
, FALSE
);
292 /* Test flags exposed by connected sockets. */
294 check_poll(client
, event
, AFD_POLL_WRITE
| AFD_POLL_CONNECT
);
295 check_poll(server
, event
, AFD_POLL_WRITE
| AFD_POLL_CONNECT
);
297 /* It is valid to poll on a socket other than the one passed to
298 * NtDeviceIoControlFile(). */
300 in_params
->count
= 1;
301 in_params
->sockets
[0].socket
= server
;
302 in_params
->sockets
[0].flags
= ~0;
304 ret
= NtDeviceIoControlFile((HANDLE
)listener
, event
, NULL
, NULL
, &io
,
305 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
306 ok(!ret
, "got %#x\n", ret
);
307 ok(!io
.Status
, "got %#x\n", io
.Status
);
308 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[1]), "got %#Ix\n", io
.Information
);
309 ok(out_params
->count
== 1, "got count %u\n", out_params
->count
);
310 ok(out_params
->sockets
[0].socket
== server
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
311 ok(out_params
->sockets
[0].flags
== (AFD_POLL_WRITE
| AFD_POLL_CONNECT
),
312 "got flags %#x\n", out_params
->sockets
[0].flags
);
313 ok(!out_params
->sockets
[0].status
, "got status %#x\n", out_params
->sockets
[0].status
);
315 /* Test sending data. */
317 ret
= send(server
, "data", 5, 0);
318 ok(ret
== 5, "got %d\n", ret
);
320 check_poll_mask(client
, event
, AFD_POLL_READ
, AFD_POLL_READ
);
321 check_poll(client
, event
, AFD_POLL_WRITE
| AFD_POLL_CONNECT
| AFD_POLL_READ
);
322 check_poll(server
, event
, AFD_POLL_WRITE
| AFD_POLL_CONNECT
);
324 while (send(server
, large_buffer
, large_buffer_size
, 0) == large_buffer_size
);
326 check_poll(client
, event
, AFD_POLL_WRITE
| AFD_POLL_CONNECT
| AFD_POLL_READ
);
327 check_poll(server
, event
, AFD_POLL_CONNECT
);
329 /* Test sending out-of-band data. */
331 ret
= send(client
, "a", 1, MSG_OOB
);
332 ok(ret
== 1, "got %d\n", ret
);
334 check_poll(client
, event
, AFD_POLL_WRITE
| AFD_POLL_CONNECT
| AFD_POLL_READ
);
335 check_poll_mask(server
, event
, AFD_POLL_OOB
, AFD_POLL_OOB
);
336 check_poll(server
, event
, AFD_POLL_CONNECT
| AFD_POLL_OOB
);
338 ret
= recv(server
, large_buffer
, 1, MSG_OOB
);
339 ok(ret
== 1, "got %d\n", ret
);
341 check_poll(client
, event
, AFD_POLL_WRITE
| AFD_POLL_CONNECT
| AFD_POLL_READ
);
342 check_poll(server
, event
, AFD_POLL_CONNECT
);
345 ret
= setsockopt(server
, SOL_SOCKET
, SO_OOBINLINE
, (char *)&ret
, sizeof(ret
));
346 ok(!ret
, "got error %u\n", WSAGetLastError());
348 ret
= send(client
, "a", 1, MSG_OOB
);
349 ok(ret
== 1, "got %d\n", ret
);
351 check_poll(client
, event
, AFD_POLL_WRITE
| AFD_POLL_CONNECT
| AFD_POLL_READ
);
352 check_poll_mask(server
, event
, AFD_POLL_READ
, AFD_POLL_READ
);
353 check_poll(server
, event
, AFD_POLL_CONNECT
| AFD_POLL_READ
);
360 client
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
361 ret
= connect(client
, (struct sockaddr
*)&addr
, sizeof(addr
));
362 ok(!ret
, "got error %u\n", WSAGetLastError());
363 server
= accept(listener
, NULL
, NULL
);
364 ok(server
!= -1, "got error %u\n", WSAGetLastError());
366 ret
= shutdown(client
, SD_RECEIVE
);
367 ok(!ret
, "got error %u\n", WSAGetLastError());
369 check_poll(client
, event
, AFD_POLL_WRITE
| AFD_POLL_CONNECT
);
370 check_poll(server
, event
, AFD_POLL_WRITE
| AFD_POLL_CONNECT
);
372 ret
= shutdown(client
, SD_SEND
);
373 ok(!ret
, "got error %u\n", WSAGetLastError());
375 check_poll(client
, event
, AFD_POLL_WRITE
| AFD_POLL_CONNECT
);
376 check_poll_mask(server
, event
, AFD_POLL_HUP
, AFD_POLL_HUP
);
377 check_poll(server
, event
, AFD_POLL_WRITE
| AFD_POLL_CONNECT
| AFD_POLL_HUP
);
382 /* Test shutdown with data in the pipe. */
384 client
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
385 ret
= connect(client
, (struct sockaddr
*)&addr
, sizeof(addr
));
386 ok(!ret
, "got error %u\n", WSAGetLastError());
387 server
= accept(listener
, NULL
, NULL
);
388 ok(server
!= -1, "got error %u\n", WSAGetLastError());
390 ret
= send(client
, "data", 5, 0);
391 ok(ret
== 5, "got %d\n", ret
);
393 check_poll(client
, event
, AFD_POLL_WRITE
| AFD_POLL_CONNECT
);
394 check_poll_mask(server
, event
, AFD_POLL_READ
, AFD_POLL_READ
);
395 check_poll(server
, event
, AFD_POLL_WRITE
| AFD_POLL_CONNECT
| AFD_POLL_READ
);
397 ret
= shutdown(client
, SD_SEND
);
398 ok(!ret
, "got error %u\n", WSAGetLastError());
400 check_poll(client
, event
, AFD_POLL_WRITE
| AFD_POLL_CONNECT
);
401 check_poll_mask(server
, event
, AFD_POLL_READ
, AFD_POLL_READ
);
402 check_poll_todo(server
, event
, AFD_POLL_WRITE
| AFD_POLL_CONNECT
| AFD_POLL_READ
| AFD_POLL_HUP
);
404 /* Test closing a socket while polling on it. Note that AFD_POLL_CLOSE
405 * is always returned, regardless of whether it's polled for. */
407 in_params
->timeout
= -1000 * 10000;
408 in_params
->count
= 1;
409 in_params
->sockets
[0].socket
= client
;
410 in_params
->sockets
[0].flags
= 0;
412 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
413 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
414 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
418 ret
= WaitForSingleObject(event
, 100);
419 ok(!ret
, "got %#x\n", ret
);
420 ok(!io
.Status
, "got %#x\n", io
.Status
);
421 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[1]), "got %#Ix\n", io
.Information
);
422 ok(out_params
->count
== 1, "got count %u\n", out_params
->count
);
423 ok(out_params
->sockets
[0].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
424 ok(out_params
->sockets
[0].flags
== AFD_POLL_CLOSE
,
425 "got flags %#x\n", out_params
->sockets
[0].flags
);
426 ok(!out_params
->sockets
[0].status
, "got status %#x\n", out_params
->sockets
[0].status
);
430 /* Test a failed connection.
432 * The following poll works even where the equivalent WSAPoll() call fails.
433 * However, it can take over 2 seconds to complete on the testbot. */
435 if (winetest_interactive
)
437 client
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
438 set_blocking(client
, FALSE
);
440 in_params
->timeout
= -10000 * 10000;
441 in_params
->count
= 1;
442 in_params
->sockets
[0].socket
= client
;
443 in_params
->sockets
[0].flags
= ~0;
445 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
446 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
447 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
450 ret
= connect(client
, (struct sockaddr
*)&addr
, sizeof(addr
));
451 ok(ret
== -1, "got %d\n", ret
);
452 ok(WSAGetLastError() == WSAEWOULDBLOCK
, "got error %u\n", WSAGetLastError());
454 ret
= WaitForSingleObject(event
, 10000);
455 ok(!ret
, "got %#x\n", ret
);
456 ok(!io
.Status
, "got %#x\n", io
.Status
);
457 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[1]), "got %#Ix\n", io
.Information
);
458 ok(out_params
->count
== 1, "got count %u\n", out_params
->count
);
459 ok(out_params
->sockets
[0].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
460 ok(out_params
->sockets
[0].flags
== AFD_POLL_CONNECT_ERR
, "got flags %#x\n", out_params
->sockets
[0].flags
);
461 ok(out_params
->sockets
[0].status
== STATUS_CONNECTION_REFUSED
, "got status %#x\n", out_params
->sockets
[0].status
);
463 in_params
->timeout
= now
.QuadPart
;
464 memset(out_params
, 0xcc, sizeof(out_buffer
));
465 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
466 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
467 ok(!ret
, "got %#x\n", ret
);
468 ok(!io
.Status
, "got %#x\n", io
.Status
);
469 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[1]), "got %#Ix\n", io
.Information
);
470 ok(out_params
->count
== 1, "got count %u\n", out_params
->count
);
471 ok(out_params
->sockets
[0].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
472 ok(out_params
->sockets
[0].flags
== AFD_POLL_CONNECT_ERR
, "got flags %#x\n", out_params
->sockets
[0].flags
);
473 ok(out_params
->sockets
[0].status
== STATUS_CONNECTION_REFUSED
, "got status %#x\n", out_params
->sockets
[0].status
);
475 memset(out_params
, 0xcc, sizeof(out_buffer
));
476 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
477 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
478 ok(!ret
, "got %#x\n", ret
);
479 ok(!io
.Status
, "got %#x\n", io
.Status
);
480 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[1]), "got %#Ix\n", io
.Information
);
481 ok(out_params
->count
== 1, "got count %u\n", out_params
->count
);
482 ok(out_params
->sockets
[0].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
483 ok(out_params
->sockets
[0].flags
== AFD_POLL_CONNECT_ERR
, "got flags %#x\n", out_params
->sockets
[0].flags
);
484 ok(out_params
->sockets
[0].status
== STATUS_CONNECTION_REFUSED
, "got status %#x\n", out_params
->sockets
[0].status
);
486 ret
= connect(client
, (struct sockaddr
*)&addr
, sizeof(addr
));
487 ok(ret
== -1, "got %d\n", ret
);
488 todo_wine
ok(WSAGetLastError() == WSAEWOULDBLOCK
, "got error %u\n", WSAGetLastError());
489 if (WSAGetLastError() == WSAECONNABORTED
)
491 ret
= connect(client
, (struct sockaddr
*)&addr
, sizeof(addr
));
492 ok(ret
== -1, "got %d\n", ret
);
493 ok(WSAGetLastError() == WSAEWOULDBLOCK
, "got error %u\n", WSAGetLastError());
496 /* A subsequent poll call returns no events, or times out. However, this
497 * can't be reliably tested, as e.g. Linux will fail the connection
502 client
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
504 ret
= connect(client
, (struct sockaddr
*)&addr
, sizeof(addr
));
505 ok(ret
== -1, "expected failure\n");
506 ok(WSAGetLastError() == WSAECONNREFUSED
, "got error %u\n", WSAGetLastError());
508 memset(out_params
, 0xcc, sizeof(out_buffer
));
509 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
510 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
511 ok(!ret
, "got %#x\n", ret
);
512 ok(!io
.Status
, "got %#x\n", io
.Status
);
513 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[1]), "got %#Ix\n", io
.Information
);
514 ok(out_params
->count
== 1, "got count %u\n", out_params
->count
);
515 ok(out_params
->sockets
[0].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
516 ok(out_params
->sockets
[0].flags
== AFD_POLL_CONNECT_ERR
, "got flags %#x\n", out_params
->sockets
[0].flags
);
517 ok(out_params
->sockets
[0].status
== STATUS_CONNECTION_REFUSED
, "got status %#x\n", out_params
->sockets
[0].status
);
522 /* Test supplying multiple handles to the ioctl. */
525 ret
= getsockname(listener
, (struct sockaddr
*)&addr
, &len
);
526 ok(!ret
, "got error %u\n", WSAGetLastError());
528 client
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
529 ret
= connect(client
, (struct sockaddr
*)&addr
, sizeof(addr
));
530 ok(!ret
, "got error %u\n", WSAGetLastError());
531 server
= accept(listener
, NULL
, NULL
);
532 ok(server
!= -1, "got error %u\n", WSAGetLastError());
534 in_params
->timeout
= -1000 * 10000;
535 in_params
->count
= 2;
536 in_params
->sockets
[0].socket
= client
;
537 in_params
->sockets
[0].flags
= AFD_POLL_READ
;
538 in_params
->sockets
[1].socket
= server
;
539 in_params
->sockets
[1].flags
= AFD_POLL_READ
;
541 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
542 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
543 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
545 params_size
= offsetof(struct afd_poll_params
, sockets
[2]);
547 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
548 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
549 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
551 ret
= send(client
, "data", 5, 0);
552 ok(ret
== 5, "got %d\n", ret
);
554 ret
= WaitForSingleObject(event
, 100);
555 ok(!ret
, "got %#x\n", ret
);
556 ok(!io
.Status
, "got %#x\n", io
.Status
);
557 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[1]), "got %#Ix\n", io
.Information
);
558 ok(out_params
->count
== 1, "got count %u\n", out_params
->count
);
559 ok(out_params
->sockets
[0].socket
== server
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
560 ok(out_params
->sockets
[0].flags
== AFD_POLL_READ
, "got flags %#x\n", out_params
->sockets
[0].flags
);
561 ok(!out_params
->sockets
[0].status
, "got status %#x\n", out_params
->sockets
[0].status
);
563 in_params
->count
= 2;
564 in_params
->sockets
[0].socket
= client
;
565 in_params
->sockets
[0].flags
= AFD_POLL_READ
| AFD_POLL_WRITE
;
566 in_params
->sockets
[1].socket
= server
;
567 in_params
->sockets
[1].flags
= AFD_POLL_READ
| AFD_POLL_WRITE
;
569 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
570 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
571 ok(!ret
, "got %#x\n", ret
);
572 ok(!io
.Status
, "got %#x\n", io
.Status
);
573 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[2]), "got %#Ix\n", io
.Information
);
574 ok(out_params
->count
== 2, "got count %u\n", out_params
->count
);
575 ok(out_params
->sockets
[0].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
576 ok(out_params
->sockets
[0].flags
== AFD_POLL_WRITE
, "got flags %#x\n", out_params
->sockets
[0].flags
);
577 ok(!out_params
->sockets
[0].status
, "got status %#x\n", out_params
->sockets
[0].status
);
578 ok(out_params
->sockets
[1].socket
== server
, "got socket %#Ix\n", out_params
->sockets
[1].socket
);
579 ok(out_params
->sockets
[1].flags
== (AFD_POLL_READ
| AFD_POLL_WRITE
),
580 "got flags %#x\n", out_params
->sockets
[1].flags
);
581 ok(!out_params
->sockets
[1].status
, "got status %#x\n", out_params
->sockets
[1].status
);
583 in_params
->count
= 2;
584 in_params
->sockets
[0].socket
= client
;
585 in_params
->sockets
[0].flags
= AFD_POLL_READ
| AFD_POLL_WRITE
;
586 in_params
->sockets
[1].socket
= server
;
587 in_params
->sockets
[1].flags
= AFD_POLL_READ
| AFD_POLL_WRITE
;
589 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
590 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
591 ok(!ret
, "got %#x\n", ret
);
592 ok(!io
.Status
, "got %#x\n", io
.Status
);
593 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[2]), "got %#Ix\n", io
.Information
);
594 ok(out_params
->count
== 2, "got count %u\n", out_params
->count
);
595 ok(out_params
->sockets
[0].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
596 ok(out_params
->sockets
[0].flags
== AFD_POLL_WRITE
, "got flags %#x\n", out_params
->sockets
[0].flags
);
597 ok(!out_params
->sockets
[0].status
, "got status %#x\n", out_params
->sockets
[0].status
);
598 ok(out_params
->sockets
[1].socket
== server
, "got socket %#Ix\n", out_params
->sockets
[1].socket
);
599 ok(out_params
->sockets
[1].flags
== (AFD_POLL_READ
| AFD_POLL_WRITE
),
600 "got flags %#x\n", out_params
->sockets
[1].flags
);
601 ok(!out_params
->sockets
[1].status
, "got status %#x\n", out_params
->sockets
[1].status
);
603 /* Close a socket while polling on another. */
605 in_params
->timeout
= -100 * 10000;
606 in_params
->count
= 1;
607 in_params
->sockets
[0].socket
= client
;
608 in_params
->sockets
[0].flags
= AFD_POLL_READ
;
609 params_size
= offsetof(struct afd_poll_params
, sockets
[1]);
611 ret
= NtDeviceIoControlFile((HANDLE
)server
, event
, NULL
, NULL
, &io
,
612 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
613 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
617 ret
= WaitForSingleObject(event
, 1000);
618 ok(!ret
, "got %#x\n", ret
);
619 todo_wine
ok(io
.Status
== STATUS_TIMEOUT
, "got %#x\n", io
.Status
);
620 todo_wine
ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[0]), "got %#Ix\n", io
.Information
);
621 todo_wine
ok(!out_params
->count
, "got count %u\n", out_params
->count
);
625 closesocket(listener
);
627 /* Test UDP sockets. */
629 client
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
630 server
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
632 check_poll(client
, event
, AFD_POLL_WRITE
);
633 check_poll(server
, event
, AFD_POLL_WRITE
);
635 ret
= bind(client
, (const struct sockaddr
*)&bind_addr
, sizeof(bind_addr
));
636 ok(!ret
, "got error %u\n", WSAGetLastError());
638 ret
= getsockname(client
, (struct sockaddr
*)&addr
, &len
);
639 ok(!ret
, "got error %u\n", WSAGetLastError());
641 check_poll(client
, event
, AFD_POLL_WRITE
);
642 check_poll(server
, event
, AFD_POLL_WRITE
);
644 in_params
->timeout
= -1000 * 10000;
645 in_params
->count
= 1;
646 in_params
->sockets
[0].socket
= client
;
647 in_params
->sockets
[0].flags
= (~0) & ~AFD_POLL_WRITE
;
648 params_size
= offsetof(struct afd_poll_params
, sockets
[1]);
650 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
651 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
652 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
654 ret
= sendto(server
, "data", 5, 0, (struct sockaddr
*)&addr
, sizeof(addr
));
655 ok(ret
== 5, "got %d\n", ret
);
657 ret
= WaitForSingleObject(event
, 100);
658 ok(!ret
, "got %#x\n", ret
);
659 ok(!io
.Status
, "got %#x\n", io
.Status
);
660 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[1]), "got %#Ix\n", io
.Information
);
661 ok(out_params
->count
== 1, "got count %u\n", out_params
->count
);
662 ok(out_params
->sockets
[0].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
663 ok(out_params
->sockets
[0].flags
== AFD_POLL_READ
, "got flags %#x\n", out_params
->sockets
[0].flags
);
664 ok(!out_params
->sockets
[0].status
, "got status %#x\n", out_params
->sockets
[0].status
);
669 /* Passing any invalid sockets yields STATUS_INVALID_HANDLE.
671 * Note however that WSAPoll() happily accepts invalid sockets. It seems
672 * user-side cached data is used: closing a handle with CloseHandle() before
673 * passing it to WSAPoll() yields ENOTSOCK. */
675 tcp_socketpair(&client
, &server
);
677 in_params
->count
= 2;
678 in_params
->sockets
[0].socket
= 0xabacab;
679 in_params
->sockets
[0].flags
= AFD_POLL_READ
| AFD_POLL_WRITE
;
680 in_params
->sockets
[1].socket
= client
;
681 in_params
->sockets
[1].flags
= AFD_POLL_READ
| AFD_POLL_WRITE
;
682 params_size
= offsetof(struct afd_poll_params
, sockets
[2]);
684 memset(&io
, 0, sizeof(io
));
685 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
686 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
687 ok(ret
== STATUS_INVALID_HANDLE
, "got %#x\n", ret
);
688 todo_wine
ok(!io
.Status
, "got %#x\n", io
.Status
);
689 ok(!io
.Information
, "got %#Ix\n", io
.Information
);
691 /* Test passing the same handle twice. */
693 in_params
->count
= 3;
694 in_params
->sockets
[0].socket
= client
;
695 in_params
->sockets
[0].flags
= AFD_POLL_READ
| AFD_POLL_WRITE
;
696 in_params
->sockets
[1].socket
= client
;
697 in_params
->sockets
[1].flags
= AFD_POLL_READ
| AFD_POLL_WRITE
;
698 in_params
->sockets
[2].socket
= client
;
699 in_params
->sockets
[2].flags
= AFD_POLL_READ
| AFD_POLL_WRITE
| AFD_POLL_CONNECT
;
700 params_size
= offsetof(struct afd_poll_params
, sockets
[3]);
702 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
703 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
704 ok(!ret
, "got %#x\n", ret
);
705 ok(!io
.Status
, "got %#x\n", io
.Status
);
706 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[3]), "got %#Ix\n", io
.Information
);
707 ok(out_params
->count
== 3, "got count %u\n", out_params
->count
);
708 ok(out_params
->sockets
[0].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
709 ok(out_params
->sockets
[0].flags
== AFD_POLL_WRITE
, "got flags %#x\n", out_params
->sockets
[0].flags
);
710 ok(!out_params
->sockets
[0].status
, "got status %#x\n", out_params
->sockets
[0].status
);
711 ok(out_params
->sockets
[1].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[1].socket
);
712 ok(out_params
->sockets
[1].flags
== AFD_POLL_WRITE
, "got flags %#x\n", out_params
->sockets
[1].flags
);
713 ok(!out_params
->sockets
[1].status
, "got status %#x\n", out_params
->sockets
[1].status
);
714 ok(out_params
->sockets
[2].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[2].socket
);
715 ok(out_params
->sockets
[2].flags
== (AFD_POLL_WRITE
| AFD_POLL_CONNECT
),
716 "got flags %#x\n", out_params
->sockets
[2].flags
);
717 ok(!out_params
->sockets
[2].status
, "got status %#x\n", out_params
->sockets
[2].status
);
719 in_params
->count
= 2;
720 in_params
->sockets
[0].socket
= client
;
721 in_params
->sockets
[0].flags
= AFD_POLL_READ
;
722 in_params
->sockets
[1].socket
= client
;
723 in_params
->sockets
[1].flags
= AFD_POLL_READ
;
724 params_size
= offsetof(struct afd_poll_params
, sockets
[2]);
726 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
727 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
728 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
730 ret
= send(server
, "data", 5, 0);
731 ok(ret
== 5, "got %d\n", ret
);
733 ret
= WaitForSingleObject(event
, 100);
734 ok(!ret
, "got %#x\n", ret
);
735 ok(!io
.Status
, "got %#x\n", io
.Status
);
736 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[1]), "got %#Ix\n", io
.Information
);
737 ok(out_params
->count
== 1, "got count %u\n", out_params
->count
);
738 ok(out_params
->sockets
[0].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
739 ok(out_params
->sockets
[0].flags
== AFD_POLL_READ
, "got flags %#x\n", out_params
->sockets
[0].flags
);
740 ok(!out_params
->sockets
[0].status
, "got status %#x\n", out_params
->sockets
[0].status
);
749 static void test_poll_completion_port(void)
751 struct afd_poll_params params
= {0};
752 LARGE_INTEGER zero
= {{0}};
753 SOCKET client
, server
;
754 ULONG_PTR key
, value
;
759 event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
760 tcp_socketpair(&client
, &server
);
761 port
= CreateIoCompletionPort((HANDLE
)client
, NULL
, 0, 0);
763 params
.timeout
= -100 * 10000;
765 params
.sockets
[0].socket
= client
;
766 params
.sockets
[0].flags
= AFD_POLL_WRITE
;
767 params
.sockets
[0].status
= 0xdeadbeef;
769 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
770 IOCTL_AFD_POLL
, ¶ms
, sizeof(params
), ¶ms
, sizeof(params
));
771 ok(!ret
, "got %#x\n", ret
);
773 ret
= NtRemoveIoCompletion(port
, &key
, &value
, &io
, &zero
);
774 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
776 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, (void *)0xdeadbeef, &io
,
777 IOCTL_AFD_POLL
, ¶ms
, sizeof(params
), ¶ms
, sizeof(params
));
778 ok(!ret
, "got %#x\n", ret
);
780 ret
= NtRemoveIoCompletion(port
, &key
, &value
, &io
, &zero
);
781 ok(!ret
, "got %#x\n", ret
);
782 ok(!key
, "got key %#Ix\n", key
);
783 ok(value
== 0xdeadbeef, "got value %#Ix\n", value
);
787 params
.sockets
[0].socket
= client
;
788 params
.sockets
[0].flags
= AFD_POLL_READ
;
789 params
.sockets
[0].status
= 0xdeadbeef;
791 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, (void *)0xdeadbeef, &io
,
792 IOCTL_AFD_POLL
, ¶ms
, sizeof(params
), ¶ms
, sizeof(params
));
793 ok(!ret
, "got %#x\n", ret
);
795 ret
= NtRemoveIoCompletion(port
, &key
, &value
, &io
, &zero
);
796 ok(!ret
, "got %#x\n", ret
);
797 ok(!key
, "got key %#Ix\n", key
);
798 ok(value
== 0xdeadbeef, "got value %#Ix\n", value
);
800 /* Close a socket while polling on another. */
802 params
.timeout
= -100 * 10000;
804 params
.sockets
[0].socket
= server
;
805 params
.sockets
[0].flags
= AFD_POLL_READ
;
806 params
.sockets
[0].status
= 0xdeadbeef;
808 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, (void *)0xdeadbeef, &io
,
809 IOCTL_AFD_POLL
, ¶ms
, sizeof(params
), ¶ms
, sizeof(params
));
810 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
814 ret
= WaitForSingleObject(event
, 1000);
815 ok(!ret
, "got %#x\n", ret
);
816 todo_wine
ok(io
.Status
== STATUS_TIMEOUT
, "got %#x\n", io
.Status
);
817 todo_wine
ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[0]), "got %#Ix\n", io
.Information
);
818 todo_wine
ok(!params
.count
, "got count %u\n", params
.count
);
820 ret
= NtRemoveIoCompletion(port
, &key
, &value
, &io
, &zero
);
821 ok(!ret
, "got %#x\n", ret
);
822 ok(!key
, "got key %#Ix\n", key
);
823 ok(value
== 0xdeadbeef, "got value %#Ix\n", value
);
830 static void test_recv(void)
832 const struct sockaddr_in bind_addr
= {.sin_family
= AF_INET
, .sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
)};
833 struct afd_recv_params params
= {0};
834 SOCKET client
, server
, listener
;
835 struct sockaddr addr
;
842 event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
844 listener
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
845 ret
= bind(listener
, (const struct sockaddr
*)&bind_addr
, sizeof(bind_addr
));
846 ok(!ret
, "got error %u\n", WSAGetLastError());
847 ret
= listen(listener
, 1);
848 ok(!ret
, "got error %u\n", WSAGetLastError());
850 ret
= getsockname(listener
, (struct sockaddr
*)&addr
, &len
);
851 ok(!ret
, "got error %u\n", WSAGetLastError());
853 memset(&io
, 0, sizeof(io
));
854 ret
= NtDeviceIoControlFile((HANDLE
)listener
, event
, NULL
, NULL
, &io
, IOCTL_AFD_RECV
, NULL
, 0, NULL
, 0);
855 todo_wine
ok(ret
== STATUS_INVALID_CONNECTION
, "got %#x\n", ret
);
856 todo_wine
ok(!io
.Status
, "got status %#x\n", io
.Status
);
857 ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
859 client
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
860 ret
= connect(client
, (struct sockaddr
*)&addr
, sizeof(addr
));
861 ok(!ret
, "got error %u\n", WSAGetLastError());
862 server
= accept(listener
, NULL
, NULL
);
863 ok(server
!= -1, "got error %u\n", WSAGetLastError());
865 memset(&io
, 0, sizeof(io
));
866 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
, IOCTL_AFD_RECV
, NULL
, 0, NULL
, 0);
867 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
868 todo_wine
ok(!io
.Status
, "got status %#x\n", io
.Status
);
869 ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
871 wsabufs
[0].len
= sizeof(buffer
);
872 wsabufs
[0].buf
= buffer
;
873 params
.buffers
= wsabufs
;
875 params
.msg_flags
= AFD_MSG_NOT_OOB
;
877 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
878 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
) - 1, NULL
, 0);
879 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
881 memset(&io
, 0, sizeof(io
));
882 memset(buffer
, 0xcc, sizeof(buffer
));
883 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
884 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
885 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
886 ok(!io
.Status
, "got status %#x\n", io
.Status
);
887 ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
889 /* These structures need not remain valid. */
890 memset(¶ms
, 0xcc, sizeof(params
));
891 memset(wsabufs
, 0xcc, sizeof(wsabufs
));
893 ret
= send(server
, "data", 5, 0);
894 ok(ret
== 5, "got %d\n", ret
);
896 ret
= WaitForSingleObject(event
, 200);
897 ok(!ret
, "wait timed out\n");
898 ok(!io
.Status
, "got %#x\n", io
.Status
);
899 ok(io
.Information
== 5, "got %#Ix\n", io
.Information
);
900 ok(!strcmp(buffer
, "data"), "got %s\n", debugstr_an(buffer
, io
.Information
));
902 /* Test with multiple buffers. */
905 wsabufs
[0].buf
= buffer
;
907 wsabufs
[1].buf
= buffer
+ 3;
908 memset(¶ms
, 0, sizeof(params
));
909 params
.buffers
= wsabufs
;
911 params
.msg_flags
= AFD_MSG_NOT_OOB
;
913 memset(&io
, 0, sizeof(io
));
914 memset(buffer
, 0xcc, sizeof(buffer
));
915 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
916 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
917 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
918 ok(!io
.Status
, "got status %#x\n", io
.Status
);
919 ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
921 ret
= send(server
, "data", 5, 0);
922 ok(ret
== 5, "got %d\n", ret
);
924 ret
= WaitForSingleObject(event
, 200);
925 ok(!ret
, "wait timed out\n");
926 ok(!io
.Status
, "got %#x\n", io
.Status
);
927 ok(io
.Information
== 5, "got %#Ix\n", io
.Information
);
928 ok(!strcmp(buffer
, "da\xccta"), "got %s\n", debugstr_an(buffer
, io
.Information
));
930 /* Test synchronous return. */
932 ret
= send(server
, "data", 5, 0);
933 ok(ret
== 5, "got %d\n", ret
);
935 /* wait for the data to be available */
936 check_poll_mask(client
, event
, AFD_POLL_READ
, AFD_POLL_READ
);
938 memset(&io
, 0xcc, sizeof(io
));
939 memset(buffer
, 0xcc, sizeof(buffer
));
940 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
941 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
942 ok(!ret
, "got %#x\n", ret
);
943 ok(!io
.Status
, "got %#x\n", io
.Status
);
944 ok(io
.Information
== 5, "got %#Ix\n", io
.Information
);
945 ok(!strcmp(buffer
, "da\xccta"), "got %s\n", debugstr_an(buffer
, io
.Information
));
947 /* Test nonblocking mode. */
949 set_blocking(client
, FALSE
);
951 memset(&io
, 0, sizeof(io
));
952 memset(buffer
, 0xcc, sizeof(buffer
));
953 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
954 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
955 ok(ret
== STATUS_DEVICE_NOT_READY
, "got %#x\n", ret
);
956 todo_wine
ok(!io
.Status
, "got status %#x\n", io
.Status
);
957 ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
959 ret
= send(server
, "data", 5, 0);
960 ok(ret
== 5, "got %d\n", ret
);
962 /* wait for the data to be available */
963 check_poll_mask(client
, event
, AFD_POLL_READ
, AFD_POLL_READ
);
965 memset(&io
, 0xcc, sizeof(io
));
966 memset(buffer
, 0xcc, sizeof(buffer
));
967 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
968 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
969 ok(!ret
, "got %#x\n", ret
);
970 ok(!io
.Status
, "got %#x\n", io
.Status
);
971 ok(io
.Information
== 5, "got %#Ix\n", io
.Information
);
972 ok(!strcmp(buffer
, "da\xccta"), "got %s\n", debugstr_an(buffer
, io
.Information
));
974 params
.recv_flags
= AFD_RECV_FORCE_ASYNC
;
976 memset(&io
, 0, sizeof(io
));
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
== STATUS_PENDING
, "got %#x\n", ret
);
981 todo_wine
ok(!io
.Status
, "got status %#x\n", io
.Status
);
982 todo_wine
ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
984 ret
= send(server
, "data", 5, 0);
985 ok(ret
== 5, "got %d\n", ret
);
987 ret
= WaitForSingleObject(event
, 200);
988 ok(!ret
, "wait timed out\n");
989 ok(!io
.Status
, "got %#x\n", io
.Status
);
990 ok(io
.Information
== 5, "got %#Ix\n", io
.Information
);
991 ok(!strcmp(buffer
, "da\xccta"), "got %s\n", debugstr_an(buffer
, io
.Information
));
993 params
.recv_flags
= 0;
995 set_blocking(client
, TRUE
);
999 ret
= send(server
, "a", 1, MSG_OOB
);
1000 ok(ret
== 1, "got %d\n", ret
);
1002 ret
= send(server
, "data", 5, 0);
1003 ok(ret
== 5, "got %d\n", ret
);
1005 /* wait for the data to be available */
1006 check_poll_mask(client
, event
, AFD_POLL_READ
, AFD_POLL_READ
);
1008 memset(&io
, 0xcc, sizeof(io
));
1009 memset(buffer
, 0xcc, sizeof(buffer
));
1010 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1011 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1012 ok(!ret
, "got %#x\n", ret
);
1013 ok(!io
.Status
, "got %#x\n", io
.Status
);
1014 ok(io
.Information
== 5, "got %#Ix\n", io
.Information
);
1015 ok(!strcmp(buffer
, "da\xccta"), "got %s\n", debugstr_an(buffer
, io
.Information
));
1017 params
.msg_flags
= 0;
1019 io
.Status
= 0xdeadbeef;
1020 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1021 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1022 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
1023 todo_wine
ok(io
.Status
== 0xdeadbeef, "got %#x\n", io
.Status
);
1025 params
.msg_flags
= AFD_MSG_OOB
| AFD_MSG_NOT_OOB
;
1027 io
.Status
= 0xdeadbeef;
1028 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1029 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1030 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
1031 todo_wine
ok(io
.Status
== 0xdeadbeef, "got %#x\n", io
.Status
);
1033 params
.msg_flags
= AFD_MSG_OOB
;
1035 memset(buffer
, 0xcc, sizeof(buffer
));
1036 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1037 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1038 todo_wine
ok(!ret
, "got %#x\n", ret
);
1039 todo_wine
ok(!io
.Status
, "got %#x\n", io
.Status
);
1040 todo_wine
ok(io
.Information
== 1, "got %#Ix\n", io
.Information
);
1041 todo_wine
ok(buffer
[0] == 'a', "got %s\n", debugstr_an(buffer
, io
.Information
));
1043 params
.msg_flags
= AFD_MSG_NOT_OOB
| AFD_MSG_PEEK
;
1045 ret
= send(server
, "data", 4, 0);
1046 ok(ret
== 4, "got %d\n", ret
);
1048 /* wait for the data to be available */
1049 check_poll_mask(client
, event
, AFD_POLL_READ
, AFD_POLL_READ
);
1051 memset(buffer
, 0xcc, sizeof(buffer
));
1052 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1053 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1054 ok(!ret
, "got %#x\n", ret
);
1055 ok(!io
.Status
, "got %#x\n", io
.Status
);
1056 ok(io
.Information
== 4, "got %#Ix\n", io
.Information
);
1057 ok(!memcmp(buffer
, "da\xccta", 5), "got %s\n", debugstr_an(buffer
, io
.Information
));
1059 memset(buffer
, 0xcc, sizeof(buffer
));
1060 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1061 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1062 ok(!ret
, "got %#x\n", ret
);
1063 ok(!io
.Status
, "got %#x\n", io
.Status
);
1064 ok(io
.Information
== 4, "got %#Ix\n", io
.Information
);
1065 ok(!memcmp(buffer
, "da\xccta", 5), "got %s\n", debugstr_an(buffer
, io
.Information
));
1067 params
.msg_flags
= AFD_MSG_NOT_OOB
| AFD_MSG_WAITALL
;
1069 memset(buffer
, 0xcc, sizeof(buffer
));
1070 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1071 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1072 todo_wine
ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
1074 if (ret
== STATUS_PENDING
)
1076 ret
= send(server
, "s", 2, 0);
1077 ok(ret
== 2, "got %d\n", ret
);
1079 ret
= WaitForSingleObject(event
, 200);
1080 ok(!ret
, "wait timed out\n");
1081 ok(!io
.Status
, "got %#x\n", io
.Status
);
1082 ok(io
.Information
== 6, "got %#Ix\n", io
.Information
);
1083 ok(!strcmp(buffer
, "da\xcctas"), "got %s\n", debugstr_an(buffer
, io
.Information
));
1086 params
.msg_flags
= AFD_MSG_NOT_OOB
;
1088 /* Test shutdown. */
1090 memset(buffer
, 0xcc, sizeof(buffer
));
1091 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1092 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1093 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
1095 closesocket(server
);
1097 ret
= WaitForSingleObject(event
, 200);
1098 ok(!ret
, "wait timed out\n");
1099 ok(!io
.Status
, "got %#x\n", io
.Status
);
1100 ok(!io
.Information
, "got %#Ix\n", io
.Information
);
1102 ret
= shutdown(client
, SD_RECEIVE
);
1103 ok(!ret
, "got error %u\n", WSAGetLastError());
1105 memset(&io
, 0, sizeof(io
));
1106 memset(buffer
, 0xcc, sizeof(buffer
));
1107 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1108 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1109 todo_wine
ok(ret
== STATUS_PIPE_DISCONNECTED
, "got %#x\n", ret
);
1110 ok(!io
.Status
, "got status %#x\n", io
.Status
);
1111 ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
1113 closesocket(client
);
1114 closesocket(listener
);
1116 /* Test UDP datagrams. */
1118 client
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
1119 server
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
1121 memset(buffer
, 0xcc, sizeof(buffer
));
1122 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1123 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1124 todo_wine
ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
1125 if (ret
== STATUS_PENDING
)
1126 CancelIo((HANDLE
)client
);
1128 ret
= bind(client
, (const struct sockaddr
*)&bind_addr
, sizeof(bind_addr
));
1129 ok(!ret
, "got error %u\n", WSAGetLastError());
1131 ret
= getsockname(client
, (struct sockaddr
*)&addr
, &len
);
1132 ok(!ret
, "got error %u\n", WSAGetLastError());
1134 memset(buffer
, 0xcc, sizeof(buffer
));
1135 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1136 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1137 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
1139 ret
= sendto(server
, "data", 5, 0, (struct sockaddr
*)&addr
, sizeof(addr
));
1140 ok(ret
== 5, "got %d\n", ret
);
1142 ret
= WaitForSingleObject(event
, 200);
1143 ok(!ret
, "wait timed out\n");
1144 ok(!io
.Status
, "got %#x\n", io
.Status
);
1145 ok(io
.Information
== 5, "got %#Ix\n", io
.Information
);
1146 ok(!strcmp(buffer
, "da\xccta"), "got %s\n", debugstr_an(buffer
, io
.Information
));
1148 /* Test a short read of a UDP datagram. */
1150 memset(buffer
, 0xcc, sizeof(buffer
));
1151 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1152 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1153 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
1155 ret
= sendto(server
, "moredata", 9, 0, (struct sockaddr
*)&addr
, sizeof(addr
));
1156 ok(ret
== 9, "got %d\n", ret
);
1158 ret
= WaitForSingleObject(event
, 200);
1159 ok(!ret
, "wait timed out\n");
1160 ok(io
.Status
== STATUS_BUFFER_OVERFLOW
, "got %#x\n", io
.Status
);
1161 ok(io
.Information
== 6, "got %#Ix\n", io
.Information
);
1162 ok(!memcmp(buffer
, "mo\xccreda\xcc", 7), "got %s\n", debugstr_an(buffer
, io
.Information
));
1164 ret
= sendto(server
, "moredata", 9, 0, (struct sockaddr
*)&addr
, sizeof(addr
));
1165 ok(ret
== 9, "got %d\n", ret
);
1167 /* wait for the data to be available */
1168 check_poll_mask(client
, event
, AFD_POLL_READ
, AFD_POLL_READ
);
1170 memset(&io
, 0, sizeof(io
));
1171 memset(buffer
, 0xcc, sizeof(buffer
));
1172 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1173 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1174 ok(ret
== STATUS_BUFFER_OVERFLOW
, "got %#x\n", ret
);
1175 ok(io
.Status
== STATUS_BUFFER_OVERFLOW
, "got %#x\n", io
.Status
);
1176 ok(io
.Information
== 6, "got %#Ix\n", io
.Information
);
1177 ok(!memcmp(buffer
, "mo\xccreda\xcc", 7), "got %s\n", debugstr_an(buffer
, io
.Information
));
1179 /* Test closing a socket during an async. */
1181 memset(buffer
, 0xcc, sizeof(buffer
));
1182 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1183 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1184 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
1186 closesocket(client
);
1188 ret
= WaitForSingleObject(event
, 200);
1189 ok(!ret
, "wait timed out\n");
1190 todo_wine
ok(io
.Status
== STATUS_CANCELLED
, "got %#x\n", io
.Status
);
1191 ok(!io
.Information
, "got %#Ix\n", io
.Information
);
1193 closesocket(server
);
1197 static void test_event_select(void)
1199 struct afd_event_select_params params
;
1200 WSANETWORKEVENTS events
;
1201 SOCKET client
, server
;
1206 event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
1208 tcp_socketpair(&client
, &server
);
1210 memset(&io
, 0xcc, sizeof(io
));
1211 ret
= NtDeviceIoControlFile((HANDLE
)client
, NULL
, NULL
, NULL
, &io
,
1212 IOCTL_AFD_EVENT_SELECT
, NULL
, 0, NULL
, 0);
1213 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
1214 ok(io
.Status
== STATUS_INVALID_PARAMETER
, "got status %#x\n", io
.Status
);
1215 ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
1219 memset(&io
, 0xcc, sizeof(io
));
1220 ret
= NtDeviceIoControlFile((HANDLE
)client
, NULL
, NULL
, NULL
, &io
,
1221 IOCTL_AFD_EVENT_SELECT
, ¶ms
, sizeof(params
), NULL
, 0);
1222 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
1223 ok(io
.Status
== STATUS_INVALID_PARAMETER
, "got status %#x\n", io
.Status
);
1224 ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
1226 params
.event
= event
;
1228 memset(&io
, 0xcc, sizeof(io
));
1229 ret
= NtDeviceIoControlFile((HANDLE
)client
, NULL
, NULL
, NULL
, &io
,
1230 IOCTL_AFD_EVENT_SELECT
, ¶ms
, sizeof(params
), NULL
, 0);
1231 ok(!ret
, "got %#x\n", ret
);
1232 ok(!io
.Status
, "got status %#x\n", io
.Status
);
1233 ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
1235 ret
= WSAEnumNetworkEvents(client
, event
, &events
);
1236 ok(!ret
, "got error %u\n", WSAGetLastError());
1237 ok(events
.lNetworkEvents
== (FD_CONNECT
| FD_WRITE
), "got events %#x\n", events
.lNetworkEvents
);
1239 closesocket(client
);
1240 closesocket(server
);
1242 tcp_socketpair(&client
, &server
);
1244 params
.event
= event
;
1245 params
.mask
= AFD_POLL_CONNECT
;
1246 memset(&io
, 0xcc, sizeof(io
));
1247 ret
= NtDeviceIoControlFile((HANDLE
)client
, NULL
, NULL
, NULL
, &io
,
1248 IOCTL_AFD_EVENT_SELECT
, ¶ms
, sizeof(params
), NULL
, 0);
1249 ok(!ret
, "got %#x\n", ret
);
1250 ok(!io
.Status
, "got status %#x\n", io
.Status
);
1251 ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
1253 ret
= WSAEnumNetworkEvents(client
, event
, &events
);
1254 ok(!ret
, "got error %u\n", WSAGetLastError());
1255 ok(events
.lNetworkEvents
== FD_CONNECT
, "got events %#x\n", events
.lNetworkEvents
);
1257 closesocket(client
);
1258 closesocket(server
);
1260 tcp_socketpair(&client
, &server
);
1262 params
.event
= event
;
1264 memset(&io
, 0xcc, sizeof(io
));
1265 ret
= NtDeviceIoControlFile((HANDLE
)client
, NULL
, NULL
, NULL
, &io
,
1266 IOCTL_AFD_EVENT_SELECT
, ¶ms
, sizeof(params
), NULL
, 0);
1267 ok(!ret
, "got %#x\n", ret
);
1268 ok(!io
.Status
, "got status %#x\n", io
.Status
);
1269 ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
1273 memset(&io
, 0xcc, sizeof(io
));
1274 ret
= NtDeviceIoControlFile((HANDLE
)client
, NULL
, NULL
, NULL
, &io
,
1275 IOCTL_AFD_EVENT_SELECT
, ¶ms
, sizeof(params
), NULL
, 0);
1276 ok(!ret
, "got %#x\n", ret
);
1277 ok(!io
.Status
, "got status %#x\n", io
.Status
);
1278 ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
1280 ret
= WSAEnumNetworkEvents(client
, event
, &events
);
1281 ok(!ret
, "got error %u\n", WSAGetLastError());
1282 ok(!events
.lNetworkEvents
, "got events %#x\n", events
.lNetworkEvents
);
1284 closesocket(client
);
1285 closesocket(server
);
1290 static void test_get_events(void)
1292 const struct sockaddr_in invalid_addr
=
1294 .sin_family
= AF_INET
,
1295 .sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
),
1298 struct afd_get_events_params params
;
1299 WSANETWORKEVENTS events
;
1300 SOCKET client
, server
;
1306 event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
1308 tcp_socketpair(&client
, &server
);
1310 ret
= WSAEventSelect(client
, event
, FD_ACCEPT
| FD_CLOSE
| FD_CONNECT
| FD_OOB
| FD_READ
| FD_WRITE
);
1311 ok(!ret
, "got error %u\n", GetLastError());
1313 memset(¶ms
, 0xcc, sizeof(params
));
1314 memset(&io
, 0xcc, sizeof(io
));
1315 ret
= NtDeviceIoControlFile((HANDLE
)client
, NULL
, NULL
, NULL
, &io
,
1316 IOCTL_AFD_GET_EVENTS
, NULL
, 0, NULL
, 0);
1317 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
1319 memset(¶ms
, 0xcc, sizeof(params
));
1320 memset(&io
, 0xcc, sizeof(io
));
1321 ret
= NtDeviceIoControlFile((HANDLE
)client
, NULL
, NULL
, NULL
, &io
,
1322 IOCTL_AFD_GET_EVENTS
, NULL
, 0, ¶ms
, sizeof(params
));
1323 ok(!ret
, "got %#x\n", ret
);
1324 ok(params
.flags
== (AFD_POLL_WRITE
| AFD_POLL_CONNECT
), "got flags %#x\n", params
.flags
);
1325 for (i
= 0; i
< ARRAY_SIZE(params
.status
); ++i
)
1326 ok(!params
.status
[i
], "got status[%u] %#x\n", i
, params
.status
[i
]);
1328 ret
= WSAEnumNetworkEvents(client
, event
, &events
);
1329 ok(!ret
, "got error %u\n", GetLastError());
1330 ok(!events
.lNetworkEvents
, "got events %#x\n", events
.lNetworkEvents
);
1332 closesocket(client
);
1333 closesocket(server
);
1335 tcp_socketpair(&client
, &server
);
1337 ret
= WSAEventSelect(client
, event
, FD_ACCEPT
| FD_CLOSE
| FD_CONNECT
| FD_OOB
| FD_READ
| FD_WRITE
);
1338 ok(!ret
, "got error %u\n", GetLastError());
1340 ret
= WSAEnumNetworkEvents(client
, event
, &events
);
1341 ok(!ret
, "got error %u\n", GetLastError());
1342 ok(events
.lNetworkEvents
== (FD_WRITE
| FD_CONNECT
), "got events %#x\n", events
.lNetworkEvents
);
1344 memset(¶ms
, 0xcc, sizeof(params
));
1345 memset(&io
, 0xcc, sizeof(io
));
1346 ret
= NtDeviceIoControlFile((HANDLE
)client
, NULL
, NULL
, NULL
, &io
,
1347 IOCTL_AFD_GET_EVENTS
, NULL
, 0, ¶ms
, sizeof(params
));
1348 ok(!ret
, "got %#x\n", ret
);
1349 ok(!params
.flags
, "got flags %#x\n", params
.flags
);
1350 for (i
= 0; i
< ARRAY_SIZE(params
.status
); ++i
)
1351 ok(!params
.status
[i
], "got status[%u] %#x\n", i
, params
.status
[i
]);
1353 closesocket(client
);
1354 closesocket(server
);
1356 /* Test a failed connection. The following call can take over 2 seconds to
1357 * complete, so make the test interactive-only. */
1359 if (winetest_interactive
)
1361 client
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
1364 ret
= WSAEventSelect(client
, event
, FD_CONNECT
);
1365 ok(!ret
, "got error %u\n", GetLastError());
1367 ret
= connect(client
, (struct sockaddr
*)&invalid_addr
, sizeof(invalid_addr
));
1368 ok(ret
== -1, "expected failure\n");
1369 ok(WSAGetLastError() == WSAEWOULDBLOCK
, "got error %u\n", WSAGetLastError());
1371 ret
= WaitForSingleObject(event
, 10000);
1372 ok(!ret
, "got %#x\n", ret
);
1374 memset(¶ms
, 0xcc, sizeof(params
));
1375 memset(&io
, 0xcc, sizeof(io
));
1376 ret
= NtDeviceIoControlFile((HANDLE
)client
, NULL
, NULL
, NULL
, &io
,
1377 IOCTL_AFD_GET_EVENTS
, NULL
, 0, ¶ms
, sizeof(params
));
1378 ok(!ret
, "got %#x\n", ret
);
1379 ok(params
.flags
== AFD_POLL_CONNECT_ERR
, "got flags %#x\n", params
.flags
);
1380 for (i
= 0; i
< ARRAY_SIZE(params
.status
); ++i
)
1382 if (i
== AFD_POLL_BIT_CONNECT_ERR
)
1383 ok(params
.status
[i
] == STATUS_CONNECTION_REFUSED
, "got status[%u] %#x\n", i
, params
.status
[i
]);
1385 ok(!params
.status
[i
], "got status[%u] %#x\n", i
, params
.status
[i
]);
1389 ret
= WSAEventSelect(client
, event
, FD_CONNECT
);
1390 ok(!ret
, "got error %u\n", GetLastError());
1392 ret
= WaitForSingleObject(event
, 0);
1393 ok(ret
== WAIT_TIMEOUT
, "got %#x\n", ret
);
1395 memset(¶ms
, 0xcc, sizeof(params
));
1396 memset(&io
, 0xcc, sizeof(io
));
1397 ret
= NtDeviceIoControlFile((HANDLE
)client
, NULL
, NULL
, NULL
, &io
,
1398 IOCTL_AFD_GET_EVENTS
, NULL
, 0, ¶ms
, sizeof(params
));
1399 ok(!ret
, "got %#x\n", ret
);
1400 ok(!params
.flags
, "got flags %#x\n", params
.flags
);
1401 for (i
= 0; i
< ARRAY_SIZE(params
.status
); ++i
)
1403 if (i
== AFD_POLL_BIT_CONNECT_ERR
)
1404 ok(params
.status
[i
] == STATUS_CONNECTION_REFUSED
, "got status[%u] %#x\n", i
, params
.status
[i
]);
1406 ok(!params
.status
[i
], "got status[%u] %#x\n", i
, params
.status
[i
]);
1409 closesocket(client
);
1415 static void test_bind(void)
1417 const struct sockaddr_in invalid_addr
= {.sin_family
= AF_INET
, .sin_addr
.s_addr
= inet_addr("192.0.2.0")};
1418 const struct sockaddr_in bind_addr
= {.sin_family
= AF_INET
, .sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
)};
1419 struct afd_bind_params params
= {0};
1420 struct sockaddr_in addr
, addr2
;
1421 struct hostent
*host
;
1428 event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
1429 memset(&addr
, 0xcc, sizeof(addr
));
1431 s
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
1433 params
.addr
.sa_family
= 0xdead;
1434 ret
= NtDeviceIoControlFile((HANDLE
)s
, event
, NULL
, NULL
, &io
, IOCTL_AFD_BIND
,
1435 ¶ms
, sizeof(params
), &addr
, sizeof(addr
));
1436 ok(ret
== STATUS_INVALID_ADDRESS
, "got %#x\n", ret
);
1438 memcpy(¶ms
.addr
, &bind_addr
, sizeof(bind_addr
));
1439 ret
= NtDeviceIoControlFile((HANDLE
)s
, event
, NULL
, NULL
, &io
, IOCTL_AFD_BIND
,
1440 ¶ms
, sizeof(params
) - 1, &addr
, sizeof(addr
));
1441 ok(ret
== STATUS_INVALID_ADDRESS
, "got %#x\n", ret
);
1443 memcpy(¶ms
.addr
, &bind_addr
, sizeof(bind_addr
));
1444 ret
= NtDeviceIoControlFile((HANDLE
)s
, event
, NULL
, NULL
, &io
, IOCTL_AFD_BIND
,
1445 ¶ms
, offsetof(struct afd_bind_params
, addr
.sa_data
), &addr
, sizeof(addr
));
1446 ok(ret
== STATUS_INVALID_ADDRESS
, "got %#x\n", ret
);
1448 memcpy(¶ms
.addr
, &bind_addr
, sizeof(bind_addr
));
1449 ret
= NtDeviceIoControlFile((HANDLE
)s
, event
, NULL
, NULL
, &io
, IOCTL_AFD_BIND
,
1450 ¶ms
, offsetof(struct afd_bind_params
, addr
.sa_data
) - 1, &addr
, sizeof(addr
));
1451 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
1453 memcpy(¶ms
.addr
, &invalid_addr
, sizeof(invalid_addr
));
1454 ret
= NtDeviceIoControlFile((HANDLE
)s
, event
, NULL
, NULL
, &io
, IOCTL_AFD_BIND
,
1455 ¶ms
, sizeof(params
), &addr
, sizeof(addr
));
1456 todo_wine
ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
1457 ret
= WaitForSingleObject(event
, 0);
1458 ok(!ret
, "got %#x\n", ret
);
1459 ok(io
.Status
== STATUS_INVALID_ADDRESS_COMPONENT
, "got %#x\n", io
.Status
);
1461 memcpy(¶ms
.addr
, &bind_addr
, sizeof(bind_addr
));
1462 ret
= NtDeviceIoControlFile((HANDLE
)s
, event
, NULL
, NULL
, &io
, IOCTL_AFD_BIND
,
1463 ¶ms
, sizeof(params
), &addr
, sizeof(addr
) - 1);
1464 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
1466 memcpy(¶ms
.addr
, &bind_addr
, sizeof(bind_addr
));
1467 memset(&io
, 0xcc, sizeof(io
));
1468 memset(&addr
, 0xcc, sizeof(addr
));
1469 ret
= NtDeviceIoControlFile((HANDLE
)s
, event
, NULL
, NULL
, &io
, IOCTL_AFD_BIND
,
1470 ¶ms
, sizeof(params
), &addr
, sizeof(addr
));
1471 todo_wine
ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
1472 ret
= WaitForSingleObject(event
, 0);
1473 ok(!ret
, "got %#x\n", ret
);
1474 ok(!io
.Status
, "got %#x\n", io
.Status
);
1475 ok(io
.Information
== sizeof(addr
), "got %#Ix\n", io
.Information
);
1476 ok(addr
.sin_family
== AF_INET
, "got family %u\n", addr
.sin_family
);
1477 ok(addr
.sin_addr
.s_addr
== htonl(INADDR_LOOPBACK
), "got address %#08x\n", addr
.sin_addr
.s_addr
);
1478 ok(addr
.sin_port
, "expected nonzero port\n");
1480 /* getsockname() returns EINVAL here. Possibly the socket name is cached (in shared memory?) */
1481 memset(&addr2
, 0xcc, sizeof(addr2
));
1482 ret
= NtDeviceIoControlFile((HANDLE
)s
, event
, NULL
, NULL
, &io
,
1483 IOCTL_AFD_GETSOCKNAME
, NULL
, 0, &addr2
, sizeof(addr2
));
1484 ok(!ret
, "got %#x\n", ret
);
1485 ok(!memcmp(&addr
, &addr2
, sizeof(addr
)), "addresses didn't match\n");
1487 ret
= NtDeviceIoControlFile((HANDLE
)s
, event
, NULL
, NULL
, &io
, IOCTL_AFD_BIND
,
1488 ¶ms
, sizeof(params
), &addr
, sizeof(addr
));
1489 ok(ret
== STATUS_ADDRESS_ALREADY_ASSOCIATED
, "got %#x\n", ret
);
1491 s2
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
1493 memcpy(¶ms
.addr
, &addr2
, sizeof(addr2
));
1494 memset(&io
, 0xcc, sizeof(io
));
1495 memset(&addr
, 0xcc, sizeof(addr
));
1496 ret
= NtDeviceIoControlFile((HANDLE
)s2
, event
, NULL
, NULL
, &io
, IOCTL_AFD_BIND
,
1497 ¶ms
, sizeof(params
), &addr
, sizeof(addr
));
1498 todo_wine
ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
1499 ret
= WaitForSingleObject(event
, 0);
1500 ok(!ret
, "got %#x\n", ret
);
1501 ok(io
.Status
== STATUS_SHARING_VIOLATION
, "got %#x\n", io
.Status
);
1502 ok(!io
.Information
, "got %#Ix\n", io
.Information
);
1509 s
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
1511 memcpy(¶ms
.addr
, &bind_addr
, sizeof(bind_addr
));
1512 memset(&io
, 0xcc, sizeof(io
));
1513 memset(&addr
, 0xcc, sizeof(addr
));
1514 ret
= NtDeviceIoControlFile((HANDLE
)s
, event
, NULL
, NULL
, &io
, IOCTL_AFD_BIND
,
1515 ¶ms
, sizeof(params
), &addr
, sizeof(addr
));
1516 todo_wine
ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
1517 ret
= WaitForSingleObject(event
, 0);
1518 ok(!ret
, "got %#x\n", ret
);
1519 ok(!io
.Status
, "got %#x\n", io
.Status
);
1520 ok(io
.Information
== sizeof(addr
), "got %#Ix\n", io
.Information
);
1521 ok(addr
.sin_family
== AF_INET
, "got family %u\n", addr
.sin_family
);
1522 ok(addr
.sin_addr
.s_addr
== htonl(INADDR_LOOPBACK
), "got address %#08x\n", addr
.sin_addr
.s_addr
);
1523 ok(addr
.sin_port
, "expected nonzero port\n");
1525 memset(&addr2
, 0xcc, sizeof(addr2
));
1526 ret
= NtDeviceIoControlFile((HANDLE
)s
, event
, NULL
, NULL
, &io
,
1527 IOCTL_AFD_GETSOCKNAME
, NULL
, 0, &addr2
, sizeof(addr2
));
1528 ok(!ret
, "got %#x\n", ret
);
1529 ok(!memcmp(&addr
, &addr2
, sizeof(addr
)), "addresses didn't match\n");
1533 host
= gethostbyname("");
1534 if (host
&& host
->h_length
== 4)
1536 for (i
= 0; host
->h_addr_list
[i
]; ++i
)
1538 ULONG in_addr
= *(ULONG
*)host
->h_addr_list
[i
];
1540 s
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
1542 ((struct sockaddr_in
*)¶ms
.addr
)->sin_addr
.s_addr
= in_addr
;
1543 memset(&io
, 0xcc, sizeof(io
));
1544 memset(&addr
, 0xcc, sizeof(addr
));
1545 ret
= NtDeviceIoControlFile((HANDLE
)s
, event
, NULL
, NULL
, &io
, IOCTL_AFD_BIND
,
1546 ¶ms
, sizeof(params
), &addr
, sizeof(addr
));
1547 todo_wine
ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
1548 ret
= WaitForSingleObject(event
, 0);
1549 ok(!ret
, "got %#x\n", ret
);
1550 ok(!io
.Status
, "got %#x\n", io
.Status
);
1551 ok(io
.Information
== sizeof(addr
), "got %#Ix\n", io
.Information
);
1552 ok(addr
.sin_family
== AF_INET
, "got family %u\n", addr
.sin_family
);
1553 ok(addr
.sin_addr
.s_addr
== in_addr
, "expected address %#08x, got %#08x\n", in_addr
, addr
.sin_addr
.s_addr
);
1554 ok(addr
.sin_port
, "expected nonzero port\n");
1556 memset(&addr2
, 0xcc, sizeof(addr2
));
1557 ret
= NtDeviceIoControlFile((HANDLE
)s
, event
, NULL
, NULL
, &io
,
1558 IOCTL_AFD_GETSOCKNAME
, NULL
, 0, &addr2
, sizeof(addr2
));
1559 ok(!ret
, "got %#x\n", ret
);
1560 ok(!memcmp(&addr
, &addr2
, sizeof(addr
)), "addresses didn't match\n");
1569 static void test_getsockname(void)
1571 const struct sockaddr_in bind_addr
= {.sin_family
= AF_INET
, .sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
)};
1572 struct sockaddr addr
, addr2
;
1573 SOCKET server
, client
;
1578 event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
1580 tcp_socketpair(&client
, &server
);
1582 memset(&addr
, 0xcc, sizeof(addr
));
1583 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1584 IOCTL_AFD_GETSOCKNAME
, NULL
, 0, &addr
, sizeof(addr
) - 1);
1585 ok(ret
== STATUS_BUFFER_TOO_SMALL
, "got %#x\n", ret
);
1587 memset(&io
, 0xcc, sizeof(io
));
1588 memset(&addr
, 0xcc, sizeof(addr
));
1589 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1590 IOCTL_AFD_GETSOCKNAME
, NULL
, 0, &addr
, sizeof(addr
));
1591 ok(!ret
, "got %#x\n", ret
);
1592 ok(!io
.Status
, "got %#x\n", io
.Status
);
1593 ok(io
.Information
== sizeof(addr
), "got %#Ix\n", io
.Information
);
1594 len
= sizeof(addr2
);
1595 ret
= getsockname(client
, (struct sockaddr
*)&addr2
, &len
);
1596 ok(!ret
, "got error %u\n", WSAGetLastError());
1597 ok(!memcmp(&addr
, &addr2
, sizeof(struct sockaddr
)), "addresses didn't match\n");
1599 memset(&io
, 0xcc, sizeof(io
));
1600 memset(&addr
, 0xcc, sizeof(addr
));
1601 ret
= NtDeviceIoControlFile((HANDLE
)server
, event
, NULL
, NULL
, &io
,
1602 IOCTL_AFD_GETSOCKNAME
, NULL
, 0, &addr
, sizeof(addr
));
1603 ok(!ret
, "got %#x\n", ret
);
1604 ok(!io
.Status
, "got %#x\n", io
.Status
);
1605 ok(io
.Information
== sizeof(addr
), "got %#Ix\n", io
.Information
);
1606 len
= sizeof(addr2
);
1607 ret
= getsockname(server
, (struct sockaddr
*)&addr2
, &len
);
1608 ok(!ret
, "got error %u\n", WSAGetLastError());
1609 ok(!memcmp(&addr
, &addr2
, sizeof(struct sockaddr
)), "addresses didn't match\n");
1611 closesocket(server
);
1612 closesocket(client
);
1614 client
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
1616 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1617 IOCTL_AFD_GETSOCKNAME
, NULL
, 0, &addr
, sizeof(addr
));
1618 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
1620 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1621 IOCTL_AFD_GETSOCKNAME
, NULL
, 0, &addr
, sizeof(addr
) - 1);
1622 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
1624 ret
= bind(client
, (const struct sockaddr
*)&bind_addr
, sizeof(bind_addr
));
1625 ok(!ret
, "got error %u\n", WSAGetLastError());
1627 memset(&io
, 0xcc, sizeof(io
));
1628 memset(&addr
, 0xcc, sizeof(addr
));
1629 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1630 IOCTL_AFD_GETSOCKNAME
, NULL
, 0, &addr
, sizeof(addr
));
1631 ok(!ret
, "got %#x\n", ret
);
1632 ok(!io
.Status
, "got %#x\n", io
.Status
);
1633 ok(io
.Information
== sizeof(addr
), "got %#Ix\n", io
.Information
);
1634 len
= sizeof(addr2
);
1635 ret
= getsockname(client
, (struct sockaddr
*)&addr2
, &len
);
1636 ok(!ret
, "got error %u\n", WSAGetLastError());
1637 ok(!memcmp(&addr
, &addr2
, sizeof(struct sockaddr
)), "addresses didn't match\n");
1639 closesocket(client
);
1648 WSAStartup(MAKEWORD(2, 2), &data
);
1652 test_poll_completion_port();
1654 test_event_select();