iphlpapi: Implement GetExtendedUdpTable.
This commit is contained in:
parent
bde5156876
commit
18ba68ea62
|
@ -81,7 +81,7 @@
|
||||||
@ stub GetBestRouteFromStack
|
@ stub GetBestRouteFromStack
|
||||||
#@ stub GetCurrentThreadCompartmentId
|
#@ stub GetCurrentThreadCompartmentId
|
||||||
@ stdcall GetExtendedTcpTable( ptr ptr long long long long )
|
@ stdcall GetExtendedTcpTable( ptr ptr long long long long )
|
||||||
#@ stub GetExtendedUdpTable
|
@ stdcall GetExtendedUdpTable( ptr ptr long long long long )
|
||||||
@ stdcall GetFriendlyIfIndex( long )
|
@ stdcall GetFriendlyIfIndex( long )
|
||||||
#@ stub GetIcmpStatisticsEx
|
#@ stub GetIcmpStatisticsEx
|
||||||
@ stdcall GetIcmpStatistics( ptr )
|
@ stdcall GetIcmpStatistics( ptr )
|
||||||
|
|
|
@ -1917,31 +1917,46 @@ DWORD WINAPI GetExtendedTcpTable(PVOID pTcpTable, PDWORD pdwSize, BOOL bOrder,
|
||||||
*/
|
*/
|
||||||
DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
|
DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
|
||||||
{
|
{
|
||||||
DWORD ret;
|
return GetExtendedUdpTable(pUdpTable, pdwSize, bOrder, AF_INET, UDP_TABLE_BASIC, 0);
|
||||||
PMIB_UDPTABLE table;
|
}
|
||||||
|
|
||||||
TRACE("pUdpTable %p, pdwSize %p, bOrder %d\n", pUdpTable, pdwSize, bOrder);
|
/******************************************************************
|
||||||
|
* GetExtendedUdpTable (IPHLPAPI.@)
|
||||||
|
*/
|
||||||
|
DWORD WINAPI GetExtendedUdpTable(PVOID pUdpTable, PDWORD pdwSize, BOOL bOrder,
|
||||||
|
ULONG ulAf, UDP_TABLE_CLASS TableClass, ULONG Reserved)
|
||||||
|
{
|
||||||
|
DWORD ret, size;
|
||||||
|
void *table;
|
||||||
|
|
||||||
|
TRACE("pUdpTable %p, pdwSize %p, bOrder %d, ulAf %u, TableClass %u, Reserved %u\n",
|
||||||
|
pUdpTable, pdwSize, bOrder, ulAf, TableClass, Reserved);
|
||||||
|
|
||||||
if (!pdwSize) return ERROR_INVALID_PARAMETER;
|
if (!pdwSize) return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
ret = AllocateAndGetUdpTableFromStack( &table, bOrder, GetProcessHeap(), 0 );
|
if (ulAf != AF_INET ||
|
||||||
if (!ret) {
|
(TableClass != UDP_TABLE_BASIC && TableClass != UDP_TABLE_OWNER_PID))
|
||||||
DWORD size = FIELD_OFFSET( MIB_UDPTABLE, table[table->dwNumEntries] );
|
{
|
||||||
if (!pUdpTable || *pdwSize < size) {
|
FIXME("ulAf = %u, TableClass = %u not supported\n", ulAf, TableClass);
|
||||||
|
return ERROR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
if ((ret = build_udp_table(TableClass, &table, bOrder, GetProcessHeap(), 0, &size)))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (!pUdpTable || *pdwSize < size)
|
||||||
|
{
|
||||||
*pdwSize = size;
|
*pdwSize = size;
|
||||||
ret = ERROR_INSUFFICIENT_BUFFER;
|
ret = ERROR_INSUFFICIENT_BUFFER;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
*pdwSize = size;
|
*pdwSize = size;
|
||||||
memcpy(pUdpTable, table, size);
|
memcpy(pUdpTable, table, size);
|
||||||
}
|
}
|
||||||
HeapFree(GetProcessHeap(), 0, table);
|
HeapFree(GetProcessHeap(), 0, table);
|
||||||
}
|
|
||||||
TRACE("returning %d\n", ret);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* GetUniDirectionalAdapterInfo (IPHLPAPI.@)
|
* GetUniDirectionalAdapterInfo (IPHLPAPI.@)
|
||||||
*
|
*
|
||||||
|
|
|
@ -1433,203 +1433,6 @@ done:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static MIB_UDPTABLE *append_udp_row( HANDLE heap, DWORD flags, MIB_UDPTABLE *table,
|
|
||||||
DWORD *count, const MIB_UDPROW *row )
|
|
||||||
{
|
|
||||||
if (table->dwNumEntries >= *count)
|
|
||||||
{
|
|
||||||
MIB_UDPTABLE *new_table;
|
|
||||||
DWORD new_count = table->dwNumEntries * 2;
|
|
||||||
|
|
||||||
if (!(new_table = HeapReAlloc( heap, flags, table, FIELD_OFFSET(MIB_UDPTABLE, table[new_count] ))))
|
|
||||||
{
|
|
||||||
HeapFree( heap, 0, table );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
*count = new_count;
|
|
||||||
table = new_table;
|
|
||||||
}
|
|
||||||
memcpy( &table->table[table->dwNumEntries++], row, sizeof(*row) );
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int compare_udp_rows(const void *a, const void *b)
|
|
||||||
{
|
|
||||||
const MIB_UDPROW *rowA = a;
|
|
||||||
const MIB_UDPROW *rowB = b;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if ((ret = rowA->dwLocalAddr - rowB->dwLocalAddr) != 0) return ret;
|
|
||||||
return rowA->dwLocalPort - rowB->dwLocalPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************
|
|
||||||
* AllocateAndGetUdpTableFromStack (IPHLPAPI.@)
|
|
||||||
*
|
|
||||||
* Get the UDP listener table.
|
|
||||||
* Like GetUdpTable(), but allocate the returned table from heap.
|
|
||||||
*
|
|
||||||
* PARAMS
|
|
||||||
* ppUdpTable [Out] pointer into which the MIB_UDPTABLE is
|
|
||||||
* allocated and returned.
|
|
||||||
* bOrder [In] whether to sort the table
|
|
||||||
* heap [In] heap from which the table is allocated
|
|
||||||
* flags [In] flags to HeapAlloc
|
|
||||||
*
|
|
||||||
* RETURNS
|
|
||||||
* ERROR_INVALID_PARAMETER if ppUdpTable is NULL, whatever GetUdpTable()
|
|
||||||
* returns otherwise.
|
|
||||||
*/
|
|
||||||
DWORD WINAPI AllocateAndGetUdpTableFromStack(PMIB_UDPTABLE *ppUdpTable, BOOL bOrder,
|
|
||||||
HANDLE heap, DWORD flags)
|
|
||||||
{
|
|
||||||
MIB_UDPTABLE *table;
|
|
||||||
MIB_UDPROW row;
|
|
||||||
DWORD ret = NO_ERROR, count = 16;
|
|
||||||
|
|
||||||
TRACE("table %p, bOrder %d, heap %p, flags 0x%08x\n", ppUdpTable, bOrder, heap, flags);
|
|
||||||
|
|
||||||
if (!ppUdpTable) return ERROR_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
if (!(table = HeapAlloc( heap, flags, FIELD_OFFSET(MIB_UDPTABLE, table[count] ))))
|
|
||||||
return ERROR_OUTOFMEMORY;
|
|
||||||
|
|
||||||
table->dwNumEntries = 0;
|
|
||||||
|
|
||||||
#ifdef __linux__
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
if ((fp = fopen("/proc/net/udp", "r")))
|
|
||||||
{
|
|
||||||
char buf[512], *ptr;
|
|
||||||
DWORD dummy;
|
|
||||||
|
|
||||||
/* skip header line */
|
|
||||||
ptr = fgets(buf, sizeof(buf), fp);
|
|
||||||
while ((ptr = fgets(buf, sizeof(buf), fp)))
|
|
||||||
{
|
|
||||||
if (sscanf( ptr, "%u: %x:%x", &dummy, &row.dwLocalAddr, &row.dwLocalPort ) != 3)
|
|
||||||
continue;
|
|
||||||
row.dwLocalPort = htons( row.dwLocalPort );
|
|
||||||
if (!(table = append_udp_row( heap, flags, table, &count, &row )))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
else ret = ERROR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
#elif defined(HAVE_SYS_TIHDR_H) && defined(T_OPTMGMT_ACK)
|
|
||||||
{
|
|
||||||
void *data;
|
|
||||||
int fd, len;
|
|
||||||
mib2_udpEntry_t *entry;
|
|
||||||
|
|
||||||
if ((fd = open_streams_mib( "udp" )) != -1)
|
|
||||||
{
|
|
||||||
if ((data = read_mib_entry( fd, MIB2_UDP, MIB2_UDP_ENTRY, &len )))
|
|
||||||
{
|
|
||||||
for (entry = data; (char *)(entry + 1) <= (char *)data + len; entry++)
|
|
||||||
{
|
|
||||||
row.dwLocalAddr = entry->udpLocalAddress;
|
|
||||||
row.dwLocalPort = htons( entry->udpLocalPort );
|
|
||||||
if (!(table = append_udp_row( heap, flags, table, &count, &row ))) break;
|
|
||||||
}
|
|
||||||
HeapFree( GetProcessHeap(), 0, data );
|
|
||||||
}
|
|
||||||
close( fd );
|
|
||||||
}
|
|
||||||
else ret = ERROR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
#elif defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_STRUCT_XINPGEN)
|
|
||||||
{
|
|
||||||
size_t Len = 0;
|
|
||||||
char *Buf = NULL;
|
|
||||||
struct xinpgen *pXIG, *pOrigXIG;
|
|
||||||
|
|
||||||
if (sysctlbyname ("net.inet.udp.pcblist", NULL, &Len, NULL, 0) < 0)
|
|
||||||
{
|
|
||||||
ERR ("Failure to read net.inet.udp.pcblist via sysctlbyname!\n");
|
|
||||||
ret = ERROR_NOT_SUPPORTED;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
Buf = HeapAlloc (GetProcessHeap (), 0, Len);
|
|
||||||
if (!Buf)
|
|
||||||
{
|
|
||||||
ret = ERROR_OUTOFMEMORY;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sysctlbyname ("net.inet.udp.pcblist", Buf, &Len, NULL, 0) < 0)
|
|
||||||
{
|
|
||||||
ERR ("Failure to read net.inet.udp.pcblist via sysctlbyname!\n");
|
|
||||||
ret = ERROR_NOT_SUPPORTED;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Might be nothing here; first entry is just a header it seems */
|
|
||||||
if (Len <= sizeof (struct xinpgen)) goto done;
|
|
||||||
|
|
||||||
pOrigXIG = (struct xinpgen *)Buf;
|
|
||||||
pXIG = pOrigXIG;
|
|
||||||
|
|
||||||
for (pXIG = (struct xinpgen *)((char *)pXIG + pXIG->xig_len);
|
|
||||||
pXIG->xig_len > sizeof (struct xinpgen);
|
|
||||||
pXIG = (struct xinpgen *)((char *)pXIG + pXIG->xig_len))
|
|
||||||
{
|
|
||||||
struct inpcb *pINData;
|
|
||||||
struct xsocket *pSockData;
|
|
||||||
|
|
||||||
pINData = &((struct xinpcb *)pXIG)->xi_inp;
|
|
||||||
pSockData = &((struct xinpcb *)pXIG)->xi_socket;
|
|
||||||
|
|
||||||
/* Ignore sockets for other protocols */
|
|
||||||
if (pSockData->xso_protocol != IPPROTO_UDP)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Ignore PCBs that were freed while generating the data */
|
|
||||||
if (pINData->inp_gencnt > pOrigXIG->xig_gen)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* we're only interested in IPv4 addresses */
|
|
||||||
if (!(pINData->inp_vflag & INP_IPV4) ||
|
|
||||||
(pINData->inp_vflag & INP_IPV6))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* If all 0's, skip it */
|
|
||||||
if (!pINData->inp_laddr.s_addr &&
|
|
||||||
!pINData->inp_lport)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Fill in structure details */
|
|
||||||
row.dwLocalAddr = pINData->inp_laddr.s_addr;
|
|
||||||
row.dwLocalPort = pINData->inp_lport;
|
|
||||||
if (!(table = append_udp_row( heap, flags, table, &count, &row ))) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
|
||||||
HeapFree (GetProcessHeap (), 0, Buf);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
FIXME( "not implemented\n" );
|
|
||||||
ret = ERROR_NOT_SUPPORTED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!table) return ERROR_OUTOFMEMORY;
|
|
||||||
if (!ret)
|
|
||||||
{
|
|
||||||
if (bOrder && table->dwNumEntries)
|
|
||||||
qsort( table->table, table->dwNumEntries, sizeof(row), compare_udp_rows );
|
|
||||||
*ppUdpTable = table;
|
|
||||||
}
|
|
||||||
else HeapFree( heap, flags, table );
|
|
||||||
TRACE( "returning ret %u table %p\n", ret, table );
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static DWORD get_tcp_table_sizes( TCP_TABLE_CLASS class, DWORD row_count, DWORD *row_size )
|
static DWORD get_tcp_table_sizes( TCP_TABLE_CLASS class, DWORD row_count, DWORD *row_size )
|
||||||
{
|
{
|
||||||
DWORD table_size;
|
DWORD table_size;
|
||||||
|
@ -2015,3 +1818,244 @@ DWORD WINAPI AllocateAndGetTcpTableFromStack( PMIB_TCPTABLE *ppTcpTable, BOOL bO
|
||||||
if (!ppTcpTable) return ERROR_INVALID_PARAMETER;
|
if (!ppTcpTable) return ERROR_INVALID_PARAMETER;
|
||||||
return build_tcp_table( TCP_TABLE_BASIC_ALL, (void **)ppTcpTable, bOrder, heap, flags, NULL );
|
return build_tcp_table( TCP_TABLE_BASIC_ALL, (void **)ppTcpTable, bOrder, heap, flags, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DWORD get_udp_table_sizes( UDP_TABLE_CLASS class, DWORD row_count, DWORD *row_size )
|
||||||
|
{
|
||||||
|
DWORD table_size;
|
||||||
|
|
||||||
|
switch (class)
|
||||||
|
{
|
||||||
|
case UDP_TABLE_BASIC:
|
||||||
|
{
|
||||||
|
table_size = FIELD_OFFSET(MIB_UDPTABLE, table[row_count]);
|
||||||
|
if (row_size) *row_size = sizeof(MIB_UDPROW);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UDP_TABLE_OWNER_PID:
|
||||||
|
{
|
||||||
|
table_size = FIELD_OFFSET(MIB_UDPTABLE_OWNER_PID, table[row_count]);
|
||||||
|
if (row_size) *row_size = sizeof(MIB_UDPROW_OWNER_PID);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
ERR("unhandled class %u\n", class);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return table_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MIB_UDPTABLE *append_udp_row( UDP_TABLE_CLASS class, HANDLE heap, DWORD flags,
|
||||||
|
MIB_UDPTABLE *table, DWORD *count,
|
||||||
|
const MIB_UDPROW_OWNER_PID *row, DWORD row_size )
|
||||||
|
{
|
||||||
|
if (table->dwNumEntries >= *count)
|
||||||
|
{
|
||||||
|
MIB_UDPTABLE *new_table;
|
||||||
|
DWORD new_count = table->dwNumEntries * 2, new_table_size;
|
||||||
|
|
||||||
|
new_table_size = get_udp_table_sizes( class, new_count, NULL );
|
||||||
|
if (!(new_table = HeapReAlloc( heap, flags, table, new_table_size )))
|
||||||
|
{
|
||||||
|
HeapFree( heap, 0, table );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*count = new_count;
|
||||||
|
table = new_table;
|
||||||
|
}
|
||||||
|
memcpy( (char *)table->table + (table->dwNumEntries * row_size), row, row_size );
|
||||||
|
table->dwNumEntries++;
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int compare_udp_rows(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const MIB_UDPROW *rowA = a;
|
||||||
|
const MIB_UDPROW *rowB = b;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((ret = rowA->dwLocalAddr - rowB->dwLocalAddr) != 0) return ret;
|
||||||
|
return rowA->dwLocalPort - rowB->dwLocalPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD build_udp_table( UDP_TABLE_CLASS class, void **tablep, BOOL order, HANDLE heap, DWORD flags,
|
||||||
|
DWORD *size )
|
||||||
|
{
|
||||||
|
MIB_UDPTABLE *table;
|
||||||
|
MIB_UDPROW_OWNER_PID row;
|
||||||
|
DWORD ret = NO_ERROR, count = 16, table_size, row_size;
|
||||||
|
|
||||||
|
if (!(table_size = get_udp_table_sizes( class, count, &row_size )))
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
if (!(table = HeapAlloc( heap, flags, table_size )))
|
||||||
|
return ERROR_OUTOFMEMORY;
|
||||||
|
|
||||||
|
table->dwNumEntries = 0;
|
||||||
|
memset( &row, 0, sizeof(row) );
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if ((fp = fopen( "/proc/net/udp", "r" )))
|
||||||
|
{
|
||||||
|
char buf[512], *ptr;
|
||||||
|
struct pid_map *map = NULL;
|
||||||
|
unsigned int dummy, num_entries = 0;
|
||||||
|
int inode;
|
||||||
|
|
||||||
|
if (class == UDP_TABLE_OWNER_PID) map = get_pid_map( &num_entries );
|
||||||
|
|
||||||
|
/* skip header line */
|
||||||
|
ptr = fgets( buf, sizeof(buf), fp );
|
||||||
|
while ((ptr = fgets( buf, sizeof(buf), fp )))
|
||||||
|
{
|
||||||
|
if (sscanf( ptr, "%u: %x:%x %*s %*s %*s %*s %*s %*s %*s %d", &dummy,
|
||||||
|
&row.dwLocalAddr, &row.dwLocalPort, &inode ) != 4)
|
||||||
|
continue;
|
||||||
|
row.dwLocalPort = htons( row.dwLocalPort );
|
||||||
|
if (class == UDP_TABLE_OWNER_PID)
|
||||||
|
row.dwOwningPid = find_owning_pid( map, num_entries, inode );
|
||||||
|
if (!(table = append_udp_row( class, heap, flags, table, &count, &row, row_size )))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
HeapFree( GetProcessHeap(), 0, map );
|
||||||
|
fclose( fp );
|
||||||
|
}
|
||||||
|
else ret = ERROR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
#elif defined(HAVE_SYS_TIHDR_H) && defined(T_OPTMGMT_ACK)
|
||||||
|
{
|
||||||
|
void *data;
|
||||||
|
int fd, len;
|
||||||
|
mib2_udpEntry_t *entry;
|
||||||
|
|
||||||
|
if ((fd = open_streams_mib( "udp" )) != -1)
|
||||||
|
{
|
||||||
|
if ((data = read_mib_entry( fd, MIB2_UDP, MIB2_UDP_ENTRY, &len )))
|
||||||
|
{
|
||||||
|
for (entry = data; (char *)(entry + 1) <= (char *)data + len; entry++)
|
||||||
|
{
|
||||||
|
row.dwLocalAddr = entry->udpLocalAddress;
|
||||||
|
row.dwLocalPort = htons( entry->udpLocalPort );
|
||||||
|
if (!(table = append_udp_row( class, heap, flags, table, &count, &row, row_size ))) break;
|
||||||
|
}
|
||||||
|
HeapFree( GetProcessHeap(), 0, data );
|
||||||
|
}
|
||||||
|
close( fd );
|
||||||
|
}
|
||||||
|
else ret = ERROR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
#elif defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_STRUCT_XINPGEN)
|
||||||
|
{
|
||||||
|
size_t Len = 0;
|
||||||
|
char *Buf = NULL;
|
||||||
|
struct xinpgen *pXIG, *pOrigXIG;
|
||||||
|
|
||||||
|
if (sysctlbyname ("net.inet.udp.pcblist", NULL, &Len, NULL, 0) < 0)
|
||||||
|
{
|
||||||
|
ERR ("Failure to read net.inet.udp.pcblist via sysctlbyname!\n");
|
||||||
|
ret = ERROR_NOT_SUPPORTED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buf = HeapAlloc (GetProcessHeap (), 0, Len);
|
||||||
|
if (!Buf)
|
||||||
|
{
|
||||||
|
ret = ERROR_OUTOFMEMORY;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sysctlbyname ("net.inet.udp.pcblist", Buf, &Len, NULL, 0) < 0)
|
||||||
|
{
|
||||||
|
ERR ("Failure to read net.inet.udp.pcblist via sysctlbyname!\n");
|
||||||
|
ret = ERROR_NOT_SUPPORTED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Might be nothing here; first entry is just a header it seems */
|
||||||
|
if (Len <= sizeof (struct xinpgen)) goto done;
|
||||||
|
|
||||||
|
pOrigXIG = (struct xinpgen *)Buf;
|
||||||
|
pXIG = pOrigXIG;
|
||||||
|
|
||||||
|
for (pXIG = (struct xinpgen *)((char *)pXIG + pXIG->xig_len);
|
||||||
|
pXIG->xig_len > sizeof (struct xinpgen);
|
||||||
|
pXIG = (struct xinpgen *)((char *)pXIG + pXIG->xig_len))
|
||||||
|
{
|
||||||
|
struct inpcb *pINData;
|
||||||
|
struct xsocket *pSockData;
|
||||||
|
|
||||||
|
pINData = &((struct xinpcb *)pXIG)->xi_inp;
|
||||||
|
pSockData = &((struct xinpcb *)pXIG)->xi_socket;
|
||||||
|
|
||||||
|
/* Ignore sockets for other protocols */
|
||||||
|
if (pSockData->xso_protocol != IPPROTO_UDP)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Ignore PCBs that were freed while generating the data */
|
||||||
|
if (pINData->inp_gencnt > pOrigXIG->xig_gen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* we're only interested in IPv4 addresses */
|
||||||
|
if (!(pINData->inp_vflag & INP_IPV4) ||
|
||||||
|
(pINData->inp_vflag & INP_IPV6))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* If all 0's, skip it */
|
||||||
|
if (!pINData->inp_laddr.s_addr &&
|
||||||
|
!pINData->inp_lport)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Fill in structure details */
|
||||||
|
row.dwLocalAddr = pINData->inp_laddr.s_addr;
|
||||||
|
row.dwLocalPort = pINData->inp_lport;
|
||||||
|
if (!(table = append_udp_row( class, heap, flags, table, &count, &row, row_size ))) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
HeapFree (GetProcessHeap (), 0, Buf);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
FIXME( "not implemented\n" );
|
||||||
|
ret = ERROR_NOT_SUPPORTED;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!table) return ERROR_OUTOFMEMORY;
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
if (order && table->dwNumEntries)
|
||||||
|
qsort( table->table, table->dwNumEntries, row_size, compare_udp_rows );
|
||||||
|
*tablep = table;
|
||||||
|
}
|
||||||
|
else HeapFree( heap, flags, table );
|
||||||
|
if (size) *size = get_udp_table_sizes( class, count, NULL );
|
||||||
|
TRACE( "returning ret %u table %p\n", ret, table );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* AllocateAndGetUdpTableFromStack (IPHLPAPI.@)
|
||||||
|
*
|
||||||
|
* Get the UDP listener table.
|
||||||
|
* Like GetUdpTable(), but allocate the returned table from heap.
|
||||||
|
*
|
||||||
|
* PARAMS
|
||||||
|
* ppUdpTable [Out] pointer into which the MIB_UDPTABLE is
|
||||||
|
* allocated and returned.
|
||||||
|
* bOrder [In] whether to sort the table
|
||||||
|
* heap [In] heap from which the table is allocated
|
||||||
|
* flags [In] flags to HeapAlloc
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* ERROR_INVALID_PARAMETER if ppUdpTable is NULL, whatever GetUdpTable()
|
||||||
|
* returns otherwise.
|
||||||
|
*/
|
||||||
|
DWORD WINAPI AllocateAndGetUdpTableFromStack(PMIB_UDPTABLE *ppUdpTable, BOOL bOrder,
|
||||||
|
HANDLE heap, DWORD flags)
|
||||||
|
{
|
||||||
|
TRACE("table %p, bOrder %d, heap %p, flags 0x%08x\n", ppUdpTable, bOrder, heap, flags);
|
||||||
|
|
||||||
|
if (!ppUdpTable) return ERROR_INVALID_PARAMETER;
|
||||||
|
return build_udp_table( UDP_TABLE_BASIC, (void **)ppUdpTable, bOrder, heap, flags, NULL );
|
||||||
|
}
|
||||||
|
|
|
@ -38,5 +38,6 @@ DWORD WINAPI AllocateAndGetIpNetTableFromStack(PMIB_IPNETTABLE *ppIpNetTable, BO
|
||||||
DWORD WINAPI AllocateAndGetIpForwardTableFromStack(PMIB_IPFORWARDTABLE *ppIpForwardTable, BOOL bOrder, HANDLE heap, DWORD flags) DECLSPEC_HIDDEN;
|
DWORD WINAPI AllocateAndGetIpForwardTableFromStack(PMIB_IPFORWARDTABLE *ppIpForwardTable, BOOL bOrder, HANDLE heap, DWORD flags) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
DWORD build_tcp_table(TCP_TABLE_CLASS, void **, BOOL, HANDLE, DWORD, DWORD *) DECLSPEC_HIDDEN;
|
DWORD build_tcp_table(TCP_TABLE_CLASS, void **, BOOL, HANDLE, DWORD, DWORD *) DECLSPEC_HIDDEN;
|
||||||
|
DWORD build_udp_table(UDP_TABLE_CLASS, void **, BOOL, HANDLE, DWORD, DWORD *) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
#endif /* ndef WINE_IPSTATS_H_ */
|
#endif /* ndef WINE_IPSTATS_H_ */
|
||||||
|
|
|
@ -71,6 +71,7 @@ static DWORD (WINAPI *pGetAdaptersAddresses)(ULONG,ULONG,PVOID,PIP_ADAPTER_ADDRE
|
||||||
static DWORD (WINAPI *pNotifyAddrChange)(PHANDLE,LPOVERLAPPED);
|
static DWORD (WINAPI *pNotifyAddrChange)(PHANDLE,LPOVERLAPPED);
|
||||||
static BOOL (WINAPI *pCancelIPChangeNotify)(LPOVERLAPPED);
|
static BOOL (WINAPI *pCancelIPChangeNotify)(LPOVERLAPPED);
|
||||||
static DWORD (WINAPI *pGetExtendedTcpTable)(PVOID,PDWORD,BOOL,ULONG,TCP_TABLE_CLASS,ULONG);
|
static DWORD (WINAPI *pGetExtendedTcpTable)(PVOID,PDWORD,BOOL,ULONG,TCP_TABLE_CLASS,ULONG);
|
||||||
|
static DWORD (WINAPI *pGetExtendedUdpTable)(PVOID,PDWORD,BOOL,ULONG,UDP_TABLE_CLASS,ULONG);
|
||||||
static DWORD (WINAPI *pSetTcpEntry)(PMIB_TCPROW);
|
static DWORD (WINAPI *pSetTcpEntry)(PMIB_TCPROW);
|
||||||
|
|
||||||
static void loadIPHlpApi(void)
|
static void loadIPHlpApi(void)
|
||||||
|
@ -102,6 +103,7 @@ static void loadIPHlpApi(void)
|
||||||
pNotifyAddrChange = (void *)GetProcAddress(hLibrary, "NotifyAddrChange");
|
pNotifyAddrChange = (void *)GetProcAddress(hLibrary, "NotifyAddrChange");
|
||||||
pCancelIPChangeNotify = (void *)GetProcAddress(hLibrary, "CancelIPChangeNotify");
|
pCancelIPChangeNotify = (void *)GetProcAddress(hLibrary, "CancelIPChangeNotify");
|
||||||
pGetExtendedTcpTable = (void *)GetProcAddress(hLibrary, "GetExtendedTcpTable");
|
pGetExtendedTcpTable = (void *)GetProcAddress(hLibrary, "GetExtendedTcpTable");
|
||||||
|
pGetExtendedUdpTable = (void *)GetProcAddress(hLibrary, "GetExtendedUdpTable");
|
||||||
pSetTcpEntry = (void *)GetProcAddress(hLibrary, "SetTcpEntry");
|
pSetTcpEntry = (void *)GetProcAddress(hLibrary, "SetTcpEntry");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1203,6 +1205,39 @@ static void test_GetExtendedTcpTable(void)
|
||||||
HeapFree( GetProcessHeap(), 0, table_pid );
|
HeapFree( GetProcessHeap(), 0, table_pid );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_GetExtendedUdpTable(void)
|
||||||
|
{
|
||||||
|
DWORD ret, size;
|
||||||
|
MIB_UDPTABLE *table;
|
||||||
|
MIB_UDPTABLE_OWNER_PID *table_pid;
|
||||||
|
|
||||||
|
if (!pGetExtendedUdpTable)
|
||||||
|
{
|
||||||
|
win_skip("GetExtendedUdpTable not available\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ret = pGetExtendedUdpTable( NULL, NULL, TRUE, AF_INET, UDP_TABLE_BASIC, 0 );
|
||||||
|
ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret );
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
ret = pGetExtendedUdpTable( NULL, &size, TRUE, AF_INET, UDP_TABLE_BASIC, 0 );
|
||||||
|
ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
|
||||||
|
|
||||||
|
table = HeapAlloc( GetProcessHeap(), 0, size );
|
||||||
|
ret = pGetExtendedUdpTable( table, &size, TRUE, AF_INET, UDP_TABLE_BASIC, 0 );
|
||||||
|
ok( ret == ERROR_SUCCESS, "got %u\n", ret );
|
||||||
|
HeapFree( GetProcessHeap(), 0, table );
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
ret = pGetExtendedUdpTable( NULL, &size, TRUE, AF_INET, UDP_TABLE_OWNER_PID, 0 );
|
||||||
|
ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret );
|
||||||
|
|
||||||
|
table_pid = HeapAlloc( GetProcessHeap(), 0, size );
|
||||||
|
ret = pGetExtendedUdpTable( table_pid, &size, TRUE, AF_INET, UDP_TABLE_OWNER_PID, 0 );
|
||||||
|
ok( ret == ERROR_SUCCESS, "got %u\n", ret );
|
||||||
|
HeapFree( GetProcessHeap(), 0, table_pid );
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(iphlpapi)
|
START_TEST(iphlpapi)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -1221,6 +1256,7 @@ START_TEST(iphlpapi)
|
||||||
testWin2KFunctions();
|
testWin2KFunctions();
|
||||||
test_GetAdaptersAddresses();
|
test_GetAdaptersAddresses();
|
||||||
test_GetExtendedTcpTable();
|
test_GetExtendedTcpTable();
|
||||||
|
test_GetExtendedUdpTable();
|
||||||
freeIPHlpApi();
|
freeIPHlpApi();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,9 @@ extern "C" {
|
||||||
DWORD WINAPI GetExtendedTcpTable(PVOID pTcpTable, PDWORD pdwSize, BOOL bOrder,
|
DWORD WINAPI GetExtendedTcpTable(PVOID pTcpTable, PDWORD pdwSize, BOOL bOrder,
|
||||||
ULONG ulAf, TCP_TABLE_CLASS TableClass, ULONG Reserved);
|
ULONG ulAf, TCP_TABLE_CLASS TableClass, ULONG Reserved);
|
||||||
|
|
||||||
|
DWORD WINAPI GetExtendedUdpTable(PVOID pUdpTable, PDWORD pdwSize, BOOL bOrder,
|
||||||
|
ULONG ulAf, UDP_TABLE_CLASS TableClass, ULONG Reserved);
|
||||||
|
|
||||||
DWORD WINAPI GetNumberOfInterfaces(PDWORD pdwNumIf);
|
DWORD WINAPI GetNumberOfInterfaces(PDWORD pdwNumIf);
|
||||||
|
|
||||||
DWORD WINAPI GetIfEntry(PMIB_IFROW pIfRow);
|
DWORD WINAPI GetIfEntry(PMIB_IFROW pIfRow);
|
||||||
|
|
|
@ -38,4 +38,11 @@ typedef enum _TCP_TABLE_CLASS
|
||||||
TCP_TABLE_OWNER_MODULE_ALL
|
TCP_TABLE_OWNER_MODULE_ALL
|
||||||
} TCP_TABLE_CLASS, *PTCP_TABLE_CLASS;
|
} TCP_TABLE_CLASS, *PTCP_TABLE_CLASS;
|
||||||
|
|
||||||
|
typedef enum _UDP_TABLE_CLASS
|
||||||
|
{
|
||||||
|
UDP_TABLE_BASIC,
|
||||||
|
UDP_TABLE_OWNER_PID,
|
||||||
|
UDP_TABLE_OWNER_MODULE
|
||||||
|
} UDP_TABLE_CLASS, *PUDP_TABLE_CLASS;
|
||||||
|
|
||||||
#endif /* WINE_IPRTRMIB_H__ */
|
#endif /* WINE_IPRTRMIB_H__ */
|
||||||
|
|
|
@ -39,6 +39,7 @@ typedef struct _MIB_UDPROW_OWNER_PID
|
||||||
{
|
{
|
||||||
DWORD dwLocalAddr;
|
DWORD dwLocalAddr;
|
||||||
DWORD dwLocalPort;
|
DWORD dwLocalPort;
|
||||||
|
DWORD dwOwningPid;
|
||||||
} MIB_UDPROW_OWNER_PID, *PMIB_UDPROW_OWNER_PID;
|
} MIB_UDPROW_OWNER_PID, *PMIB_UDPROW_OWNER_PID;
|
||||||
|
|
||||||
typedef struct _MIB_UDPTABLE_OWNER_PID
|
typedef struct _MIB_UDPTABLE_OWNER_PID
|
||||||
|
@ -47,7 +48,6 @@ typedef struct _MIB_UDPTABLE_OWNER_PID
|
||||||
MIB_UDPROW_OWNER_PID table[1];
|
MIB_UDPROW_OWNER_PID table[1];
|
||||||
} MIB_UDPTABLE_OWNER_PID, *PMIB_UDPTABLE_OWNER_PID;
|
} MIB_UDPTABLE_OWNER_PID, *PMIB_UDPTABLE_OWNER_PID;
|
||||||
|
|
||||||
|
|
||||||
/* UDP statistics */
|
/* UDP statistics */
|
||||||
|
|
||||||
typedef struct _MIB_UDPSTATS
|
typedef struct _MIB_UDPSTATS
|
||||||
|
|
Loading…
Reference in New Issue