[PATCH v2 1/3] ws2_32: Extend WS_EnterSingleProtocolW

Robin Ebert ebertrobin2002 at gmail.com
Thu Aug 13 07:08:18 CDT 2020


WS_EnterSingleProtocol needs to handle addressfamily as the WSAPROTOCOL_INFOW struct differs among different addressfamilies.
This renders the old WS_EnumProtocols implementation useless resulting in missing WS_EnumProtocolsA and WS_EnumProtocolsW implementations.

Signed-off-by: Robin Ebert <ebertrobin2002 at gmail.com>
---
v2: Report not supported error in WS_EnumProtocols
---
 dlls/ws2_32/socket.c | 225 +++++++++++++++++++++++++++++--------------
 1 file changed, 151 insertions(+), 74 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 4d2afa94..c67527d0 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -2158,23 +2158,20 @@ static INT WS_DuplicateSocket(BOOL unicode, SOCKET s, DWORD dwProcessId, LPWSAPR
 }
 
 /*****************************************************************************
- *          WS_EnterSingleProtocolW [internal]
+ *          WS_AF_INET_EnterSingleProtocolW [internal]
  *
  *    enters the protocol information of one given protocol into the given
  *    buffer.
  *
+ *    HANDLES AF_INET
+ *
  * RETURNS
  *    TRUE if a protocol was entered into the buffer.
  *
- * BUGS
- *    - only implemented for IPX, SPX, SPXII, TCP, UDP
- *    - there is no check that the operating system supports the returned
- *      protocols
  */
-static BOOL WS_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info )
+static BOOL WS_AF_INET_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info )
 {
-    memset( info, 0, sizeof(WSAPROTOCOL_INFOW) );
-    info->iProtocol = protocol;
+    info->iAddressFamily = WS_AF_INET;
 
     switch (protocol)
     {
@@ -2187,7 +2184,6 @@ static BOOL WS_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info )
         info->dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO;
         info->ProtocolChain.ChainLen = 1;
         info->iVersion = 2;
-        info->iAddressFamily = WS_AF_INET;
         info->iMaxSockAddr = 0x10;
         info->iMinSockAddr = 0x10;
         info->iSocketType = WS_SOCK_STREAM;
@@ -2203,7 +2199,6 @@ static BOOL WS_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info )
         info->dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO;
         info->ProtocolChain.ChainLen = 1;
         info->iVersion = 2;
-        info->iAddressFamily = WS_AF_INET;
         info->iMaxSockAddr = 0x10;
         info->iMinSockAddr = 0x10;
         info->iSocketType = WS_SOCK_DGRAM;
@@ -2211,6 +2206,85 @@ static BOOL WS_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info )
         strcpyW( info->szProtocol, NameUdpW );
         break;
 
+    default:
+        FIXME("unknown Protocol <0x%08x>\n", protocol);
+        return FALSE;
+    }
+    return TRUE;
+}
+/*****************************************************************************
+ *          WS_AF_INET6_EnterSingleProtocolW [internal]
+ *
+ *    enters the protocol information of one given protocol into the given
+ *    buffer.
+ *
+ *    HANDLES AF_INET6
+ *
+ * RETURNS
+ *    TRUE if a protocol was entered into the buffer.
+ *
+ */
+static BOOL WS_AF_INET6_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info )
+{
+    info->iAddressFamily = WS_AF_INET6;
+
+    switch (protocol)
+    {
+    case WS_IPPROTO_TCP:
+        info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_EXPEDITED_DATA |
+                                XP1_GRACEFUL_CLOSE | XP1_GUARANTEED_ORDER |
+                                XP1_GUARANTEED_DELIVERY;
+        info->ProviderId = ProviderIdIP;
+        info->dwCatalogEntryId = 0x3ec;
+        info->dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO;
+        info->ProtocolChain.ChainLen = 1;
+        info->iVersion = 2;
+        info->iMaxSockAddr = 0x1c;
+        info->iMinSockAddr = 0x1c;
+        info->iSocketType = WS_SOCK_STREAM;
+        strcpyW( info->szProtocol, NameTcpW );
+        break;
+
+    case WS_IPPROTO_UDP:
+        info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_SUPPORT_BROADCAST |
+                                XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED |
+                                XP1_CONNECTIONLESS;
+        info->ProviderId = ProviderIdIP;
+        info->dwCatalogEntryId = 0x3ea;
+        info->dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO;
+        info->ProtocolChain.ChainLen = 1;
+        info->iVersion = 2;
+        info->iMaxSockAddr = 0x1c;
+        info->iMinSockAddr = 0x1c;
+        info->iSocketType = WS_SOCK_DGRAM;
+        info->dwMessageSize = 0xffbb;
+        strcpyW( info->szProtocol, NameUdpW );
+        break;
+
+    default:
+        FIXME("unknown Protocol <0x%08x>\n", protocol);
+        return FALSE;
+    }
+    return TRUE;
+}
+/*****************************************************************************
+ *          WS_AF_IPX_EnterSingleProtocolW [internal]
+ *
+ *    enters the protocol information of one given protocol into the given
+ *    buffer.
+ *
+ *    HANDLES AF_IPX
+ *
+ * RETURNS
+ *    TRUE if a protocol was entered into the buffer.
+ *
+ */
+static BOOL WS_AF_IPX_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info )
+{
+    info->iAddressFamily = WS_AF_IPX;
+
+    switch (protocol)
+    {
     case WS_NSPROTO_IPX:
         info->dwServiceFlags1 = XP1_PARTIAL_MESSAGE | XP1_SUPPORT_BROADCAST |
                                 XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED |
@@ -2220,7 +2294,6 @@ static BOOL WS_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info )
         info->dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO;
         info->ProtocolChain.ChainLen = 1;
         info->iVersion = 2;
-        info->iAddressFamily = WS_AF_IPX;
         info->iMaxSockAddr = 0x10;
         info->iMinSockAddr = 0x0e;
         info->iSocketType = WS_SOCK_DGRAM;
@@ -2238,7 +2311,6 @@ static BOOL WS_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info )
         info->dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO;
         info->ProtocolChain.ChainLen = 1;
         info->iVersion = 2;
-        info->iAddressFamily = WS_AF_IPX;
         info->iMaxSockAddr = 0x10;
         info->iMinSockAddr = 0x0e;
         info->iSocketType = WS_SOCK_SEQPACKET;
@@ -2255,7 +2327,6 @@ static BOOL WS_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info )
         info->dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO;
         info->ProtocolChain.ChainLen = 1;
         info->iVersion = 2;
-        info->iAddressFamily = WS_AF_IPX;
         info->iMaxSockAddr = 0x10;
         info->iMinSockAddr = 0x0e;
         info->iSocketType = WS_SOCK_SEQPACKET;
@@ -2269,85 +2340,94 @@ static BOOL WS_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info )
     }
     return TRUE;
 }
-
 /*****************************************************************************
- *          WS_EnterSingleProtocolA [internal]
+ *          WS_EnterSingleProtocolW [internal]
  *
- *    see function WS_EnterSingleProtocolW
+ *    enters the protocol information of one given protocol into the given
+ *    buffer.
  *
+ * RETURNS
+ *    count of returned WSAPROTOCOL_INFOW structs
+ *
+ * BUGS
+ *    - only implemented for IPX, SPX, SPXII, TCP, UDP
+ *    - there is no check that the operating system supports the returned
+ *      protocols
  */
-static BOOL WS_EnterSingleProtocolA( INT protocol, WSAPROTOCOL_INFOA* info )
+static INT WS_EnterSingleProtocolW( INT address_family, INT protocol, WSAPROTOCOL_INFOW info[], INT* info_size )
 {
-    WSAPROTOCOL_INFOW infow;
-    INT ret;
-    memset( info, 0, sizeof(WSAPROTOCOL_INFOA) );
+    if(address_family)
+    {
+        memset( info, 0, sizeof(WSAPROTOCOL_INFOW) );
+        info->iProtocol = protocol;
 
-    ret = WS_EnterSingleProtocolW( protocol, &infow );
-    if (ret)
+        switch (address_family)
+        {
+        case WS_AF_INET:
+            WS_AF_INET_EnterSingleProtocolW(protocol, info);
+            break;
+        case WS_AF_INET6:
+            WS_AF_INET6_EnterSingleProtocolW(protocol, info);
+            break;
+        case WS_AF_IPX:
+            WS_AF_IPX_EnterSingleProtocolW(protocol, info);
+            break;
+        default:
+            FIXME("unhandled addressfamily <0x%08x>\n", address_family);
+            return 0;
+        }
+        return 1;
+    }
+    else
     {
-        /* convert the structure from W to A */
-        memcpy( info, &infow, FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
-        WideCharToMultiByte( CP_ACP, 0, infow.szProtocol, -1,
-                             info->szProtocol, WSAPROTOCOL_LEN+1, NULL, NULL );
+        FIXME("Unspecified address_family not implemented yet\n");
+        return 0;
     }
-
-    return ret;
 }
 
-static INT WS_EnumProtocols( BOOL unicode, const INT *protocols, LPWSAPROTOCOL_INFOW buffer, LPDWORD len )
+/*****************************************************************************
+ *          WS_EnterSingleProtocolA [internal]
+ *
+ *    see function WS_EnterSingleProtocolW
+ *
+ */
+static INT WS_EnterSingleProtocolA( INT addressfamily, INT protocol, WSAPROTOCOL_INFOA* info , INT* info_size)
 {
-    INT i = 0, items = 0;
-    DWORD size = 0;
-    union _info
-    {
-      LPWSAPROTOCOL_INFOA a;
-      LPWSAPROTOCOL_INFOW w;
-    } info;
-    info.w = buffer;
+    WSAPROTOCOL_INFOW* infow;
+    INT ret, i;
 
-    if (!protocols) protocols = valid_protocols;
+    infow = HeapAlloc(GetProcessHeap(), 0, sizeof(WSAPROTOCOL_INFOW) * *info_size);
 
-    while (protocols[i])
+    ret = WS_EnterSingleProtocolW( addressfamily, protocol, infow, info_size );
+    if (ret)
     {
-        if(supported_protocol(protocols[i++]))
-            items++;
+        for(i = 0; i < ret; i++)
+        {
+            /* convert the structure from W to A */
+            memcpy( &info[i], &infow[i], FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
+            WideCharToMultiByte( CP_ACP, 0, infow[i].szProtocol, -1,
+                                info[i].szProtocol, WSAPROTOCOL_LEN+1, NULL, NULL );
+        }
     }
 
-    size = items * (unicode ? sizeof(WSAPROTOCOL_INFOW) : sizeof(WSAPROTOCOL_INFOA));
-
-    TRACE("unicode %d, protocols %p, buffer %p, length %p %d, items %d, required %d\n",
-          unicode, protocols, buffer, len, len ? *len : 0, items, size);
+    HeapFree(GetProcessHeap(), 0, infow);
 
-    if (*len < size || !buffer)
-    {
-        *len = size;
-        SetLastError(WSAENOBUFS);
-        return SOCKET_ERROR;
-    }
+    return ret;
+}
 
-    for (i = items = 0; protocols[i]; i++)
-    {
-        if (!supported_protocol(protocols[i])) continue;
-        if (unicode)
-        {
-            if (WS_EnterSingleProtocolW( protocols[i], &info.w[items] ))
-                items++;
-        }
-        else
-        {
-            if (WS_EnterSingleProtocolA( protocols[i], &info.a[items] ))
-                items++;
-        }
-    }
-    return items;
+static INT WS_EnumProtocols( BOOL unicode, const INT *protocols, LPWSAPROTOCOL_INFOW buffer, LPDWORD len )
+{
+    FIXME("Not implemented\n");
+    WSASetLastError(WSAEOPNOTSUPP);
+    return SOCKET_ERROR;
 }
 
 static BOOL ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, int *size)
 {
     NTSTATUS status;
     int address_family;
-    int socket_type;
     int protocol;
+    int buffer_size = 1;
 
     *size = unicode ? sizeof(WSAPROTOCOL_INFOW) : sizeof(WSAPROTOCOL_INFOA);
     memset(buffer, 0, *size);
@@ -2359,7 +2439,6 @@ static BOOL ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, i
         if (!status)
         {
             address_family = convert_af_u2w(reply->family);
-            socket_type = convert_socktype_u2w(reply->type);
             protocol = convert_proto_u2w(reply->protocol);
         }
     }
@@ -2373,12 +2452,9 @@ static BOOL ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, i
     }
 
     if (unicode)
-        WS_EnterSingleProtocolW( protocol, buffer);
+        WS_EnterSingleProtocolW( address_family, protocol, buffer, &buffer_size);
     else
-        WS_EnterSingleProtocolA( protocol, (WSAPROTOCOL_INFOA *)buffer);
-    buffer->iAddressFamily = address_family;
-    buffer->iSocketType = socket_type;
-    buffer->iProtocol = protocol;
+        WS_EnterSingleProtocolA( address_family, protocol, (WSAPROTOCOL_INFOA *)buffer, &buffer_size);
 
     return TRUE;
 }
@@ -7578,6 +7654,7 @@ SOCKET WINAPI WSASocketW(int af, int type, int protocol,
     {
         int autoproto = protocol;
         WSAPROTOCOL_INFOW infow;
+        int infow_size = 1;
 
         /* default to the first valid protocol */
         if (!autoproto)
@@ -7585,7 +7662,7 @@ SOCKET WINAPI WSASocketW(int af, int type, int protocol,
         else if(IS_IPX_PROTO(autoproto))
             autoproto = WS_NSPROTO_IPX;
 
-        if (WS_EnterSingleProtocolW(autoproto, &infow))
+        if (WS_EnterSingleProtocolW(af, autoproto, &infow, &infow_size))
         {
             type = infow.iSocketType;
 
-- 
2.20.1




More information about the wine-devel mailing list