| /* | |
| * Protocol enumeration functions | |
| * | |
| * Copyright (C) 2001 Stefan Leichter | |
| * Copyright (C) 2004 Hans Leidekker | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| */ | |
| /* 02/11/2004 | |
| * The protocol enumeration functions were verified to match Win2k versions | |
| * for these protocols: IPX, SPX, SPXII, TCP/IP and UDP/IP. | |
| */ | |
| #include "config.h" | |
| #include <stdarg.h> | |
| #include <stdio.h> | |
| #include <string.h> | |
| #include <sys/types.h> | |
| #ifdef HAVE_ARPA_INET_H | |
| #include <arpa/inet.h> | |
| #endif | |
| #ifdef HAVE_NETDB_H | |
| #include <netdb.h> | |
| #endif | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include "winnls.h" | |
| #include "wtypes.h" | |
| #include "nspapi.h" | |
| #include "winsock2.h" | |
| #include "wsipx.h" | |
| #include "wshisotp.h" | |
| #include "wine/unicode.h" | |
| #include "wine/debug.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(winsock); | |
| /* names of the protocols */ | |
| static const CHAR NameIpx[] = "IPX"; | |
| static const CHAR NameSpx[] = "SPX"; | |
| static const CHAR NameSpxII[] = "SPX II"; | |
| static const CHAR NameTcp[] = "TCP/IP"; | |
| static const CHAR NameUdp[] = "UDP/IP"; | |
| static const WCHAR NameIpxW[] = {'I', 'P', 'X', '\0'}; | |
| static const WCHAR NameSpxW[] = {'S', 'P', 'X', '\0'}; | |
| static const WCHAR NameSpxIIW[] = {'S', 'P', 'X', ' ', 'I', 'I', '\0'}; | |
| static const WCHAR NameTcpW[] = {'T', 'C', 'P', '/', 'I', 'P', '\0'}; | |
| static const WCHAR NameUdpW[] = {'U', 'D', 'P', '/', 'I', 'P', '\0'}; | |
| /* Taken from Win2k */ | |
| static const GUID ProviderIdIP = { 0xe70f1aa0, 0xab8b, 0x11cf, | |
| { 0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92 } }; | |
| static const GUID ProviderIdIPX = { 0x11058240, 0xbe47, 0x11cf, | |
| { 0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92 } }; | |
| static const GUID ProviderIdSPX = { 0x11058241, 0xbe47, 0x11cf, | |
| { 0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92 } }; | |
| /***************************************************************************** | |
| * WINSOCK_EnterSingleProtocolW [internal] | |
| * | |
| * enters the protocol information of one given protocol into the given | |
| * buffer. | |
| * | |
| * RETURNS | |
| * 1 if a protocol was entered into the buffer. | |
| * SOCKET_ERROR otherwise. | |
| * | |
| * BUGS | |
| * - only implemented for IPX, SPX, SPXII, TCP, UDP | |
| * - there is no check that the operating system supports the returned | |
| * protocols | |
| */ | |
| static INT WINSOCK_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info ) | |
| { | |
| memset( info, 0, sizeof(WSAPROTOCOL_INFOW) ); | |
| info->iProtocol = protocol; | |
| switch (protocol) | |
| { | |
| case WS_IPPROTO_TCP: | |
| info->dwServiceFlags1 = XP1_PARTIAL_MESSAGE | XP1_EXPEDITED_DATA | | |
| XP1_GRACEFUL_CLOSE | XP1_GUARANTEED_ORDER | | |
| XP1_GUARANTEED_DELIVERY; | |
| memcpy( &info->ProviderId, &ProviderIdIP, sizeof(GUID) ); | |
| info->dwCatalogEntryId = 0x3e9; | |
| info->ProtocolChain.ChainLen = 1; | |
| info->iVersion = 2; | |
| info->iAddressFamily = WS_AF_INET; | |
| info->iMaxSockAddr = 0x10; | |
| info->iMinSockAddr = 0x10; | |
| info->iSocketType = WS_SOCK_STREAM; | |
| strcpyW( info->szProtocol, NameTcpW ); | |
| break; | |
| case WS_IPPROTO_UDP: | |
| info->dwServiceFlags1 = XP1_PARTIAL_MESSAGE | XP1_SUPPORT_BROADCAST | | |
| XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED | | |
| XP1_CONNECTIONLESS; | |
| memcpy( &info->ProviderId, &ProviderIdIP, sizeof(GUID) ); | |
| info->dwCatalogEntryId = 0x3ea; | |
| info->ProtocolChain.ChainLen = 1; | |
| info->iVersion = 2; | |
| info->iAddressFamily = WS_AF_INET; | |
| info->iMaxSockAddr = 0x10; | |
| info->iMinSockAddr = 0x10; | |
| info->iSocketType = WS_SOCK_DGRAM; | |
| info->dwMessageSize = 0xffbb; | |
| strcpyW( info->szProtocol, NameUdpW ); | |
| break; | |
| case NSPROTO_IPX: | |
| info->dwServiceFlags1 = XP1_PARTIAL_MESSAGE | XP1_SUPPORT_BROADCAST | | |
| XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED | | |
| XP1_CONNECTIONLESS; | |
| memcpy( &info->ProviderId, &ProviderIdIPX, sizeof(GUID) ); | |
| info->dwCatalogEntryId = 0x406; | |
| info->ProtocolChain.ChainLen = 1; | |
| info->iVersion = 2; | |
| info->iAddressFamily = WS_AF_IPX; | |
| info->iMaxSockAddr = 0x10; | |
| info->iMinSockAddr = 0x0e; | |
| info->iSocketType = WS_SOCK_DGRAM; | |
| info->iProtocolMaxOffset = 0xff; | |
| info->dwMessageSize = 0x240; | |
| strcpyW( info->szProtocol, NameIpxW ); | |
| break; | |
| case NSPROTO_SPX: | |
| info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_PSEUDO_STREAM | | |
| XP1_MESSAGE_ORIENTED | XP1_GUARANTEED_ORDER | | |
| XP1_GUARANTEED_DELIVERY; | |
| memcpy( &info->ProviderId, &ProviderIdSPX, sizeof(GUID) ); | |
| info->dwCatalogEntryId = 0x407; | |
| info->ProtocolChain.ChainLen = 1; | |
| info->iVersion = 2; | |
| info->iAddressFamily = WS_AF_IPX; | |
| info->iMaxSockAddr = 0x10; | |
| info->iMinSockAddr = 0x0e; | |
| info->iSocketType = 5; | |
| info->dwMessageSize = 0xffffffff; | |
| strcpyW( info->szProtocol, NameSpxW ); | |
| break; | |
| case NSPROTO_SPXII: | |
| info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_GRACEFUL_CLOSE | | |
| XP1_PSEUDO_STREAM | XP1_MESSAGE_ORIENTED | | |
| XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY; | |
| memcpy( &info->ProviderId, &ProviderIdSPX, sizeof(GUID) ); | |
| info->dwCatalogEntryId = 0x409; | |
| info->ProtocolChain.ChainLen = 1; | |
| info->iVersion = 2; | |
| info->iAddressFamily = WS_AF_IPX; | |
| info->iMaxSockAddr = 0x10; | |
| info->iMinSockAddr = 0x0e; | |
| info->iSocketType = 5; | |
| info->dwMessageSize = 0xffffffff; | |
| strcpyW( info->szProtocol, NameSpxIIW ); | |
| break; | |
| default: | |
| if ((protocol == ISOPROTO_TP4) || (protocol == NSPROTO_SPX)) | |
| FIXME("Protocol <%s> not implemented\n", | |
| (protocol == ISOPROTO_TP4) ? "ISOPROTO_TP4" : "NSPROTO_SPX"); | |
| else | |
| FIXME("unknown Protocol <0x%08x>\n", protocol); | |
| return SOCKET_ERROR; | |
| } | |
| return 1; | |
| } | |
| /***************************************************************************** | |
| * WINSOCK_EnterSingleProtocolA [internal] | |
| * | |
| * see function WINSOCK_EnterSingleProtocolW | |
| * | |
| */ | |
| static INT WINSOCK_EnterSingleProtocolA( INT protocol, WSAPROTOCOL_INFOA* info ) | |
| { | |
| memset( info, 0, sizeof(WSAPROTOCOL_INFOA) ); | |
| info->iProtocol = protocol; | |
| switch (protocol) | |
| { | |
| case WS_IPPROTO_TCP: | |
| info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_EXPEDITED_DATA | | |
| XP1_GRACEFUL_CLOSE | XP1_GUARANTEED_ORDER | | |
| XP1_GUARANTEED_DELIVERY; | |
| memcpy( &info->ProviderId, &ProviderIdIP, sizeof(GUID) ); | |
| info->dwCatalogEntryId = 0x3e9; | |
| info->ProtocolChain.ChainLen = 1; | |
| info->iVersion = 2; | |
| info->iAddressFamily = WS_AF_INET; | |
| info->iMaxSockAddr = 0x10; | |
| info->iMinSockAddr = 0x10; | |
| info->iSocketType = WS_SOCK_STREAM; | |
| strcpy( info->szProtocol, NameTcp ); | |
| break; | |
| case WS_IPPROTO_UDP: | |
| info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_SUPPORT_BROADCAST | | |
| XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED | | |
| XP1_CONNECTIONLESS; | |
| memcpy( &info->ProviderId, &ProviderIdIP, sizeof(GUID) ); | |
| info->dwCatalogEntryId = 0x3ea; | |
| info->ProtocolChain.ChainLen = 1; | |
| info->iVersion = 2; | |
| info->iAddressFamily = WS_AF_INET; | |
| info->iMaxSockAddr = 0x10; | |
| info->iMinSockAddr = 0x10; | |
| info->iSocketType = WS_SOCK_DGRAM; | |
| info->dwMessageSize = 0xffbb; | |
| strcpy( info->szProtocol, NameUdp ); | |
| break; | |
| case NSPROTO_IPX: | |
| info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_SUPPORT_BROADCAST | | |
| XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED | | |
| XP1_CONNECTIONLESS; | |
| memcpy( &info->ProviderId, &ProviderIdIPX, sizeof(GUID) ); | |
| info->dwCatalogEntryId = 0x406; | |
| info->ProtocolChain.ChainLen = 1; | |
| info->iVersion = 2; | |
| info->iAddressFamily = WS_AF_IPX; | |
| info->iMaxSockAddr = 0x10; | |
| info->iMinSockAddr = 0x0e; | |
| info->iSocketType = WS_SOCK_DGRAM; | |
| info->iProtocolMaxOffset = 0xff; | |
| info->dwMessageSize = 0x240; | |
| strcpy( info->szProtocol, NameIpx ); | |
| break; | |
| case NSPROTO_SPX: | |
| info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_PSEUDO_STREAM | | |
| XP1_MESSAGE_ORIENTED | XP1_GUARANTEED_ORDER | | |
| XP1_GUARANTEED_DELIVERY; | |
| memcpy( &info->ProviderId, &ProviderIdSPX, sizeof(GUID) ); | |
| info->dwCatalogEntryId = 0x407; | |
| info->ProtocolChain.ChainLen = 1; | |
| info->iVersion = 2; | |
| info->iAddressFamily = WS_AF_IPX; | |
| info->iMaxSockAddr = 0x10; | |
| info->iMinSockAddr = 0x0e; | |
| info->iSocketType = 5; | |
| info->dwMessageSize = 0xffffffff; | |
| strcpy( info->szProtocol, NameSpx ); | |
| break; | |
| case NSPROTO_SPXII: | |
| info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_GRACEFUL_CLOSE | | |
| XP1_PSEUDO_STREAM | XP1_MESSAGE_ORIENTED | | |
| XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY; | |
| memcpy( &info->ProviderId, &ProviderIdSPX, sizeof(GUID) ); | |
| info->dwCatalogEntryId = 0x409; | |
| info->ProtocolChain.ChainLen = 1; | |
| info->iVersion = 2; | |
| info->iAddressFamily = WS_AF_IPX; | |
| info->iMaxSockAddr = 0x10; | |
| info->iMinSockAddr = 0x0e; | |
| info->iSocketType = 5; | |
| info->dwMessageSize = 0xffffffff; | |
| strcpy( info->szProtocol, NameSpxII ); | |
| break; | |
| default: | |
| if ((protocol == ISOPROTO_TP4) || (protocol == NSPROTO_SPX)) | |
| FIXME("Protocol <%s> not implemented\n", | |
| (protocol == ISOPROTO_TP4) ? "ISOPROTO_TP4" : "NSPROTO_SPX"); | |
| else | |
| FIXME("unknown Protocol <0x%08x>\n", protocol); | |
| return SOCKET_ERROR; | |
| } | |
| return 1; | |
| } | |
| /***************************************************************************** | |
| * WSAEnumProtocolsA [WS2_32.@] | |
| * | |
| * see function WSAEnumProtocolsW | |
| */ | |
| INT WINAPI WSAEnumProtocolsA( LPINT protocols, LPWSAPROTOCOL_INFOA buffer, LPDWORD len ) | |
| { | |
| INT i = 0; | |
| DWORD size = 0; | |
| INT local[] = { WS_IPPROTO_TCP, WS_IPPROTO_UDP, NSPROTO_IPX, NSPROTO_SPX, NSPROTO_SPXII, 0 }; | |
| if (!buffer) | |
| return SOCKET_ERROR; | |
| if (!protocols) protocols = local; | |
| while (protocols[i]) i++; | |
| size = i * sizeof(WSAPROTOCOL_INFOA); | |
| if (*len < size) | |
| { | |
| *len = size; | |
| return SOCKET_ERROR; | |
| } | |
| for (i = 0; protocols[i]; i++) | |
| { | |
| if (WINSOCK_EnterSingleProtocolA( protocols[i], &buffer[i] ) == SOCKET_ERROR) | |
| return i; | |
| } | |
| return i; | |
| } | |
| /***************************************************************************** | |
| * WSAEnumProtocolsW [WS2_32.@] | |
| * | |
| * Retrieves information about specified set of active network protocols. | |
| * | |
| * PARAMS | |
| * protocols [I] Pointer to null-terminated array of protocol id's. NULL | |
| * retrieves information on all available protocols. | |
| * buffer [I] Pointer to a buffer to be filled with WSAPROTOCOL_INFO | |
| * structures. | |
| * len [I/O] Pointer to a variable specifying buffer size. On output | |
| * the variable holds the number of bytes needed when the | |
| * specified size is too small. | |
| * | |
| * RETURNS | |
| * Success: number of WSAPROTOCOL_INFO structures in buffer. | |
| * Failure: SOCKET_ERROR | |
| * | |
| * NOTES | |
| * NT4SP5 does not return SPX if protocols == NULL | |
| * | |
| * BUGS | |
| * - NT4SP5 returns in addition these list of NETBIOS protocols | |
| * (address family 17), each entry two times one for socket type 2 and 5 | |
| * | |
| * iProtocol szProtocol | |
| * 0x80000000 \Device\NwlnkNb | |
| * 0xfffffffa \Device\NetBT_CBENT7 | |
| * 0xfffffffb \Device\Nbf_CBENT7 | |
| * 0xfffffffc \Device\NetBT_NdisWan5 | |
| * 0xfffffffd \Device\NetBT_El9202 | |
| * 0xfffffffe \Device\Nbf_El9202 | |
| * 0xffffffff \Device\Nbf_NdisWan4 | |
| * | |
| * - there is no check that the operating system supports the returned | |
| * protocols | |
| */ | |
| INT WINAPI WSAEnumProtocolsW( LPINT protocols, LPWSAPROTOCOL_INFOW buffer, LPDWORD len ) | |
| { | |
| INT i = 0; | |
| DWORD size = 0; | |
| INT local[] = { WS_IPPROTO_TCP, WS_IPPROTO_UDP, NSPROTO_IPX, NSPROTO_SPX, NSPROTO_SPXII, 0 }; | |
| if (!buffer) | |
| return SOCKET_ERROR; | |
| if (!protocols) protocols = local; | |
| while (protocols[i]) i++; | |
| size = i * sizeof(WSAPROTOCOL_INFOW); | |
| if (*len < size) | |
| { | |
| *len = size; | |
| return SOCKET_ERROR; | |
| } | |
| for (i = 0; protocols[i]; i++) | |
| { | |
| if (WINSOCK_EnterSingleProtocolW( protocols[i], &buffer[i] ) == SOCKET_ERROR) | |
| return i; | |
| } | |
| return i; | |
| } | |
| /***************************************************************************** | |
| * WSCEnumProtocols [WS2_32.@] | |
| * | |
| * PARAMS | |
| * protocols [I] Null-terminated array of iProtocol values. | |
| * buffer [O] Buffer of WSAPROTOCOL_INFOW structures. | |
| * len [I/O] Size of buffer on input/output. | |
| * errno [O] Error code. | |
| * | |
| * RETURNS | |
| * Success: number of protocols to be reported on. | |
| * Failure: SOCKET_ERROR. error is in errno. | |
| * | |
| * BUGS | |
| * Doesn't supply info on layered protocols. | |
| * | |
| */ | |
| INT WINAPI WSCEnumProtocols( LPINT protocols, LPWSAPROTOCOL_INFOW buffer, LPDWORD len, LPINT errno ) | |
| { | |
| INT ret = WSAEnumProtocolsW( protocols, buffer, len ); | |
| if (ret == SOCKET_ERROR) *errno = WSAENOBUFS; | |
| return ret; | |
| } |