Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53175
Commit 910d58520a6d75cada82d992757ca013099d9345 (iphlpapi: Return ERROR_NO_DATA from GetIpNetTable() if no entries are found.) introduced a regression in Roon application. It looks like the app doesn't tolerate an error return from GetIpNetTable() if there are active interfaces found. The blamed patch still looks correct to me per se, that is, if number of entries ends up being zero Windows returns ERROR_NO_DATA. However, number of entries is never zero on Windows if there is any network adapter.
There are two things why Windows always has some arp entries and we do not: 1. We currently parse /proc/net/arp line on Linux a bit wrong and end up getting no entries from there (patch 1 fixes that); 2. With the patch patch 1 there Roon seems happy (at least as far as I could test it right at start), at least as long we have an entry in /proc/sys/net (which might not be necessarily the case if there is, e. g., no actual network connection). But that breaks SCP: Secret Laboratory again the same way as before 910d58520a6d75cada82d992757ca013099d9345. It turns out the latter game depends on GetIpNetTable() returning at least 4 entries when returning success (for some reason, I am not sure why but I think I saw that quite clearly). And both apps can actually work reliably on Windows as there are always at least 4 static arp entries if there is any network adaptere configured at all.
There are "224.0.0.22" and "239.255.255.250" static arp multicast entries which are always there for any interface on Windows, including loopback (starting from Win10; earlier versions might be missing "239.255.255.250" but have "224.0.0.22"). So adding those like on Windows should hopefully fix all those cases.
-- v3: iphlpapi: Sort by adapter index first in GetIpNetTable(). iphlpapi: Correctly index dynamic data array. nsiproxy.sys: Strip trailing end of line for iface name on Linux.
This merge request was approved by Alexandre Julliard.
From: Paul Gofman pgofman@codeweavers.com
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/nsiproxy.sys/ip.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/dlls/nsiproxy.sys/ip.c b/dlls/nsiproxy.sys/ip.c index 27344756580..79f3bd80bfe 100644 --- a/dlls/nsiproxy.sys/ip.c +++ b/dlls/nsiproxy.sys/ip.c @@ -1014,7 +1014,7 @@ static NTSTATUS ipv4_neighbour_enumerate_all( void *key_data, UINT key_size, voi
#ifdef __linux__ { - char buf[512], *ptr; + char buf[512], *ptr, *s; UINT atf_flags; FILE *fp;
@@ -1053,6 +1053,9 @@ static NTSTATUS ipv4_neighbour_enumerate_all( void *key_data, UINT key_size, voi while (*ptr && !isspace( *ptr )) ptr++; /* mask (skip) */ while (*ptr && isspace( *ptr )) ptr++;
+ s = ptr; + while (*s && !isspace(*s)) s++; + *s = 0; if (!convert_unix_name_to_luid( ptr, &entry.luid )) continue; if (!convert_luid_to_index( &entry.luid, &entry.if_index )) continue;
From: Paul Gofman pgofman@codeweavers.com
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/iphlpapi/iphlpapi_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c index 33b12361d70..5d904d875fe 100644 --- a/dlls/iphlpapi/iphlpapi_main.c +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -2344,7 +2344,8 @@ DWORD WINAPI GetIpNetTable( MIB_IPNETTABLE *table, ULONG *size, BOOL sort ) memset( row->bPhysAddr + row->dwPhysAddrLen, 0, sizeof(row->bPhysAddr) - row->dwPhysAddrLen ); row->dwAddr = keys[i].addr.s_addr; - switch (dyn->state) + + switch (dyn[i].state) { case NlnsUnreachable: case NlnsIncomplete:
From: Paul Gofman pgofman@codeweavers.com
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/iphlpapi/iphlpapi_main.c | 3 +++ dlls/iphlpapi/tests/iphlpapi.c | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c index 5d904d875fe..fc8ee3d2040 100644 --- a/dlls/iphlpapi/iphlpapi_main.c +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -2282,6 +2282,9 @@ err: static int ipnetrow_cmp( const void *a, const void *b ) { const MIB_IPNETROW *rowA = a, *rowB = b; + + if (rowA->dwIndex != rowB->dwIndex) return DWORD_cmp( rowA->dwIndex, rowB->dwIndex ); + return DWORD_cmp(RtlUlongByteSwap( rowA->dwAddr ), RtlUlongByteSwap( rowB->dwAddr )); }
diff --git a/dlls/iphlpapi/tests/iphlpapi.c b/dlls/iphlpapi/tests/iphlpapi.c index 09d02b02f08..84d5143ba8e 100644 --- a/dlls/iphlpapi/tests/iphlpapi.c +++ b/dlls/iphlpapi/tests/iphlpapi.c @@ -371,6 +371,7 @@ static void testGetIpNetTable(void) { DWORD apiReturn; ULONG dwSize = 0; + unsigned int i;
apiReturn = GetIpNetTable(NULL, NULL, FALSE); if (apiReturn == ERROR_NOT_SUPPORTED) { @@ -390,11 +391,23 @@ static void testGetIpNetTable(void) PMIB_IPNETTABLE buf = HeapAlloc(GetProcessHeap(), 0, dwSize);
memset(buf, 0xcc, dwSize); - apiReturn = GetIpNetTable(buf, &dwSize, FALSE); + apiReturn = GetIpNetTable(buf, &dwSize, TRUE); ok((apiReturn == NO_ERROR && buf->dwNumEntries) || (apiReturn == ERROR_NO_DATA && !buf->dwNumEntries), "got apiReturn %lu, dwSize %lu, buf->dwNumEntries %lu.\n", apiReturn, dwSize, buf->dwNumEntries);
+ if (apiReturn == NO_ERROR) + { + for (i = 0; i < buf->dwNumEntries - 1; ++i) + { + ok( buf->table[i].dwIndex <= buf->table[i + 1].dwIndex, + "Entries are not sorted by index, i %u.\n", i ); + if (buf->table[i].dwIndex == buf->table[i + 1].dwIndex) + ok(ntohl(buf->table[i].dwAddr) <= ntohl(buf->table[i + 1].dwAddr), + "Entries are not sorted by address, i %u.\n", i ); + } + } + if (apiReturn == NO_ERROR && winetest_debug > 1) { DWORD i, j;