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(a)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;
--
2.20.1