diff --git a/dll/win32/iphlpapi/iphlpapi.spec b/dll/win32/iphlpapi/iphlpapi.spec index 76b5fb30d30..ee112c6c910 100644 --- a/dll/win32/iphlpapi/iphlpapi.spec +++ b/dll/win32/iphlpapi/iphlpapi.spec @@ -33,7 +33,7 @@ @ stdcall GetBestRoute( long long long ) @ stub GetBestRouteFromStack @ stdcall GetExtendedTcpTable( ptr ptr long long long long ) -@ stdcall -stub GetExtendedUdpTable( ptr ptr long long long long ) +@ stdcall GetExtendedUdpTable( ptr ptr long long long long ) @ stdcall GetFriendlyIfIndex( long ) @ stdcall GetIcmpStatistics( ptr ) @ stdcall GetIcmpStatisticsEx(ptr long) diff --git a/dll/win32/iphlpapi/iphlpapi_main.c b/dll/win32/iphlpapi/iphlpapi_main.c index a0e83aee4dd..d1333cbf479 100644 --- a/dll/win32/iphlpapi/iphlpapi_main.c +++ b/dll/win32/iphlpapi/iphlpapi_main.c @@ -1091,7 +1091,108 @@ DWORD WINAPI GetExtendedTcpTable(PVOID pTcpTable, PDWORD pdwSize, BOOL bOrder, U break; } - return ret; + return ret; +} + + +static int UdpTableSorter(const void *a, const void *b); + +/****************************************************************** + * GetExtendedUdpTable (IPHLPAPI.@) + * + * Get the table of UDP endpoints available to the application. + * + * PARAMS + * pUdpTable [Out] table struct with the filtered UDP endpoints available to application + * pdwSize [In/Out] estimated size of the structure returned in pUdpTable, in bytes + * bOrder [In] whether to order the table + * ulAf [in] version of IP used by the UDP endpoints + * TableClass [in] type of the UDP table structure from UDP_TABLE_CLASS + * Reserved [in] reserved - this value must be zero + * + * RETURNS + * Success: NO_ERROR + * Failure: either ERROR_INSUFFICIENT_BUFFER or ERROR_INVALID_PARAMETER + * + * NOTES + */ + +DWORD WINAPI GetExtendedUdpTable(PVOID pUdpTable, PDWORD pdwSize, BOOL bOrder, ULONG ulAf, UDP_TABLE_CLASS TableClass, ULONG Reserved) +{ + DWORD ret = NO_ERROR; + + if (!pdwSize) + { + return ERROR_INVALID_PARAMETER; + } + + if (ulAf != AF_INET) + { + UNIMPLEMENTED; + return ERROR_INVALID_PARAMETER; + } + + switch (TableClass) + { + case UDP_TABLE_BASIC: + { + PMIB_UDPTABLE pOurUdpTable = getUdpTable(); + PMIB_UDPTABLE pTheirUdpTable = pUdpTable; + + if (pOurUdpTable) + { + if (sizeof(DWORD) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW) > *pdwSize || !pTheirUdpTable) + { + *pdwSize = sizeof(DWORD) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW); + ret = ERROR_INSUFFICIENT_BUFFER; + } + else + { + memcpy(pTheirUdpTable, pOurUdpTable, sizeof(DWORD) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW_OWNER_PID)); + + if (bOrder) + qsort(pTheirUdpTable->table, pTheirUdpTable->dwNumEntries, + sizeof(MIB_UDPROW), UdpTableSorter); + } + + free(pOurUdpTable); + } + } + break; + + case UDP_TABLE_OWNER_PID: + { + PMIB_UDPTABLE_OWNER_PID pOurUdpTable = getOwnerUdpTable(); + PMIB_UDPTABLE_OWNER_PID pTheirUdpTable = pUdpTable; + + if (pOurUdpTable) + { + if (sizeof(DWORD) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW_OWNER_PID) > *pdwSize || !pTheirUdpTable) + { + *pdwSize = sizeof(DWORD) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW_OWNER_PID); + ret = ERROR_INSUFFICIENT_BUFFER; + } + else + { + memcpy(pTheirUdpTable, pOurUdpTable, sizeof(DWORD) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW_OWNER_PID)); + + if (bOrder) + qsort(pTheirUdpTable->table, pTheirUdpTable->dwNumEntries, + sizeof(MIB_UDPROW_OWNER_PID), UdpTableSorter); + } + + free(pOurUdpTable); + } + } + break; + + default: + UNIMPLEMENTED; + ret = ERROR_INVALID_PARAMETER; + break; + } + + return ret; } diff --git a/dll/win32/iphlpapi/ipstats.h b/dll/win32/iphlpapi/ipstats.h index 1fd51574c30..da49d2b1d3f 100644 --- a/dll/win32/iphlpapi/ipstats.h +++ b/dll/win32/iphlpapi/ipstats.h @@ -97,6 +97,11 @@ DWORD getNumUdpEntries(void); */ PMIB_UDPTABLE getUdpTable(void); +/* Allocates and returns to you the UDP state table with owner PID, + * or NULL if it can't allocate enough memory. free() the returned table. + */ +PMIB_UDPTABLE_OWNER_PID getOwnerUdpTable(void); + /* Returns the number of entries in the TCP state table. */ DWORD getNumTcpEntries(void);