make single label resolution work (for pkey at least
[oweals/gnunet.git] / src / gns / w32nsp-resolve.c
index f5ba22478fa946146e7daac5aed82cc82b2e046e..841f5b9e6652e1f8d5053a2f014df4b04641c681 100644 (file)
@@ -1,20 +1,47 @@
-#define INITGUID\r
-#include <windows.h>\r
-#include <nspapi.h>\r
-#include <ws2spi.h>\r
-#include <nspapi.h>\r
-#include <ws2tcpip.h>\r
-#include <gnunet_w32nsp_lib.h>\r
-#include <stdio.h>\r
-\r
-typedef int (WSPAPI *LPNSPSTARTUP) (LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines);\r
-\r
-GUID host = {0x0002a800,0,0,{ 0xC0,0,0,0,0,0,0,0x46 }};\r
-GUID ip4 = {0x00090035,0,1,{ 0xc0,0,0,0,0,0,0,0x046}}; \r
-GUID ip6 = {0x00090035,0,0x001c, { 0xc0,0,0,0,0,0,0,0x046}};\r
-\r
-DEFINE_GUID(W32_DNS, 0x22059D40, 0x7E9E, 0x11CF, 0xAE, 0x5A, 0x00, 0xAA, 0x00, 0xA7, 0x11, 0x2B);\r
-\r
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2012 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Affero General Public License for more details.
+    
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+*/
+/**
+ * @file gns/w32nsp-resolve.c
+ * @brief W32 integration for GNS
+ * @author LRN
+ */
+/* Instead of including gnunet_common.h */
+#define GNUNET_memcpy(dst,src,n) do { if (0 != n) { (void) memcpy (dst,src,n); } } while (0)
+
+#include <ws2tcpip.h>
+#include <windows.h>
+#include <nspapi.h>
+#include <ws2spi.h>
+#include <nspapi.h>
+#include <initguid.h>
+#include "gnunet_w32nsp_lib.h"
+#include <stdio.h>
+
+typedef int (WSPAPI *LPNSPSTARTUP) (LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines);
+
+GUID host = {0x0002a800,0,0,{ 0xC0,0,0,0,0,0,0,0x46 }};
+GUID ip4 = {0x00090035,0,1,{ 0xc0,0,0,0,0,0,0,0x046}};
+GUID ip6 = {0x00090035,0,0x001c, { 0xc0,0,0,0,0,0,0,0x046}};
+
+DEFINE_GUID(W32_DNS, 0x22059D40, 0x7E9E, 0x11CF, 0xAE, 0x5A, 0x00, 0xAA, 0x00, 0xA7, 0x11, 0x2B);
+
 #define DEFINE_DNS_GUID(a,x) DEFINE_GUID(a, 0x00090035, 0x0000, x, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)
 DEFINE_DNS_GUID(SVCID_DNS_TYPE_A, 0x0001);
 DEFINE_DNS_GUID(SVCID_DNS_TYPE_NS, 0x0002);
@@ -27,314 +54,393 @@ DEFINE_DNS_GUID(SVCID_DNS_TYPE_AAAA, 0x001c);
 DEFINE_DNS_GUID(SVCID_DNS_TYPE_SRV, 0x0021);
 DEFINE_GUID(SVCID_HOSTNAME, 0x0002a800, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
 DEFINE_GUID(SVCID_INET_HOSTADDRBYNAME, 0x0002a803, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
-\r
-//\r
-// Utility to turn a list of offsets into a list of addresses. Used\r
-// to convert structures returned as BLOBs.\r
-//\r
-\r
-VOID FixList(PCHAR ** List, PCHAR Base)\r
-{\r
-    if(*List)\r
-    {\r
-        PCHAR * Addr;\r
-\r
-        Addr = *List = (PCHAR *)( ((DWORD)*List + Base) );\r
-        while(*Addr)\r
-        {\r
-            *Addr = (PCHAR)(((DWORD)*Addr + Base));\r
-            Addr++;\r
-        }\r
-    }\r
-}\r
-\r
-\r
-//\r
-// Routine to convert a hostent returned in a BLOB to one with\r
-// usable pointers. The structure is converted in-place.\r
-//\r
-VOID UnpackHostEnt(struct hostent * hostent)\r
-{\r
-     PCHAR pch;\r
-\r
-     pch = (PCHAR)hostent;\r
-\r
-     if(hostent->h_name)\r
-     {\r
-         hostent->h_name = (PCHAR)((DWORD)hostent->h_name + pch);\r
-     }\r
-     FixList(&hostent->h_aliases, pch);\r
-     FixList(&hostent->h_addr_list, pch);\r
-}\r
-\r
-void\r
-print_hostent (struct hostent *he)\r
-{\r
-  int i;\r
-  char **pAlias;\r
-  printf("\tOfficial name: %s\n", he->h_name);\r
-  for (pAlias = he->h_aliases; *pAlias != 0; pAlias++) {\r
-      printf("\tAlternate name #%d: %s\n", ++i, *pAlias);\r
-  }\r
-  printf("\tAddress type: ");\r
-  switch (he->h_addrtype) {\r
-  case AF_INET:\r
-      printf("AF_INET\n");\r
-      break;\r
-  case AF_INET6:\r
-      printf("AF_INET6\n");\r
-      break;\r
-  case AF_NETBIOS:\r
-      printf("AF_NETBIOS\n");\r
-      break;\r
-  default:\r
-      printf(" %d\n", he->h_addrtype);\r
-      break;\r
-  }\r
-  printf("\tAddress length: %d\n", he->h_length);\r
-\r
-  if (he->h_addrtype == AF_INET) {\r
-    struct sockaddr_in addr;\r
-    memset (&addr, 0, sizeof (addr));\r
-    addr.sin_family = AF_INET;\r
-    addr.sin_port = 0;\r
-    i = 0;\r
-    while (he->h_addr_list[i] != 0) {\r
-      char buf[1024];\r
-      DWORD buflen = 1024;\r
-      addr.sin_addr = *(struct in_addr *) he->h_addr_list[i++];\r
-      if (NO_ERROR == WSAAddressToStringA ((LPSOCKADDR) &addr, sizeof (addr), NULL, buf, &buflen))\r
-        printf("\tIPv4 Address #%d: %s\n", i, buf);\r
-      else\r
-        printf("\tIPv4 Address #%d: Can't convert: %lu\n", i, GetLastError ());\r
-    }\r
-  } else if (he->h_addrtype == AF_INET6) {\r
-    struct sockaddr_in6 addr;\r
-    memset (&addr, 0, sizeof (addr));\r
-    addr.sin6_family = AF_INET6;\r
-    addr.sin6_port = 0;\r
-    i = 0;\r
-    while (he->h_addr_list[i] != 0) {\r
-      char buf[1024];\r
-      DWORD buflen = 1024;\r
-      addr.sin6_addr = *(struct in6_addr *) he->h_addr_list[i++];\r
-      if (NO_ERROR == WSAAddressToStringA ((LPSOCKADDR) &addr, sizeof (addr), NULL, buf, &buflen))\r
-        printf("\tIPv6 Address #%d: %s\n", i, buf);\r
-      else\r
-        printf("\tIPv6 Address #%d: Can't convert: %lu\n", i, GetLastError ());\r
-    }\r
-  }\r
-}\r
-\r
-int\r
-main (int argc, char **argv)\r
-{\r
-  int ret;\r
-  int r = 1;\r
-  WSADATA wsd;\r
-  GUID *prov = NULL;\r
-  GUID *sc = NULL;\r
-  wchar_t *cmdl;\r
-  int wargc;\r
-  wchar_t **wargv;\r
-\r
-  if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)\r
-  {\r
-    fprintf (stderr, "WSAStartup() failed: %lu\n", GetLastError());\r
-    return 5;\r
-  }\r
-\r
-  cmdl = GetCommandLineW ();\r
-  if (cmdl == NULL)\r
-  {\r
-    WSACleanup();\r
-    return 2;\r
-  }\r
-  wargv = CommandLineToArgvW (cmdl, &wargc);\r
-  if (wargv == NULL)\r
-  {\r
-    WSACleanup();\r
-    return 3;\r
-  }\r
-  r = 4;\r
-\r
-  if (wargc == 5)\r
-  {\r
-    if (wcscmp (wargv[1], L"A") == 0)\r
-      sc = &SVCID_DNS_TYPE_A;\r
-    else if (wcscmp (wargv[1], L"AAAA") == 0)\r
-      sc = &SVCID_DNS_TYPE_AAAA;\r
-    else if (wcscmp (wargv[1], L"name") == 0)\r
-      sc = &SVCID_HOSTNAME;\r
-    else if (wcscmp (wargv[1], L"addr") == 0)\r
-      sc = &SVCID_INET_HOSTADDRBYNAME;\r
-    else\r
-      wargc -= 1;\r
-    if (wcscmp (wargv[4], L"mswdns") == 0)\r
-      prov = &W32_DNS;\r
-    else if (wcscmp (wargv[4], L"gnunetdns") == 0)\r
-      prov = &GNUNET_NAMESPACE_PROVIDER_DNS;\r
-    else\r
-      wargc -= 1;\r
-  }\r
-\r
-  if (wargc == 5)\r
-  {\r
-    HMODULE nsp;\r
-   \r
-    nsp = LoadLibraryW (wargv[3]);\r
-    if (nsp == NULL)\r
-    {\r
-      fprintf (stderr, "Failed to load library `%S'\n", wargv[3]);\r
-    }\r
-    else\r
-    {\r
-      LPNSPSTARTUP startup = (LPNSPSTARTUP) GetProcAddress (nsp, "NSPStartup");\r
-      if (startup != NULL)\r
-      {\r
-        NSP_ROUTINE api;\r
-        ret = startup (prov, &api);\r
-        if (NO_ERROR != ret)\r
-          fprintf (stderr, "startup failed\n");\r
-        else\r
-        {\r
-          HANDLE lookup;\r
-          WSAQUERYSETW search;\r
-          char buf[4096];\r
-          WSAQUERYSETW *result = (WSAQUERYSETW *) buf;\r
-          DWORD resultsize;\r
-          DWORD err;\r
-          memset (&search, 0, sizeof (search));\r
-          search.dwSize = sizeof (search);\r
-          search.lpszServiceInstanceName = (wcscmp (wargv[2], L" ") == 0) ? NULL : wargv[2];\r
-          search.lpServiceClassId = sc;\r
-          search.lpNSProviderId = prov;\r
-          search.dwNameSpace = NS_ALL;\r
-          ret = api.NSPLookupServiceBegin (prov, &search, NULL, LUP_RETURN_ALL, &lookup);\r
-          if (ret != NO_ERROR)\r
-          {\r
-            fprintf (stderr, "lookup start failed\n");\r
-          }\r
-          else\r
-          {\r
-            resultsize = 4096;\r
-            ret = api.NSPLookupServiceNext (lookup, LUP_RETURN_ALL, &resultsize, result);\r
-            err = GetLastError ();\r
-            if (ret != NO_ERROR)\r
-            {\r
-              fprintf (stderr, "lookup next failed\n");\r
-            }\r
-            else\r
-            {\r
-              int i;\r
-              printf ("Got result:\n");\r
-              printf ("  lpszServiceInstanceName: %S\n", result->lpszServiceInstanceName ? result->lpszServiceInstanceName : L"NULL");\r
-              if (result->lpServiceClassId)\r
-                printf ("  lpServiceClassId:        { 0x%08lX,0x%04X,0x%04X, { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X } }\n",\r
-                    result->lpServiceClassId->Data1, result->lpServiceClassId->Data2, result->lpServiceClassId->Data3, result->lpServiceClassId->Data4[0],\r
-                    result->lpServiceClassId->Data4[1], result->lpServiceClassId->Data4[2], result->lpServiceClassId->Data4[3], result->lpServiceClassId->Data4[4],\r
-                    result->lpServiceClassId->Data4[5], result->lpServiceClassId->Data4[6], result->lpServiceClassId->Data4[7]);\r
-              else\r
-                printf ("  lpServiceClassId:        NULL\n");\r
-              if (result->lpVersion)\r
-                printf ("  lpVersion:               0x%08lX, %d\n", result->lpVersion->dwVersion, result->lpVersion->ecHow);\r
-              else\r
-                printf ("  lpVersion:               NULL\n");\r
-              printf ("  lpszComment:             %S\n", result->lpszComment ? result->lpszComment : L"NULL");\r
-              printf ("  dwNameSpace:             %lu\n", result->dwNameSpace);\r
-              if (result->lpNSProviderId)\r
-                printf ("  lpNSProviderId:          { 0x%08lX,0x%04X,0x%04X, { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X } }\n",\r
-                    result->lpNSProviderId->Data1, result->lpNSProviderId->Data2, result->lpNSProviderId->Data3, result->lpNSProviderId->Data4[0],\r
-                    result->lpNSProviderId->Data4[1], result->lpNSProviderId->Data4[2], result->lpNSProviderId->Data4[3], result->lpNSProviderId->Data4[4],\r
-                    result->lpNSProviderId->Data4[5], result->lpNSProviderId->Data4[6], result->lpNSProviderId->Data4[7]);\r
-              else\r
-                printf ("  lpNSProviderId:          NULL\n");\r
-              printf ("  lpszContext:             %S\n", result->lpszContext ? result->lpszContext : L"NULL");\r
-              printf ("  dwNumberOfProtocols:     %lu\n", result->dwNumberOfProtocols);\r
-              printf ("  lpszQueryString:         %S\n", result->lpszQueryString ? result->lpszQueryString : L"NULL");\r
-              printf ("  dwNumberOfCsAddrs:       %lu\n", result->dwNumberOfCsAddrs);\r
-              for (i = 0; i < result->dwNumberOfCsAddrs; i++)\r
-              {\r
-                switch (result->lpcsaBuffer[i].iSocketType)\r
-                {\r
-                case SOCK_STREAM:\r
-                  printf ("    %d: iSocketType = SOCK_STREAM\n", i);\r
-                  break;\r
-                case SOCK_DGRAM:\r
-                  printf ("    %d: iSocketType = SOCK_DGRAM\n", i);\r
-                  break;\r
-                default:\r
-                  printf ("    %d: iSocketType = %d\n", i, result->lpcsaBuffer[i].iSocketType);\r
-                }\r
-                switch (result->lpcsaBuffer[i].iProtocol)\r
-                {\r
-                case IPPROTO_TCP:\r
-                  printf ("    %d: iProtocol   = IPPROTO_TCP\n", i);\r
-                  break;\r
-                case IPPROTO_UDP:\r
-                  printf ("    %d: iProtocol   = IPPROTO_UDP\n", i);\r
-                  break;\r
-                default:\r
-                  printf ("    %d: iProtocol   = %d\n", i, result->lpcsaBuffer[i].iProtocol);\r
-                }\r
-                switch (result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family)\r
-                {\r
-                case AF_INET:\r
-                  printf ("    %d: loc family  = AF_INET\n", i);\r
-                  break;\r
-                case AF_INET6:\r
-                  printf ("    %d: loc family  = AF_INET6\n", i);\r
-                  break;\r
-                default:\r
-                  printf ("    %d: loc family  = %hu\n", i, result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family);\r
-                }\r
-                switch (result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family)\r
-                {\r
-                case AF_INET:\r
-                  printf ("    %d: rem family  = AF_INET\n", i);\r
-                  break;\r
-                case AF_INET6:\r
-                  printf ("    %d: rem family  = AF_INET6\n", i);\r
-                  break;\r
-                default:\r
-                  printf ("    %d: rem family = %hu\n", i, result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family);\r
-                }\r
-                char buf[1024];\r
-                DWORD buflen = 1024;\r
-                if (NO_ERROR == WSAAddressToStringA (result->lpcsaBuffer[i].LocalAddr.lpSockaddr, result->lpcsaBuffer[i].LocalAddr.iSockaddrLength, NULL, buf, &buflen))\r
-                  printf("\tLocal Address #%d: %s\n", i, buf);\r
-                else\r
-                  printf("\tLocal Address #%d: Can't convert: %lu\n", i, GetLastError ());\r
-                buflen = 1024;\r
-                if (NO_ERROR == WSAAddressToStringA (result->lpcsaBuffer[i].RemoteAddr.lpSockaddr, result->lpcsaBuffer[i].RemoteAddr.iSockaddrLength, NULL, buf, &buflen))\r
-                  printf("\tRemote Address #%d: %s\n", i, buf);\r
-                else\r
-                  printf("\tRemote Address #%d: Can't convert: %lu\n", i, GetLastError ());\r
-              }\r
-              printf ("  dwOutputFlags:           0x%08lX\n", result->dwOutputFlags);\r
-              printf ("  lpBlob:                  0x%p\n", result->lpBlob);\r
-              if (result->lpBlob)\r
-              {\r
-                struct hostent *he = malloc (result->lpBlob->cbSize);\r
-                if (he != NULL)\r
-                {\r
-                  memcpy (he, result->lpBlob->pBlobData, result->lpBlob->cbSize);\r
-                  UnpackHostEnt (he);\r
-                  print_hostent (he);\r
-                  free (he);\r
-                }\r
-              }\r
-            }\r
-            ret = api.NSPLookupServiceEnd (lookup);\r
-            if (ret != NO_ERROR)\r
-              printf ("NSPLookupServiceEnd() failed: %lu\n", GetLastError ());\r
-          }\r
-          api.NSPCleanup (prov);\r
-        }\r
-      }\r
-      FreeLibrary (nsp);\r
-    }\r
-  }\r
-  WSACleanup();\r
-  return r;\r
-}
\ No newline at end of file
+
+//
+// Utility to turn a list of offsets into a list of addresses. Used
+// to convert structures returned as BLOBs.
+//
+
+VOID
+FixList(PCHAR ** List, PCHAR Base)
+{
+    if(*List)
+    {
+        PCHAR * Addr;
+
+        Addr = *List = (PCHAR *)( ((DWORD)*List + Base) );
+        while(*Addr)
+        {
+            *Addr = (PCHAR)(((DWORD)*Addr + Base));
+            Addr++;
+        }
+    }
+}
+
+
+//
+// Routine to convert a hostent returned in a BLOB to one with
+// usable pointers. The structure is converted in-place.
+//
+VOID
+UnpackHostEnt(struct hostent * hostent)
+{
+     PCHAR pch;
+
+     pch = (PCHAR)hostent;
+
+     if(hostent->h_name)
+     {
+         hostent->h_name = (PCHAR)((DWORD)hostent->h_name + pch);
+     }
+     FixList(&hostent->h_aliases, pch);
+     FixList(&hostent->h_addr_list, pch);
+}
+
+
+static void
+print_hostent (struct hostent *he)
+{
+  int i;
+  char **pAlias;
+
+  printf("\tOfficial name: %s\n", he->h_name);
+  for (i=0, pAlias = he->h_aliases; *pAlias != 0; pAlias++) {
+      printf("\tAlternate name #%d: %s\n", ++i, *pAlias);
+  }
+  printf("\tAddress type: ");
+  switch (he->h_addrtype) {
+  case AF_INET:
+      printf("AF_INET\n");
+      break;
+  case AF_INET6:
+      printf("AF_INET6\n");
+      break;
+  case AF_NETBIOS:
+      printf("AF_NETBIOS\n");
+      break;
+  default:
+      printf(" %d\n", he->h_addrtype);
+      break;
+  }
+  printf("\tAddress length: %d\n", he->h_length);
+
+  if (he->h_addrtype == AF_INET) {
+    struct sockaddr_in addr;
+    memset (&addr, 0, sizeof (addr));
+    addr.sin_family = AF_INET;
+    addr.sin_port = 0;
+    i = 0;
+    while (he->h_addr_list[i] != 0) {
+      char buf[1024];
+      DWORD buflen = 1024;
+      addr.sin_addr = *(struct in_addr *) he->h_addr_list[i++];
+      if (NO_ERROR == WSAAddressToStringA ((LPSOCKADDR) &addr, sizeof (addr), NULL, buf, &buflen))
+        printf("\tIPv4 Address #%d: %s\n", i, buf);
+      else
+        printf("\tIPv4 Address #%d: Can't convert: %lu\n", i, GetLastError ());
+    }
+  } else if (he->h_addrtype == AF_INET6) {
+    struct sockaddr_in6 addr;
+    memset (&addr, 0, sizeof (addr));
+    addr.sin6_family = AF_INET6;
+    addr.sin6_port = 0;
+    i = 0;
+    while (he->h_addr_list[i] != 0) {
+      char buf[1024];
+      DWORD buflen = 1024;
+      addr.sin6_addr = *(struct in6_addr *) he->h_addr_list[i++];
+      if (NO_ERROR == WSAAddressToStringA ((LPSOCKADDR) &addr, sizeof (addr), NULL, buf, &buflen))
+        printf("\tIPv6 Address #%d: %s\n", i, buf);
+      else
+        printf("\tIPv6 Address #%d: Can't convert: %lu\n", i, GetLastError ());
+    }
+  }
+}
+
+
+int
+main (int argc, char **argv)
+{
+  int ret;
+  int r = 1;
+  WSADATA wsd;
+  GUID prov;
+  GUID sc;
+  wchar_t *cmdl;
+  int wargc;
+  wchar_t **wargv;
+
+  if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
+  {
+    fprintf (stderr, "WSAStartup() failed: %lu\n", GetLastError());
+    return 5;
+  }
+
+  cmdl = GetCommandLineW ();
+  if (cmdl == NULL)
+  {
+    WSACleanup();
+    return 2;
+  }
+  wargv = CommandLineToArgvW (cmdl, &wargc);
+  if (wargv == NULL)
+  {
+    WSACleanup();
+    return 3;
+  }
+  r = 4;
+
+  if (wargc == 5)
+  {
+    if (wcscmp (wargv[1], L"A") == 0)
+      sc = SVCID_DNS_TYPE_A;
+    else if (wcscmp (wargv[1], L"AAAA") == 0)
+      sc = SVCID_DNS_TYPE_AAAA;
+    else if (wcscmp (wargv[1], L"name") == 0)
+      sc = SVCID_HOSTNAME;
+    else if (wcscmp (wargv[1], L"addr") == 0)
+      sc = SVCID_INET_HOSTADDRBYNAME;
+    else
+      wargc -= 1;
+    if (wcscmp (wargv[4], L"mswdns") == 0)
+      prov = W32_DNS;
+    else if (wcscmp (wargv[4], L"gnunetdns") == 0)
+      prov = GNUNET_NAMESPACE_PROVIDER_DNS;
+    else
+      wargc -= 1;
+  }
+  else if (wargc == 3)
+  {
+  }
+  else
+  {
+    fprintf (stderr, "Usage: %S <record type> <service name> <NSP library path> <NSP id>\n"
+        "record type      - one of the following: A | AAAA | name | addr\n"
+        "service name     - a string to resolve; \" \" (a space) means 'blank'\n"
+        "NSP library path - path to libw32nsp\n"
+        "NSP id           - one of the following: mswdns | gnunetdns\n",
+        wargv[0]);
+  }
+
+  if (wargc == 5)
+  {
+    HMODULE nsp;
+
+    nsp = LoadLibraryW (wargv[3]);
+    if (nsp == NULL)
+    {
+      fprintf (stderr, "Failed to load library `%S'\n", wargv[3]);
+    }
+    else
+    {
+      LPNSPSTARTUP startup = (LPNSPSTARTUP) GetProcAddress (nsp, "NSPStartup");
+      if (startup == NULL)
+        startup = (LPNSPSTARTUP) GetProcAddress (nsp, "NSPStartup@8");
+      if (startup != NULL)
+      {
+        NSP_ROUTINE api;
+        api.cbSize = sizeof (api);
+        ret = startup (&prov, &api);
+        if (NO_ERROR != ret)
+          fprintf (stderr, "startup failed: %lu\n", GetLastError ());
+        else
+        {
+          HANDLE lookup;
+          WSAQUERYSETW search;
+          char buf[4096];
+          WSAQUERYSETW *result = (WSAQUERYSETW *) buf;
+          DWORD resultsize;
+          DWORD err;
+          memset (&search, 0, sizeof (search));
+          search.dwSize = sizeof (search);
+          search.lpszServiceInstanceName = (wcscmp (wargv[2], L" ") == 0) ? NULL : wargv[2];
+          search.lpServiceClassId = &sc;
+          search.lpNSProviderId = &prov;
+          search.dwNameSpace = NS_ALL;
+          ret = api.NSPLookupServiceBegin (&prov, &search, NULL, LUP_RETURN_ALL, &lookup);
+          if (ret != NO_ERROR)
+          {
+            fprintf (stderr, "lookup start failed\n");
+          }
+          else
+          {
+            resultsize = 4096;
+            ret = api.NSPLookupServiceNext (lookup, LUP_RETURN_ALL, &resultsize, result);
+            err = GetLastError ();
+            if (ret != NO_ERROR)
+            {
+              fprintf (stderr, "lookup next failed: %lu\n", err);
+            }
+            else
+            {
+              int i;
+              printf ("Got result:\n");
+              printf ("  lpszServiceInstanceName: %S\n", result->lpszServiceInstanceName ? result->lpszServiceInstanceName : L"NULL");
+              if (result->lpServiceClassId)
+                printf ("  lpServiceClassId:        { 0x%08lX,0x%04X,0x%04X, { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X } }\n",
+                    result->lpServiceClassId->Data1, result->lpServiceClassId->Data2, result->lpServiceClassId->Data3, result->lpServiceClassId->Data4[0],
+                    result->lpServiceClassId->Data4[1], result->lpServiceClassId->Data4[2], result->lpServiceClassId->Data4[3], result->lpServiceClassId->Data4[4],
+                    result->lpServiceClassId->Data4[5], result->lpServiceClassId->Data4[6], result->lpServiceClassId->Data4[7]);
+              else
+                printf ("  lpServiceClassId:        NULL\n");
+              if (result->lpVersion)
+                printf ("  lpVersion:               0x%08lX, %d\n", result->lpVersion->dwVersion, result->lpVersion->ecHow);
+              else
+                printf ("  lpVersion:               NULL\n");
+              printf ("  lpszComment:             %S\n", result->lpszComment ? result->lpszComment : L"NULL");
+              printf ("  dwNameSpace:             %lu\n", result->dwNameSpace);
+              if (result->lpNSProviderId)
+                printf ("  lpNSProviderId:          { 0x%08lX,0x%04X,0x%04X, { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X } }\n",
+                    result->lpNSProviderId->Data1, result->lpNSProviderId->Data2, result->lpNSProviderId->Data3, result->lpNSProviderId->Data4[0],
+                    result->lpNSProviderId->Data4[1], result->lpNSProviderId->Data4[2], result->lpNSProviderId->Data4[3], result->lpNSProviderId->Data4[4],
+                    result->lpNSProviderId->Data4[5], result->lpNSProviderId->Data4[6], result->lpNSProviderId->Data4[7]);
+              else
+                printf ("  lpNSProviderId:          NULL\n");
+              printf ("  lpszContext:             %S\n", result->lpszContext ? result->lpszContext : L"NULL");
+              printf ("  dwNumberOfProtocols:     %lu\n", result->dwNumberOfProtocols);
+              printf ("  lpszQueryString:         %S\n", result->lpszQueryString ? result->lpszQueryString : L"NULL");
+              printf ("  dwNumberOfCsAddrs:       %lu\n", result->dwNumberOfCsAddrs);
+              for (i = 0; i < result->dwNumberOfCsAddrs; i++)
+              {
+                switch (result->lpcsaBuffer[i].iSocketType)
+                {
+                case SOCK_STREAM:
+                  printf ("    %d: iSocketType = SOCK_STREAM\n", i);
+                  break;
+                case SOCK_DGRAM:
+                  printf ("    %d: iSocketType = SOCK_DGRAM\n", i);
+                  break;
+                default:
+                  printf ("    %d: iSocketType = %d\n", i, result->lpcsaBuffer[i].iSocketType);
+                }
+                switch (result->lpcsaBuffer[i].iProtocol)
+                {
+                case IPPROTO_TCP:
+                  printf ("    %d: iProtocol   = IPPROTO_TCP\n", i);
+                  break;
+                case IPPROTO_UDP:
+                  printf ("    %d: iProtocol   = IPPROTO_UDP\n", i);
+                  break;
+                default:
+                  printf ("    %d: iProtocol   = %d\n", i, result->lpcsaBuffer[i].iProtocol);
+                }
+                switch (result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family)
+                {
+                case AF_INET:
+                  printf ("    %d: loc family  = AF_INET\n", i);
+                  break;
+                case AF_INET6:
+                  printf ("    %d: loc family  = AF_INET6\n", i);
+                  break;
+                default:
+                  printf ("    %d: loc family  = %hu\n", i, result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family);
+                }
+                switch (result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family)
+                {
+                case AF_INET:
+                  printf ("    %d: rem family  = AF_INET\n", i);
+                  break;
+                case AF_INET6:
+                  printf ("    %d: rem family  = AF_INET6\n", i);
+                  break;
+                default:
+                  printf ("    %d: rem family = %hu\n", i, result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family);
+                }
+                char buf[1024];
+                DWORD buflen = 1024;
+                if (NO_ERROR == WSAAddressToStringA (result->lpcsaBuffer[i].LocalAddr.lpSockaddr, result->lpcsaBuffer[i].LocalAddr.iSockaddrLength, NULL, buf, &buflen))
+                  printf("\tLocal Address #%d: %s\n", i, buf);
+                else
+                  printf("\tLocal Address #%d: Can't convert: %lu\n", i, GetLastError ());
+                buflen = 1024;
+                if (NO_ERROR == WSAAddressToStringA (result->lpcsaBuffer[i].RemoteAddr.lpSockaddr, result->lpcsaBuffer[i].RemoteAddr.iSockaddrLength, NULL, buf, &buflen))
+                  printf("\tRemote Address #%d: %s\n", i, buf);
+                else
+                  printf("\tRemote Address #%d: Can't convert: %lu\n", i, GetLastError ());
+              }
+              printf ("  dwOutputFlags:           0x%08lX\n", result->dwOutputFlags);
+              printf ("  lpBlob:                  0x%p\n", result->lpBlob);
+              if (result->lpBlob)
+              {
+                struct hostent *he = malloc (result->lpBlob->cbSize);
+                if (he != NULL)
+                {
+                  GNUNET_memcpy (he, result->lpBlob->pBlobData, result->lpBlob->cbSize);
+                  UnpackHostEnt (he);
+                  print_hostent (he);
+                  free (he);
+                }
+              }
+            }
+            ret = api.NSPLookupServiceEnd (lookup);
+            if (ret != NO_ERROR)
+              printf ("NSPLookupServiceEnd() failed: %lu\n", GetLastError ());
+          }
+          api.NSPCleanup (&prov);
+        }
+      }
+      FreeLibrary (nsp);
+    }
+  }
+  else if (wargc == 3)
+  {
+    int s;
+    ADDRINFOW hints;
+    ADDRINFOW *result;
+    ADDRINFOW *pos;
+
+    memset (&hints, 0, sizeof (struct addrinfo));
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+
+    if (0 != (s = GetAddrInfoW (wargv[2], NULL, &hints, &result)))
+    {
+      fprintf (stderr, "Cound not resolve `%S' using GetAddrInfoW: %lu\n",
+          wargv[2], GetLastError ());
+    }
+    else
+    {
+      for (pos = result; pos != NULL; pos = pos->ai_next)
+      {
+        wchar_t tmpbuf[1024];
+        DWORD buflen = 1024;
+        if (0 == WSAAddressToStringW (pos->ai_addr, pos->ai_addrlen, NULL, tmpbuf, &buflen))
+          fprintf (stderr, "Result:\n"
+                         "  flags: 0x%X\n"
+                         "  family: 0x%X\n"
+                         "  socktype: 0x%X\n"
+                         "  protocol: 0x%X\n"
+                         "  addrlen: %u\n"
+                         "  addr: %S\n"
+                         "  canonname: %S\n",
+                         pos->ai_flags,
+                         pos->ai_family,
+                         pos->ai_socktype,
+                         pos->ai_protocol,
+                         pos->ai_addrlen,
+                         tmpbuf,
+                         pos->ai_canonname);
+        else
+          fprintf (stderr, "Result:\n"
+                         "  flags: 0x%X\n"
+                         "  family: 0x%X\n"
+                         "  socktype: 0x%X\n"
+                         "  protocol: 0x%X\n"
+                         "  addrlen: %u\n"
+                         "  addr: %S\n"
+                         "  canonname: %S\n",
+                         pos->ai_flags,
+                         pos->ai_family,
+                         pos->ai_socktype,
+                         pos->ai_protocol,
+                         pos->ai_addrlen,
+                         L"<can't stringify>",
+                         pos->ai_canonname);
+      }
+      if (NULL != result)
+        FreeAddrInfoW (result);
+    }
+  }
+  WSACleanup();
+  return r;
+}