ws2_32: Fix handling of NULL and empty hostname in getaddrinfo/GetAddrInfoW. (try 2)
Hans Leidekker
hans at codeweavers.com
Tue Nov 15 04:38:20 CST 2011
This version avoids test failures on nt4 and win2k.
Fixes http://bugs.winehq.org/show_bug.cgi?id=29039
---
dlls/ws2_32/socket.c | 56 +++++++++++++++++----------
dlls/ws2_32/tests/sock.c | 95 ++++++++++++++++++++++++++++++++++++++-------
2 files changed, 116 insertions(+), 35 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 00a15b6..fe645c1 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -4785,6 +4785,22 @@ static int convert_eai_u2w(int unixret) {
return unixret;
}
+static char *get_hostname(void)
+{
+ char *ret;
+ DWORD size = 0;
+
+ GetComputerNameExA( ComputerNamePhysicalDnsHostname, NULL, &size );
+ if (GetLastError() != ERROR_MORE_DATA) return NULL;
+ if (!(ret = HeapAlloc( GetProcessHeap(), 0, size ))) return NULL;
+ if (!GetComputerNameExA( ComputerNamePhysicalDnsHostname, ret, &size ))
+ {
+ HeapFree( GetProcessHeap(), 0, ret );
+ return NULL;
+ }
+ return ret;
+}
+
/***********************************************************************
* getaddrinfo (WS2_32.@)
*/
@@ -4794,17 +4810,19 @@ int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addr
struct addrinfo *unixaires = NULL;
int result;
struct addrinfo unixhints, *punixhints = NULL;
- CHAR *node = NULL, *serv = NULL;
+ char *hostname = NULL;
+ const char *node;
- if (nodename)
- if (!(node = strdup_lower(nodename))) return WSA_NOT_ENOUGH_MEMORY;
+ if (!nodename && !servname) return WSAHOST_NOT_FOUND;
- if (servname) {
- if (!(serv = strdup_lower(servname))) {
- HeapFree(GetProcessHeap(), 0, node);
- return WSA_NOT_ENOUGH_MEMORY;
- }
- }
+ if (!nodename)
+ node = "localhost";
+ else if (!nodename[0])
+ node = hostname = get_hostname();
+ else
+ node = nodename;
+
+ if (!node) return WSA_NOT_ENOUGH_MEMORY;
if (hints) {
punixhints = &unixhints;
@@ -4826,12 +4844,10 @@ int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addr
}
/* getaddrinfo(3) is thread safe, no need to wrap in CS */
- result = getaddrinfo(nodename, servname, punixhints, &unixaires);
+ result = getaddrinfo(node, servname, punixhints, &unixaires);
TRACE("%s, %s %p -> %p %d\n", debugstr_a(nodename), debugstr_a(servname), hints, res, result);
-
- HeapFree(GetProcessHeap(), 0, node);
- HeapFree(GetProcessHeap(), 0, serv);
+ HeapFree(GetProcessHeap(), 0, hostname);
if (!result) {
struct addrinfo *xuai = unixaires;
@@ -4991,15 +5007,15 @@ static struct WS_addrinfo *addrinfo_WtoA(const struct WS_addrinfoW *ai)
int WINAPI GetAddrInfoW(LPCWSTR nodename, LPCWSTR servname, const ADDRINFOW *hints, PADDRINFOW *res)
{
int ret, len;
- char *nodenameA, *servnameA = NULL;
+ char *nodenameA = NULL, *servnameA = NULL;
struct WS_addrinfo *resA, *hintsA = NULL;
- if (!nodename) return WSAHOST_NOT_FOUND;
-
- len = WideCharToMultiByte(CP_ACP, 0, nodename, -1, NULL, 0, NULL, NULL);
- if (!(nodenameA = HeapAlloc(GetProcessHeap(), 0, len))) return EAI_MEMORY;
- WideCharToMultiByte(CP_ACP, 0, nodename, -1, nodenameA, len, NULL, NULL);
-
+ if (nodename)
+ {
+ len = WideCharToMultiByte(CP_ACP, 0, nodename, -1, NULL, 0, NULL, NULL);
+ if (!(nodenameA = HeapAlloc(GetProcessHeap(), 0, len))) return EAI_MEMORY;
+ WideCharToMultiByte(CP_ACP, 0, nodename, -1, nodenameA, len, NULL, NULL);
+ }
if (servname)
{
len = WideCharToMultiByte(CP_ACP, 0, servname, -1, NULL, 0, NULL, NULL);
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 237bc86..7b5dde8 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -59,9 +59,11 @@
k.keepaliveinterval = interval;
/* Function pointers */
-static void (WINAPI *pFreeAddrInfoW)(PADDRINFOW) = 0;
-static int (WINAPI *pGetAddrInfoW)(LPCWSTR,LPCWSTR,const ADDRINFOW *,PADDRINFOW *) = 0;
-static PCSTR (WINAPI *pInetNtop)(INT,LPVOID,LPSTR,ULONG) = 0;
+static void (WINAPI *pfreeaddrinfo)(struct addrinfo *);
+static int (WINAPI *pgetaddrinfo)(LPCSTR,LPCSTR,const struct addrinfo *,struct addrinfo **);
+static void (WINAPI *pFreeAddrInfoW)(PADDRINFOW);
+static int (WINAPI *pGetAddrInfoW)(LPCWSTR,LPCWSTR,const ADDRINFOW *,PADDRINFOW *);
+static PCSTR (WINAPI *pInetNtop)(INT,LPVOID,LPSTR,ULONG);
/**************** Structs and typedefs ***************/
@@ -1002,6 +1004,8 @@ static void Init (void)
WSADATA data;
HMODULE hws2_32 = GetModuleHandle("ws2_32.dll");
+ pfreeaddrinfo = (void *)GetProcAddress(hws2_32, "freeaddrinfo");
+ pgetaddrinfo = (void *)GetProcAddress(hws2_32, "getaddrinfo");
pFreeAddrInfoW = (void *)GetProcAddress(hws2_32, "FreeAddrInfoW");
pGetAddrInfoW = (void *)GetProcAddress(hws2_32, "GetAddrInfoW");
pInetNtop = (void *)GetProcAddress(hws2_32, "inet_ntop");
@@ -4153,7 +4157,6 @@ static void test_GetAddrInfoW(void)
static const WCHAR empty[] = {0};
static const WCHAR localhost[] = {'l','o','c','a','l','h','o','s','t',0};
static const WCHAR zero[] = {'0',0};
-
int ret;
ADDRINFOW *result, hint;
@@ -4162,7 +4165,6 @@ static void test_GetAddrInfoW(void)
win_skip("GetAddrInfoW and/or FreeAddrInfoW not present\n");
return;
}
-
memset(&hint, 0, sizeof(ADDRINFOW));
ret = pGetAddrInfoW(NULL, NULL, NULL, &result);
@@ -4170,44 +4172,107 @@ static void test_GetAddrInfoW(void)
result = NULL;
ret = pGetAddrInfoW(empty, NULL, NULL, &result);
- todo_wine
- {
ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
ok(result != NULL, "GetAddrInfoW failed\n");
- }
pFreeAddrInfoW(result);
result = NULL;
ret = pGetAddrInfoW(NULL, zero, NULL, &result);
- todo_wine
- {
ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
ok(result != NULL, "GetAddrInfoW failed\n");
- }
pFreeAddrInfoW(result);
result = NULL;
ret = pGetAddrInfoW(empty, zero, NULL, &result);
- todo_wine
- {
ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
ok(result != NULL, "GetAddrInfoW failed\n");
- }
pFreeAddrInfoW(result);
+ result = NULL;
ret = pGetAddrInfoW(localhost, NULL, NULL, &result);
ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
pFreeAddrInfoW(result);
+ result = NULL;
+ ret = pGetAddrInfoW(localhost, empty, NULL, &result);
+ ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
+ pFreeAddrInfoW(result);
+
+ result = NULL;
+ ret = pGetAddrInfoW(localhost, zero, NULL, &result);
+ ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
+ pFreeAddrInfoW(result);
+
+ result = NULL;
ret = pGetAddrInfoW(localhost, port, NULL, &result);
ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
pFreeAddrInfoW(result);
+ result = NULL;
ret = pGetAddrInfoW(localhost, port, &hint, &result);
ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
pFreeAddrInfoW(result);
}
+static void test_getaddrinfo(void)
+{
+ int ret;
+ ADDRINFOA *result, hint;
+
+ if (!pgetaddrinfo || !pfreeaddrinfo)
+ {
+ win_skip("getaddrinfo and/or freeaddrinfo not present\n");
+ return;
+ }
+ memset(&hint, 0, sizeof(ADDRINFOA));
+
+ ret = pgetaddrinfo(NULL, NULL, NULL, &result);
+ ok(ret == WSAHOST_NOT_FOUND, "got %d expected WSAHOST_NOT_FOUND\n", ret);
+
+ result = NULL;
+ ret = pgetaddrinfo("", NULL, NULL, &result);
+ ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+ ok(result != NULL, "getaddrinfo failed\n");
+ pfreeaddrinfo(result);
+
+ result = NULL;
+ ret = pgetaddrinfo(NULL, "0", NULL, &result);
+ ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+ ok(result != NULL, "getaddrinfo failed\n");
+ pfreeaddrinfo(result);
+
+ result = NULL;
+ ret = pgetaddrinfo("", "0", NULL, &result);
+ ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+ ok(result != NULL, "getaddrinfo failed\n");
+ pfreeaddrinfo(result);
+
+ result = NULL;
+ ret = pgetaddrinfo("localhost", NULL, NULL, &result);
+ ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+ pfreeaddrinfo(result);
+
+ result = NULL;
+ ret = pgetaddrinfo("localhost", "", NULL, &result);
+ ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+ pfreeaddrinfo(result);
+
+ result = NULL;
+ ret = pgetaddrinfo("localhost", "0", NULL, &result);
+ ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+ pfreeaddrinfo(result);
+
+ result = NULL;
+ ret = pgetaddrinfo("localhost", "80", NULL, &result);
+ ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+ pfreeaddrinfo(result);
+
+ result = NULL;
+ ret = pgetaddrinfo("localhost", "80", &hint, &result);
+ ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+ pfreeaddrinfo(result);
+}
+
static void test_ConnectEx(void)
{
SOCKET listener = INVALID_SOCKET;
@@ -5153,7 +5218,7 @@ START_TEST( sock )
test_ipv6only();
test_GetAddrInfoW();
-
+ test_getaddrinfo();
test_AcceptEx();
test_ConnectEx();
--
1.7.5.4
More information about the wine-patches
mailing list