[PATCH v2 1/4] ws2_32: Reimplement WSAEnumProtocols() using a flat array of WSA_PROTOCOLINFO structures.

Zebediah Figura z.figura12 at gmail.com
Mon Sep 28 22:35:02 CDT 2020


Looking up protocol information by protocol number is not reliable, as protocol
numbers for different families may overlap.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/ws2_32/socket.c | 210 ++++++++++++++++++++++++++++++-------------
 1 file changed, 149 insertions(+), 61 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index a52b708f8ec..733e412db0b 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -200,6 +200,90 @@ static const GUID ProviderIdIPX = { 0x11058240, 0xbe47, 0x11cf,
 static const GUID ProviderIdSPX = { 0x11058241, 0xbe47, 0x11cf,
                                     { 0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92 } };
 
+static const WSAPROTOCOL_INFOW supported_protocols[] =
+{
+    {
+        .dwServiceFlags1 = XP1_IFS_HANDLES | XP1_EXPEDITED_DATA | XP1_GRACEFUL_CLOSE
+                | XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY,
+        .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
+        .ProviderId = {0xe70f1aa0, 0xab8b, 0x11cf, {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
+        .dwCatalogEntryId = 1001,
+        .ProtocolChain.ChainLen = 1,
+        .iVersion = 2,
+        .iAddressFamily = WS_AF_INET,
+        .iMaxSockAddr = sizeof(struct WS_sockaddr_in),
+        .iMinSockAddr = sizeof(struct WS_sockaddr_in),
+        .iSocketType = WS_SOCK_STREAM,
+        .iProtocol = WS_IPPROTO_TCP,
+        .szProtocol = {'T','C','P','/','I','P',0},
+    },
+    {
+        .dwServiceFlags1 = XP1_IFS_HANDLES | XP1_SUPPORT_BROADCAST
+                | XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED | XP1_CONNECTIONLESS,
+        .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
+        .ProviderId = {0xe70f1aa0, 0xab8b, 0x11cf, {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
+        .dwCatalogEntryId = 1002,
+        .ProtocolChain.ChainLen = 1,
+        .iVersion = 2,
+        .iAddressFamily = WS_AF_INET,
+        .iMaxSockAddr = sizeof(struct WS_sockaddr_in),
+        .iMinSockAddr = sizeof(struct WS_sockaddr_in),
+        .iSocketType = WS_SOCK_DGRAM,
+        .iProtocol = WS_IPPROTO_UDP,
+        .dwMessageSize = 0xffbb,
+        .szProtocol = {'U','D','P','/','I','P',0},
+    },
+    {
+        .dwServiceFlags1 = XP1_PARTIAL_MESSAGE | XP1_SUPPORT_BROADCAST
+                | XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED | XP1_CONNECTIONLESS,
+        .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
+        .ProviderId = {0x11058240, 0xbe47, 0x11cf, {0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
+        .dwCatalogEntryId = 1030,
+        .ProtocolChain.ChainLen = 1,
+        .iVersion = 2,
+        .iAddressFamily = WS_AF_IPX,
+        .iMaxSockAddr = sizeof(struct WS_sockaddr),
+        .iMinSockAddr = sizeof(struct WS_sockaddr_ipx),
+        .iSocketType = WS_SOCK_DGRAM,
+        .iProtocol = WS_NSPROTO_IPX,
+        .iProtocolMaxOffset = 255,
+        .dwMessageSize = 0x240,
+        .szProtocol = {'I','P','X',0},
+    },
+    {
+        .dwServiceFlags1 = XP1_IFS_HANDLES | XP1_PSEUDO_STREAM | XP1_MESSAGE_ORIENTED
+                | XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY,
+        .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
+        .ProviderId = {0x11058241, 0xbe47, 0x11cf, {0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
+        .dwCatalogEntryId = 1031,
+        .ProtocolChain.ChainLen = 1,
+        .iVersion = 2,
+        .iAddressFamily = WS_AF_IPX,
+        .iMaxSockAddr = sizeof(struct WS_sockaddr),
+        .iMinSockAddr = sizeof(struct WS_sockaddr_ipx),
+        .iSocketType = WS_SOCK_SEQPACKET,
+        .iProtocol = WS_NSPROTO_SPX,
+        .dwMessageSize = UINT_MAX,
+        .szProtocol = {'S','P','X',0},
+    },
+    {
+        .dwServiceFlags1 = XP1_IFS_HANDLES | XP1_GRACEFUL_CLOSE | XP1_PSEUDO_STREAM
+                | XP1_MESSAGE_ORIENTED | XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY,
+        .dwProviderFlags = PFL_MATCHES_PROTOCOL_ZERO,
+        .ProviderId = {0x11058241, 0xbe47, 0x11cf, {0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
+        .dwCatalogEntryId = 1033,
+        .ProtocolChain.ChainLen = 1,
+        .iVersion = 2,
+        .iAddressFamily = WS_AF_IPX,
+        .iMaxSockAddr = sizeof(struct WS_sockaddr),
+        .iMinSockAddr = sizeof(struct WS_sockaddr_ipx),
+        .iSocketType = WS_SOCK_SEQPACKET,
+        .iProtocol = WS_NSPROTO_SPXII,
+        .dwMessageSize = UINT_MAX,
+        .szProtocol = {'S','P','X',' ','I','I',0},
+    },
+};
+
 static const INT valid_protocols[] =
 {
     WS_IPPROTO_TCP,
@@ -1869,15 +1953,6 @@ static inline BOOL supported_pf(int pf)
     }
 }
 
-static inline BOOL supported_protocol(int protocol)
-{
-    int i;
-    for (i = 0; i < ARRAY_SIZE(valid_protocols); i++)
-        if (protocol == valid_protocols[i])
-            return TRUE;
-    return FALSE;
-}
-
 /**********************************************************************/
 
 /* Returns the length of the converted address if successful, 0 if it was too
@@ -2345,54 +2420,6 @@ static BOOL WS_EnterSingleProtocolA( INT protocol, WSAPROTOCOL_INFOA* info )
     return ret;
 }
 
-static INT WS_EnumProtocols( BOOL unicode, const INT *protocols, LPWSAPROTOCOL_INFOW buffer, LPDWORD len )
-{
-    INT i = 0, items = 0;
-    DWORD size = 0;
-    union _info
-    {
-      LPWSAPROTOCOL_INFOA a;
-      LPWSAPROTOCOL_INFOW w;
-    } info;
-    info.w = buffer;
-
-    if (!protocols) protocols = valid_protocols;
-
-    while (protocols[i])
-    {
-        if(supported_protocol(protocols[i++]))
-            items++;
-    }
-
-    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);
-
-    if (*len < size || !buffer)
-    {
-        *len = size;
-        SetLastError(WSAENOBUFS);
-        return SOCKET_ERROR;
-    }
-
-    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 BOOL ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, int *size)
 {
     NTSTATUS status;
@@ -9104,14 +9131,52 @@ INT WINAPI WSANSPIoctl( HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer,
     return SOCKET_ERROR;
 }
 
+static BOOL protocol_matches_filter( const int *filter, int protocol )
+{
+    if (!filter) return TRUE;
+    while (*filter)
+    {
+        if (protocol == *filter++) return TRUE;
+    }
+    return FALSE;
+}
+
 /*****************************************************************************
  *          WSAEnumProtocolsA       [WS2_32.@]
  *
  *    see function WSAEnumProtocolsW
  */
-INT WINAPI WSAEnumProtocolsA( LPINT protocols, LPWSAPROTOCOL_INFOA buffer, LPDWORD len )
+int WINAPI WSAEnumProtocolsA( int *filter, WSAPROTOCOL_INFOA *protocols, DWORD *size )
 {
-    return WS_EnumProtocols( FALSE, protocols, (LPWSAPROTOCOL_INFOW) buffer, len);
+    DWORD i, count = 0;
+
+    TRACE("filter %p, protocols %p, size %p\n", filter, protocols, size);
+
+    for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
+    {
+        if (protocol_matches_filter( filter, supported_protocols[i].iProtocol ))
+            ++count;
+    }
+
+    if (!protocols || *size < count * sizeof(WSAPROTOCOL_INFOA))
+    {
+        *size = count * sizeof(WSAPROTOCOL_INFOA);
+        WSASetLastError( WSAENOBUFS );
+        return SOCKET_ERROR;
+    }
+
+    count = 0;
+    for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
+    {
+        if (protocol_matches_filter( filter, supported_protocols[i].iProtocol ))
+        {
+            memcpy( &protocols[count], &supported_protocols[i], offsetof( WSAPROTOCOL_INFOW, szProtocol ) );
+            WideCharToMultiByte( CP_ACP, 0, supported_protocols[i].szProtocol, -1,
+                                 protocols[count].szProtocol, sizeof(protocols[count].szProtocol), NULL, NULL );
+            ++count;
+        }
+    }
+    return count;
 }
 
 /*****************************************************************************
@@ -9151,9 +9216,32 @@ INT WINAPI WSAEnumProtocolsA( LPINT protocols, LPWSAPROTOCOL_INFOA buffer, LPDWO
  *  - there is no check that the operating system supports the returned
  *    protocols
  */
-INT WINAPI WSAEnumProtocolsW( LPINT protocols, LPWSAPROTOCOL_INFOW buffer, LPDWORD len )
+int WINAPI WSAEnumProtocolsW( int *filter, WSAPROTOCOL_INFOW *protocols, DWORD *size )
 {
-    return WS_EnumProtocols( TRUE, protocols, buffer, len);
+    DWORD i, count = 0;
+
+    TRACE("filter %p, protocols %p, size %p\n", filter, protocols, size);
+
+    for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
+    {
+        if (protocol_matches_filter( filter, supported_protocols[i].iProtocol ))
+            ++count;
+    }
+
+    if (!protocols || *size < count * sizeof(WSAPROTOCOL_INFOW))
+    {
+        *size = count * sizeof(WSAPROTOCOL_INFOW);
+        WSASetLastError( WSAENOBUFS );
+        return SOCKET_ERROR;
+    }
+
+    count = 0;
+    for (i = 0; i < ARRAY_SIZE(supported_protocols); ++i)
+    {
+        if (protocol_matches_filter( filter, supported_protocols[i].iProtocol ))
+            protocols[count++] = supported_protocols[i];
+    }
+    return count;
 }
 
 /*****************************************************************************
-- 
2.28.0




More information about the wine-devel mailing list