[SHELL32] Remove 2 redundant initializations
[reactos.git] / dll / win32 / iphlpapi / iphlpapi_main.c
index 3dfd296..a2fccb2 100644 (file)
@@ -2,6 +2,7 @@
  * iphlpapi dll implementation
  *
  * Copyright (C) 2003 Juan Lang
+ *               2018 Pierre Schweitzer
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -22,6 +23,8 @@
 
 #include <config.h>
 #include "iphlpapi_private.h"
+#include <strsafe.h>
+#include <psapi.h>
 
 WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
 
@@ -51,9 +54,7 @@ BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
 /******************************************************************
  *    AddIPAddress (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  Address [In]
  *  IpMask [In]
  *  IfIndex [In]
@@ -61,9 +62,7 @@ BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
  *  NTEInstance [In/Out]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI AddIPAddress(IPAddr Address, IPMask Netmask, DWORD IfIndex, PULONG NteContext, PULONG NteInstance)
 {
@@ -72,9 +71,9 @@ DWORD WINAPI AddIPAddress(IPAddr Address, IPMask Netmask, DWORD IfIndex, PULONG
 
 DWORD getInterfaceGatewayByIndex(DWORD index)
 {
-   DWORD ndx, retVal = 0, numRoutes = getNumRoutes();
-   RouteTable *table = getRouteTable();
-   if (!table) return 0;
+    DWORD ndx, retVal = 0, numRoutes = getNumRoutes();
+    RouteTable *table = getRouteTable();
+    if (!table) return 0;
 
     for (ndx = 0; ndx < numRoutes; ndx++)
     {
@@ -88,9 +87,7 @@ DWORD getInterfaceGatewayByIndex(DWORD index)
 /******************************************************************
  *    AllocateAndGetIfTableFromStack (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  ppIfTable [Out] -- pointer into which the MIB_IFTABLE is
  *   allocated and returned.
  *  bOrder [In] -- passed to GetIfTable to order the table
@@ -99,24 +96,28 @@ DWORD getInterfaceGatewayByIndex(DWORD index)
  *
  * RETURNS -- ERROR_INVALID_PARAMETER if ppIfTable is NULL, whatever
  *  GetIfTable returns otherwise
- *
  */
 DWORD WINAPI AllocateAndGetIfTableFromStack(PMIB_IFTABLE *ppIfTable,
  BOOL bOrder, HANDLE heap, DWORD flags)
 {
   DWORD ret;
 
-  TRACE("ppIfTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n", ppIfTable,
-   (DWORD)bOrder, (DWORD)heap, flags);
+  TRACE("ppIfTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx\n", ppIfTable,
+   (DWORD)bOrder, heap, flags);
   if (!ppIfTable)
     ret = ERROR_INVALID_PARAMETER;
   else {
     DWORD dwSize = 0;
 
+    *ppIfTable = NULL;
     ret = GetIfTable(*ppIfTable, &dwSize, bOrder);
     if (ret == ERROR_INSUFFICIENT_BUFFER) {
       *ppIfTable = (PMIB_IFTABLE)HeapAlloc(heap, flags, dwSize);
       ret = GetIfTable(*ppIfTable, &dwSize, bOrder);
+      if (ret != NO_ERROR) {
+        HeapFree(heap, flags, *ppIfTable);
+        *ppIfTable = NULL;
+      }
     }
   }
   TRACE("returning %ld\n", ret);
@@ -127,35 +128,36 @@ DWORD WINAPI AllocateAndGetIfTableFromStack(PMIB_IFTABLE *ppIfTable,
 /******************************************************************
  *    AllocateAndGetIpAddrTableFromStack (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  ppIpAddrTable [Out]
  *  bOrder [In] -- passed to GetIpAddrTable to order the table
  *  heap [In] -- heap from which the table is allocated
  *  flags [In] -- flags to HeapAlloc
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI AllocateAndGetIpAddrTableFromStack(PMIB_IPADDRTABLE *ppIpAddrTable,
  BOOL bOrder, HANDLE heap, DWORD flags)
 {
   DWORD ret;
 
-  TRACE("ppIpAddrTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
-   ppIpAddrTable, (DWORD)bOrder, (DWORD)heap, flags);
+  TRACE("ppIpAddrTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx\n",
+   ppIpAddrTable, (DWORD)bOrder, heap, flags);
   if (!ppIpAddrTable)
     ret = ERROR_INVALID_PARAMETER;
   else {
     DWORD dwSize = 0;
 
+    *ppIpAddrTable = NULL;
     ret = GetIpAddrTable(*ppIpAddrTable, &dwSize, bOrder);
     if (ret == ERROR_INSUFFICIENT_BUFFER) {
       *ppIpAddrTable = (PMIB_IPADDRTABLE)HeapAlloc(heap, flags, dwSize);
       ret = GetIpAddrTable(*ppIpAddrTable, &dwSize, bOrder);
+      if (ret != NO_ERROR) {
+        HeapFree(heap, flags, *ppIpAddrTable);
+        *ppIpAddrTable = NULL;
+      }
     }
   }
   TRACE("returning %ld\n", ret);
@@ -166,7 +168,6 @@ DWORD WINAPI AllocateAndGetIpAddrTableFromStack(PMIB_IPADDRTABLE *ppIpAddrTable,
 /******************************************************************
  *    AllocateAndGetIpForwardTableFromStack (IPHLPAPI.@)
  *
- *
  *  ppIpForwardTable [Out] -- pointer into which the MIB_IPFORWARDTABLE is
  *   allocated and returned.
  *  bOrder [In] -- passed to GetIfTable to order the table
@@ -175,24 +176,28 @@ DWORD WINAPI AllocateAndGetIpAddrTableFromStack(PMIB_IPADDRTABLE *ppIpAddrTable,
  *
  * RETURNS -- ERROR_INVALID_PARAMETER if ppIfTable is NULL, whatever
  *  GetIpForwardTable returns otherwise
- *
  */
 DWORD WINAPI AllocateAndGetIpForwardTableFromStack(PMIB_IPFORWARDTABLE *
  ppIpForwardTable, BOOL bOrder, HANDLE heap, DWORD flags)
 {
   DWORD ret;
 
-  TRACE("ppIpForwardTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
-   ppIpForwardTable, (DWORD)bOrder, (DWORD)heap, flags);
+  TRACE("ppIpForwardTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx\n",
+   ppIpForwardTable, (DWORD)bOrder, heap, flags);
   if (!ppIpForwardTable)
     ret = ERROR_INVALID_PARAMETER;
   else {
     DWORD dwSize = 0;
 
+    *ppIpForwardTable = NULL;
     ret = GetIpForwardTable(*ppIpForwardTable, &dwSize, bOrder);
     if (ret == ERROR_INSUFFICIENT_BUFFER) {
       *ppIpForwardTable = (PMIB_IPFORWARDTABLE)HeapAlloc(heap, flags, dwSize);
       ret = GetIpForwardTable(*ppIpForwardTable, &dwSize, bOrder);
+      if (ret != NO_ERROR) {
+        HeapFree(heap, flags, *ppIpForwardTable);
+        *ppIpForwardTable = NULL;
+      }
     }
   }
   TRACE("returning %ld\n", ret);
@@ -203,35 +208,36 @@ DWORD WINAPI AllocateAndGetIpForwardTableFromStack(PMIB_IPFORWARDTABLE *
 /******************************************************************
  *    AllocateAndGetIpNetTableFromStack (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  ppIpNetTable [Out]
  *  bOrder [In] -- passed to GetIpNetTable to order the table
  *  heap [In] -- heap from which the table is allocated
  *  flags [In] -- flags to HeapAlloc
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI AllocateAndGetIpNetTableFromStack(PMIB_IPNETTABLE *ppIpNetTable,
  BOOL bOrder, HANDLE heap, DWORD flags)
 {
   DWORD ret;
 
-  TRACE("ppIpNetTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
-   ppIpNetTable, (DWORD)bOrder, (DWORD)heap, flags);
+  TRACE("ppIpNetTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx\n",
+   ppIpNetTable, (DWORD)bOrder, heap, flags);
   if (!ppIpNetTable)
     ret = ERROR_INVALID_PARAMETER;
   else {
     DWORD dwSize = 0;
 
+    *ppIpNetTable = NULL;
     ret = GetIpNetTable(*ppIpNetTable, &dwSize, bOrder);
     if (ret == ERROR_INSUFFICIENT_BUFFER) {
       *ppIpNetTable = (PMIB_IPNETTABLE)HeapAlloc(heap, flags, dwSize);
       ret = GetIpNetTable(*ppIpNetTable, &dwSize, bOrder);
+      if (ret != NO_ERROR) {
+        HeapFree(heap, flags, *ppIpNetTable);
+        *ppIpNetTable = NULL;
+      }
     }
   }
   TRACE("returning %ld\n", ret);
@@ -242,35 +248,36 @@ DWORD WINAPI AllocateAndGetIpNetTableFromStack(PMIB_IPNETTABLE *ppIpNetTable,
 /******************************************************************
  *    AllocateAndGetTcpTableFromStack (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  ppTcpTable [Out]
  *  bOrder [In] -- passed to GetTcpTable to order the table
  *  heap [In] -- heap from which the table is allocated
  *  flags [In] -- flags to HeapAlloc
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI AllocateAndGetTcpTableFromStack(PMIB_TCPTABLE *ppTcpTable,
  BOOL bOrder, HANDLE heap, DWORD flags)
 {
   DWORD ret;
 
-  TRACE("ppTcpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
-   ppTcpTable, (DWORD)bOrder, (DWORD)heap, flags);
+  TRACE("ppTcpTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx\n",
+   ppTcpTable, (DWORD)bOrder, heap, flags);
   if (!ppTcpTable)
     ret = ERROR_INVALID_PARAMETER;
   else {
     DWORD dwSize = 0;
 
+    *ppTcpTable = NULL;
     ret = GetTcpTable(*ppTcpTable, &dwSize, bOrder);
     if (ret == ERROR_INSUFFICIENT_BUFFER) {
       *ppTcpTable = (PMIB_TCPTABLE)HeapAlloc(heap, flags, dwSize);
       ret = GetTcpTable(*ppTcpTable, &dwSize, bOrder);
+      if (ret != NO_ERROR) {
+        HeapFree(heap, flags, *ppTcpTable);
+        *ppTcpTable = NULL;
+      }
     }
   }
   TRACE("returning %ld\n", ret);
@@ -279,37 +286,121 @@ DWORD WINAPI AllocateAndGetTcpTableFromStack(PMIB_TCPTABLE *ppTcpTable,
 
 
 /******************************************************************
- *    AllocateAndGetUdpTableFromStack (IPHLPAPI.@)
+ *    AllocateAndGetTcpExTableFromStack (IPHLPAPI.@)
+ *
+ * PARAMS
+ *  ppTcpTable [Out]
+ *  bOrder [In] -- passed to GetExtendedTcpTable to order the table
+ *  heap [In] -- heap from which the table is allocated
+ *  flags [In] -- flags to HeapAlloc
+ *  family [In] -- passed to GetExtendedTcpTable to select INET family
  *
+ * RETURNS
+ *  DWORD
+ */
+DWORD WINAPI AllocateAndGetTcpExTableFromStack(PVOID *ppTcpTable,
+ BOOL bOrder, HANDLE heap, DWORD flags, DWORD family)
+{
+  DWORD ret;
+
+  TRACE("ppTcpTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx, family 0x%08lx\n",
+   ppTcpTable, (DWORD)bOrder, heap, flags, family);
+  if (!ppTcpTable)
+    ret = ERROR_INVALID_PARAMETER;
+  else {
+    DWORD dwSize = 0;
+
+    *ppTcpTable = NULL;
+    ret = GetExtendedTcpTable(*ppTcpTable, &dwSize, bOrder, family, TCP_TABLE_OWNER_PID_ALL, 0);
+    if (ret == ERROR_INSUFFICIENT_BUFFER) {
+      *ppTcpTable = (PMIB_TCPTABLE_OWNER_PID)HeapAlloc(heap, flags, dwSize);
+      ret = GetExtendedTcpTable(*ppTcpTable, &dwSize, bOrder, family, TCP_TABLE_OWNER_PID_ALL, 0);
+      if (ret != NO_ERROR) {
+        HeapFree(heap, flags, *ppTcpTable);
+        *ppTcpTable = NULL;
+      }
+    }
+  }
+  TRACE("returning %ld\n", ret);
+  return ret;
+}
+
+
+/******************************************************************
+ *    AllocateAndGetTcpExTable2FromStack (IPHLPAPI.@)
  *
  * PARAMS
+ *  ppTcpTable [Out]
+ *  bOrder [In] -- passed to GetExtendedTcpTable to order the table
+ *  heap [In] -- heap from which the table is allocated
+ *  flags [In] -- flags to HeapAlloc
+ *  family [In] -- passed to GetExtendedTcpTable to select INET family
+ *  class [In] -- passed to GetExtendedTcpTable to select information
+ *
+ * RETURNS
+ *  DWORD
+ */
+DWORD WINAPI AllocateAndGetTcpExTable2FromStack(PVOID *ppTcpTable,
+ BOOL bOrder, HANDLE heap, DWORD flags, DWORD family, TCP_TABLE_CLASS class)
+{
+  DWORD ret;
+
+  TRACE("ppTcpTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx, family %ld, class %ld\n",
+   ppTcpTable, (DWORD)bOrder, heap, flags, family, class);
+  if (!ppTcpTable)
+    ret = ERROR_INVALID_PARAMETER;
+  else {
+    DWORD dwSize = 0;
+
+    *ppTcpTable = NULL;
+    ret = GetExtendedTcpTable(*ppTcpTable, &dwSize, bOrder, family, class, 0);
+    if (ret == ERROR_INSUFFICIENT_BUFFER) {
+      *ppTcpTable = HeapAlloc(heap, flags, dwSize);
+      ret = GetExtendedTcpTable(*ppTcpTable, &dwSize, bOrder, family, class, 0);
+      if (ret != NO_ERROR) {
+        HeapFree(heap, flags, *ppTcpTable);
+        *ppTcpTable = NULL;
+      }
+    }
+  }
+  TRACE("returning %ld\n", ret);
+  return ret;
+}
+
+
+/******************************************************************
+ *    AllocateAndGetUdpTableFromStack (IPHLPAPI.@)
  *
+ * PARAMS
  *  ppUdpTable [Out]
  *  bOrder [In] -- passed to GetUdpTable to order the table
  *  heap [In] -- heap from which the table is allocated
  *  flags [In] -- flags to HeapAlloc
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI AllocateAndGetUdpTableFromStack(PMIB_UDPTABLE *ppUdpTable,
  BOOL bOrder, HANDLE heap, DWORD flags)
 {
   DWORD ret;
 
-  TRACE("ppUdpTable %p, bOrder %ld, heap 0x%08lx, flags 0x%08lx\n",
-   ppUdpTable, (DWORD)bOrder, (DWORD)heap, flags);
+  TRACE("ppUdpTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx\n",
+   ppUdpTable, (DWORD)bOrder, heap, flags);
   if (!ppUdpTable)
     ret = ERROR_INVALID_PARAMETER;
   else {
     DWORD dwSize = 0;
 
+    *ppUdpTable = NULL;
     ret = GetUdpTable(*ppUdpTable, &dwSize, bOrder);
     if (ret == ERROR_INSUFFICIENT_BUFFER) {
       *ppUdpTable = (PMIB_UDPTABLE)HeapAlloc(heap, flags, dwSize);
       ret = GetUdpTable(*ppUdpTable, &dwSize, bOrder);
+      if (ret != NO_ERROR) {
+        HeapFree(heap, flags, *ppUdpTable);
+        *ppUdpTable = NULL;
+      }
     }
   }
   TRACE("returning %ld\n", ret);
@@ -318,17 +409,96 @@ DWORD WINAPI AllocateAndGetUdpTableFromStack(PMIB_UDPTABLE *ppUdpTable,
 
 
 /******************************************************************
- *    CreateIpForwardEntry (IPHLPAPI.@)
+ *    AllocateAndGetUdpExTableFromStack (IPHLPAPI.@)
  *
+ * PARAMS
+ *  ppUdpTable [Out]
+ *  bOrder [In] -- passed to GetExtendedUdpTable to order the table
+ *  heap [In] -- heap from which the table is allocated
+ *  flags [In] -- flags to HeapAlloc
+ *  family [In] -- passed to GetExtendedUdpTable to select INET family
+ *
+ * RETURNS
+ *  DWORD
+ */
+DWORD WINAPI AllocateAndGetUdpExTableFromStack(PVOID *ppUdpTable,
+ BOOL bOrder, HANDLE heap, DWORD flags, DWORD family)
+{
+  DWORD ret;
+
+  TRACE("ppUdpTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx, family 0x%08lx\n",
+   ppUdpTable, (DWORD)bOrder, heap, flags, family);
+  if (!ppUdpTable)
+    ret = ERROR_INVALID_PARAMETER;
+  else {
+    DWORD dwSize = 0;
+
+    *ppUdpTable = NULL;
+    ret = GetExtendedUdpTable(*ppUdpTable, &dwSize, bOrder, family, UDP_TABLE_OWNER_PID, 0);
+    if (ret == ERROR_INSUFFICIENT_BUFFER) {
+      *ppUdpTable = (PMIB_UDPTABLE_OWNER_PID)HeapAlloc(heap, flags, dwSize);
+      ret = GetExtendedUdpTable(*ppUdpTable, &dwSize, bOrder, family, UDP_TABLE_OWNER_PID, 0);
+      if (ret != NO_ERROR) {
+        HeapFree(heap, flags, *ppUdpTable);
+        *ppUdpTable = NULL;
+      }
+    }
+  }
+  TRACE("returning %ld\n", ret);
+  return ret;
+}
+
+
+/******************************************************************
+ *    AllocateAndGetUdpExTable2FromStack (IPHLPAPI.@)
  *
  * PARAMS
+ *  ppUdpTable [Out]
+ *  bOrder [In] -- passed to GetExtendedUdpTable to order the table
+ *  heap [In] -- heap from which the table is allocated
+ *  flags [In] -- flags to HeapAlloc
+ *  family [In] -- passed to GetExtendedUdpTable to select INET family
+ *  class [In] -- passed to GetExtendedUdpTable to select information
+ *
+ * RETURNS
+ *  DWORD
+ */
+DWORD WINAPI AllocateAndGetUdpExTable2FromStack(PVOID *ppUdpTable,
+ BOOL bOrder, HANDLE heap, DWORD flags, DWORD family, UDP_TABLE_CLASS class)
+{
+  DWORD ret;
+
+  TRACE("ppUdpTable %p, bOrder %ld, heap 0x%p, flags 0x%08lx, family %ld, class %ld\n",
+   ppUdpTable, (DWORD)bOrder, heap, flags, family, class);
+  if (!ppUdpTable)
+    ret = ERROR_INVALID_PARAMETER;
+  else {
+    DWORD dwSize = 0;
+
+    *ppUdpTable = NULL;
+    ret = GetExtendedUdpTable(*ppUdpTable, &dwSize, bOrder, family, class, 0);
+    if (ret == ERROR_INSUFFICIENT_BUFFER) {
+      *ppUdpTable = HeapAlloc(heap, flags, dwSize);
+      ret = GetExtendedUdpTable(*ppUdpTable, &dwSize, bOrder, family, class, 0);
+      if (ret != NO_ERROR) {
+        HeapFree(heap, flags, *ppUdpTable);
+        *ppUdpTable = NULL;
+      }
+    }
+  }
+  TRACE("returning %ld\n", ret);
+  return ret;
+}
+
+
+/******************************************************************
+ *    CreateIpForwardEntry (IPHLPAPI.@)
  *
+ * PARAMS
  *  pRoute [In/Out]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI CreateIpForwardEntry(PMIB_IPFORWARDROW pRoute)
 {
@@ -339,15 +509,11 @@ DWORD WINAPI CreateIpForwardEntry(PMIB_IPFORWARDROW pRoute)
 /******************************************************************
  *    CreateIpNetEntry (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pArpEntry [In/Out]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI CreateIpNetEntry(PMIB_IPNETROW pArpEntry)
 {
@@ -361,17 +527,13 @@ DWORD WINAPI CreateIpNetEntry(PMIB_IPNETROW pArpEntry)
 /******************************************************************
  *    CreateProxyArpEntry (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  dwAddress [In]
  *  dwMask [In]
  *  dwIfIndex [In]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI CreateProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex)
 {
@@ -386,15 +548,11 @@ DWORD WINAPI CreateProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex)
 /******************************************************************
  *    DeleteIPAddress (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  NTEContext [In]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI DeleteIPAddress(ULONG NTEContext)
 {
@@ -406,15 +564,11 @@ DWORD WINAPI DeleteIPAddress(ULONG NTEContext)
 /******************************************************************
  *    DeleteIpForwardEntry (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pRoute [In/Out]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI DeleteIpForwardEntry(PMIB_IPFORWARDROW pRoute)
 {
@@ -425,15 +579,11 @@ DWORD WINAPI DeleteIpForwardEntry(PMIB_IPFORWARDROW pRoute)
 /******************************************************************
  *    DeleteIpNetEntry (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pArpEntry [In/Out]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI DeleteIpNetEntry(PMIB_IPNETROW pArpEntry)
 {
@@ -447,17 +597,13 @@ DWORD WINAPI DeleteIpNetEntry(PMIB_IPNETROW pArpEntry)
 /******************************************************************
  *    DeleteProxyArpEntry (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  dwAddress [In]
  *  dwMask [In]
  *  dwIfIndex [In]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI DeleteProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex)
 {
@@ -471,16 +617,12 @@ DWORD WINAPI DeleteProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex)
 /******************************************************************
  *    EnableRouter (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pHandle [In/Out]
  *  pOverlapped [In/Out]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI EnableRouter(HANDLE * pHandle, OVERLAPPED * pOverlapped)
 {
@@ -496,15 +638,11 @@ DWORD WINAPI EnableRouter(HANDLE * pHandle, OVERLAPPED * pOverlapped)
 /******************************************************************
  *    FlushIpNetTable (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  dwIfIndex [In]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI FlushIpNetTable(DWORD dwIfIndex)
 {
@@ -519,16 +657,12 @@ DWORD WINAPI FlushIpNetTable(DWORD dwIfIndex)
 /******************************************************************
  *    GetAdapterIndex (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  AdapterName [In/Out]
  *  IfIndex [In/Out]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetAdapterIndex(LPWSTR AdapterName, PULONG IfIndex)
 {
@@ -542,16 +676,12 @@ DWORD WINAPI GetAdapterIndex(LPWSTR AdapterName, PULONG IfIndex)
 /******************************************************************
  *    GetAdaptersInfo (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pAdapterInfo [In/Out]
  *  pOutBufLen [In/Out]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
 {
@@ -593,9 +723,8 @@ DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
             IP_ADDRESS_STRING primaryWINS, secondaryWINS;
 
             memset(pAdapterInfo, 0, size);
-            if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
-             "Software\\Wine\\Wine\\Config\\Network", 0, KEY_READ,
-             &hKey) == ERROR_SUCCESS) {
+            /* @@ Wine registry key: HKCU\Software\Wine\Network */
+            if (RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Network", &hKey) == ERROR_SUCCESS) {
               DWORD size = sizeof(primaryWINS.String);
               unsigned long addr;
 
@@ -612,7 +741,7 @@ DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
                 winsEnabled = TRUE;
               RegCloseKey(hKey);
             }
-                       TRACE("num of index is %lu\n", table->numIndexes);
+            TRACE("num of index is %lu\n", table->numIndexes);
             for (ndx = 0; ndx < table->numIndexes; ndx++) {
               PIP_ADAPTER_INFO ptr = &pAdapterInfo[ndx];
               DWORD addrLen = sizeof(ptr->Address), type;
@@ -679,16 +808,12 @@ DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
 /******************************************************************
  *    GetBestInterface (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  dwDestAddr [In]
  *  pdwBestIfIndex [In/Out]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetBestInterface(IPAddr dwDestAddr, PDWORD pdwBestIfIndex)
 {
@@ -712,17 +837,13 @@ DWORD WINAPI GetBestInterface(IPAddr dwDestAddr, PDWORD pdwBestIfIndex)
 /******************************************************************
  *    GetBestRoute (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  dwDestAddr [In]
  *  dwSourceAddr [In]
  *  OUT [In]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetBestRoute(DWORD dwDestAddr, DWORD dwSourceAddr, PMIB_IPFORWARDROW pBestRoute)
 {
@@ -736,18 +857,19 @@ DWORD WINAPI GetBestRoute(DWORD dwDestAddr, DWORD dwSourceAddr, PMIB_IPFORWARDRO
 
   AllocateAndGetIpForwardTableFromStack(&table, FALSE, GetProcessHeap(), 0);
   if (table) {
-    DWORD ndx, matchedBits, matchedNdx = 0;
+    DWORD ndx, minMaskSize, matchedNdx = 0;
 
-    for (ndx = 0, matchedBits = 0; ndx < table->dwNumEntries; ndx++) {
+    for (ndx = 0, minMaskSize = 255; ndx < table->dwNumEntries; ndx++) {
       if ((dwDestAddr & table->table[ndx].dwForwardMask) ==
        (table->table[ndx].dwForwardDest & table->table[ndx].dwForwardMask)) {
-        DWORD numShifts, mask;
+        DWORD hostMaskSize;
 
-        for (numShifts = 0, mask = table->table[ndx].dwForwardMask;
-         mask && !(mask & 1); mask >>= 1, numShifts++)
-          ;
-        if (numShifts > matchedBits) {
-          matchedBits = numShifts;
+        if (!_BitScanForward(&hostMaskSize, ntohl(table->table[ndx].dwForwardMask)))
+        {
+            hostMaskSize = 32;
+        }
+        if (hostMaskSize < minMaskSize) {
+          minMaskSize = hostMaskSize;
           matchedNdx = ndx;
         }
       }
@@ -762,6 +884,28 @@ DWORD WINAPI GetBestRoute(DWORD dwDestAddr, DWORD dwSourceAddr, PMIB_IPFORWARDRO
   return ret;
 }
 
+static int TcpTableSorter(const void *a, const void *b)
+{
+  int ret;
+
+  if (a && b) {
+    PMIB_TCPROW rowA = (PMIB_TCPROW)a, rowB = (PMIB_TCPROW)b;
+
+    ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
+    if (ret == 0) {
+      ret = rowA->dwLocalPort - rowB->dwLocalPort;
+      if (ret == 0) {
+        ret = rowA->dwRemoteAddr - rowB->dwRemoteAddr;
+        if (ret == 0)
+          ret = rowA->dwRemotePort - rowB->dwRemotePort;
+      }
+    }
+  }
+  else
+    ret = 0;
+  return ret;
+}
+
 /******************************************************************
  *    GetExtendedTcpTable (IPHLPAPI.@)
  *
@@ -778,29 +922,539 @@ DWORD WINAPI GetBestRoute(DWORD dwDestAddr, DWORD dwSourceAddr, PMIB_IPFORWARDRO
  * RETURNS
  *  Success: NO_ERROR
  *  Failure: either ERROR_INSUFFICIENT_BUFFER or ERROR_INVALID_PARAMETER
- *
- * NOTES
  */
 DWORD WINAPI GetExtendedTcpTable(PVOID pTcpTable, PDWORD pdwSize, BOOL bOrder, ULONG ulAf, TCP_TABLE_CLASS TableClass, ULONG Reserved)
 {
+    DWORD i, count, size;
        DWORD ret = NO_ERROR;
-       UNIMPLEMENTED;
-       return ret;     
+
+    if (!pdwSize)
+    {
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    if (ulAf != AF_INET)
+    {
+        UNIMPLEMENTED;
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    switch (TableClass)
+    {
+        case TCP_TABLE_BASIC_ALL:
+        {
+            PMIB_TCPTABLE pOurTcpTable = getTcpTable(ClassBasic);
+            PMIB_TCPTABLE pTheirTcpTable = pTcpTable;
+
+            if (pOurTcpTable)
+            {
+                size = FIELD_OFFSET(MIB_TCPTABLE, table) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW);
+                if (size > *pdwSize || !pTheirTcpTable)
+                {
+                    *pdwSize = size;
+                    ret = ERROR_INSUFFICIENT_BUFFER;
+                }
+                else
+                {
+                    memcpy(pTheirTcpTable, pOurTcpTable, size);
+
+                    if (bOrder)
+                        qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
+                              sizeof(MIB_TCPROW), TcpTableSorter);
+                }
+
+                HeapFree(GetProcessHeap(),0, pOurTcpTable);
+            }
+        }
+        break;
+
+        case TCP_TABLE_BASIC_CONNECTIONS:
+        {
+            PMIB_TCPTABLE pOurTcpTable = getTcpTable(ClassBasic);
+            PMIB_TCPTABLE pTheirTcpTable = pTcpTable;
+
+            if (pOurTcpTable)
+            {
+                for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+                {
+                    if (pOurTcpTable->table[i].State != MIB_TCP_STATE_LISTEN)
+                    {
+                        ++count;
+                    }
+                }
+
+                size = FIELD_OFFSET(MIB_TCPTABLE, table) + count * sizeof(MIB_TCPROW);
+                if (size > *pdwSize || !pTheirTcpTable)
+                {
+                    *pdwSize = size;
+                    ret = ERROR_INSUFFICIENT_BUFFER;
+                }
+                else
+                {
+                    pTheirTcpTable->dwNumEntries = count;
+
+                    for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+                    {
+                        if (pOurTcpTable->table[i].State != MIB_TCP_STATE_LISTEN)
+                        {
+                            memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW));
+                            ++count;
+                        }
+                    }
+                    ASSERT(count == pTheirTcpTable->dwNumEntries);
+
+                    if (bOrder)
+                        qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
+                              sizeof(MIB_TCPROW), TcpTableSorter);
+                }
+
+                HeapFree(GetProcessHeap(), 0, pOurTcpTable);
+            }
+        }
+        break;
+
+        case TCP_TABLE_BASIC_LISTENER:
+        {
+            PMIB_TCPTABLE pOurTcpTable = getTcpTable(ClassBasic);
+            PMIB_TCPTABLE pTheirTcpTable = pTcpTable;
+
+            if (pOurTcpTable)
+            {
+                for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+                {
+                    if (pOurTcpTable->table[i].State == MIB_TCP_STATE_LISTEN)
+                    {
+                        ++count;
+                    }
+                }
+
+                size = FIELD_OFFSET(MIB_TCPTABLE, table) + count * sizeof(MIB_TCPROW);
+                if (size > *pdwSize || !pTheirTcpTable)
+                {
+                    *pdwSize = size;
+                    ret = ERROR_INSUFFICIENT_BUFFER;
+                }
+                else
+                {
+                    pTheirTcpTable->dwNumEntries = count;
+
+                    for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+                    {
+                        if (pOurTcpTable->table[i].State == MIB_TCP_STATE_LISTEN)
+                        {
+                            memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW));
+                            ++count;
+                        }
+                    }
+                    ASSERT(count == pTheirTcpTable->dwNumEntries);
+
+                    if (bOrder)
+                        qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
+                              sizeof(MIB_TCPROW), TcpTableSorter);
+                }
+
+                HeapFree(GetProcessHeap(), 0, pOurTcpTable);
+            }
+        }
+        break;
+
+        case TCP_TABLE_OWNER_PID_ALL:
+        {
+            PMIB_TCPTABLE_OWNER_PID pOurTcpTable = getTcpTable(ClassModulePid);
+            PMIB_TCPTABLE_OWNER_PID pTheirTcpTable = pTcpTable;
+
+            if (pOurTcpTable)
+            {
+                size = FIELD_OFFSET(MIB_TCPTABLE_OWNER_PID, table) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW_OWNER_PID);
+                if (size > *pdwSize || !pTheirTcpTable)
+                {
+                    *pdwSize = size;
+                    ret = ERROR_INSUFFICIENT_BUFFER;
+                }
+                else
+                {
+                    memcpy(pTheirTcpTable, pOurTcpTable, size);
+
+                    /* Don't sort on PID, so use basic helper */
+                    if (bOrder)
+                        qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
+                              sizeof(MIB_TCPROW_OWNER_PID), TcpTableSorter);
+                }
+
+                HeapFree(GetProcessHeap(), 0, pOurTcpTable);
+            }
+        }
+        break;
+
+        case TCP_TABLE_OWNER_PID_CONNECTIONS:
+        {
+            PMIB_TCPTABLE_OWNER_PID pOurTcpTable = getTcpTable(ClassModulePid);
+            PMIB_TCPTABLE_OWNER_PID pTheirTcpTable = pTcpTable;
+
+            if (pOurTcpTable)
+            {
+                for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+                {
+                    if (pOurTcpTable->table[i].dwState != MIB_TCP_STATE_LISTEN)
+                    {
+                        ++count;
+                    }
+                }
+
+                size = FIELD_OFFSET(MIB_TCPTABLE_OWNER_PID, table) + count * sizeof(MIB_TCPROW_OWNER_PID);
+                if (size > *pdwSize || !pTheirTcpTable)
+                {
+                    *pdwSize = size;
+                    ret = ERROR_INSUFFICIENT_BUFFER;
+                }
+                else
+                {
+                    pTheirTcpTable->dwNumEntries = count;
+
+                    for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+                    {
+                        if (pOurTcpTable->table[i].dwState != MIB_TCP_STATE_LISTEN)
+                        {
+                            memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW_OWNER_PID));
+                            ++count;
+                        }
+                    }
+                    ASSERT(count == pTheirTcpTable->dwNumEntries);
+
+                    /* Don't sort on PID, so use basic helper */
+                    if (bOrder)
+                        qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
+                              sizeof(MIB_TCPROW_OWNER_PID), TcpTableSorter);
+                }
+
+                HeapFree(GetProcessHeap(), 0, pOurTcpTable);
+            }
+        }
+        break;
+
+        case TCP_TABLE_OWNER_PID_LISTENER:
+        {
+            PMIB_TCPTABLE_OWNER_PID pOurTcpTable = getTcpTable(ClassModulePid);
+            PMIB_TCPTABLE_OWNER_PID pTheirTcpTable = pTcpTable;
+
+            if (pOurTcpTable)
+            {
+                for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+                {
+                    if (pOurTcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN)
+                    {
+                        ++count;
+                    }
+                }
+
+                size = FIELD_OFFSET(MIB_TCPTABLE_OWNER_PID, table) + count * sizeof(MIB_TCPROW_OWNER_PID);
+                if (size > *pdwSize || !pTheirTcpTable)
+                {
+                    *pdwSize = size;
+                    ret = ERROR_INSUFFICIENT_BUFFER;
+                }
+                else
+                {
+                    pTheirTcpTable->dwNumEntries = count;
+
+                    for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+                    {
+                        if (pOurTcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN)
+                        {
+                            memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW_OWNER_PID));
+                            ++count;
+                        }
+                    }
+                    ASSERT(count == pTheirTcpTable->dwNumEntries);
+
+                    /* Don't sort on PID, so use basic helper */
+                    if (bOrder)
+                        qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
+                              sizeof(MIB_TCPROW_OWNER_PID), TcpTableSorter);
+                }
+
+                HeapFree(GetProcessHeap(), 0, pOurTcpTable);
+            }
+        }
+        break;
+
+        case TCP_TABLE_OWNER_MODULE_ALL:
+        {
+            PMIB_TCPTABLE_OWNER_MODULE pOurTcpTable = getTcpTable(ClassModule);
+            PMIB_TCPTABLE_OWNER_MODULE pTheirTcpTable = pTcpTable;
+
+            if (pOurTcpTable)
+            {
+                size = FIELD_OFFSET(MIB_TCPTABLE_OWNER_MODULE, table) + pOurTcpTable->dwNumEntries * sizeof(MIB_TCPROW_OWNER_MODULE);
+                if (size > *pdwSize || !pTheirTcpTable)
+                {
+                    *pdwSize = size;
+                    ret = ERROR_INSUFFICIENT_BUFFER;
+                }
+                else
+                {
+                    memcpy(pTheirTcpTable, pOurTcpTable, size);
+
+                    /* Don't sort on PID, so use basic helper */
+                    if (bOrder)
+                        qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
+                              sizeof(MIB_TCPROW_OWNER_MODULE), TcpTableSorter);
+                }
+
+                HeapFree(GetProcessHeap(), 0, pOurTcpTable);
+            }
+        }
+        break;
+
+        case TCP_TABLE_OWNER_MODULE_CONNECTIONS:
+        {
+            PMIB_TCPTABLE_OWNER_MODULE pOurTcpTable = getTcpTable(ClassModule);
+            PMIB_TCPTABLE_OWNER_MODULE pTheirTcpTable = pTcpTable;
+
+            if (pOurTcpTable)
+            {
+                for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+                {
+                    if (pOurTcpTable->table[i].dwState != MIB_TCP_STATE_LISTEN)
+                    {
+                        ++count;
+                    }
+                }
+
+                size = FIELD_OFFSET(MIB_TCPTABLE_OWNER_MODULE, table) + count * sizeof(MIB_TCPROW_OWNER_MODULE);
+                if (size > *pdwSize || !pTheirTcpTable)
+                {
+                    *pdwSize = size;
+                    ret = ERROR_INSUFFICIENT_BUFFER;
+                }
+                else
+                {
+                    pTheirTcpTable->dwNumEntries = count;
+
+                    for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+                    {
+                        if (pOurTcpTable->table[i].dwState != MIB_TCP_STATE_LISTEN)
+                        {
+                            memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW_OWNER_MODULE));
+                            ++count;
+                        }
+                    }
+                    ASSERT(count == pTheirTcpTable->dwNumEntries);
+
+                    /* Don't sort on PID, so use basic helper */
+                    if (bOrder)
+                        qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
+                              sizeof(MIB_TCPROW_OWNER_MODULE), TcpTableSorter);
+                }
+
+                HeapFree(GetProcessHeap(), 0, pOurTcpTable);
+            }
+        }
+        break;
+
+        case TCP_TABLE_OWNER_MODULE_LISTENER:
+        {
+            PMIB_TCPTABLE_OWNER_MODULE pOurTcpTable = getTcpTable(ClassModule);
+            PMIB_TCPTABLE_OWNER_MODULE pTheirTcpTable = pTcpTable;
+
+            if (pOurTcpTable)
+            {
+                for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+                {
+                    if (pOurTcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN)
+                    {
+                        ++count;
+                    }
+                }
+
+                size = FIELD_OFFSET(MIB_TCPTABLE_OWNER_MODULE, table) + count * sizeof(MIB_TCPROW_OWNER_MODULE);
+                if (size > *pdwSize || !pTheirTcpTable)
+                {
+                    *pdwSize = size;
+                    ret = ERROR_INSUFFICIENT_BUFFER;
+                }
+                else
+                {
+                    pTheirTcpTable->dwNumEntries = count;
+
+                    for (i = 0, count = 0; i < pOurTcpTable->dwNumEntries; ++i)
+                    {
+                        if (pOurTcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN)
+                        {
+                            memcpy(&pTheirTcpTable->table[count], &pOurTcpTable->table[i], sizeof(MIB_TCPROW_OWNER_MODULE));
+                            ++count;
+                        }
+                    }
+                    ASSERT(count == pTheirTcpTable->dwNumEntries);
+
+                    /* Don't sort on PID, so use basic helper */
+                    if (bOrder)
+                        qsort(pTheirTcpTable->table, pTheirTcpTable->dwNumEntries,
+                              sizeof(MIB_TCPROW_OWNER_MODULE), TcpTableSorter);
+                }
+
+                HeapFree(GetProcessHeap(), 0, pOurTcpTable);
+            }
+        }
+        break;
+
+        default:
+            ret = ERROR_INVALID_PARAMETER;
+            break;
+    }
+
+    return ret;
 }
 
+static int UdpTableSorter(const void *a, const void *b)
+{
+  int ret;
+
+  if (a && b) {
+    PMIB_UDPROW rowA = (PMIB_UDPROW)a, rowB = (PMIB_UDPROW)b;
+
+    ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
+    if (ret == 0)
+      ret = rowA->dwLocalPort - rowB->dwLocalPort;
+  }
+  else
+    ret = 0;
+  return ret;
+}
 
 /******************************************************************
- *    GetFriendlyIfIndex (IPHLPAPI.@)
+ *    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
+ */
+DWORD WINAPI GetExtendedUdpTable(PVOID pUdpTable, PDWORD pdwSize, BOOL bOrder, ULONG ulAf, UDP_TABLE_CLASS TableClass, ULONG Reserved)
+{
+    DWORD size;
+    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(ClassBasic);
+            PMIB_UDPTABLE pTheirUdpTable = pUdpTable;
+
+            if (pOurUdpTable)
+            {
+                size = FIELD_OFFSET(MIB_UDPTABLE, table) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW);
+                if (size > *pdwSize || !pTheirUdpTable)
+                {
+                    *pdwSize = size;
+                    ret = ERROR_INSUFFICIENT_BUFFER;
+                }
+                else
+                {
+                    memcpy(pTheirUdpTable, pOurUdpTable, size);
+
+                    if (bOrder)
+                        qsort(pTheirUdpTable->table, pTheirUdpTable->dwNumEntries,
+                              sizeof(MIB_UDPROW), UdpTableSorter);
+                }
+
+                HeapFree(GetProcessHeap(), 0, pOurUdpTable);
+            }
+        }
+        break;
+
+        case UDP_TABLE_OWNER_PID:
+        {
+            PMIB_UDPTABLE_OWNER_PID pOurUdpTable = getUdpTable(ClassModulePid);
+            PMIB_UDPTABLE_OWNER_PID pTheirUdpTable = pUdpTable;
+
+            if (pOurUdpTable)
+            {
+                size = FIELD_OFFSET(MIB_UDPTABLE_OWNER_PID, table) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW_OWNER_PID);
+                if (size > *pdwSize || !pTheirUdpTable)
+                {
+                    *pdwSize = size;
+                    ret = ERROR_INSUFFICIENT_BUFFER;
+                }
+                else
+                {
+                    memcpy(pTheirUdpTable, pOurUdpTable, size);
+
+                    if (bOrder)
+                        qsort(pTheirUdpTable->table, pTheirUdpTable->dwNumEntries,
+                              sizeof(MIB_UDPROW_OWNER_PID), UdpTableSorter);
+                }
+
+                HeapFree(GetProcessHeap(), 0, pOurUdpTable);
+            }
+        }
+        break;
+
+        case UDP_TABLE_OWNER_MODULE:
+        {
+            PMIB_UDPTABLE_OWNER_MODULE pOurUdpTable = getUdpTable(ClassModule);
+            PMIB_UDPTABLE_OWNER_MODULE pTheirUdpTable = pUdpTable;
+
+            if (pOurUdpTable)
+            {
+                size = FIELD_OFFSET(MIB_UDPTABLE_OWNER_MODULE, table) + pOurUdpTable->dwNumEntries * sizeof(MIB_UDPROW_OWNER_MODULE);
+                if (size > *pdwSize || !pTheirUdpTable)
+                {
+                    *pdwSize = size;
+                    ret = ERROR_INSUFFICIENT_BUFFER;
+                }
+                else
+                {
+                    memcpy(pTheirUdpTable, pOurUdpTable, size);
+
+                    if (bOrder)
+                        qsort(pTheirUdpTable->table, pTheirUdpTable->dwNumEntries,
+                              sizeof(MIB_UDPROW_OWNER_MODULE), UdpTableSorter);
+                }
+
+                HeapFree(GetProcessHeap(), 0, pOurUdpTable);
+            }
+        }
+        break;
+
+        default:
+            ret = ERROR_INVALID_PARAMETER;
+            break;
+    }
+
+    return ret;
+}
+
+
+/******************************************************************
+ *    GetFriendlyIfIndex (IPHLPAPI.@)
  *
+ * PARAMS
  *  IfIndex [In]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetFriendlyIfIndex(DWORD IfIndex)
 {
@@ -815,15 +1469,11 @@ DWORD WINAPI GetFriendlyIfIndex(DWORD IfIndex)
 /******************************************************************
  *    GetIcmpStatistics (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pStats [In/Out]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetIcmpStatistics(PMIB_ICMP pStats)
 {
@@ -839,15 +1489,11 @@ DWORD WINAPI GetIcmpStatistics(PMIB_ICMP pStats)
 /******************************************************************
  *    GetIfEntry (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pIfRow [In/Out]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetIfEntry(PMIB_IFROW pIfRow)
 {
@@ -887,17 +1533,13 @@ static int IfTableSorter(const void *a, const void *b)
 /******************************************************************
  *    GetIfTable (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pIfTable [In/Out]
  *  pdwSize [In/Out]
  *  bOrder [In]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder)
 {
@@ -955,16 +1597,12 @@ DWORD WINAPI GetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder)
 /******************************************************************
  *    GetInterfaceInfo (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pIfTable [In/Out]
  *  dwOutBufLen [In/Out]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable, PULONG dwOutBufLen)
 {
@@ -1005,9 +1643,10 @@ DWORD WINAPI GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable, PULONG dwOutBufLen)
 
             pIfTable->Adapter[ndx].Index = table->indexes[ndx];
             name = getInterfaceNameByIndex(table->indexes[ndx]);
-            for (walker = name, assigner = pIfTable->Adapter[ndx].Name;
+            wcscpy(pIfTable->Adapter[ndx].Name, L"\\DEVICE\\TCPIP_");
+            for (walker = name, assigner = &pIfTable->Adapter[ndx].Name[14];
              walker && *walker &&
-             assigner - pIfTable->Adapter[ndx].Name < MAX_ADAPTER_NAME - 1;
+             assigner - pIfTable->Adapter[ndx].Name < MAX_ADAPTER_NAME - 1 - 14;
              walker++, assigner++)
               *assigner = *walker;
             *assigner = 0;
@@ -1042,17 +1681,13 @@ static int IpAddrTableSorter(const void *a, const void *b)
 /******************************************************************
  *    GetIpAddrTable (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pIpAddrTable [In/Out]
  *  pdwSize [In/Out]
  *  bOrder [In]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL bOrder)
 {
@@ -1146,17 +1781,13 @@ static int IpForwardTableSorter(const void *a, const void *b)
 /******************************************************************
  *    GetIpForwardTable (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pIpForwardTable [In/Out]
  *  pdwSize [In/Out]
  *  bOrder [In]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSize, BOOL bOrder)
 {
@@ -1246,17 +1877,13 @@ static int IpNetTableSorter(const void *a, const void *b)
 /******************************************************************
  *    GetIpNetTable (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pIpNetTable [In/Out]
  *  pdwSize [In/Out]
  *  bOrder [In]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize, BOOL bOrder)
 {
@@ -1306,15 +1933,11 @@ DWORD WINAPI GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize, BOOL bOr
 /******************************************************************
  *    GetIpStatistics (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pStats [In/Out]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetIpStatistics(PMIB_IPSTATS pStats)
 {
@@ -1324,16 +1947,12 @@ DWORD WINAPI GetIpStatistics(PMIB_IPSTATS pStats)
 /******************************************************************
  *    GetIpStatisticsEx (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pStats [In/Out]
  *  dwFamily [In]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetIpStatisticsEx(PMIB_IPSTATS pStats, DWORD dwFamily)
 {
@@ -1348,20 +1967,16 @@ DWORD WINAPI GetIpStatisticsEx(PMIB_IPSTATS pStats, DWORD dwFamily)
 /******************************************************************
  *    GetNetworkParams (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pFixedInfo [In/Out]
  *  pOutBufLen [In/Out]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen)
 {
-  DWORD ret, size;
+  DWORD ret, size, type;
   LONG regReturn;
   HKEY hKey;
   PIPHLP_RES_INFO resInfo;
@@ -1383,10 +1998,59 @@ DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen)
   }
 
   memset(pFixedInfo, 0, size);
-  size = sizeof(pFixedInfo->HostName);
-  GetComputerNameExA(ComputerNameDnsHostname, pFixedInfo->HostName, &size);
-  size = sizeof(pFixedInfo->DomainName);
-  GetComputerNameExA(ComputerNameDnsDomain, pFixedInfo->DomainName, &size);
+  /* Check for DhcpHostname and DhcpDomain first */
+  regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
+                            "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
+                            0,
+                            KEY_READ,
+                            &hKey);
+  if (regReturn == ERROR_SUCCESS) {
+      /* Windows doesn't honor DHCP option 12 even if RFC requires it if it is returned by DHCP server! */
+#if 0
+      type = REG_SZ;
+      size = sizeof(pFixedInfo->HostName);
+      regReturn = RegQueryValueExA(hKey,
+                                      "DhcpHostname",
+                                      NULL,
+                                      &type,
+                                      (LPBYTE)pFixedInfo->HostName,
+                                      &size);
+      if (regReturn == ERROR_FILE_NOT_FOUND || (regReturn == ERROR_SUCCESS && size < 1))
+      {
+#endif
+          type = REG_SZ;
+          size = sizeof(pFixedInfo->HostName);
+          regReturn = RegQueryValueExA(hKey,
+                                          "Hostname",
+                                          NULL,
+                                          &type,
+                                          (LPBYTE)pFixedInfo->HostName,
+                                          &size);
+#if 0
+      }
+#endif
+
+      type = REG_SZ;
+      size = sizeof(pFixedInfo->DomainName);
+      regReturn = RegQueryValueExA(hKey,
+                                      "DhcpDomain",
+                                      NULL,
+                                      &type,
+                                      (LPBYTE)pFixedInfo->DomainName,
+                                      &size);
+      if (regReturn == ERROR_FILE_NOT_FOUND || (regReturn == ERROR_SUCCESS && size < 1))
+      {
+          type = REG_SZ;
+          size = sizeof(pFixedInfo->DomainName);
+          regReturn = RegQueryValueExA(hKey,
+                                          "Domain",
+                                          NULL,
+                                          &type,
+                                          (LPBYTE)pFixedInfo->DomainName,
+                                          &size);
+      }
+      RegCloseKey(hKey);
+  }
 
   TRACE("GetComputerNameExA: %s\n", pFixedInfo->DomainName);
 
@@ -1435,49 +2099,206 @@ DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen)
   {
     DWORD size = sizeof(pFixedInfo->ScopeId);
 
-    RegQueryValueExA(hKey, "ScopeID", NULL, NULL, (PBYTE)pFixedInfo->ScopeId, &size);
-    RegCloseKey(hKey);
-  }
+    RegQueryValueExA(hKey, "ScopeID", NULL, NULL, (PBYTE)pFixedInfo->ScopeId, &size);
+    RegCloseKey(hKey);
+  }
+
+  disposeResInfo( resInfo );
+  /* FIXME: can check whether routing's enabled in /proc/sys/net/ipv4/ip_forward
+     I suppose could also check for a listener on port 53 to set EnableDns */
+  ret = NO_ERROR;
+  TRACE("returning %ld\n", ret);
+
+  return ret;
+}
+
+
+/******************************************************************
+ *    GetNumberOfInterfaces (IPHLPAPI.@)
+ *
+ * PARAMS
+ *  pdwNumIf [In/Out]
+ *
+ * RETURNS
+ *  DWORD
+ */
+DWORD WINAPI GetNumberOfInterfaces(PDWORD pdwNumIf)
+{
+  DWORD ret;
+
+  TRACE("pdwNumIf %p\n", pdwNumIf);
+  if (!pdwNumIf)
+    ret = ERROR_INVALID_PARAMETER;
+  else {
+    *pdwNumIf = getNumInterfaces();
+    ret = NO_ERROR;
+  }
+  TRACE("returning %ld\n", ret);
+  return ret;
+}
+
+
+static DWORD GetOwnerModuleFromPidEntry(DWORD OwningPid, TCPIP_OWNER_MODULE_INFO_CLASS Class, PVOID Buffer, PDWORD pdwSize)
+{
+    HANDLE Process;
+    DWORD FileLen, PathLen, Error;
+    WCHAR File[MAX_PATH], Path[MAX_PATH];
+    PTCPIP_OWNER_MODULE_BASIC_INFO BasicInfo;
+
+    if (IsBadWritePtr(pdwSize, sizeof(DWORD)) ||
+        IsBadWritePtr(Buffer, *pdwSize))
+    {
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    if (OwningPid == 0)
+    {
+        return ERROR_NOT_FOUND;
+    }
+
+    Process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, OwningPid);
+    if (Process == NULL)
+    {
+        return GetLastError();
+    }
+
+    FileLen = GetModuleBaseNameW(Process, NULL, File, MAX_PATH);
+    if (FileLen != 0)
+    {
+        PathLen = GetModuleFileNameExW(Process, NULL, Path, MAX_PATH);
+        if (PathLen == 0)
+        {
+            CloseHandle(Process);
+            return GetLastError();
+        }
+
+        /* Add NULL char */
+        ++FileLen;
+        ++PathLen;
+        PathLen *= sizeof(WCHAR);
+        FileLen *= sizeof(WCHAR);
+    }
+    else
+    {
+        Error = GetLastError();
+
+        if (Error == ERROR_PARTIAL_COPY)
+        {
+            wcscpy(File, L"System");
+            wcscpy(Path, L"System");
+
+            PathLen = sizeof(L"System");
+            FileLen = sizeof(L"System");
+        }
+        else
+        {
+            CloseHandle(Process);
+            return Error;
+        }
+    }
+
+    CloseHandle(Process);
+
+    if (*pdwSize < sizeof(TCPIP_OWNER_MODULE_BASIC_INFO) + PathLen + FileLen)
+    {
+        *pdwSize = sizeof(TCPIP_OWNER_MODULE_BASIC_INFO) + PathLen + FileLen;
+        return ERROR_INSUFFICIENT_BUFFER;
+    }
+
+    BasicInfo = Buffer;
+    BasicInfo->pModuleName = (PVOID)((ULONG_PTR)BasicInfo + sizeof(TCPIP_OWNER_MODULE_BASIC_INFO));
+    BasicInfo->pModulePath = (PVOID)((ULONG_PTR)BasicInfo->pModuleName + FileLen);
+    wcscpy(BasicInfo->pModuleName, File);
+    wcscpy(BasicInfo->pModulePath, Path);
+    *pdwSize = sizeof(TCPIP_OWNER_MODULE_BASIC_INFO) + PathLen + FileLen;
+
+    return NO_ERROR;
+}
+
+static DWORD GetOwnerModuleFromTagEntry(DWORD OwningPid, DWORD OwningTag, TCPIP_OWNER_MODULE_INFO_CLASS Class, PVOID Buffer, PDWORD pdwSize)
+{
+    UINT Size;
+    HRESULT Res;
+    HANDLE hAdvapi32;
+    WCHAR SysDir[MAX_PATH];
+    PTCPIP_OWNER_MODULE_BASIC_INFO BasicInfo;
+    ULONG (NTAPI *_I_QueryTagInformation)(PVOID, DWORD, PVOID);
+    struct
+    {
+        DWORD ProcessId;
+        DWORD ServiceTag;
+        DWORD TagType;
+        PWSTR Buffer;
+    } ServiceQuery;
+
+    if (IsBadWritePtr(pdwSize, sizeof(DWORD)) ||
+        IsBadWritePtr(Buffer, *pdwSize))
+    {
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    /* First, secure (avoid injections) load advapi32.dll */
+    Size = GetSystemDirectoryW(SysDir, MAX_PATH);
+    if (Size == 0)
+    {
+        return GetLastError();
+    }
+
+    Res = StringCchCatW(&SysDir[Size], MAX_PATH - Size, L"\\advapi32.dll");
+    if (FAILED(Res))
+    {
+        return Res;
+    }
+
+    hAdvapi32 = GetModuleHandleW(SysDir);
+    if (hAdvapi32 == NULL)
+    {
+        return GetLastError();
+    }
+
+    /* Now, we'll query the service associated with the tag */
+    _I_QueryTagInformation = (PVOID)GetProcAddress(hAdvapi32, "I_QueryTagInformation");
+    if (_I_QueryTagInformation == NULL)
+    {
+        return GetLastError();
+    }
+
+    /* Set tag and PID for the query */
+    ServiceQuery.ProcessId = OwningPid;
+    ServiceQuery.ServiceTag = OwningTag;
+    ServiceQuery.TagType = 0;
+    ServiceQuery.Buffer = NULL;
 
-  disposeResInfo( resInfo );
-  /* FIXME: can check whether routing's enabled in /proc/sys/net/ipv4/ip_forward
-     I suppose could also check for a listener on port 53 to set EnableDns */
-  ret = NO_ERROR;
-  TRACE("returning %ld\n", ret);
+    /* And query */
+    Res = _I_QueryTagInformation(NULL, 1, &ServiceQuery);
+    if (Res != ERROR_SUCCESS)
+    {
+        return Res;
+    }
 
-  return ret;
-}
+    /* Compute service name length */
+    Size = wcslen(ServiceQuery.Buffer) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
 
+    /* We'll copy it twice, so make sure we have enough room */
+    if (*pdwSize < sizeof(TCPIP_OWNER_MODULE_BASIC_INFO) + 2 * Size)
+    {
+        *pdwSize = sizeof(TCPIP_OWNER_MODULE_BASIC_INFO) + 2 * Size;
+        LocalFree(ServiceQuery.Buffer);
+        return ERROR_INSUFFICIENT_BUFFER;
+    }
 
-/******************************************************************
- *    GetNumberOfInterfaces (IPHLPAPI.@)
- *
- *
- * PARAMS
- *
- *  pdwNumIf [In/Out]
- *
- * RETURNS
- *
- *  DWORD
- *
- */
-DWORD WINAPI GetNumberOfInterfaces(PDWORD pdwNumIf)
-{
-  DWORD ret;
+    /* Copy back data */
+    BasicInfo = Buffer;
+    BasicInfo->pModuleName = (PVOID)((ULONG_PTR)BasicInfo + sizeof(TCPIP_OWNER_MODULE_BASIC_INFO));
+    BasicInfo->pModulePath = (PVOID)((ULONG_PTR)BasicInfo->pModuleName + Size);
+    wcscpy(BasicInfo->pModuleName, ServiceQuery.Buffer);
+    wcscpy(BasicInfo->pModulePath, ServiceQuery.Buffer);
+    *pdwSize = sizeof(TCPIP_OWNER_MODULE_BASIC_INFO) + 2 * Size;
+    LocalFree(ServiceQuery.Buffer);
 
-  TRACE("pdwNumIf %p\n", pdwNumIf);
-  if (!pdwNumIf)
-    ret = ERROR_INVALID_PARAMETER;
-  else {
-    *pdwNumIf = getNumInterfaces();
-    ret = NO_ERROR;
-  }
-  TRACE("returning %ld\n", ret);
-  return ret;
+    return NO_ERROR;
 }
 
-
 /******************************************************************
  *    GetOwnerModuleFromTcpEntry (IPHLPAPI.@)
  *
@@ -1497,29 +2318,51 @@ DWORD WINAPI GetNumberOfInterfaces(PDWORD pdwNumIf)
  * NOTES
  * The type of data returned in Buffer is indicated by the value of the Class parameter.
  */
-DWORD WINAPI GetOwnerModuleFromTcpEntry( PMIB_TCPROW_OWNER_MODULE pTcpEntry, TCPIP_OWNER_MODULE_INFO_CLASS Class, PVOID Buffer, PDWORD pdwSize)
+DWORD WINAPI GetOwnerModuleFromTcpEntry(PMIB_TCPROW_OWNER_MODULE pTcpEntry, TCPIP_OWNER_MODULE_INFO_CLASS Class, PVOID Buffer, PDWORD pdwSize)
 {
-       DWORD ret = NO_ERROR;
-       UNIMPLEMENTED;
-       return ret;     
+    /* If we have a service tag, that's a service connection */
+    if (pTcpEntry->OwningModuleInfo[0] != 0)
+    {
+        return GetOwnerModuleFromTagEntry(pTcpEntry->dwOwningPid, (DWORD)(pTcpEntry->OwningModuleInfo[0]), Class, Buffer, pdwSize);
+    }
+    else
+    {
+        return GetOwnerModuleFromPidEntry(pTcpEntry->dwOwningPid, Class, Buffer, pdwSize);
+    }
 }
 
-
 /******************************************************************
- *    GetPerAdapterInfo (IPHLPAPI.@)
+ *    GetOwnerModuleFromUdpEntry (IPHLPAPI.@)
  *
+ * Get data about the module that issued the context bind for a specific IPv4 UDP endpoint in a MIB table row
  *
  * PARAMS
- *
- *  IfIndex [In]
- *  pPerAdapterInfo [In/Out]
- *  pOutBufLen [In/Out]
+ *  pUdpEntry [in]    pointer to a MIB_UDPROW_OWNER_MODULE structure
+ *  Class [in]         TCPIP_OWNER_MODULE_INFO_CLASS enumeration value
+ *  Buffer [out]       pointer a buffer containing a TCPIP_OWNER_MODULE_BASIC_INFO structure with the owner module data. 
+ *  pdwSize [in, out]  estimated size of the structure returned in Buffer, in bytes
  *
  * RETURNS
+ *  Success: NO_ERROR
+ *  Failure: ERROR_INSUFFICIENT_BUFFER, ERROR_INVALID_PARAMETER, ERROR_NOT_ENOUGH_MEMORY
+ *            ERROR_NOT_FOUND or ERROR_PARTIAL_COPY
  *
- *  DWORD
- *
+ * NOTES
+ * The type of data returned in Buffer is indicated by the value of the Class parameter.
  */
+DWORD WINAPI GetOwnerModuleFromUdpEntry(PMIB_UDPROW_OWNER_MODULE pUdpEntry, TCPIP_OWNER_MODULE_INFO_CLASS Class, PVOID Buffer, PDWORD pdwSize)
+{
+    /* If we have a service tag, that's a service connection */
+    if (pUdpEntry->OwningModuleInfo[0] != 0)
+    {
+        return GetOwnerModuleFromTagEntry(pUdpEntry->dwOwningPid, (DWORD)(pUdpEntry->OwningModuleInfo[0]), Class, Buffer, pdwSize);
+    }
+    else
+    {
+        return GetOwnerModuleFromPidEntry(pUdpEntry->dwOwningPid, Class, Buffer, pdwSize);
+    }
+}
+
 static void CreateNameServerListEnumNamesFunc( PWCHAR Interface, PWCHAR Server, PVOID Data)
 {
   IP_ADDR_STRING *pNext;
@@ -1550,6 +2393,17 @@ static void CreateNameServerListEnumNamesFunc( PWCHAR Interface, PWCHAR Server,
   Context->NumServers++;
 }
 
+/******************************************************************
+ *    GetPerAdapterInfo (IPHLPAPI.@)
+ *
+ * PARAMS
+ *  IfIndex [In]
+ *  pPerAdapterInfo [In/Out]
+ *  pOutBufLen [In/Out]
+ *
+ * RETURNS
+ *  DWORD
+ */
 DWORD WINAPI GetPerAdapterInfo(ULONG IfIndex, PIP_PER_ADAPTER_INFO pPerAdapterInfo, PULONG pOutBufLen)
 {
   HKEY hkey;
@@ -1612,18 +2466,14 @@ DWORD WINAPI GetPerAdapterInfo(ULONG IfIndex, PIP_PER_ADAPTER_INFO pPerAdapterIn
 /******************************************************************
  *    GetRTTAndHopCount (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  DestIpAddress [In]
  *  HopCount [In/Out]
  *  MaxHops [In]
  *  RTT [In/Out]
  *
  * RETURNS
- *
  *  BOOL
- *
  */
 BOOL WINAPI GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount, ULONG MaxHops, PULONG RTT)
 {
@@ -1637,16 +2487,12 @@ BOOL WINAPI GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount, ULONG MaxHo
 /******************************************************************
  *    GetTcpStatisticsEx (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pStats [In/Out]
  *  dwFamily [In]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetTcpStatisticsEx(PMIB_TCPSTATS pStats, DWORD dwFamily)
 {
@@ -1661,15 +2507,11 @@ DWORD WINAPI GetTcpStatisticsEx(PMIB_TCPSTATS pStats, DWORD dwFamily)
 /******************************************************************
  *    GetTcpStatistics (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pStats [In/Out]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetTcpStatistics(PMIB_TCPSTATS pStats)
 {
@@ -1677,29 +2519,6 @@ DWORD WINAPI GetTcpStatistics(PMIB_TCPSTATS pStats)
 }
 
 
-static int TcpTableSorter(const void *a, const void *b)
-{
-  int ret;
-
-  if (a && b) {
-    PMIB_TCPROW rowA = (PMIB_TCPROW)a, rowB = (PMIB_TCPROW)b;
-
-    ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
-    if (ret == 0) {
-      ret = rowA->dwLocalPort - rowB->dwLocalPort;
-      if (ret == 0) {
-        ret = rowA->dwRemoteAddr - rowB->dwRemoteAddr;
-        if (ret == 0)
-          ret = rowA->dwRemotePort - rowB->dwRemotePort;
-      }
-    }
-  }
-  else
-    ret = 0;
-  return ret;
-}
-
-
 /******************************************************************
  *    GetTcpTable (IPHLPAPI.@)
  *
@@ -1724,69 +2543,19 @@ static int TcpTableSorter(const void *a, const void *b)
  */
 DWORD WINAPI GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder)
 {
-  DWORD ret = ERROR_NO_DATA;
-
-  TRACE("pTcpTable %p, pdwSize %p, bOrder %d\n", pTcpTable, pdwSize,
-   (DWORD)bOrder);
-  if (!pdwSize)
-    ret = ERROR_INVALID_PARAMETER;
-  else {
-    DWORD numEntries = getNumTcpEntries();
-    DWORD size = sizeof(MIB_TCPTABLE);
-
-    if (numEntries > 1)
-      size += (numEntries - 1) * sizeof(MIB_TCPROW);
-    if (!pTcpTable || *pdwSize < size) {
-      *pdwSize = size;
-      ret = ERROR_INSUFFICIENT_BUFFER;
-    }
-    else {
-      PMIB_TCPTABLE pOurTcpTable = getTcpTable();
-         if (pOurTcpTable)
-      {
-        size = sizeof(MIB_TCPTABLE);
-        if (pOurTcpTable->dwNumEntries > 1)
-            size += (pOurTcpTable->dwNumEntries - 1) * sizeof(MIB_TCPROW);
-          
-        if (*pdwSize < size)
-        {
-            *pdwSize = size;
-
-            ret = ERROR_INSUFFICIENT_BUFFER;
-        }
-        else
-        {
-            memcpy(pTcpTable, pOurTcpTable, size);
-            
-            if (bOrder)
-                qsort(pTcpTable->table, pTcpTable->dwNumEntries,
-                      sizeof(MIB_TCPROW), TcpTableSorter);
-            
-            ret = NO_ERROR;
-        }
-          
-        free(pOurTcpTable);
-         }
-       }
-  }
-  TRACE("returning %d\n", ret);
-  return ret;
+    return GetExtendedTcpTable(pTcpTable, pdwSize, bOrder, AF_INET, TCP_TABLE_BASIC_ALL, 0);
 }
 
 
 /******************************************************************
  *    GetUdpStatisticsEx (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pStats [In/Out]
  *  dwFamily [In]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetUdpStatisticsEx(PMIB_UDPSTATS pStats, DWORD dwFamily)
 {
@@ -1801,15 +2570,11 @@ DWORD WINAPI GetUdpStatisticsEx(PMIB_UDPSTATS pStats, DWORD dwFamily)
 /******************************************************************
  *    GetUdpStatistics (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pStats [In/Out]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS pStats)
 {
@@ -1817,79 +2582,20 @@ DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS pStats)
 }
 
 
-static int UdpTableSorter(const void *a, const void *b)
-{
-  int ret;
-
-  if (a && b) {
-    PMIB_UDPROW rowA = (PMIB_UDPROW)a, rowB = (PMIB_UDPROW)b;
-
-    ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
-    if (ret == 0)
-      ret = rowA->dwLocalPort - rowB->dwLocalPort;
-  }
-  else
-    ret = 0;
-  return ret;
-}
-
-
 /******************************************************************
  *    GetUdpTable (IPHLPAPI.@)
  *
- *
  * PARAMS
- *
  *  pUdpTable [In/Out]
  *  pdwSize [In/Out]
  *  bOrder [In]
  *
  * RETURNS
- *
  *  DWORD
- *
  */
 DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
 {
-  DWORD ret;
-
-  TRACE("pUdpTable %p, pdwSize %p, bOrder %ld\n", pUdpTable, pdwSize,
-   (DWORD)bOrder);
-  if (!pdwSize)
-    ret = ERROR_INVALID_PARAMETER;
-  else {
-    DWORD numEntries = getNumUdpEntries();
-    ULONG size = sizeof(MIB_UDPTABLE) + (numEntries - 1) * sizeof(MIB_UDPROW);
-
-    if (!pUdpTable || *pdwSize < size) {
-      *pdwSize = size;
-      ret = ERROR_INSUFFICIENT_BUFFER;
-    }
-    else {
-      PMIB_UDPTABLE table = getUdpTable();
-
-      if (table) {
-        size = sizeof(MIB_UDPTABLE) + (table->dwNumEntries - 1) *
-         sizeof(MIB_UDPROW);
-        if (*pdwSize < size) {
-          *pdwSize = size;
-          ret = ERROR_INSUFFICIENT_BUFFER;
-        }
-        else {
-          memcpy(pUdpTable, table, size);
-          if (bOrder)
-            qsort(pUdpTable->table, pUdpTable->dwNumEntries,
-             sizeof(MIB_UDPROW), UdpTableSorter);
-          ret = NO_ERROR;
-        }
-        free(table);
-      }
-      else
-        ret = ERROR_OUTOFMEMORY;
-    }
-  }
-  TRACE("returning %ld\n", ret);
-  return ret;
+    return GetExtendedUdpTable(pUdpTable, pdwSize, bOrder, AF_INET, UDP_TABLE_BASIC, 0);
 }
 
 
@@ -1930,13 +2636,12 @@ DWORD WINAPI GetUniDirectionalAdapterInfo(PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIP
  * RETURNS
  *  Success: NO_ERROR
  *  Failure: error code from winerror.h
- *
  */
 DWORD WINAPI IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
 {
   DWORD Status, Version = 0;
 
-  if (!AdapterInfo || !AdapterInfo->Name)
+  if (!AdapterInfo)
       return ERROR_INVALID_PARAMETER;
 
   /* Maybe we should do this in DllMain */
@@ -1970,7 +2675,7 @@ DWORD WINAPI IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
 {
   DWORD Status, Version = 0;
 
-  if (!AdapterInfo || !AdapterInfo->Name)
+  if (!AdapterInfo)
       return ERROR_INVALID_PARAMETER;
 
   /* Maybe we should do this in DllMain */
@@ -2035,7 +2740,6 @@ DWORD WINAPI NotifyRouteChange(PHANDLE Handle, LPOVERLAPPED overlapped)
   return ERROR_NOT_SUPPORTED;
 }
 
-
 /******************************************************************
  *    SendARP (IPHLPAPI.@)
  *
@@ -2050,15 +2754,19 @@ DWORD WINAPI NotifyRouteChange(PHANDLE Handle, LPOVERLAPPED overlapped)
  * RETURNS
  *  Success: NO_ERROR
  *  Failure: error code from winerror.h
- *
- * FIXME
- *  Stub, returns ERROR_NOT_SUPPORTED.
  */
 DWORD WINAPI SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen)
 {
-  FIXME("(DestIP 0x%08x, SrcIP 0x%08x, pMacAddr %p, PhyAddrLen %p): stub\n",
-   DestIP, SrcIP, pMacAddr, PhyAddrLen);
-  return ERROR_NOT_SUPPORTED;
+  IPAddr IPs[2];
+  ULONG Size;
+
+  if (IsBadWritePtr(pMacAddr, sizeof(ULONG)) || IsBadWritePtr(PhyAddrLen, sizeof(ULONG)))
+    return ERROR_INVALID_PARAMETER;
+
+  IPs[0] = DestIP;
+  IPs[1] = SrcIP;
+  Size = sizeof(IPs);
+  return TCPSendIoctl(INVALID_HANDLE_VALUE, IOCTL_QUERY_IP_HW_ADDRESS, IPs, &Size, pMacAddr, PhyAddrLen);
 }
 
 
@@ -2099,7 +2807,6 @@ DWORD WINAPI SetIfEntry(PMIB_IFROW pIfRow)
  * RETURNS
  *  Success: NO_ERROR
  *  Failure: error code from winerror.h
- *
  */
 DWORD WINAPI SetIpForwardEntry(PMIB_IPFORWARDROW pRoute)
 {
@@ -2132,7 +2839,7 @@ DWORD WINAPI SetIpNetEntry(PMIB_IPNETROW pArpEntry)
   if (!pArpEntry)
       return ERROR_INVALID_PARAMETER;
 
-  if (!NT_SUCCESS(openTcpFile( &tcpFile )))
+  if (!NT_SUCCESS(openTcpFile( &tcpFile, FILE_READ_DATA | FILE_WRITE_DATA )))
       return ERROR_NOT_SUPPORTED;
 
   if (!NT_SUCCESS(getNthIpEntity( tcpFile, pArpEntry->dwIndex, &id )))
@@ -2278,10 +2985,7 @@ PIP_ADAPTER_ORDER_MAP WINAPI GetAdapterOrderMap(VOID)
     return 0L;
 }
 
-/*
- * @implemented
- */
-#if 0
+#ifdef GetAdaptersAddressesV1
 DWORD WINAPI DECLSPEC_HOTPATCH GetAdaptersAddresses(ULONG Family,ULONG Flags,PVOID Reserved,PIP_ADAPTER_ADDRESSES pAdapterAddresses,PULONG pOutBufLen)
 {
     InterfaceIndexTable *indexTable;
@@ -2295,13 +2999,16 @@ DWORD WINAPI DECLSPEC_HOTPATCH GetAdaptersAddresses(ULONG Family,ULONG Flags,PVO
     if (!pOutBufLen) return ERROR_INVALID_PARAMETER;
     if (Reserved) return ERROR_INVALID_PARAMETER;
 
-    indexTable = getNonLoopbackInterfaceIndexTable(); //I think we want non-loopback here
+    indexTable = getInterfaceIndexTable();
     if (!indexTable)
         return ERROR_NOT_ENOUGH_MEMORY;
 
-    ret = openTcpFile(&tcpFile);
+    ret = openTcpFile(&tcpFile, FILE_READ_DATA);
     if (!NT_SUCCESS(ret))
+    {
+        free(indexTable);
         return ERROR_NO_DATA;
+    }
 
     for (i = indexTable->numIndexes; i >= 0; i--)
     {
@@ -2315,10 +3022,10 @@ DWORD WINAPI DECLSPEC_HOTPATCH GetAdaptersAddresses(ULONG Family,ULONG Flags,PVO
 
             /* Friendly name */
             if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
-                requiredSize += strlen((char *)ifInfo.if_info.ent.if_descr) + 1; //FIXME
+                requiredSize += ifInfo.if_info.ent.if_descrlen + 1; //FIXME
 
             /* Adapter name */
-            requiredSize += strlen((char *)ifInfo.if_info.ent.if_descr) + 1;
+            requiredSize += ifInfo.if_info.ent.if_descrlen + 1;
 
             /* Unicast address */
             if (!(Flags & GAA_FLAG_SKIP_UNICAST))
@@ -2332,8 +3039,8 @@ DWORD WINAPI DECLSPEC_HOTPATCH GetAdaptersAddresses(ULONG Family,ULONG Flags,PVO
             /* We're only going to implement what's required for XP SP0 */
         }
     }
-
-    if (*pOutBufLen < requiredSize)
+    TRACE("size: %d, requiredSize: %d\n", *pOutBufLen, requiredSize);
+    if (!pAdapterAddresses || *pOutBufLen < requiredSize)
     {
         *pOutBufLen = requiredSize;
         closeTcpFile(tcpFile);
@@ -2363,7 +3070,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH GetAdaptersAddresses(ULONG Family,ULONG Flags,PVO
 
             /* Adapter name */
             currentAddress->AdapterName = (PVOID)currentLocation;
-            currentLocation += strlen((char *)ifInfo.if_info.ent.if_descr) + 1;
+            currentLocation += ifInfo.if_info.ent.if_descrlen + 1;
 
             /* Unicast address */
             if (!(Flags & GAA_FLAG_SKIP_UNICAST))
@@ -2384,6 +3091,9 @@ DWORD WINAPI DECLSPEC_HOTPATCH GetAdaptersAddresses(ULONG Family,ULONG Flags,PVO
             currentLocation += sizeof(WCHAR);
 
             currentAddress->Next = (PVOID)currentLocation;
+            /* Terminate the last address correctly */
+            if(i==0)
+                currentAddress->Next = NULL;
 
             /* We're only going to implement what's required for XP SP0 */
 
@@ -2391,10 +3101,6 @@ DWORD WINAPI DECLSPEC_HOTPATCH GetAdaptersAddresses(ULONG Family,ULONG Flags,PVO
         }
     }
 
-    /* Terminate the last address correctly */
-    if (currentAddress)
-        currentAddress->Next = NULL;
-
     /* Now again, for real this time */
 
     currentAddress = pAdapterAddresses;
@@ -2413,7 +3119,8 @@ DWORD WINAPI DECLSPEC_HOTPATCH GetAdaptersAddresses(ULONG Family,ULONG Flags,PVO
             currentAddress->IfIndex = indexTable->indexes[i];
 
             /* Adapter name */
-            strcpy(currentAddress->AdapterName, (char *)ifInfo.if_info.ent.if_descr);
+            memcpy(currentAddress->AdapterName, ifInfo.if_info.ent.if_descr, ifInfo.if_info.ent.if_descrlen);
+            currentAddress->AdapterName[ifInfo.if_info.ent.if_descrlen] = '\0';
 
             if (!(Flags & GAA_FLAG_SKIP_UNICAST))
             {
@@ -2457,7 +3164,10 @@ DWORD WINAPI DECLSPEC_HOTPATCH GetAdaptersAddresses(ULONG Family,ULONG Flags,PVO
             currentAddress->IfType = ifInfo.if_info.ent.if_type;
 
             /* Operational status */
-            currentAddress->OperStatus = ifInfo.if_info.ent.if_operstatus;
+            if(ifInfo.if_info.ent.if_operstatus >= IF_OPER_STATUS_CONNECTING)
+                currentAddress->OperStatus = IfOperStatusUp;
+            else
+                currentAddress->OperStatus = IfOperStatusDown;
 
             /* We're only going to implement what's required for XP SP0 */
 
@@ -2506,6 +3216,13 @@ DWORD WINAPI NhpAllocateAndGetInterfaceInfoFromStack(IP_INTERFACE_NAME_INFO **pp
 DWORD WINAPI GetIcmpStatisticsEx(PMIB_ICMP_EX pStats,DWORD dwFamily)
 {
     FIXME(":stub\n");
+
+    if (!pStats)
+        return ERROR_INVALID_PARAMETER;
+
+    if (dwFamily != AF_INET && dwFamily != AF_INET6)
+        return ERROR_INVALID_PARAMETER;
+
     return 0L;
 }
 
@@ -2516,13 +3233,90 @@ SetIpForwardEntryToStack(PMIB_IPFORWARDROW pRoute)
     return 0L;
 }
 
+DWORD GetInterfaceNameInternal(_In_ const GUID * pInterfaceGUID,
+                               _Out_writes_bytes_to_(*pOutBufLen, *pOutBufLen) PWCHAR pInterfaceName,
+                               _Inout_ PULONG pOutBufLen)
+{
+    UNICODE_STRING GuidString;
+    DWORD result, type;
+    WCHAR szKeyName[2*MAX_PATH];
+    HRESULT hr;
+    HKEY hKey;
+
+    if (pInterfaceGUID == NULL || pOutBufLen == NULL)
+        return ERROR_INVALID_PARAMETER;
+
+    result = RtlStringFromGUID(pInterfaceGUID, &GuidString);
+
+    if (!NT_SUCCESS(result))
+    {
+        // failed to convert guid to string
+        return RtlNtStatusToDosError(result);
+    }
+
+    hr = StringCbPrintfW(szKeyName, sizeof(szKeyName), L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", GuidString.Buffer);
+    RtlFreeUnicodeString(&GuidString);
+
+    if (FAILED(hr))
+    {
+        // key name is too long
+        return ERROR_BUFFER_OVERFLOW;
+    }
+
+    result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_READ, &hKey);
+
+    if (result != ERROR_SUCCESS)
+    {
+        // failed to find adapter entry
+        return ERROR_NOT_FOUND;
+    }
+
+    result = RegQueryValueExW(hKey, L"Name", NULL, &type, (PVOID)pInterfaceName, pOutBufLen);
+
+    RegCloseKey(hKey);
+
+    if (result == ERROR_MORE_DATA)
+    {
+        *pOutBufLen = MAX_INTERFACE_NAME_LEN * 2;
+        return ERROR_INSUFFICIENT_BUFFER;
+    }
+
+    if (result != ERROR_SUCCESS || type != REG_SZ)
+    {
+        // failed to read adapter name
+        return ERROR_NO_DATA;
+    }
+    return ERROR_SUCCESS;
+}
+
 DWORD WINAPI
-NhGetInterfaceNameFromDeviceGuid(DWORD dwUnknown1,
-                                 DWORD dwUnknown2,
-                                 DWORD dwUnknown3,
+NhGetInterfaceNameFromDeviceGuid(_In_ const GUID * pInterfaceGUID,
+                                 _Out_writes_bytes_to_(*pOutBufLen, *pOutBufLen) PWCHAR pInterfaceName,
+                                 _Inout_ PULONG pOutBufLen,
                                  DWORD dwUnknown4,
                                  DWORD dwUnknown5)
 {
-    FIXME("NhGetInterfaceNameFromDeviceGuid() stub\n");
-    return 0L;
+    SetLastError(ERROR_SUCCESS);
+
+    if (pInterfaceName == NULL)
+        return ERROR_INVALID_PARAMETER;
+
+    return GetInterfaceNameInternal(pInterfaceGUID, pInterfaceName, pOutBufLen);
+}
+
+DWORD WINAPI
+NhGetInterfaceNameFromGuid(_In_ const GUID * pInterfaceGUID,
+                           _Out_writes_bytes_to_(*pOutBufLen, *pOutBufLen) PWCHAR pInterfaceName,
+                           _Inout_ PULONG pOutBufLen,
+                           DWORD dwUnknown4,
+                           DWORD dwUnknown5)
+{
+    DWORD result;
+
+    result = GetInterfaceNameInternal(pInterfaceGUID, pInterfaceName, pOutBufLen);
+
+    if (result == ERROR_NOT_FOUND)
+        SetLastError(ERROR_PATH_NOT_FOUND);
+
+    return result;
 }