[PATCH v2 2/3] ws2_32: Reimplement WS_EnumProtocols
Robin Ebert
ebertrobin2002 at gmail.com
Thu Aug 13 07:08:19 CDT 2020
WS_EnumProtocols broke with changes to WS_EnterSingleProtocol{W|A} so it needs to be reimplemented.
Signed-off-by: Robin Ebert <ebertrobin2002 at 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)
--
2.20.1
More information about the wine-devel
mailing list