[PATCH 3/3] ws2_32: Properly implement getsockopt(SO_CONNECT_TIME).

Zebediah Figura zfigura at codeweavers.com
Wed Aug 18 22:34:13 CDT 2021


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
I don't know what application wants this, if any do, but it at least seems
better than reporting a fake value.

 dlls/ws2_32/socket.c | 29 ++++++++---------------------
 include/wine/afd.h   |  1 +
 server/sock.c        | 17 +++++++++++++++++
 3 files changed, 26 insertions(+), 21 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index a5461ae9327..1c23da8c571 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -1424,6 +1424,14 @@ int WINAPI getsockopt( SOCKET s, int level, int optname, char *optval, int *optl
             return 0;
         }
 
+        case SO_CONNECT_TIME:
+            if (!optlen || !optval)
+            {
+                SetLastError( WSAEFAULT );
+                return -1;
+            }
+            return server_getsockopt( s, IOCTL_AFD_WINE_GET_SO_CONNECT_TIME, optval, optlen );
+
         case SO_DEBUG:
             WARN( "returning 0 for SO_DEBUG\n" );
             *(DWORD *)optval = 0;
@@ -1450,27 +1458,6 @@ int WINAPI getsockopt( SOCKET s, int level, int optname, char *optval, int *optl
             return ret;
         }
 
-        case SO_CONNECT_TIME:
-        {
-            static int pretendtime = 0;
-            struct sockaddr addr;
-            int len = sizeof(addr);
-
-            if (!optlen || *optlen < sizeof(DWORD) || !optval)
-            {
-                SetLastError(WSAEFAULT);
-                return SOCKET_ERROR;
-            }
-            if (getpeername(s, &addr, &len) == SOCKET_ERROR)
-                *(DWORD *)optval = ~0u;
-            else
-            {
-                if (!pretendtime) FIXME("SO_CONNECT_TIME - faking results\n");
-                *(DWORD *)optval = pretendtime++;
-            }
-            *optlen = sizeof(DWORD);
-            return ret;
-        }
         /* As mentioned in setsockopt, Windows ignores this, so we
          * always return true here */
         case SO_DONTROUTE:
diff --git a/include/wine/afd.h b/include/wine/afd.h
index 43e140c91c6..1eb174eb5f5 100644
--- a/include/wine/afd.h
+++ b/include/wine/afd.h
@@ -232,6 +232,7 @@ struct afd_get_events_params
 #define IOCTL_AFD_WINE_SET_IPV6_RECVPKTINFO             WINE_AFD_IOC(289)
 #define IOCTL_AFD_WINE_GET_IPV6_RECVTCLASS              WINE_AFD_IOC(290)
 #define IOCTL_AFD_WINE_SET_IPV6_RECVTCLASS              WINE_AFD_IOC(291)
+#define IOCTL_AFD_WINE_GET_SO_CONNECT_TIME              WINE_AFD_IOC(292)
 
 struct afd_create_params
 {
diff --git a/server/sock.c b/server/sock.c
index 27477200ed0..50bfc08e145 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -2807,6 +2807,23 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
         return 0;
     }
 
+    case IOCTL_AFD_WINE_GET_SO_CONNECT_TIME:
+    {
+        DWORD time = ~0u;
+
+        if (get_reply_max_size() < sizeof(time))
+        {
+            set_error( STATUS_BUFFER_TOO_SMALL );
+            return 0;
+        }
+
+        if (sock->state == SOCK_CONNECTED)
+            time = (current_time - sock->connect_time) / 10000000;
+
+        set_reply_data( &time, sizeof(time) );
+        return 1;
+    }
+
     default:
         set_error( STATUS_NOT_SUPPORTED );
         return 0;
-- 
2.30.2




More information about the wine-devel mailing list