ws2_32: Try harder to get the host name address in getaddrinfo (try 2)
Bruno Jesus
00cpxxx at gmail.com
Mon Aug 3 11:17:44 CDT 2015
try 2:
Tests now prove that resolving with the host name is the same as
resolving with empty name.
Fixes bug https://bugs.winehq.org/show_bug.cgi?id=29609
original:
When the host name is not resolvable getaddrinfo/GetAddrInfoW will
fail, this is not expected for some applications like League of
Legends. We can deal with this in two ways:
- Try harder and use a NULL name to resolve the localhost address
(user transparent).
- Just warn the user and give up (requires the user to understand the
issue and fix /etc/hosts).
This patch tries harder and at the same time warns the user.
Tested on PC-BSD 9 and Debian 7 by removing the host name in /etc/hosts.
-------------- next part --------------
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index b06d7e7..2d06a87 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -5973,7 +5973,7 @@ int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addr
struct addrinfo *unixaires = NULL;
int result;
struct addrinfo unixhints, *punixhints = NULL;
- char *hostname = NULL;
+ char *hostname;
const char *node;
*res = NULL;
@@ -5983,13 +5983,13 @@ int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addr
return WSAHOST_NOT_FOUND;
}
+ hostname = get_hostname();
+ if (!hostname) return WSA_NOT_ENOUGH_MEMORY;
+
if (!nodename)
node = NULL;
else if (!nodename[0])
- {
- node = hostname = get_hostname();
- if (!node) return WSA_NOT_ENOUGH_MEMORY;
- }
+ node = hostname;
else
node = nodename;
@@ -6033,6 +6033,14 @@ 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(node, servname, punixhints, &unixaires);
+ if (result && !strcmp(hostname, node))
+ {
+ /* If it didn't work it means the host name IP is not in /etc/hosts, try again
+ * by sending a NULL host and avoid sending a NULL servname too because that
+ * is invalid */
+ ERR_(winediag)("Failed to resolve your host name IP. You should fix this!\n");
+ result = getaddrinfo(NULL, servname ? servname : "0", punixhints, &unixaires);
+ }
TRACE("%s, %s %p -> %p %d\n", debugstr_a(nodename), debugstr_a(servname), hints, res, result);
HeapFree(GetProcessHeap(), 0, hostname);
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 2d14496..03e1627 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -6313,6 +6313,8 @@ static void test_GetAddrInfoW(void)
static const WCHAR zero[] = {'0',0};
int i, ret;
ADDRINFOW *result, *result2, *p, hint;
+ WCHAR name[256];
+ DWORD size = sizeof(name);
if (!pGetAddrInfoW || !pFreeAddrInfoW)
{
@@ -6320,6 +6322,8 @@ static void test_GetAddrInfoW(void)
return;
}
memset(&hint, 0, sizeof(ADDRINFOW));
+ name[0] = 0;
+ GetComputerNameExW( ComputerNamePhysicalDnsHostname, name, &size );
result = (ADDRINFOW *)0xdeadbeef;
WSASetLastError(0xdeadbeef);
@@ -6395,6 +6399,30 @@ static void test_GetAddrInfoW(void)
ok(WSAGetLastError() == 0, "expected 0, got %d\n", WSAGetLastError());
pFreeAddrInfoW(result);
+ /* try to get information from the computer name, result is the same
+ * as if requesting with an empty host name. */
+ ret = pGetAddrInfoW(name, NULL, NULL, &result);
+ ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
+ ok(result != NULL, "GetAddrInfoW failed\n");
+
+ ret = pGetAddrInfoW(empty, NULL, NULL, &result2);
+ ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
+ ok(result != NULL, "GetAddrInfoW failed\n");
+ compare_addrinfow(result, result2);
+ pFreeAddrInfoW(result);
+ pFreeAddrInfoW(result2);
+
+ ret = pGetAddrInfoW(name, empty, NULL, &result);
+ ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
+ ok(result != NULL, "GetAddrInfoW failed\n");
+
+ ret = pGetAddrInfoW(empty, empty, NULL, &result2);
+ ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
+ ok(result != NULL, "GetAddrInfoW failed\n");
+ compare_addrinfow(result, result2);
+ pFreeAddrInfoW(result);
+ pFreeAddrInfoW(result2);
+
result = (ADDRINFOW *)0xdeadbeef;
WSASetLastError(0xdeadbeef);
ret = pGetAddrInfoW(NULL, NULL, NULL, &result);
@@ -6475,6 +6503,8 @@ static void test_getaddrinfo(void)
{
int i, ret;
ADDRINFOA *result, *result2, *p, hint;
+ CHAR name[256];
+ DWORD size = sizeof(name);
if (!pgetaddrinfo || !pfreeaddrinfo)
{
@@ -6482,6 +6512,7 @@ static void test_getaddrinfo(void)
return;
}
memset(&hint, 0, sizeof(ADDRINFOA));
+ GetComputerNameExA( ComputerNamePhysicalDnsHostname, name, &size );
result = (ADDRINFOA *)0xdeadbeef;
WSASetLastError(0xdeadbeef);
@@ -6558,6 +6589,30 @@ static void test_getaddrinfo(void)
ok(WSAGetLastError() == 0, "expected 0, got %d\n", WSAGetLastError());
pfreeaddrinfo(result);
+ /* try to get information from the computer name, result is the same
+ * as if requesting with an empty host name. */
+ ret = pgetaddrinfo(name, NULL, NULL, &result);
+ ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+ ok(result != NULL, "GetAddrInfoW failed\n");
+
+ ret = pgetaddrinfo("", NULL, NULL, &result2);
+ ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+ ok(result != NULL, "GetAddrInfoW failed\n");
+ compare_addrinfo(result, result2);
+ pfreeaddrinfo(result);
+ pfreeaddrinfo(result2);
+
+ ret = pgetaddrinfo(name, "", NULL, &result);
+ ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+ ok(result != NULL, "GetAddrInfoW failed\n");
+
+ ret = pgetaddrinfo("", "", NULL, &result2);
+ ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+ ok(result != NULL, "GetAddrInfoW failed\n");
+ compare_addrinfo(result, result2);
+ pfreeaddrinfo(result);
+ pfreeaddrinfo(result2);
+
result = (ADDRINFOA *)0xdeadbeef;
WSASetLastError(0xdeadbeef);
ret = pgetaddrinfo("nxdomain.codeweavers.com", NULL, NULL, &result);
More information about the wine-patches
mailing list