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@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; }
/*****************************************************************************