From: Timo Teräs Subject: iphlpapi: fix GetAdaptersAddresses return values Message-Id: <1293436581-14632-1-git-send-email-timo.teras@iki.fi> Date: Mon, 27 Dec 2010 09:56:21 +0200 We should return ERROR_BUFFER_OVERFLOW always if the buffer pointer is NULL (regardless of old buffer length). Additionally, while strictly not defined, Windows seems to always return the WCHAR members as valid pointers. This is easily verified by checking the output of the example code at: http://msdn.microsoft.com/en-us/library/aa365915%28v=VS.85%29.aspx In Windows it will not print (null) ever. Some programs seem to rely on this behaviour. One test case which does not work at all without these changes is available from: http://www.ipv6style.jp/files/ipv6/en/apps/20060320_2/GetAdaptersAddresses-EN.c This updates also the test cases to verify both changes, and additionally fixes a memory leak in the tests code. --- I also have a similar patch for wine stable branch (1.2.x tree). The iphlpapi has been changed a lot recently, so the fix is slightly different there. dlls/iphlpapi/iphlpapi_main.c | 5 ++++- dlls/iphlpapi/tests/iphlpapi.c | 21 ++++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c index d734c39..3995a17 100644 --- a/dlls/iphlpapi/iphlpapi_main.c +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -1115,10 +1115,13 @@ ULONG WINAPI GetAdaptersAddresses(ULONG family, ULONG flags, PVOID reserved, { if (aa->IfType != IF_TYPE_SOFTWARE_LOOPBACK && aa->OperStatus == IfOperStatusUp) aa->DnsSuffix = dnsSuffix; + else + aa->DnsSuffix = (WCHAR *)((BYTE*)dnsSuffix + dns_suffix_size - 2); } ret = ERROR_SUCCESS; } - if (*buflen < total_size) ret = ERROR_BUFFER_OVERFLOW; + else + ret = ERROR_BUFFER_OVERFLOW; *buflen = total_size; TRACE("num adapters %u\n", table->numIndexes); diff --git a/dlls/iphlpapi/tests/iphlpapi.c b/dlls/iphlpapi/tests/iphlpapi.c index 823e596..a747423 100644 --- a/dlls/iphlpapi/tests/iphlpapi.c +++ b/dlls/iphlpapi/tests/iphlpapi.c @@ -819,7 +819,7 @@ static void testWin2KFunctions(void) static void test_GetAdaptersAddresses(void) { ULONG ret, size; - IP_ADAPTER_ADDRESSES *aa; + IP_ADAPTER_ADDRESSES *aa, *ptr; IP_ADAPTER_UNICAST_ADDRESS *ua; if (!gGetAdaptersAddresses) @@ -831,17 +831,25 @@ static void test_GetAdaptersAddresses(void) ret = gGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, NULL); ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", ret); - size = 0; + /* size should be ignored and overwritten if buffer is NULL */ + size = 0x7fffffff; ret = gGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &size); ok(ret == ERROR_BUFFER_OVERFLOW, "expected ERROR_BUFFER_OVERFLOW, got %u\n", ret); if (ret != ERROR_BUFFER_OVERFLOW) return; - aa = HeapAlloc(GetProcessHeap(), 0, size); - ret = gGetAdaptersAddresses(AF_UNSPEC, 0, NULL, aa, &size); + ptr = HeapAlloc(GetProcessHeap(), 0, size); + ret = gGetAdaptersAddresses(AF_UNSPEC, 0, NULL, ptr, &size); ok(!ret, "expected ERROR_SUCCESS got %u\n", ret); - while (!ret && winetest_debug > 1 && aa) + for (aa = ptr; !ret && aa; aa = aa->Next) { + ok(aa->DnsSuffix != NULL, "DnsSuffix is not a valid pointer\n"); + ok(aa->Description != NULL, "Description is not a valid pointer\n"); + ok(aa->FriendlyName != NULL, "FriendlyName is not a valid pointer\n"); + + if (winetest_debug <= 1) + continue; + trace("Length: %u\n", S(U(*aa)).Length); trace("IfIndex: %u\n", S(U(*aa)).IfIndex); trace("Next: %p\n", aa->Next); @@ -877,9 +885,8 @@ static void test_GetAdaptersAddresses(void) trace("IfType: %u\n", aa->IfType); trace("OperStatus: %u\n", aa->OperStatus); trace("\n"); - aa = aa->Next; } - HeapFree(GetProcessHeap(), 0, aa); + HeapFree(GetProcessHeap(), 0, ptr); } START_TEST(iphlpapi)