Alexandre Julliard : iphlpapi: Reimplement GetUdpTable to avoid parsing the same information three times.

Alexandre Julliard julliard at winehq.org
Mon Mar 2 09:01:53 CST 2009


Module: wine
Branch: master
Commit: d069e498e17ae8daea44bf284deb0492c301d219
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d069e498e17ae8daea44bf284deb0492c301d219

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Mar  2 12:43:33 2009 +0100

iphlpapi: Reimplement GetUdpTable to avoid parsing the same information three times.

---

 dlls/iphlpapi/iphlpapi_main.c |   39 ++++----------
 dlls/iphlpapi/ipstats.c       |  118 ++++++++++++++++++++---------------------
 2 files changed, 68 insertions(+), 89 deletions(-)

diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index f580ca8..c9ced14 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -1685,31 +1685,17 @@ DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS pStats)
  */
 DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
 {
-  DWORD ret;
+    DWORD ret;
+    PMIB_UDPTABLE table;
 
-  TRACE("pUdpTable %p, pdwSize %p, bOrder %d\n", pUdpTable, pdwSize,
-   (DWORD)bOrder);
-  if (!pdwSize)
-    ret = ERROR_INVALID_PARAMETER;
-  else {
-    DWORD numEntries = getNumUdpEntries();
-    DWORD size = sizeof(MIB_UDPTABLE);
+    TRACE("pUdpTable %p, pdwSize %p, bOrder %d\n", pUdpTable, pdwSize, bOrder);
 
-    if (numEntries > 1)
-      size += (numEntries - 1) * sizeof(MIB_UDPROW);
-    if (!pUdpTable || *pdwSize < size) {
-      *pdwSize = size;
-      ret = ERROR_INSUFFICIENT_BUFFER;
-    }
-    else {
-      PMIB_UDPTABLE table;
+    if (!pdwSize) return ERROR_INVALID_PARAMETER;
 
-      ret = getUdpTable(&table, GetProcessHeap(), 0);
-      if (!ret) {
-        size = sizeof(MIB_UDPTABLE);
-        if (table->dwNumEntries > 1)
-          size += (table->dwNumEntries - 1) * sizeof(MIB_UDPROW);
-        if (*pdwSize < size) {
+    ret = getUdpTable(&table, GetProcessHeap(), 0);
+    if (!ret) {
+        DWORD size = FIELD_OFFSET( MIB_UDPTABLE, table[table->dwNumEntries] );
+        if (!pUdpTable || *pdwSize < size) {
           *pdwSize = size;
           ret = ERROR_INSUFFICIENT_BUFFER;
         }
@@ -1719,16 +1705,11 @@ DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
           if (bOrder)
             qsort(pUdpTable->table, pUdpTable->dwNumEntries,
              sizeof(MIB_UDPROW), UdpTableSorter);
-          ret = NO_ERROR;
         }
         HeapFree(GetProcessHeap(), 0, table);
-      }
-      else
-        ret = ERROR_OUTOFMEMORY;
     }
-  }
-  TRACE("returning %d\n", ret);
-  return ret;
+    TRACE("returning %d\n", ret);
+    return ret;
 }
 
 
diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c
index ada1430..57398bb 100644
--- a/dlls/iphlpapi/ipstats.c
+++ b/dlls/iphlpapi/ipstats.c
@@ -1,5 +1,7 @@
-/* Copyright (C) 2003,2006 Juan Lang
+/*
+ * Copyright (C) 2003,2006 Juan Lang
  * Copyright (C) 2007 TransGaming Technologies Inc.
+ * Copyright (C) 2009 Alexandre Julliard
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -14,9 +16,6 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- *
- * This file implements statistics getting using the /proc filesystem exported
- * by Linux, and maybe other OSes.
  */
 
 #include "config.h"
@@ -1480,72 +1479,71 @@ DWORD getNumUdpEntries(void)
 #endif
 }
 
-DWORD getUdpTable(PMIB_UDPTABLE *ppUdpTable, HANDLE heap, DWORD flags)
+static MIB_UDPTABLE *append_udp_row( HANDLE heap, DWORD flags, MIB_UDPTABLE *table,
+                                     DWORD *count, const MIB_UDPROW *row )
 {
-  DWORD ret;
+    if (table->dwNumEntries >= *count)
+    {
+        MIB_UDPTABLE *new_table;
+        DWORD new_count = table->dwNumEntries * 2;
 
-#if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
-  ERR ("unimplemented!\n");
-  return ERROR_NOT_SUPPORTED;
-#endif
+        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;
+}
 
-  if (!ppUdpTable)
-    ret = ERROR_INVALID_PARAMETER;
-  else {
-    DWORD numEntries = getNumUdpEntries();
-    DWORD size = sizeof(MIB_UDPTABLE);
-    PMIB_UDPTABLE table;
+DWORD getUdpTable(PMIB_UDPTABLE *ppUdpTable, HANDLE heap, DWORD flags)
+{
+    MIB_UDPTABLE *table;
+    MIB_UDPROW row;
+    DWORD ret = NO_ERROR, count = 16;
 
-    if (numEntries > 1)
-      size += (numEntries - 1) * sizeof(MIB_UDPROW);
-    table = HeapAlloc(heap, flags, size);
-    if (table) {
-      FILE *fp;
+    if (!ppUdpTable) return ERROR_INVALID_PARAMETER;
 
-      ret = NO_ERROR;
-      *ppUdpTable = table;
-      table->dwNumEntries = 0;
-      /* get from /proc/net/udp, no error if can't */
-      fp = fopen("/proc/net/udp", "r");
-      if (fp) {
-        char buf[512] = { 0 }, *ptr;
+    if (!(table = HeapAlloc( heap, flags, FIELD_OFFSET(MIB_UDPTABLE, table[count] ))))
+        return ERROR_OUTOFMEMORY;
 
-        /* skip header line */
-        ptr = fgets(buf, sizeof(buf), fp);
-        while (ptr && table->dwNumEntries < numEntries) {
-          memset(&table->table[table->dwNumEntries], 0, sizeof(MIB_UDPROW));
-          ptr = fgets(buf, sizeof(buf), fp);
-          if (ptr) {
-            char *endPtr;
+    table->dwNumEntries = 0;
 
-            if (ptr && *ptr) {
-              strtoul(ptr, &endPtr, 16); /* skip */
-              ptr = endPtr;
-            }
-            if (ptr && *ptr) {
-              ptr++;
-              table->table[table->dwNumEntries].dwLocalAddr = strtoul(ptr,
-               &endPtr, 16);
-              ptr = endPtr;
-            }
-            if (ptr && *ptr) {
-              ptr++;
-              table->table[table->dwNumEntries].dwLocalPort = strtoul(ptr,
-               &endPtr, 16);
-              ptr = endPtr;
+#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;
             }
-            table->dwNumEntries++;
-          }
+            fclose(fp);
         }
-        fclose(fp);
-      }
-      else
-        ret = ERROR_NOT_SUPPORTED;
+        else ret = ERROR_NOT_SUPPORTED;
     }
-    else
-      ret = ERROR_OUTOFMEMORY;
-  }
-  return ret;
+#else
+    FIXME( "not implemented\n" );
+    ret = ERROR_NOT_SUPPORTED;
+#endif
+
+    if (!table) return ERROR_OUTOFMEMORY;
+    if (!ret) *ppUdpTable = table;
+    else HeapFree( heap, flags, table );
+    return ret;
 }
 
 




More information about the wine-cvs mailing list