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
|| WSAGetLastError() == WSAEWOULDBLOCK
, "got error %u\n", WSAGetLastError());
453 ret
= WaitForSingleObject(event
, 10000);
454 ok(!ret
, "got %#x\n", ret
);
455 ok(!io
.Status
, "got %#x\n", io
.Status
);
456 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[1]), "got %#Ix\n", io
.Information
);
457 ok(out_params
->count
== 1, "got count %u\n", out_params
->count
);
458 ok(out_params
->sockets
[0].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
459 ok(out_params
->sockets
[0].flags
== AFD_POLL_CONNECT_ERR
, "got flags %#x\n", out_params
->sockets
[0].flags
);
460 ok(out_params
->sockets
[0].status
== STATUS_CONNECTION_REFUSED
, "got status %#x\n", out_params
->sockets
[0].status
);
465 /* Test supplying multiple handles to the ioctl. */
468 ret
= getsockname(listener
, (struct sockaddr
*)&addr
, &len
);
469 ok(!ret
, "got error %u\n", WSAGetLastError());
471 client
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
472 ret
= connect(client
, (struct sockaddr
*)&addr
, sizeof(addr
));
473 ok(!ret
, "got error %u\n", WSAGetLastError());
474 server
= accept(listener
, NULL
, NULL
);
475 ok(server
!= -1, "got error %u\n", WSAGetLastError());
477 in_params
->count
= 2;
478 in_params
->sockets
[0].socket
= client
;
479 in_params
->sockets
[0].flags
= AFD_POLL_READ
;
480 in_params
->sockets
[1].socket
= server
;
481 in_params
->sockets
[1].flags
= AFD_POLL_READ
;
483 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
484 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
485 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
487 params_size
= offsetof(struct afd_poll_params
, sockets
[2]);
489 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
490 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
491 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
493 ret
= send(client
, "data", 5, 0);
494 ok(ret
== 5, "got %d\n", ret
);
496 ret
= WaitForSingleObject(event
, 100);
497 ok(!ret
, "got %#x\n", ret
);
498 ok(!io
.Status
, "got %#x\n", io
.Status
);
499 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[1]), "got %#Ix\n", io
.Information
);
500 ok(out_params
->count
== 1, "got count %u\n", out_params
->count
);
501 ok(out_params
->sockets
[0].socket
== server
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
502 ok(out_params
->sockets
[0].flags
== AFD_POLL_READ
, "got flags %#x\n", out_params
->sockets
[0].flags
);
503 ok(!out_params
->sockets
[0].status
, "got status %#x\n", out_params
->sockets
[0].status
);
505 in_params
->count
= 2;
506 in_params
->sockets
[0].socket
= client
;
507 in_params
->sockets
[0].flags
= AFD_POLL_READ
| AFD_POLL_WRITE
;
508 in_params
->sockets
[1].socket
= server
;
509 in_params
->sockets
[1].flags
= AFD_POLL_READ
| AFD_POLL_WRITE
;
511 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
512 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
513 ok(!ret
, "got %#x\n", ret
);
514 ok(!io
.Status
, "got %#x\n", io
.Status
);
515 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[2]), "got %#Ix\n", io
.Information
);
516 ok(out_params
->count
== 2, "got count %u\n", out_params
->count
);
517 ok(out_params
->sockets
[0].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
518 ok(out_params
->sockets
[0].flags
== AFD_POLL_WRITE
, "got flags %#x\n", out_params
->sockets
[0].flags
);
519 ok(!out_params
->sockets
[0].status
, "got status %#x\n", out_params
->sockets
[0].status
);
520 ok(out_params
->sockets
[1].socket
== server
, "got socket %#Ix\n", out_params
->sockets
[1].socket
);
521 ok(out_params
->sockets
[1].flags
== (AFD_POLL_READ
| AFD_POLL_WRITE
),
522 "got flags %#x\n", out_params
->sockets
[1].flags
);
523 ok(!out_params
->sockets
[1].status
, "got status %#x\n", out_params
->sockets
[1].status
);
525 in_params
->count
= 2;
526 in_params
->sockets
[0].socket
= client
;
527 in_params
->sockets
[0].flags
= AFD_POLL_READ
| AFD_POLL_WRITE
;
528 in_params
->sockets
[1].socket
= server
;
529 in_params
->sockets
[1].flags
= AFD_POLL_READ
| AFD_POLL_WRITE
;
531 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
532 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
533 ok(!ret
, "got %#x\n", ret
);
534 ok(!io
.Status
, "got %#x\n", io
.Status
);
535 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[2]), "got %#Ix\n", io
.Information
);
536 ok(out_params
->count
== 2, "got count %u\n", out_params
->count
);
537 ok(out_params
->sockets
[0].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
538 ok(out_params
->sockets
[0].flags
== AFD_POLL_WRITE
, "got flags %#x\n", out_params
->sockets
[0].flags
);
539 ok(!out_params
->sockets
[0].status
, "got status %#x\n", out_params
->sockets
[0].status
);
540 ok(out_params
->sockets
[1].socket
== server
, "got socket %#Ix\n", out_params
->sockets
[1].socket
);
541 ok(out_params
->sockets
[1].flags
== (AFD_POLL_READ
| AFD_POLL_WRITE
),
542 "got flags %#x\n", out_params
->sockets
[1].flags
);
543 ok(!out_params
->sockets
[1].status
, "got status %#x\n", out_params
->sockets
[1].status
);
545 /* Close a socket while polling on another. */
547 in_params
->timeout
= -100 * 10000;
548 in_params
->count
= 1;
549 in_params
->sockets
[0].socket
= client
;
550 in_params
->sockets
[0].flags
= AFD_POLL_READ
;
551 params_size
= offsetof(struct afd_poll_params
, sockets
[1]);
553 ret
= NtDeviceIoControlFile((HANDLE
)server
, event
, NULL
, NULL
, &io
,
554 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
555 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
559 ret
= WaitForSingleObject(event
, 1000);
560 ok(!ret
, "got %#x\n", ret
);
561 todo_wine
ok(io
.Status
== STATUS_TIMEOUT
, "got %#x\n", io
.Status
);
562 todo_wine
ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[0]), "got %#Ix\n", io
.Information
);
563 todo_wine
ok(!out_params
->count
, "got count %u\n", out_params
->count
);
567 closesocket(listener
);
569 /* Test UDP sockets. */
571 client
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
572 server
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
574 check_poll(client
, event
, AFD_POLL_WRITE
);
575 check_poll(server
, event
, AFD_POLL_WRITE
);
577 ret
= bind(client
, (const struct sockaddr
*)&bind_addr
, sizeof(bind_addr
));
578 ok(!ret
, "got error %u\n", WSAGetLastError());
580 ret
= getsockname(client
, (struct sockaddr
*)&addr
, &len
);
581 ok(!ret
, "got error %u\n", WSAGetLastError());
583 check_poll(client
, event
, AFD_POLL_WRITE
);
584 check_poll(server
, event
, AFD_POLL_WRITE
);
586 in_params
->timeout
= -1000 * 10000;
587 in_params
->count
= 1;
588 in_params
->sockets
[0].socket
= client
;
589 in_params
->sockets
[0].flags
= (~0) & ~AFD_POLL_WRITE
;
590 params_size
= offsetof(struct afd_poll_params
, sockets
[1]);
592 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
593 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
594 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
596 ret
= sendto(server
, "data", 5, 0, (struct sockaddr
*)&addr
, sizeof(addr
));
597 ok(ret
== 5, "got %d\n", ret
);
599 ret
= WaitForSingleObject(event
, 100);
600 ok(!ret
, "got %#x\n", ret
);
601 ok(!io
.Status
, "got %#x\n", io
.Status
);
602 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[1]), "got %#Ix\n", io
.Information
);
603 ok(out_params
->count
== 1, "got count %u\n", out_params
->count
);
604 ok(out_params
->sockets
[0].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
605 ok(out_params
->sockets
[0].flags
== AFD_POLL_READ
, "got flags %#x\n", out_params
->sockets
[0].flags
);
606 ok(!out_params
->sockets
[0].status
, "got status %#x\n", out_params
->sockets
[0].status
);
611 /* Passing any invalid sockets yields STATUS_INVALID_HANDLE.
613 * Note however that WSAPoll() happily accepts invalid sockets. It seems
614 * user-side cached data is used: closing a handle with CloseHandle() before
615 * passing it to WSAPoll() yields ENOTSOCK. */
617 tcp_socketpair(&client
, &server
);
619 in_params
->count
= 2;
620 in_params
->sockets
[0].socket
= 0xabacab;
621 in_params
->sockets
[0].flags
= AFD_POLL_READ
| AFD_POLL_WRITE
;
622 in_params
->sockets
[1].socket
= client
;
623 in_params
->sockets
[1].flags
= AFD_POLL_READ
| AFD_POLL_WRITE
;
624 params_size
= offsetof(struct afd_poll_params
, sockets
[2]);
626 memset(&io
, 0, sizeof(io
));
627 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
628 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
629 ok(ret
== STATUS_INVALID_HANDLE
, "got %#x\n", ret
);
630 todo_wine
ok(!io
.Status
, "got %#x\n", io
.Status
);
631 ok(!io
.Information
, "got %#Ix\n", io
.Information
);
633 /* Test passing the same handle twice. */
635 in_params
->count
= 3;
636 in_params
->sockets
[0].socket
= client
;
637 in_params
->sockets
[0].flags
= AFD_POLL_READ
| AFD_POLL_WRITE
;
638 in_params
->sockets
[1].socket
= client
;
639 in_params
->sockets
[1].flags
= AFD_POLL_READ
| AFD_POLL_WRITE
;
640 in_params
->sockets
[2].socket
= client
;
641 in_params
->sockets
[2].flags
= AFD_POLL_READ
| AFD_POLL_WRITE
| AFD_POLL_CONNECT
;
642 params_size
= offsetof(struct afd_poll_params
, sockets
[3]);
644 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
645 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
646 ok(!ret
, "got %#x\n", ret
);
647 ok(!io
.Status
, "got %#x\n", io
.Status
);
648 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[3]), "got %#Ix\n", io
.Information
);
649 ok(out_params
->count
== 3, "got count %u\n", out_params
->count
);
650 ok(out_params
->sockets
[0].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
651 ok(out_params
->sockets
[0].flags
== AFD_POLL_WRITE
, "got flags %#x\n", out_params
->sockets
[0].flags
);
652 ok(!out_params
->sockets
[0].status
, "got status %#x\n", out_params
->sockets
[0].status
);
653 ok(out_params
->sockets
[1].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[1].socket
);
654 ok(out_params
->sockets
[1].flags
== AFD_POLL_WRITE
, "got flags %#x\n", out_params
->sockets
[1].flags
);
655 ok(!out_params
->sockets
[1].status
, "got status %#x\n", out_params
->sockets
[1].status
);
656 ok(out_params
->sockets
[2].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[2].socket
);
657 ok(out_params
->sockets
[2].flags
== (AFD_POLL_WRITE
| AFD_POLL_CONNECT
),
658 "got flags %#x\n", out_params
->sockets
[2].flags
);
659 ok(!out_params
->sockets
[2].status
, "got status %#x\n", out_params
->sockets
[2].status
);
661 in_params
->count
= 2;
662 in_params
->sockets
[0].socket
= client
;
663 in_params
->sockets
[0].flags
= AFD_POLL_READ
;
664 in_params
->sockets
[1].socket
= client
;
665 in_params
->sockets
[1].flags
= AFD_POLL_READ
;
666 params_size
= offsetof(struct afd_poll_params
, sockets
[2]);
668 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
669 IOCTL_AFD_POLL
, in_params
, params_size
, out_params
, params_size
);
670 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
672 ret
= send(server
, "data", 5, 0);
673 ok(ret
== 5, "got %d\n", ret
);
675 ret
= WaitForSingleObject(event
, 100);
676 ok(!ret
, "got %#x\n", ret
);
677 ok(!io
.Status
, "got %#x\n", io
.Status
);
678 ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[1]), "got %#Ix\n", io
.Information
);
679 ok(out_params
->count
== 1, "got count %u\n", out_params
->count
);
680 ok(out_params
->sockets
[0].socket
== client
, "got socket %#Ix\n", out_params
->sockets
[0].socket
);
681 ok(out_params
->sockets
[0].flags
== AFD_POLL_READ
, "got flags %#x\n", out_params
->sockets
[0].flags
);
682 ok(!out_params
->sockets
[0].status
, "got status %#x\n", out_params
->sockets
[0].status
);
691 static void test_poll_completion_port(void)
693 struct afd_poll_params params
= {0};
694 LARGE_INTEGER zero
= {{0}};
695 SOCKET client
, server
;
696 ULONG_PTR key
, value
;
701 event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
702 tcp_socketpair(&client
, &server
);
703 port
= CreateIoCompletionPort((HANDLE
)client
, NULL
, 0, 0);
705 params
.timeout
= -100 * 10000;
707 params
.sockets
[0].socket
= client
;
708 params
.sockets
[0].flags
= AFD_POLL_WRITE
;
709 params
.sockets
[0].status
= 0xdeadbeef;
711 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
712 IOCTL_AFD_POLL
, ¶ms
, sizeof(params
), ¶ms
, sizeof(params
));
713 ok(!ret
, "got %#x\n", ret
);
715 ret
= NtRemoveIoCompletion(port
, &key
, &value
, &io
, &zero
);
716 ok(ret
== STATUS_TIMEOUT
, "got %#x\n", ret
);
718 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, (void *)0xdeadbeef, &io
,
719 IOCTL_AFD_POLL
, ¶ms
, sizeof(params
), ¶ms
, sizeof(params
));
720 ok(!ret
, "got %#x\n", ret
);
722 ret
= NtRemoveIoCompletion(port
, &key
, &value
, &io
, &zero
);
723 ok(!ret
, "got %#x\n", ret
);
724 ok(!key
, "got key %#Ix\n", key
);
725 ok(value
== 0xdeadbeef, "got value %#Ix\n", value
);
729 params
.sockets
[0].socket
= client
;
730 params
.sockets
[0].flags
= AFD_POLL_READ
;
731 params
.sockets
[0].status
= 0xdeadbeef;
733 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, (void *)0xdeadbeef, &io
,
734 IOCTL_AFD_POLL
, ¶ms
, sizeof(params
), ¶ms
, sizeof(params
));
735 ok(!ret
, "got %#x\n", ret
);
737 ret
= NtRemoveIoCompletion(port
, &key
, &value
, &io
, &zero
);
738 ok(!ret
, "got %#x\n", ret
);
739 ok(!key
, "got key %#Ix\n", key
);
740 ok(value
== 0xdeadbeef, "got value %#Ix\n", value
);
742 /* Close a socket while polling on another. */
744 params
.timeout
= -100 * 10000;
746 params
.sockets
[0].socket
= server
;
747 params
.sockets
[0].flags
= AFD_POLL_READ
;
748 params
.sockets
[0].status
= 0xdeadbeef;
750 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, (void *)0xdeadbeef, &io
,
751 IOCTL_AFD_POLL
, ¶ms
, sizeof(params
), ¶ms
, sizeof(params
));
752 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
756 ret
= WaitForSingleObject(event
, 1000);
757 ok(!ret
, "got %#x\n", ret
);
758 todo_wine
ok(io
.Status
== STATUS_TIMEOUT
, "got %#x\n", io
.Status
);
759 todo_wine
ok(io
.Information
== offsetof(struct afd_poll_params
, sockets
[0]), "got %#Ix\n", io
.Information
);
760 todo_wine
ok(!params
.count
, "got count %u\n", params
.count
);
762 ret
= NtRemoveIoCompletion(port
, &key
, &value
, &io
, &zero
);
763 ok(!ret
, "got %#x\n", ret
);
764 ok(!key
, "got key %#Ix\n", key
);
765 ok(value
== 0xdeadbeef, "got value %#Ix\n", value
);
772 static void test_recv(void)
774 const struct sockaddr_in bind_addr
= {.sin_family
= AF_INET
, .sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
)};
775 struct afd_recv_params params
= {0};
776 SOCKET client
, server
, listener
;
777 struct sockaddr addr
;
784 event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
786 listener
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
787 ret
= bind(listener
, (const struct sockaddr
*)&bind_addr
, sizeof(bind_addr
));
788 ok(!ret
, "got error %u\n", WSAGetLastError());
789 ret
= listen(listener
, 1);
790 ok(!ret
, "got error %u\n", WSAGetLastError());
792 ret
= getsockname(listener
, (struct sockaddr
*)&addr
, &len
);
793 ok(!ret
, "got error %u\n", WSAGetLastError());
795 memset(&io
, 0, sizeof(io
));
796 ret
= NtDeviceIoControlFile((HANDLE
)listener
, event
, NULL
, NULL
, &io
, IOCTL_AFD_RECV
, NULL
, 0, NULL
, 0);
797 todo_wine
ok(ret
== STATUS_INVALID_CONNECTION
, "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 client
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
802 ret
= connect(client
, (struct sockaddr
*)&addr
, sizeof(addr
));
803 ok(!ret
, "got error %u\n", WSAGetLastError());
804 server
= accept(listener
, NULL
, NULL
);
805 ok(server
!= -1, "got error %u\n", WSAGetLastError());
807 memset(&io
, 0, sizeof(io
));
808 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
, IOCTL_AFD_RECV
, NULL
, 0, NULL
, 0);
809 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
810 todo_wine
ok(!io
.Status
, "got status %#x\n", io
.Status
);
811 ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
813 wsabufs
[0].len
= sizeof(buffer
);
814 wsabufs
[0].buf
= buffer
;
815 params
.buffers
= wsabufs
;
817 params
.msg_flags
= AFD_MSG_NOT_OOB
;
819 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
820 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
) - 1, NULL
, 0);
821 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
823 memset(&io
, 0, sizeof(io
));
824 memset(buffer
, 0xcc, sizeof(buffer
));
825 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
826 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
827 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
828 ok(!io
.Status
, "got status %#x\n", io
.Status
);
829 ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
831 /* These structures need not remain valid. */
832 memset(¶ms
, 0xcc, sizeof(params
));
833 memset(wsabufs
, 0xcc, sizeof(wsabufs
));
835 ret
= send(server
, "data", 5, 0);
836 ok(ret
== 5, "got %d\n", ret
);
838 ret
= WaitForSingleObject(event
, 200);
839 ok(!ret
, "wait timed out\n");
840 ok(!io
.Status
, "got %#x\n", io
.Status
);
841 ok(io
.Information
== 5, "got %#Ix\n", io
.Information
);
842 ok(!strcmp(buffer
, "data"), "got %s\n", debugstr_an(buffer
, io
.Information
));
844 /* Test with multiple buffers. */
847 wsabufs
[0].buf
= buffer
;
849 wsabufs
[1].buf
= buffer
+ 3;
850 memset(¶ms
, 0, sizeof(params
));
851 params
.buffers
= wsabufs
;
853 params
.msg_flags
= AFD_MSG_NOT_OOB
;
855 memset(&io
, 0, sizeof(io
));
856 memset(buffer
, 0xcc, sizeof(buffer
));
857 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
858 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
859 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
860 ok(!io
.Status
, "got status %#x\n", io
.Status
);
861 ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
863 ret
= send(server
, "data", 5, 0);
864 ok(ret
== 5, "got %d\n", ret
);
866 ret
= WaitForSingleObject(event
, 200);
867 ok(!ret
, "wait timed out\n");
868 ok(!io
.Status
, "got %#x\n", io
.Status
);
869 ok(io
.Information
== 5, "got %#Ix\n", io
.Information
);
870 ok(!strcmp(buffer
, "da\xccta"), "got %s\n", debugstr_an(buffer
, io
.Information
));
872 /* Test synchronous return. */
874 ret
= send(server
, "data", 5, 0);
875 ok(ret
== 5, "got %d\n", ret
);
877 /* wait for the data to be available */
878 check_poll_mask(client
, event
, AFD_POLL_READ
, AFD_POLL_READ
);
880 memset(&io
, 0xcc, sizeof(io
));
881 memset(buffer
, 0xcc, sizeof(buffer
));
882 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
883 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
884 ok(!ret
, "got %#x\n", ret
);
885 ok(!io
.Status
, "got %#x\n", io
.Status
);
886 ok(io
.Information
== 5, "got %#Ix\n", io
.Information
);
887 ok(!strcmp(buffer
, "da\xccta"), "got %s\n", debugstr_an(buffer
, io
.Information
));
889 /* Test nonblocking mode. */
891 set_blocking(client
, FALSE
);
893 memset(&io
, 0, sizeof(io
));
894 memset(buffer
, 0xcc, sizeof(buffer
));
895 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
896 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
897 ok(ret
== STATUS_DEVICE_NOT_READY
, "got %#x\n", ret
);
898 todo_wine
ok(!io
.Status
, "got status %#x\n", io
.Status
);
899 ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
901 ret
= send(server
, "data", 5, 0);
902 ok(ret
== 5, "got %d\n", ret
);
904 /* wait for the data to be available */
905 check_poll_mask(client
, event
, AFD_POLL_READ
, AFD_POLL_READ
);
907 memset(&io
, 0xcc, sizeof(io
));
908 memset(buffer
, 0xcc, sizeof(buffer
));
909 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
910 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
911 ok(!ret
, "got %#x\n", ret
);
912 ok(!io
.Status
, "got %#x\n", io
.Status
);
913 ok(io
.Information
== 5, "got %#Ix\n", io
.Information
);
914 ok(!strcmp(buffer
, "da\xccta"), "got %s\n", debugstr_an(buffer
, io
.Information
));
916 params
.recv_flags
= AFD_RECV_FORCE_ASYNC
;
918 memset(&io
, 0, sizeof(io
));
919 memset(buffer
, 0xcc, sizeof(buffer
));
920 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
921 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
922 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
923 todo_wine
ok(!io
.Status
, "got status %#x\n", io
.Status
);
924 todo_wine
ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
926 ret
= send(server
, "data", 5, 0);
927 ok(ret
== 5, "got %d\n", ret
);
929 ret
= WaitForSingleObject(event
, 200);
930 ok(!ret
, "wait timed out\n");
931 ok(!io
.Status
, "got %#x\n", io
.Status
);
932 ok(io
.Information
== 5, "got %#Ix\n", io
.Information
);
933 ok(!strcmp(buffer
, "da\xccta"), "got %s\n", debugstr_an(buffer
, io
.Information
));
935 params
.recv_flags
= 0;
937 set_blocking(client
, TRUE
);
941 ret
= send(server
, "a", 1, MSG_OOB
);
942 ok(ret
== 1, "got %d\n", ret
);
944 ret
= send(server
, "data", 5, 0);
945 ok(ret
== 5, "got %d\n", ret
);
947 /* wait for the data to be available */
948 check_poll_mask(client
, event
, AFD_POLL_READ
, AFD_POLL_READ
);
950 memset(&io
, 0xcc, sizeof(io
));
951 memset(buffer
, 0xcc, sizeof(buffer
));
952 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
953 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
954 ok(!ret
, "got %#x\n", ret
);
955 ok(!io
.Status
, "got %#x\n", io
.Status
);
956 ok(io
.Information
== 5, "got %#Ix\n", io
.Information
);
957 ok(!strcmp(buffer
, "da\xccta"), "got %s\n", debugstr_an(buffer
, io
.Information
));
959 params
.msg_flags
= 0;
961 io
.Status
= 0xdeadbeef;
962 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
963 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
964 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
965 todo_wine
ok(io
.Status
== 0xdeadbeef, "got %#x\n", io
.Status
);
967 params
.msg_flags
= AFD_MSG_OOB
| AFD_MSG_NOT_OOB
;
969 io
.Status
= 0xdeadbeef;
970 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
971 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
972 ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
973 todo_wine
ok(io
.Status
== 0xdeadbeef, "got %#x\n", io
.Status
);
975 params
.msg_flags
= AFD_MSG_OOB
;
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 todo_wine
ok(!ret
, "got %#x\n", ret
);
981 todo_wine
ok(!io
.Status
, "got %#x\n", io
.Status
);
982 todo_wine
ok(io
.Information
== 1, "got %#Ix\n", io
.Information
);
983 todo_wine
ok(buffer
[0] == 'a', "got %s\n", debugstr_an(buffer
, io
.Information
));
985 params
.msg_flags
= AFD_MSG_NOT_OOB
| AFD_MSG_PEEK
;
987 ret
= send(server
, "data", 4, 0);
988 ok(ret
== 4, "got %d\n", ret
);
990 /* wait for the data to be available */
991 check_poll_mask(client
, event
, AFD_POLL_READ
, AFD_POLL_READ
);
993 memset(buffer
, 0xcc, sizeof(buffer
));
994 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
995 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
996 ok(!ret
, "got %#x\n", ret
);
997 ok(!io
.Status
, "got %#x\n", io
.Status
);
998 ok(io
.Information
== 4, "got %#Ix\n", io
.Information
);
999 ok(!memcmp(buffer
, "da\xccta", 5), "got %s\n", debugstr_an(buffer
, io
.Information
));
1001 memset(buffer
, 0xcc, sizeof(buffer
));
1002 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1003 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1004 ok(!ret
, "got %#x\n", ret
);
1005 ok(!io
.Status
, "got %#x\n", io
.Status
);
1006 ok(io
.Information
== 4, "got %#Ix\n", io
.Information
);
1007 ok(!memcmp(buffer
, "da\xccta", 5), "got %s\n", debugstr_an(buffer
, io
.Information
));
1009 params
.msg_flags
= AFD_MSG_NOT_OOB
| AFD_MSG_WAITALL
;
1011 memset(buffer
, 0xcc, sizeof(buffer
));
1012 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1013 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1014 todo_wine
ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
1016 if (ret
== STATUS_PENDING
)
1018 ret
= send(server
, "s", 2, 0);
1019 ok(ret
== 2, "got %d\n", ret
);
1021 ret
= WaitForSingleObject(event
, 200);
1022 ok(!ret
, "wait timed out\n");
1023 ok(!io
.Status
, "got %#x\n", io
.Status
);
1024 ok(io
.Information
== 6, "got %#Ix\n", io
.Information
);
1025 ok(!strcmp(buffer
, "da\xcctas"), "got %s\n", debugstr_an(buffer
, io
.Information
));
1028 params
.msg_flags
= AFD_MSG_NOT_OOB
;
1030 /* Test shutdown. */
1032 memset(buffer
, 0xcc, sizeof(buffer
));
1033 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1034 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1035 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
1037 closesocket(server
);
1039 ret
= WaitForSingleObject(event
, 200);
1040 ok(!ret
, "wait timed out\n");
1041 ok(!io
.Status
, "got %#x\n", io
.Status
);
1042 ok(!io
.Information
, "got %#Ix\n", io
.Information
);
1044 ret
= shutdown(client
, SD_RECEIVE
);
1045 ok(!ret
, "got error %u\n", WSAGetLastError());
1047 memset(&io
, 0, sizeof(io
));
1048 memset(buffer
, 0xcc, sizeof(buffer
));
1049 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1050 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1051 todo_wine
ok(ret
== STATUS_PIPE_DISCONNECTED
, "got %#x\n", ret
);
1052 ok(!io
.Status
, "got status %#x\n", io
.Status
);
1053 ok(!io
.Information
, "got information %#Ix\n", io
.Information
);
1055 closesocket(client
);
1056 closesocket(listener
);
1058 /* Test UDP datagrams. */
1060 client
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
1061 server
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
1063 memset(buffer
, 0xcc, sizeof(buffer
));
1064 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1065 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1066 todo_wine
ok(ret
== STATUS_INVALID_PARAMETER
, "got %#x\n", ret
);
1067 if (ret
== STATUS_PENDING
)
1068 CancelIo((HANDLE
)client
);
1070 ret
= bind(client
, (const struct sockaddr
*)&bind_addr
, sizeof(bind_addr
));
1071 ok(!ret
, "got error %u\n", WSAGetLastError());
1073 ret
= getsockname(client
, (struct sockaddr
*)&addr
, &len
);
1074 ok(!ret
, "got error %u\n", WSAGetLastError());
1076 memset(buffer
, 0xcc, sizeof(buffer
));
1077 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1078 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1079 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
1081 ret
= sendto(server
, "data", 5, 0, (struct sockaddr
*)&addr
, sizeof(addr
));
1082 ok(ret
== 5, "got %d\n", ret
);
1084 ret
= WaitForSingleObject(event
, 200);
1085 ok(!ret
, "wait timed out\n");
1086 ok(!io
.Status
, "got %#x\n", io
.Status
);
1087 ok(io
.Information
== 5, "got %#Ix\n", io
.Information
);
1088 ok(!strcmp(buffer
, "da\xccta"), "got %s\n", debugstr_an(buffer
, io
.Information
));
1090 /* Test a short read of a UDP datagram. */
1092 memset(buffer
, 0xcc, sizeof(buffer
));
1093 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1094 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1095 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
1097 ret
= sendto(server
, "moredata", 9, 0, (struct sockaddr
*)&addr
, sizeof(addr
));
1098 ok(ret
== 9, "got %d\n", ret
);
1100 ret
= WaitForSingleObject(event
, 200);
1101 ok(!ret
, "wait timed out\n");
1102 ok(io
.Status
== STATUS_BUFFER_OVERFLOW
, "got %#x\n", io
.Status
);
1103 ok(io
.Information
== 6, "got %#Ix\n", io
.Information
);
1104 ok(!memcmp(buffer
, "mo\xccreda\xcc", 7), "got %s\n", debugstr_an(buffer
, io
.Information
));
1106 ret
= sendto(server
, "moredata", 9, 0, (struct sockaddr
*)&addr
, sizeof(addr
));
1107 ok(ret
== 9, "got %d\n", ret
);
1109 /* wait for the data to be available */
1110 check_poll_mask(client
, event
, AFD_POLL_READ
, AFD_POLL_READ
);
1112 memset(&io
, 0, sizeof(io
));
1113 memset(buffer
, 0xcc, sizeof(buffer
));
1114 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1115 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1116 ok(ret
== STATUS_BUFFER_OVERFLOW
, "got %#x\n", ret
);
1117 ok(io
.Status
== STATUS_BUFFER_OVERFLOW
, "got %#x\n", io
.Status
);
1118 ok(io
.Information
== 6, "got %#Ix\n", io
.Information
);
1119 ok(!memcmp(buffer
, "mo\xccreda\xcc", 7), "got %s\n", debugstr_an(buffer
, io
.Information
));
1121 /* Test closing a socket during an async. */
1123 memset(buffer
, 0xcc, sizeof(buffer
));
1124 ret
= NtDeviceIoControlFile((HANDLE
)client
, event
, NULL
, NULL
, &io
,
1125 IOCTL_AFD_RECV
, ¶ms
, sizeof(params
), NULL
, 0);
1126 ok(ret
== STATUS_PENDING
, "got %#x\n", ret
);
1128 closesocket(client
);
1130 ret
= WaitForSingleObject(event
, 200);
1131 ok(!ret
, "wait timed out\n");
1132 todo_wine
ok(io
.Status
== STATUS_CANCELLED
, "got %#x\n", io
.Status
);
1133 ok(!io
.Information
, "got %#Ix\n", io
.Information
);
1135 closesocket(server
);
1143 WSAStartup(MAKEWORD(2, 2), &data
);
1147 test_poll_completion_port();