Bruno Jesus : ws2_32: Implement get socket option SO_PROTOCOL_INFO.

Alexandre Julliard julliard at winehq.org
Tue Sep 10 14:49:56 CDT 2013


Module: wine
Branch: master
Commit: dea4f7bc02c388f6d17b28217995e2dc7611beb1
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=dea4f7bc02c388f6d17b28217995e2dc7611beb1

Author: Bruno Jesus <00cpxxx at gmail.com>
Date:   Tue Sep 10 00:56:47 2013 -0300

ws2_32: Implement get socket option SO_PROTOCOL_INFO.

---

 dlls/ws2_32/socket.c     |   53 ++++++++++++++++++++++++++++++++++++++++++++++
 dlls/ws2_32/tests/sock.c |   45 ++++++++++++++++++++++++++------------
 2 files changed, 84 insertions(+), 14 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 833c713..5f5f161 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -1747,6 +1747,40 @@ static INT WS_EnumProtocols( BOOL unicode, const INT *protocols, LPWSAPROTOCOL_I
     return items;
 }
 
+static BOOL ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, int *size)
+{
+    NTSTATUS status;
+
+    *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)
+        {
+            buffer->iAddressFamily = convert_af_u2w(reply->family);
+            buffer->iSocketType = convert_socktype_u2w(reply->type);
+            buffer->iProtocol = convert_proto_u2w(reply->protocol);
+        }
+    }
+    SERVER_END_REQ;
+
+    if (status)
+    {
+        set_error(status);
+        return FALSE;
+    }
+
+    if (unicode)
+        WS_EnterSingleProtocolW( buffer->iProtocol, buffer);
+    else
+        WS_EnterSingleProtocolA( buffer->iProtocol, (WSAPROTOCOL_INFOA *)buffer);
+
+    return TRUE;
+}
+
 /**************************************************************************
  * Functions for handling overlapped I/O
  **************************************************************************/
@@ -3024,7 +3058,26 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level,
             *optlen = sizeof(int);
             TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
             return 0;
+        case WS_SO_PROTOCOL_INFOA:
+        case WS_SO_PROTOCOL_INFOW:
+        {
+            int size;
+            WSAPROTOCOL_INFOW infow;
 
+            ret = ws_protocol_info(s, optname == WS_SO_PROTOCOL_INFOW, &infow, &size);
+            if (ret)
+            {
+                if (!optlen || !optval || *optlen < size)
+                {
+                    if(optlen) *optlen = size;
+                    ret = 0;
+                    SetLastError(WSAEFAULT);
+                }
+                else
+                    memcpy(optval, &infow, size);
+            }
+            return ret ? 0 : SOCKET_ERROR;
+        }
 #ifdef SO_RCVTIMEO
         case WS_SO_RCVTIMEO:
 #endif
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 78521ae..e072033 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -1235,29 +1235,40 @@ todo_wine
     closesocket(s);
 
     /* test SO_PROTOCOL_INFOA invalid parameters */
+    ok(getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_PROTOCOL_INFOA, NULL, NULL),
+       "getsockopt should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAENOTSOCK, "expected 10038, got %d instead\n", err);
+    size = sizeof(WSAPROTOCOL_INFOA);
+    ok(getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_PROTOCOL_INFOA, (char *) &infoA, &size),
+       "getsockopt should have failed\n");
+    ok(size == sizeof(WSAPROTOCOL_INFOA), "got size %d\n", size);
+    err = WSAGetLastError();
+    ok(err == WSAENOTSOCK, "expected 10038, got %d instead\n", err);
     s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     ok(getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, NULL, NULL),
        "getsockopt should have failed\n");
     err = WSAGetLastError();
-todo_wine
     ok(err == WSAEFAULT, "expected 10014, got %d instead\n", err);
     ok(getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, (char *) &infoA, NULL),
        "getsockopt should have failed\n");
     err = WSAGetLastError();
-todo_wine
     ok(err == WSAEFAULT, "expected 10014, got %d instead\n", err);
     ok(getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, NULL, &size),
        "getsockopt should have failed\n");
     err = WSAGetLastError();
-todo_wine
     ok(err == WSAEFAULT, "expected 10014, got %d instead\n", err);
-
     size = sizeof(WSAPROTOCOL_INFOA) / 2;
     ok(getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, (char *) &infoA, &size),
        "getsockopt should have failed\n");
     err = WSAGetLastError();
-todo_wine
     ok(err == WSAEFAULT, "expected 10014, got %d instead\n", err);
+    ok(size == sizeof(WSAPROTOCOL_INFOA), "got size %d\n", size);
+    size = sizeof(WSAPROTOCOL_INFOA) * 2;
+    err = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, (char *) &infoA, &size);
+    ok(!err,"getsockopt failed with %d\n", WSAGetLastError());
+    ok(size == sizeof(WSAPROTOCOL_INFOA) * 2, "got size %d\n", size);
+
     closesocket(s);
 
     /* test SO_PROTOCOL_INFO structure returned for different protocols */
@@ -1273,40 +1284,46 @@ todo_wine
         infoA.szProtocol[0] = 0;
         size = sizeof(WSAPROTOCOL_INFOA);
         err = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, (char *) &infoA, &size);
-todo_wine
         ok(!err,"getsockopt failed with %d\n", WSAGetLastError());
+        ok(size == sizeof(WSAPROTOCOL_INFOA), "got size %d\n", size);
 
         infoW.szProtocol[0] = 0;
         size = sizeof(WSAPROTOCOL_INFOW);
         err = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOW, (char *) &infoW, &size);
-todo_wine
         ok(!err,"getsockopt failed with %d\n", WSAGetLastError());
+        ok(size == sizeof(WSAPROTOCOL_INFOW), "got size %d\n", size);
 
         trace("provider name '%s', family %d, type %d, proto %d\n",
               infoA.szProtocol, prottest[i].family, prottest[i].type, prottest[i].proto);
 
-        todo_wine {
         ok(infoA.szProtocol[0] || broken(!infoA.szProtocol[0]) /* NT4 */,
            "WSAPROTOCOL_INFOA was not filled\n");
         ok(infoW.szProtocol[0] || broken(!infoA.szProtocol[0]) /* NT4 */,
            "WSAPROTOCOL_INFOW was not filled\n");
-        }
 
         WideCharToMultiByte(CP_ACP, 0, infoW.szProtocol, -1,
                             providername, sizeof(providername), NULL, NULL);
         ok(!strcmp(infoA.szProtocol,providername),
            "different provider names '%s' != '%s'\n", infoA.szProtocol, providername);
 
-        todo_wine {
         ok(!memcmp(&infoA, &infoW, FIELD_OFFSET(WSAPROTOCOL_INFOA, szProtocol)),
            "SO_PROTOCOL_INFO[A/W] comparison failed\n");
-        ok(infoA.iAddressFamily == prottest[i].family, "socket family invalid, expected %d received %d\n",
-           prottest[i].family, infoA.iAddressFamily);
-        ok(infoA.iSocketType == prottest[i].type, "socket type invalid, expected %d received %d\n",
+
+        /* Remove IF when WSAEnumProtocols support IPV6 data */
+        if (prottest[i].family == AF_INET6)
+        {
+            todo_wine
+            ok(infoA.iAddressFamily == prottest[i].family, "socket family invalid, expected %d received %d\n",
+               prottest[i].family, infoA.iAddressFamily);
+        }
+        else
+        {
+            ok(infoA.iAddressFamily == prottest[i].family, "socket family invalid, expected %d received %d\n",
+               prottest[i].family, infoA.iAddressFamily);
+        }        ok(infoA.iSocketType == prottest[i].type, "socket type invalid, expected %d received %d\n",
            prottest[i].type, infoA.iSocketType);
         ok(infoA.iProtocol == prottest[i].proto, "socket protocol invalid, expected %d received %d\n",
            prottest[i].proto, infoA.iProtocol);
-        }
 
         closesocket(s);
     }




More information about the wine-cvs mailing list