iphlpapi: Implement GetUnicastIpAddressTable.

Signed-off-by: André Hentschel <nerv@dawncrow.de>
Signed-off-by: Bruno Jesus <bjesus@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
oldstable
André Hentschel 2017-03-27 22:48:00 +02:00 committed by Alexandre Julliard
parent 12a7b2b41c
commit eda35423f4
4 changed files with 141 additions and 1 deletions

View File

@ -148,7 +148,7 @@
@ stdcall GetUdpTable( ptr ptr long )
@ stub GetUdpTableFromStack
@ stdcall GetUnicastIpAddressEntry( ptr )
#@ stub GetUnicastIpAddressTable
@ stdcall GetUnicastIpAddressTable(long ptr)
@ stdcall GetUniDirectionalAdapterInfo( ptr ptr )
@ stdcall Icmp6CreateFile()
#@ stub Icmp6ParseReplies

View File

@ -2534,6 +2534,84 @@ DWORD WINAPI GetUnicastIpAddressEntry(MIB_UNICASTIPADDRESS_ROW *row)
return ret;
}
DWORD WINAPI GetUnicastIpAddressTable(ADDRESS_FAMILY family, MIB_UNICASTIPADDRESS_TABLE **table)
{
IP_ADAPTER_ADDRESSES *aa, *ptr;
MIB_UNICASTIPADDRESS_TABLE *data;
DWORD ret, count = 0;
ULONG size, flags;
TRACE("%u, %p\n", family, table);
if (!table || (family != WS_AF_INET && family != WS_AF_INET6 && family != WS_AF_UNSPEC))
return ERROR_INVALID_PARAMETER;
flags = GAA_FLAG_SKIP_ANYCAST |
GAA_FLAG_SKIP_MULTICAST |
GAA_FLAG_SKIP_DNS_SERVER |
GAA_FLAG_SKIP_FRIENDLY_NAME;
ret = GetAdaptersAddresses(family, flags, NULL, NULL, &size);
if (ret != ERROR_BUFFER_OVERFLOW)
return ret;
if (!(ptr = HeapAlloc(GetProcessHeap(), 0, size)))
return ERROR_OUTOFMEMORY;
if ((ret = GetAdaptersAddresses(family, flags, NULL, ptr, &size)))
{
HeapFree(GetProcessHeap(), 0, ptr);
return ret;
}
for (aa = ptr; aa; aa = aa->Next)
{
IP_ADAPTER_UNICAST_ADDRESS *ua = aa->FirstUnicastAddress;
while (ua)
{
count++;
ua = ua->Next;
}
}
if (!(data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data) + (count - 1) * sizeof(data->Table[0]))))
{
HeapFree(GetProcessHeap(), 0, ptr);
return ERROR_OUTOFMEMORY;
}
data->NumEntries = 0;
for (aa = ptr; aa; aa = aa->Next)
{
IP_ADAPTER_UNICAST_ADDRESS *ua = aa->FirstUnicastAddress;
while (ua)
{
MIB_UNICASTIPADDRESS_ROW *row = &data->Table[data->NumEntries];
memcpy(&row->Address, ua->Address.lpSockaddr, ua->Address.iSockaddrLength);
memcpy(&row->InterfaceLuid, &aa->Luid, sizeof(aa->Luid));
row->InterfaceIndex = aa->u.s.IfIndex;
row->PrefixOrigin = ua->PrefixOrigin;
row->SuffixOrigin = ua->SuffixOrigin;
row->ValidLifetime = ua->ValidLifetime;
row->PreferredLifetime = ua->PreferredLifetime;
row->OnLinkPrefixLength = ua->OnLinkPrefixLength;
row->SkipAsSource = 0;
row->DadState = ua->DadState;
if (row->Address.si_family == WS_AF_INET6)
row->ScopeId.u.Value = row->Address.Ipv6.sin6_scope_id;
else
row->ScopeId.u.Value = 0;
NtQuerySystemTime(&row->CreationTimeStamp);
data->NumEntries++;
ua = ua->Next;
}
}
HeapFree(GetProcessHeap(), 0, ptr);
*table = data;
return ret;
}
/******************************************************************
* GetUniDirectionalAdapterInfo (IPHLPAPI.@)
*

View File

@ -76,6 +76,7 @@ static DWORD (WINAPI *pGetUdpTable)(PMIB_UDPTABLE,PDWORD,BOOL);
static DWORD (WINAPI *pGetPerAdapterInfo)(ULONG,PIP_PER_ADAPTER_INFO,PULONG);
static DWORD (WINAPI *pGetAdaptersAddresses)(ULONG,ULONG,PVOID,PIP_ADAPTER_ADDRESSES,PULONG);
static DWORD (WINAPI *pGetUnicastIpAddressEntry)(MIB_UNICASTIPADDRESS_ROW*);
static DWORD (WINAPI *pGetUnicastIpAddressTable)(ADDRESS_FAMILY,MIB_UNICASTIPADDRESS_TABLE**);
static DWORD (WINAPI *pNotifyAddrChange)(PHANDLE,LPOVERLAPPED);
static BOOL (WINAPI *pCancelIPChangeNotify)(LPOVERLAPPED);
static DWORD (WINAPI *pGetExtendedTcpTable)(PVOID,PDWORD,BOOL,ULONG,TCP_TABLE_CLASS,ULONG);
@ -125,6 +126,7 @@ static void loadIPHlpApi(void)
pGetPerAdapterInfo = (void *)GetProcAddress(hLibrary, "GetPerAdapterInfo");
pGetAdaptersAddresses = (void *)GetProcAddress(hLibrary, "GetAdaptersAddresses");
pGetUnicastIpAddressEntry = (void *)GetProcAddress(hLibrary, "GetUnicastIpAddressEntry");
pGetUnicastIpAddressTable = (void *)GetProcAddress(hLibrary, "GetUnicastIpAddressTable");
pNotifyAddrChange = (void *)GetProcAddress(hLibrary, "NotifyAddrChange");
pCancelIPChangeNotify = (void *)GetProcAddress(hLibrary, "CancelIPChangeNotify");
pGetExtendedTcpTable = (void *)GetProcAddress(hLibrary, "GetExtendedTcpTable");
@ -2095,6 +2097,59 @@ static void test_GetUnicastIpAddressEntry(void)
HeapFree(GetProcessHeap(), 0, ptr);
}
static void test_GetUnicastIpAddressTable(void)
{
MIB_UNICASTIPADDRESS_TABLE *table;
DWORD ret;
ULONG i;
if (!pGetUnicastIpAddressTable)
{
win_skip( "GetUnicastIpAddressTable not available\n" );
return;
}
ret = pGetUnicastIpAddressTable(AF_UNSPEC, NULL);
ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
ret = pGetUnicastIpAddressTable(AF_BAN, &table);
ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
ret = pGetUnicastIpAddressTable(AF_INET, &table);
ok( ret == NO_ERROR, "got %u\n", ret );
trace("GetUnicastIpAddressTable(AF_INET): NumEntries %u\n", table->NumEntries);
pFreeMibTable(table);
ret = pGetUnicastIpAddressTable(AF_INET6, &table);
ok( ret == NO_ERROR, "got %u\n", ret );
trace("GetUnicastIpAddressTable(AF_INET6): NumEntries %u\n", table->NumEntries);
pFreeMibTable(table);
ret = pGetUnicastIpAddressTable(AF_UNSPEC, &table);
ok( ret == NO_ERROR, "got %u\n", ret );
trace("GetUnicastIpAddressTable(AF_UNSPEC): NumEntries %u\n", table->NumEntries);
for (i = 0; i < table->NumEntries && winetest_debug > 1; i++)
{
trace("Index %u:\n", i);
trace("Address.si_family: %u\n", table->Table[i].Address.si_family);
trace("InterfaceLuid.Info.Reserved: %u\n", table->Table[i].InterfaceLuid.Info.Reserved);
trace("InterfaceLuid.Info.NetLuidIndex: %u\n", table->Table[i].InterfaceLuid.Info.NetLuidIndex);
trace("InterfaceLuid.Info.IfType: %u\n", table->Table[i].InterfaceLuid.Info.IfType);
trace("InterfaceIndex: %u\n", table->Table[i].InterfaceIndex);
trace("PrefixOrigin: %u\n", table->Table[i].PrefixOrigin);
trace("SuffixOrigin: %u\n", table->Table[i].SuffixOrigin);
trace("ValidLifetime: %u seconds\n", table->Table[i].ValidLifetime);
trace("PreferredLifetime: %u seconds\n", table->Table[i].PreferredLifetime);
trace("OnLinkPrefixLength: %u\n", table->Table[i].OnLinkPrefixLength);
trace("SkipAsSource: %u\n", table->Table[i].SkipAsSource);
trace("DadState: %u\n", table->Table[i].DadState);
trace("ScopeId.Value: %u\n", table->Table[i].ScopeId.Value);
trace("CreationTimeStamp: %08x%08x\n", table->Table[i].CreationTimeStamp.HighPart, table->Table[i].CreationTimeStamp.LowPart);
}
pFreeMibTable(table);
}
START_TEST(iphlpapi)
{
@ -2120,6 +2175,7 @@ START_TEST(iphlpapi)
test_GetIfEntry2();
test_GetIfTable2();
test_GetUnicastIpAddressEntry();
test_GetUnicastIpAddressTable();
freeIPHlpApi();
}
}

View File

@ -145,6 +145,12 @@ typedef struct _MIB_UNICASTIPADDRESS_ROW
LARGE_INTEGER CreationTimeStamp;
} MIB_UNICASTIPADDRESS_ROW, *PMIB_UNICASTIPADDRESS_ROW;
typedef struct _MIB_UNICASTIPADDRESS_TABLE
{
ULONG NumEntries;
MIB_UNICASTIPADDRESS_ROW Table[1];
} MIB_UNICASTIPADDRESS_TABLE, *PMIB_UNICASTIPADDRESS_TABLE;
typedef VOID (WINAPI *PIPINTERFACE_CHANGE_CALLBACK)(PVOID, PMIB_IPINTERFACE_ROW,
MIB_NOTIFICATION_TYPE);
typedef VOID (WINAPI *PUNICAST_IPADDRESS_CHANGE_CALLBACK)(PVOID, PMIB_UNICASTIPADDRESS_ROW,