[1/2] iphlpapi: Implement GetExtendedUdpTable.

Hans Leidekker hans at codeweavers.com
Fri Sep 7 06:35:36 CDT 2012


---
 dlls/iphlpapi/iphlpapi.spec    |    2 +-
 dlls/iphlpapi/iphlpapi_main.c  |   49 +++--
 dlls/iphlpapi/ipstats.c        |  438 ++++++++++++++++++++++------------------
 dlls/iphlpapi/ipstats.h        |    1 +
 dlls/iphlpapi/tests/iphlpapi.c |   36 ++++
 include/iphlpapi.h             |    3 +
 include/iprtrmib.h             |    7 +
 include/udpmib.h               |    2 +-
 8 files changed, 322 insertions(+), 216 deletions(-)

diff --git a/dlls/iphlpapi/iphlpapi.spec b/dlls/iphlpapi/iphlpapi.spec
index f168492..cadb247 100644
--- a/dlls/iphlpapi/iphlpapi.spec
+++ b/dlls/iphlpapi/iphlpapi.spec
@@ -81,7 +81,7 @@
 @ stub GetBestRouteFromStack
 #@ stub GetCurrentThreadCompartmentId
 @ stdcall GetExtendedTcpTable( ptr ptr long long long long )
-#@ stub GetExtendedUdpTable
+@ stdcall GetExtendedUdpTable( ptr ptr long long long long )
 @ stdcall GetFriendlyIfIndex( long )
 #@ stub GetIcmpStatisticsEx
 @ stdcall GetIcmpStatistics( ptr )
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index 961736f..a9ab1e0 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -1917,31 +1917,46 @@ DWORD WINAPI GetExtendedTcpTable(PVOID pTcpTable, PDWORD pdwSize, BOOL bOrder,
  */
 DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
 {
-    DWORD ret;
-    PMIB_UDPTABLE table;
+    return GetExtendedUdpTable(pUdpTable, pdwSize, bOrder, AF_INET, UDP_TABLE_BASIC, 0);
+}
 
-    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;
 
-    ret = AllocateAndGetUdpTableFromStack( &table, bOrder, GetProcessHeap(), 0 );
-    if (!ret) {
-        DWORD size = FIELD_OFFSET( MIB_UDPTABLE, table[table->dwNumEntries] );
-        if (!pUdpTable || *pdwSize < size) {
-          *pdwSize = size;
-          ret = ERROR_INSUFFICIENT_BUFFER;
-        }
-        else {
-          *pdwSize = size;
-          memcpy(pUdpTable, table, size);
-        }
-        HeapFree(GetProcessHeap(), 0, table);
+    if (ulAf != AF_INET ||
+        (TableClass != UDP_TABLE_BASIC && TableClass != UDP_TABLE_OWNER_PID))
+    {
+        FIXME("ulAf = %u, TableClass = %u not supported\n", ulAf, TableClass);
+        return ERROR_NOT_SUPPORTED;
     }
-    TRACE("returning %d\n", ret);
+    if ((ret = build_udp_table(TableClass, &table, bOrder, GetProcessHeap(), 0, &size)))
+        return ret;
+
+    if (!pUdpTable || *pdwSize < size)
+    {
+        *pdwSize = size;
+        ret = ERROR_INSUFFICIENT_BUFFER;
+    }
+    else
+    {
+        *pdwSize = size;
+        memcpy(pUdpTable, table, size);
+    }
+    HeapFree(GetProcessHeap(), 0, table);
     return ret;
 }
 
-
 /******************************************************************
  *    GetUniDirectionalAdapterInfo (IPHLPAPI.@)
  *
diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c
index 2f8ec90..18307d5 100644
--- a/dlls/iphlpapi/ipstats.c
+++ b/dlls/iphlpapi/ipstats.c
@@ -1433,203 +1433,6 @@ done:
     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 )
 {
     DWORD table_size;
@@ -2015,3 +1818,244 @@ DWORD WINAPI AllocateAndGetTcpTableFromStack( PMIB_TCPTABLE *ppTcpTable, BOOL bO
     if (!ppTcpTable) return ERROR_INVALID_PARAMETER;
     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 );
+}
diff --git a/dlls/iphlpapi/ipstats.h b/dlls/iphlpapi/ipstats.h
index 16854e8..bf5bb92 100644
--- a/dlls/iphlpapi/ipstats.h
+++ b/dlls/iphlpapi/ipstats.h
@@ -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 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_ */
diff --git a/dlls/iphlpapi/tests/iphlpapi.c b/dlls/iphlpapi/tests/iphlpapi.c
index aabcf04..638d7e5 100644
--- a/dlls/iphlpapi/tests/iphlpapi.c
+++ b/dlls/iphlpapi/tests/iphlpapi.c
@@ -71,6 +71,7 @@ static DWORD (WINAPI *pGetAdaptersAddresses)(ULONG,ULONG,PVOID,PIP_ADAPTER_ADDRE
 static DWORD (WINAPI *pNotifyAddrChange)(PHANDLE,LPOVERLAPPED);
 static BOOL  (WINAPI *pCancelIPChangeNotify)(LPOVERLAPPED);
 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 void loadIPHlpApi(void)
@@ -102,6 +103,7 @@ static void loadIPHlpApi(void)
     pNotifyAddrChange = (void *)GetProcAddress(hLibrary, "NotifyAddrChange");
     pCancelIPChangeNotify = (void *)GetProcAddress(hLibrary, "CancelIPChangeNotify");
     pGetExtendedTcpTable = (void *)GetProcAddress(hLibrary, "GetExtendedTcpTable");
+    pGetExtendedUdpTable = (void *)GetProcAddress(hLibrary, "GetExtendedUdpTable");
     pSetTcpEntry = (void *)GetProcAddress(hLibrary, "SetTcpEntry");
   }
 }
@@ -1203,6 +1205,39 @@ static void test_GetExtendedTcpTable(void)
     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)
 {
 
@@ -1221,6 +1256,7 @@ START_TEST(iphlpapi)
     testWin2KFunctions();
     test_GetAdaptersAddresses();
     test_GetExtendedTcpTable();
+    test_GetExtendedUdpTable();
     freeIPHlpApi();
   }
 }
diff --git a/include/iphlpapi.h b/include/iphlpapi.h
index 4390903..ca8e48f 100644
--- a/include/iphlpapi.h
+++ b/include/iphlpapi.h
@@ -29,6 +29,9 @@ extern "C" {
 DWORD WINAPI GetExtendedTcpTable(PVOID pTcpTable, PDWORD pdwSize, BOOL bOrder,
  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 GetIfEntry(PMIB_IFROW pIfRow);
diff --git a/include/iprtrmib.h b/include/iprtrmib.h
index 3d4e65e..977b117 100644
--- a/include/iprtrmib.h
+++ b/include/iprtrmib.h
@@ -38,4 +38,11 @@ typedef enum _TCP_TABLE_CLASS
     TCP_TABLE_OWNER_MODULE_ALL
 } 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__ */
diff --git a/include/udpmib.h b/include/udpmib.h
index 5693279..c2d507f 100644
--- a/include/udpmib.h
+++ b/include/udpmib.h
@@ -39,6 +39,7 @@ typedef struct _MIB_UDPROW_OWNER_PID
 {
     DWORD dwLocalAddr;
     DWORD dwLocalPort;
+    DWORD dwOwningPid;
 } MIB_UDPROW_OWNER_PID, *PMIB_UDPROW_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_UDPTABLE_OWNER_PID, *PMIB_UDPTABLE_OWNER_PID;
 
-
 /* UDP statistics */
 
 typedef struct _MIB_UDPSTATS
-- 
1.7.10.4







More information about the wine-patches mailing list