diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 92fd3f6d8d6..90fa9b06873 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -4429,7 +4429,6 @@ INT WINAPI WSAStringToAddressA(LPSTR AddressString, LPINT lpAddressLength) { INT res=0; - struct in_addr inetaddr; LPSTR workBuffer=NULL,ptrPort; TRACE( "(%s, %x, %p, %p, %p)\n", AddressString, AddressFamily, lpProtocolInfo, @@ -4437,63 +4436,84 @@ INT WINAPI WSAStringToAddressA(LPSTR AddressString, if (!lpAddressLength || !lpAddress) return SOCKET_ERROR; - if (AddressString) + if (!AddressString) { - workBuffer = HeapAlloc( GetProcessHeap(), 0, strlen(AddressString)+1 ); - if (workBuffer) - { - strcpy(workBuffer,AddressString); - switch (AddressFamily) - { - case AF_INET: - /* caller wants to know the size of the socket buffer */ - if (*lpAddressLength < sizeof(SOCKADDR_IN)) - { - *lpAddressLength = sizeof(SOCKADDR_IN); - res = WSAEFAULT; - } - else - { - /* caller wants to translate an AddressString into a SOCKADDR */ - if (lpAddress) - { - memset(lpAddress,0,sizeof(SOCKADDR_IN)); - ((LPSOCKADDR_IN)lpAddress)->sin_family = AF_INET; - ptrPort = strchr(workBuffer,':'); - if (ptrPort) - { - ((LPSOCKADDR_IN)lpAddress)->sin_port = (WS_u_short)atoi(ptrPort+1); - *ptrPort = '\0'; - } - else - ((LPSOCKADDR_IN)lpAddress)->sin_port = 0; - if (inet_aton(workBuffer, &inetaddr) > 0) - { - ((LPSOCKADDR_IN)lpAddress)->sin_addr.WS_s_addr = inetaddr.s_addr; - res = 0; - } - else - res = WSAEINVAL; - } - } - if (lpProtocolInfo) - FIXME("(%s, %x, %p, %p, %p) - ProtocolInfo not implemented!\n", - AddressString, AddressFamily, - lpProtocolInfo, lpAddress, lpAddressLength); + WSASetLastError(WSAEINVAL); + return SOCKET_ERROR; + } - break; - default: - FIXME("(%s, %x, %p, %p, %p) - AddressFamiliy not implemented!\n", - AddressString, AddressFamily, - lpProtocolInfo, lpAddress, lpAddressLength); - } - HeapFree( GetProcessHeap(), 0, workBuffer ); + if (lpProtocolInfo) + FIXME("ProtocolInfo not implemented.\n"); + + workBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + strlen(AddressString) + 1); + if (!workBuffer) + { + WSASetLastError(WSA_NOT_ENOUGH_MEMORY); + return SOCKET_ERROR; + } + + strcpy(workBuffer, AddressString); + + switch(AddressFamily) + { + case AF_INET: + { + struct in_addr inetaddr; + + /* If lpAddressLength is too small, tell caller the size we need */ + if (*lpAddressLength < sizeof(SOCKADDR_IN)) + { + *lpAddressLength = sizeof(SOCKADDR_IN); + res = WSAEFAULT; + break; + } + memset(lpAddress, 0, sizeof(SOCKADDR_IN)); + + ((LPSOCKADDR_IN)lpAddress)->sin_family = AF_INET; + + ptrPort = strchr(workBuffer, ':'); + if(ptrPort) + { + ((LPSOCKADDR_IN)lpAddress)->sin_port = (WS_u_short)atoi(ptrPort+1); + *ptrPort = '\0'; } else - res = WSA_NOT_ENOUGH_MEMORY; + { + ((LPSOCKADDR_IN)lpAddress)->sin_port = 0; + } + + if(inet_aton(workBuffer, &inetaddr) > 0) + { + ((LPSOCKADDR_IN)lpAddress)->sin_addr.WS_s_addr = inetaddr.s_addr; + res = 0; + } + else + res = WSAEINVAL; + + break; + } - else + case AF_INET6: + { + /* If lpAddressLength is too small, tell caller the size we need */ + if (*lpAddressLength < sizeof(SOCKADDR_IN6)) + { + *lpAddressLength = sizeof(SOCKADDR_IN6); + res = WSAEFAULT; + break; + } + FIXME("We don't support IPv6 yet.\n"); res = WSAEINVAL; + break; + } + default: + /* According to MSDN, only AF_INET and AF_INET6 are supported. */ + TRACE("Unsupported address family specified: %d.\n", AddressFamily); + res = WSAEINVAL; + } + + HeapFree(GetProcessHeap(), 0, workBuffer); if (!res) return 0; WSASetLastError(res); diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index cc413206655..7eb6d38c989 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "wine/test.h" #include @@ -1250,6 +1251,7 @@ static void test_WSAStringToAddressA(void) { INT ret, len; SOCKADDR_IN sockaddr; + SOCKADDR_IN6 sockaddr6; int GLE; CHAR address1[] = "0.0.0.0"; @@ -1257,6 +1259,9 @@ static void test_WSAStringToAddressA(void) CHAR address3[] = "255.255.255.255"; CHAR address4[] = "127.127.127.127:65535"; CHAR address5[] = "255.255.255.255:65535"; + CHAR address6[] = "::1"; + CHAR address7[] = "[::1]"; + CHAR address8[] = "[::1]:65535"; len = 0; sockaddr.sin_family = AF_INET; @@ -1308,12 +1313,45 @@ static void test_WSAStringToAddressA(void) ok( (ret == 0 && sockaddr.sin_addr.s_addr == 0xffffffff && sockaddr.sin_port == 0xffff) || (ret == SOCKET_ERROR && (GLE == ERROR_INVALID_PARAMETER || GLE == WSAEINVAL)), "WSAStringToAddressA() failed unexpectedly: %d\n", GLE ); + + len = sizeof(sockaddr6); + memset(&sockaddr6, 0, len); + sockaddr6.sin6_family = AF_INET6; + + ret = WSAStringToAddressA( address6, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, + &len ); + GLE = WSAGetLastError(); + ok( ret == 0 || (ret == SOCKET_ERROR && GLE == WSAEINVAL), + "WSAStringToAddressA() failed for IPv6 address: %d\n", GLE); + + len = sizeof(sockaddr6); + memset(&sockaddr6, 0, len); + sockaddr6.sin6_family = AF_INET6; + + ret = WSAStringToAddressA( address7, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, + &len ); + GLE = WSAGetLastError(); + ok( ret == 0 || (ret == SOCKET_ERROR && GLE == WSAEINVAL), + "WSAStringToAddressA() failed for IPv6 address: %d\n", GLE); + + len = sizeof(sockaddr6); + memset(&sockaddr6, 0, len); + sockaddr6.sin6_family = AF_INET6; + + ret = WSAStringToAddressA( address8, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, + &len ); + GLE = WSAGetLastError(); + ok( (ret == 0 && sockaddr6.sin6_port == 0xffff) || + (ret == SOCKET_ERROR && GLE == WSAEINVAL), + "WSAStringToAddressA() failed for IPv6 address: %d\n", GLE); + } static void test_WSAStringToAddressW(void) { INT ret, len; SOCKADDR_IN sockaddr; + SOCKADDR_IN6 sockaddr6; int GLE; WCHAR address1[] = { '0','.','0','.','0','.','0', 0 }; @@ -1323,6 +1361,9 @@ static void test_WSAStringToAddressW(void) ':', '6', '5', '5', '3', '5', 0 }; WCHAR address5[] = { '2','5','5','.','2','5','5','.','2','5','5','.','2','5','5', ':', '6', '5', '5', '3', '5', 0 }; + WCHAR address6[] = {':',':','1','\0'}; + WCHAR address7[] = {'[',':',':','1',']','\0'}; + WCHAR address8[] = {'[',':',':','1',']',':','6','5','5','3','5','\0'}; len = 0; sockaddr.sin_family = AF_INET; @@ -1373,6 +1414,38 @@ static void test_WSAStringToAddressW(void) ok( (ret == 0 && sockaddr.sin_addr.s_addr == 0xffffffff && sockaddr.sin_port == 0xffff) || (ret == SOCKET_ERROR && (GLE == ERROR_INVALID_PARAMETER || GLE == WSAEINVAL)), "WSAStringToAddressW() failed unexpectedly: %d\n", GLE ); + + len = sizeof(sockaddr6); + memset(&sockaddr6, 0, len); + sockaddr6.sin6_family = AF_INET6; + + ret = WSAStringToAddressW( address6, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, + &len ); + GLE = WSAGetLastError(); + ok( ret == 0 || (ret == SOCKET_ERROR && GLE == WSAEINVAL), + "WSAStringToAddressW() failed for IPv6 address: %d\n", GLE); + + len = sizeof(sockaddr6); + memset(&sockaddr6, 0, len); + sockaddr6.sin6_family = AF_INET6; + + ret = WSAStringToAddressW( address7, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, + &len ); + GLE = WSAGetLastError(); + ok( ret == 0 || (ret == SOCKET_ERROR && GLE == WSAEINVAL), + "WSAStringToAddressW() failed for IPv6 address: %d\n", GLE); + + len = sizeof(sockaddr6); + memset(&sockaddr6, 0, len); + sockaddr6.sin6_family = AF_INET6; + + ret = WSAStringToAddressW( address8, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, + &len ); + GLE = WSAGetLastError(); + ok( (ret == 0 && sockaddr6.sin6_port == 0xffff) || + (ret == SOCKET_ERROR && GLE == WSAEINVAL), + "WSAStringToAddressW() failed for IPv6 address: %d\n", GLE); + } static VOID WINAPI SelectReadThread(select_thread_params *par)