diff --git a/dlls/winsock/Makefile.in b/dlls/winsock/Makefile.in index ae27824e573..5f03748d7e9 100644 --- a/dlls/winsock/Makefile.in +++ b/dlls/winsock/Makefile.in @@ -5,6 +5,7 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = ws2_32.dll IMPORTS = user32 iphlpapi kernel32 ntdll +EXTRALIBS = $(LIBUNICODE) C_SRCS = \ async.c \ diff --git a/dlls/winsock/socket.c b/dlls/winsock/socket.c index d2d8baac15a..035a276a4cd 100644 --- a/dlls/winsock/socket.c +++ b/dlls/winsock/socket.c @@ -128,6 +128,7 @@ #include "thread.h" #include "wine/server.h" #include "wine/debug.h" +#include "wine/unicode.h" #ifdef HAVE_IPX # include "wsnwlink.h" @@ -3693,6 +3694,9 @@ INT WINAPI WSAStringToAddressA(LPSTR AddressString, LONG inetaddr; LPSTR workBuffer=NULL,ptrPort; + TRACE( "(%s, %x, %p, %p, %d)\n", AddressString, AddressFamily, lpProtocolInfo, + lpAddress, *lpAddressLength ); + if (AddressString) { workBuffer = HeapAlloc( GetProcessHeap(), 0, strlen(AddressString)+1 ); @@ -3775,6 +3779,9 @@ INT WINAPI WSAStringToAddressW(LPWSTR AddressString, WSAPROTOCOL_INFOA infoA; LPWSAPROTOCOL_INFOA lpProtoInfoA = NULL; + TRACE( "(%s, %x, %p, %p, %d)\n", debugstr_w(AddressString), AddressFamily, lpProtocolInfo, + lpAddress, *lpAddressLength ); + /* if ProtocolInfo is available - convert to ANSI variant */ if (lpProtocolInfo) { @@ -3814,6 +3821,109 @@ INT WINAPI WSAStringToAddressW(LPWSTR AddressString, return SOCKET_ERROR; } +/*********************************************************************** + * WSAAddressToStringA (WS2_32.27) + * + * See WSAAddressToStringW + */ +INT WINAPI WSAAddressToStringA( LPSOCKADDR sockaddr, DWORD len, + LPWSAPROTOCOL_INFOA info, LPSTR string, + LPDWORD lenstr ) +{ + INT size; + CHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */ + static const CHAR format[] = "%d.%d.%d.%d:%d"; + CHAR *p; + + TRACE( "(%p, %lx, %p, %p, %ld)\n", sockaddr, len, info, string, *lenstr ); + + if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR; + + /* sin_family is garanteed to be the first u_short */ + if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR; + + sprintf( buffer, format, + ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff, + ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff, + ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff, + ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff, + ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) ); + + p = strchr( buffer, ':' ); + if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0; + + size = strlen( buffer ); + + if (*lenstr < size) + { + *lenstr = size; + return SOCKET_ERROR; + } + + strcpy( string, buffer ); + return 0; +} + +/*********************************************************************** + * WSAAddressToStringW (WS2_32.28) + * + * Convert a sockaddr address into a readable address string. + * + * PARAMS + * sockaddr [I] Pointer to a sockaddr structure. + * len [I] Size of the sockaddr structure. + * info [I] Pointer to a WSAPROTOCOL_INFOW structure (optional). + * string [I/O] Pointer to a buffer to receive the address string. + * lenstr [I/O] Size of the receive buffer in WCHARs. + * + * RETURNS + * Success: 0 + * Failure: SOCKET_ERROR + * + * NOTES + * The 'info' parameter is ignored. + * + * BUGS + * Only supports AF_INET addresses. + */ +INT WINAPI WSAAddressToStringW( LPSOCKADDR sockaddr, DWORD len, + LPWSAPROTOCOL_INFOW info, LPWSTR string, + LPDWORD lenstr ) +{ + INT size; + WCHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */ + static const WCHAR format[] = { '%','d','.','%','d','.','%','d','.','%','d', ':', '%', 'd',0 }; + WCHAR *p; + + TRACE( "(%p, %lx, %p, %p, %ld)\n", sockaddr, len, info, string, *lenstr ); + + if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR; + + /* sin_family is garanteed to be the first u_short */ + if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR; + + sprintfW( buffer, format, + ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff, + ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff, + ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff, + ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff, + ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) ); + + p = strchrW( buffer, ':' ); + if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0; + + size = lstrlenW( buffer ); + + if (*lenstr < size) + { + *lenstr = size; + return SOCKET_ERROR; + } + + lstrcpyW( string, buffer ); + return 0; +} + /*********************************************************************** * WSALookupServiceBeginA (WS2_32.59) */ @@ -3846,25 +3956,3 @@ INT WINAPI WSCUnInstallNameSpace( LPGUID lpProviderId ) return NO_ERROR; } - -INT WINAPI WSAAddressToStringA(LPSOCKADDR lpsaAddress, - DWORD dwAddressLenght, - LPWSAPROTOCOL_INFOA lpProtocolInfo, - LPSTR lpszAddressString, - LPDWORD lpdwAddressStringLength) -{ - FIXME("Stub!"); - WSASetLastError(WSAENOBUFS); - return SOCKET_ERROR; -} - -INT WINAPI WSAAddressToStringW(LPSOCKADDR lpsaAddress, - DWORD dwAddressLenght, - LPWSAPROTOCOL_INFOW lpProtocolInfo, - LPWSTR lpszAddressString, - LPDWORD lpdwAddressStringLength) -{ - FIXME("Stub!"); - WSASetLastError(WSAENOBUFS); - return SOCKET_ERROR; -} diff --git a/dlls/winsock/tests/sock.c b/dlls/winsock/tests/sock.c index 96eabe7eb9e..2c73e25603d 100644 --- a/dlls/winsock/tests/sock.c +++ b/dlls/winsock/tests/sock.c @@ -777,6 +777,248 @@ static test_setup tests [NUM_TESTS] = } }; +static void test_WSAAddressToStringA() +{ + INT ret; + DWORD len; + SOCKADDR_IN sockaddr; + CHAR address[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */ + + CHAR expect1[] = "0.0.0.0"; + CHAR expect2[] = "255.255.255.255"; + CHAR expect3[] = "0.0.0.0:65535"; + CHAR expect4[] = "255.255.255.255:65535"; + + len = 0; + + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = 0; + sockaddr.sin_addr.s_addr = 0; + + ret = WSAAddressToStringA( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len ); + ok( ret == SOCKET_ERROR, "WSAAddressToStringA() succeeded unexpectedly: %d\n", WSAGetLastError() ); + + len = sizeof(address); + + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = 0; + sockaddr.sin_addr.s_addr = 0; + + ret = WSAAddressToStringA( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len ); + ok( !ret, "WSAAddressToStringA() failed unexpectedly: %d\n", WSAGetLastError() ); + + ok( !strcmp( address, expect1 ), "Expected: %s, got: %s\n", expect1, address ); + + len = sizeof(address); + + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = 0; + sockaddr.sin_addr.s_addr = 0xffffffff; + + ret = WSAAddressToStringA( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len ); + ok( !ret, "WSAAddressToStringA() failed unexpectedly: %d\n", WSAGetLastError() ); + + ok( !strcmp( address, expect2 ), "Expected: %s, got: %s\n", expect2, address ); + + len = sizeof(address); + + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = 0xffff; + sockaddr.sin_addr.s_addr = 0; + + ret = WSAAddressToStringA( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len ); + ok( !ret, "WSAAddressToStringA() failed unexpectedly: %d\n", WSAGetLastError() ); + + ok( !strcmp( address, expect3 ), "Expected: %s, got: %s\n", expect3, address ); + + len = sizeof(address); + + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = 0xffff; + sockaddr.sin_addr.s_addr = 0xffffffff; + + ret = WSAAddressToStringA( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len ); + ok( !ret, "WSAAddressToStringA() failed unexpectedly: %d\n", WSAGetLastError() ); + + ok( !strcmp( address, expect4 ), "Expected: %s, got: %s\n", expect4, address ); +} + +static void test_WSAAddressToStringW() +{ + INT ret; + DWORD len; + SOCKADDR_IN sockaddr; + WCHAR address[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */ + + WCHAR expect1[] = { '0','.','0','.','0','.','0', 0 }; + WCHAR expect2[] = { '2','5','5','.','2','5','5','.','2','5','5','.','2','5','5', 0 }; + WCHAR expect3[] = { '0','.','0','.','0','.','0', ':', '6', '5', '5', '3', '5', 0 }; + WCHAR expect4[] = { '2','5','5','.','2','5','5','.','2','5','5','.','2','5','5', ':', + '6', '5', '5', '3', '5', 0 }; + + len = 0; + + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = 0; + sockaddr.sin_addr.s_addr = 0; + + ret = WSAAddressToStringW( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len ); + ok( ret == SOCKET_ERROR, "WSAAddressToStringW() succeeded unexpectedly: %x\n", WSAGetLastError() ); + + len = sizeof(address); + + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = 0; + sockaddr.sin_addr.s_addr = 0; + + ret = WSAAddressToStringW( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len ); + ok( !ret, "WSAAddressToStringW() failed unexpectedly: %x\n", WSAGetLastError() ); + + ok( !lstrcmpW( address, expect1 ), "Expected different address string\n" ); + + len = sizeof(address); + + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = 0; + sockaddr.sin_addr.s_addr = 0xffffffff; + + ret = WSAAddressToStringW( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len ); + ok( !ret, "WSAAddressToStringW() failed unexpectedly: %x\n", WSAGetLastError() ); + + ok( !lstrcmpW( address, expect2 ), "Expected different address string\n" ); + + len = sizeof(address); + + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = 0xffff; + sockaddr.sin_addr.s_addr = 0; + + ret = WSAAddressToStringW( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len ); + ok( !ret, "WSAAddressToStringW() failed unexpectedly: %x\n", WSAGetLastError() ); + + ok( !lstrcmpW( address, expect3 ), "Expected different address string\n" ); + + len = sizeof(address); + + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = 0xffff; + sockaddr.sin_addr.s_addr = 0xffffffff; + + ret = WSAAddressToStringW( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len ); + ok( !ret, "WSAAddressToStringW() failed unexpectedly: %x\n", WSAGetLastError() ); + + ok( !lstrcmpW( address, expect4 ), "Expected different address string\n" ); +} + +static void test_WSAStringToAddressA() +{ + INT ret, len; + SOCKADDR_IN sockaddr; + + CHAR address1[] = "0.0.0.0"; + CHAR address2[] = "127.127.127.127"; + CHAR address3[] = "255.255.255.255"; + CHAR address4[] = "127.127.127.127:65535"; + CHAR address5[] = "255.255.255.255:65535"; + + len = 0; + sockaddr.sin_family = AF_INET; + + ret = WSAStringToAddressA( address1, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); + ok( ret == SOCKET_ERROR, "WSAStringToAddressA() succeeded unexpectedly: %x\n", + WSAGetLastError() ); + + len = sizeof(sockaddr); + sockaddr.sin_port = 0; + sockaddr.sin_addr.s_addr = 0; + + ret = WSAStringToAddressA( address1, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); + ok( !ret && sockaddr.sin_addr.s_addr == 0, + "WSAStringToAddressA() failed unexpectedly: %d\n", WSAGetLastError() ); + + len = sizeof(sockaddr); + sockaddr.sin_port = 0; + sockaddr.sin_addr.s_addr = 0; + + ret = WSAStringToAddressA( address2, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); + ok( !ret && sockaddr.sin_addr.s_addr == 0x7f7f7f7f, + "WSAStringToAddressA() failed unexpectedly: %d\n", WSAGetLastError() ); + + len = sizeof(sockaddr); + + ret = WSAStringToAddressA( address3, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); + ok( ret, "WSAStringToAddressA() succeeded unexpectedly: %d\n", WSAGetLastError() ); + + len = sizeof(sockaddr); + sockaddr.sin_port = 0; + sockaddr.sin_addr.s_addr = 0; + + ret = WSAStringToAddressA( address4, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); + ok( !ret && sockaddr.sin_addr.s_addr == 0x7f7f7f7f && sockaddr.sin_port == 0xffff, + "WSAStringToAddressA() failed unexpectedly: %d\n", WSAGetLastError() ); + + len = sizeof(sockaddr); + + ret = WSAStringToAddressA( address5, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); + ok( ret, "WSAStringToAddressA() succeeded unexpectedly: %d\n", WSAGetLastError() ); +} + +static void test_WSAStringToAddressW() +{ + INT ret, len; + SOCKADDR_IN sockaddr; + + WCHAR address1[] = { '0','.','0','.','0','.','0', 0 }; + WCHAR address2[] = { '1','2','7','.','1','2','7','.','1','2','7','.','1','2','7', 0 }; + WCHAR address3[] = { '2','5','5','.','2','5','5','.','2','5','5','.','2','5','5', 0 }; + WCHAR address4[] = { '1','2','7','.','1','2','7','.','1','2','7','.','1','2','7', + ':', '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 }; + + len = 0; + sockaddr.sin_family = AF_INET; + + ret = WSAStringToAddressW( address1, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); + ok( ret == SOCKET_ERROR, "WSAStringToAddressW() failed unexpectedly: %d\n", + WSAGetLastError() ); + + len = sizeof(sockaddr); + sockaddr.sin_port = 0; + sockaddr.sin_addr.s_addr = 0; + + ret = WSAStringToAddressW( address1, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); + ok( !ret && sockaddr.sin_addr.s_addr == 0, + "WSAStringToAddressW() failed unexpectedly: %d\n", WSAGetLastError() ); + + len = sizeof(sockaddr); + + sockaddr.sin_port = 0; + sockaddr.sin_addr.s_addr = 0; + + ret = WSAStringToAddressW( address2, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); + ok( !ret && sockaddr.sin_addr.s_addr == 0x7f7f7f7f, + "WSAStringToAddressW() failed unexpectedly: %d\n", WSAGetLastError() ); + + len = sizeof(sockaddr); + + ret = WSAStringToAddressW( address3, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); + ok( ret, "WSAStringToAddressW() failed unexpectedly: %d\n", WSAGetLastError() ); + + len = sizeof(sockaddr); + sockaddr.sin_port = 0; + sockaddr.sin_addr.s_addr = 0; + + ret = WSAStringToAddressW( address4, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); + ok( !ret && sockaddr.sin_addr.s_addr == 0x7f7f7f7f && sockaddr.sin_port == 0xffff, + "WSAStringToAddressW() failed unexpectedly: %d\n", WSAGetLastError() ); + + len = sizeof(sockaddr); + + ret = WSAStringToAddressW( address5, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); + ok( ret, "WSAStringToAddressW() succeeded unexpectedly: %d\n", WSAGetLastError() ); +} + /**************** Main program ***************/ START_TEST( sock ) @@ -794,5 +1036,11 @@ START_TEST( sock ) trace ( " **** TEST %d COMPLETE **** \n", i ); } + test_WSAAddressToStringA(); + test_WSAAddressToStringW(); + + test_WSAStringToAddressA(); + test_WSAStringToAddressW(); + Exit(); }