Signed-off-by: Zebediah Figura z.figura12@gmail.com --- include/wine/afd.h | 4 ++-- server/sock.c | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/include/wine/afd.h b/include/wine/afd.h index 8199e0e2dbe..5074c1f20dd 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -95,8 +95,8 @@ struct afd_poll_params #define IOCTL_AFD_WINE_RECVMSG CTL_CODE(FILE_DEVICE_NETWORK, 205, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_SENDMSG CTL_CODE(FILE_DEVICE_NETWORK, 206, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_TRANSMIT CTL_CODE(FILE_DEVICE_NETWORK, 207, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_AFD_WINE_ADDRESS_LIST_CHANGE CTL_CODE(FILE_DEVICE_NETWORK, 323, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_AFD_WINE_ADDRESS_LIST_CHANGE CTL_CODE(FILE_DEVICE_NETWORK, 208, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_AFD_WINE_FIONBIO CTL_CODE(FILE_DEVICE_NETWORK, 209, METHOD_BUFFERED, FILE_ANY_ACCESS)
struct afd_create_params { diff --git a/server/sock.c b/server/sock.c index e521818dc4b..45390127acc 100644 --- a/server/sock.c +++ b/server/sock.c @@ -1892,6 +1892,27 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) set_error( STATUS_PENDING ); return 1;
+ case IOCTL_AFD_WINE_FIONBIO: + if (get_req_data_size() < sizeof(int)) + { + set_error( STATUS_BUFFER_TOO_SMALL ); + return 0; + } + if (*(int *)get_req_data()) + { + sock->state |= FD_WINE_NONBLOCKING; + } + else + { + if (sock->mask) + { + set_error( STATUS_INVALID_PARAMETER ); + return 0; + } + sock->state &= ~FD_WINE_NONBLOCKING; + } + return 1; + default: set_error( STATUS_NOT_SUPPORTED ); return 0;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/socket.c | 91 +++++++++++----------------------------- dlls/ws2_32/tests/sock.c | 17 ++++---- 2 files changed, 31 insertions(+), 77 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index c1f415444df..0fc13344ee2 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -798,35 +798,6 @@ static inline void release_sock_fd( SOCKET s, int fd ) close( fd ); }
-static void _enable_event( HANDLE s, unsigned int event, - unsigned int sstate, unsigned int cstate ) -{ - SERVER_START_REQ( enable_socket_event ) - { - req->handle = wine_server_obj_handle( s ); - req->mask = event; - req->sstate = sstate; - req->cstate = cstate; - wine_server_call( req ); - } - SERVER_END_REQ; -} - -static unsigned int _get_sock_mask(SOCKET s) -{ - unsigned int ret; - SERVER_START_REQ( get_socket_event ) - { - req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) ); - req->service = FALSE; - req->c_event = 0; - wine_server_call( req ); - ret = reply->mask; - } - SERVER_END_REQ; - return ret; -} - static void _get_sock_errors(SOCKET s, int *events) { SERVER_START_REQ( get_socket_event ) @@ -3371,23 +3342,20 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID switch (code) { case WS_FIONBIO: - if (in_size != sizeof(WS_u_long) || IS_INTRESOURCE(in_buff)) + { + DWORD ret; + + if (IS_INTRESOURCE( in_buff )) { - SetLastError(WSAEFAULT); - return SOCKET_ERROR; + SetLastError( WSAEFAULT ); + return -1; } - TRACE("-> FIONBIO (%x)\n", *(WS_u_long*)in_buff); - if (_get_sock_mask(s)) - { - /* AsyncSelect()'ed sockets are always nonblocking */ - if (!*(WS_u_long *)in_buff) status = WSAEINVAL; - break; - } - if (*(WS_u_long *)in_buff) - _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0); - else - _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING); - break; + + ret = server_ioctl_sock( s, IOCTL_AFD_WINE_FIONBIO, in_buff, in_size, + out_buff, out_size, ret_size, overlapped, completion ); + SetLastError( ret ); + return ret ? -1 : 0; + }
case WS_FIONREAD: { @@ -3684,32 +3652,21 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID case 0x667e: /* Netscape tries hard to use bogus ioctl 0x667e */ SetLastError(WSAEOPNOTSUPP); return SOCKET_ERROR; + case WS_SIO_ADDRESS_LIST_CHANGE: - code = IOCTL_AFD_WINE_ADDRESS_LIST_CHANGE; - status = WSAEOPNOTSUPP; - break; - default: - status = WSAEOPNOTSUPP; - break; + { + DWORD ret; + + ret = server_ioctl_sock( s, IOCTL_AFD_WINE_ADDRESS_LIST_CHANGE, in_buff, in_size, + out_buff, out_size, ret_size, overlapped, completion ); + SetLastError( ret ); + return ret ? -1 : 0; }
- if (status == WSAEOPNOTSUPP) - { - status = server_ioctl_sock(s, code, in_buff, in_size, out_buff, out_size, &total, - overlapped, completion); - if (status != WSAEOPNOTSUPP) - { - if (status == 0 || status == WSA_IO_PENDING || status == WSAEWOULDBLOCK) - TRACE("-> %s request\n", debugstr_wsaioctl(code)); - else - ERR("-> %s request failed with status 0x%x\n", debugstr_wsaioctl(code), status); - - /* overlapped and completion operations will be handled by the server */ - completion = NULL; - overlapped = NULL; - } - else - FIXME("unsupported WS_IOCTL cmd (%s)\n", debugstr_wsaioctl(code)); + default: + FIXME( "unimplemented ioctl %s\n", debugstr_wsaioctl( code ) ); + status = WSAEOPNOTSUPP; + break; }
if (completion) diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index bf8d028611f..fe7f155a8d8 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -3931,11 +3931,11 @@ static void test_fionbio(void) WSASetLastError(0xdeadbeef); ret = WSAIoctl(s, FIONBIO, &one, sizeof(one), NULL, 0, &size, NULL, NULL); ok(!ret, "expected success\n"); - todo_wine ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); + ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); ok(!size, "got size %u\n", size);
ret = WSAIoctl(s, FIONBIO, &one, sizeof(one) + 1, NULL, 0, &size, NULL, NULL); - todo_wine ok(!ret, "got error %u\n", WSAGetLastError()); + ok(!ret, "got error %u\n", WSAGetLastError());
overlapped.Internal = 0xdeadbeef; overlapped.InternalHigh = 0xdeadbeef; @@ -3984,14 +3984,11 @@ static void test_fionbio(void) ok(!size, "got size %u\n", size);
ret = SleepEx(0, TRUE); - todo_wine ok(ret == WAIT_IO_COMPLETION, "got %d\n", ret); - if (ret == WAIT_IO_COMPLETION) - { - ok(apc_count == 1, "APC was called %u times\n", apc_count); - ok(!apc_error, "got APC error %u\n", apc_error); - ok(!apc_size, "got APC size %u\n", apc_size); - ok(apc_overlapped == &overlapped, "got APC overlapped %p\n", apc_overlapped); - } + ok(ret == WAIT_IO_COMPLETION, "got %d\n", ret); + ok(apc_count == 1, "APC was called %u times\n", apc_count); + ok(!apc_error, "got APC error %u\n", apc_error); + ok(!apc_size, "got APC size %u\n", apc_size); + ok(apc_overlapped == &overlapped, "got APC overlapped %p\n", apc_overlapped);
closesocket(s); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=91648
Your paranoid android.
=== debiant2 (32 bit report) ===
ws2_32: afd.c:336: Test failed: got flags 0x43 afd.c:342: Test failed: got flags 0x41
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- server/protocol.def | 8 -------- server/sock.c | 24 ------------------------ 2 files changed, 32 deletions(-)
diff --git a/server/protocol.def b/server/protocol.def index 8a68c9a5eb7..30624a7cbaf 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1456,14 +1456,6 @@ enum server_fd_type @END
-/* Re-enable pending socket events */ -@REQ(enable_socket_event) - obj_handle_t handle; /* handle to the socket */ - unsigned int mask; /* events to re-enable */ - unsigned int sstate; /* status bits to set */ - unsigned int cstate; /* status bits to clear */ -@END - @REQ(set_socket_deferred) obj_handle_t handle; /* handle to the socket */ obj_handle_t deferred; /* handle to the socket for which accept() is deferred */ diff --git a/server/sock.c b/server/sock.c index 45390127acc..700d4c0761a 100644 --- a/server/sock.c +++ b/server/sock.c @@ -2378,30 +2378,6 @@ DECL_HANDLER(get_socket_event) release_object( &sock->obj ); }
-/* re-enable pending socket events */ -DECL_HANDLER(enable_socket_event) -{ - struct sock *sock; - - if (!(sock = (struct sock*)get_handle_obj( current->process, req->handle, - FILE_WRITE_ATTRIBUTES, &sock_ops))) - return; - - if (get_unix_fd( sock->fd ) == -1) return; - - /* for event-based notification, windows erases stale events */ - sock->pending_events &= ~req->mask; - - sock->reported_events &= ~req->mask; - sock->state |= req->sstate; - sock->state &= ~req->cstate; - if (sock->type != WS_SOCK_STREAM) sock->state &= ~STREAM_FLAG_MASK; - - sock_reselect( sock ); - - release_object( &sock->obj ); -} - DECL_HANDLER(set_socket_deferred) { struct sock *sock, *acceptsock;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/unix/file.c | 2 +- dlls/ntdll/unix/socket.c | 21 +++++++++++++++++++++ dlls/ntdll/unix/unix_private.h | 1 + include/wine/afd.h | 1 + 4 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index a2d0a4b1483..21f5d10f3f8 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -5099,7 +5099,7 @@ static NTSTATUS register_async_file_read( HANDLE handle, HANDLE event, return status; }
-static void add_completion( HANDLE handle, ULONG_PTR value, NTSTATUS status, ULONG info, BOOL async ) +void add_completion( HANDLE handle, ULONG_PTR value, NTSTATUS status, ULONG info, BOOL async ) { SERVER_START_REQ( add_fd_completion ) { diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index db65752a031..cfc5780b082 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1116,6 +1116,17 @@ static NTSTATUS sock_transmit( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, return status; }
+static void complete_async( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, + IO_STATUS_BLOCK *io, NTSTATUS status, ULONG_PTR information ) +{ + io->Status = status; + io->Information = information; + if (event) NtSetEvent( event, NULL ); + if (apc) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc, (ULONG_PTR)apc_user, (ULONG_PTR)io, 0 ); + if (apc_user) add_completion( handle, (ULONG_PTR)apc_user, status, information, FALSE ); +} + + NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, IO_STATUS_BLOCK *io, ULONG code, void *in_buffer, ULONG in_size, void *out_buffer, ULONG out_size ) { @@ -1249,6 +1260,16 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc break; }
+ case IOCTL_AFD_WINE_COMPLETE_ASYNC: + { + if (in_size != sizeof(NTSTATUS)) + return STATUS_BUFFER_TOO_SMALL; + + status = *(NTSTATUS *)in_buffer; + complete_async( handle, event, apc, apc_user, io, status, 0 ); + break; + } + case IOCTL_AFD_POLL: status = sock_poll( handle, event, apc, apc_user, io, in_buffer, in_size, out_buffer, out_size ); break; diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index cf3b8280200..03c45e42997 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -279,6 +279,7 @@ extern NTSTATUS open_unix_file( HANDLE *handle, const char *unix_name, ACCESS_MA ULONG options, void *ea_buffer, ULONG ea_length ) DECLSPEC_HIDDEN; extern void init_files(void) DECLSPEC_HIDDEN; extern void init_cpu_info(void) DECLSPEC_HIDDEN; +extern void add_completion( HANDLE handle, ULONG_PTR value, NTSTATUS status, ULONG info, BOOL async ) DECLSPEC_HIDDEN;
extern void dbg_init(void) DECLSPEC_HIDDEN;
diff --git a/include/wine/afd.h b/include/wine/afd.h index 5074c1f20dd..77801b1fbe3 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -97,6 +97,7 @@ struct afd_poll_params #define IOCTL_AFD_WINE_TRANSMIT CTL_CODE(FILE_DEVICE_NETWORK, 207, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_ADDRESS_LIST_CHANGE CTL_CODE(FILE_DEVICE_NETWORK, 208, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_FIONBIO CTL_CODE(FILE_DEVICE_NETWORK, 209, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_AFD_WINE_COMPLETE_ASYNC CTL_CODE(FILE_DEVICE_NETWORK, 210, METHOD_BUFFERED, FILE_ANY_ACCESS)
struct afd_create_params {
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/socket.c | 26 +++++++++++++------------- dlls/ws2_32/tests/sock.c | 27 ++++++++++++--------------- 2 files changed, 25 insertions(+), 28 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 0fc13344ee2..79085cf0c2a 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -3515,29 +3515,29 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID EXTENSION_FUNCTION(WSAID_WSASENDMSG, WSASendMsg) }; #undef EXTENSION_FUNCTION - BOOL found = FALSE; unsigned int i;
for (i = 0; i < ARRAY_SIZE(guid_funcs); i++) { if (IsEqualGUID(&guid_funcs[i].guid, in_buff)) { - found = TRUE; - break; + NTSTATUS status = STATUS_SUCCESS; + DWORD ret = 0; + + TRACE( "returning %s\n", guid_funcs[i].name ); + *(void **)out_buff = guid_funcs[i].func_ptr; + + ret = server_ioctl_sock( s, IOCTL_AFD_WINE_COMPLETE_ASYNC, &status, sizeof(status), + NULL, 0, ret_size, overlapped, completion ); + *ret_size = sizeof(void *); + SetLastError( ret ); + return ret ? -1 : 0; } }
- if (found) - { - TRACE("-> got %s\n", guid_funcs[i].name); - *(void **)out_buff = guid_funcs[i].func_ptr; - total = sizeof(void *); - break; - } - FIXME("SIO_GET_EXTENSION_FUNCTION_POINTER %s: stub\n", debugstr_guid(in_buff)); - status = WSAEOPNOTSUPP; - break; + SetLastError( WSAEOPNOTSUPP ); + return -1; } case WS_SIO_KEEPALIVE_VALS: { diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index fe7f155a8d8..c0b1abcaaa5 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -4231,7 +4231,7 @@ static void test_get_extension_func(void) ret = WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &acceptex_guid, sizeof(GUID), &func, sizeof(func), &size, NULL, NULL); ok(!ret, "expected success\n"); - todo_wine ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); + ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); ok(size == sizeof(func), "got size %u\n", size);
WSASetLastError(0xdeadbeef); @@ -4241,16 +4241,16 @@ static void test_get_extension_func(void) ret = WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &acceptex_guid, sizeof(GUID), &func, sizeof(func), &size, &overlapped, NULL); ok(!ret, "expected success\n"); - todo_wine ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); + ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); ok(size == sizeof(func), "got size %u\n", size);
ret = GetQueuedCompletionStatus(port, &size, &key, &overlapped_ptr, 0); ok(ret, "got error %u\n", GetLastError()); - todo_wine ok(!size, "got size %u\n", size); + ok(!size, "got size %u\n", size); ok(key == 123, "got key %Iu\n", key); ok(overlapped_ptr == &overlapped, "got overlapped %p\n", overlapped_ptr); ok(!overlapped.Internal, "got status %#x\n", (NTSTATUS)overlapped.Internal); - todo_wine ok(!overlapped.InternalHigh, "got size %Iu\n", overlapped.InternalHigh); + ok(!overlapped.InternalHigh, "got size %Iu\n", overlapped.InternalHigh);
size = 0xdeadbeef; overlapped.Internal = 0xdeadbeef; @@ -4260,12 +4260,12 @@ static void test_get_extension_func(void) ok(ret == -1, "expected failure\n"); todo_wine ok(WSAGetLastError() == WSAEINVAL, "got error %u\n", WSAGetLastError()); ok(size == 0xdeadbeef, "got size %u\n", size); - todo_wine ok(overlapped.Internal == 0xdeadbeef, "got status %#x\n", (NTSTATUS)overlapped.Internal); - todo_wine ok(overlapped.InternalHigh == 0xdeadbeef, "got size %Iu\n", overlapped.InternalHigh); + ok(overlapped.Internal == 0xdeadbeef, "got status %#x\n", (NTSTATUS)overlapped.Internal); + ok(overlapped.InternalHigh == 0xdeadbeef, "got size %Iu\n", overlapped.InternalHigh);
ret = GetQueuedCompletionStatus(port, &size, &key, &overlapped_ptr, 0); ok(!ret, "expected failure\n"); - todo_wine ok(GetLastError() == WAIT_TIMEOUT, "got error %u\n", WSAGetLastError()); + ok(GetLastError() == WAIT_TIMEOUT, "got error %u\n", WSAGetLastError());
CloseHandle(port); closesocket(s); @@ -4285,14 +4285,11 @@ static void test_get_extension_func(void) ok(size == sizeof(func), "got size %u\n", size);
ret = SleepEx(0, TRUE); - todo_wine ok(ret == WAIT_IO_COMPLETION, "got %d\n", ret); - if (ret == WAIT_IO_COMPLETION) - { - ok(apc_count == 1, "APC was called %u times\n", apc_count); - ok(!apc_error, "got APC error %u\n", apc_error); - ok(!apc_size, "got APC size %u\n", apc_size); - ok(apc_overlapped == &overlapped, "got APC overlapped %p\n", apc_overlapped); - } + ok(ret == WAIT_IO_COMPLETION, "got %d\n", ret); + ok(apc_count == 1, "APC was called %u times\n", apc_count); + ok(!apc_error, "got APC error %u\n", apc_error); + ok(!apc_size, "got APC size %u\n", apc_size); + ok(apc_overlapped == &overlapped, "got APC overlapped %p\n", apc_overlapped);
closesocket(s); }