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@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;