-fixes
[oweals/gnunet.git] / src / util / win.cc
index 8e71744d0492382affe5cb975790d6eefd4ef22d..1f660720e55912f62981f113b4f82f321e38765b 100644 (file)
 */\r
 \r
 /**\r
- * @file util/win/win.cc\r
+ * @file util/win.cc\r
  * @brief Helper functions for MS Windows in C++\r
  * @author Nils Durner\r
- **/\r
+ */\r
 \r
 #ifndef _WIN_CC\r
 #define _WIN_CC\r
@@ -42,172 +42,610 @@ using namespace std;
 \r
 extern "C" {\r
 \r
-typedef list<WSAOVERLAPPED *> TOLList;\r
+int plibc_conv_to_win_path(const char *pszUnix, char *pszWindows);\r
 \r
-static HANDLE hOLLock;\r
-static TOLList lstOL;\r
+#define _IP_ADAPTER_UNICAST_ADDRESS_HEAD \\r
+  union { \\r
+    struct { \\r
+      ULONG Length; \\r
+      DWORD Flags; \\r
+    }; \\r
+  }; \\r
+\r
+#define _IP_ADAPTER_UNICAST_ADDRESS_BASE \\r
+  SOCKET_ADDRESS                     Address; \\r
+  IP_PREFIX_ORIGIN                   PrefixOrigin; \\r
+  IP_SUFFIX_ORIGIN                   SuffixOrigin; \\r
+  IP_DAD_STATE                       DadState; \\r
+  ULONG                              ValidLifetime; \\r
+  ULONG                              PreferredLifetime; \\r
+  ULONG                              LeaseLifetime;\r
+\r
+#define _IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA \\r
+  UINT8                              OnLinkPrefixLength;\r
+\r
+\r
+#define _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(suffix,addition) \\r
+typedef struct _IP_ADAPTER_UNICAST_ADDRESS##suffix { \\r
+  _IP_ADAPTER_UNICAST_ADDRESS_HEAD \\r
+  struct _IP_ADAPTER_UNICAST_ADDRESS##suffix *Next; \\r
+  _IP_ADAPTER_UNICAST_ADDRESS_BASE \\r
+  addition \\r
+} IP_ADAPTER_UNICAST_ADDRESS##suffix, *PIP_ADAPTER_UNICAST_ADDRESS##suffix;\r
+\r
+/* _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(,) defined in w32api headers */\r
+_IP_ADAPTER_UNICAST_ADDRESS_DEFINE(_VISTA,_IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA)\r
+\r
+\r
+typedef struct _IP_ADAPTER_WINS_SERVER_ADDRESS {\r
+  union {\r
+    ULONGLONG Alignment;\r
+    struct {\r
+      ULONG Length;\r
+      DWORD Reserved;\r
+    };\r
+  };\r
+  struct _IP_ADAPTER_WINS_SERVER_ADDRESS  *Next;\r
+  SOCKET_ADDRESS                         Address;\r
+} IP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS_LH;\r
+\r
+typedef struct _IP_ADAPTER_GATEWAY_ADDRESS {\r
+  union {\r
+    ULONGLONG Alignment;\r
+    struct {\r
+      ULONG Length;\r
+      DWORD Reserved;\r
+    };\r
+  };\r
+  struct _IP_ADAPTER_GATEWAY_ADDRESS  *Next;\r
+  SOCKET_ADDRESS                     Address;\r
+} IP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS_LH;\r
+\r
+typedef UINT32 NET_IF_COMPARTMENT_ID;\r
+typedef GUID NET_IF_NETWORK_GUID;\r
+\r
+typedef enum _NET_IF_CONNECTION_TYPE {\r
+  NET_IF_CONNECTION_DEDICATED   = 1,\r
+  NET_IF_CONNECTION_PASSIVE,\r
+  NET_IF_CONNECTION_DEMAND,\r
+  NET_IF_CONNECTION_MAXIMUM \r
+} NET_IF_CONNECTION_TYPE, *PNET_IF_CONNECTION_TYPE;\r
+\r
+typedef enum  {\r
+  TUNNEL_TYPE_NONE      = 0,\r
+  TUNNEL_TYPE_OTHER,\r
+  TUNNEL_TYPE_DIRECT,\r
+  TUNNEL_TYPE_6TO4,\r
+  TUNNEL_TYPE_ISATAP,\r
+  TUNNEL_TYPE_TEREDO,\r
+  TUNNEL_TYPE_IPHTTPS \r
+} TUNNEL_TYPE, *PTUNNEL_TYPE;\r
 \r
-int plibc_conv_to_win_path(const char *pszUnix, char *pszWindows);\r
+/*\r
+A DUID consists of a two-octet type code represented in network byte\r
+   order, followed by a variable number of octets that make up the\r
+   actual identifier.  A DUID can be no more than 128 octets long (not\r
+   including the type code).\r
+*/\r
+#define MAX_DHCPV6_DUID_LENGTH 130\r
+\r
+typedef union _NET_LUID {\r
+  ULONG64 Value;\r
+  struct {\r
+    ULONG64 Reserved  :24;\r
+    ULONG64 NetLuidIndex  :24;\r
+    ULONG64 IfType  :16;\r
+  } Info;\r
+} NET_LUID, *PNET_LUID, IF_LUID;\r
+\r
+#define MAX_DNS_SUFFIX_STRING_LENGTH 246\r
+\r
+typedef struct _IP_ADAPTER_DNS_SUFFIX {\r
+  struct _IP_ADAPTER_DNS_SUFFIX  *Next;\r
+  WCHAR                         String[MAX_DNS_SUFFIX_STRING_LENGTH];\r
+} IP_ADAPTER_DNS_SUFFIX, *PIP_ADAPTER_DNS_SUFFIX;\r
+\r
+\r
+\r
+#define _IP_ADAPTER_ADDRESSES_HEAD \\r
+  union { \\r
+    ULONGLONG Alignment; \\r
+    struct { \\r
+      ULONG Length; \\r
+      DWORD IfIndex; \\r
+    }; \\r
+  };\r
+\r
+#define _IP_ADAPTER_ADDRESSES_BASE \\r
+  PCHAR                              AdapterName; \\r
+  PIP_ADAPTER_UNICAST_ADDRESS        FirstUnicastAddress; \\r
+  PIP_ADAPTER_ANYCAST_ADDRESS        FirstAnycastAddress; \\r
+  PIP_ADAPTER_MULTICAST_ADDRESS      FirstMulticastAddress; \\r
+  PIP_ADAPTER_DNS_SERVER_ADDRESS     FirstDnsServerAddress; \\r
+  PWCHAR                             DnsSuffix; \\r
+  PWCHAR                             Description; \\r
+  PWCHAR                             FriendlyName; \\r
+  BYTE                               PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH]; \\r
+  DWORD                              PhysicalAddressLength; \\r
+  DWORD                              Flags; \\r
+  DWORD                              Mtu; \\r
+  DWORD                              IfType; \\r
+  IF_OPER_STATUS                     OperStatus;\r
+\r
+#define _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \\r
+  DWORD                              Ipv6IfIndex; \\r
+  DWORD                              ZoneIndices[16]; \\r
+  PIP_ADAPTER_PREFIX                 FirstPrefix; \\r
+\r
+\r
+#define _IP_ADAPTER_ADDRESSES_ADD_VISTA \\r
+  _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \\r
+  ULONG64                            TransmitLinkSpeed; \\r
+  ULONG64                            ReceiveLinkSpeed; \\r
+  PIP_ADAPTER_WINS_SERVER_ADDRESS_LH FirstWinsServerAddress; \\r
+  PIP_ADAPTER_GATEWAY_ADDRESS_LH     FirstGatewayAddress; \\r
+  ULONG                              Ipv4Metric; \\r
+  ULONG                              Ipv6Metric; \\r
+  IF_LUID                            Luid; \\r
+  SOCKET_ADDRESS                     Dhcpv4Server; \\r
+  NET_IF_COMPARTMENT_ID              CompartmentId; \\r
+  NET_IF_NETWORK_GUID                NetworkGuid; \\r
+  NET_IF_CONNECTION_TYPE             ConnectionType; \\r
+  TUNNEL_TYPE                        TunnelType; \\r
+  SOCKET_ADDRESS                     Dhcpv6Server; \\r
+  BYTE                               Dhcpv6ClientDuid[MAX_DHCPV6_DUID_LENGTH]; \\r
+  ULONG                              Dhcpv6ClientDuidLength; \\r
+  ULONG                              Dhcpv6Iaid;\r
+\r
+#define _IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1 \\r
+  _IP_ADAPTER_ADDRESSES_ADD_VISTA \\r
+  PIP_ADAPTER_DNS_SUFFIX             FirstDnsSuffix;\r
+\r
+#define _IP_ADAPTER_ADDRESSES_DEFINE(suffix,addition) \\r
+typedef struct _IP_ADAPTER_ADDRESSES##suffix { \\r
+  _IP_ADAPTER_ADDRESSES_HEAD \\r
+  struct _IP_ADAPTER_ADDRESSES##suffix *Next; \\r
+  _IP_ADAPTER_ADDRESSES_BASE \\r
+  addition \\r
+} IP_ADAPTER_ADDRESSES##suffix, *PIP_ADAPTER_ADDRESSES##suffix;\r
+  \r
+\r
+/* _IP_ADAPTER_ADDRESSES_DEFINE(,) defined in w32api headers */\r
+_IP_ADAPTER_ADDRESSES_DEFINE(_XPSP1,_IP_ADAPTER_ADDRESSES_ADD_XPSP1)\r
+_IP_ADAPTER_ADDRESSES_DEFINE(_VISTA,_IP_ADAPTER_ADDRESSES_ADD_VISTA)\r
+_IP_ADAPTER_ADDRESSES_DEFINE(_2008_OR_VISTASP1,_IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1)\r
+\r
+static int\r
+EnumNICs_IPv6_get_ifs_count (SOCKET s)\r
+{\r
+  DWORD dwret = 0, err;\r
+  int iret;\r
+  iret = WSAIoctl (s, SIO_ADDRESS_LIST_QUERY, NULL, 0, NULL, 0,\r
+      &dwret, NULL, NULL);\r
+  err = GetLastError ();\r
+  if (iret == SOCKET_ERROR && err == WSAEFAULT)\r
+    return dwret;\r
+  else if (iret == 0)\r
+    return 0;\r
+  return GNUNET_SYSERR;\r
+}\r
+\r
+static int\r
+EnumNICs_IPv6_get_ifs (SOCKET s, SOCKET_ADDRESS_LIST *inf, int size)\r
+{\r
+  int iret;\r
+  DWORD dwret = 0;\r
+  iret = WSAIoctl (s, SIO_ADDRESS_LIST_QUERY, NULL, 0, inf, size,\r
+      &dwret, NULL, NULL);\r
 \r
-void __attribute__ ((constructor)) gnunet_win_init() {\r
-  hOLLock = CreateMutex(NULL, FALSE, NULL);\r
+  if (iret != 0 || dwret != size)\r
+  {\r
+    /* It's supposed to succeed! And size should be the same */\r
+    return GNUNET_SYSERR;\r
+  }\r
+  return GNUNET_OK;\r
 }\r
 \r
-void __attribute__ ((destructor)) gnunet_win_fini() {\r
-  CloseHandle(hOLLock);\r
+#undef GNUNET_malloc\r
+#define GNUNET_malloc(a) HeapAlloc(GetProcessHeap (), HEAP_ZERO_MEMORY | \\r
+    HEAP_GENERATE_EXCEPTIONS, a)\r
+\r
+#undef GNUNET_free\r
+#define GNUNET_free(a) HeapFree(GetProcessHeap (), 0, a)\r
+\r
+#undef GNUNET_free_non_null\r
+#define GNUNET_free_non_null(a) do { if ((a) != NULL) GNUNET_free(a); } while (0)\r
+\r
+static int\r
+EnumNICs_IPv4_get_ifs (SOCKET s, INTERFACE_INFO **inf, int *size)\r
+{\r
+  int iret;\r
+  DWORD dwret = 0;\r
+  DWORD error;\r
+  INTERFACE_INFO *ii = NULL;\r
+  DWORD ii_size = sizeof (INTERFACE_INFO) * 15;\r
+  while (TRUE)\r
+  {\r
+    if (ii_size >= sizeof (INTERFACE_INFO) * 1000)\r
+      return GNUNET_SYSERR;\r
+    ii = (INTERFACE_INFO *) GNUNET_malloc (ii_size);\r
+    dwret = 0;\r
+    iret = WSAIoctl (s, SIO_GET_INTERFACE_LIST, NULL, 0, ii, ii_size,\r
+        &dwret, NULL, NULL);\r
+    error = GetLastError ();\r
+    if (iret == SOCKET_ERROR)\r
+    {\r
+      if (error == WSAEFAULT)\r
+      {\r
+        GNUNET_free (ii);\r
+        ii_size *= 2;\r
+        continue;\r
+      }\r
+      GNUNET_free (ii);\r
+      return GNUNET_SYSERR;\r
+    }\r
+    else\r
+    {\r
+      *inf = ii;\r
+      *size = dwret;\r
+      return GNUNET_OK;\r
+    }\r
+  }\r
+  return GNUNET_SYSERR;\r
+}\r
+\r
+int\r
+EnumNICs2 (INTERFACE_INFO **ifs4, int *ifs4_len, SOCKET_ADDRESS_LIST **ifs6)\r
+{\r
+  int result = 0;\r
+  SOCKET s4 = INVALID_SOCKET, s6 = INVALID_SOCKET;\r
+  DWORD dwret1 = 0, dwret2;\r
+  DWORD err1, err2;\r
+  int ifs4len = 0, ifs6len = 0;\r
+  INTERFACE_INFO *interfaces4 = NULL;\r
+  SOCKET_ADDRESS_LIST *interfaces6 = NULL;\r
+  SetLastError (0);\r
+  s4 = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);\r
+  err1 = GetLastError ();\r
+  SetLastError (0);\r
+  s6 = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP);\r
+  err2 = GetLastError ();\r
+  if (s6 != INVALID_SOCKET)\r
+  {\r
+    ifs6len = EnumNICs_IPv6_get_ifs_count (s6);\r
+    if (ifs6len > 0)\r
+    {\r
+      interfaces6 = (SOCKET_ADDRESS_LIST *) GNUNET_malloc (ifs6len);\r
+      result = EnumNICs_IPv6_get_ifs (s6, interfaces6, ifs6len) || result;\r
+    }\r
+    closesocket (s6);\r
+    s6 = INVALID_SOCKET;\r
+  }\r
+\r
+  if (s4 != INVALID_SOCKET)\r
+  {\r
+    result = EnumNICs_IPv4_get_ifs (s4, &interfaces4, &ifs4len) || result;\r
+    closesocket (s4);\r
+    s4 = INVALID_SOCKET;\r
+  }\r
+  if (ifs6len + ifs4len == 0)\r
+    goto error;\r
+\r
+  if (!result)\r
+  {\r
+    *ifs4 = interfaces4;\r
+    *ifs4_len = ifs4len;\r
+    *ifs6 = interfaces6;\r
+    return GNUNET_OK;\r
+  }\r
+error:\r
+  if (interfaces4 != NULL)\r
+    GNUNET_free (interfaces4);\r
+  if (interfaces6 != NULL)\r
+    GNUNET_free (interfaces6);\r
+  if (s4 != INVALID_SOCKET)\r
+    closesocket (s4);\r
+  if (s6 != INVALID_SOCKET)\r
+    closesocket (s6);\r
+  return GNUNET_SYSERR;\r
 }\r
 \r
 /**\r
- * Enumerate all network adapters\r
+ * Returns GNUNET_OK on OK, GNUNET_SYSERR on error\r
  */\r
-void EnumNICs(PMIB_IFTABLE *pIfTable, PMIB_IPADDRTABLE *pAddrTable)\r
+int\r
+EnumNICs3 (struct EnumNICs3_results **results, int *results_count)\r
 {\r
-  DWORD dwSize, dwRet;\r
-\r
-  *pIfTable = NULL;\r
+  DWORD dwRetVal = 0;\r
+  int count = 0;\r
+  ULONG flags = /*GAA_FLAG_INCLUDE_PREFIX |*/ GAA_FLAG_SKIP_ANYCAST |\r
+      GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;\r
+  struct sockaddr_in6 examplecom6;\r
+  IPAddr examplecom;\r
+  DWORD best_interface = 0;\r
+  DWORD best_interface6 = 0;\r
+\r
+  int use_enum2 = 0;\r
+  INTERFACE_INFO *interfaces4 = NULL;\r
+  int interfaces4_len = 0;\r
+  SOCKET_ADDRESS_LIST *interfaces6 = NULL;\r
+\r
+  unsigned long outBufLen = sizeof (IP_ADAPTER_ADDRESSES);\r
+  IP_ADAPTER_ADDRESSES *pCurrentAddress = NULL;\r
+  IP_ADAPTER_ADDRESSES *pAddresses = (IP_ADAPTER_ADDRESSES *) GNUNET_malloc (outBufLen);\r
+\r
+  if (GetAdaptersAddresses (AF_UNSPEC, flags, NULL, pAddresses, &outBufLen)\r
+      == ERROR_BUFFER_OVERFLOW)\r
+  {\r
+    GNUNET_free (pAddresses);\r
+    pAddresses = (IP_ADAPTER_ADDRESSES *) GNUNET_malloc (outBufLen);\r
+  }\r
 \r
-  if (pAddrTable)\r
-    *pAddrTable = NULL;\r
+  dwRetVal = GetAdaptersAddresses (AF_UNSPEC, flags, NULL, pAddresses, &outBufLen);\r
 \r
-  if (GNGetIfTable)\r
+  if (dwRetVal != NO_ERROR)\r
   {\r
-    dwSize = dwRet = 0;\r
+    GNUNET_free (pAddresses);\r
+    return GNUNET_SYSERR;\r
+  }\r
 \r
-    *pIfTable = (MIB_IFTABLE *) GlobalAlloc(GPTR, sizeof(MIB_IFTABLE));\r
+  if (pAddresses->Length < sizeof (IP_ADAPTER_ADDRESSES_VISTA))\r
+  {\r
+    use_enum2 = 1;\r
 \r
-    /* Get size of table */\r
-    if (GNGetIfTable(*pIfTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER)\r
+    /* Enumerate NICs using WSAIoctl() */\r
+    if (GNUNET_OK != EnumNICs2 (&interfaces4, &interfaces4_len, &interfaces6))\r
     {\r
-      GlobalFree(*pIfTable);\r
-      *pIfTable = (MIB_IFTABLE *) GlobalAlloc(GPTR, dwSize);\r
+      GNUNET_free (pAddresses);\r
+      return GNUNET_SYSERR;\r
     }\r
+  }\r
 \r
-    if ((dwRet = GNGetIfTable(*pIfTable, &dwSize, 0)) == NO_ERROR &&\r
-      pAddrTable)\r
-    {\r
-      DWORD dwIfIdx, dwSize = sizeof(MIB_IPADDRTABLE);\r
-      *pAddrTable = (MIB_IPADDRTABLE *) GlobalAlloc(GPTR, dwSize);\r
+  examplecom = inet_addr("192.0.34.166"); /* www.example.com */\r
+  if (GetBestInterface (examplecom, &best_interface) != NO_ERROR)\r
+    best_interface = 0;\r
 \r
-      /* Make an initial call to GetIpAddrTable to get the\r
-         necessary size */\r
-      if (GNGetIpAddrTable(*pAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER)\r
+  if (GNGetBestInterfaceEx != NULL)\r
+  {\r
+    examplecom6.sin6_family = AF_INET6;\r
+    examplecom6.sin6_port = 0;\r
+    examplecom6.sin6_flowinfo = 0;\r
+    examplecom6.sin6_scope_id = 0;\r
+    inet_pton (AF_INET6, "2001:500:88:200:0:0:0:10",\r
+        (struct sockaddr *) &examplecom6.sin6_addr);\r
+    dwRetVal = GNGetBestInterfaceEx ((struct sockaddr *) &examplecom6,\r
+        &best_interface6);\r
+    if (dwRetVal != NO_ERROR)\r
+      best_interface6 = 0;\r
+  }\r
+\r
+  /* Give IPv6 a priority */\r
+  if (best_interface6 != 0)\r
+    best_interface = best_interface6;\r
+\r
+  count = 0;\r
+  for (pCurrentAddress = pAddresses;\r
+      pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next)\r
+  {\r
+    if (pCurrentAddress->OperStatus == IfOperStatusUp)\r
+    {\r
+      IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL;\r
+      for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL;\r
+          unicast = unicast->Next)\r
       {\r
-        GlobalFree(*pAddrTable);\r
-        *pAddrTable = (MIB_IPADDRTABLE *) GlobalAlloc(GPTR, dwSize);\r
+        if ((unicast->Address.lpSockaddr->sa_family == AF_INET ||\r
+            unicast->Address.lpSockaddr->sa_family == AF_INET6) &&\r
+            (unicast->DadState == IpDadStateDeprecated ||\r
+            unicast->DadState == IpDadStatePreferred))\r
+          count += 1;\r
       }\r
-      GNGetIpAddrTable(*pAddrTable, &dwSize, 0);\r
     }\r
   }\r
-}\r
 \r
-/**\r
- * Lists all network interfaces in a combo box\r
- * Used by the basic GTK configurator\r
- * @param callback\r
- */\r
-  int ListNICs(void (*callback) (const char *, int, void *), void * cls)\r
-{\r
-  PMIB_IFTABLE pTable;\r
-  PMIB_IPADDRTABLE pAddrTable;\r
-  DWORD dwIfIdx, dwExternalNIC;\r
-  IPAddr theIP;\r
-\r
-  /* Determine our external NIC  */\r
-  theIP = inet_addr("192.0.34.166"); /* www.example.com */\r
-  if ((! GNGetBestInterface) ||\r
-      (GNGetBestInterface(theIP, &dwExternalNIC) != NO_ERROR))\r
+  if (count == 0)\r
   {\r
-    dwExternalNIC = 0;\r
+    *results = NULL;\r
+    *results_count = 0;\r
+    GNUNET_free (pAddresses);\r
+    GNUNET_free_non_null (interfaces4);\r
+    GNUNET_free_non_null (interfaces6);\r
+    return GNUNET_OK;\r
   }\r
 \r
-  /* Enumerate NICs */\r
-  EnumNICs(&pTable, &pAddrTable);\r
+  *results = (struct EnumNICs3_results *) GNUNET_malloc (\r
+      sizeof (struct EnumNICs3_results) * count);\r
+  *results_count = count;\r
 \r
-  if (pTable)\r
+  count = 0;\r
+  for (pCurrentAddress = pAddresses;\r
+      pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next)\r
   {\r
-    for(dwIfIdx=0; dwIfIdx <= pTable->dwNumEntries; dwIfIdx++)\r
+    struct EnumNICs3_results *r;\r
+    IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL;\r
+    if (pCurrentAddress->OperStatus != IfOperStatusUp)\r
+      continue;\r
+    for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL;\r
+        unicast = unicast->Next)\r
     {\r
-      char szEntry[1001];\r
-      DWORD dwIP = 0;\r
-      int iItm;\r
-               PIP_ADAPTER_INFO pAdapterInfo;\r
-               PIP_ADAPTER_INFO pAdapter = NULL;\r
-               DWORD dwRetVal = 0;\r
-\r
-      /* Get IP-Address */\r
-      int i;\r
-      for(i = 0; i < pAddrTable->dwNumEntries; i++)\r
+      int i, j;\r
+      int mask_length = -1;\r
+      char dst[INET6_ADDRSTRLEN + 1];\r
+\r
+      if ((unicast->Address.lpSockaddr->sa_family != AF_INET &&\r
+          unicast->Address.lpSockaddr->sa_family != AF_INET6) ||\r
+          (unicast->DadState != IpDadStateDeprecated &&\r
+          unicast->DadState != IpDadStatePreferred))\r
+        continue;\r
+\r
+      r = &(*results)[count];\r
+      r->flags = 0;\r
+      if (pCurrentAddress->IfIndex > 0 &&\r
+          pCurrentAddress->IfIndex == best_interface &&\r
+          unicast->Address.lpSockaddr->sa_family == AF_INET)\r
+        r->is_default = 1;\r
+      else if (pCurrentAddress->Ipv6IfIndex > 0 &&\r
+          pCurrentAddress->Ipv6IfIndex == best_interface6 &&\r
+          unicast->Address.lpSockaddr->sa_family == AF_INET6)\r
+        r->is_default = 1;\r
+      else\r
+        r->is_default = 0;\r
+\r
+      /* Don't choose default interface twice */\r
+      if (r->is_default)\r
+        best_interface = best_interface6 = 0;\r
+\r
+      if (!use_enum2)\r
       {\r
-        if (pAddrTable->table[i].dwIndex == pTable->table[dwIfIdx].dwIndex)\r
+        memcpy (&r->address, unicast->Address.lpSockaddr,\r
+            unicast->Address.iSockaddrLength);\r
+        memset (&r->mask, 0, sizeof (struct sockaddr));\r
+        mask_length = ((IP_ADAPTER_UNICAST_ADDRESS_VISTA *) unicast)->\r
+              OnLinkPrefixLength;\r
+        /* OnLinkPrefixLength is the number of leading 1s in the mask.\r
+         * OnLinkPrefixLength is available on Vista and later (hence use_enum2).\r
+         */\r
+        if (unicast->Address.lpSockaddr->sa_family == AF_INET)\r
         {\r
-          dwIP = pAddrTable->table[i].dwAddr;\r
-          break;\r
+          struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;\r
+          for (i = 0; i < mask_length; i++)\r
+              ((unsigned char *) &m->sin_addr)[i / 8] |= 0x80 >> (i % 8);\r
         }\r
+        else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)\r
+        {\r
+          struct sockaddr_in6 *m = (struct sockaddr_in6 *) &r->mask;\r
+          struct sockaddr_in6 *b = (struct sockaddr_in6 *) &r->broadcast;\r
+          for (i = 0; i < mask_length; i++)\r
+            ((unsigned char *) &m->sin6_addr)[i / 8] |= 0x80 >> (i % 8);\r
+          memcpy (&r->broadcast, &r->address, unicast->Address.iSockaddrLength);\r
+          for (i = mask_length; i < 128; i++)\r
+            ((unsigned char *) &b->sin6_addr)[i / 8] |= 0x80 >> (i % 8);\r
+        }\r
+        r->flags |= ENUMNICS3_MASK_OK;\r
       }\r
-\r
-      if (dwIP)\r
+      else\r
+      {\r
+        int found = 0;\r
+        if (unicast->Address.lpSockaddr->sa_family == AF_INET)\r
+        {\r
+          for (i = 0; !found && i < interfaces4_len / sizeof (INTERFACE_INFO); i++)\r
+          {\r
+            struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;\r
+            if (memcpy (&interfaces4[i].iiAddress.Address,\r
+                unicast->Address.lpSockaddr,\r
+                unicast->Address.iSockaddrLength) != 0)\r
+              continue;\r
+            found = 1;\r
+            memcpy (&r->address, &interfaces4[i].iiAddress.Address,\r
+                sizeof (struct sockaddr_in));\r
+            memcpy (&r->mask, &interfaces4[i].iiNetmask.Address,\r
+                sizeof (struct sockaddr_in));\r
+            for (mask_length = 0;\r
+                ((unsigned char *) &m->sin_addr)[mask_length / 8] &\r
+                0x80 >> (mask_length % 8); mask_length++)\r
+            {\r
+            }\r
+            r->flags |= ENUMNICS3_MASK_OK;\r
+          }\r
+        }\r
+        else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)\r
+        {\r
+          for (i = 0;\r
+              interfaces6 != NULL && !found && i < interfaces6->iAddressCount;\r
+              i++)\r
+          {\r
+            if (memcpy (interfaces6->Address[i].lpSockaddr,\r
+                unicast->Address.lpSockaddr,\r
+                unicast->Address.iSockaddrLength) != 0)\r
+              continue;\r
+            found = 1;\r
+            memcpy (&r->address, interfaces6->Address[i].lpSockaddr,\r
+                sizeof (struct sockaddr_in6));\r
+            /* TODO: Find a way to reliably get network mask for IPv6 on XP */\r
+            memset (&r->mask, 0, sizeof (struct sockaddr));\r
+            r->flags &= ~ENUMNICS3_MASK_OK;\r
+          }\r
+        }\r
+        if (!found)\r
+        {\r
+          DebugBreak ();\r
+        }\r
+      }\r
+      if (unicast->Address.lpSockaddr->sa_family == AF_INET)\r
       {\r
-        BYTE bPhysAddr[MAXLEN_PHYSADDR];\r
-                 char *pszIfName = NULL;\r
-        char dst[INET_ADDRSTRLEN];\r
-\r
-        /* Get friendly interface name */\r
-                       pAdapterInfo = (IP_ADAPTER_INFO *) malloc(sizeof(IP_ADAPTER_INFO));\r
-                       ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);\r
-\r
-                       /* Make an initial call to GetAdaptersInfo to get\r
-                          the necessary size into the ulOutBufLen variable */\r
-                       if (GGetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {\r
-                         free(pAdapterInfo);\r
-                         pAdapterInfo = (IP_ADAPTER_INFO *) malloc (ulOutBufLen);\r
-                       }\r
-\r
-                       if ((dwRetVal = GGetAdaptersInfo( pAdapterInfo, &ulOutBufLen)) == NO_ERROR) {\r
-                         pAdapter = pAdapterInfo;\r
-                         while (pAdapter) {\r
-                               if (pTable->table[dwIfIdx].dwIndex == pAdapter->Index)\r
-                               {\r
-                                       char szKey[251];\r
-                                       long lLen = 250;\r
-\r
-                                       sprintf(szKey, "SYSTEM\\CurrentControlSet\\Control\\Network\\"\r
-                                               "{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection",\r
-                                               pAdapter->AdapterName);\r
-                                       pszIfName = (char *) malloc(251);\r
-                                       if (QueryRegistry(HKEY_LOCAL_MACHINE, szKey, "Name", pszIfName,\r
-                                               &lLen) != ERROR_SUCCESS)\r
-                                       {\r
-                                               free(pszIfName);\r
-                                               pszIfName = NULL;\r
-                                       }\r
-                               }\r
-                           pAdapter = pAdapter->Next;\r
-                         }\r
-                       }\r
-                       free(pAdapterInfo);\r
-\r
-                       /* Set entry */\r
-        memset(bPhysAddr, 0, MAXLEN_PHYSADDR);\r
-        memcpy(bPhysAddr,\r
-          pTable->table[dwIfIdx].bPhysAddr,\r
-          pTable->table[dwIfIdx].dwPhysAddrLen);\r
-\r
-        snprintf(szEntry, 1000, "%s (%s - %I64u)",\r
-          pszIfName ? pszIfName : (char *) pTable->table[dwIfIdx].bDescr,\r
-          inet_ntop (AF_INET, &dwIP, dst, INET_ADDRSTRLEN),\r
-          *((unsigned long long *) bPhysAddr));\r
-        szEntry[1000] = 0;\r
-\r
-        if (pszIfName)\r
-               free(pszIfName);\r
-\r
-        callback(szEntry, pAddrTable->table[dwIfIdx].dwIndex == dwExternalNIC, cls);\r
+        struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;\r
+        struct sockaddr_in *a = (struct sockaddr_in *) &r->address;\r
+        /* copy address to broadcast, then flip all the trailing bits not\r
+         * falling under netmask to 1,\r
+         * so we get, 192.168.0.255 from, say, 192.168.0.43 with mask == 24.\r
+         */\r
+        memcpy (&r->broadcast, &r->address, unicast->Address.iSockaddrLength);\r
+        for (i = mask_length; i < 32; i++)\r
+          ((unsigned char *) &m->sin_addr)[i / 8] |= 0x80 >> (i % 8);\r
+        r->flags |= ENUMNICS3_BCAST_OK;\r
+        r->addr_size = sizeof (struct sockaddr_in);\r
+        inet_ntop (AF_INET, &a->sin_addr, dst, INET_ADDRSTRLEN);\r
       }\r
+      else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)\r
+      {\r
+        struct sockaddr_in6 *a = (struct sockaddr_in6 *) &r->address;\r
+        /* for IPv6 broadcast is not defined, zero it down */\r
+        memset (&r->broadcast, 0, sizeof (struct sockaddr));\r
+        r->flags &= ~ENUMNICS3_BCAST_OK;\r
+        r->addr_size = sizeof (struct sockaddr_in6);\r
+        inet_ntop (AF_INET6, &a->sin6_addr, dst, INET6_ADDRSTRLEN);\r
+      }\r
+\r
+      i = 0;\r
+      i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0,\r
+          "%S (%s", pCurrentAddress->FriendlyName, dst);\r
+      for (j = 0; j < pCurrentAddress->PhysicalAddressLength; j++)\r
+        i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0,\r
+            "%s%02X",j > 0 ? ":" : " - ", pCurrentAddress->PhysicalAddress[j]);\r
+      i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0, ")");\r
+      r->pretty_name[1000] = '\0';\r
+      count += 1;\r
     }\r
-    GlobalFree(pAddrTable);\r
-    GlobalFree(pTable);\r
   }\r
 \r
+  if (use_enum2)\r
+  {\r
+    GNUNET_free_non_null (interfaces4);\r
+    GNUNET_free_non_null (interfaces6);\r
+  }\r
+\r
+  GNUNET_free (pAddresses);\r
+  return GNUNET_OK;\r
+}\r
+\r
+void\r
+EnumNICs3_free (struct EnumNICs3_results *r)\r
+{\r
+  GNUNET_free_non_null (r);\r
+}\r
+\r
+\r
+/**\r
+ * Lists all network interfaces in a combo box\r
+ * Used by the basic GTK configurator\r
+ *\r
+ * @param callback function to call for each NIC\r
+ * @param callback_cls closure for callback\r
+ */\r
+int\r
+ListNICs (void (*callback) (void *, const char *, int), void * callback_cls)\r
+{\r
+  int r;\r
+  int i;\r
+  struct EnumNICs3_results *results = NULL;\r
+  int results_count;\r
+\r
+  r = EnumNICs3 (&results, &results_count);\r
+  if (r != GNUNET_OK)\r
+    return GNUNET_NO;\r
+\r
+  for (i = 0; i < results_count; i++)\r
+    callback (callback_cls, results[i].pretty_name, results[i].is_default);\r
+  GNUNET_free_non_null (results);\r
   return GNUNET_YES;\r
 }\r
 \r
@@ -355,7 +793,7 @@ NTSTATUS _OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyH
  * @remarks Call GetLastError() to obtain extended error information.\r
  * @see http://support.microsoft.com/?scid=kb;en-us;132958\r
  */\r
-BOOL _GetAccountSid(LPTSTR SystemName, LPTSTR AccountName, PSID * Sid)\r
+BOOL _GetAccountSid(LPCTSTR SystemName, LPCTSTR AccountName, PSID * Sid)\r
 {\r
   LPTSTR ReferencedDomain = NULL;\r
   DWORD cbSid = 128;                                                   /* initial allocation attempt */\r
@@ -461,7 +899,7 @@ NTSTATUS _SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle,/* open policy handle */
  * @param pszName the name of the account\r
  * @param pszDesc description of the account\r
  */\r
-int CreateServiceAccount(char *pszName, char *pszDesc)\r
+int CreateServiceAccount(const char *pszName, const char *pszDesc)\r
 {\r
   USER_INFO_1 ui;\r
   USER_INFO_1008 ui2;\r
@@ -495,14 +933,14 @@ int CreateServiceAccount(char *pszName, char *pszDesc)
                                                                                STATUS_SUCCESS)\r
        return 3;\r
 \r
-  _GetAccountSid(NULL, (LPTSTR) pszName, &pSID);\r
+  _GetAccountSid(NULL, (LPCTSTR) pszName, &pSID);\r
 \r
-  if (_SetPrivilegeOnAccount(hPolicy, pSID, L"SeServiceLogonRight", TRUE) != STATUS_SUCCESS)\r
+  if (_SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeServiceLogonRight", TRUE) != STATUS_SUCCESS)\r
        return 4;\r
 \r
-  _SetPrivilegeOnAccount(hPolicy, pSID, L"SeDenyInteractiveLogonRight", TRUE);\r
-  _SetPrivilegeOnAccount(hPolicy, pSID, L"SeDenyBatchLogonRight", TRUE);\r
-  _SetPrivilegeOnAccount(hPolicy, pSID, L"SeDenyNetworkLogonRight", TRUE);\r
+  _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeDenyInteractiveLogonRight", TRUE);\r
+  _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeDenyBatchLogonRight", TRUE);\r
+  _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeDenyNetworkLogonRight", TRUE);\r
 \r
   GNLsaClose(hPolicy);\r
 \r
@@ -513,7 +951,7 @@ int CreateServiceAccount(char *pszName, char *pszDesc)
  * @brief Grant permission to a file\r
  * @param lpszFileName the name of the file or directory\r
  * @param lpszAccountName the user account\r
- * @param the desired access (e.g. GENERIC_ALL)\r
+ * @param dwAccessMask the desired access (e.g. GENERIC_ALL)\r
  * @return TRUE on success\r
  * @remark based on http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q102102&\r
  */\r
@@ -810,7 +1248,7 @@ char *winErrorStr(const char *prefix, int dwErr)
     NULL, (DWORD) dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &err,\r
     0, NULL ))\r
   {\r
-    err = "";\r
+    err = (char *) LocalAlloc (LMEM_FIXED | LMEM_ZEROINIT, 1);\r
   }\r
 \r
   mem = strlen(err) + strlen(prefix) + 20;\r