[PATCH resend] ws2_32: Support setting SO_ERROR
Alex Henrie
alexhenrie24 at gmail.com
Mon Nov 22 23:06:02 CST 2021
Signed-off-by: Alex Henrie <alexhenrie24 at gmail.com>
---
This patch was previously assigned to Zeb Figura, but dropped off the
patches list without review.
---
dlls/ws2_32/socket.c | 4 +---
dlls/ws2_32/tests/sock.c | 10 ++++++++--
include/wine/afd.h | 1 +
server/sock.c | 38 +++++++++++++++++++++++++++-----------
4 files changed, 37 insertions(+), 16 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 2db441bee3c..2c2eabc09fa 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -2750,9 +2750,7 @@ int WINAPI setsockopt( SOCKET s, int level, int optname, const char *optval, int
}
case SO_ERROR:
- FIXME( "SO_ERROR, stub!\n" );
- SetLastError( WSAENOPROTOOPT );
- return -1;
+ return server_setsockopt( s, IOCTL_AFD_WINE_SET_SO_ERROR, optval, optlen );
case SO_KEEPALIVE:
return server_setsockopt( s, IOCTL_AFD_WINE_SET_SO_KEEPALIVE, optval, optlen );
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 02713a7c625..76f4f1ef8a2 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -1289,7 +1289,6 @@ static void test_set_getsockopt(void)
SetLastError(0xdeadbeef);
i = 1234;
err = setsockopt(s, SOL_SOCKET, SO_ERROR, (char *) &i, size);
-todo_wine
ok( !err && !WSAGetLastError(),
"got %d with %d (expected 0 with 0)\n",
err, WSAGetLastError());
@@ -1300,7 +1299,14 @@ todo_wine
ok( !err && !WSAGetLastError(),
"got %d with %d (expected 0 with 0)\n",
err, WSAGetLastError());
-todo_wine
+ ok (i == 1234, "got %d (expected 1234)\n", i);
+
+ SetLastError(0xdeadbeef);
+ i = 4321;
+ err = getsockopt(s, SOL_SOCKET, SO_ERROR, (char *) &i, &size);
+ ok( !err && !WSAGetLastError(),
+ "got %d with %d (expected 0 with 0)\n",
+ err, WSAGetLastError());
ok (i == 1234, "got %d (expected 1234)\n", i);
/* Test invalid optlen */
diff --git a/include/wine/afd.h b/include/wine/afd.h
index 3b8bdcb9e5d..9382e2acf2f 100644
--- a/include/wine/afd.h
+++ b/include/wine/afd.h
@@ -238,6 +238,7 @@ struct afd_get_events_params
#define IOCTL_AFD_WINE_SET_IP_RECVTTL WINE_AFD_IOC(294)
#define IOCTL_AFD_WINE_GET_IP_RECVTOS WINE_AFD_IOC(295)
#define IOCTL_AFD_WINE_SET_IP_RECVTOS WINE_AFD_IOC(296)
+#define IOCTL_AFD_WINE_SET_SO_ERROR WINE_AFD_IOC(297)
struct afd_create_params
{
diff --git a/server/sock.c b/server/sock.c
index c9b71137c4c..cfb65e0b54c 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -191,6 +191,7 @@ struct sock
unsigned int message; /* message to send */
obj_handle_t wparam; /* message wparam (socket handle) */
int errors[AFD_POLL_BIT_COUNT]; /* event errors */
+ unsigned int last_error; /* most recent error code */
timeout_t connect_time;/* time the socket was connected */
struct sock *deferred; /* socket that waits for a deferred accept */
struct async_queue read_q; /* queue for asynchronous reads */
@@ -963,6 +964,7 @@ static void post_socket_event( struct sock *sock, enum afd_poll_bit event_bit, i
sock->pending_events |= event;
sock->reported_events |= event;
sock->errors[event_bit] = error;
+ sock->last_error = sock_get_error( error );
}
}
@@ -978,6 +980,7 @@ static void sock_dispatch_events( struct sock *sock, enum connection_state prevs
{
post_socket_event( sock, AFD_POLL_BIT_CONNECT, 0 );
sock->errors[AFD_POLL_BIT_CONNECT_ERR] = 0;
+ sock->last_error = 0;
}
if (event & (POLLERR | POLLHUP))
post_socket_event( sock, AFD_POLL_BIT_CONNECT_ERR, error );
@@ -1441,6 +1444,7 @@ static struct sock *create_socket(void)
init_async_queue( &sock->connect_q );
init_async_queue( &sock->poll_q );
memset( sock->errors, 0, sizeof(sock->errors) );
+ sock->last_error = 0;
list_init( &sock->accept_list );
return sock;
}
@@ -2675,7 +2679,6 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
{
int error;
socklen_t len = sizeof(error);
- unsigned int i;
if (get_reply_max_size() < sizeof(error))
{
@@ -2689,19 +2692,32 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
return;
}
- if (!error)
+ if (error)
+ sock->last_error = sock_get_error( error );
+
+ set_reply_data( &sock->last_error, sizeof(sock->last_error) );
+ return;
+ }
+
+ case IOCTL_AFD_WINE_SET_SO_ERROR:
+ {
+ int error;
+ socklen_t len = sizeof(error);
+
+ if (get_req_data_size() < sizeof(sock->last_error))
{
- for (i = 0; i < ARRAY_SIZE( sock->errors ); ++i)
- {
- if (sock->errors[i])
- {
- error = sock_get_error( sock->errors[i] );
- break;
- }
- }
+ set_error( STATUS_BUFFER_TOO_SMALL );
+ return;
+ }
+
+ /* clear the native error, if any */
+ if (getsockopt( unix_fd, SOL_SOCKET, SO_ERROR, (char *)&error, &len ) < 0)
+ {
+ set_error( sock_get_ntstatus( errno ) );
+ return;
}
- set_reply_data( &error, sizeof(error) );
+ sock->last_error = *(unsigned int *)get_req_data();
return;
}
--
2.34.0
More information about the wine-devel
mailing list