WS_EnumProtocols broke with changes to WS_EnterSingleProtocol{W|A} so it needs to be reimplemented.
Signed-off-by: Robin Ebert ebertrobin2002@gmail.com --- v2: Fix wrong iProtocol values in WS_EnumProtocols --- dlls/ws2_32/socket.c | 97 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 91 insertions(+), 6 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index c67527d0..9387801c 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2172,6 +2172,7 @@ static INT WS_DuplicateSocket(BOOL unicode, SOCKET s, DWORD dwProcessId, LPWSAPR static BOOL WS_AF_INET_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info ) { info->iAddressFamily = WS_AF_INET; + info->iProtocol = protocol;
switch (protocol) { @@ -2227,6 +2228,7 @@ static BOOL WS_AF_INET_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* in static BOOL WS_AF_INET6_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info ) { info->iAddressFamily = WS_AF_INET6; + info->iProtocol = protocol;
switch (protocol) { @@ -2282,6 +2284,7 @@ static BOOL WS_AF_INET6_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* i static BOOL WS_AF_IPX_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info ) { info->iAddressFamily = WS_AF_IPX; + info->iProtocol = protocol;
switch (protocol) { @@ -2348,6 +2351,7 @@ static BOOL WS_AF_IPX_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* inf * * RETURNS * count of returned WSAPROTOCOL_INFOW structs + * *len contains the amount of needed WSAPROTOCOL_INFOW entries available if the buffer was too small * * BUGS * - only implemented for IPX, SPX, SPXII, TCP, UDP @@ -2358,8 +2362,8 @@ static INT WS_EnterSingleProtocolW( INT address_family, INT protocol, WSAPROTOCO { if(address_family) { + /* the buffer needs to be valid here. This should be checked by the caller */ memset( info, 0, sizeof(WSAPROTOCOL_INFOW) ); - info->iProtocol = protocol;
switch (address_family) { @@ -2380,8 +2384,39 @@ static INT WS_EnterSingleProtocolW( INT address_family, INT protocol, WSAPROTOCO } else { - FIXME("Unspecified address_family not implemented yet\n"); - return 0; + /* the buffer can be too small so we need our own as well */ + INT ret = 0, min_buffer = 0; + WSAPROTOCOL_INFOW infow; + WSAPROTOCOL_INFOW* buffer; + + buffer = *info_size - ret ? &info[ret] : &infow; + if(WS_AF_INET_EnterSingleProtocolW(protocol, buffer)) + { + min_buffer++; + if(buffer != &infow) + ret++; + + buffer = *info_size - ret ? &info[ret] : &infow; + } + if(WS_AF_INET6_EnterSingleProtocolW(protocol, buffer)) + { + min_buffer++; + if(buffer != &infow) + ret++; + + buffer = *info_size - ret ? &info[ret] : &infow; + } + if(WS_AF_IPX_EnterSingleProtocolW(protocol, buffer)) + { + min_buffer++; + if(buffer != &infow) + ret++; + } + + if(min_buffer > *info_size) + *info_size = min_buffer; + + return ret; } }
@@ -2417,9 +2452,59 @@ static INT WS_EnterSingleProtocolA( INT addressfamily, INT protocol, WSAPROTOCOL
static INT WS_EnumProtocols( BOOL unicode, const INT *protocols, LPWSAPROTOCOL_INFOW buffer, LPDWORD len ) { - FIXME("Not implemented\n"); - WSASetLastError(WSAEOPNOTSUPP); - return SOCKET_ERROR; + INT i = 0, items = 0, space, temp, space_temp, min_buffer_size; + DWORD size = 0; + union _info + { + LPWSAPROTOCOL_INFOA a; + LPWSAPROTOCOL_INFOW w; + } info; + info.w = buffer; + + if (!protocols) protocols = valid_protocols; + + size = unicode ? sizeof(WSAPROTOCOL_INFOW) : sizeof(WSAPROTOCOL_INFOA); + + TRACE("unicode %d, protocols %p, buffer %p, length %p %d\n", + unicode, protocols, buffer, len, len ? *len : 0); + + if (*len < size || !buffer) + { + /* len should return the count of needed space */ + *len = 0; + SetLastError(WSAENOBUFS); + } + + + min_buffer_size = 0; + space = *len / (unicode ? sizeof(WSAPROTOCOL_INFOW) : sizeof(WSAPROTOCOL_INFOA)); + for (i = items = 0; protocols[i]; i++) + { + if (!supported_protocol(protocols[i])) continue; + space_temp = space; /* WS_EnterSingleProtocol may alter this value */ + if (unicode) + { + temp = WS_EnterSingleProtocolW( WS_AF_UNSPEC, protocols[i], &info.w[items], &space_temp ); + } + else + { + temp = WS_EnterSingleProtocolA( WS_AF_UNSPEC, protocols[i], &info.a[items], &space_temp ); + } + min_buffer_size += space_temp != space ? space_temp : temp; /* if WS_EnterSingleProtocol altered it we need to use this value */ + items += temp; + space -= temp; + } + size = min_buffer_size * (unicode ? sizeof(WSAPROTOCOL_INFOW) : sizeof(WSAPROTOCOL_INFOA)); + if(*len == 0) + { + /* if len is 0 it's either passed in or explicitly set resulting in an error */ + *len = size; + return SOCKET_ERROR; + } + else if(size > *len) + /* len should return the count of needed space */ + *len = size; + return items; }
static BOOL ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, int *size)