Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/tests/sock.c | 6 +++--- server/sock.c | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 266ddc14451..9116c2b169d 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -4455,12 +4455,12 @@ static void test_close_events(struct event_test_ctx *ctx) check_events(ctx, 0, 0, 0); select_events(ctx, server, FD_ACCEPT | FD_CLOSE | FD_CONNECT | FD_OOB | FD_READ); if (ctx->is_message) - check_events_todo_msg(ctx, FD_CLOSE, 0, 200); + check_events(ctx, FD_CLOSE, 0, 200); check_events(ctx, 0, 0, 0); select_events(ctx, server, 0); select_events(ctx, server, FD_ACCEPT | FD_CLOSE | FD_CONNECT | FD_OOB | FD_READ); if (ctx->is_message) - check_events_todo_msg(ctx, FD_CLOSE, 0, 200); + check_events(ctx, FD_CLOSE, 0, 200); check_events(ctx, 0, 0, 0);
ret = recv(server, buffer, 5, 0); @@ -4553,7 +4553,7 @@ static void test_close_events(struct event_test_ctx *ctx)
check_events(ctx, 0, 0, 200); select_events(ctx, server, FD_ACCEPT | FD_CLOSE | FD_CONNECT | FD_OOB | FD_READ); - check_events_todo_event(ctx, FD_CLOSE, 0, 200); + check_events_todo(ctx, FD_CLOSE, 0, 200);
closesocket(server); } diff --git a/server/sock.c b/server/sock.c index c8cd603149b..92202d317c4 100644 --- a/server/sock.c +++ b/server/sock.c @@ -786,8 +786,7 @@ static int sock_get_poll_events( struct fd *fd ) else if (smask & FD_READ || (sock->state & FD_WINE_LISTENING && mask & FD_ACCEPT)) ev |= POLLIN | POLLPRI; /* We use POLLIN with 0 bytes recv() as FD_CLOSE indication for stream sockets. */ - else if (sock->type == WS_SOCK_STREAM && (sock->state & FD_READ) && (mask & FD_CLOSE) && - !(sock->reported_events & FD_READ)) + else if (sock->type == WS_SOCK_STREAM && (mask & FD_CLOSE) && !(sock->reported_events & FD_READ)) ev |= POLLIN;
if (async_queued( &sock->write_q ))
Instead of clearing all messages when any match.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/tests/sock.c | 2 +- server/sock.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 9116c2b169d..33cdd5d6d15 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -4553,7 +4553,7 @@ static void test_close_events(struct event_test_ctx *ctx)
check_events(ctx, 0, 0, 200); select_events(ctx, server, FD_ACCEPT | FD_CLOSE | FD_CONNECT | FD_OOB | FD_READ); - check_events_todo(ctx, FD_CLOSE, 0, 200); + check_events_todo_event(ctx, FD_CLOSE, 0, 200);
closesocket(server); } diff --git a/server/sock.c b/server/sock.c index 92202d317c4..340566cbb0a 100644 --- a/server/sock.c +++ b/server/sock.c @@ -400,12 +400,11 @@ static void sock_wake_up( struct sock *sock ) unsigned int events = sock->pending_events & sock->mask; int i;
- if ( !events ) return; - if (sock->event) { if (debug_level) fprintf(stderr, "signalling events %x ptr %p\n", events, sock->event ); - set_event( sock->event ); + if (events) + set_event( sock->event ); } if (sock->window) {
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/socket.c | 8 ++++---- include/wine/afd.h | 8 ++++---- server/sock.c | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 0a23b44cc68..6c03a57e325 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2341,7 +2341,7 @@ SOCKET WINAPI WS_accept( SOCKET s, struct WS_sockaddr *addr, int *len )
if (!(sync_event = CreateEventW( NULL, TRUE, FALSE, NULL ))) return INVALID_SOCKET; status = NtDeviceIoControlFile( SOCKET2HANDLE(s), (HANDLE)((ULONG_PTR)sync_event | 0), NULL, NULL, &io, - IOCTL_AFD_ACCEPT, NULL, 0, &accept_handle, sizeof(accept_handle) ); + IOCTL_AFD_WINE_ACCEPT, NULL, 0, &accept_handle, sizeof(accept_handle) ); if (status == STATUS_PENDING) { if (WaitForSingleObject( sync_event, INFINITE ) == WAIT_FAILED) @@ -2416,7 +2416,7 @@ static BOOL WINAPI WS2_AcceptEx( SOCKET listener, SOCKET acceptor, void *dest, D }
status = NtDeviceIoControlFile( SOCKET2HANDLE(listener), overlapped->hEvent, NULL, cvalue, - (IO_STATUS_BLOCK *)overlapped, IOCTL_AFD_ACCEPT_INTO, ¶ms, sizeof(params), + (IO_STATUS_BLOCK *)overlapped, IOCTL_AFD_WINE_ACCEPT_INTO, ¶ms, sizeof(params), dest, recv_len + local_len + remote_len );
if (ret_len) *ret_len = overlapped->InternalHigh; @@ -4507,7 +4507,7 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID SetLastError(WSAEOPNOTSUPP); return SOCKET_ERROR; case WS_SIO_ADDRESS_LIST_CHANGE: - code = IOCTL_AFD_ADDRESS_LIST_CHANGE; + code = IOCTL_AFD_WINE_ADDRESS_LIST_CHANGE; status = WSAEOPNOTSUPP; break; default: @@ -5921,7 +5921,7 @@ SOCKET WINAPI WSASocketW(int af, int type, int protocol, create_params.protocol = protocol; create_params.flags = flags & ~(WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED); if ((status = NtDeviceIoControlFile(handle, NULL, NULL, NULL, &io, - IOCTL_AFD_CREATE, &create_params, sizeof(create_params), NULL, 0))) + IOCTL_AFD_WINE_CREATE, &create_params, sizeof(create_params), NULL, 0))) { WARN("Failed to initialize socket, status %#x.\n", status); err = RtlNtStatusToDosError( status ); diff --git a/include/wine/afd.h b/include/wine/afd.h index 07320e7bab5..3562962d6a1 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -24,11 +24,11 @@ #include <winioctl.h> #include "wine/server_protocol.h"
-#define IOCTL_AFD_CREATE CTL_CODE(FILE_DEVICE_NETWORK, 200, METHOD_BUFFERED, FILE_WRITE_ACCESS) -#define IOCTL_AFD_ACCEPT CTL_CODE(FILE_DEVICE_NETWORK, 201, METHOD_BUFFERED, FILE_WRITE_ACCESS) -#define IOCTL_AFD_ACCEPT_INTO CTL_CODE(FILE_DEVICE_NETWORK, 202, METHOD_BUFFERED, FILE_WRITE_ACCESS) +#define IOCTL_AFD_WINE_CREATE CTL_CODE(FILE_DEVICE_NETWORK, 200, METHOD_BUFFERED, FILE_WRITE_ACCESS) +#define IOCTL_AFD_WINE_ACCEPT CTL_CODE(FILE_DEVICE_NETWORK, 201, METHOD_BUFFERED, FILE_WRITE_ACCESS) +#define IOCTL_AFD_WINE_ACCEPT_INTO CTL_CODE(FILE_DEVICE_NETWORK, 202, METHOD_BUFFERED, FILE_WRITE_ACCESS)
-#define IOCTL_AFD_ADDRESS_LIST_CHANGE CTL_CODE(FILE_DEVICE_NETWORK, 323, METHOD_BUFFERED, 0) +#define IOCTL_AFD_WINE_ADDRESS_LIST_CHANGE CTL_CODE(FILE_DEVICE_NETWORK, 323, METHOD_BUFFERED, 0)
struct afd_create_params { diff --git a/server/sock.c b/server/sock.c index 340566cbb0a..dadcc607fbb 100644 --- a/server/sock.c +++ b/server/sock.c @@ -1357,11 +1357,11 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
assert( sock->obj.ops == &sock_ops );
- if (code != IOCTL_AFD_CREATE && get_unix_fd( fd ) < 0) return 0; + if (code != IOCTL_AFD_WINE_CREATE && get_unix_fd( fd ) < 0) return 0;
switch(code) { - case IOCTL_AFD_CREATE: + case IOCTL_AFD_WINE_CREATE: { const struct afd_create_params *params = get_req_data();
@@ -1374,7 +1374,7 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) return 0; }
- case IOCTL_AFD_ACCEPT: + case IOCTL_AFD_WINE_ACCEPT: { struct sock *acceptsock; obj_handle_t handle; @@ -1409,7 +1409,7 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) return 0; }
- case IOCTL_AFD_ACCEPT_INTO: + case IOCTL_AFD_WINE_ACCEPT_INTO: { static const int access = FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | FILE_READ_DATA; const struct afd_accept_into_params *params = get_req_data(); @@ -1459,7 +1459,7 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) return 1; }
- case IOCTL_AFD_ADDRESS_LIST_CHANGE: + case IOCTL_AFD_WINE_ADDRESS_LIST_CHANGE: if ((sock->state & FD_WINE_NONBLOCKING) && async_is_blocking( async )) { set_error( STATUS_DEVICE_NOT_READY );
All native ioctls use FILE_ANY_ACCESS.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- include/wine/afd.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/include/wine/afd.h b/include/wine/afd.h index 3562962d6a1..a711fba23a5 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -24,11 +24,11 @@ #include <winioctl.h> #include "wine/server_protocol.h"
-#define IOCTL_AFD_WINE_CREATE CTL_CODE(FILE_DEVICE_NETWORK, 200, METHOD_BUFFERED, FILE_WRITE_ACCESS) -#define IOCTL_AFD_WINE_ACCEPT CTL_CODE(FILE_DEVICE_NETWORK, 201, METHOD_BUFFERED, FILE_WRITE_ACCESS) -#define IOCTL_AFD_WINE_ACCEPT_INTO CTL_CODE(FILE_DEVICE_NETWORK, 202, METHOD_BUFFERED, FILE_WRITE_ACCESS) +#define IOCTL_AFD_WINE_CREATE CTL_CODE(FILE_DEVICE_NETWORK, 200, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_AFD_WINE_ACCEPT CTL_CODE(FILE_DEVICE_NETWORK, 201, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_AFD_WINE_ACCEPT_INTO CTL_CODE(FILE_DEVICE_NETWORK, 202, METHOD_BUFFERED, FILE_ANY_ACCESS)
-#define IOCTL_AFD_WINE_ADDRESS_LIST_CHANGE CTL_CODE(FILE_DEVICE_NETWORK, 323, METHOD_BUFFERED, 0) +#define IOCTL_AFD_WINE_ADDRESS_LIST_CHANGE CTL_CODE(FILE_DEVICE_NETWORK, 323, METHOD_BUFFERED, FILE_ANY_ACCESS)
struct afd_create_params {
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- This is a native, undocumented ioctl which can be called on Windows TCP sockets. Unlike some others (which I intend to submit later), no known application uses this ioctl, but as it matches closely an ioctl which is useful for Wine, I have reverse-engineered and implemented it anyway.
This marks the first of several native ioctls which I have made use of when moving socket code to ntdll and wineserver. For more details on AFD reverse-engineering, please see [1].
I have not included tests for this ioctl. Unfortunately calling accept() on such a socket fails (calling the ioctl equivalent succeeds, but unfortunately this is not trivial to implement or use.) It seems likely that listen() is setting some user-mode state.
[1] https://wiki.winehq.org/AFD
include/wine/afd.h | 9 +++++++++ server/sock.c | 29 ++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/include/wine/afd.h b/include/wine/afd.h index a711fba23a5..e890020ca88 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -24,6 +24,15 @@ #include <winioctl.h> #include "wine/server_protocol.h"
+#define IOCTL_AFD_LISTEN CTL_CODE(FILE_DEVICE_BEEP, 0x802, METHOD_NEITHER, FILE_ANY_ACCESS) + +struct afd_listen_params +{ + int unknown1; + int backlog; + int unknown2; +}; + #define IOCTL_AFD_WINE_CREATE CTL_CODE(FILE_DEVICE_NETWORK, 200, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_ACCEPT CTL_CODE(FILE_DEVICE_NETWORK, 201, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_ACCEPT_INTO CTL_CODE(FILE_DEVICE_NETWORK, 202, METHOD_BUFFERED, FILE_ANY_ACCESS) diff --git a/server/sock.c b/server/sock.c index dadcc607fbb..945895b51a4 100644 --- a/server/sock.c +++ b/server/sock.c @@ -1354,10 +1354,11 @@ static struct accept_req *alloc_accept_req( struct sock *sock, struct sock *acce static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) { struct sock *sock = get_fd_user( fd ); + int unix_fd;
assert( sock->obj.ops == &sock_ops );
- if (code != IOCTL_AFD_WINE_CREATE && get_unix_fd( fd ) < 0) return 0; + if (code != IOCTL_AFD_WINE_CREATE && (unix_fd = get_unix_fd( fd )) < 0) return 0;
switch(code) { @@ -1459,6 +1460,32 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) return 1; }
+ case IOCTL_AFD_LISTEN: + { + const struct afd_listen_params *params = get_req_data(); + + if (get_req_data_size() < sizeof(*params)) + { + set_error( STATUS_INVALID_PARAMETER ); + return 0; + } + + if (listen( unix_fd, params->backlog ) < 0) + { + set_error( sock_get_ntstatus( errno ) ); + return 0; + } + + sock->pending_events &= ~FD_ACCEPT; + sock->reported_events &= ~FD_ACCEPT; + sock->state |= FD_WINE_LISTENING; + sock->state &= ~(FD_CONNECT | FD_WINE_CONNECTED); + + /* we may already be selecting for FD_ACCEPT */ + sock_reselect( sock ); + return 0; + } + case IOCTL_AFD_WINE_ADDRESS_LIST_CHANGE: if ((sock->state & FD_WINE_NONBLOCKING) && async_is_blocking( async )) {
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/socket.c | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 6c03a57e325..2ba1982b1d9 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -4566,37 +4566,36 @@ int WINAPI WS_ioctlsocket(SOCKET s, LONG cmd, WS_u_long *argp) return WSAIoctl( s, cmd, argp, sizeof(WS_u_long), argp, sizeof(WS_u_long), &ret_size, NULL, NULL ); }
+ /*********************************************************************** - * listen (WS2_32.13) + * listen (ws2_32.13) */ -int WINAPI WS_listen(SOCKET s, int backlog) +int WINAPI WS_listen( SOCKET s, int backlog ) { - int fd = get_sock_fd( s, FILE_READ_DATA, NULL ), ret = SOCKET_ERROR; + struct afd_listen_params params = {.backlog = backlog}; + IO_STATUS_BLOCK io; + NTSTATUS status; + int fd, bound;
- TRACE("socket %04lx, backlog %d\n", s, backlog); - if (fd != -1) + TRACE( "socket %#lx, backlog %d\n", s, backlog ); + + if ((fd = get_sock_fd( s, FILE_READ_DATA, NULL )) == -1) + return -1; + bound = is_fd_bound( fd, NULL, NULL ); + release_sock_fd( s, fd ); + if (bound <= 0) { - int bound = is_fd_bound(fd, NULL, NULL); - - if (bound <= 0) - { - SetLastError(bound == -1 ? wsaErrno() : WSAEINVAL); - } - else if (listen(fd, backlog) == 0) - { - _enable_event(SOCKET2HANDLE(s), FD_ACCEPT, - FD_WINE_LISTENING, - FD_CONNECT|FD_WINE_CONNECTED); - ret = 0; - } - else - SetLastError(wsaErrno()); - release_sock_fd( s, fd ); + SetLastError( bound ? wsaErrno() : WSAEINVAL ); + return -1; }
- return ret; + status = NtDeviceIoControlFile( SOCKET2HANDLE(s), NULL, NULL, NULL, &io, + IOCTL_AFD_LISTEN, ¶ms, sizeof(params), NULL, 0 ); + SetLastError( NtStatusToWSAError( status ) ); + return status ? -1 : 0; }
+ /*********************************************************************** * recv (WS2_32.16) */