From 93863d25fc32a6229590e3b97a9d12e1a94676d5 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 12 Oct 2016 17:11:34 +0200 Subject: [PATCH] ws2_32: Pass completion routing to NtDeviceIoControlFile in server_ioctl_sock only if caller provided completion routine. Otherwise we're always doing non-blocking calls, preventing server from doing the right thing (and in actually doing the opposite in WS_SIO_ADDRESS_LIST_CHANGE case). Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/ws2_32/socket.c | 27 ++++++++++++++++++--------- dlls/ws2_32/tests/sock.c | 2 -- server/sock.c | 2 +- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index e3c75070faf..e8c5130a06c 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -4520,18 +4520,27 @@ static DWORD server_ioctl_sock( SOCKET s, DWORD code, LPVOID in_buff, DWORD in_s { HANDLE event = overlapped ? overlapped->hEvent : 0; HANDLE handle = SOCKET2HANDLE( s ); - struct ws2_async *wsa; + struct ws2_async *wsa = NULL; + IO_STATUS_BLOCK *io = (PIO_STATUS_BLOCK)overlapped, iosb; + void *cvalue = NULL; NTSTATUS status; - PIO_STATUS_BLOCK io; - if (!(wsa = (struct ws2_async *)alloc_async_io( sizeof(*wsa) ))) - return WSA_NOT_ENOUGH_MEMORY; - wsa->hSocket = handle; - wsa->user_overlapped = overlapped; - wsa->completion_func = completion; - io = (overlapped ? (PIO_STATUS_BLOCK)overlapped : &wsa->local_iosb); + if (completion) + { + if (!(wsa = (struct ws2_async *)alloc_async_io( sizeof(*wsa) ))) + return WSA_NOT_ENOUGH_MEMORY; + wsa->hSocket = handle; + wsa->user_overlapped = overlapped; + wsa->completion_func = completion; + if (!io) io = &wsa->local_iosb; + cvalue = wsa; + } + else if (!io) + io = &iosb; + else if (!((ULONG_PTR)overlapped->hEvent & 1)) + cvalue = overlapped; - status = NtDeviceIoControlFile( handle, event, ws2_async_apc, wsa, io, code, + status = NtDeviceIoControlFile( handle, event, wsa ? ws2_async_apc : NULL, cvalue, io, code, in_buff, in_size, out_buff, out_size ); if (status == STATUS_NOT_SUPPORTED) { diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 320f82096d6..b7aaea38601 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -8387,7 +8387,6 @@ static void test_sioAddressListChange(void) ret = WSAIoctl(sock, SIO_ADDRESS_LIST_CHANGE, NULL, 0, NULL, 0, &num_bytes, &overlapped, NULL); error = GetLastError(); ok (ret == SOCKET_ERROR, "WSAIoctl(SIO_ADDRESS_LIST_CHANGE) failed with error %d\n", error); -todo_wine ok (error == ERROR_IO_PENDING, "expected 0x3e5, got 0x%x\n", error); CloseHandle(overlapped.hEvent); @@ -8426,7 +8425,6 @@ todo_wine ret = WSAIoctl(sock, SIO_ADDRESS_LIST_CHANGE, NULL, 0, NULL, 0, &num_bytes, &overlapped, NULL); error = GetLastError(); ok (ret == SOCKET_ERROR, "WSAIoctl(SIO_ADDRESS_LIST_CHANGE) failed with error %d\n", error); -todo_wine ok (error == ERROR_IO_PENDING, "expected 0x3e5, got 0x%x\n", error); CloseHandle(overlapped.hEvent); diff --git a/server/sock.c b/server/sock.c index 89049e0e878..d7349fc283e 100644 --- a/server/sock.c +++ b/server/sock.c @@ -548,7 +548,7 @@ obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *a switch(code) { case WS_SIO_ADDRESS_LIST_CHANGE: - if ((sock->state & FD_WINE_NONBLOCKING) && !blocking) + if ((sock->state & FD_WINE_NONBLOCKING) && blocking) { set_error( STATUS_CANT_WAIT ); return 0;