Module: wine Branch: master Commit: fa172e1ca6d91d0ad2eb9ba442ff369bd4a7646a URL: http://source.winehq.org/git/wine.git/?a=commit;h=fa172e1ca6d91d0ad2eb9ba442...
Author: Bruno Jesus 00cpxxx@gmail.com Date: Wed Nov 30 04:48:26 2016 -0200
ws2_32: Add IDN resolution support to GetAddrInfoW.
Signed-off-by: Bruno Jesus 00cpxxx@gmail.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ws2_32/socket.c | 52 +++++++++++++++++++++++++++++++++++++++--------- dlls/ws2_32/tests/sock.c | 4 ++-- 2 files changed, 45 insertions(+), 11 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 8510034..898c1eb 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -6743,25 +6743,56 @@ int WINAPI GetAddrInfoExW(const WCHAR *name, const WCHAR *servname, DWORD namesp */ int WINAPI GetAddrInfoW(LPCWSTR nodename, LPCWSTR servname, const ADDRINFOW *hints, PADDRINFOW *res) { - int ret, len; + int ret = EAI_MEMORY, len, i; char *nodenameA = NULL, *servnameA = NULL; struct WS_addrinfo *resA, *hintsA = NULL; + WCHAR *local_nodenameW = (WCHAR *)nodename; + + TRACE("nodename %s, servname %s, hints %p, result %p\n", + debugstr_w(nodename), debugstr_w(servname), hints, res);
*res = 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); + /* Is this an IDN? Most likely if any char is above the Ascii table, this + * is the simplest validation possible, further validation will be done by + * the native getaddrinfo() */ + for (i = 0; nodename[i]; i++) + { + if (nodename[i] > 'z') + break; + } + if (nodename[i]) + { + if (hints && (hints->ai_flags & WS_AI_DISABLE_IDN_ENCODING)) + { + /* Name requires conversion but it was disabled */ + ret = WSAHOST_NOT_FOUND; + WSASetLastError(ret); + goto end; + } + + len = IdnToAscii(0, nodename, -1, NULL, 0); + if (!len) + { + ERR("Failed to convert %s to punycode\n", debugstr_w(nodename)); + ret = EAI_FAIL; + goto end; + } + if (!(local_nodenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) goto end; + IdnToAscii(0, nodename, -1, local_nodenameW, len); + } + } + if (local_nodenameW) + { + len = WideCharToMultiByte(CP_ACP, 0, local_nodenameW, -1, NULL, 0, NULL, NULL); + if (!(nodenameA = HeapAlloc(GetProcessHeap(), 0, len))) goto end; + WideCharToMultiByte(CP_ACP, 0, local_nodenameW, -1, nodenameA, len, NULL, NULL); } if (servname) { len = WideCharToMultiByte(CP_ACP, 0, servname, -1, NULL, 0, NULL, NULL); - if (!(servnameA = HeapAlloc(GetProcessHeap(), 0, len))) - { - HeapFree(GetProcessHeap(), 0, nodenameA); - return EAI_MEMORY; - } + if (!(servnameA = HeapAlloc(GetProcessHeap(), 0, len))) goto end; WideCharToMultiByte(CP_ACP, 0, servname, -1, servnameA, len, NULL, NULL); }
@@ -6775,6 +6806,9 @@ int WINAPI GetAddrInfoW(LPCWSTR nodename, LPCWSTR servname, const ADDRINFOW *hin WS_freeaddrinfo(resA); }
+end: + if (local_nodenameW != nodename) + HeapFree(GetProcessHeap(), 0, local_nodenameW); HeapFree(GetProcessHeap(), 0, nodenameA); HeapFree(GetProcessHeap(), 0, servnameA); return ret; diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 049213a..83a931e 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -7026,7 +7026,7 @@ static void test_GetAddrInfoW(void) win_skip("IDN resolution not supported in Win <= 7\n"); return; } -todo_wine { + ok(!ret, "got %d expected success\n", ret); ok(result2 != NULL, "got %p\n", result2); pFreeAddrInfoW(result2); @@ -7057,7 +7057,7 @@ todo_wine { ok(!ret, "got %d expected success\n", ret); ok(result2 != NULL, "got %p\n", result2); pFreeAddrInfoW(result2); -} + /* Disable IDN resolution and test again*/ hint.ai_family = AF_INET; hint.ai_socktype = 0;