Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/tests/sock.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index f67bc4efae5..b171e6c03e1 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -3816,6 +3816,9 @@ static void test_fionread_siocatmark(void) ret = recv(client, buffer, 1, MSG_OOB); ok(ret == 1, "got %d\n", ret);
+ /* wait for the data to be available */ + check_poll_mask_todo(client, POLLRDBAND, POLLRDBAND); + check_fionread_siocatmark_todo(client, 2, FALSE);
ret = recv(client, buffer, 5, 0); @@ -3831,6 +3834,9 @@ static void test_fionread_siocatmark(void) ret = send(server, "a", 1, MSG_OOB); ok(ret == 1, "got %d\n", ret);
+ /* wait for the data to be available */ + check_poll_mask(client, POLLRDBAND, POLLRDBAND); + ret = 1; ret = setsockopt(client, SOL_SOCKET, SO_OOBINLINE, (char *)&ret, sizeof(ret)); ok(!ret, "got error %u\n", WSAGetLastError()); @@ -3845,6 +3851,9 @@ static void test_fionread_siocatmark(void) ret = send(server, "a", 1, MSG_OOB); ok(ret == 1, "got %d\n", ret);
+ /* wait for the data to be available */ + check_poll_mask(client, POLLRDNORM, POLLRDNORM); + check_fionread_siocatmark(client, 1, TRUE);
closesocket(client);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/socket.c | 170 +++++++++++++++++++++------------------ dlls/ws2_32/tests/sock.c | 14 ++-- 2 files changed, 97 insertions(+), 87 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index bfc4bb6c09d..f5958e86e9f 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -510,17 +510,6 @@ static const int ws_socktype_map[][2] = {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO}, };
-static const int ws_poll_map[][2] = -{ - MAP_OPTION( POLLERR ), - MAP_OPTION( POLLHUP ), - MAP_OPTION( POLLNVAL ), - MAP_OPTION( POLLWRNORM ), - MAP_OPTION( POLLWRBAND ), - MAP_OPTION( POLLRDNORM ), - { WS_POLLRDBAND, POLLPRI } -}; - UINT sock_get_error( int err ) { switch(err) @@ -988,40 +977,6 @@ convert_socktype_u2w(int unixsocktype) { return -1; }
-static int convert_poll_w2u(int events) -{ - int i, ret; - for (i = ret = 0; events && i < ARRAY_SIZE(ws_poll_map); i++) - { - if (ws_poll_map[i][0] & events) - { - ret |= ws_poll_map[i][1]; - events &= ~ws_poll_map[i][0]; - } - } - - if (events) - FIXME("Unsupported WSAPoll() flags 0x%x\n", events); - return ret; -} - -static int convert_poll_u2w(int events) -{ - int i, ret; - for (i = ret = 0; events && i < ARRAY_SIZE(ws_poll_map); i++) - { - if (ws_poll_map[i][1] & events) - { - ret |= ws_poll_map[i][0]; - events &= ~ws_poll_map[i][1]; - } - } - - if (events) - FIXME("Unsupported poll() flags 0x%x\n", events); - return ret; -} - static int set_ipx_packettype(int sock, int ptype) { #ifdef HAS_IPX @@ -3531,65 +3486,120 @@ static unsigned int afd_poll_flag_to_win32( unsigned int flags )
/*********************************************************************** - * WSAPoll + * WSAPoll (ws2_32.@) */ -int WINAPI WSAPoll(WSAPOLLFD *wfds, ULONG count, int timeout) +int WINAPI WSAPoll( WSAPOLLFD *fds, ULONG count, int timeout ) { - int i, ret; - struct pollfd *ufds; + struct afd_poll_params *params; + ULONG params_size, i, j; + SOCKET poll_socket = 0; + IO_STATUS_BLOCK io; + HANDLE sync_event; + int ret_count = 0; + NTSTATUS status;
if (!count) { SetLastError(WSAEINVAL); return SOCKET_ERROR; } - if (!wfds) + if (!fds) { SetLastError(WSAEFAULT); return SOCKET_ERROR; }
- if (!(ufds = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ufds[0])))) + if (!(sync_event = get_sync_event())) return -1; + + params_size = offsetof( struct afd_poll_params, sockets[count] ); + if (!(params = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, params_size ))) { SetLastError(WSAENOBUFS); return SOCKET_ERROR; }
- for (i = 0; i < count; i++) - { - ufds[i].fd = get_sock_fd(wfds[i].fd, 0, NULL); - ufds[i].events = convert_poll_w2u(wfds[i].events); - ufds[i].revents = 0; - } + params->timeout = (timeout >= 0 ? timeout * -10000 : TIMEOUT_INFINITE);
- ret = do_poll(ufds, count, timeout); - - for (i = 0; i < count; i++) + for (i = 0; i < count; ++i) { - if (ufds[i].fd != -1) + unsigned int flags = AFD_POLL_HUP | AFD_POLL_RESET | AFD_POLL_CONNECT_ERR; + + if ((INT_PTR)fds[i].fd < 0 || !socket_list_find( fds[i].fd )) { - release_sock_fd(wfds[i].fd, ufds[i].fd); - if (ufds[i].revents & POLLHUP) - { - /* Check if the socket still exists */ - int fd = get_sock_fd(wfds[i].fd, 0, NULL); - if (fd != -1) - { - wfds[i].revents = WS_POLLHUP; - release_sock_fd(wfds[i].fd, fd); - } - else - wfds[i].revents = WS_POLLNVAL; - } - else - wfds[i].revents = convert_poll_u2w(ufds[i].revents); + fds[i].revents = WS_POLLNVAL; + continue; } - else - wfds[i].revents = WS_POLLNVAL; + + poll_socket = fds[i].fd; + params->sockets[params->count].socket = fds[i].fd; + + if (fds[i].events & WS_POLLRDNORM) + flags |= AFD_POLL_ACCEPT | AFD_POLL_READ; + if (fds[i].events & WS_POLLRDBAND) + flags |= AFD_POLL_OOB; + if (fds[i].events & WS_POLLWRNORM) + flags |= AFD_POLL_WRITE; + params->sockets[params->count].flags = flags; + ++params->count; + + fds[i].revents = 0; }
- HeapFree(GetProcessHeap(), 0, ufds); - return ret; + if (!poll_socket) + { + SetLastError( WSAENOTSOCK ); + HeapFree( GetProcessHeap(), 0, params ); + return -1; + } + + status = NtDeviceIoControlFile( (HANDLE)poll_socket, sync_event, NULL, NULL, &io, IOCTL_AFD_POLL, + params, params_size, params, params_size ); + if (status == STATUS_PENDING) + { + if (WaitForSingleObject( sync_event, INFINITE ) == WAIT_FAILED) + { + HeapFree( GetProcessHeap(), 0, params ); + return -1; + } + status = io.u.Status; + } + if (!status) + { + for (i = 0; i < count; ++i) + { + for (j = 0; j < params->count; ++j) + { + if (fds[i].fd == params->sockets[j].socket) + { + unsigned int revents = 0; + + if (params->sockets[j].flags & (AFD_POLL_ACCEPT | AFD_POLL_READ)) + revents |= WS_POLLRDNORM; + if (params->sockets[j].flags & AFD_POLL_OOB) + revents |= WS_POLLRDBAND; + if (params->sockets[j].flags & AFD_POLL_WRITE) + revents |= WS_POLLWRNORM; + if (params->sockets[j].flags & AFD_POLL_HUP) + revents |= WS_POLLHUP; + if (params->sockets[j].flags & (AFD_POLL_RESET | AFD_POLL_CONNECT_ERR)) + revents |= WS_POLLERR; + if (params->sockets[j].flags & AFD_POLL_CLOSE) + revents |= WS_POLLNVAL; + + fds[i].revents = revents & (fds[i].events | WS_POLLHUP | WS_POLLERR | WS_POLLNVAL); + + if (fds[i].revents) + ++ret_count; + } + } + } + } + if (status == STATUS_TIMEOUT) status = STATUS_SUCCESS; + + HeapFree( GetProcessHeap(), 0, params ); + + SetLastError( NtStatusToWSAError( status ) ); + return status ? -1 : ret_count; }
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index b171e6c03e1..7b92d0b4e84 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -6064,7 +6064,7 @@ static void test_WSAPoll(void) WSASetLastError(0xdeadbeef); ret = pWSAPoll(fds, 2, 0); ok(!ret, "got %d\n", ret); - todo_wine ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); + ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); ok(fds[0].revents == POLLNVAL, "got events %#x\n", fds[0].revents); ok(!fds[1].revents, "got events %#x\n", fds[1].revents);
@@ -6077,7 +6077,7 @@ static void test_WSAPoll(void) WSASetLastError(0xdeadbeef); ret = pWSAPoll(fds, 2, 0); ok(!ret, "got %d\n", ret); - todo_wine ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); + ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); ok(!fds[0].revents, "got events %#x\n", fds[0].revents); ok(fds[1].revents == POLLNVAL, "got events %#x\n", fds[1].revents);
@@ -6102,7 +6102,7 @@ static void test_WSAPoll(void) fds[1].revents = 0xdead; WSASetLastError(0xdeadbeef); ret = pWSAPoll(fds, 2, 0); - todo_wine ok(ret == -1, "got %d\n", ret); + ok(ret == -1, "got %d\n", ret); ok(WSAGetLastError() == WSAENOTSOCK, "got error %u\n", WSAGetLastError()); ok(fds[0].revents == POLLNVAL, "got events %#x\n", fds[0].revents); ok(fds[1].revents == POLLNVAL, "got events %#x\n", fds[1].revents); @@ -6222,8 +6222,8 @@ static void test_WSAPoll(void) ok(ret == 1, "got %d\n", ret);
check_poll(client, POLLWRNORM); - check_poll_mask_todo(server, POLLRDNORM | POLLRDBAND, POLLRDNORM); - check_poll_todo(server, POLLWRNORM | POLLRDNORM); + check_poll_mask(server, POLLRDNORM | POLLRDBAND, POLLRDNORM); + check_poll(server, POLLWRNORM | POLLRDNORM);
buffer[0] = 0xcc; ret = recv(server, buffer, 1, 0); @@ -6261,8 +6261,8 @@ static void test_WSAPoll(void)
closesocket(client);
- check_poll_mask_todo(server, 0, POLLHUP); - check_poll_todo(server, POLLWRNORM | POLLHUP); + check_poll_mask(server, 0, POLLHUP); + check_poll(server, POLLWRNORM | POLLHUP);
closesocket(server);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/socket.c | 339 ++++++++++++----------------------- dlls/ws2_32/tests/sock.c | 10 +- dlls/ws2_32/ws2_32_private.h | 2 - 3 files changed, 126 insertions(+), 225 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index f5958e86e9f..f8ba7025ec5 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -841,7 +841,6 @@ static void free_per_thread_data(void) HeapFree( GetProcessHeap(), 0, ptb->he_buffer ); HeapFree( GetProcessHeap(), 0, ptb->se_buffer ); HeapFree( GetProcessHeap(), 0, ptb->pe_buffer ); - HeapFree( GetProcessHeap(), 0, ptb->fd_cache );
HeapFree( GetProcessHeap(), 0, ptb ); NtCurrentTeb()->WinSockData = NULL; @@ -3216,246 +3215,142 @@ int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags, return n; }
-/* allocate a poll array for the corresponding fd sets */ -static struct pollfd *fd_sets_to_poll( const WS_fd_set *readfds, const WS_fd_set *writefds, - const WS_fd_set *exceptfds, int *count_ptr ) + +/* as FD_SET(), but returns 1 if the fd was added, 0 otherwise */ +static int add_fd_to_set( SOCKET fd, struct WS_fd_set *set ) { - unsigned int i, j = 0, count = 0; - struct pollfd *fds; - struct per_thread_data *ptb = get_per_thread_data(); + unsigned int i;
- if (readfds) count += readfds->fd_count; - if (writefds) count += writefds->fd_count; - if (exceptfds) count += exceptfds->fd_count; - *count_ptr = count; - if (!count) + for (i = 0; i < set->fd_count; ++i) { - SetLastError(WSAEINVAL); - return NULL; + if (set->fd_array[i] == fd) + return 0; }
- /* check if the cache can hold all descriptors, if not do the resizing */ - if (ptb->fd_count < count) + if (set->fd_count < WS_FD_SETSIZE) { - if (!(fds = HeapAlloc(GetProcessHeap(), 0, count * sizeof(fds[0])))) - { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return NULL; - } - HeapFree(GetProcessHeap(), 0, ptb->fd_cache); - ptb->fd_cache = fds; - ptb->fd_count = count; + set->fd_array[set->fd_count++] = fd; + return 1; } - else - fds = ptb->fd_cache;
- if (readfds) - for (i = 0; i < readfds->fd_count; i++, j++) - { - fds[j].fd = get_sock_fd( readfds->fd_array[i], FILE_READ_DATA, NULL ); - if (fds[j].fd == -1) goto failed; - fds[j].revents = 0; - if (is_fd_bound(fds[j].fd, NULL, NULL) == 1) - { - fds[j].events = POLLIN; - } - else - { - release_sock_fd( readfds->fd_array[i], fds[j].fd ); - fds[j].fd = -1; - fds[j].events = 0; - } - } - if (writefds) - for (i = 0; i < writefds->fd_count; i++, j++) - { - fds[j].fd = get_sock_fd( writefds->fd_array[i], FILE_WRITE_DATA, NULL ); - if (fds[j].fd == -1) goto failed; - fds[j].revents = 0; - if (is_fd_bound(fds[j].fd, NULL, NULL) == 1 || - _get_fd_type(fds[j].fd) == SOCK_DGRAM) - { - fds[j].events = POLLOUT; - } - else - { - release_sock_fd( writefds->fd_array[i], fds[j].fd ); - fds[j].fd = -1; - fds[j].events = 0; - } - } - if (exceptfds) - for (i = 0; i < exceptfds->fd_count; i++, j++) - { - fds[j].fd = get_sock_fd( exceptfds->fd_array[i], 0, NULL ); - if (fds[j].fd == -1) goto failed; - fds[j].revents = 0; - if (is_fd_bound(fds[j].fd, NULL, NULL) == 1) - { - int oob_inlined = 0; - socklen_t olen = sizeof(oob_inlined); - - fds[j].events = POLLHUP; - - /* Check if we need to test for urgent data or not */ - getsockopt(fds[j].fd, SOL_SOCKET, SO_OOBINLINE, (char*) &oob_inlined, &olen); - if (!oob_inlined) - fds[j].events |= POLLPRI; - } - else - { - release_sock_fd( exceptfds->fd_array[i], fds[j].fd ); - fds[j].fd = -1; - fds[j].events = 0; - } - } - return fds; - -failed: - count = j; - j = 0; - if (readfds) - for (i = 0; i < readfds->fd_count && j < count; i++, j++) - if (fds[j].fd != -1) release_sock_fd( readfds->fd_array[i], fds[j].fd ); - if (writefds) - for (i = 0; i < writefds->fd_count && j < count; i++, j++) - if (fds[j].fd != -1) release_sock_fd( writefds->fd_array[i], fds[j].fd ); - if (exceptfds) - for (i = 0; i < exceptfds->fd_count && j < count; i++, j++) - if (fds[j].fd != -1) release_sock_fd( exceptfds->fd_array[i], fds[j].fd ); - return NULL; + return 0; }
-/* release the file descriptor obtained in fd_sets_to_poll */ -/* must be called with the original fd_set arrays, before calling get_poll_results */ -static void release_poll_fds( const WS_fd_set *readfds, const WS_fd_set *writefds, - const WS_fd_set *exceptfds, struct pollfd *fds ) -{ - unsigned int i, j = 0; - - if (readfds) - { - for (i = 0; i < readfds->fd_count; i++, j++) - if (fds[j].fd != -1) release_sock_fd( readfds->fd_array[i], fds[j].fd ); - } - if (writefds) - { - for (i = 0; i < writefds->fd_count; i++, j++) - if (fds[j].fd != -1) release_sock_fd( writefds->fd_array[i], fds[j].fd ); - } - if (exceptfds) - { - for (i = 0; i < exceptfds->fd_count; i++, j++) - { - if (fds[j].fd == -1) continue; - release_sock_fd( exceptfds->fd_array[i], fds[j].fd ); - if (fds[j].revents & POLLHUP) - { - int fd = get_sock_fd( exceptfds->fd_array[i], 0, NULL ); - if (fd != -1) - release_sock_fd( exceptfds->fd_array[i], fd ); - else - fds[j].revents = 0; - } - } - } -} - -static int do_poll(struct pollfd *pollfds, int count, int timeout) -{ - struct timeval tv1, tv2; - int ret, torig = timeout; - - if (timeout > 0) gettimeofday( &tv1, 0 ); - - while ((ret = poll( pollfds, count, timeout )) < 0) - { - if (errno != EINTR) break; - if (timeout < 0) continue; - if (timeout == 0) return 0; - - gettimeofday( &tv2, 0 ); - - tv2.tv_sec -= tv1.tv_sec; - tv2.tv_usec -= tv1.tv_usec; - if (tv2.tv_usec < 0) - { - tv2.tv_usec += 1000000; - tv2.tv_sec -= 1; - } - - timeout = torig - (tv2.tv_sec * 1000) - (tv2.tv_usec + 999) / 1000; - if (timeout <= 0) return 0; - } - return ret; -} - -/* map the poll results back into the Windows fd sets */ -static int get_poll_results( WS_fd_set *readfds, WS_fd_set *writefds, WS_fd_set *exceptfds, - const struct pollfd *fds ) -{ - const struct pollfd *poll_writefds = fds + (readfds ? readfds->fd_count : 0); - const struct pollfd *poll_exceptfds = poll_writefds + (writefds ? writefds->fd_count : 0); - unsigned int i, k, total = 0; - - if (readfds) - { - for (i = k = 0; i < readfds->fd_count; i++) - { - if (fds[i].revents || - (readfds == writefds && (poll_writefds[i].revents & POLLOUT) && !(poll_writefds[i].revents & POLLHUP)) || - (readfds == exceptfds && poll_exceptfds[i].revents)) - readfds->fd_array[k++] = readfds->fd_array[i]; - } - readfds->fd_count = k; - total += k; - } - if (writefds && writefds != readfds) - { - for (i = k = 0; i < writefds->fd_count; i++) - { - if (((poll_writefds[i].revents & POLLOUT) && !(poll_writefds[i].revents & POLLHUP)) || - (writefds == exceptfds && poll_exceptfds[i].revents)) - writefds->fd_array[k++] = writefds->fd_array[i]; - } - writefds->fd_count = k; - total += k; - } - if (exceptfds && exceptfds != readfds && exceptfds != writefds) - { - for (i = k = 0; i < exceptfds->fd_count; i++) - if (poll_exceptfds[i].revents) exceptfds->fd_array[k++] = exceptfds->fd_array[i]; - exceptfds->fd_count = k; - total += k; - } - return total; -}
/*********************************************************************** - * select (WS2_32.18) + * select (ws2_32.18) */ -int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds, - WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds, - const struct WS_timeval* ws_timeout) +int WINAPI WS_select( int count, WS_fd_set *read_ptr, WS_fd_set *write_ptr, + WS_fd_set *except_ptr, const struct WS_timeval *timeout) { - struct pollfd *pollfds; - int count, ret, timeout = -1; + char buffer[offsetof( struct afd_poll_params, sockets[WS_FD_SETSIZE * 3] )] = {0}; + struct afd_poll_params *params = (struct afd_poll_params *)buffer; + struct WS_fd_set read, write, except; + ULONG params_size, i, j; + SOCKET poll_socket = 0; + IO_STATUS_BLOCK io; + HANDLE sync_event; + int ret_count = 0; + NTSTATUS status;
- TRACE("read %p, write %p, excp %p timeout %p\n", - ws_readfds, ws_writefds, ws_exceptfds, ws_timeout); + TRACE( "read %p, write %p, except %p, timeout %p\n", read_ptr, write_ptr, except_ptr, timeout );
- if (!(pollfds = fd_sets_to_poll( ws_readfds, ws_writefds, ws_exceptfds, &count ))) - return SOCKET_ERROR; + WS_FD_ZERO( &read ); + WS_FD_ZERO( &write ); + WS_FD_ZERO( &except ); + if (read_ptr) read = *read_ptr; + if (write_ptr) write = *write_ptr; + if (except_ptr) except = *except_ptr;
- if (ws_timeout) - timeout = (ws_timeout->tv_sec * 1000) + (ws_timeout->tv_usec + 999) / 1000; + if (!(sync_event = get_sync_event())) return -1;
- ret = do_poll(pollfds, count, timeout); - release_poll_fds( ws_readfds, ws_writefds, ws_exceptfds, pollfds ); + if (timeout) + params->timeout = timeout->tv_sec * -10000000 + timeout->tv_usec * -10; + else + params->timeout = TIMEOUT_INFINITE;
- if (ret == -1) SetLastError(wsaErrno()); - else ret = get_poll_results( ws_readfds, ws_writefds, ws_exceptfds, pollfds ); - return ret; + for (i = 0; i < read.fd_count; ++i) + { + params->sockets[params->count].socket = read.fd_array[i]; + params->sockets[params->count].flags = AFD_POLL_READ | AFD_POLL_ACCEPT | AFD_POLL_HUP; + ++params->count; + poll_socket = read.fd_array[i]; + } + + for (i = 0; i < write.fd_count; ++i) + { + params->sockets[params->count].socket = write.fd_array[i]; + params->sockets[params->count].flags = AFD_POLL_WRITE; + ++params->count; + poll_socket = write.fd_array[i]; + } + + for (i = 0; i < except.fd_count; ++i) + { + params->sockets[params->count].socket = except.fd_array[i]; + params->sockets[params->count].flags = AFD_POLL_OOB | AFD_POLL_CONNECT_ERR; + ++params->count; + poll_socket = except.fd_array[i]; + } + + if (!params->count) + { + SetLastError( WSAEINVAL ); + return -1; + } + + params_size = offsetof( struct afd_poll_params, sockets[params->count] ); + + status = NtDeviceIoControlFile( (HANDLE)poll_socket, sync_event, NULL, NULL, &io, + IOCTL_AFD_POLL, params, params_size, params, params_size ); + if (status == STATUS_PENDING) + { + if (WaitForSingleObject( sync_event, INFINITE ) == WAIT_FAILED) + return -1; + status = io.u.Status; + } + if (status == STATUS_TIMEOUT) status = STATUS_SUCCESS; + if (!status) + { + /* pointers may alias, so clear them all first */ + if (read_ptr) WS_FD_ZERO( read_ptr ); + if (write_ptr) WS_FD_ZERO( write_ptr ); + if (except_ptr) WS_FD_ZERO( except_ptr ); + + for (i = 0; i < params->count; ++i) + { + unsigned int flags = params->sockets[i].flags; + SOCKET s = params->sockets[i].socket; + + for (j = 0; j < read.fd_count; ++j) + { + if (read.fd_array[j] == s + && (flags & (AFD_POLL_READ | AFD_POLL_ACCEPT | AFD_POLL_HUP | AFD_POLL_CLOSE))) + { + ret_count += add_fd_to_set( s, read_ptr ); + flags &= ~AFD_POLL_CLOSE; + } + } + + if (flags & AFD_POLL_CLOSE) + status = STATUS_INVALID_HANDLE; + + for (j = 0; j < write.fd_count; ++j) + { + if (write.fd_array[j] == s && (flags & AFD_POLL_WRITE)) + ret_count += add_fd_to_set( s, write_ptr ); + } + + for (j = 0; j < except.fd_count; ++j) + { + if (except.fd_array[j] == s && (flags & (AFD_POLL_OOB | AFD_POLL_CONNECT_ERR))) + ret_count += add_fd_to_set( s, except_ptr ); + } + } + } + + SetLastError( NtStatusToWSAError( status ) ); + return status ? -1 : ret_count; }
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 7b92d0b4e84..01c14382e84 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -3127,6 +3127,14 @@ static void test_select(void) ret = select(0, &readfds, &writefds, &exceptfds, &select_timeout); ok(ret == 1, "expected 1, got %d\n", ret); ok(FD_ISSET(fdRead, &readfds), "fdRead socket is not in the set\n"); + ok(!FD_ISSET(fdRead, &exceptfds), "fdRead socket is in the set\n"); + FD_ZERO_ALL(); + FD_SET_ALL(fdRead); + ret = select(0, &readfds, &writefds, &exceptfds, &select_timeout); + ok(ret == 2, "expected 1, got %d\n", ret); + ok(FD_ISSET(fdRead, &readfds), "fdRead socket is not in the set\n"); + ok(FD_ISSET(fdRead, &writefds), "fdRead socket is not in the set\n"); + ok(!FD_ISSET(fdRead, &exceptfds), "fdRead socket is in the set\n"); ret = recv(fdRead, tmp_buf, sizeof(tmp_buf), 0); ok(ret == 4, "expected 4, got %d\n", ret); ok(!strcmp(tmp_buf, "1234"), "data received differs from sent\n"); @@ -3239,9 +3247,9 @@ static void test_select(void) FD_SET(fdWrite, &exceptfds); SetLastError(0xdeadbeef); ret = select(0, NULL, NULL, &exceptfds, &select_timeout); -todo_wine ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret); ok(GetLastError() == WSAENOTSOCK, "got %d\n", GetLastError()); + ok(!FD_ISSET(fdWrite, &exceptfds), "fdWrite socket is in the set\n"); WaitForSingleObject (thread_handle, 1000); closesocket(fdRead);
diff --git a/dlls/ws2_32/ws2_32_private.h b/dlls/ws2_32/ws2_32_private.h index 8baa62908dd..b70f4a1595d 100644 --- a/dlls/ws2_32/ws2_32_private.h +++ b/dlls/ws2_32/ws2_32_private.h @@ -190,8 +190,6 @@ struct per_thread_data struct WS_hostent *he_buffer; struct WS_servent *se_buffer; struct WS_protoent *pe_buffer; - struct pollfd *fd_cache; - unsigned int fd_count; int he_len; int se_len; int pe_len;
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=92808
Your paranoid android.
=== debiant2 (32 bit WoW report) ===
Report validation errors: sock: Timeout
=== debiant2 (build log) ===
WineRunWineTest.pl:error: The task timed out
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- include/wine/afd.h | 6 ++++++ server/sock.c | 17 +++++++++++++++++ 2 files changed, 23 insertions(+)
diff --git a/include/wine/afd.h b/include/wine/afd.h index 6f0a78ca933..e497eece0be 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -158,6 +158,7 @@ struct afd_get_events_params #define IOCTL_AFD_WINE_MESSAGE_SELECT CTL_CODE(FILE_DEVICE_NETWORK, 215, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_GETPEERNAME CTL_CODE(FILE_DEVICE_NETWORK, 216, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_DEFER CTL_CODE(FILE_DEVICE_NETWORK, 217, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_AFD_WINE_GET_INFO CTL_CODE(FILE_DEVICE_NETWORK, 218, METHOD_BUFFERED, FILE_ANY_ACCESS)
struct afd_create_params { @@ -218,4 +219,9 @@ struct afd_message_select_params int mask; };
+struct afd_get_info_params +{ + int family, type, protocol; +}; + #endif diff --git a/server/sock.c b/server/sock.c index 547287572d5..46018887692 100644 --- a/server/sock.c +++ b/server/sock.c @@ -2515,6 +2515,23 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) return 1; }
+ case IOCTL_AFD_WINE_GET_INFO: + { + struct afd_get_info_params params; + + if (get_reply_max_size() < sizeof(params)) + { + set_error( STATUS_BUFFER_TOO_SMALL ); + return 0; + } + + params.family = sock->family; + params.type = sock->type; + params.protocol = sock->proto; + set_reply_data( ¶ms, sizeof(params) ); + return 0; + } + default: set_error( STATUS_NOT_SUPPORTED ); return 0;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/socket.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index f8ba7025ec5..44c0690d535 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -1433,41 +1433,29 @@ static INT WS_DuplicateSocket(BOOL unicode, SOCKET s, DWORD dwProcessId, LPWSAPR
static BOOL ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, int *size) { + struct afd_get_info_params params; + IO_STATUS_BLOCK io; NTSTATUS status; - int address_family; - int socket_type; - int protocol; unsigned int i;
*size = unicode ? sizeof(WSAPROTOCOL_INFOW) : sizeof(WSAPROTOCOL_INFOA); memset(buffer, 0, *size);
- SERVER_START_REQ( get_socket_info ) - { - req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) ); - status = wine_server_call( req ); - if (!status) - { - address_family = reply->family; - socket_type = reply->type; - protocol = reply->protocol; - } - } - SERVER_END_REQ; - + status = NtDeviceIoControlFile( (HANDLE)s, NULL, NULL, NULL, &io, + IOCTL_AFD_WINE_GET_INFO, NULL, 0, ¶ms, sizeof(params) ); if (status) { - unsigned int err = NtStatusToWSAError( status ); - SetLastError( err == WSAEBADF ? WSAENOTSOCK : err ); + SetLastError( NtStatusToWSAError( status ) ); return FALSE; }
for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i) { const WSAPROTOCOL_INFOW *info = &supported_protocols[i]; - if (address_family == info->iAddressFamily && - socket_type == info->iSocketType && - protocol >= info->iProtocol && protocol <= info->iProtocol + info->iProtocolMaxOffset) + if (params.family == info->iAddressFamily && + params.type == info->iSocketType && + params.protocol >= info->iProtocol && + params.protocol <= info->iProtocol + info->iProtocolMaxOffset) { if (unicode) *buffer = *info; @@ -1478,12 +1466,12 @@ static BOOL ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, i WideCharToMultiByte( CP_ACP, 0, info->szProtocol, -1, bufferA->szProtocol, sizeof(bufferA->szProtocol), NULL, NULL ); } - buffer->iProtocol = protocol; + buffer->iProtocol = params.protocol; return TRUE; } } - FIXME("Could not fill protocol information for family %d, type %d, protocol %d.\n", - address_family, socket_type, protocol); + FIXME( "Could not fill protocol information for family %d, type %d, protocol %d.\n", + params.family, params.type, params.protocol ); return TRUE; }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- server/protocol.def | 10 ---------- server/sock.c | 16 ---------------- 2 files changed, 26 deletions(-)
diff --git a/server/protocol.def b/server/protocol.def index 72f2f2c20ae..b5bc049ccf6 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1435,16 +1435,6 @@ enum server_fd_type @END
-/* Get socket info */ -@REQ(get_socket_info) - obj_handle_t handle; /* handle to the socket */ -@REPLY - int family; /* family, see socket manpage */ - int type; /* type, see socket manpage */ - int protocol; /* protocol, see socket manpage */ -@END - - /* Perform a recv on a socket */ @REQ(recv_socket) int oob; /* are we receiving OOB data? */ diff --git a/server/sock.c b/server/sock.c index 46018887692..b73fbb98388 100644 --- a/server/sock.c +++ b/server/sock.c @@ -2967,22 +2967,6 @@ DECL_HANDLER(get_socket_event) release_object( &sock->obj ); }
-DECL_HANDLER(get_socket_info) -{ - struct sock *sock; - - sock = (struct sock *)get_handle_obj( current->process, req->handle, FILE_READ_ATTRIBUTES, &sock_ops ); - if (!sock) return; - - if (get_unix_fd( sock->fd ) == -1) return; - - reply->family = sock->family; - reply->type = sock->type; - reply->protocol = sock->proto; - - release_object( &sock->obj ); -} - DECL_HANDLER(recv_socket) { struct sock *sock = (struct sock *)get_handle_obj( current->process, req->async.handle, 0, &sock_ops );