ws2_32: Reimplement WSAStringToAddress on top of ntdll functions.
And add tests to show that the address is always zeroed out even if there is an error, and that WSAStringToAddress has the same bug with leading double colons as RtlIpv6StringToAddress. Signed-off-by: Alex Henrie <alexhenrie24@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
2756b68559
commit
3bb824f988
|
@ -154,6 +154,7 @@
|
||||||
#include "winnt.h"
|
#include "winnt.h"
|
||||||
#define USE_WC_PREFIX /* For CMSG_DATA */
|
#define USE_WC_PREFIX /* For CMSG_DATA */
|
||||||
#include "iphlpapi.h"
|
#include "iphlpapi.h"
|
||||||
|
#include "ip2string.h"
|
||||||
#include "wine/server.h"
|
#include "wine/server.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
#include "wine/exception.h"
|
#include "wine/exception.h"
|
||||||
|
@ -8484,7 +8485,7 @@ INT WINAPI WSAStringToAddressA(LPSTR AddressString,
|
||||||
LPINT lpAddressLength)
|
LPINT lpAddressLength)
|
||||||
{
|
{
|
||||||
INT res=0;
|
INT res=0;
|
||||||
LPSTR workBuffer=NULL,ptrPort;
|
NTSTATUS status;
|
||||||
|
|
||||||
TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_a(AddressString), AddressFamily,
|
TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_a(AddressString), AddressFamily,
|
||||||
lpProtocolInfo, lpAddress, lpAddressLength );
|
lpProtocolInfo, lpAddress, lpAddressLength );
|
||||||
|
@ -8500,21 +8501,11 @@ INT WINAPI WSAStringToAddressA(LPSTR AddressString,
|
||||||
if (lpProtocolInfo)
|
if (lpProtocolInfo)
|
||||||
FIXME("ProtocolInfo not implemented.\n");
|
FIXME("ProtocolInfo not implemented.\n");
|
||||||
|
|
||||||
workBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
|
||||||
strlen(AddressString) + 1);
|
|
||||||
if (!workBuffer)
|
|
||||||
{
|
|
||||||
SetLastError(WSA_NOT_ENOUGH_MEMORY);
|
|
||||||
return SOCKET_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(workBuffer, AddressString);
|
|
||||||
|
|
||||||
switch(AddressFamily)
|
switch(AddressFamily)
|
||||||
{
|
{
|
||||||
case WS_AF_INET:
|
case WS_AF_INET:
|
||||||
{
|
{
|
||||||
struct in_addr inetaddr;
|
SOCKADDR_IN *addr4 = (SOCKADDR_IN *)lpAddress;
|
||||||
|
|
||||||
/* If lpAddressLength is too small, tell caller the size we need */
|
/* If lpAddressLength is too small, tell caller the size we need */
|
||||||
if (*lpAddressLength < sizeof(SOCKADDR_IN))
|
if (*lpAddressLength < sizeof(SOCKADDR_IN))
|
||||||
|
@ -8526,35 +8517,18 @@ INT WINAPI WSAStringToAddressA(LPSTR AddressString,
|
||||||
*lpAddressLength = sizeof(SOCKADDR_IN);
|
*lpAddressLength = sizeof(SOCKADDR_IN);
|
||||||
memset(lpAddress, 0, sizeof(SOCKADDR_IN));
|
memset(lpAddress, 0, sizeof(SOCKADDR_IN));
|
||||||
|
|
||||||
((LPSOCKADDR_IN)lpAddress)->sin_family = WS_AF_INET;
|
status = RtlIpv4StringToAddressExA(AddressString, FALSE, &addr4->sin_addr, &addr4->sin_port);
|
||||||
|
if (status != STATUS_SUCCESS)
|
||||||
ptrPort = strchr(workBuffer, ':');
|
|
||||||
if(ptrPort)
|
|
||||||
{
|
{
|
||||||
/* User may have entered an IPv6 and asked to parse as IPv4 */
|
|
||||||
if(strchr(ptrPort + 1, ':'))
|
|
||||||
{
|
|
||||||
res = WSAEINVAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
((LPSOCKADDR_IN)lpAddress)->sin_port = htons(atoi(ptrPort+1));
|
|
||||||
*ptrPort = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
if(inet_aton(workBuffer, &inetaddr) > 0)
|
|
||||||
{
|
|
||||||
((LPSOCKADDR_IN)lpAddress)->sin_addr.WS_s_addr = inetaddr.s_addr;
|
|
||||||
res = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
res = WSAEINVAL;
|
res = WSAEINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
addr4->sin_family = WS_AF_INET;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WS_AF_INET6:
|
case WS_AF_INET6:
|
||||||
{
|
{
|
||||||
struct in6_addr inetaddr;
|
SOCKADDR_IN6 *addr6 = (SOCKADDR_IN6 *)lpAddress;
|
||||||
char *ptrAddr = workBuffer;
|
|
||||||
|
|
||||||
/* If lpAddressLength is too small, tell caller the size we need */
|
/* If lpAddressLength is too small, tell caller the size we need */
|
||||||
if (*lpAddressLength < sizeof(SOCKADDR_IN6))
|
if (*lpAddressLength < sizeof(SOCKADDR_IN6))
|
||||||
|
@ -8563,42 +8537,16 @@ INT WINAPI WSAStringToAddressA(LPSTR AddressString,
|
||||||
res = WSAEFAULT;
|
res = WSAEFAULT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_INET_PTON
|
|
||||||
*lpAddressLength = sizeof(SOCKADDR_IN6);
|
*lpAddressLength = sizeof(SOCKADDR_IN6);
|
||||||
memset(lpAddress, 0, sizeof(SOCKADDR_IN6));
|
memset(lpAddress, 0, sizeof(SOCKADDR_IN6));
|
||||||
|
|
||||||
((LPSOCKADDR_IN6)lpAddress)->sin6_family = WS_AF_INET6;
|
status = RtlIpv6StringToAddressExA(AddressString, &addr6->sin6_addr, &addr6->sin6_scope_id, &addr6->sin6_port);
|
||||||
|
if (status != STATUS_SUCCESS)
|
||||||
/* Valid IPv6 addresses can also be surrounded by [ ], and in this case
|
|
||||||
* a port number may follow after like in [fd12:3456:7890::1]:12345
|
|
||||||
* We need to cut the brackets and find the port if any. */
|
|
||||||
|
|
||||||
if(*workBuffer == '[')
|
|
||||||
{
|
{
|
||||||
ptrPort = strchr(workBuffer, ']');
|
|
||||||
if (!ptrPort)
|
|
||||||
{
|
|
||||||
SetLastError(WSAEINVAL);
|
|
||||||
return SOCKET_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ptrPort[1] == ':')
|
|
||||||
((LPSOCKADDR_IN6)lpAddress)->sin6_port = htons(atoi(ptrPort + 2));
|
|
||||||
|
|
||||||
*ptrPort = '\0';
|
|
||||||
ptrAddr = workBuffer + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(inet_pton(AF_INET6, ptrAddr, &inetaddr) > 0)
|
|
||||||
{
|
|
||||||
memcpy(&((LPSOCKADDR_IN6)lpAddress)->sin6_addr, &inetaddr,
|
|
||||||
sizeof(struct in6_addr));
|
|
||||||
res = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif /* HAVE_INET_PTON */
|
|
||||||
res = WSAEINVAL;
|
res = WSAEINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
addr6->sin6_family = WS_AF_INET6;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -8607,8 +8555,6 @@ INT WINAPI WSAStringToAddressA(LPSTR AddressString,
|
||||||
res = WSAEINVAL;
|
res = WSAEINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, workBuffer);
|
|
||||||
|
|
||||||
if (!res) return 0;
|
if (!res) return 0;
|
||||||
SetLastError(res);
|
SetLastError(res);
|
||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
|
|
|
@ -3429,6 +3429,8 @@ static void test_WSAStringToAddress(void)
|
||||||
{ "127.127.127.127:65535", 0x7f7f7f7f, 65535 },
|
{ "127.127.127.127:65535", 0x7f7f7f7f, 65535 },
|
||||||
{ "255.255.255.255:65535", 0xffffffff, 65535 },
|
{ "255.255.255.255:65535", 0xffffffff, 65535 },
|
||||||
{ "2001::1", 0xd1070000, 0, WSAEINVAL },
|
{ "2001::1", 0xd1070000, 0, WSAEINVAL },
|
||||||
|
{ "1.2.3.", 0, 0, WSAEINVAL },
|
||||||
|
{ "", 0, 0, WSAEINVAL },
|
||||||
};
|
};
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
|
@ -3445,6 +3447,10 @@ static void test_WSAStringToAddress(void)
|
||||||
{ "2001::1", { 0x120, 0, 0, 0, 0, 0, 0, 0x100 } },
|
{ "2001::1", { 0x120, 0, 0, 0, 0, 0, 0, 0x100 } },
|
||||||
{ "::1]:65535", { 0, 0, 0, 0, 0, 0, 0, 0x100 }, 0, WSAEINVAL },
|
{ "::1]:65535", { 0, 0, 0, 0, 0, 0, 0, 0x100 }, 0, WSAEINVAL },
|
||||||
{ "001::1", { 0x100, 0, 0, 0, 0, 0, 0, 0x100 } },
|
{ "001::1", { 0x100, 0, 0, 0, 0, 0, 0, 0x100 } },
|
||||||
|
{ "::1:2:3:4:5:6:7", { 0, 0, 0x100, 0x200, 0x300, 0x400, 0x500, 0x600 }, 0, WSAEINVAL }, /* Windows bug */
|
||||||
|
{ "1.2.3.4", { 0x201, 0x3, 0, 0, 0, 0, 0, 0 }, 0, WSAEINVAL },
|
||||||
|
{ "1:2:3:", { 0x100, 0x200, 0x300, 0, 0, 0, 0 }, 0, WSAEINVAL },
|
||||||
|
{ "", { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, WSAEINVAL },
|
||||||
};
|
};
|
||||||
|
|
||||||
WCHAR inputW[64];
|
WCHAR inputW[64];
|
||||||
|
@ -3485,11 +3491,9 @@ static void test_WSAStringToAddress(void)
|
||||||
ok( WSAGetLastError() == ipv4_tests[j].error,
|
ok( WSAGetLastError() == ipv4_tests[j].error,
|
||||||
"WSAStringToAddress(%s) gave error %d, expected %d\n",
|
"WSAStringToAddress(%s) gave error %d, expected %d\n",
|
||||||
wine_dbgstr_a( ipv4_tests[j].input ), WSAGetLastError(), ipv4_tests[j].error );
|
wine_dbgstr_a( ipv4_tests[j].input ), WSAGetLastError(), ipv4_tests[j].error );
|
||||||
todo_wine_if(ipv4_tests[j].error)
|
|
||||||
ok( sockaddr.sin_family == expected_family,
|
ok( sockaddr.sin_family == expected_family,
|
||||||
"WSAStringToAddress(%s) gave family %d, expected %d\n",
|
"WSAStringToAddress(%s) gave family %d, expected %d\n",
|
||||||
wine_dbgstr_a( ipv4_tests[j].input ), sockaddr.sin_family, expected_family );
|
wine_dbgstr_a( ipv4_tests[j].input ), sockaddr.sin_family, expected_family );
|
||||||
todo_wine_if(ipv4_tests[j].error)
|
|
||||||
ok( sockaddr.sin_addr.s_addr == ipv4_tests[j].address,
|
ok( sockaddr.sin_addr.s_addr == ipv4_tests[j].address,
|
||||||
"WSAStringToAddress(%s) gave address %08x, expected %08x\n",
|
"WSAStringToAddress(%s) gave address %08x, expected %08x\n",
|
||||||
wine_dbgstr_a( ipv4_tests[j].input ), sockaddr.sin_addr.s_addr, ipv4_tests[j].address );
|
wine_dbgstr_a( ipv4_tests[j].input ), sockaddr.sin_addr.s_addr, ipv4_tests[j].address );
|
||||||
|
@ -3526,11 +3530,9 @@ todo_wine_if(ipv4_tests[j].error)
|
||||||
ok( WSAGetLastError() == ipv6_tests[j].error,
|
ok( WSAGetLastError() == ipv6_tests[j].error,
|
||||||
"WSAStringToAddress(%s) gave error %d, expected %d\n",
|
"WSAStringToAddress(%s) gave error %d, expected %d\n",
|
||||||
wine_dbgstr_a( ipv6_tests[j].input ), WSAGetLastError(), ipv6_tests[j].error );
|
wine_dbgstr_a( ipv6_tests[j].input ), WSAGetLastError(), ipv6_tests[j].error );
|
||||||
todo_wine_if(ipv6_tests[j].error)
|
|
||||||
ok( sockaddr6.sin6_family == expected_family,
|
ok( sockaddr6.sin6_family == expected_family,
|
||||||
"WSAStringToAddress(%s) gave family %d, expected %d\n",
|
"WSAStringToAddress(%s) gave family %d, expected %d\n",
|
||||||
wine_dbgstr_a( ipv4_tests[j].input ), sockaddr6.sin6_family, expected_family );
|
wine_dbgstr_a( ipv4_tests[j].input ), sockaddr6.sin6_family, expected_family );
|
||||||
todo_wine_if(ipv6_tests[j].error)
|
|
||||||
ok( memcmp(&sockaddr6.sin6_addr, ipv6_tests[j].address, sizeof(sockaddr6.sin6_addr)) == 0,
|
ok( memcmp(&sockaddr6.sin6_addr, ipv6_tests[j].address, sizeof(sockaddr6.sin6_addr)) == 0,
|
||||||
"WSAStringToAddress(%s) gave address %x:%x:%x:%x:%x:%x:%x:%x, expected %x:%x:%x:%x:%x:%x:%x:%x\n",
|
"WSAStringToAddress(%s) gave address %x:%x:%x:%x:%x:%x:%x:%x, expected %x:%x:%x:%x:%x:%x:%x:%x\n",
|
||||||
wine_dbgstr_a( ipv6_tests[j].input ),
|
wine_dbgstr_a( ipv6_tests[j].input ),
|
||||||
|
|
Loading…
Reference in New Issue