From e91f21b8dd965402dfa862d1a4f0d1a6ff476de5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=A0=D1=83=D1=81=D0=BB=D0=B0=D0=BD=20=D0=98=D0=B6=D0=B1=D1=83=D0=BB=D0=B0=D1=82=D0=BE=D0=B2?= <lrn1986@gmail.com>
Date: Sun, 21 Nov 2010 21:15:15 +0300
Subject: [PATCH] First w32io-with-fake-FDs commit

Second w32io-with-fake-FDs commit

Fixed the select() implementation and the socket test

Added a shutdown() wrapper, fixed shutdown in the test

Fixed select() and the test

Fixed named pipe tests and poll()

Almost final W32I/O commit

W32IO: Finally passing all 45 tests

Merge W32IO into latest head. Disable NAT on MinGW
---
 src/include/gnunet_common.h          |    2 +-
 src/include/gnunet_network_lib.h     |   13 -
 src/include/platform.h               |  136 ++-
 src/include/winproc.h                |    1 +
 src/nat/Makefile.am                  |    3 +-
 src/transport/Makefile.am            |    4 +-
 src/transport/gnunet-nat-server.c    |    2 +
 src/transport/plugin_transport_tcp.c |    4 +
 src/util/Makefile.am                 |   14 +-
 src/util/client.c                    |    2 +-
 src/util/common_logging.c            |   22 +-
 src/util/disk.c                      |  205 +--
 src/util/disk.h                      |   15 -
 src/util/gnunet-service-resolver.c   |    6 +-
 src/util/network.c                   |  552 ++----
 src/util/os_installation.c           |    6 +-
 src/util/os_network.c                |    2 +-
 src/util/os_priority.c               |  122 +-
 src/util/scheduler.c                 |   68 +-
 src/util/service.c                   |    8 +-
 src/util/signal.c                    |   10 +-
 src/util/strings.c                   |    6 +-
 src/util/test_configuration.c        |    2 +-
 src/util/test_getopt.c               |    2 +-
 src/util/test_os_start_process.c     |   12 +-
 src/util/test_resolver_api.c         |    7 +-
 src/util/test_scheduler.c            |    5 +-
 src/util/test_service.c              |    3 -
 src/util/test_service_data.conf      |    2 +
 src/util/test_strings.c              |    2 +-
 src/util/test_w32io.c                |  960 +++++++++
 src/util/w32io.c                     | 3698 ++++++++++++++++++++++++++++++++++
 src/util/w32io.h                     |  279 +++
 src/util/winproc.c                   |    9 +-
 34 files changed, 5473 insertions(+), 711 deletions(-)
 create mode 100644 src/util/test_w32io.c
 create mode 100644 src/util/w32io.c
 create mode 100644 src/util/w32io.h

diff --git a/src/include/gnunet_common.h b/src/include/gnunet_common.h
index dddee06..b75d36f 100644
--- a/src/include/gnunet_common.h
+++ b/src/include/gnunet_common.h
@@ -36,7 +36,7 @@
 #if HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
-#ifdef MINGW
+#if WINDOWS && !defined(__CYGWIN__)
 #include "winproc.h"
 #endif
 #ifdef HAVE_STDINT_H
diff --git a/src/include/gnunet_network_lib.h b/src/include/gnunet_network_lib.h
index 7330368..a5ae0e4 100644
--- a/src/include/gnunet_network_lib.h
+++ b/src/include/gnunet_network_lib.h
@@ -271,19 +271,6 @@ void GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
                                const struct GNUNET_NETWORK_Handle *desc);
 
 
-#ifdef __MINGW32__
-/* TODO: maybe #ifdef WINDOWS? -ndurner */
-/**
- * Add a W32 file handle to the fd set
- * @param fds fd set
- * @param h the file handle to add
- */
-void
-GNUNET_NETWORK_fdset_handle_set_native_w32_handle (struct GNUNET_NETWORK_FDSet *fds,
-						   HANDLE h);
-#endif
-
-
 /**
  * Check whether a socket is part of the fd set
  * @param fds fd set
diff --git a/src/include/platform.h b/src/include/platform.h
index cc2aa03..26a800d 100644
--- a/src/include/platform.h
+++ b/src/include/platform.h
@@ -80,7 +80,7 @@
 #include <Winsock2.h>
 #include <ws2tcpip.h>
 #else
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
 #include <netdb.h>
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -199,7 +199,7 @@
 #define SIOCGIFADDR     _IOW('s', 102, struct ifreq)    /* Get if addr */
 #endif
 
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
 #include <sys/mman.h>
 #endif
 
@@ -239,4 +239,136 @@ long long atoll (const char *nptr);
 #define MAKE_UNALIGNED(val) val
 #endif
 
+#ifdef WINDOWS
+struct W32Fd;
+/**
+ * Sometimes pollfd is used as a struct, not as a pointer, which is why
+ * we need to wrap W32Fd - to make sure it always stays a pointer.
+ * Also keeps things consistent (caller might expect to access pollfd.events)
+ */
+struct W32PollFd
+{
+  struct W32Fd *fd;
+  short events;
+  short revents;
+};
+struct pollfd
+{
+  int fd;
+  short events;
+  short revents;
+};
+#define POLL_FD_TYPE struct W32Fd *
+#define POLLFD struct W32PollFd
+#define NATIVE_FD_TYPE HANDLE
+
+typedef enum
+{
+  POLLIN = FD_READ | FD_ACCEPT,
+  POLLRDNORM = FD_READ | FD_ACCEPT,
+  POLLRDBAND = FD_OOB,
+  POLLOUT = FD_WRITE | FD_CONNECT,
+  POLLWRNORM = FD_WRITE | FD_CONNECT,
+  POLLHUP = FD_CLOSE,
+  POLLPRI = 1 << FD_MAX_EVENTS,
+  POLLWRBAND = 1 << (FD_MAX_EVENTS + 1),
+  POLLERR = 1 << (FD_MAX_EVENTS + 2),
+  POLLNVAL = 1 << (FD_MAX_EVENTS + 3),
+  POLLLAST = FD_MAX_EVENTS + 4
+} GNUNET_W32IO_PollEvents;
+
+#define POLLIN_BIT FD_READ_BIT
+#define POLLOUT_BIT FD_WRITE_BIT
+#define POLLHUP_BIT FD_CLOSE_BIT
+#define POLLWRBAND_BIT FD_MAX_EVENTS + 1
+#define POLLERR_BIT FD_MAX_EVENTS + 2
+#define POLLNVAL_BIT FD_MAX_EVENTS + 3
+
+#else
+#define POLL_FD_TYPE int
+#define POLLFD struct pollfd
+#define NATIVE_FD_TYPE int
+#endif
+
+#define INVALID_POLL_FD (POLL_FD_TYPE) -1
+
+typedef long int __fd_mask;
+
+#undef __NFDBITS
+#define __NFDBITS	(8 * sizeof (__fd_mask))
+#define	__FDELT(d)	((d) / __NFDBITS)
+#define	__FDMASK(d)	((__fd_mask) 1 << ((d) % __NFDBITS))
+
+#undef __FD_SETSIZE
+#define __FD_SETSIZE  1024
+
+#undef __FDSET_LONGS
+#define __FDSET_LONGS  (__FD_SETSIZE/__NFDBITS)
+
+/* Maximum number of file descriptors in `fd_set'.  */
+#define	W32_FD_SETSIZE		__FD_SETSIZE
+
+#ifdef __USE_MISC
+/* Sometimes the fd_set member is assumed to have this type.  */
+typedef __fd_mask fd_mask;
+
+/* Number of bits per word of `fd_set' (some code assumes this is 32).  */
+# define W32_NFDBITS		__NFDBITS
+#endif
+
+# define __FD_ZERO(fdsp) \
+  do {									      \
+    int __d0, __d1;							      \
+    __asm__ __volatile__ ("cld; rep; stosl"				      \
+			  : "=c" (__d0), "=D" (__d1)			      \
+			  : "a" (0), "0" (sizeof (w32fd_set)		      \
+					  / sizeof (__fd_mask)),	      \
+			    "1" (&__FDS_BITS (fdsp)[0])			      \
+			  : "memory");					      \
+  } while (0)
+
+# define __FD_SET(fd, fdsp) \
+  __asm__ __volatile__ ("btsl %1,%0"					      \
+			: "=m" (__FDS_BITS (fdsp)[__FDELT (fd)])	      \
+			: "r" (((int) (fd)) % __NFDBITS)		      \
+			: "cc","memory")
+# define __FD_CLR(fd, fdsp) \
+  __asm__ __volatile__ ("btrl %1,%0"					      \
+			: "=m" (__FDS_BITS (fdsp)[__FDELT (fd)])	      \
+			: "r" (((int) (fd)) % __NFDBITS)		      \
+			: "cc","memory")
+# define __FD_ISSET(fd, fdsp) \
+  (__extension__							      \
+   ({register char __result;						      \
+     __asm__ __volatile__ ("btl %1,%2 ; setcb %b0"			      \
+			   : "=q" (__result)				      \
+			   : "r" (((int) (fd)) % __NFDBITS),		      \
+			     "m" (__FDS_BITS (fdsp)[__FDELT (fd)])	      \
+			   : "cc");					      \
+     __result; }))
+
+/* fd_set for select and pselect.  */
+typedef struct 
+  {
+    /* XPG4.2 requires this member name.  Otherwise avoid the name
+       from the global namespace.  */
+#ifdef __USE_XOPEN
+    __fd_mask fds_bits[__FDSET_LONGS];
+# define __FDS_BITS(set) ((set)->fds_bits)
+#else
+    __fd_mask __fds_bits[__FDSET_LONGS];
+# define __FDS_BITS(set) ((set)->__fds_bits)
+#endif
+  } w32fd_set;
+
+/* Access macros for `fd_set'.  */
+#define	W32_FD_SET(fd, fdsetp)		__FD_SET(fd, fdsetp)
+#define	W32_FD_CLR(fd, fdsetp)		__FD_CLR(fd, fdsetp)
+#define	W32_FD_ISSET(fd, fdsetp)	__FD_ISSET(fd, fdsetp)
+#define	W32_FD_ZERO(fdsetp)		__FD_ZERO(fdsetp)
+
+#ifdef WINDOWS
+  typedef long nfds_t;
+#endif
+
 #endif
diff --git a/src/include/winproc.h b/src/include/winproc.h
index 595180a..f23b00b 100644
--- a/src/include/winproc.h
+++ b/src/include/winproc.h
@@ -45,6 +45,7 @@
 #include <Ntsecapi.h>
 #include <lm.h>
 #include <Aclapi.h>
+#include <shlwapi.h>
 
 
 #ifdef __cplusplus
diff --git a/src/nat/Makefile.am b/src/nat/Makefile.am
index 3ca896b..e091327 100644
--- a/src/nat/Makefile.am
+++ b/src/nat/Makefile.am
@@ -48,4 +48,5 @@ test_nat_LDADD = \
  $(top_builddir)/src/nat/libgnunetnat.la \
  $(top_builddir)/src/util/libgnunetutil.la \
  @LIBCURL@
-endif
+
+endif
\ No newline at end of file
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index 313d948..468082c 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -7,9 +7,11 @@ if MINGW
   NATBIN = gnunet-nat-server gnunet-nat-client
   NATSERVER = gnunet-nat-server-windows.c
   NATCLIENT = gnunet-nat-client-windows.c
+  NATLIB = 
 else
   NATSERVER = gnunet-nat-server.c
   NATCLIENT = gnunet-nat-client.c
+  NATLIB = $(top_builddir)/src/nat/libgnunetnat.la
 endif
 
 if HAVE_MHD
@@ -117,7 +119,7 @@ libgnunet_plugin_transport_tcp_la_LIBADD = \
   $(top_builddir)/src/hello/libgnunethello.la \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
   $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
-  $(top_builddir)/src/nat/libgnunetnat.la \
+  $(NATLIB) \
   $(top_builddir)/src/util/libgnunetutil.la 
 libgnunet_plugin_transport_tcp_la_LDFLAGS = \
  $(GN_PLUGIN_LDFLAGS)
diff --git a/src/transport/gnunet-nat-server.c b/src/transport/gnunet-nat-server.c
index ab99b5f..5c5b924 100644
--- a/src/transport/gnunet-nat-server.c
+++ b/src/transport/gnunet-nat-server.c
@@ -461,6 +461,7 @@ make_icmp_socket ()
 	       strerror (errno));
       return -1;
     }
+#if WINDOWS && !defined(__CYGWIN__)
   if (ret >= FD_SETSIZE)
     {
       fprintf (stderr,
@@ -470,6 +471,7 @@ make_icmp_socket ()
       close (ret);
       return -1;
     }
+#endif
   return ret;
 }
 
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c
index 18aad98..7179da9 100644
--- a/src/transport/plugin_transport_tcp.c
+++ b/src/transport/plugin_transport_tcp.c
@@ -619,10 +619,12 @@ add_to_address_list (struct Plugin *plugin,
       GNUNET_break (0);
       return;
     }
+#if !WINDOWS || defined(__CYGWIN__)
   if (plugin->allow_upnp)
     lal->nat = GNUNET_NAT_register (sa, salen,
 				    &nat_port_map_callback,
 				    lal);
+#endif
 }
 
 
@@ -2910,8 +2912,10 @@ libgnunet_plugin_transport_tcp_done (void *cls)
       GNUNET_CONTAINER_DLL_remove (plugin->lal_head,
 				   plugin->lal_tail,
 				   lal);
+#if !WINDOWS || defined(__CYGWIN__)
       if (lal->nat != NULL)
 	GNUNET_NAT_unregister (lal->nat);
+#endif
       GNUNET_free_non_null (lal->external_nat_address);
       GNUNET_free (lal);
     }
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 427ed25..e99341e 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -6,14 +6,18 @@ if MINGW
 noinst_LTLIBRARIES = \
   libgnunetutilwin.la
 libgnunetutilwin_la_SOURCES = \
+  w32io.c \
+  w32io.h \
   win.cc \
   winproc.c
 libgnunetutilwin_la_LDFLAGS = \
   -Wl,--no-undefined -Wl,--export-all-symbols 
 libgnunetutilwin_la_LIBADD = \
   -lshell32 -liconv -lstdc++ \
-  -lcomdlg32 -lgdi32
+  -lcomdlg32 -lgdi32 
 WINLIB = libgnunetutilwin.la
+
+WINTESTS = test_w32io
 endif
 
 if USE_COVERAGE
@@ -108,6 +112,7 @@ libgnunet_plugin_test_la_LDFLAGS = \
  $(GN_PLUGIN_LDFLAGS)
 
 check_PROGRAMS = \
+ $(WINTESTS) \
  test_bio \
  test_client \
  test_common_allocation \
@@ -157,6 +162,13 @@ if !DISABLE_TEST_RUN
 TESTS = $(check_PROGRAMS)
 endif
 
+if MINGW
+test_w32io_SOURCES = \
+ test_w32io.c
+test_w32io_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la
+endif
+
 test_bio_SOURCES = \
  test_bio.c
 test_bio_LDADD = \
diff --git a/src/util/client.c b/src/util/client.c
index d957dd0..90d1576 100644
--- a/src/util/client.c
+++ b/src/util/client.c
@@ -34,7 +34,7 @@
 #include "gnunet_server_lib.h"
 #include "gnunet_scheduler_lib.h"
 
-#define DEBUG_CLIENT GNUNET_NO
+#define DEBUG_CLIENT GNUNET_YES
 
 /**
  * How often do we re-try tranmsitting requests before giving up?
diff --git a/src/util/common_logging.c b/src/util/common_logging.c
index 1a32c44..c7df541 100644
--- a/src/util/common_logging.c
+++ b/src/util/common_logging.c
@@ -134,6 +134,11 @@ static unsigned int skip_log;
  */
 static FILE *GNUNET_stderr;
 
+#if WINDOWS && !defined(__CYGWIN__)
+CRITICAL_SECTION cs;
+BOOL cs_inited = FALSE;
+#endif
+
 /**
  * Convert a textual description of a loglevel
  * to the respective GNUNET_GE_KIND.
@@ -173,6 +178,13 @@ GNUNET_log_setup (const char *comp, const char *loglevel, const char *logfile)
   int dirwarn;
   char *fn;
 
+#if WINDOWS && !defined(__CYGWIN__)
+  if (!cs_inited)
+  {
+    cs_inited = TRUE;
+    InitializeCriticalSection (&cs);
+  }
+#endif
   GNUNET_free_non_null (component);
   GNUNET_asprintf (&component,
 		   "%s-%d",
@@ -263,6 +275,9 @@ output_message (enum GNUNET_ErrorType kind,
                 const char *comp, const char *datestr, const char *msg)
 {
   struct CustomLogger *pos;
+#if WINDOWS && !defined(__CYGWIN__)
+  EnterCriticalSection (&cs);
+#endif
   if (GNUNET_stderr != NULL)
     {
       fprintf (GNUNET_stderr, "%s %s %s %s", datestr, comp, 
@@ -275,6 +290,9 @@ output_message (enum GNUNET_ErrorType kind,
       pos->logger (pos->logger_cls, kind, comp, datestr, msg);
       pos = pos->next;
     }
+#if WINDOWS && !defined(__CYGWIN__)
+  LeaveCriticalSection (&cs);
+#endif
 }
 
 
@@ -599,7 +617,7 @@ GNUNET_a2s (const struct sockaddr *addr, socklen_t addrlen)
 void __attribute__ ((constructor)) GNUNET_util_cl_init ()
 {
   GNUNET_stderr = stderr;
-#ifdef MINGW
+#if WINDOWS
   GNInitWinEnv (NULL);
 #endif
 }
@@ -610,7 +628,7 @@ void __attribute__ ((constructor)) GNUNET_util_cl_init ()
  */
 void __attribute__ ((destructor)) GNUNET_util_cl_fini ()
 {
-#ifdef MINGW
+#if WINDOWS
   GNShutdownWinEnv ();
 #endif
 }
diff --git a/src/util/disk.c b/src/util/disk.c
index 0b37da8..168edb9 100644
--- a/src/util/disk.c
+++ b/src/util/disk.c
@@ -32,7 +32,7 @@
 #include "gnunet_scheduler_lib.h"
 #include "gnunet_strings_lib.h"
 #include "disk.h"
-
+#include "w32io.h"
 
 /**
  * Block size for IO for copying files.
@@ -52,7 +52,7 @@
 #include <sys/types.h>
 #include <sys/statvfs.h>
 #else
-#ifdef MINGW
+#if WINDOWS && !defined(__CYGWIN__)
 #define  	_IFMT		0170000 /* type of file */
 #define  	_IFLNK		0120000 /* symbolic link */
 #define  S_ISLNK(m)	(((m)&_IFMT) == _IFLNK)
@@ -182,11 +182,7 @@ getSizeRec (void *cls, const char *fn)
 int
 GNUNET_DISK_handle_invalid (const struct GNUNET_DISK_FileHandle *h)
 {
-#ifdef MINGW
-  return ((!h) || (h->h == INVALID_HANDLE_VALUE)) ? GNUNET_YES : GNUNET_NO;
-#else
   return ((!h) || (h->fd == -1)) ? GNUNET_YES : GNUNET_NO;
-#endif
 }
 
 
@@ -208,24 +204,13 @@ GNUNET_DISK_file_seek (const struct GNUNET_DISK_FileHandle * h, off_t offset,
       return GNUNET_SYSERR;
     }
 
-#ifdef MINGW
-  DWORD ret;
-  static DWORD t[] = {[GNUNET_DISK_SEEK_SET] = FILE_BEGIN,
-    [GNUNET_DISK_SEEK_CUR] = FILE_CURRENT,[GNUNET_DISK_SEEK_END] = FILE_END
-  };
-
-  ret = SetFilePointer (h->h, offset, NULL, t[whence]);
-  if (ret == INVALID_SET_FILE_POINTER)
-    {
-      SetErrnoFromWinError (GetLastError ());
-      return GNUNET_SYSERR;
-    }
-  return ret;
-#else
   static int t[] = {[GNUNET_DISK_SEEK_SET] = SEEK_SET,
     [GNUNET_DISK_SEEK_CUR] = SEEK_CUR,[GNUNET_DISK_SEEK_END] = SEEK_END
   };
 
+#if WINDOWS
+  return GNUNET_W32IO_lseek (h->fd, offset, t[whence]);
+#else
   return lseek (h->fd, offset, t[whence]);
 #endif
 }
@@ -308,7 +293,7 @@ GNUNET_DISK_file_get_identifiers (const char *filename,
   fh = GNUNET_DISK_file_open(filename, GNUNET_DISK_OPEN_READ, 0);
   if (fh == NULL)
     return GNUNET_SYSERR;
-  succ = GetFileInformationByHandle(fh->h, &info);
+  succ = GetFileInformationByHandle(GNUNET_W32IO_fd_get_handle (fh->fd), &info);
   GNUNET_DISK_file_close(fh);
   if (succ)
     {
@@ -354,7 +339,7 @@ GNUNET_DISK_mktemp (const char *t)
     {
       GNUNET_asprintf (&tmpl, "%s%s", t, "XXXXXX");
     }
-#ifdef MINGW
+#if WINDOWS && !defined(__CYGWIN__)
   fn = (char *) GNUNET_malloc (MAX_PATH + 1);
   if (ERROR_SUCCESS != plibc_conv_to_win_path (tmpl, fn))
     {
@@ -398,7 +383,7 @@ GNUNET_DISK_get_blocks_available (const char *part)
       return -1;
     }
   return buf.f_bavail;
-#elif MINGW
+#elif WINDOWS
   DWORD dwDummy;
   DWORD dwBlocks;
   char szDrive[4];
@@ -532,7 +517,7 @@ GNUNET_DISK_directory_create (const char *dir)
     return GNUNET_SYSERR;
 
   len = strlen (rdir);
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   pos = 1;                      /* skip heading '/' */
 #else
   /* Local or Network path? */
@@ -567,7 +552,7 @@ GNUNET_DISK_directory_create (const char *dir)
             }
           if (ret == GNUNET_NO)
             {
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
               ret = mkdir (rdir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);  /* 755 */
 #else
               ret = mkdir (rdir);
@@ -638,15 +623,8 @@ GNUNET_DISK_file_read (const struct GNUNET_DISK_FileHandle * h, void *result,
       return GNUNET_SYSERR;
     }
 
-#ifdef MINGW
-  DWORD bytesRead;
-
-  if (!ReadFile (h->h, result, len, &bytesRead, NULL))
-    {
-      SetErrnoFromWinError (GetLastError ());
-      return GNUNET_SYSERR;
-    }
-  return bytesRead;
+#if WINDOWS
+  return GNUNET_W32IO_read (h->fd, result, len);
 #else
   return read (h->fd, result, len);
 #endif
@@ -695,15 +673,8 @@ GNUNET_DISK_file_write (const struct GNUNET_DISK_FileHandle * h,
       return GNUNET_SYSERR;
     }
 
-#ifdef MINGW
-  DWORD bytesWritten;
-
-  if (!WriteFile (h->h, buffer, n, &bytesWritten, NULL))
-    {
-      SetErrnoFromWinError (GetLastError ());
-      return GNUNET_SYSERR;
-    }
-  return bytesWritten;
+#if WINDOWS
+  return GNUNET_W32IO_write (h->fd, buffer, n);
 #else
   return write (h->fd, buffer, n);
 #endif
@@ -1122,7 +1093,7 @@ GNUNET_DISK_filename_canonicalize (char *fn)
 int
 GNUNET_DISK_file_change_owner (const char *filename, const char *user)
 {
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   struct passwd *pws;
 
   pws = getpwnam (user);
@@ -1158,7 +1129,7 @@ GNUNET_DISK_file_lock (struct GNUNET_DISK_FileHandle *fh, off_t lockStart,
       return GNUNET_SYSERR;
     }
 
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   struct flock fl;
 
   memset (&fl, 0, sizeof (struct flock));
@@ -1174,7 +1145,7 @@ GNUNET_DISK_file_lock (struct GNUNET_DISK_FileHandle *fh, off_t lockStart,
   memset (&o, 0, sizeof (OVERLAPPED));
   o.Offset = lockStart;
 
-  if (!LockFileEx (fh->h, (excl ? LOCKFILE_EXCLUSIVE_LOCK : 0)
+  if (!LockFileEx (GNUNET_W32IO_fd_get_handle (fh->fd), (excl ? LOCKFILE_EXCLUSIVE_LOCK : 0)
                    | LOCKFILE_FAIL_IMMEDIATELY, 0, lockEnd - lockStart, 0,
                    &o))
     {
@@ -1204,7 +1175,7 @@ GNUNET_DISK_file_unlock (struct GNUNET_DISK_FileHandle *fh, off_t unlockStart,
       return GNUNET_SYSERR;
     }
 
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   struct flock fl;
 
   memset (&fl, 0, sizeof (struct flock));
@@ -1220,7 +1191,7 @@ GNUNET_DISK_file_unlock (struct GNUNET_DISK_FileHandle *fh, off_t unlockStart,
   memset (&o, 0, sizeof (OVERLAPPED));
   o.Offset = unlockStart;
 
-  if (!UnlockFileEx (fh->h, 0, unlockEnd - unlockStart, 0, &o))
+  if (!UnlockFileEx (GNUNET_W32IO_fd_get_handle (fh->fd), 0, unlockEnd - unlockStart, 0, &o))
     {
       SetErrnoFromWinError (GetLastError ());
       return GNUNET_SYSERR;
@@ -1250,7 +1221,7 @@ GNUNET_DISK_file_open (const char *fn,
 {
   char *expfn;
   struct GNUNET_DISK_FileHandle *ret;
-#ifdef MINGW
+#if WINDOWS
   DWORD access;
   DWORD disp;
   HANDLE h;
@@ -1263,7 +1234,7 @@ GNUNET_DISK_file_open (const char *fn,
   expfn = GNUNET_STRINGS_filename_expand (fn);
   if (NULL == expfn)
     return NULL;
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   mode = 0;
   if (GNUNET_DISK_OPEN_READWRITE == (flags & GNUNET_DISK_OPEN_READWRITE))
     oflags = O_RDWR;            /* note: O_RDWR is NOT always O_RDONLY | O_WRONLY */
@@ -1356,9 +1327,8 @@ GNUNET_DISK_file_open (const char *fn,
 #endif
 
   ret = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle));
-#ifdef MINGW
-  ret->h = h;
-  ret->type = GNUNET_DISK_FILE;
+#if WINDOWS
+  ret->fd = GNUNET_W32IO_fd_from_handle (h, GNUNET_W32IO_FILE, access, 1, 1, 1);
 #else
   ret->fd = fd;
 #endif
@@ -1381,10 +1351,9 @@ GNUNET_DISK_file_close (struct GNUNET_DISK_FileHandle *h)
       return GNUNET_SYSERR;
     }
 
-#if MINGW
-  if (!CloseHandle (h->h))
+#if WINDOWS
+  if (GNUNET_W32IO_close (h->fd, 1) != 0)
     {
-      SetErrnoFromWinError (GetLastError ());
       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "close");
       GNUNET_free (h);
       return GNUNET_SYSERR;
@@ -1478,7 +1447,7 @@ GNUNET_DISK_get_home_filename (const struct GNUNET_CONFIGURATION_Handle *cfg,
  */
 struct GNUNET_DISK_MapHandle
 {
-#ifdef MINGW
+#if WINDOWS && !defined(__CYGWIN__)
   /**
    * Underlying OS handle.
    */
@@ -1521,7 +1490,7 @@ GNUNET_DISK_file_map (const struct GNUNET_DISK_FileHandle *h,
       return NULL;
     }
 
-#ifdef MINGW
+#if WINDOWS
   DWORD mapAccess, protect;
   void *ret;
 
@@ -1548,7 +1517,7 @@ GNUNET_DISK_file_map (const struct GNUNET_DISK_FileHandle *h,
     }
 
   *m = GNUNET_malloc (sizeof (struct GNUNET_DISK_MapHandle));
-  (*m)->h = CreateFileMapping (h->h, NULL, protect, 0, 0, NULL);
+  (*m)->h = CreateFileMapping (GNUNET_W32IO_fd_get_handle (h->fd), NULL, protect, 0, 0, NULL);
   if ((*m)->h == INVALID_HANDLE_VALUE)
     {
       SetErrnoFromWinError (GetLastError ());
@@ -1601,7 +1570,7 @@ GNUNET_DISK_file_unmap (struct GNUNET_DISK_MapHandle *h)
       return GNUNET_SYSERR;
     }
 
-#ifdef MINGW
+#if WINDOWS && !defined(__CYGWIN__)
   ret = UnmapViewOfFile (h->h) ? GNUNET_OK : GNUNET_SYSERR;
   if (ret != GNUNET_OK)
     SetErrnoFromWinError (GetLastError ());
@@ -1632,13 +1601,8 @@ GNUNET_DISK_file_sync (const struct GNUNET_DISK_FileHandle *h)
       return GNUNET_SYSERR;
     }
 
-#ifdef MINGW
-  int ret;
-
-  ret = FlushFileBuffers (h->h) ? GNUNET_OK : GNUNET_SYSERR;
-  if (ret != GNUNET_OK)
-    SetErrnoFromWinError (GetLastError ());
-  return ret;
+#if WINDOWS
+  return GNUNET_W32IO_fsync (h->fd) == -1 ? GNUNET_SYSERR : GNUNET_OK;
 #elif defined(FREEBSD) || defined(OPENBSD) || defined(DARWIN)
   return fsync (h->fd) == -1 ? GNUNET_SYSERR : GNUNET_OK;
 #else
@@ -1668,7 +1632,7 @@ GNUNET_DISK_pipe (int blocking, int inherit_read, int inherit_write)
   fds = (struct GNUNET_DISK_FileHandle *) &p[1];
   p->fd[0] = &fds[0];
   p->fd[1] = &fds[1];
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   int fd[2];
   int ret;
   int flags;
@@ -1717,51 +1681,16 @@ GNUNET_DISK_pipe (int blocking, int inherit_read, int inherit_write)
     }
 #else
   BOOL ret;
-  HANDLE tmp_handle;
+  int pipe[2];
 
-  ret = CreatePipe (&p->fd[0]->h, &p->fd[1]->h, NULL, 0);
+  ret = GNUNET_W32IO_anonymous_pipe (pipe, inherit_read == GNUNET_YES ? TRUE : FALSE, inherit_write == GNUNET_YES ? TRUE : FALSE);
   if (!ret)
     {
       GNUNET_free (p);
-      SetErrnoFromWinError (GetLastError ());
       return NULL;
     }
-  if (!DuplicateHandle (GetCurrentProcess (), p->fd[0]->h,
-		GetCurrentProcess (), &tmp_handle, 0, inherit_read == GNUNET_YES ? TRUE : FALSE,
-			DUPLICATE_SAME_ACCESS))
-	{
-	  SetErrnoFromWinError (GetLastError ());
-	  CloseHandle (p->fd[0]->h);
-	  CloseHandle (p->fd[1]->h);
-	  GNUNET_free (p);
-	  return NULL;
-	}
-	CloseHandle (p->fd[0]->h);
-	p->fd[0]->h = tmp_handle;
-
-	if (!DuplicateHandle (GetCurrentProcess (), p->fd[1]->h,
-			GetCurrentProcess (), &tmp_handle, 0, inherit_write == GNUNET_YES ? TRUE : FALSE,
-			DUPLICATE_SAME_ACCESS))
-	{
-	  SetErrnoFromWinError (GetLastError ());
-	  CloseHandle (p->fd[0]->h);
-	  CloseHandle (p->fd[1]->h);
-	  GNUNET_free (p);
-	  return NULL;
-	}
-  CloseHandle (p->fd[1]->h);
-  p->fd[1]->h = tmp_handle;
-  if (!blocking)
-    {
-      DWORD mode;
-
-      mode = PIPE_NOWAIT;
-      SetNamedPipeHandleState (p->fd[0]->h, &mode, NULL, NULL);
-      SetNamedPipeHandleState (p->fd[1]->h, &mode, NULL, NULL);
-      /* this always fails on Windows 95, so we don't care about error handling */
-    }
-  p->fd[0]->type = GNUNET_PIPE;
-  p->fd[1]->type = GNUNET_PIPE;
+  p->fd[0]->fd = pipe[0];
+  p->fd[1]->fd = pipe[1];
 #endif
   return p;
 }
@@ -1781,26 +1710,26 @@ GNUNET_DISK_pipe_close_end (struct GNUNET_DISK_PipeHandle *p,
   int ret = GNUNET_OK;
   int save;
 
-#ifdef MINGW
+#if WINDOWS
+  save = 0;
   if (end == GNUNET_DISK_PIPE_END_READ)
     {
-      if (!CloseHandle (p->fd[0]->h))
+      if (0 != GNUNET_W32IO_close (p->fd[0]->fd, 1))
         {
-          SetErrnoFromWinError (GetLastError ());
           ret = GNUNET_SYSERR;
+          save = errno;
         }
-      p->fd[0]->h = INVALID_HANDLE_VALUE;
+      p->fd[0]->fd = -1;
     }
   else if (end == GNUNET_DISK_PIPE_END_WRITE)
     {
-      if (!CloseHandle (p->fd[1]->h))
+      if (0 != GNUNET_W32IO_close (p->fd[1]->fd, 1))
         {
-          SetErrnoFromWinError (GetLastError ());
           ret = GNUNET_SYSERR;
+          save = errno;
         }
-      p->fd[1]->h = INVALID_HANDLE_VALUE;
+      p->fd[1]->fd = -1;
     }
-  save = errno;
 #else
   save = 0;
   if (end == GNUNET_DISK_PIPE_END_READ)
@@ -1838,18 +1767,25 @@ GNUNET_DISK_pipe_close (struct GNUNET_DISK_PipeHandle *p)
   int ret = GNUNET_OK;
   int save;
 
-#ifdef MINGW
-  if (!CloseHandle (p->fd[0]->h))
+#if WINDOWS
+  save = 0;
+  if (p->fd[0]->fd != -1)
     {
-      SetErrnoFromWinError (GetLastError ());
-      ret = GNUNET_SYSERR;
+      if (0 != GNUNET_W32IO_close (p->fd[0]->fd, 1))
+        {
+          ret = GNUNET_SYSERR;
+          save = errno;
+        }
     }
-  if (!CloseHandle (p->fd[1]->h))
+
+  if (p->fd[1]->fd != -1)
     {
-      SetErrnoFromWinError (GetLastError ());
-      ret = GNUNET_SYSERR;
+      if (0 != GNUNET_W32IO_close (p->fd[1]->fd, 1))
+        {
+          ret = GNUNET_SYSERR;
+          save = errno;
+        }
     }
-  save = errno;
 #else
   save = 0;
   if (p->fd[0]->fd != -1)
@@ -1888,7 +1824,7 @@ GNUNET_DISK_npipe_open (const char *fn,
                        enum GNUNET_DISK_OpenFlags flags,
                        enum GNUNET_DISK_AccessPermissions perm)
 {
-#ifdef MINGW
+#if WINDOWS && !defined(__CYGWIN__)
   struct GNUNET_DISK_FileHandle *ret;
   HANDLE h;
   DWORD openMode;
@@ -1916,7 +1852,7 @@ GNUNET_DISK_npipe_open (const char *fn,
     }
 
   ret = GNUNET_malloc(sizeof(*ret));
-  ret->h = h;
+  ret->fd = GNUNET_W32IO_fd_from_handle (h, GNUNET_W32IO_NAMED_PIPE, (openMode & PIPE_ACCESS_OUTBOUND ? GENERIC_WRITE : 0) | (openMode & PIPE_ACCESS_INBOUND ? GENERIC_READ : 0), 0, 0, 0);
 
   return ret;
 #else
@@ -1940,19 +1876,10 @@ GNUNET_DISK_npipe_open (const char *fn,
 int
 GNUNET_DISK_npipe_close (struct GNUNET_DISK_FileHandle *pipe)
 {
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   return close(pipe->fd) == 0 ? GNUNET_OK : GNUNET_SYSERR;
 #else
-  BOOL ret;
-
-  ret = CloseHandle(pipe->h);
-  if (!ret)
-    {
-      SetErrnoFromWinError(GetLastError());
-      return GNUNET_SYSERR;
-    }
-  else
-    return GNUNET_OK;
+  return GNUNET_W32IO_close (pipe->fd, 1);
 #endif
 }
 
@@ -1992,15 +1919,9 @@ int
 GNUNET_DISK_internal_file_handle_ (const struct GNUNET_DISK_FileHandle *fh,
                                    void *dst, size_t dst_len)
 {
-#ifdef MINGW
-  if (dst_len < sizeof (HANDLE))
-    return GNUNET_SYSERR;
-  *((HANDLE *) dst) = fh->h;
-#else
   if (dst_len < sizeof (int))
     return GNUNET_SYSERR;
   *((int *) dst) = fh->fd;
-#endif
 
   return GNUNET_OK;
 }
diff --git a/src/util/disk.h b/src/util/disk.h
index 093d704..73b84f4 100644
--- a/src/util/disk.h
+++ b/src/util/disk.h
@@ -34,25 +34,10 @@
  */ 
 struct GNUNET_DISK_FileHandle 
 {
-  
-#ifdef MINGW
-  /**
-   * File handle under W32.
-   */ 
-  HANDLE h;
-
-  /**
-   * Type
-   */
-  enum {GNUNET_DISK_FILE, GNUNET_PIPE} type;
-#else
-
   /**
    * File handle on other OSes.
    */ 
   int fd;
-   
-#endif                          /*  */
 };
 
 /**
diff --git a/src/util/gnunet-service-resolver.c b/src/util/gnunet-service-resolver.c
index f72b70d..97de8a6 100644
--- a/src/util/gnunet-service-resolver.c
+++ b/src/util/gnunet-service-resolver.c
@@ -250,7 +250,7 @@ getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc,
 
   memset (&hints, 0, sizeof (struct addrinfo));
 // FIXME in PlibC
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   hints.ai_family = domain;
 #else
   hints.ai_family = AF_INET;
@@ -266,7 +266,7 @@ getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc,
                                          AF_INET6) ? "IPv6" : "any"),
                   gai_strerror (s));
       if ((s == EAI_BADFLAGS) || (s == EAI_MEMORY) 
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
           || (s == EAI_SYSTEM)
 #else
           // FIXME NILS
@@ -466,7 +466,7 @@ handle_get (void *cls,
     {
 #if DEBUG_RESOLVER
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  _("Resolver asked to look up IP address.\n"));
+                  _("Resolver asked to look up IP address `%s'.\n"), GNUNET_a2s ((const struct sockaddr *) &msg[1], size));
 #endif
       get_ip_as_string (client, (const struct sockaddr *) &msg[1], size);
     }
diff --git a/src/util/network.c b/src/util/network.c
index 3b76a35..af15862 100644
--- a/src/util/network.c
+++ b/src/util/network.c
@@ -28,6 +28,7 @@
 #include "gnunet_disk_lib.h"
 #include "disk.h"
 #include "gnunet_container_lib.h"
+#include "w32io.h"
 
 #define DEBUG_NETWORK GNUNET_NO
 
@@ -38,13 +39,8 @@
 
 struct GNUNET_NETWORK_Handle
 {
-#ifndef MINGW
   int fd;
 
-#else
-  SOCKET fd;
-#endif
-
   /**
    * Address family / domain.
    */
@@ -60,23 +56,25 @@ struct GNUNET_NETWORK_FDSet
    */
   int nsds;
 
+#if WINDOWS
   /**
    * Bitset with the descriptors.
    */
-  fd_set sds;
-
-#ifdef WINDOWS
+  w32fd_set sds;
+#else
   /**
-   * Linked list of handles
+   * Bitset with the descriptors.
    */
-  struct GNUNET_CONTAINER_SList *handles;
+  fd_set sds;
 #endif
-
 };
 
 #ifndef FD_COPY
 #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
 #endif
+#if WINDOWS
+#define W32_FD_COPY(s, d) (memcpy ((d), (s), sizeof (w32fd_set)))
+#endif
 
 
 /**
@@ -89,11 +87,11 @@ static int
 socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
 {
 
-#if MINGW
+#if WINDOWS && !defined(__CYGWIN__)
   u_long mode;
   mode = !doBlock;
-  if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
 
+  if (ioctlsocket ((SOCKET) GNUNET_W32IO_fd_get_handle (fd->fd), FIONBIO, &mode) == SOCKET_ERROR)
     {
       SetErrnoFromWinsockError (WSAGetLastError ());
       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
@@ -102,7 +100,7 @@ socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
   return GNUNET_OK;
 
 #else
-  /* not MINGW */
+  /* not WINDOWS */
   int flags = fcntl (fd->fd, F_GETFL);
   if (flags == -1)
 
@@ -126,7 +124,7 @@ socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
 }
 
 
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
 /**
  * Make a socket non-inheritable to child processes
  *
@@ -179,13 +177,13 @@ socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
 static void
 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
 {
-#ifndef WINDOWS  
+#if !WINDOWS || defined(__CYGWIN__)
   int value = 1;
   if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
 #else
   const char * abs_value = "1";
-  if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, abs_value, sizeof (abs_value)))
+  if (0 != setsockopt ((SOCKET) GNUNET_W32IO_fd_get_handle (h->fd), IPPROTO_TCP, TCP_NODELAY, abs_value, sizeof (abs_value)))
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
 #endif	
 }
@@ -207,17 +205,26 @@ GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
   struct GNUNET_NETWORK_Handle *ret;
 
   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
+#if !WINDOWS || defined(__CYGWIN__)
   ret->fd = accept (desc->fd, address, address_len);
+#else
+  ret->fd = GNUNET_W32IO_accept (desc->fd, address, address_len);
+#endif
   ret->af = address->sa_family;
   if (ret->fd == INVALID_SOCKET)
     {
-#ifdef MINGW
-      SetErrnoFromWinsockError (WSAGetLastError ());
-#endif
       GNUNET_free (ret);
       return NULL;
     }
-#ifndef MINGW
+#if WINDOWS && !defined(__CYGWIN__)
+  if (ret->fd >= W32_FD_SETSIZE)
+    {
+      GNUNET_break (0 == GNUNET_W32IO_close (ret->fd, 1));
+      GNUNET_free (ret);
+      errno = EMFILE;
+      return NULL;
+    }
+#else
   if (ret->fd >= FD_SETSIZE)
     {
       GNUNET_break (0 == close (ret->fd));
@@ -227,16 +234,14 @@ GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
     }
 #endif
   if (GNUNET_SYSERR == socket_set_blocking (ret, GNUNET_NO))
-
     {
-
       /* we might want to treat this one as fatal... */
       GNUNET_break (0);
       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ret));
       return NULL;
     }
 
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   if (GNUNET_OK != socket_set_inheritable (ret))
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                          "socket_set_inheritable");
@@ -269,19 +274,25 @@ GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
 #ifdef IPV6_V6ONLY 
 #ifdef IPPROTO_IPV6
   const int on = 1;
+#if !WINDOWS || defined(__CYGWIN__)
   if (desc->af == AF_INET6)
     setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on));
+#else
+  if (desc->af == AF_INET6)
+    setsockopt (GNUNET_W32IO_fd_get_handle (desc->fd), IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on));
+#endif
 #if 0
   /* is this needed or desired? or done elsewhere? */
   setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on));
 #endif
 #endif
 #endif
+#if !WINDOWS || defined(__CYGWIN__)
   ret = bind (desc->fd, address, address_len);
-#ifdef MINGW
-  if (SOCKET_ERROR == ret)
-    SetErrnoFromWinsockError (WSAGetLastError ());
 #else
+  ret = GNUNET_W32IO_bind (desc->fd, address, address_len);
+#endif
+#if !WINDOWS || defined(__CYGWIN__)
 #ifndef LINUX
   if ( (ret == 0) && (address->sa_family == AF_UNIX))
     {
@@ -307,9 +318,8 @@ GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
 {
   int ret;
 
-#ifdef MINGW
-  ret = closesocket (desc->fd);
-  SetErrnoFromWinsockError (WSAGetLastError ());
+#if WINDOWS && !defined(__CYGWIN__)
+  ret = GNUNET_W32IO_close (desc->fd, 1);
 #else
   ret = close (desc->fd);
 #endif
@@ -327,8 +337,16 @@ GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
 struct GNUNET_NETWORK_Handle *
 GNUNET_NETWORK_socket_box_native (int fd)
 {
-#if MINGW
-  return NULL;
+#if WINDOWS && !defined(__CYGWIN__)
+  struct GNUNET_NETWORK_Handle *ret;
+
+  if (GNUNET_W32IO_find_handle_type ((HANDLE) fd) != GNUNET_W32IO_SOCKET)
+    return NULL; /* invalid FD */
+  ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle)); 
+  /* The arguments (three 1's at the end) are subject to discussion */
+  ret->fd = GNUNET_W32IO_fd_from_handle ((HANDLE) fd, GNUNET_W32IO_SOCKET, GENERIC_READ | GENERIC_WRITE, 1, 1, 1);
+  ret->af = AF_UNSPEC;
+  return ret;
 #else
   struct GNUNET_NETWORK_Handle *ret;
 
@@ -341,7 +359,6 @@ GNUNET_NETWORK_socket_box_native (int fd)
 #endif
 }
 
-
 /**
  * Connect a socket
  * @param desc socket
@@ -355,16 +372,10 @@ GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
                                socklen_t address_len)
 {
   int ret;
+#if WINDOWS && !defined(__CYGWIN__)
+  ret = GNUNET_W32IO_connect (desc->fd, address, address_len);
+#else
   ret = connect (desc->fd, address, address_len);
-
-#ifdef MINGW
-  if (SOCKET_ERROR == ret)
-
-    {
-      SetErrnoFromWinsockError (WSAGetLastError ());
-      if (errno == EWOULDBLOCK)
-        errno = EINPROGRESS;
-    }
 #endif
   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
 }
@@ -386,15 +397,15 @@ GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
                                   socklen_t * optlen)
 {
   int ret;
-  ret = getsockopt (desc->fd, level, optname, optval, optlen);
-
-#ifdef MINGW
+#if WINDOWS && !defined(__CYGWIN__)
+  ret = getsockopt ((SOCKET) GNUNET_W32IO_fd_get_handle (desc->fd), level, optname, optval, optlen);
   if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
     *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
 
   else if (SOCKET_ERROR == ret)
     SetErrnoFromWinsockError (WSAGetLastError ());
-
+#else
+  ret = getsockopt (desc->fd, level, optname, optval, optlen);
 #endif
   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
 }
@@ -411,12 +422,10 @@ GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
                               int backlog)
 {
   int ret;
+#if WINDOWS && !defined(__CYGWIN__)
+  ret = GNUNET_W32IO_listen (desc->fd, backlog);
+#else
   ret = listen (desc->fd, backlog);
-
-#ifdef MINGW
-  if (SOCKET_ERROR == ret)
-    SetErrnoFromWinsockError (WSAGetLastError ());
-
 #endif
   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
 }
@@ -435,13 +444,13 @@ GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle
   int error;
 
   /* How much is there to be read? */
-#ifndef WINDOWS
+#if !WINDOWS || defined(__CYGWIN__)
   int pending;
   error = ioctl (desc->fd, FIONREAD, &pending);
   if (error == 0)
-#else
+#elif WINDOWS
   u_long pending;
-  error = ioctlsocket (desc->fd, FIONREAD, &pending);
+  error = ioctlsocket ((SOCKET) GNUNET_W32IO_fd_get_handle (desc->fd), FIONREAD, &pending);
   if (error != SOCKET_ERROR)
 #endif
     return pending;
@@ -470,13 +479,12 @@ GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
 
 #ifdef MSG_DONTWAIT
   flags |= MSG_DONTWAIT;
-
 #endif
+#if WINDOWS && !defined(__CYGWIN__)
+  ret = GNUNET_W32IO_recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
+#else
   ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
-#ifdef MINGW
-  if (SOCKET_ERROR == ret)
-    SetErrnoFromWinsockError (WSAGetLastError ());
-#endif 
+#endif
   return ret;
 }
 
@@ -498,10 +506,10 @@ GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
 #ifdef MSG_DONTWAIT
   flags |= MSG_DONTWAIT;
 #endif
+#if WINDOWS && !defined(__CYGWIN__)
+  ret = GNUNET_W32IO_recv (desc->fd, buffer, length, flags);
+#else
   ret = recv (desc->fd, buffer, length, flags);
-#ifdef MINGW
-  if (SOCKET_ERROR == ret)
-    SetErrnoFromWinsockError (WSAGetLastError ());
 #endif
   return ret;
 }
@@ -525,19 +533,16 @@ GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
 
 #ifdef MSG_DONTWAIT
   flags |= MSG_DONTWAIT;
-
 #endif /*  */
 #ifdef MSG_NOSIGNAL
   flags |= MSG_NOSIGNAL;
-
 #endif /*  */
+#if WINDOWS && !defined(__CYGWIN__)
+  ret = desc->fd;
+  ret = GNUNET_W32IO_send (ret, buffer, length, flags);
+#else
   ret = send (desc->fd, buffer, length, flags);
-
-#ifdef MINGW
-  if (SOCKET_ERROR == ret)
-    SetErrnoFromWinsockError (WSAGetLastError ());
-
-#endif /*  */
+#endif
   return ret;
 }
 
@@ -569,10 +574,10 @@ GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
 #ifdef MSG_NOSIGNAL
   flags |= MSG_NOSIGNAL;
 #endif
+#if WINDOWS && !defined(__CYGWIN__)
+  ret = GNUNET_W32IO_sendto (desc->fd, message, length, flags, dest_addr, dest_len);
+#else
   ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
-#ifdef MINGW
-  if (SOCKET_ERROR == ret)
-    SetErrnoFromWinsockError (WSAGetLastError ());
 #endif
   return ret;
 }
@@ -595,10 +600,12 @@ GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd,
 {
   int ret;
 
-  ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
-#ifdef MINGW
+#if WINDOWS && !defined(__CYGWIN__)
+  ret = setsockopt ((SOCKET) GNUNET_W32IO_fd_get_handle (fd->fd), level, option_name, option_value, option_len);
   if (SOCKET_ERROR == ret)
     SetErrnoFromWinsockError (WSAGetLastError ());
+#else
+  ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
 #endif
   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
 }
@@ -620,17 +627,30 @@ GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
   struct GNUNET_NETWORK_Handle *ret;
   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
   ret->af = domain;
+#if WINDOWS && !defined(__CYGWIN__)
+  ret->fd = GNUNET_W32IO_fd_from_handle ((HANDLE) WSASocket (domain, type, protocol, NULL, 0, WSA_FLAG_OVERLAPPED), GNUNET_W32IO_SOCKET, GENERIC_READ | GENERIC_WRITE, 0, 0, 0);
+  if (ret->fd == -1)
+    {
+      GNUNET_free (ret);
+      return NULL;
+    }
+#else
   ret->fd = socket (domain, type, protocol);
   if (INVALID_SOCKET == ret->fd)
     {
-#ifdef MINGW
-      SetErrnoFromWinsockError (WSAGetLastError ());
+      GNUNET_free (ret);
+      return NULL;
+    }
 #endif
+#if WINDOWS && !defined(__CYGWIN__)
+  if (ret->fd >= W32_FD_SETSIZE)
+    {
+      GNUNET_break (0 == GNUNET_W32IO_close (ret->fd, 1));
       GNUNET_free (ret);
+      errno = EMFILE;
       return NULL;
     }
-
-#ifndef MINGW
+#else
   if (ret->fd >= FD_SETSIZE)
     {
       GNUNET_break (0 == close (ret->fd));
@@ -638,7 +658,6 @@ GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
       errno = EMFILE;
       return NULL;
     }
-
 #endif
   if (GNUNET_SYSERR == socket_set_blocking (ret, GNUNET_NO))
     {
@@ -648,7 +667,7 @@ GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
       return NULL;
     }
 
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   if (GNUNET_OK != socket_set_inheritable (ret))
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                          "socket_set_inheritable");
@@ -665,7 +684,6 @@ GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
   return ret;
 }
 
-
 /**
  * Shut down socket operations
  * @param desc socket
@@ -677,10 +695,10 @@ GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
 {
   int ret;
 
+#if WINDOWS && !defined(__CYGWIN__)
+  ret = GNUNET_W32IO_shutdown (desc->fd, how);
+#else
   ret = shutdown (desc->fd, how);
-#ifdef MINGW
-  if (ret != 0)
-    SetErrnoFromWinsockError (WSAGetLastError ());
 #endif
   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
 }
@@ -693,11 +711,12 @@ GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
 void
 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
 {
+#if WINDOWS && !defined(__CYGWIN__)
+  W32_FD_ZERO(&fds->sds);
+#else
   FD_ZERO (&fds->sds);
-  fds->nsds = 0;
-#ifdef MINGW
-  GNUNET_CONTAINER_slist_clear (fds->handles);
 #endif
+  fds->nsds = 0;
 }
 
 /**
@@ -709,7 +728,11 @@ void
 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
                           const struct GNUNET_NETWORK_Handle *desc)
 {
+#if WINDOWS && !defined(__CYGWIN__)
+  W32_FD_SET(desc->fd, &fds->sds);
+#else
   FD_SET (desc->fd, &fds->sds);
+#endif
   if (desc->fd + 1 > fds->nsds)
     fds->nsds = desc->fd + 1;
 }
@@ -725,7 +748,11 @@ int
 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
                             const struct GNUNET_NETWORK_Handle *desc)
 {
+#if WINDOWS && !defined(__CYGWIN__)
+  return W32_FD_ISSET(desc->fd, &fds->sds);
+#else
   return FD_ISSET (desc->fd, &fds->sds);
+#endif
 }
 
 
@@ -739,6 +766,16 @@ GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
                           const struct GNUNET_NETWORK_FDSet *src)
 {
   int nfds;
+#if WINDOWS && !defined(__CYGWIN__)
+  for (nfds = src->nsds; nfds > 0; nfds--)
+    if (W32_FD_ISSET(nfds, &src->sds))
+
+      {
+        W32_FD_SET(nfds, &dst->sds);
+        if (nfds + 1 > dst->nsds)
+          dst->nsds = nfds + 1;
+      }
+#else
   for (nfds = src->nsds; nfds > 0; nfds--)
     if (FD_ISSET (nfds, &src->sds))
 
@@ -747,8 +784,6 @@ GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
         if (nfds + 1 > dst->nsds)
           dst->nsds = nfds + 1;
       }
-#ifdef MINGW
-  GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
 #endif
 }
 
@@ -763,13 +798,12 @@ void
 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
                            const struct GNUNET_NETWORK_FDSet *from)
 {
+#if WINDOWS && !defined(__CYGWIN__)
+  W32_FD_COPY(&from->sds, &to->sds);
+#else
   FD_COPY (&from->sds, &to->sds);
-  to->nsds = from->nsds;
-
-#ifdef MINGW
-  GNUNET_CONTAINER_slist_clear (to->handles);
-  GNUNET_CONTAINER_slist_append (to->handles, from->handles);
 #endif
+  to->nsds = from->nsds;
 }
 
 int
@@ -789,7 +823,11 @@ void
 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
                                   const fd_set * from, int nfds)
 {
+#if WINDOWS && !defined(__CYGWIN__)
+  W32_FD_COPY(from, &to->sds);
+#else
   FD_COPY (from, &to->sds);
+#endif
   to->nsds = nfds;
 }
 
@@ -803,7 +841,11 @@ GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
 void GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to,
 				      int nfd)
 {
+#if WINDOWS && !defined(__CYGWIN__)
+  W32_FD_SET(nfd, &to->sds);
+#else
   FD_SET (nfd, &to->sds);
+#endif
   to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
 }
 
@@ -821,7 +863,11 @@ GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
 {
   if ( (nfd == -1) || (to == NULL) )
     return GNUNET_NO;
+#if WINDOWS && !defined(__CYGWIN__)
+  return W32_FD_ISSET(nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
+#else
   return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
+#endif
 }
 
 
@@ -834,19 +880,16 @@ void
 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
                                  const struct GNUNET_DISK_FileHandle *h)
 {
-#ifdef MINGW
-  GNUNET_CONTAINER_slist_add (fds->handles,
-                              GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
-                              h, sizeof (struct GNUNET_DISK_FileHandle));
-
-#else
   int fd;
   GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
+#if WINDOWS && !defined(__CYGWIN__)
+  W32_FD_SET(fd, &fds->sds);
+#else
   FD_SET (fd, &fds->sds);
+#endif
   if (fd + 1 > fds->nsds)
     fds->nsds = fd + 1;
 
-#endif
 }
 
 
@@ -861,9 +904,8 @@ GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
                                    const struct GNUNET_DISK_FileHandle *h)
 {
 
-#ifdef MINGW
-  return GNUNET_CONTAINER_slist_contains (fds->handles, h,
-                                          sizeof (struct GNUNET_DISK_FileHandle));
+#if WINDOWS && !defined(__CYGWIN__)
+  return W32_FD_ISSET (h->fd, &fds->sds);
 #else
   return FD_ISSET (h->fd, &fds->sds);
 #endif
@@ -880,7 +922,7 @@ int
 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
                               const struct GNUNET_NETWORK_FDSet *fds2)
 {
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   int nfds;
 
   nfds = fds1->nsds;
@@ -893,35 +935,17 @@ GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
 	return GNUNET_YES;
     }
 #else
-  struct GNUNET_CONTAINER_SList_Iterator *it;
-  struct GNUNET_DISK_FileHandle *h;
-  int i;
-  int j;
-
-  /*This code is somewhat hacky, we are not supposed to know what's
-    inside of fd_set; also the O(n^2) is really bad... */
+  int nfds;
 
-  for (i = 0; i < fds1->sds.fd_count; i++)
-  {
-    for (j = 0; j < fds2->sds.fd_count; j++)
-    {
-      if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
-        return GNUNET_YES;
-    }
-  }
-  it = GNUNET_CONTAINER_slist_begin (fds1->handles);
-  while (GNUNET_CONTAINER_slist_end (it) != GNUNET_YES)
+  nfds = fds1->nsds;
+  if (nfds > fds2->nsds)
+    nfds = fds2->nsds;
+  while (nfds > 0)
     {
-      h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (it, NULL);
-      if (GNUNET_CONTAINER_slist_contains
-          (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
-        {
-          GNUNET_CONTAINER_slist_iter_destroy (it);
-          return GNUNET_YES;
-        }
-      GNUNET_CONTAINER_slist_next (it);
+      nfds--;
+      if (W32_FD_ISSET(nfds, &fds1->sds) && W32_FD_ISSET(nfds, &fds2->sds))
+	return GNUNET_YES;
     }
-  GNUNET_CONTAINER_slist_iter_destroy (it);
 #endif
   return GNUNET_NO;
 }
@@ -936,9 +960,6 @@ GNUNET_NETWORK_fdset_create ()
 {
   struct GNUNET_NETWORK_FDSet *fds;
   fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
-#ifdef MINGW
-  fds->handles = GNUNET_CONTAINER_slist_create ();
-#endif
   GNUNET_NETWORK_fdset_zero (fds);
   return fds;
 }
@@ -951,9 +972,6 @@ GNUNET_NETWORK_fdset_create ()
 void
 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
 {
-#ifdef MINGW
-  GNUNET_CONTAINER_slist_destroy (fds->handles);
-#endif
   GNUNET_free (fds);
 }
 
@@ -972,33 +990,18 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
                               const struct GNUNET_TIME_Relative timeout)
 {
   int nfds;
-#ifdef MINGW
-  int handles;
-#endif
   nfds = 0;
-#ifdef MINGW
-  handles = 0;
-#endif
   if (NULL != rfds)
     {
       nfds = rfds->nsds;
-#ifdef MINGW
-      handles = GNUNET_CONTAINER_slist_count (rfds->handles);
-#endif
     }
   if (NULL != wfds)
     {
       nfds = GNUNET_MAX (nfds, wfds->nsds);
-#ifdef MINGW
-      handles += GNUNET_CONTAINER_slist_count (wfds->handles);
-#endif
     }
   if (NULL != efds)
     {
       nfds = GNUNET_MAX (nfds, efds->nsds);
-#ifdef MINGW
-      handles += GNUNET_CONTAINER_slist_count (efds->handles);
-#endif
     }
 
   struct timeval tv;
@@ -1006,9 +1009,6 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
   tv.tv_usec =
     1000 * (timeout.rel_value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
   if ((nfds == 0) && (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
-#ifdef MINGW
-      && handles == 0
-#endif
     )
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -1017,244 +1017,20 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
                   "select");
       GNUNET_break (0);
     }
-#ifndef MINGW
-  return select (nfds,
+#if WINDOWS && !defined(__CYGWIN__)
+  return GNUNET_W32IO_select (nfds,
                  (rfds != NULL) ? &rfds->sds : NULL,
                  (wfds != NULL) ? &wfds->sds : NULL,
                  (efds != NULL) ? &efds->sds : NULL,
                  (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
                  ? NULL : &tv);
-
 #else
-  DWORD limit;
-  fd_set sock_read, sock_write, sock_except;
-  fd_set aread, awrite, aexcept;
-  struct GNUNET_CONTAINER_SList *handles_read, *handles_write,
-    *handles_except;
-
-  int i;
-  struct timeval tvslice;
-  int retcode;
-  DWORD ms_total;
-
-#define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
-
-  /* calculate how long we need to wait in milliseconds */
-  if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
-    ms_total = INFINITE;
-
-  else
-    ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
-
-  /* select() may be used as a portable way to sleep */
-  if (!(rfds || wfds || efds))
-
-    {
-      Sleep (ms_total);
-      return 0;
-    }
-
-  handles_read = GNUNET_CONTAINER_slist_create ();
-  handles_write = GNUNET_CONTAINER_slist_create ();
-  handles_except = GNUNET_CONTAINER_slist_create ();
-
-  if (rfds)
-    sock_read = rfds->sds;
-  else
-    FD_ZERO (&sock_read);
-  if (wfds)
-    sock_write = wfds->sds;
-  else
-    FD_ZERO (&sock_write);
-  if (efds)
-    sock_except = efds->sds;
-  else
-    FD_ZERO (&sock_except);
-
-  /* multiplex between winsock select() and waiting on the handles */
-  FD_ZERO (&aread);
-  FD_ZERO (&awrite);
-  FD_ZERO (&aexcept);
-  limit = GetTickCount () + ms_total;
-
-  do
-    {
-      retcode = 0;
-      if (nfds > 0)
-
-        {
-
-          /* overwrite the zero'd sets here; the select call
-           * will clear those that are not active */
-          FD_COPY (&sock_read, &aread);
-          FD_COPY (&sock_write, &awrite);
-          FD_COPY (&sock_except, &aexcept);
-          tvslice.tv_sec = 0;
-          tvslice.tv_usec = 100000;
-          if ((retcode =
-               select (nfds + 1, &aread, &awrite, &aexcept,
-                       &tvslice)) == SOCKET_ERROR)
-
-            {
-              SetErrnoFromWinsockError (WSAGetLastError ());
-              if (errno == ENOTSOCK)
-                errno = EBADF;
-
-#if DEBUG_NETWORK
-              GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select");
-
-#endif
-              goto select_loop_end;
-            }
-        }
-
-      /* Poll read pipes */
-      if (rfds)
-
-        {
-          struct GNUNET_CONTAINER_SList_Iterator *i;
-          for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
-               GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
-               GNUNET_CONTAINER_slist_next (i))
-
-            {
-              struct GNUNET_DISK_FileHandle *fh;
-              DWORD dwBytes;
-              fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL);
-              if (fh->type == GNUNET_PIPE)
-                {
-                  if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
-                    {
-                      retcode = -1;
-                      SetErrnoFromWinError (GetLastError ());
-
-    #if DEBUG_NETWORK
-                      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
-                                           "PeekNamedPipe");
-
-    #endif
-                      goto select_loop_end;
-                    }
-                  else if (dwBytes)
-
-                    {
-                      GNUNET_CONTAINER_slist_add (handles_read,
-                                                  GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
-                                                  fh, sizeof (struct GNUNET_DISK_FileHandle));
-                      retcode++;
-                    }
-                }
-              else
-                {
-                  /* Should we wait for more bytes to read here (in case of previous EOF)? */
-                  GNUNET_CONTAINER_slist_add (handles_read,
-                                              GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
-                                              fh, sizeof (struct GNUNET_DISK_FileHandle));
-                }
-            }
-          GNUNET_CONTAINER_slist_iter_destroy (i);
-        }
-
-      /* Poll for faulty pipes */
-      if (efds)
-
-        {
-          struct GNUNET_CONTAINER_SList_Iterator *i;
-          for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
-               GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
-               GNUNET_CONTAINER_slist_next (i))
-
-            {
-              struct GNUNET_DISK_FileHandle *fh;
-              DWORD dwBytes;
-
-              fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL);
-              if (fh->type == GNUNET_PIPE)
-                {
-                  if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
-
-                    {
-                      GNUNET_CONTAINER_slist_add (handles_except,
-                                                  GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
-                                                  fh, sizeof (struct GNUNET_DISK_FileHandle));
-                      retcode++;
-                    }
-                }
-            }
-          GNUNET_CONTAINER_slist_iter_destroy (i);
-        }
-
-      if (wfds)
-        {
-          GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
-          retcode += GNUNET_CONTAINER_slist_count (wfds->handles);
-        }
-
-      /* Check for closed sockets */
-      for (i = 0; i < nfds; i++)
-
-        {
-          if (SAFE_FD_ISSET (i, &sock_read))
-
-            {
-              struct sockaddr addr;
-              int len;
-              if (getpeername (i, &addr, &len) == SOCKET_ERROR)
-
-                {
-                  int err, len;
-                  len = sizeof (err);
-                  if (getsockopt
-                      (i, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == 0
-                      && err == WSAENOTCONN)
-
-                    {
-                      if (!SAFE_FD_ISSET (i, &aread))
-
-                        {
-                          FD_SET (i, &aread);
-                          retcode++;
-                        }
-                    }
-                }
-            }
-        }
-    select_loop_end:
-      if (retcode == 0 && nfds == 0)
-        Sleep (GNUNET_MIN (100, limit - GetTickCount ()));
-    }
-  while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit));
-
-  if (retcode != -1)
-    {
-      if (rfds)
-        {
-          GNUNET_NETWORK_fdset_zero (rfds);
-          GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
-          GNUNET_CONTAINER_slist_clear (rfds->handles);
-          GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
-        }
-      if (wfds)
-        {
-          GNUNET_NETWORK_fdset_zero (wfds);
-          GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
-          GNUNET_CONTAINER_slist_clear (wfds->handles);
-          GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
-        }
-      if (efds)
-        {
-          GNUNET_NETWORK_fdset_zero (efds);
-          GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
-          GNUNET_CONTAINER_slist_clear (efds->handles);
-          GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
-        }
-    }
-
-  GNUNET_CONTAINER_slist_destroy (handles_read);
-  GNUNET_CONTAINER_slist_destroy (handles_write);
-  GNUNET_CONTAINER_slist_destroy (handles_except);
-
-  return retcode;
+  return select (nfds,
+                 (rfds != NULL) ? &rfds->sds : NULL,
+                 (wfds != NULL) ? &wfds->sds : NULL,
+                 (efds != NULL) ? &efds->sds : NULL,
+                 (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
+                 ? NULL : &tv);
 #endif
 }
 
diff --git a/src/util/os_installation.c b/src/util/os_installation.c
index cbbc614..830b68d 100644
--- a/src/util/os_installation.c
+++ b/src/util/os_installation.c
@@ -106,7 +106,7 @@ get_path_from_proc_exe ()
 }
 #endif
 
-#if WINDOWS
+#if WINDOWS && !defined(__CYGWIN__)
 /**
  * Try to determine path with win32-specific function
  */
@@ -268,7 +268,7 @@ os_get_gnunet_path ()
   if (ret != NULL)
     return ret;
 #endif
-#if WINDOWS
+#if WINDOWS && !defined(__CYGWIN__)
   ret = get_path_from_module_filename ();
   if (ret != NULL)
     return ret;
@@ -310,7 +310,7 @@ os_get_exec_path ()
   if (ret != NULL)
     return ret;
 #endif
-#if WINDOWS
+#if WINDOWS && !defined(__CYGWIN__)
   ret = get_path_from_module_filename ();
   if (ret != NULL)
     return ret;
diff --git a/src/util/os_network.c b/src/util/os_network.c
index 453eea6..76e9579 100644
--- a/src/util/os_network.c
+++ b/src/util/os_network.c
@@ -41,7 +41,7 @@ void
 GNUNET_OS_network_interfaces_list (GNUNET_OS_NetworkInterfaceProcessor proc,
                                    void *proc_cls)
 {
-#ifdef MINGW
+#if WINDOWS && !defined(__CYGWIN__)
   PMIB_IFTABLE pTable;
   PMIB_IPADDRTABLE pAddrTable;
   DWORD dwIfIdx, dwExternalNIC;
diff --git a/src/util/os_priority.c b/src/util/os_priority.c
index fb6c292..093d2a7 100644
--- a/src/util/os_priority.c
+++ b/src/util/os_priority.c
@@ -23,16 +23,16 @@
  * @brief Methods to set process priority
  * @author Nils Durner
  */
-
 #include "platform.h"
 #include "gnunet_common.h"
 #include "gnunet_os_lib.h"
 #include "disk.h"
+#include "w32io.h"
 
 struct GNUNET_OS_Process
 {
   pid_t pid;
-#if WINDOWS
+#if WINDOWS && !defined(__CYGWIN__)
   HANDLE handle;
 #endif
 };
@@ -40,7 +40,7 @@ struct GNUNET_OS_Process
 static struct GNUNET_OS_Process current_process;
 
 
-#if WINDOWS
+#if WINDOWS && !defined(__CYGWIN__)
 void
 GNUNET_OS_process_set_handle(struct GNUNET_OS_Process *proc, HANDLE handle)
 {
@@ -62,7 +62,7 @@ GNUNET_OS_process_set_handle(struct GNUNET_OS_Process *proc, HANDLE handle)
 struct GNUNET_OS_Process *
 GNUNET_OS_process_current ()
 {
-#if WINDOWS
+#if WINDOWS && !defined(__CYGWIN__)
   current_process.pid = GetCurrentProcessId ();
   current_process.handle = GetCurrentProcess ();
 #else
@@ -74,7 +74,7 @@ GNUNET_OS_process_current ()
 int
 GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig)
 {
-#if WINDOWS
+#if WINDOWS && !defined(__CYGWIN__)
   if (sig == SIGKILL || sig == SIGTERM)
   {
     HANDLE h = proc->handle;
@@ -117,14 +117,14 @@ GNUNET_OS_process_get_pid (struct GNUNET_OS_Process *proc)
 void
 GNUNET_OS_process_close (struct GNUNET_OS_Process *proc)
 {
-#if WINDOWS
+#if WINDOWS && !defined(__CYGWIN__)
   if (proc->handle != NULL)
     CloseHandle (proc->handle);
 #endif  
   GNUNET_free (proc);
 }
 
-#if WINDOWS
+#if WINDOWS && !defined(__CYGWIN__)
 #include "gnunet_signal_lib.h"
 
 extern GNUNET_SIGNAL_Handler w32_sigchld_handler;
@@ -173,7 +173,7 @@ GNUNET_OS_set_process_priority (struct GNUNET_OS_Process *proc,
     {
     case GNUNET_SCHEDULER_PRIORITY_UI:
     case GNUNET_SCHEDULER_PRIORITY_URGENT:
-#ifdef MINGW
+#if WINDOWS && !defined(__CYGWIN__)
       rprio = HIGH_PRIORITY_CLASS;
 #else
       rprio = 0;
@@ -181,7 +181,7 @@ GNUNET_OS_set_process_priority (struct GNUNET_OS_Process *proc,
       break;
 
     case GNUNET_SCHEDULER_PRIORITY_HIGH:
-#ifdef MINGW
+#if WINDOWS && !defined(__CYGWIN__)
       rprio = ABOVE_NORMAL_PRIORITY_CLASS;
 #else
       rprio = 5;
@@ -189,7 +189,7 @@ GNUNET_OS_set_process_priority (struct GNUNET_OS_Process *proc,
       break;
 
     case GNUNET_SCHEDULER_PRIORITY_DEFAULT:
-#ifdef MINGW
+#if WINDOWS && !defined(__CYGWIN__)
       rprio = NORMAL_PRIORITY_CLASS;
 #else
       rprio = 7;
@@ -197,7 +197,7 @@ GNUNET_OS_set_process_priority (struct GNUNET_OS_Process *proc,
       break;
 
     case GNUNET_SCHEDULER_PRIORITY_BACKGROUND:
-#ifdef MINGW
+#if WINDOWS && !defined(__CYGWIN__)
       rprio = BELOW_NORMAL_PRIORITY_CLASS;
 #else
       rprio = 10;
@@ -205,7 +205,7 @@ GNUNET_OS_set_process_priority (struct GNUNET_OS_Process *proc,
       break;
 
     case GNUNET_SCHEDULER_PRIORITY_IDLE:
-#ifdef MINGW
+#if WINDOWS && !defined(__CYGWIN__)
       rprio = IDLE_PRIORITY_CLASS;
 #else
       rprio = 19;
@@ -217,7 +217,7 @@ GNUNET_OS_set_process_priority (struct GNUNET_OS_Process *proc,
     }
 
   /* Set process priority */
-#ifdef MINGW
+#if WINDOWS && !defined(__CYGWIN__)
   {
     HANDLE h = proc->handle;
     GNUNET_assert (h != NULL);
@@ -274,7 +274,7 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin,
 {
   va_list ap;
 
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   pid_t ret;
   struct GNUNET_OS_Process *gnunet_proc = NULL;
   char **argv;
@@ -368,22 +368,43 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin,
   STARTUPINFO start;
   PROCESS_INFORMATION proc;
   struct GNUNET_OS_Process *gnunet_proc = NULL;
-
-  HANDLE stdin_handle;
-  HANDLE stdout_handle;
+  size_t flen;
 
   char path[MAX_PATH + 1];
 
+  int stdin_handle;
+  int stdout_handle;
+
+  flen = strlen (filename);
+
+  if (flen < 4 || (filename[flen - 1] != 'e' && filename[flen - 1] != 'E') ||
+      (filename[flen - 2] != 'x' && filename[flen - 2] != 'X') ||
+      (filename[flen - 3] != 'e' && filename[flen - 3] != 'E') ||
+      (filename[flen - 4] != '.'))
+    snprintf (path, MAX_PATH + 1, "%s.exe", filename);
+  else
+    snprintf (path, MAX_PATH + 1, "%s", filename);
+
   cmdlen = 0;
   va_start (ap, filename);
   while (NULL != (arg = va_arg (ap, char *)))
-      cmdlen = cmdlen + strlen (arg) + 3;
+  {
+      if (cmdlen == 0)
+        cmdlen = cmdlen + strlen (path) + 3;
+      else
+        cmdlen = cmdlen + strlen (arg) + 3;
+  }
   va_end (ap);
 
   cmd = idx = GNUNET_malloc (sizeof (char) * (cmdlen + 1));
   va_start (ap, filename);
   while (NULL != (arg = va_arg (ap, char *)))
-      idx += sprintf (idx, "\"%s\" ", arg);
+  {
+      if (idx == cmd)
+        idx += sprintf (idx, "\"%s\" ", path);
+      else
+        idx += sprintf (idx, "\"%s\" ", arg);
+  }
   va_end (ap);
 
   memset (&start, 0, sizeof (start));
@@ -394,32 +415,37 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin,
 
   if (pipe_stdin != NULL)
     {
-      GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle(pipe_stdin, GNUNET_DISK_PIPE_END_READ), &stdin_handle, sizeof (HANDLE));
-      start.hStdInput = stdin_handle;
+      GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle(pipe_stdin, GNUNET_DISK_PIPE_END_READ), &stdin_handle, sizeof (int));
+      start.hStdInput = GNUNET_W32IO_fd_get_handle (stdin_handle);
     }
 
   if (pipe_stdout != NULL)
     {
-      GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle(pipe_stdout, GNUNET_DISK_PIPE_END_WRITE), &stdout_handle, sizeof (HANDLE));
-      start.hStdOutput = stdout_handle;
+      GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle(pipe_stdout, GNUNET_DISK_PIPE_END_WRITE), &stdout_handle, sizeof (int));
+      start.hStdOutput = GNUNET_W32IO_fd_get_handle (stdout_handle);
     }
 
-  if (32 >= (int) FindExecutableA (filename, NULL, path)) 
+  if (!CreateProcessA
+      (path, cmd, NULL, NULL, TRUE, DETACHED_PROCESS | CREATE_SUSPENDED, NULL, NULL, &start,
+       &proc))
     {
       SetErrnoFromWinError (GetLastError ());
-      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "FindExecutable", filename);
+      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "CreateProcess", filename);
       return NULL;
     }
 
-  if (!CreateProcessA
-      (path, cmd, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &start,
-       &proc))
+  if (pipe_stdin != NULL)
     {
-      SetErrnoFromWinError (GetLastError ());
-      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "CreateProcess", path);
-      return NULL;
+      GNUNET_DISK_pipe_close_end (pipe_stdin, GNUNET_DISK_PIPE_END_READ);
+    }
+
+  if (pipe_stdout != NULL)
+    {
+      GNUNET_DISK_pipe_close_end (pipe_stdout, GNUNET_DISK_PIPE_END_WRITE);
     }
 
+  ResumeThread (proc.hThread);
+
   gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process));
   gnunet_proc->pid = proc.dwProcessId;
   gnunet_proc->handle = proc.hProcess;
@@ -450,7 +476,7 @@ struct GNUNET_OS_Process *
 GNUNET_OS_start_process_v (const int *lsocks,
 			   const char *filename, char *const argv[])
 {
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   pid_t ret;
   char lpid[16];
   char fds[16];
@@ -555,17 +581,21 @@ GNUNET_OS_start_process_v (const int *lsocks,
   STARTUPINFO start;
   PROCESS_INFORMATION proc;
   int argcount = 0;
-  char non_const_filename[MAX_PATH +1];
+  char path[MAX_PATH +1];
+  size_t flen;
   struct GNUNET_OS_Process *gnunet_proc = NULL;
 
   GNUNET_assert (lsocks == NULL);
 
-  if (32 >= (int) FindExecutableA (filename, NULL, non_const_filename)) 
-    {
-      SetErrnoFromWinError (GetLastError ());
-      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "FindExecutable", filename);
-      return NULL;
-    }
+  flen = strlen (filename);
+
+  if (flen < 4 || (filename[flen - 1] != 'e' && filename[flen - 1] != 'E') ||
+      (filename[flen - 2] != 'x' && filename[flen - 2] != 'X') ||
+      (filename[flen - 3] != 'e' && filename[flen - 3] != 'E') ||
+      (filename[flen - 4] != '.'))
+    snprintf (path, MAX_PATH + 1, "%s.exe", filename);
+  else
+    snprintf (path, MAX_PATH + 1, "%s", filename);
 
   /* Count the number of arguments */
   arg = (char **) argv;
@@ -583,7 +613,10 @@ GNUNET_OS_start_process_v (const int *lsocks,
   arg = (char **) argv;
   while (*arg)
     {
-      non_const_argv[argcount] = GNUNET_strdup (*arg);
+      if (argcount == 0)
+        non_const_argv[argcount] = GNUNET_strdup (path);
+      else
+        non_const_argv[argcount] = GNUNET_strdup (*arg);
       arg++;
       argcount++;
     }
@@ -610,8 +643,8 @@ GNUNET_OS_start_process_v (const int *lsocks,
   memset (&start, 0, sizeof (start));
   start.cb = sizeof (start);
 
-  if (!CreateProcess
-      (non_const_filename, cmd, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &start,
+  if (!CreateProcessA
+      (path, cmd, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &start,
        &proc))
     {
       SetErrnoFromWinError (GetLastError ());
@@ -648,7 +681,7 @@ GNUNET_OS_process_status (struct GNUNET_OS_Process *proc,
 			  enum GNUNET_OS_ProcessStatusType *type,
                           unsigned long *code)
 {
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   int status;
   int ret;
 
@@ -742,7 +775,7 @@ int
 GNUNET_OS_process_wait (struct GNUNET_OS_Process *proc)
 {
 
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   pid_t pid = proc->pid;
   if (pid != waitpid (pid, NULL, 0))
     return GNUNET_SYSERR;
@@ -777,3 +810,4 @@ GNUNET_OS_process_wait (struct GNUNET_OS_Process *proc)
 
 
 /* end of os_priority.c */
+
diff --git a/src/util/scheduler.c b/src/util/scheduler.c
index 13b3f85..fda1ab4 100644
--- a/src/util/scheduler.c
+++ b/src/util/scheduler.c
@@ -666,7 +666,7 @@ static struct GNUNET_DISK_PipeHandle *shutdown_pipe_handle;
 /**
  * Signal handler called for SIGPIPE.
  */
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
 static void
 sighandler_pipe ()
 {
@@ -712,7 +712,7 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls)
   int ret;
   struct GNUNET_SIGNAL_Context *shc_int;
   struct GNUNET_SIGNAL_Context *shc_term;
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   struct GNUNET_SIGNAL_Context *shc_quit;
   struct GNUNET_SIGNAL_Context *shc_hup;
   struct GNUNET_SIGNAL_Context *shc_pipe;
@@ -732,7 +732,7 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls)
   GNUNET_assert (pr != NULL);
   shc_int = GNUNET_SIGNAL_handler_install (SIGINT, &sighandler_shutdown);
   shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, &sighandler_shutdown);
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE, &sighandler_pipe);
   shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT, &sighandler_shutdown);
   shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, &sighandler_shutdown);
@@ -764,7 +764,7 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls)
             continue;
 
           GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select");
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
 #if USE_LSOF
 	  char lsof[512];
 	  snprintf (lsof, sizeof (lsof), "lsof -p %d", getpid());
@@ -803,7 +803,7 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls)
     }
   GNUNET_SIGNAL_handler_uninstall (shc_int);
   GNUNET_SIGNAL_handler_uninstall (shc_term);
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   GNUNET_SIGNAL_handler_uninstall (shc_pipe);
   GNUNET_SIGNAL_handler_uninstall (shc_quit);
   GNUNET_SIGNAL_handler_uninstall (shc_hup);
@@ -1194,7 +1194,6 @@ GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_Task task,
  * @return unique task identifier for the job
  *         only valid until "task" is started!
  */
-#ifndef MINGW
 GNUNET_SCHEDULER_TaskIdentifier
 add_without_sets (struct GNUNET_TIME_Relative delay,
 		  int rfd,
@@ -1244,7 +1243,6 @@ add_without_sets (struct GNUNET_TIME_Relative delay,
 #endif
   return t->id;
 }
-#endif
 
 
 
@@ -1269,25 +1267,11 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay,
                                struct GNUNET_NETWORK_Handle * rfd,
                                GNUNET_SCHEDULER_Task task, void *task_cls)
 {
-#if MINGW
-  struct GNUNET_NETWORK_FDSet *rs;
-  GNUNET_SCHEDULER_TaskIdentifier ret;
-
-  GNUNET_assert (rfd != NULL);
-  rs = GNUNET_NETWORK_fdset_create ();
-  GNUNET_NETWORK_fdset_set (rs, rfd);
-  ret = GNUNET_SCHEDULER_add_select (check_priority (current_priority),
-                                     GNUNET_SCHEDULER_NO_TASK, delay,
-                                     rs, NULL, task, task_cls);
-  GNUNET_NETWORK_fdset_destroy (rs);
-  return ret;
-#else
   return add_without_sets (delay,
 			   GNUNET_NETWORK_get_fd (rfd),
 			   -1,
 			   task,
 			   task_cls);
-#endif
 }
 
 
@@ -1312,25 +1296,11 @@ GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay,
                                 struct GNUNET_NETWORK_Handle * wfd,
                                 GNUNET_SCHEDULER_Task task, void *task_cls)
 {
-#if MINGW
-  struct GNUNET_NETWORK_FDSet *ws;
-  GNUNET_SCHEDULER_TaskIdentifier ret;
-
-  GNUNET_assert (wfd != NULL);
-  ws = GNUNET_NETWORK_fdset_create ();
-  GNUNET_NETWORK_fdset_set (ws, wfd);
-  ret = GNUNET_SCHEDULER_add_select (check_priority (current_priority),
-                                     GNUNET_SCHEDULER_NO_TASK, delay,
-                                     NULL, ws, task, task_cls);
-  GNUNET_NETWORK_fdset_destroy (ws);
-  return ret;
-#else
   return add_without_sets (delay,
 			   -1,
 			   GNUNET_NETWORK_get_fd (wfd),
 			   task,
 			   task_cls);
-#endif
 }
 
 
@@ -1355,19 +1325,6 @@ GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay,
                                 const struct GNUNET_DISK_FileHandle * rfd,
                                 GNUNET_SCHEDULER_Task task, void *task_cls)
 {
-#if MINGW
-  struct GNUNET_NETWORK_FDSet *rs;
-  GNUNET_SCHEDULER_TaskIdentifier ret;
-
-  GNUNET_assert (rfd != NULL);
-  rs = GNUNET_NETWORK_fdset_create ();
-  GNUNET_NETWORK_fdset_handle_set (rs, rfd);
-  ret = GNUNET_SCHEDULER_add_select (check_priority (current_priority),
-                                     GNUNET_SCHEDULER_NO_TASK, delay,
-                                     rs, NULL, task, task_cls);
-  GNUNET_NETWORK_fdset_destroy (rs);
-  return ret;
-#else
   int fd;
 
   GNUNET_DISK_internal_file_handle_ (rfd, &fd, sizeof (int));
@@ -1377,7 +1334,6 @@ GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay,
 			   task,
 			   task_cls);
 
-#endif
 }
 
 
@@ -1402,19 +1358,6 @@ GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay,
                                  const struct GNUNET_DISK_FileHandle * wfd,
                                  GNUNET_SCHEDULER_Task task, void *task_cls)
 {
-#if MINGW
-  struct GNUNET_NETWORK_FDSet *ws;
-  GNUNET_SCHEDULER_TaskIdentifier ret;
-
-  GNUNET_assert (wfd != NULL);
-  ws = GNUNET_NETWORK_fdset_create ();
-  GNUNET_NETWORK_fdset_handle_set (ws, wfd);
-  ret = GNUNET_SCHEDULER_add_select (check_priority (current_priority),
-                                     GNUNET_SCHEDULER_NO_TASK,
-                                     delay, NULL, ws, task, task_cls);
-  GNUNET_NETWORK_fdset_destroy (ws);
-  return ret;
-#else
   int fd;
 
   GNUNET_DISK_internal_file_handle_ (wfd, &fd, sizeof (int));
@@ -1424,7 +1367,6 @@ GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay,
 			   task,
 			   task_cls);
 
-#endif
 }
 
 
diff --git a/src/util/service.c b/src/util/service.c
index 25a9b08..30f6680 100644
--- a/src/util/service.c
+++ b/src/util/service.c
@@ -1099,7 +1099,7 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
 {
   struct GNUNET_TIME_Relative idleout;
   int tolerant;
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   const char *lpid;
   unsigned int pid;
   const char *nfds;
@@ -1144,7 +1144,7 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
   else
     tolerant = GNUNET_NO;
 
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   errno = 0;
   if ( (NULL != (lpid = getenv ("LISTEN_PID"))) &&
        (1 == sscanf (lpid, "%u", &pid)) &&
@@ -1365,7 +1365,7 @@ service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 static int
 detach_terminal (struct GNUNET_SERVICE_Context *sctx)
 {
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   pid_t pid;
   int nullfd;
   int filedes[2];
@@ -1449,7 +1449,7 @@ set_user_id (struct GNUNET_SERVICE_Context *sctx)
 
   if (NULL == (user = get_user_name (sctx)))
     return GNUNET_OK;           /* keep */
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   struct passwd *pws;
 
   errno = 0;
diff --git a/src/util/signal.c b/src/util/signal.c
index 0fe4bfc..efcad10 100644
--- a/src/util/signal.c
+++ b/src/util/signal.c
@@ -34,12 +34,12 @@ struct GNUNET_SIGNAL_Context
 
   GNUNET_SIGNAL_Handler method;
 
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   struct sigaction oldsig;
 #endif
 };
 
-#ifdef WINDOWS
+#if WINDOWS
 GNUNET_SIGNAL_Handler w32_sigchld_handler = NULL;
 #endif
 
@@ -47,14 +47,14 @@ struct GNUNET_SIGNAL_Context *
 GNUNET_SIGNAL_handler_install (int signum, GNUNET_SIGNAL_Handler handler)
 {
   struct GNUNET_SIGNAL_Context *ret;
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   struct sigaction sig;
 #endif
 
   ret = GNUNET_malloc (sizeof (struct GNUNET_SIGNAL_Context));
   ret->sig = signum;
   ret->method = handler;
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   sig.sa_handler = (void *) handler;
   sigemptyset (&sig.sa_mask);
 #ifdef SA_INTERRUPT
@@ -84,7 +84,7 @@ GNUNET_SIGNAL_handler_install (int signum, GNUNET_SIGNAL_Handler handler)
 void
 GNUNET_SIGNAL_handler_uninstall (struct GNUNET_SIGNAL_Context *ctx)
 {
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   struct sigaction sig;
 
   sigemptyset (&sig.sa_mask);
diff --git a/src/util/strings.c b/src/util/strings.c
index fa445f6..c78cdc1 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -199,7 +199,7 @@ GNUNET_STRINGS_to_utf8 (const char *input, size_t len, const char *charset)
   itmp = tmp;
   finSize = tmpSize;
   if (iconv (cd,
-#if FREEBSD || DARWIN || WINDOWS
+#if FREEBSD || DARWIN || (WINDOWS && !defined(__CYGWIN__))
              (const char **) &input,
 #else
              (char **) &input,
@@ -241,7 +241,7 @@ char *
 GNUNET_STRINGS_filename_expand (const char *fil)
 {
   char *buffer;
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   size_t len;
   size_t n;
   char *fm;
@@ -254,7 +254,7 @@ GNUNET_STRINGS_filename_expand (const char *fil)
   if (fil == NULL)
     return NULL;
 
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   if (fil[0] == DIR_SEPARATOR)
     /* absolute path, just copy */
     return GNUNET_strdup (fil);
diff --git a/src/util/test_configuration.c b/src/util/test_configuration.c
index 77e33a5..0d05f46 100644
--- a/src/util/test_configuration.c
+++ b/src/util/test_configuration.c
@@ -320,7 +320,7 @@ testConfig ()
       GNUNET_break (0);
       return 8;
     }
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   if (0 != strcmp (c, "/hello/world"))
 #else
 #define HI "\\hello\\world"
diff --git a/src/util/test_getopt.c b/src/util/test_getopt.c
index 88a4255..4464d13 100644
--- a/src/util/test_getopt.c
+++ b/src/util/test_getopt.c
@@ -194,7 +194,7 @@ main (int argc, char *argv[])
 
   GNUNET_log_setup ("test_getopt", "WARNING", NULL);
   /* suppress output from -h, -v options */
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   GNUNET_break (0 == CLOSE (1));
 #endif
   if (0 != testMinimal ())
diff --git a/src/util/test_os_start_process.c b/src/util/test_os_start_process.c
index f82860e..8b7720c 100644
--- a/src/util/test_os_start_process.c
+++ b/src/util/test_os_start_process.c
@@ -106,9 +106,12 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   char *fn;
   const struct GNUNET_DISK_FileHandle *stdout_read_handle;
   const struct GNUNET_DISK_FileHandle *wh;
-
+#if !WINDOWS || defined(__CYGWIN__)
   GNUNET_asprintf(&fn, "cat");
-
+#else
+  /* Assume that MSys sets %HOME% to %MSYSDIR%/home/%USERNAME% */
+  GNUNET_asprintf(&fn, "%s\\..\\..\\bin\\cat.exe", getenv ("HOME"));
+#endif
   hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO);
   hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES);
 
@@ -124,11 +127,6 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
                                  "test_gnunet_echo_hello", "-", NULL);
   GNUNET_free (fn);
 
-  /* Close the write end of the read pipe */
-  GNUNET_DISK_pipe_close_end(hello_pipe_stdout, GNUNET_DISK_PIPE_END_WRITE);
-  /* Close the read end of the write pipe */
-  GNUNET_DISK_pipe_close_end(hello_pipe_stdin, GNUNET_DISK_PIPE_END_READ);
-
   wh = GNUNET_DISK_pipe_handle (hello_pipe_stdin, GNUNET_DISK_PIPE_END_WRITE);
 
   /* Write the test_phrase to the cat process */
diff --git a/src/util/test_resolver_api.c b/src/util/test_resolver_api.c
index bf2f8f0..dc01b63 100644
--- a/src/util/test_resolver_api.c
+++ b/src/util/test_resolver_api.c
@@ -315,8 +315,13 @@ run(void *cls, char * const *args,
       GNUNET_break(0);
     }
 
+#if WINDOWS && !defined(__CYGWIN__)
+  rootserver
+      = gethostbyaddr((const char *) &rootserver_addr, sizeof(rootserver_addr), AF_INET);
+#else
   rootserver
       = gethostbyaddr(&rootserver_addr, sizeof(rootserver_addr), AF_INET);
+#endif
   if (rootserver == NULL)
     {
       /* Error: resolving IP addresses does not work */
@@ -345,7 +350,7 @@ run(void *cls, char * const *args,
 
   memset(&sa, 0, sizeof(sa));
   sa.sin_family = AF_INET;
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   inet_aton(ROOTSERVER_IP, &sa.sin_addr);
 #else
   sa.sin_addr.S_un.S_addr = inet_addr(ROOTSERVER_IP);
diff --git a/src/util/test_scheduler.c b/src/util/test_scheduler.c
index f0c908d..3b5c5cb 100644
--- a/src/util/test_scheduler.c
+++ b/src/util/test_scheduler.c
@@ -181,6 +181,7 @@ checkShutdown ()
   return ok;
 }
 
+#if !WINDOWS || defined(__CYGWIN__)
 
 static void
 taskSig (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
@@ -206,7 +207,7 @@ checkSignal ()
   GNUNET_SCHEDULER_run (&taskSig, &ok);
   return ok;
 }
-
+#endif
 
 static void
 taskCancel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
@@ -243,7 +244,7 @@ main (int argc, char *argv[])
 
   GNUNET_log_setup ("test_scheduler", "WARNING", NULL);
   ret += check ();
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   ret += checkSignal ();
 #endif
   ret += checkShutdown ();
diff --git a/src/util/test_service.c b/src/util/test_service.c
index 9bd5835..3f445f4 100644
--- a/src/util/test_service.c
+++ b/src/util/test_service.c
@@ -273,10 +273,7 @@ main (int argc, char *argv[])
   ret += check ();
   ret += check ();
 
-  // FIXME
-#ifndef MINGW
   s = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
-#endif
   if (NULL == s)
     {
       if ((errno == ENOBUFS) ||
diff --git a/src/util/test_service_data.conf b/src/util/test_service_data.conf
index cff43cc..a243745 100644
--- a/src/util/test_service_data.conf
+++ b/src/util/test_service_data.conf
@@ -10,6 +10,7 @@ REJECT_FROM=1.2.3.0/15;4.5.0.0/8;6.7.8.9/255.255.255.0;
 ACCEPT_FROM6=::1;
 REJECT_FROM6=AB:CD:EF::00;AB:CD::00/40;
 HOSTNAME=localhost
+OPTIONS = -l test_service.log -L DEBUG
 
 [test_service6]
 PORT=12435
@@ -22,6 +23,7 @@ REJECT_FROM=1.2.3.0/15;4.5.0.0/8;6.7.8.9/255.255.255.0;
 ACCEPT_FROM6=::1;
 REJECT_FROM6=AB:CD:EF::00;AB:CD::00/40;
 HOSTNAME=::1
+OPTIONS = -l test_service-6.log -L DEBUG
 
 [resolver]
 HOSTNAME=localhost
diff --git a/src/util/test_strings.c b/src/util/test_strings.c
index a1614b4..0f2135a 100644
--- a/src/util/test_strings.c
+++ b/src/util/test_strings.c
@@ -66,7 +66,7 @@ check ()
                                             (GNUNET_TIME_UNIT_MILLISECONDS,
                                              7 * 60 * 60 * 1000));
   WANT (buf, b);
-#ifndef MINGW
+#if !WINDOWS || defined(__CYGWIN__)
   hdir = getenv ("HOME");
 #else
   hdir = getenv ("USERPROFILE");
diff --git a/src/util/test_w32io.c b/src/util/test_w32io.c
new file mode 100644
index 0000000..2523a62
--- /dev/null
+++ b/src/util/test_w32io.c
@@ -0,0 +1,960 @@
+/*
+     This file is part of GNUnet.
+     (C) 2003, 2004, 2005, 2006, 2009 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, 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
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file util/test_w32io.c
+ * @brief testcase for util/w32io.c
+ */
+#include "platform.h"
+#include "gnunet_common.h"
+#include "gnunet_configuration_lib.h"
+#include "gnunet_os_lib.h"
+#include "disk.h"
+#include "w32io.h"
+
+#define VERBOSE GNUNET_NO
+
+
+char self_name[MAX_PATH + 1];
+
+SOCKET
+create_listening_socket (int port)
+{
+  struct sockaddr_in sa;
+  SOCKET s;
+  int r;
+  DWORD e;
+  memset (&sa, 0, sizeof (sa));
+#if HAVE_SOCKADDR_IN_SIN_LEN
+  sa.sin_len = sizeof (sa);
+#endif
+  sa.sin_addr.s_addr = inet_addr("127.0.0.1");
+  sa.sin_port = htons (port);
+  sa.sin_family = AF_INET;
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Creating a socket...\n");
+#endif
+  SetLastError (0);
+  //s = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
+  s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+  e = GetLastError ();
+  GNUNET_assert (s != INVALID_SOCKET);
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Binding the socket...\n");
+#endif
+  SetLastError (0);
+  r = bind (s, (struct sockaddr *) &sa, sizeof (sa));
+  e = GetLastError ();
+  GNUNET_assert (r == 0);
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Listening on the socket...\n");
+#endif
+  SetLastError (0);
+  r = listen (s, 5);
+  e = GetLastError ();
+  GNUNET_assert (r == 0);
+  return s;
+}
+
+SOCKET
+create_connecting_socket ()
+{
+  SOCKET s;
+
+  s = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
+  GNUNET_assert (s != INVALID_SOCKET);
+  return s;
+}
+
+
+static int
+test_socket_server (int do_spawn, int port)
+{
+  int r;
+  struct sockaddr sa;
+  int sizeofsa = sizeof (sa);
+  int server[2];
+  w32fd_set rset;
+  w32fd_set wset;
+  char buf[1024];
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Testing sockets...\n");
+#endif
+
+  SOCKET s = create_listening_socket (port);
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Created a listening socket.\n");
+#endif
+
+  server[0] = GNUNET_W32IO_fd_from_handle ((HANDLE) s, GNUNET_W32IO_SOCKET, GENERIC_READ | GENERIC_WRITE, 0, 0, 0);
+  GNUNET_assert (server[0] >= 0);
+
+  sprintf (buf, "%d", port);
+
+  if (do_spawn)
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Spawning client process.\n");
+#endif
+    struct GNUNET_OS_Process *p;
+    p = GNUNET_OS_start_process (NULL, NULL, self_name, self_name, "socket", buf, NULL);
+    GNUNET_OS_process_close (p);
+  }
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Waiting for the listening socket readability.\n");
+#endif
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(server[0], &rset);
+  r = GNUNET_W32IO_select (server[0] + 1, &rset, NULL, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (W32_FD_ISSET (server[0], &rset));
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Accepting client connection.\n");
+#endif
+
+  server[1] = GNUNET_W32IO_accept (server[0], &sa, &sizeofsa);
+  GNUNET_assert (server[1] >= 0);
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Waiting for server socket writability.\n");
+#endif
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(server[0], &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(server[0], &wset);
+  W32_FD_SET(server[1], &wset);
+  r = GNUNET_W32IO_select (server[1] + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (W32_FD_ISSET(server[1], &wset));
+  GNUNET_assert (!W32_FD_ISSET(server[0], &rset) && !W32_FD_ISSET(server[0], &wset));
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Sending 12345 to client.\n");
+#endif
+  r = GNUNET_W32IO_send (server[1], "12345", 5, 0);
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Waiting for server socket readability.\n");
+#endif
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(server[0], &rset);
+  W32_FD_SET(server[1], &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(server[0], &wset);
+  r = GNUNET_W32IO_select (server[1] + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (W32_FD_ISSET(server[1], &rset));
+  GNUNET_assert (!W32_FD_ISSET(server[0], &rset) && !W32_FD_ISSET(server[0], &wset));
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Reading 54321 from client.\n");
+#endif
+  r = GNUNET_W32IO_recv (server[1], buf, 5, 0);
+
+  GNUNET_assert (buf[0] == '5' && buf[1] == '4' && buf[2] == '3' && buf[3] == '2' && buf[4] == '1');
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Waiting for server socket writability.\n");
+#endif
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(server[0], &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(server[0], &wset);
+  W32_FD_SET(server[1], &wset);
+  r = GNUNET_W32IO_select (server[1] + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (W32_FD_ISSET(server[1], &wset));
+  GNUNET_assert (!W32_FD_ISSET(server[0], &rset) && !W32_FD_ISSET(server[0], &wset));
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Sending 98765 to client.\n");
+#endif
+  r = GNUNET_W32IO_send (server[1], "98765", 5, 0);
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting the server down.\n");
+#endif
+  GNUNET_W32IO_shutdown (server[1], SD_SEND);
+  GNUNET_W32IO_shutdown (server[0], SD_BOTH);
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Waiting for server socket readability.\n");
+#endif
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(server[0], &rset);
+  W32_FD_SET(server[1], &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(server[0], &wset);
+  r = GNUNET_W32IO_select (server[1] + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (W32_FD_ISSET(server[1], &rset));
+  GNUNET_assert (!W32_FD_ISSET(server[1], &wset));
+  GNUNET_assert (!W32_FD_ISSET(server[0], &rset));
+  GNUNET_assert (!W32_FD_ISSET(server[0], &wset));
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Closing the server.\n");
+#endif
+  GNUNET_W32IO_close (server[0], 1);
+  GNUNET_W32IO_close (server[1], 1);
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done!\n");
+#endif
+  return 0;
+}
+
+static int
+test_socket_client (int port)
+{
+  int r;
+  char buf[1024];
+  w32fd_set rset;
+  w32fd_set wset;
+  int client;
+  struct sockaddr_in sa;
+  memset (&sa, 0, sizeof (sa));
+#if HAVE_SOCKADDR_IN_SIN_LEN
+  sa.sin_len = sizeof (sa);
+#endif
+  sa.sin_addr.s_addr = inet_addr("127.0.0.1");
+  sa.sin_port = htons (port);
+  sa.sin_family = AF_INET;
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Creating a client socket.\n");
+#endif
+  SOCKET s = create_connecting_socket ();
+
+  client = GNUNET_W32IO_fd_from_handle ((HANDLE) s, GNUNET_W32IO_SOCKET, GENERIC_READ | GENERIC_WRITE, 0, 0, 0);
+  GNUNET_assert (client >= 0);
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting the client socket.\n");
+#endif
+  GNUNET_W32IO_connect (client, (struct sockaddr *) &sa, sizeof (sa));
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Waiting for client socket readability.\n");
+#endif
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(client, &rset);
+  r = GNUNET_W32IO_select (client + 1, &rset, NULL, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (W32_FD_ISSET(client, &rset));
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Receiving 12345 from the server.\n");
+#endif
+  GNUNET_W32IO_recv (client, buf, 5, 0);
+  GNUNET_assert (buf[0] == '1' && buf[1] == '2' && buf[2] == '3' && buf[3] == '4' && buf[4] == '5');
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Waiting for client socket writability.\n");
+#endif
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(client, &wset);
+  r = GNUNET_W32IO_select (client + 1, NULL, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (W32_FD_ISSET(client, &wset));
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Sending 54321 to the server.\n");
+#endif
+  GNUNET_W32IO_send (client, "54321", 5, 0);
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Waiting for client socket readability.\n");
+#endif
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(client, &rset);
+  r = GNUNET_W32IO_select (client + 1, &rset, NULL, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (W32_FD_ISSET(client, &rset));
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Reading 98765 from the server.\n");
+#endif
+  GNUNET_W32IO_recv (client, buf, 5, 0);
+  GNUNET_assert (buf[0] == '9' && buf[1] == '8' && buf[2] == '7' && buf[3] == '6' && buf[4] == '5');
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting the client down.\n");
+#endif
+  GNUNET_W32IO_shutdown (client, SD_SEND);
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Waiting for client socket readability.\n");
+#endif
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(client, &rset);
+  r = GNUNET_W32IO_select (client + 1, &rset, NULL, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (W32_FD_ISSET(client, &rset));
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Closing the client.\n");
+#endif
+  GNUNET_W32IO_close (client, 1);
+  return 0;
+}
+
+int thread_ret[2];
+
+DWORD
+test_socket_threaded_server (void *arg)
+{
+  thread_ret[0] = test_socket_server (0, (int) arg);
+  return 0;
+}
+
+DWORD
+test_socket_threaded_client (void *arg)
+{
+  thread_ret[1] = test_socket_client ((int) arg);
+  return 0;
+}
+
+static int
+test_socket_threaded (int port)
+{
+  DWORD thread_ids[2];
+  DWORD dw_ret;
+  HANDLE threads[2];
+  thread_ret[0] = thread_ret[1] = -1;
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Testing sockets (threaded)...\n");
+#endif
+  threads[0] = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) &test_socket_threaded_server, (void *) port, 0, &thread_ids[0]);
+  /* Give the server enough time to set up a listening socket.
+   * I'm too lazy to do proper synchronization with events here.
+   */
+  Sleep (100);
+  threads[1] = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) &test_socket_threaded_client, (void *) port, 0, &thread_ids[1]);
+  dw_ret = WaitForMultipleObjects (2, threads, TRUE, INFINITE);
+#if VERBOSE
+  if (thread_ret[0] == 0 && thread_ret[1] == 0)
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done!\n");
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Error!\n");
+#endif
+  return (thread_ret[0] == 0 && thread_ret[1] == 0) ? 0 : 1;
+}
+
+static int
+test_named_pipe_server_read (int do_spawn)
+{
+  int r;
+  w32fd_set rset;
+  w32fd_set wset;
+  int server;
+  char buf[1024];
+  char *servername = NULL;
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Testing named pipes (client->server)...\n");
+#endif
+  server = GNUNET_W32IO_named_pipe_server (&servername, PIPE_ACCESS_INBOUND);
+  GNUNET_assert (server >= 0);
+
+  if (do_spawn)
+  {
+    struct GNUNET_OS_Process *p;
+    p = GNUNET_OS_start_process (NULL, NULL, self_name, self_name, "named_pipe", "write", servername, NULL);
+    GNUNET_OS_process_close (p);
+  }
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(server, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(server, &wset);
+  r = GNUNET_W32IO_select (server + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (W32_FD_ISSET(server, &rset) && !W32_FD_ISSET(server, &wset));
+
+  r = GNUNET_W32IO_read (server, buf, 5);
+
+  GNUNET_assert (buf[0] == '5' && buf[1] == '4' && buf[2] == '3' && buf[3] == '2' && buf[4] == '1');
+
+  GNUNET_W32IO_close (server, 1);
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done!\n");
+#endif
+  return 0;
+}
+
+static int
+test_named_pipe_client_write (char *name)
+{
+  int r;
+  char buf[1024];
+  w32fd_set rset;
+  w32fd_set wset;
+  int client;
+
+  client = GNUNET_W32IO_named_pipe_client (name, PIPE_ACCESS_OUTBOUND);
+  GNUNET_assert (client >= 0);
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(client, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(client, &wset);
+  r = GNUNET_W32IO_select (client + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (!W32_FD_ISSET(client, &rset) && W32_FD_ISSET(client, &wset));
+
+  buf[0] = '5';
+  buf[1] = '4';
+  buf[2] = '3';
+  buf[3] = '2';
+  buf[4] = '1';
+
+  r = GNUNET_W32IO_write (client, buf, 5);
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(client, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(client, &wset);
+  r = GNUNET_W32IO_select (client + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (!W32_FD_ISSET(client, &rset) && W32_FD_ISSET(client, &wset));
+
+  GNUNET_W32IO_close (client, 1);
+  return 0;
+}
+
+static int
+test_named_pipe_server_hup (int do_spawn)
+{
+  int r;
+  w32fd_set rset;
+  w32fd_set wset;
+  int server;
+  char buf[1024];
+  char *servername = NULL;
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Testing named pipes (broken pipe)...\n");
+#endif
+  server = GNUNET_W32IO_named_pipe_server (&servername, PIPE_ACCESS_INBOUND);
+  GNUNET_assert (server >= 0);
+
+  if (do_spawn)
+  {
+    struct GNUNET_OS_Process *p;
+    p = GNUNET_OS_start_process (NULL, NULL, self_name, self_name, "named_pipe", "hup", servername, NULL);
+    GNUNET_OS_process_close (p);
+  }
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(server, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(server, &wset);
+  r = GNUNET_W32IO_select (server + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (W32_FD_ISSET(server, &rset) && !W32_FD_ISSET(server, &wset));
+
+  r = GNUNET_W32IO_read (server, buf, 5);
+
+  GNUNET_assert (buf[0] == '5' && buf[1] == '4' && buf[2] == '3' && buf[3] == '2' && buf[4] == '1');
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(server, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(server, &wset);
+  r = GNUNET_W32IO_select (server + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (W32_FD_ISSET(server, &rset) && !W32_FD_ISSET(server, &wset));
+
+  GNUNET_W32IO_close (server, 1);
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done!\n");
+#endif
+  return 0;
+}
+
+static int
+test_named_pipe_client_hup (char *name)
+{
+  int r;
+  char buf[1024];
+  w32fd_set rset;
+  w32fd_set wset;
+  int client;
+
+  client = GNUNET_W32IO_named_pipe_client (name, PIPE_ACCESS_OUTBOUND);
+  GNUNET_assert (client >= 0);
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(client, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(client, &wset);
+  r = GNUNET_W32IO_select (client + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (!W32_FD_ISSET(client, &rset) && W32_FD_ISSET(client, &wset));
+
+  buf[0] = '5';
+  buf[1] = '4';
+  buf[2] = '3';
+  buf[3] = '2';
+  buf[4] = '1';
+
+  r = GNUNET_W32IO_write (client, buf, 5);
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(client, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(client, &wset);
+  r = GNUNET_W32IO_select (client + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (!W32_FD_ISSET(client, &rset) && W32_FD_ISSET(client, &wset));
+
+  GNUNET_W32IO_close (client, 1);
+  return 0;
+}
+
+static int
+test_named_pipe_server_write (int do_spawn)
+{
+  int r;
+  w32fd_set rset;
+  w32fd_set wset;
+  int server;
+  char buf[1024];
+  char *servername = NULL;
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Testing named pipes (server->client)...\n");
+#endif
+  server = GNUNET_W32IO_named_pipe_server (&servername, PIPE_ACCESS_OUTBOUND);
+  GNUNET_assert (server >= 0);
+
+  if (do_spawn)
+  {
+    struct GNUNET_OS_Process *p;
+    p = GNUNET_OS_start_process (NULL, NULL, self_name, self_name, "named_pipe", "read", servername, NULL);
+    GNUNET_OS_process_close (p);
+  }
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(server, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(server, &wset);
+  r = GNUNET_W32IO_select (server + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (!W32_FD_ISSET(server, &rset) && W32_FD_ISSET(server, &wset));
+
+  buf[0] = '5';
+  buf[1] = '4';
+  buf[2] = '3';
+  buf[3] = '2';
+  buf[4] = '1';
+
+  r = GNUNET_W32IO_write (server, buf, 5);
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(server, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(server, &wset);
+  r = GNUNET_W32IO_select (server + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (!W32_FD_ISSET(server, &rset) && W32_FD_ISSET(server, &wset));
+
+  GNUNET_W32IO_close (server, 1);
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done!\n");
+#endif
+  return 0;
+}
+
+static int
+test_named_pipe_client_read (char *name)
+{
+  int r;
+  char buf[1024];
+  w32fd_set rset;
+  w32fd_set wset;
+  int client;
+
+  client = GNUNET_W32IO_named_pipe_client (name, PIPE_ACCESS_INBOUND);
+  GNUNET_assert (client >= 0);
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(client, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(client, &wset);
+  r = GNUNET_W32IO_select (client + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (W32_FD_ISSET(client, &rset) && !W32_FD_ISSET(client, &wset));
+
+  r = GNUNET_W32IO_read (client, buf, 5);
+
+  GNUNET_assert (buf[0] == '5' && buf[1] == '4' && buf[2] == '3' && buf[3] == '2' && buf[4] == '1');
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(client, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(client, &wset);
+  r = GNUNET_W32IO_select (client + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (W32_FD_ISSET(client, &rset) && !W32_FD_ISSET(client, &wset));
+
+  GNUNET_W32IO_close (client, 1);
+  return 0;
+}
+
+static int
+test_anonymous_pipe_server_write ()
+{
+  int r;
+  w32fd_set rset;
+  w32fd_set wset;
+  struct GNUNET_DISK_PipeHandle *stdin_pipe, *test_pipe;
+  int server;
+  SOCKET s;
+  char buf[1024];
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Testing anonymous pipes (stdin)...\n");
+#endif
+  stdin_pipe = GNUNET_DISK_pipe (0, 1, 0);
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Created anonymous pipe (writable, not readable).\n");
+#endif
+  GNUNET_assert (stdin_pipe != NULL);
+  GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle(stdin_pipe, GNUNET_DISK_PIPE_END_WRITE), &server, sizeof (int));
+
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Spawning the child process...\n");
+#endif
+    struct GNUNET_OS_Process *p;
+    p = GNUNET_OS_start_process (stdin_pipe, NULL, self_name, self_name, "anonymous_pipe", "read", NULL);
+    GNUNET_OS_process_close (p);
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Spawned the child process.\n");
+#endif
+  }
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(server, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(server, &wset);
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Waiting for the server pipe writability...\n");
+#endif
+  r = GNUNET_W32IO_select (server + 1, &rset, &wset, NULL, NULL);
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done waiting for the server pipe writability...\n");
+#endif
+  GNUNET_assert (r == 1);
+  GNUNET_assert (!W32_FD_ISSET(server, &rset) && W32_FD_ISSET(server, &wset));
+
+  buf[0] = '5';
+  buf[1] = '4';
+  buf[2] = '3';
+  buf[3] = '2';
+  buf[4] = '1';
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Writing 54321 server->client \n");
+#endif
+  r = GNUNET_W32IO_write (server, buf, 5);
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done writing 54321 server->client \n");
+#endif
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(server, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(server, &wset);
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Waiting for the server pipe writability...\n");
+#endif
+  r = GNUNET_W32IO_select (server + 1, &rset, &wset, NULL, NULL);
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done waiting for the server pipe writability...\n");
+#endif
+  GNUNET_assert (r == 1);
+  GNUNET_assert (!W32_FD_ISSET(server, &rset) && W32_FD_ISSET(server, &wset));
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Closing the server pipe\n");
+#endif
+  GNUNET_DISK_pipe_close (stdin_pipe);
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done!\n");
+#endif
+  return 0;
+}
+
+static int
+test_anonymous_pipe_client_read (HANDLE in)
+{
+  int r;
+  char buf[1024];
+  w32fd_set rset;
+  w32fd_set wset;
+  int client;
+
+  client = GNUNET_W32IO_fd_from_handle (in, GNUNET_W32IO_ANONYMOUS_PIPE, GENERIC_READ, 1, 0, 1);
+  GNUNET_assert (client >= 0);
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(client, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(client, &wset);
+  r = GNUNET_W32IO_select (client + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (W32_FD_ISSET(client, &rset) && !W32_FD_ISSET(client, &wset));
+
+  r = GNUNET_W32IO_read (client, buf, 5);
+
+  GNUNET_assert (buf[0] == '5' && buf[1] == '4' && buf[2] == '3' && buf[3] == '2' && buf[4] == '1');
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(client, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(client, &wset);
+  r = GNUNET_W32IO_select (client + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (W32_FD_ISSET(client, &rset) && !W32_FD_ISSET(client, &wset));
+
+  GNUNET_W32IO_close (client, 1);
+  return 0;
+}
+
+static int
+test_anonymous_pipe_client_write (HANDLE out)
+{
+  int r;
+  char buf[1024];
+  w32fd_set rset;
+  w32fd_set wset;
+  int client;
+
+  client = GNUNET_W32IO_fd_from_handle (out, GNUNET_W32IO_ANONYMOUS_PIPE, GENERIC_WRITE, 1, 1, 0);
+  GNUNET_assert (client >= 0);
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(client, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(client, &wset);
+  r = GNUNET_W32IO_select (client + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (!W32_FD_ISSET(client, &rset) && W32_FD_ISSET(client, &wset));
+
+  buf[0] = '5';
+  buf[1] = '4';
+  buf[2] = '3';
+  buf[3] = '2';
+  buf[4] = '1';
+
+  r = GNUNET_W32IO_write (client, buf, 5);
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(client, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(client, &wset);
+  r = GNUNET_W32IO_select (client + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (!W32_FD_ISSET(client, &rset) && W32_FD_ISSET(client, &wset));
+
+  GNUNET_W32IO_close (client, 1);
+  return 0;
+}
+
+static int
+test_anonymous_pipe_server_read ()
+{
+  int r;
+  w32fd_set rset;
+  w32fd_set wset;
+  struct GNUNET_DISK_PipeHandle *stdout_pipe;
+  int server;
+  char buf[1024];
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Testing anonymous pipes (stdout)...\n");
+#endif
+  stdout_pipe = GNUNET_DISK_pipe (0, 0, 1);
+  GNUNET_assert (stdout_pipe != NULL);
+  GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle(stdout_pipe, GNUNET_DISK_PIPE_END_READ), &server, sizeof (int));
+
+  {
+    struct GNUNET_OS_Process *p;
+    p = GNUNET_OS_start_process (NULL, stdout_pipe, self_name, self_name, "anonymous_pipe", "write", NULL);
+    GNUNET_OS_process_close (p);
+  }
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(server, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(server, &wset);
+  r = GNUNET_W32IO_select (server + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (W32_FD_ISSET(server, &rset) && !W32_FD_ISSET(server, &wset));
+
+  r = GNUNET_W32IO_read (server, buf, 5);
+  GNUNET_assert (buf[0] == '5' && buf[1] == '4' && buf[2] == '3' && buf[3] == '2' && buf[4] == '1');
+
+  W32_FD_ZERO(&rset);
+  W32_FD_SET(server, &rset);
+  W32_FD_ZERO(&wset);
+  W32_FD_SET(server, &wset);
+  r = GNUNET_W32IO_select (server + 1, &rset, &wset, NULL, NULL);
+  GNUNET_assert (r == 1);
+  GNUNET_assert (W32_FD_ISSET(server, &rset) && !W32_FD_ISSET(server, &wset));
+
+  GNUNET_DISK_pipe_close (stdout_pipe);
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done!\n");
+#endif
+  return 0;
+}
+static int
+test_named_pipe_threaded ()
+{
+  return 0;
+}
+static int
+test_anonymous_pipe_threaded ()
+{
+  return 0;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  int errCnt = 0;
+  int port = 53210;
+
+  char *self_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_SELF_PREFIX);
+  sprintf (self_name, "%s%s", self_dir, "test_w32io.exe");
+  GNUNET_free (self_dir);
+
+  if (argc < 2)
+  {
+  GNUNET_log_setup ("test-w32io",
+#if VERBOSE
+     "DEBUG",
+#else
+     "WARNING",
+#endif
+      NULL);
+
+    if (0 != test_anonymous_pipe_server_read ())
+      errCnt++;
+    if (0 != test_anonymous_pipe_server_write ())
+      errCnt++;
+    if (0 != test_socket_server (1, port++))
+      errCnt++;
+    if (0 != test_named_pipe_server_read (1))
+      errCnt++;
+    if (0 != test_named_pipe_server_write (1))
+      errCnt++;
+    if (0 != test_named_pipe_server_hup (1))
+      errCnt++;
+    if (0 != test_socket_threaded (port++))
+      errCnt++;
+    if (0 != test_named_pipe_threaded ())
+      errCnt++;
+    if (0 != test_anonymous_pipe_threaded ())
+      errCnt++;
+  }
+  else
+  {
+  GNUNET_log_setup ("test-w32io",
+#if VERBOSE
+     "DEBUG",
+#else
+     "WARNING",
+#endif
+      NULL);
+
+    if (strcmp (argv[1], "socket") == 0)
+    {
+      if (argc < 3)
+        errCnt++;
+      else
+      {
+        port = strtol (argv[2], NULL, 10);
+        if (0 != test_socket_client (port))
+          errCnt++;
+      }
+    }
+    else if (strcmp (argv[1], "named_pipe") == 0)
+    {
+      if (argc < 4)
+        errCnt++;
+      else
+      {
+        if (strcmp (argv[2], "read") == 0)
+        {
+          if (0 != test_named_pipe_client_read (argv[3]))
+            errCnt++;
+        }
+        if (strcmp (argv[2], "write") == 0)
+        {
+          if (0 != test_named_pipe_client_write (argv[3]))
+            errCnt++;
+        }
+        if (strcmp (argv[2], "hup") == 0)
+        {
+          if (0 != test_named_pipe_client_hup (argv[3]))
+            errCnt++;
+        }
+      }
+    }
+    else if (strcmp (argv[1], "anonymous_pipe") == 0)
+    {
+      if (argc < 3)
+      {
+        errCnt++;
+      }
+      else
+      {
+        if (strcmp (argv[2], "read") == 0)
+        {
+          if (0 != test_anonymous_pipe_client_read (GetStdHandle (STD_INPUT_HANDLE)))
+            errCnt++;
+        }
+        if (strcmp (argv[2], "write") == 0)
+        {
+          if (0 != test_anonymous_pipe_client_write (GetStdHandle (STD_OUTPUT_HANDLE)))
+            errCnt++;
+        }
+      }
+    }
+  }
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All done, %d test failed\n", errCnt);
+#endif
+  return errCnt;
+}
diff --git a/src/util/w32io.c b/src/util/w32io.c
new file mode 100644
index 0000000..7c5aba7
--- /dev/null
+++ b/src/util/w32io.c
@@ -0,0 +1,3698 @@
+/*
+     This file is part of GNUnet.
+     (C) 2001, 2002, 2005, 2006, 2009, 2010 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, 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
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file util/w32io.c
+ * @brief POSIX-compatible I/O under NT
+ * @author LRN
+ */
+
+#include "platform.h"
+#include "gnunet_common.h"
+#include "w32io.h"
+
+#if WINDOWS
+
+#define W32IO_DISABLE_LOCKING 0
+#define DEBUG_W32IO GNUNET_NO
+#define DEBUG_W32IO_THREADS GNUNET_NO
+
+struct W32Fd **fds = NULL;
+size_t fds_len = 0;
+HANDLE fds_mutex = NULL;
+
+/**
+ * Call it at least once.
+ */
+int w32io_init ()
+{
+#if W32IO_DISABLE_LOCKING
+  return 0;
+#else
+  if (fds_mutex == NULL)
+  {
+    fds_mutex = CreateMutex (NULL, FALSE, NULL);
+    return 0;
+  }
+  return -1;
+#endif
+}
+
+int w32io_deinit ()
+{
+#if W32IO_DISABLE_LOCKING
+  return 0;
+#else
+  if (fds_mutex != NULL)
+  {
+    CloseHandle (fds_mutex);
+    return 0;
+  }
+  return -1;
+#endif
+}
+
+/**
+ * Fetches a real W32Fd from the array of FDs using @fake_fd as an index.
+ * Might lock waiting for the mutex.
+ *
+ * @param fake_fd fake FD, as returned and taken by W32IO functions.
+ * @return "real" W32Fd, used internally by W32IO
+ */
+struct W32Fd *
+w32io_fetch_fd (int fake_fd)
+{
+  DWORD error_code;
+  DWORD dw_result;
+  /* To keep the amount of locktime minimum all logging operations are moved
+   * outside of the locked area (well, logs[0] is moved, everything else is
+   * outside as it is, but i kept them together for consistency).
+   */
+  int logs[3] = {0, 0, 0};
+  size_t len = 0;
+  struct W32Fd *result = NULL;
+#if !W32IO_DISABLE_LOCKING
+  SetLastError (0);
+  dw_result = WaitForSingleObject (fds_mutex, INFINITE);
+  error_code = GetLastError ();
+  if (dw_result == WAIT_OBJECT_0)
+  {
+#endif
+    if (fds_len <= fake_fd)
+    {
+      logs[0] = 1;
+      len = fds_len;
+      errno = EINVAL;
+    }
+    else
+    {
+      result = fds[fake_fd];
+    }
+#if !W32IO_DISABLE_LOCKING
+    ReleaseMutex (fds_mutex);
+#endif
+    if (result == NULL)
+    {
+      logs[1] = 1;
+      errno = EINVAL;
+    }
+#if !W32IO_DISABLE_LOCKING
+  }
+  else
+  {
+    logs[2] = 1;
+    SetErrnoFromWinError (error_code);
+  }
+#endif
+  if (logs[0])
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to fetch real fd for fake fd %d - array length is only %d\n", fake_fd, len);
+  if (logs[1])
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to fetch real fd for fake fd %d - real fd is NULL\n", fake_fd);
+  if (logs[2])
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to fetch real fd for fake fd %d - can't lock mutex %08X\n", fake_fd, fds_mutex);
+  return result;
+}
+
+/**
+ * Inserts a real W32Fd into the array of FDs and returns a @fake_fd.
+ * Might lock waiting for the mutex.
+ *
+ * @param real_fd "real" W32Fd, used internally by W32IO.
+ * @return "fake" FD
+ */
+int
+w32io_insert_fd (struct W32Fd *real_fd)
+{
+  DWORD error_code;
+  DWORD dw_result;
+  int i;
+  /* To keep the amount of locktime minimum all logging operations are moved
+   * outside of the locked area (well, logs[0] is moved, everything else is
+   * outside as it is, but i kept them together for consistency).
+   */
+  int result = -1;
+#if !W32IO_DISABLE_LOCKING
+  SetLastError (0);
+  dw_result = WaitForSingleObject (fds_mutex, INFINITE);
+  error_code = GetLastError ();
+  if (dw_result == WAIT_OBJECT_0)
+  {
+#endif
+    for (i = 0; i < fds_len; i++)
+    {
+      if (fds[i] == NULL)
+      {
+        fds[i] = real_fd;
+        result = i;
+        break;
+      }
+    }
+    if (result == -1)
+    {
+      result = fds_len;
+      GNUNET_array_grow(fds, fds_len, fds_len > 0 ? fds_len * 2 : 5);
+      fds_len = fds_len * 2;
+      fds[result] = real_fd;
+    }
+#if !W32IO_DISABLE_LOCKING
+    ReleaseMutex (fds_mutex);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to insert real fd %08X - can't lock mutex %08X\n", real_fd, fds_mutex);
+    SetErrnoFromWinError (error_code);
+  }
+#endif
+  return result;
+}
+
+/**
+ * Removes a real W32Fd from the array of FDs by its "fake" index.
+ * Might lock waiting for the mutex.
+ *
+ * @param fake_fd "fake" FD
+ */
+void
+w32io_remove_fd (int fake_fd)
+{
+  DWORD error_code;
+  DWORD dw_result;
+  int logs[3] = {0, 0, 0};
+  size_t len = 0;
+  struct W32Fd *result = NULL;
+#if !W32IO_DISABLE_LOCKING
+  SetLastError (0);
+  dw_result = WaitForSingleObject (fds_mutex, INFINITE);
+  error_code = GetLastError ();
+  if (dw_result == WAIT_OBJECT_0)
+  {
+#endif
+    if (fds_len <= fake_fd)
+    {
+      logs[0] = 1;
+      len = fds_len;
+      errno = EINVAL;
+    }
+    else
+    {
+      result = fds[fake_fd];
+      fds[fake_fd] = NULL;
+    }
+#if !W32IO_DISABLE_LOCKING
+    ReleaseMutex (fds_mutex);
+#endif
+    if (result == NULL)
+    {
+      logs[1] = 1;
+      errno = EINVAL;
+    }
+#if !W32IO_DISABLE_LOCKING
+  }
+  else
+  {
+    logs[2] = 1;
+    SetErrnoFromWinError (error_code);
+  }
+#endif
+  if (logs[0])
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to fetch real fd for fake fd %d - array length is only %d\n", fake_fd, len);
+  if (logs[1])
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to fetch real fd for fake fd %d - real fd is NULL\n", fake_fd);
+  if (logs[2])
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to fetch real fd for fake fd %d - can't lock mutex %08X\n", fake_fd, fds_mutex);
+}
+
+DWORD __stdcall w32io_anonymous_pipe_thread_func (void *data);
+
+#define GNUNET_W32IO_PIPE_NAME_PREFIX "\\\\.\\pipe\\"
+
+#define SOCKET_POLL_EVENT POLLIN_BIT
+#define SOCKET_WAKEUP_EVENT POLLOUT_BIT
+#define SOCKET_OVERLAPPED_WRITE_EVENT POLLWRBAND_BIT
+#define ANON_PIPE_THREAD_POLL_EVENT POLLIN_BIT
+#define ANON_PIPE_CONFIRM_POLL_EVENT POLLWRBAND_BIT
+#define ANON_PIPE_MAIN_THREAD_POLL_EVENT POLLOUT_BIT
+#define ANON_PIPE_CLOSE_POLL_EVENT POLLHUP_BIT
+#define FILE_READY_POLL_EVENT POLLIN_BIT
+
+#define ZeroOverlappedExceptEvent(o) o.Internal = o.InternalHigh = o.Offset = o.OffsetHigh = 0
+
+HANDLE
+w32io_fd_get_handle (struct W32Fd *fd)
+{
+  return fd->fd;
+}
+
+HANDLE
+GNUNET_W32IO_fd_get_handle (int fd)
+{
+  struct W32Fd *wfd = w32io_fetch_fd (fd);
+  if (wfd == NULL || wfd == INVALID_POLL_FD)
+    return INVALID_HANDLE_VALUE;
+  return w32io_fd_get_handle (wfd);
+}
+
+void
+GNUNET_W32IO_generate_random_local_pipe_name (char pipename[255])
+{
+  int i;
+  static DWORD seed = 0;
+  static float scale = 32767 / 25;
+  static int prefixlen = 9;
+  if (seed == 0)
+  {
+    seed = GetCurrentProcessId ();
+    srand (seed);
+  }
+  /* Uniqueness is not guaranteed - but we can always regenerate the name until
+   * it comes out to be unique.
+   */
+  memcpy (pipename, GNUNET_W32IO_PIPE_NAME_PREFIX, prefixlen);
+  for (i = prefixlen; i < 254; i++)
+  {
+    /* Get a random 0-32767 integer, then scale it to 65-90. This is not
+     * really a requirement - MSDN says that the only forbidden character
+     * for pipe names is the backslash. But i won't be taking any chances.
+     */
+    /* TODO: use RtlRandom() or RtlRandomEx() instead of rand() */
+    pipename[i] = 65 + (char) (rand() / scale);
+  }
+  pipename[254] = 0;
+}
+
+int
+w32io_pipe (struct W32Fd *fd[2], int server_inheritable, int client_inheritable, DWORD server_mode, DWORD client_mode)
+{
+  char pipename[255];
+  SECURITY_ATTRIBUTES sa;
+  DWORD err;
+  BOOL bret;
+  OVERLAPPED ov;
+  HANDLE p[2];
+  p[0] = p[1] = NULL;
+  memset (&ov, 0, sizeof (ov));
+  while (!p[0])
+  {
+    sa.nLength = sizeof (sa);
+    sa.lpSecurityDescriptor = NULL;
+    sa.bInheritHandle = server_inheritable;
+    GNUNET_W32IO_generate_random_local_pipe_name (pipename);
+    /* FILE_FLAG_FIRST_PIPE_INSTANCE makes sure that we're first to create a
+     * pipe with such name.
+     * FILE_FLAG_OVERLAPPED creates async pipe. If the user wants to perform
+     * blocking I/O, we can easily create a blocking wrapper.
+     */
+    p[0] = CreateNamedPipeA ((LPCSTR) pipename, server_mode |
+        FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED |
+        PIPE_ACCESS_INBOUND, /*inbound access is necessary to read pipe info*/
+        PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
+        PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, &sa);
+    if (p[0] == INVALID_HANDLE_VALUE)
+    {
+      err = GetLastError ();
+      switch (err)
+      {
+        case ERROR_ACCESS_DENIED:
+          p[0] = NULL;
+          continue;
+      }
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create a named pipe. GLE: %d\n", err);
+      return FALSE;
+    }
+  }
+  bret = ConnectNamedPipe (p[0], &ov);
+  if (bret == 0)
+  {
+    err = GetLastError ();
+    if (err == ERROR_IO_PENDING)
+    {
+      //It's ok, it works in the background while we finish other things
+    }
+    else if (err != ERROR_PIPE_CONNECTED)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect a named pipe. GLE: %d\n", err);
+      CloseHandle (p[0]);
+      return FALSE;
+    }
+  }
+  sa.nLength = sizeof (sa);
+  sa.lpSecurityDescriptor = NULL;
+  sa.bInheritHandle = client_inheritable;
+  p[1] = CreateFileA ((LPCSTR) pipename, client_mode, 0, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_READ_ATTRIBUTES, NULL);
+  if (p[1] == INVALID_HANDLE_VALUE)
+  {
+    err = GetLastError ();
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to open client side of a named pipe. GLE: %d\n", err);
+    CloseHandle(p[0]);
+    return FALSE;
+  }
+  //We've made both I/O calls, wait until the pipe is connected an opened
+  bret = GetOverlappedResult (p[0], &ov, &err, TRUE);
+
+  /* Both are not readable because we know that there is no data to read (yet).
+   * Write end is writable, because no writing is being done.
+   * Read end is, however, not writable, because it is read-only.
+   */
+  fd[0] = w32io_fd_from_handle (p[0], GNUNET_W32IO_NAMED_PIPE, (server_mode & PIPE_ACCESS_OUTBOUND ? GENERIC_WRITE : 0) | (server_mode & PIPE_ACCESS_INBOUND ? GENERIC_READ : 0), TRUE, server_mode & PIPE_ACCESS_OUTBOUND, server_mode & PIPE_ACCESS_INBOUND);
+  fd[1] = w32io_fd_from_handle (p[1], GNUNET_W32IO_NAMED_PIPE, (client_mode & PIPE_ACCESS_OUTBOUND ? GENERIC_WRITE : 0) | (client_mode & PIPE_ACCESS_INBOUND ? GENERIC_READ : 0), TRUE, client_mode & PIPE_ACCESS_OUTBOUND, client_mode & PIPE_ACCESS_INBOUND);
+
+  return TRUE;
+}
+
+int
+GNUNET_W32IO_pipe (int fd[2], int server_inheritable, int client_inheritable, DWORD server_mode, DWORD client_mode)
+{
+  struct W32Fd *wfd[2];
+  int ret;
+  ret = w32io_pipe (wfd, server_inheritable, client_inheritable, server_mode, client_mode);
+  if (ret)
+  {
+    fd[0] = w32io_insert_fd (wfd[0]);
+    fd[1] = w32io_insert_fd (wfd[1]);
+  }
+  return ret;
+}
+
+int
+w32io_anonymous_pipe (struct W32Fd *fd[2], int read_inheritable, int write_inheritable)
+{
+  int ret = TRUE;
+  BOOL bret;
+  DWORD err;
+  HANDLE p[2] = { 0, 0 };
+  SECURITY_ATTRIBUTES sa;
+  /* Mark handle as inheritable if at least one end must be inheritable */
+  int create_inheritance = read_inheritable || write_inheritable;
+
+  sa.nLength = sizeof (sa);
+  sa.lpSecurityDescriptor = NULL;
+  sa.bInheritHandle = create_inheritance;
+
+  bret = CreatePipe (&p[0], &p[1], &sa, 4096);
+  if (bret == 0)
+  {
+    err = GetLastError ();
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create an anonymous pipe. GLE: %d\n", err);
+    ret = FALSE;
+  }
+  if (create_inheritance && !read_inheritable)
+  {
+    /* Desired read inheritance does not match create_inheritance */
+    HANDLE t = p[0];
+    bret = DuplicateHandle (GetCurrentProcess (), t, GetCurrentProcess (), &p[0],
+        0, read_inheritable, DUPLICATE_SAME_ACCESS);
+    if (bret == 0)
+    {
+      err = GetLastError ();
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to duplicate read end of an anonymous pipe. GLE: %d\n", err);
+      ret = FALSE;
+      p[0] = t;
+    }
+    else
+      CloseHandle (t);
+  }
+  if (create_inheritance && !write_inheritable)
+  {
+    /* Desired write inheritance does not match create_inheritance */
+    HANDLE t = p[1];
+    bret = DuplicateHandle (GetCurrentProcess (), t, GetCurrentProcess (), &p[1],
+        0, write_inheritable, DUPLICATE_SAME_ACCESS);
+    if (bret == 0)
+    {
+      err = GetLastError ();
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to duplicate write end of an anonymous pipe. GLE: %d\n", err);
+      ret = FALSE;
+      p[1] = t;
+    }
+    else
+      CloseHandle (t);
+  }
+
+  if (ret == FALSE)
+  {
+    if (p[0])
+      CloseHandle (p[0]);
+    if (p[1])
+      CloseHandle (p[1]);
+    return ret;
+  }
+
+#if DEBUG_W32IO_THREADS
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Registering the read handle...\n");
+#endif
+  fd[0] = w32io_fd_from_handle (p[0], GNUNET_W32IO_ANONYMOUS_PIPE, read_inheritable ? 0 : GENERIC_READ, TRUE, FALSE, TRUE);
+#if DEBUG_W32IO_THREADS
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Registering the write handle...\n");
+#endif
+  fd[1] = w32io_fd_from_handle (p[1], GNUNET_W32IO_ANONYMOUS_PIPE, write_inheritable ? 0 : GENERIC_WRITE, TRUE, TRUE, FALSE);
+#if DEBUG_W32IO_THREADS
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done creating an anonymous pipe...\n");
+#endif
+
+  return ret;
+}
+
+int
+GNUNET_W32IO_anonymous_pipe (int fd[2], int read_inheritable, int write_inheritable)
+{
+  struct W32Fd *wfd[2];
+  int ret;
+  ret = w32io_anonymous_pipe (wfd, read_inheritable, write_inheritable);
+  if (ret)
+  {
+    fd[0] = w32io_insert_fd (wfd[0]);
+    fd[1] = w32io_insert_fd (wfd[1]);
+  }
+  return ret;
+}
+
+int
+w32io_fsync (struct W32Fd *wfd)
+{
+  int ret;
+  if (wfd == NULL || wfd->fd == (void *) -1)
+  {
+    errno = EBADF;
+    return -1;
+  }
+
+  switch (wfd->fd_type)
+  {
+  case GNUNET_W32IO_FILE:
+  case GNUNET_W32IO_NAMED_PIPE:
+  case GNUNET_W32IO_ANONYMOUS_PIPE:
+    ret = TRUE == FlushFileBuffers (wfd->fd);
+    break;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Can't fsync() - fd is not a file or pipe\n");
+    ret = 0;
+  }
+  return ret;
+}
+
+int
+GNUNET_W32IO_fsync (int fd)
+{
+  return w32io_fsync (w32io_fetch_fd (fd));
+}
+
+int
+w32io_shutdown (struct W32Fd *wfd, int how)
+{
+  int ret;
+  switch (wfd->fd_type)
+  {
+  case GNUNET_W32IO_SOCKET:
+    ret = shutdown ((SOCKET) wfd->fd, how);
+    if (ret == SOCKET_ERROR)
+    {
+      DWORD error_code = GetLastError ();
+      SetErrnoFromWinError (error_code);
+    }
+    if (how == SD_SEND || how == SD_BOTH)
+      wfd->wsaevents.lNetworkEvents &= ~FD_WRITE;
+    if (how == SD_RECEIVE || how == SD_BOTH)
+      wfd->wsaevents.lNetworkEvents &= ~FD_READ;
+    return ret;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Can't shutdown() - fd is not a socket\n");
+    return 0;
+  }
+}
+
+int
+GNUNET_W32IO_shutdown (int fd, int how)
+{
+  return w32io_shutdown (w32io_fetch_fd (fd), how);
+}
+
+int
+w32io_close (struct W32Fd *wfd, int closehandle)
+{
+  int i;
+  DWORD dwresult;
+
+  int ret = 0;
+  if (wfd == NULL || wfd->fd == (void *) -1)
+    return ret;
+  switch (wfd->fd_type)
+  {
+  case GNUNET_W32IO_SOCKET:
+    /* Break the link between the socket and its event */
+    WSAEventSelect ((SOCKET) wfd->fd, NULL, 0);
+    ret = ret || !CloseHandle (wfd->overlapped[SOCKET_POLL_EVENT].hEvent);
+    ret = ret || !CloseHandle (wfd->overlapped[SOCKET_WAKEUP_EVENT].hEvent);
+
+    dwresult = WaitForSingleObject (wfd->overlapped[SOCKET_OVERLAPPED_WRITE_EVENT].hEvent, 0);
+    if (dwresult == WAIT_TIMEOUT)
+    {
+      /* Disabled state of the event means that there is still an
+       * operation going on (event has to be reset manually and should
+       * stay signalled after I/O is complete until it is started again).
+       * Except for FD_CONNECT (it is unset after pipe is connected)
+       */
+      /* We're going to free the event. Have to cancel all I/O issued by
+       * this thread using this fd.
+       */
+      if (CancelIo (wfd->fd))
+      {
+        DWORD r;
+        /* Wait until I/O is cancelled */
+        WSAGetOverlappedResult ((SOCKET) wfd->fd, &wfd->overlapped[SOCKET_OVERLAPPED_WRITE_EVENT], &dwresult, TRUE, &r);
+      }
+    }
+    ret = ret || !CloseHandle (wfd->overlapped[SOCKET_OVERLAPPED_WRITE_EVENT].hEvent);
+
+    if (wfd->wrbuffer)
+    {
+      GNUNET_free (wfd->wrbuffer->buf);
+      GNUNET_free (wfd->wrbuffer);
+      wfd->wrbuffer = NULL;
+    }
+    if (closehandle)
+    {
+      ret = ret || closesocket ((SOCKET) wfd->fd);
+    }
+    break;
+  case GNUNET_W32IO_FILE:
+  case GNUNET_W32IO_NAMED_PIPE:
+    for (i = 0; i < POLLLAST; i++)
+    {
+      if (wfd->overlapped[i].hEvent == INVALID_HANDLE_VALUE)
+        continue;
+
+      dwresult = WaitForSingleObject (wfd->overlapped[i].hEvent, 0);
+      if (dwresult == WAIT_TIMEOUT && (i == POLLIN_BIT || i == POLLOUT_BIT))
+      {
+        /* Disabled state of the event means that there is still an
+         * operation going on (event has to be reset manually and should
+         * stay signalled after I/O is complete until it is started again).
+         * Except for FD_CONNECT (it is unset after pipe is connected)
+         */
+        /* We're going to free the event. Have to cancel all I/O issued by
+         * this thread using this fd.
+         */
+        if (CancelIo (wfd->fd))
+        {
+          /* Wait until I/O is cancelled */
+          GetOverlappedResult (wfd->fd, &wfd->overlapped[i], &dwresult, TRUE);
+        }
+      }
+      ret = ret || !CloseHandle (wfd->overlapped[i].hEvent);
+      wfd->overlapped[i].hEvent = NULL;
+    }
+
+    if (wfd->wrbuffer)
+    {
+      GNUNET_free (wfd->wrbuffer->buf);
+      GNUNET_free (wfd->wrbuffer);
+      wfd->wrbuffer = NULL;
+    }
+    if (closehandle)
+    {
+      if (wfd->access & GENERIC_WRITE)
+        FlushFileBuffers (wfd->fd);
+      if (wfd->fd_type == GNUNET_W32IO_NAMED_PIPE)
+        DisconnectNamedPipe (wfd->fd);
+      ret = ret || !CloseHandle (wfd->fd);
+    }
+    break;
+  case GNUNET_W32IO_ANONYMOUS_PIPE:
+    ret = w32io_anonymous_pipe_close (wfd, closehandle);
+    break;
+  default:
+    errno = ENOSYS;
+  }
+  GNUNET_free (wfd);
+  return ret;
+}
+
+int
+GNUNET_W32IO_close (int fd, int closehandle)
+{
+  int ret = w32io_close (w32io_fetch_fd (fd), closehandle);
+  /* w32io_remove_fd() will NOT close or dealloc W32Fd,
+   * it is for fd namespace management only
+   */
+  w32io_remove_fd (fd);
+  return ret;
+}
+
+int
+w32io_poll (struct W32PollFd *fds, nfds_t nfds, int timeout, int emulate_select)
+{
+  HANDLE *hEvents = NULL;
+  unsigned int hEvents_len = 0;
+  int eventCount = 0;
+  DWORD dwResult = 0;
+  DWORD wait_ret = 0;
+  DWORD dwError = 0;
+  int result = 0;
+  int any_errors = FALSE;
+  int i, j, k;
+  int repeat;
+  int hits = 0;
+
+  /* Special case for using ppoll() as a portable way to sleep */
+  if (nfds == 0)
+  {
+    SetLastError (0);
+    dwResult = WaitForSingleObject (GetCurrentProcess (), timeout == -1 ? INFINITE : timeout);
+    dwError = GetLastError ();
+    if (dwResult == WAIT_FAILED)
+    {
+      SetErrnoFromWinError (dwError);
+      result = -1;
+    }
+    return result;
+  }
+
+  /* Instead of counting or using dynamic memory allocation, we'll just
+   * allocate the amount that is guaranteed to cover our needs.
+   */
+  hEvents = NULL;
+  GNUNET_array_grow(hEvents, hEvents_len, nfds * (POLLLAST + 1) * sizeof (HANDLE));
+
+  repeat = 1;
+  while (repeat == 1)
+  {
+    DWORD time1, time2;
+    eventCount = 0;
+    dwResult = 0;
+    wait_ret = 0;
+    dwError = 0;
+    result = 0;
+    repeat = -1;
+    for (i = 0; i < nfds; i++)
+    {
+      j = w32io_prepare_for_poll (&fds[i], &hEvents[eventCount]);
+    
+      if (eventCount + j - 1 >= nfds * (POLLLAST + 1) || j < 0)
+      {
+        GNUNET_free (hEvents);
+        return -1;
+      }
+      else
+        eventCount += j;
+    }
+  
+    SetLastError (0);
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+        "WaitForMultipleObjectsEx (%d, %x, FALSE, %d, FALSE)\n", eventCount,
+        hEvents, timeout == -1 ? INFINITE : timeout);
+#endif
+    time1 = GetTickCount ();
+    dwResult = WaitForMultipleObjectsEx (eventCount, hEvents, FALSE,
+        timeout == -1 ? INFINITE : timeout, FALSE);
+    dwError = GetLastError ();
+    if ((dwResult < eventCount && dwError == NO_ERROR) || dwResult == WAIT_TIMEOUT)
+    {
+      for (i = 0; i < nfds; i++)
+      {
+        int selected = 0;
+        if (fds[i].fd == INVALID_POLL_FD)
+          continue;
+        if (fds[i].fd->fd_type == GNUNET_W32IO_SOCKET)
+        {
+          int enumerated = 0;
+          for (j = 0; j < POLLLAST; j++)
+          {
+            if (fds[i].fd->overlapped[j].hEvent == INVALID_HANDLE_VALUE)
+              continue;
+  
+            wait_ret = WaitForSingleObject (fds[i].fd->overlapped[j].hEvent, 0);
+            if (wait_ret == WAIT_TIMEOUT)
+              continue;
+  
+            if ((j == SOCKET_POLL_EVENT || j == SOCKET_WAKEUP_EVENT))
+            {
+              WSANETWORKEVENTS events;
+              if (!enumerated)
+              {
+                enumerated = 1;
+                memset (&events, 0, sizeof (events));
+                int enum_ret = WSAEnumNetworkEvents ((SOCKET) fds[i].fd->fd, fds[i].fd->overlapped[SOCKET_POLL_EVENT].hEvent, &events);
+                if (enum_ret != 0) {
+                  dwError = GetLastError ();
+                  any_errors = TRUE;
+                  SetErrnoFromWinError (dwError);
+                  /* FIXME: make sure this is correct */
+                  if (dwError == WSAECONNRESET)
+                  {
+                    fds[i].fd->revents |= POLLHUP;
+                  }
+                  else
+                    fds[i].fd->revents |= POLLERR;
+                  break;
+                }
+                /* This way we won't lose one-time events. However, we also must
+                 * watch what we do with the socket and drop the bits from
+                 * lNetworkEvents when appropriate.
+                 */
+                fds[i].fd->wsaevents.lNetworkEvents |= events.lNetworkEvents;
+                for (k = 0; k < FD_MAX_EVENTS; k++)
+                {
+                  int bit = 1 << k;
+                  if (fds[i].fd->events & bit & fds[i].fd->wsaevents.lNetworkEvents)
+                  {
+                    fds[i].fd->revents |= bit;
+                    hits += 1;
+                    selected = 1;
+                    if (fds[i].fd->wsaevents.iErrorCode[k] != 0)
+                      fds[i].fd->revents |= POLLERR;
+                  }
+                }
+                if (fds[i].fd->revents & FD_CONNECT)
+                {
+                  fds[i].fd->revents &= ~FD_CONNECT;
+                  fds[i].fd->revents |= POLLOUT;
+                }
+                if (fds[i].fd->revents & FD_ACCEPT)
+                {
+                  fds[i].fd->revents &= ~FD_ACCEPT;
+                  fds[i].fd->revents |= POLLIN;
+                }
+                if (fds[i].fd->wsaevents.lNetworkEvents & FD_CLOSE)
+                {
+                  fds[i].fd->revents |= POLLHUP;
+                  fds[i].fd->revents &= ~POLLOUT;
+                  hits += 1;
+                  selected = 1;
+                }
+              }
+              if (j == SOCKET_WAKEUP_EVENT)
+                ResetEvent (fds[i].fd->overlapped[j].hEvent);
+            }
+            else if (j == SOCKET_OVERLAPPED_WRITE_EVENT)
+            {
+              DWORD r, t, e;
+              SetLastError (0);
+              if (!WSAGetOverlappedResult ((SOCKET) fds[i].fd->fd, &fds[i].fd->overlapped[j], &t, TRUE, &r))
+              {
+                e = GetLastError ();
+                /* FIXME: handle the error */
+              }
+              if (fds[i].fd->wrbuffer)
+              {
+                GNUNET_free (fds[i].fd->wrbuffer->buf);
+                GNUNET_free (fds[i].fd->wrbuffer);
+                fds[i].fd->wrbuffer = NULL;
+              }
+              ResetEvent (fds[i].fd->overlapped[j].hEvent);
+            }
+            else
+            {
+              switch (j)
+              {
+              case POLLERR_BIT:
+              case POLLHUP_BIT:
+              case POLLNVAL_BIT:
+                fds[i].fd->revents |= 1 << j;
+                break;
+              default:
+                ;
+              }
+              ResetEvent (fds[i].fd->overlapped[j].hEvent);
+            }
+          }
+        }
+        else if (fds[i].fd->fd_type == GNUNET_W32IO_FILE)
+        {
+          /* TODO: better implementation (consider two processes sharing
+           * a file, both for reading and for writing; consider deleting
+           * a file while a process waits on it).
+           */
+          for (j = 0; j < POLLLAST; j++)
+          {
+            DWORD eventSet;
+            BOOL bret;
+            int bit = 1 << j;
+  
+            if (fds[i].fd->overlapped[j].hEvent == INVALID_HANDLE_VALUE)
+              continue;
+  
+            eventSet = 0;
+            eventSet = WaitForSingleObject (fds[i].fd->overlapped[j].hEvent, 0);
+            if (eventSet == WAIT_FAILED)
+            {
+              // FIXME: handle the error
+              any_errors = TRUE;
+              continue;
+            }
+            if (eventSet == WAIT_TIMEOUT)
+              continue;
+  
+            /* common code for all three events */          
+            bret = 0;
+            switch (j)
+            {
+            case POLLIN_BIT:
+            case POLLOUT_BIT:
+              fds[i].fd->revents |= bit;
+              fds[i].fd->wsaevents.lNetworkEvents |= bit;
+              fds[i].fd->wsaevents.iErrorCode[j] = 0;
+              /* If ReadFile returned immediately, won't GetOvelappedResult() block forever? */
+              /*
+              bret = GetOverlappedResult (fds[i].fd->fd,
+                  &fds[i].fd->overlapped[j], &wait_ret, TRUE);
+              */
+              selected = 1;
+              break;
+            case POLLERR_BIT:
+            case POLLNVAL_BIT:
+              fds[i].fd->wsaevents.iErrorCode[j] = fds[i].fd->dwerror;
+            default:
+              fds[i].fd->revents |= bit;
+              fds[i].fd->wsaevents.lNetworkEvents |= bit;
+            }
+  
+            switch (j)
+            {
+            case POLLIN_BIT:
+              /*
+              if (bret != 0)
+                break;
+  
+  
+              wait_ret = GetLastError ();
+              if (wait_ret == ERROR_HANDLE_EOF) {
+                fds[i].fd->revents &= ~FD_READ;
+                fds[i].fd->wsaevents.lNetworkEvents &= ~FD_READ;
+              } else {
+                any_errors = TRUE;
+                fds[i].fd->revents |= POLLERR;
+                fds[i].fd->wsaevents.iErrorCode[j] = wait_ret;
+                errno = gst_win32_error_to_errno(wait_ret);
+              }
+              */
+              break;
+            case POLLOUT_BIT:
+              if (fds[i].fd->wrbuffer) {
+                GNUNET_free (fds[i].fd->wrbuffer->buf);
+                GNUNET_free (fds[i].fd->wrbuffer);
+                fds[i].fd->wrbuffer = NULL;
+              }
+              /*
+              if (bret != 0)
+                break;
+  
+              wait_ret = GetLastError ();
+              if (wait_ret != NO_ERROR)
+              {
+                any_errors = TRUE;
+                fds[i].fd->revents |= POLLERR;
+                fds[i].fd->wsaevents.iErrorCode[j] = wait_ret;
+                errno = gst_win32_error_to_errno(wait_ret);
+              }
+              */
+              break;
+            default:
+              break;
+            }
+            ResetEvent (fds[i].fd->overlapped[j].hEvent);
+          }
+        }
+        else if (fds[i].fd->fd_type == GNUNET_W32IO_ANONYMOUS_PIPE)
+        {
+          for (j = 0; j < POLLLAST; j++)
+          {
+            DWORD eventSet;
+            BOOL bret;
+            int bit = 1 << j;
+  
+            if (fds[i].fd->overlapped[j].hEvent == INVALID_HANDLE_VALUE || j == ANON_PIPE_THREAD_POLL_EVENT || j == ANON_PIPE_CONFIRM_POLL_EVENT)
+              continue;
+
+            eventSet = 0;
+            eventSet = WaitForSingleObject (fds[i].fd->overlapped[j].hEvent, 0);
+            if (eventSet == WAIT_FAILED)
+            {
+              /* FIXME: handle the error */
+              any_errors = TRUE;
+              continue;
+            }
+            if (eventSet == WAIT_TIMEOUT)
+              continue;
+            
+            /* common code for all three events */          
+            bret = 0;
+            switch (j)
+            {
+            case ANON_PIPE_MAIN_THREAD_POLL_EVENT:
+              fds[i].fd->revents |= (fds[i].fd->access & GENERIC_WRITE ? POLLOUT : 0) | (fds[i].fd->access & GENERIC_READ ? POLLIN : 0);
+              selected = 1;
+#if DEBUG_W32IO
+              GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Locking the thread mutex.\n");
+#endif
+
+              WaitForSingleObject (fds[i].fd->anon_thread_mutex, INFINITE);
+#if DEBUG_W32IO
+              GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Locked the thread mutex.\n");
+#endif
+              break;
+            case POLLHUP_BIT:
+              fds[i].fd->revents |= bit;
+            
+              selected = 1;
+#if DEBUG_W32IO
+              GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Locking the thread mutex.\n");
+#endif
+              WaitForSingleObject (fds[i].fd->anon_thread_mutex, INFINITE);
+#if DEBUG_W32IO
+              GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Locked the thread mutex.\n");
+#endif
+              break;
+            case POLLERR_BIT:
+            case POLLNVAL_BIT:
+              fds[i].fd->revents |= bit;
+            default:
+              ;
+            }
+            
+            switch (j)
+            {
+            case ANON_PIPE_MAIN_THREAD_POLL_EVENT:
+              if (fds[i].fd->dwerror == ERROR_BROKEN_PIPE) {
+                fds[i].fd->revents |= POLLHUP;
+                SetEvent (fds[i].fd->overlapped[POLLHUP_BIT].hEvent);
+              } else if (fds[i].fd->dwerror != NO_ERROR) {
+                any_errors = TRUE;
+                fds[i].fd->revents |= POLLERR;
+                SetErrnoFromWinError (fds[i].fd->dwerror);
+              }
+              break;
+            case POLLHUP_BIT:
+              if (!(fds[i].fd->events & (POLLIN | POLLOUT)))
+              {
+                if (fds[i].fd->dwerror == ERROR_BROKEN_PIPE)
+                {
+                  fds[i].fd->revents |= POLLHUP;
+                } else if (fds[i].fd->dwerror == NO_ERROR) {
+                  /* FIXME: make sure this is the right way...
+                   * something might have set [POLLHUP_BIT].hEvent but not
+                   * the dwerror
+                   */
+                  ResetEvent (fds[i].fd->overlapped[POLLHUP_BIT].hEvent);
+                } else {
+                  any_errors = TRUE;
+                  fds[i].fd->revents |= POLLERR;
+                  SetErrnoFromWinError (fds[i].fd->dwerror);
+                }
+              }
+              break;
+            default:
+              /* Never set */
+              break;
+            }
+            
+            switch (j)
+            {
+            case ANON_PIPE_MAIN_THREAD_POLL_EVENT:
+            case POLLHUP_BIT:
+            case POLLERR_BIT:
+            case POLLNVAL_BIT:
+              ResetEvent (fds[i].fd->overlapped[j].hEvent);
+              ReleaseMutex (fds[i].fd->anon_thread_mutex);
+              break;
+            default:
+              ;
+            }
+          }
+        }
+        else if (fds[i].fd->fd_type == GNUNET_W32IO_NAMED_PIPE)
+        {
+          for (j = 0; j < POLLLAST; j++)
+          {
+            DWORD eventSet;
+            int bret;
+            int bit = 1 << j;
+  
+            if (fds[i].fd->overlapped[j].hEvent == INVALID_HANDLE_VALUE)
+              continue;
+
+            /*  
+            if (j == POLLOUT_BIT)
+            {
+              if (fds[i].fd->writebuffer == NULL && (fds[i].fd->access & GENERIC_WRITE))
+              {
+                fds[i].fd->revents |= bit;
+                fds[i].fd->wsaevents.lNetworkEvents |= bit;
+                SetEvent (fds[i].fd->overlapped[POLLOUT_BIT].hEvent);
+              }
+            }
+            */
+            eventSet = 0;
+            eventSet = WaitForSingleObject (fds[i].fd->overlapped[j].hEvent, 0);
+            if (eventSet == WAIT_FAILED)
+            {
+              /* FIXME: handle the error */
+              any_errors = TRUE;
+              continue;
+            }
+            if (eventSet == WAIT_TIMEOUT)
+              continue;
+            
+            /* common code for all three events */          
+            bret = 0;
+            switch (j)
+            {
+            case POLLIN_BIT:
+            case FD_CONNECT_BIT:
+            case POLLOUT_BIT:
+              fds[i].fd->revents |= bit;
+              fds[i].fd->wsaevents.lNetworkEvents |= bit;
+              fds[i].fd->wsaevents.iErrorCode[j] = 0;
+              bret = GetOverlappedResult (fds[i].fd->fd,
+                  &fds[i].fd->overlapped[j], &wait_ret, TRUE);
+              selected = 1;
+              break;
+            default:
+              ;
+            }
+            
+            switch (j)
+            {
+            case POLLIN_BIT:
+              /* Our read-zero-bytes operation is complete, which means that
+               * there is data to be read. Keep the event set. It will be
+               * unset by our read() implementation or by *_prepare_for_poll
+               */
+              if (bret != 0)
+                break;
+            
+              wait_ret = GetLastError ();
+#if DEBUG_W32IO
+              GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GetOverlappedResult failed with GLE %d\n", wait_ret);
+#endif
+              if (wait_ret == ERROR_BROKEN_PIPE || wait_ret == ERROR_PIPE_NOT_CONNECTED) {
+                fds[i].fd->revents |= FD_CLOSE;
+                fds[i].fd->wsaevents.lNetworkEvents |= FD_CLOSE;
+            
+                SetEvent (fds[i].fd->overlapped[FD_CLOSE_BIT].hEvent);
+            
+                /* Set FD_CONNECT event so that we can attempt to connect again */
+                SetEvent (fds[i].fd->overlapped[FD_CONNECT_BIT].hEvent);
+              } else if (wait_ret != NO_ERROR) {
+                any_errors = TRUE;
+                fds[i].fd->revents |= POLLERR;
+                fds[i].fd->wsaevents.iErrorCode[j] = wait_ret;
+                SetErrnoFromWinError (wait_ret);
+              }
+              break;
+            case FD_CONNECT_BIT:
+              /* Our ConnectNamedPipe() operation is complete, which means that
+               * the pipe was not connected before, but is connected now.
+               */
+              /* Unset the event - that would prevent *_prepare_for_poll from
+               * trying to re-connect the pipe each time it is called.
+               */
+              ResetEvent (fds[i].fd->overlapped[j].hEvent);
+
+              if (bret != 0)
+                break;
+            
+              wait_ret = GetLastError ();
+#if DEBUG_W32IO
+              GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GetOverlappedResult failed with GLE %d\n", wait_ret);
+#endif
+              if (wait_ret == ERROR_NO_DATA) {
+                fds[i].fd->revents |= FD_CLOSE;
+                fds[i].fd->wsaevents.lNetworkEvents |= FD_CLOSE;
+                SetEvent (fds[i].fd->overlapped[FD_CLOSE_BIT].hEvent);
+                SetEvent (fds[i].fd->overlapped[FD_CONNECT_BIT].hEvent);
+              } else if (wait_ret != NO_ERROR) {
+                any_errors = TRUE;
+                fds[i].fd->revents |= POLLERR;
+                fds[i].fd->wsaevents.iErrorCode[j] = wait_ret;
+                SetErrnoFromWinError (wait_ret);
+              }
+            
+              break;
+            case POLLOUT_BIT:
+              /* Our WriteFile() operation is complete, which means that the pipe
+               * is ready to write once more. Keep the event set - it will be
+               * unset by our write() implementation.
+               */
+              if (fds[i].fd->wrbuffer) {
+                GNUNET_free (fds[i].fd->wrbuffer->buf);
+                GNUNET_free (fds[i].fd->wrbuffer);
+                fds[i].fd->wrbuffer = NULL;
+              }
+            
+              if (bret != 0)
+                break;
+            
+              wait_ret = GetLastError ();
+#if DEBUG_W32IO
+              GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GetOverlappedResult failed with GLE %d\n", wait_ret);
+#endif
+              if (wait_ret == ERROR_BROKEN_PIPE) {
+                fds[i].fd->revents |= FD_CLOSE;
+                fds[i].fd->wsaevents.lNetworkEvents |= FD_CLOSE;
+            
+                SetEvent (fds[i].fd->overlapped[FD_CLOSE_BIT].hEvent);
+                SetEvent (fds[i].fd->overlapped[FD_CONNECT_BIT].hEvent);
+              } else if (wait_ret != NO_ERROR) {
+                any_errors = TRUE;
+                fds[i].fd->revents |= POLLERR;
+                fds[i].fd->wsaevents.iErrorCode[j] = wait_ret;
+                SetErrnoFromWinError (wait_ret);
+              }
+            
+              break;
+            case POLLHUP_BIT:
+              if (!(fds[i].fd->events & (POLLIN | POLLOUT)))
+              { 
+                if (!(fds[i].fd->revents & POLLHUP))
+                {
+                  bret = GetOverlappedResult (fds[i].fd->fd,
+                      &fds[i].fd->overlapped[POLLHUP_BIT], &wait_ret, TRUE);
+                  selected = 1;
+  
+                  wait_ret = GetLastError ();
+                  if (wait_ret != NO_ERROR)
+                  {
+                    fds[i].fd->revents |= POLLHUP_BIT;
+                    fds[i].fd->wsaevents.lNetworkEvents |= FD_CLOSE;
+                  } else {
+                    ResetEvent (fds[i].fd->overlapped[FD_CLOSE_BIT].hEvent);
+                    fds[i].fd->revents &= ~POLLHUP_BIT;
+                    fds[i].fd->wsaevents.lNetworkEvents &= ~FD_CLOSE;
+                  }
+                }
+                else
+                {
+                   selected = 1;
+                   fds[i].fd->revents |= POLLHUP;
+                   fds[i].fd->wsaevents.lNetworkEvents |= FD_CLOSE;
+                }
+              }
+              else
+              {
+                if ((fds[i].fd->events & POLLIN) && (fds[i].fd->access & GENERIC_READ))
+                {
+                  selected = 1;
+                  fds[i].fd->revents |= POLLIN;
+                }
+                if ((fds[i].fd->events & POLLOUT) && (fds[i].fd->access & GENERIC_WRITE))
+                {
+                  selected = 1;
+                  fds[i].fd->revents |= POLLOUT;
+                }
+              }
+              break;
+            default:
+              break;
+            }
+          }
+          if (fds[i].fd->revents & FD_CONNECT)
+          {
+            fds[i].fd->revents &= ~FD_CONNECT;
+            if (fds[i].fd->access & GENERIC_READ)
+            {
+              SetEvent (fds[i].fd->overlapped[POLLIN_BIT].hEvent);
+              fds[i].fd->revents |= POLLIN;
+            }
+            if (fds[i].fd->access & GENERIC_WRITE)
+            {
+              SetEvent (fds[i].fd->overlapped[POLLOUT_BIT].hEvent);
+              fds[i].fd->revents |= POLLOUT;
+            }
+          }
+
+        }
+        if (emulate_select)
+        {
+          /* there's no HUP in select() */
+          if (fds[i].fd->revents & POLLHUP)
+          {
+            int waking = 0;
+            fds[i].fd->revents &= ~POLLHUP;
+            
+            if (fds[i].fd->events & POLLIN & fds[i].fd->revents)
+              waking = 1;
+            if (fds[i].fd->events & POLLOUT & fds[i].fd->revents)
+              waking = 1;
+            if (!waking && fds[i].fd->access & GENERIC_READ && fds[i].fd->events & POLLIN)
+            {
+              waking = 1;
+              fds[i].fd->revents |= POLLIN;
+            }
+            if (!waking && fds[i].fd->access & GENERIC_WRITE && fds[i].fd->events & POLLOUT)
+            {
+              waking = 1;
+              fds[i].fd->revents |= POLLOUT;
+            }
+          }
+          /* FIXME: What about ERR and NVAL? */
+        }
+        if (fds[i].fd->fd_type != GNUNET_W32IO_SOCKET)
+          hits += 1;
+        result += selected;
+        fds[i].revents = fds[i].fd->revents;
+      }
+    }
+    else if (dwResult == WAIT_TIMEOUT)
+    {
+      /* result = 0; */
+    }
+    else if (dwResult == WAIT_FAILED)
+    {
+      SetErrnoFromWinError (dwError);
+      result = -1;
+    }
+    if (any_errors && result >= 0)
+    {
+      result = -1;
+    }
+    if (hits == 0)
+    {
+#if DEBUG_W32IO
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Repeating ppoll()\n");
+#endif
+      time2 = GetTickCount ();
+      if (timeout != -1)
+      {
+        DWORD new_timeout = timeout - time2 > time1 ? time2 - time1 : (0xFFFFFFFF - time1) + time2;
+        if (new_timeout > timeout)
+          timeout = -1;
+        else
+          timeout = new_timeout;
+      }
+      hits = 0;
+      repeat = 1;
+    }
+  }
+
+  GNUNET_free (hEvents);
+  return result;
+}
+
+int
+GNUNET_W32IO_poll (struct pollfd fds[], nfds_t nfds, int timeout)
+{
+  struct W32PollFd *wfds;
+  int i;
+  int result;
+  wfds = GNUNET_malloc (sizeof (struct W32PollFd) * nfds);
+  for (i = 0; i < nfds; i++)
+  {
+    wfds[i].fd = w32io_fetch_fd (fds[i].fd);
+    wfds[i].events = fds[i].events;
+  }
+  result = w32io_poll (wfds, nfds, timeout, 0);
+  GNUNET_free (wfds);
+  return result;
+}
+
+int
+GNUNET_W32IO_select (int nfds, w32fd_set *readfds,
+       w32fd_set *writefds, w32fd_set *errorfds,
+       struct timeval *timeout)
+{
+  struct W32PollFd *wfds;
+  int i, j, ins;
+  int result = 0;
+  int ms_time;
+  short t;
+  wfds = GNUNET_malloc (sizeof (struct W32PollFd) * nfds);
+  for (i = 0; i < nfds; i++)
+    wfds[i].fd = INVALID_POLL_FD;
+  j = 0;
+  for (i = 0; i < nfds; i++)
+  {
+    ins = 0;
+    if (readfds && W32_FD_ISSET(i, readfds))
+    {
+      wfds[j].fd = w32io_fetch_fd (i);
+      if (!wfds[j].fd)
+      {
+        errno = EBADF;
+        result = -1;
+        break;
+      }
+      t = POLLIN;
+      wfds[j].events |= t;
+      ins = 1;
+    }
+    if (writefds && W32_FD_ISSET(i, writefds))
+    {
+      wfds[j].fd = w32io_fetch_fd (i);
+      if (!wfds[j].fd)
+      {
+        errno = EBADF;
+        result = -1;
+        break;
+      }
+      t = POLLOUT;
+      wfds[j].events |= t;
+      ins = 1;
+    }
+    if (errorfds && W32_FD_ISSET(i, errorfds))
+    {
+      wfds[j].fd = w32io_fetch_fd (i);
+      if (!wfds[j].fd)
+      {
+        errno = EBADF;
+        result = -1;
+        break;
+      }
+      wfds[j].events |= POLLERR;
+      ins = 1;
+    }
+    j += ins;
+  }
+#if DEBUG_W32IO
+  if (result != 0)
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Some of the FDs were fetched as NULL\n");
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "select() fetched everything without errors\n");
+#endif
+  if (result == 0)
+  {
+    if (timeout)
+      ms_time = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
+    else
+      ms_time = -1;
+    result = w32io_poll (wfds, j, ms_time, 1);
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "w32io_poll() returned %d\n", result);
+#endif
+  }
+  if (result >= 0)
+  {
+    result = 0;
+    j = 0;
+    for (i = 0; i < nfds; i++)
+    {
+      ins = 0;
+      if (readfds && W32_FD_ISSET(i, readfds))
+      {
+        ins = 1;
+        if (wfds[j].revents & (POLLIN | POLLHUP | POLLNVAL))
+        {
+          result += 1;
+        }
+        else
+          W32_FD_CLR(i, readfds);
+      }
+      if (writefds && W32_FD_ISSET(i, writefds))
+      {
+        ins = 1;
+        if (wfds[j].revents & (POLLOUT | POLLHUP | POLLNVAL))
+        {
+          result += 1;
+        }
+        else
+          W32_FD_CLR(i, writefds);
+      }
+      if (errorfds && W32_FD_ISSET(i, errorfds))
+      {
+        ins = 1;
+        if (wfds[j].revents & (POLLERR | POLLHUP | POLLNVAL))
+        {
+          result += 1;
+        }
+        else
+          W32_FD_CLR(i, errorfds);
+      }
+      j += ins;
+    }
+  }
+  GNUNET_free (wfds);
+  return result;
+}
+
+/**
+ * Prepares @wpfd for polling
+ */
+int
+w32io_prepare_for_poll (struct W32PollFd *wpfd, HANDLE *polllist)
+{
+  struct W32Fd *wfd = wpfd->fd;
+
+  int ret;
+  DWORD dwret;
+  int result = 0;
+  wpfd->revents = 0;
+  if (wpfd->fd == INVALID_POLL_FD)
+    return 0;
+  wfd->revents = 0;
+  wfd->events = wpfd->events;
+
+  if (wfd->fd_type == GNUNET_W32IO_SOCKET)
+  {
+    //DWORD sockevents = wfd->events & FD_ALL_EVENTS;
+    WSANETWORKEVENTS events;
+    int hits = 0;
+    memset (&events, 0, sizeof (events));
+    int enum_ret = WSAEnumNetworkEvents ((SOCKET) wfd->fd, wfd->overlapped[SOCKET_POLL_EVENT].hEvent, &events);
+    if (enum_ret != 0) {
+      DWORD dwError = GetLastError ();
+      SetErrnoFromWinError (dwError);
+      /* FIXME: make sure this is correct */
+      if (dwError == WSAECONNRESET)
+      {
+        wfd->wsaevents.lNetworkEvents |= FD_CLOSE;
+      }
+      else
+      {
+        /* FIXME: Not sure about this one. Not all errors lead to FD_CLOSE */
+        wfd->wsaevents.lNetworkEvents |= FD_CLOSE;
+        wfd->wsaevents.iErrorCode[FD_CLOSE] = dwError;
+      }
+    }
+    else
+    {
+      /* This way we won't lose one-time events. However, we also must
+       * watch what we do with the socket and drop the bits from
+       * lNetworkEvents when appropriate.
+       */
+      int k;
+      wfd->wsaevents.lNetworkEvents |= events.lNetworkEvents;
+      for (k = 0; k < FD_MAX_EVENTS; k++)
+      {
+        int bit = 1 << k;
+        if (wfd->events & bit & wfd->wsaevents.lNetworkEvents)
+        {
+          wfd->revents |= bit;
+          hits += 1;
+          if (wfd->wsaevents.iErrorCode[k] != 0)
+            wfd->revents |= POLLERR;
+        }
+      }
+      if (wfd->revents & FD_CONNECT)
+      {
+        wfd->revents &= ~FD_CONNECT;
+        wfd->revents |= POLLOUT;
+      }
+      if (wfd->revents & FD_ACCEPT)
+      {
+        wfd->revents &= ~FD_ACCEPT;
+        wfd->revents |= POLLIN;
+      }
+      if (wfd->wsaevents.lNetworkEvents & FD_CLOSE)
+      {
+        wfd->revents |= POLLHUP;
+        wfd->revents &= ~POLLOUT;
+        hits += 1;
+      }
+    }
+    if (hits > 0 || ((wfd->events & POLLOUT) && (wfd->wsaevents.lNetworkEvents & FD_WRITE)) || (wfd->wsaevents.lNetworkEvents & FD_CLOSE))
+      SetEvent (wfd->overlapped[SOCKET_WAKEUP_EVENT].hEvent);
+    polllist[result++] = wfd->overlapped[SOCKET_POLL_EVENT].hEvent;
+    polllist[result++] = wfd->overlapped[SOCKET_WAKEUP_EVENT].hEvent;
+    polllist[result++] = wfd->overlapped[SOCKET_OVERLAPPED_WRITE_EVENT].hEvent;
+    wfd->revents = 0;
+  }
+  else if (wfd->fd_type == GNUNET_W32IO_FILE)
+  {
+    /* Only POLLIN and POLLOUT are relevant for files
+     * Error conditions will be reported later on their own accord, we do not
+     * need event objects to detect these
+     */
+    wfd->events &= POLLIN | POLLOUT;
+
+    if (wfd->events & POLLIN || wfd->events & POLLOUT)
+    {
+      /* Ready to read/write unconditinally */
+      SetEvent (wfd->overlapped[FILE_READY_POLL_EVENT].hEvent);
+      polllist[result++] = wfd->overlapped[FILE_READY_POLL_EVENT].hEvent;
+    }
+    else
+      ResetEvent (wfd->overlapped[FILE_READY_POLL_EVENT].hEvent);
+    polllist[result++] = wfd->overlapped[POLLERR_BIT].hEvent;
+    polllist[result++] = wfd->overlapped[POLLNVAL_BIT].hEvent;
+  }
+  else if (wfd->fd_type == GNUNET_W32IO_ANONYMOUS_PIPE)
+  {
+    /* Anonymous pipes support only POLLIN and POLLOUT.
+     * Also don't poll for reading/writing on write-only/read-only pipes
+     */
+    wfd->events &= (wfd->access & GENERIC_READ ? POLLIN : 0) | (wfd->access & GENERIC_WRITE ? POLLOUT : 0);
+    if (wfd->events & POLLIN || (!(wfd->events & POLLOUT) && (wfd->access & GENERIC_READ)))
+    {
+      /* Get the mutex (shouldn't delay us for too long */
+#if DEBUG_W32IO
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Locking the thread mutex.\n");
+#endif
+      dwret = WaitForSingleObject (wfd->anon_thread_mutex, INFINITE);
+#if DEBUG_W32IO
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Locked the thread mutex.\n");
+#endif
+      /* Check the state of the buffer */
+      if (wfd->bytes_read >= 0 && wfd->alive)
+      {
+        /* No unread data in the buffer.
+         * Make sure we wake up when there is some (worker thread will enable
+         * ANON_PIPE_MAIN_THREAD_POLL_EVENT every time bytes_read <= 0)
+         */
+        ResetEvent (wfd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent);
+      }
+      else
+      {
+        /* Just to be safe **/
+        SetEvent (wfd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent);
+      }
+      ReleaseMutex (wfd->anon_thread_mutex);
+
+      /* We will wait upon wfd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent. When it is enabled,
+       * the worker thread has some unread data.
+       */
+      polllist[result++] = wfd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent;
+    }
+    else if (wfd->events & POLLOUT)
+    {
+      /* We will wait upon wfd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent. When it is enabled,
+       * the worker thread have completed its work and released the mutex,
+       * and we can write once again.
+       */
+      polllist[result++] = wfd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent;
+    }
+    /* Read or write operations will reveal a broken pipe, but if we
+     * have neither, we have to do something to detect that.
+     */
+    if (!(wfd->events & POLLIN) && !(wfd->events & POLLOUT) && WaitForSingleObject (wfd->anon_thread_mutex, 0) == WAIT_OBJECT_0)
+    {
+      int wait_confirm = 0;
+      if (wfd->access & GENERIC_READ)
+      {
+        /* We are reading already */
+      }
+      else if (wfd->access & GENERIC_WRITE)
+      {
+        int skipwriting = FALSE;
+        if (wfd->wrbuffer)
+        {
+          /* We've been writing somethings */
+          GNUNET_free (wfd->wrbuffer->buf);
+          GNUNET_free (wfd->wrbuffer);
+          wfd->wrbuffer = NULL;
+      
+          /* Process any error conditions from previous write operation */
+          if (wfd->bret == 0)
+          {
+            SetEvent (wfd->overlapped[POLLHUP_BIT].hEvent);
+            skipwriting = TRUE;
+          }
+        }
+
+        /* Writing a byte into the pipe. BAD IDEA! Disabled. */
+        if (!skipwriting && 0)
+        {
+          wfd->work = 1; /* write */
+          wfd->wrbuffer = GNUNET_malloc (sizeof (WSABUF));
+          wfd->wrbuffer->len = 1;
+          wfd->wrbuffer->buf = GNUNET_malloc (1);
+          ((char *)wfd->wrbuffer->buf)[0] = 0;
+        
+          ResetEvent (wfd->overlapped[ANON_PIPE_CONFIRM_POLL_EVENT].hEvent);
+          SetEvent (wfd->overlapped[ANON_PIPE_THREAD_POLL_EVENT].hEvent);
+          wait_confirm = 1;
+        }
+      }
+      ReleaseMutex (wfd->anon_thread_mutex);
+      if (wait_confirm)
+      {
+#if DEBUG_W32IO
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Waiting for confirmation.\n");
+#endif
+        WaitForSingleObject (wfd->overlapped[ANON_PIPE_CONFIRM_POLL_EVENT].hEvent, INFINITE);
+#if DEBUG_W32IO
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Done waiting for confirmation.\n");
+#endif
+      }
+      /* We will wait upon wfd->overlapped[POLLHUP_BIT].hEvent,
+       * which will be set by the working thread when the pipe breaks
+       */
+    }
+    polllist[result++] = wfd->overlapped[POLLERR_BIT].hEvent;
+    polllist[result++] = wfd->overlapped[POLLNVAL_BIT].hEvent;
+    polllist[result++] = wfd->overlapped[POLLHUP_BIT].hEvent;
+  }
+  else if (wfd->fd_type == GNUNET_W32IO_NAMED_PIPE)
+  {
+    /* POLLIN and POLLOUT might mean that the caller is interested in
+     * connection events, not reads/writes, so we won't check these
+     * against access
+     */
+    wfd->events &= POLLIN | POLLOUT;
+    if (wfd->events & (POLLIN | POLLOUT))
+    {
+      if (WaitForSingleObject (wfd->overlapped[FD_CONNECT_BIT].hEvent, 0) ==
+          WAIT_OBJECT_0)
+      {
+        /* Try to connect the pipe every time it is possible to do that.
+         * Most of the time it will return immediately with the
+         * ERROR_PIPE_CONNECTED error code to indicate that the pipe is
+         * already connected, else it will set the pipe working on
+         * becoming connected.
+         */
+        ZeroOverlappedExceptEvent(wfd->overlapped[FD_CONNECT_BIT]);
+        dwret = ConnectNamedPipe (wfd->fd, &wfd->overlapped[FD_CONNECT_BIT]);
+        if (dwret == 0)
+        {
+          dwret = GetLastError ();
+          if (dwret == ERROR_PIPE_CONNECTED ||
+              dwret == ERROR_INVALID_FUNCTION)
+          {
+            /* Already connected or we're using client end of the pipe.
+             * Disable the event to prevent further connection attempts.
+             */
+            ResetEvent (wfd->overlapped[FD_CONNECT_BIT].hEvent);
+            /* Reading (see below) might be possible on a broken pipe,
+             * but writing is not, so we only attempt a writing operation
+             * when the pipe is known to be connected.
+             */
+            /* Enable the events, so that the code below can check for
+             * writeability
+             */
+            if (wfd->access & GENERIC_WRITE)
+              SetEvent (wfd->overlapped[POLLOUT_BIT].hEvent);
+          }
+          else if (dwret == ERROR_IO_PENDING)
+          {
+            /* OK */
+          }
+          else
+          {
+            SetEvent (wfd->overlapped[POLLERR_BIT].hEvent);
+            wfd->dwerror = dwret;
+            /* Keep the event set - this will trigger a connection attempt
+             * later on
+             */
+          }
+          if (dwret != ERROR_IO_PENDING)
+          {
+            /* Pending means that we ARE unconnected, and that a connection
+             * attempt is in process. Otherwise, even if we've got an error,
+             * it MIGHT be possible to get something out of the pipe buffer.
+             */
+            /* Enable the events, so that the code below can check for
+             * readablilty.
+             */
+            if (wfd->access & GENERIC_READ)
+              SetEvent (wfd->overlapped[POLLIN_BIT].hEvent);
+          }
+        }
+      }
+      polllist[result++] = wfd->overlapped[FD_CONNECT_BIT].hEvent;
+    }
+    if (wfd->events & POLLIN)
+    {
+      if (WaitForSingleObject (wfd->overlapped[POLLIN_BIT].hEvent, 0) ==
+          WAIT_OBJECT_0)
+      {
+        /* Try to read 0 bytes from the pipe. This will enable the event
+         * when there is data to read.
+         */
+        ZeroOverlappedExceptEvent(wfd->overlapped[POLLIN_BIT]);
+        dwret = ReadFile (wfd->fd, (void *) &wfd->bytes_read, 0,
+            NULL, &wfd->overlapped[POLLIN_BIT]);
+        if (dwret == 0)
+        {
+          dwret = GetLastError ();
+          if (dwret == ERROR_BROKEN_PIPE || dwret == ERROR_PIPE_NOT_CONNECTED)
+          {
+            SetEvent (wfd->overlapped[POLLHUP_BIT].hEvent);
+          }
+          else if (dwret != ERROR_IO_PENDING)
+          {
+            SetEvent (wfd->overlapped[POLLERR_BIT].hEvent);
+            wfd->dwerror = dwret;
+          }
+          /* For some reason ReadFile won't enable the event after a failure */
+          SetEvent (wfd->overlapped[POLLIN_BIT].hEvent);
+        }
+      }
+      polllist[result++] = wfd->overlapped[POLLIN_BIT].hEvent;
+    }
+    /* There is no need to prepare for POLLOUT - underlying writing is
+     * asynchronous and is always available if there is no writing operations
+     * pending.
+     */
+    if (wfd->events & POLLOUT)
+    {
+      polllist[result++] = wfd->overlapped[POLLOUT_BIT].hEvent;
+    }
+    /* read or write operations will reveal a broken pipe, but if we
+     * have neither, we have to do something to detect that.
+     */
+    if (!(wfd->events & POLLIN) && !(wfd->events & POLLOUT))
+    {
+      if (wfd->access & GENERIC_READ)
+      {
+        /* Prefer reading */
+        if (WaitForSingleObject (wfd->overlapped[POLLIN_BIT].hEvent, 0) ==
+            WAIT_OBJECT_0)
+        {
+          /* Try to read 0 bytes from the pipe. This will enable the event
+           * when there is data to read.
+           */
+          ZeroOverlappedExceptEvent(wfd->overlapped[POLLIN_BIT]);
+          dwret = ReadFile (wfd->fd, (void *) &wfd->bytes_read, 0,
+              NULL, &wfd->overlapped[POLLIN_BIT]);
+          if (dwret == 0)
+          {
+            dwret = GetLastError ();
+            if (dwret == ERROR_BROKEN_PIPE || dwret == ERROR_PIPE_NOT_CONNECTED)
+            {
+              SetEvent (wfd->overlapped[POLLHUP_BIT].hEvent);
+            }
+            else if (dwret != ERROR_IO_PENDING)
+            {
+              SetEvent (wfd->overlapped[POLLERR_BIT].hEvent);
+              wfd->dwerror = dwret;
+            }
+          } else {
+            ResetEvent (wfd->overlapped[POLLHUP_BIT].hEvent);
+          }
+        }
+      }
+      else if (wfd->access & GENERIC_WRITE && 0)
+      {
+        if (wfd->wrbuffer != NULL)
+        {
+          if (WaitForSingleObject (wfd->overlapped[POLLOUT_BIT].hEvent, 0) ==
+              WAIT_OBJECT_0 &&
+              WaitForSingleObject (wfd->overlapped[POLLHUP_BIT].hEvent, 0) ==
+              WAIT_TIMEOUT)
+          {
+            /* Get the operation result, free the buffer */
+            DWORD wait_ret;
+            ret = GetOverlappedResult ((HANDLE) wfd->fd,
+                &wfd->overlapped[POLLOUT_BIT], &wait_ret, TRUE);
+            GNUNET_free (wfd->wrbuffer->buf);
+            GNUNET_free (wfd->wrbuffer);
+            wfd->wrbuffer = NULL;
+          }
+        }
+        if (wfd->wrbuffer == NULL)
+        {
+          ZeroOverlappedExceptEvent(wfd->overlapped[POLLOUT_BIT]);
+          BOOL bret = WriteFile ((HANDLE) wfd->fd, (void *) &wfd->alive, 0, NULL,
+              &wfd->overlapped[POLLOUT_BIT]);
+          if (bret == 0) {
+            DWORD dwret = GetLastError ();
+            if (dwret != ERROR_IO_PENDING)
+            {
+              if (dwret == ERROR_BROKEN_PIPE || dwret == ERROR_PIPE_NOT_CONNECTED)
+                SetEvent (wfd->overlapped[POLLHUP_BIT].hEvent);
+              else
+                SetEvent (wfd->overlapped[POLLERR_BIT].hEvent);
+            }
+          } else {
+            ResetEvent (wfd->overlapped[POLLHUP_BIT].hEvent);
+          }
+        }        
+      }
+    }
+    polllist[result++] = wfd->overlapped[POLLERR_BIT].hEvent;
+    polllist[result++] = wfd->overlapped[POLLNVAL_BIT].hEvent;
+    polllist[result++] = wfd->overlapped[POLLHUP_BIT].hEvent;
+  }
+
+  return result;
+}
+
+GNUNET_W32IO_HandleType
+GNUNET_W32IO_find_handle_type (HANDLE h)
+{
+  DWORD dwret, dwerr, dwret2, dwerr2;
+  WSAPROTOCOL_INFO pi;
+  dwret = GetFileType (h);
+  dwerr = GetLastError ();
+  switch (dwret) {
+  case FILE_TYPE_DISK:
+    return GNUNET_W32IO_FILE;
+  case FILE_TYPE_CHAR:
+    return GNUNET_W32IO_CONSOLE;
+  case FILE_TYPE_PIPE:
+    /* It's a socket or a pipe */
+    dwret2 = WSADuplicateSocket ((SOCKET) h, 0, &pi);
+    dwerr2 = GetLastError ();
+    if (dwret2 == 0) {
+      /* WSADuplicateSocket() should always fail when called with these
+       * arguments.
+       */
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "This should not happen\n");
+      return GNUNET_W32IO_UNSPECIFIED;
+    } else {
+      if (dwerr2 == WSAEINVAL) {
+        /* Definitely a socket */
+        return GNUNET_W32IO_SOCKET;
+      } else {
+        /* Not likely a socket. A pipe? */
+        dwret2 = GetNamedPipeInfo (h, NULL, NULL, NULL, NULL);
+        dwerr2 = GetLastError ();
+        if (dwret2 != 0) {
+          /* It's a kind of pipe */
+          dwret2 = GetNamedPipeHandleStateA (h, NULL, NULL, NULL,
+              NULL, NULL, 0);
+          dwerr2 = GetLastError ();
+          if (dwret2 == 0) {
+            if (dwerr2 == ERROR_INVALID_PARAMETER) {
+              /* It's an anonymous pipe */
+              return GNUNET_W32IO_ANONYMOUS_PIPE;
+            } else {
+              /* We have no idea what it is */
+              return GNUNET_W32IO_UNKNOWN;
+            }
+          } else {
+            /* It's a named pipe */
+            return GNUNET_W32IO_NAMED_PIPE;
+          }
+        } else {
+          /* If it was something other than a pipe, we would have found
+           * it by now, and now it's not even a pipe.
+           * It could be that this is a pipe, but damaged (or in a wrong
+           * state), or not a pipe at all.
+           */
+          return GNUNET_W32IO_UNKNOWN;
+        }
+      }
+    }
+    break;
+  case FILE_TYPE_UNKNOWN:
+  default:
+    if (dwerr == NO_ERROR)
+      return GNUNET_W32IO_UNKNOWN;
+    else
+      return GNUNET_W32IO_UNSPECIFIED;
+  }
+  return GNUNET_W32IO_UNSPECIFIED;
+}
+
+/**
+ * Allows us to create W32Fd from a HANDLE we've already got somewhere else.
+ * Will try to find the handle type on its own, or we can point it out.
+ *
+ * @param h handle
+ * @param htype type of the handle @h
+ * @param access access rights to the handle @h
+ * @param connected 1 if @h is connected, 0 otherwise
+ * @param writeable 1 if it is possible to write into @h without blocking, 0 otherwise
+ * @param readable 1 if it is possible to read from @h without blocking, 0 otherwise
+ */
+struct W32Fd *
+w32io_fd_from_handle (HANDLE h, GNUNET_W32IO_HandleType htype, DWORD access,
+    int connected, int writeable, int readable)
+{
+  int i;
+  struct W32Fd *wfd = NULL;
+  DWORD error_code = 0, thread_error, threadID;
+  BOOL bret = FALSE;
+  HANDLE tw[2];
+
+  if (h == INVALID_HANDLE_VALUE)
+  {
+    errno = EINVAL;
+    return NULL;
+  }
+
+  wfd = GNUNET_malloc(sizeof (struct W32Fd));
+
+  wfd->fd = h;
+  wfd->fd_type = htype;
+  if (htype == GNUNET_W32IO_UNSPECIFIED)
+    wfd->fd_type = GNUNET_W32IO_find_handle_type (h);
+
+  for (i = 0; i < POLLLAST; i++)
+    wfd->overlapped[i].hEvent = INVALID_HANDLE_VALUE;
+
+  wfd->anon_thread = INVALID_HANDLE_VALUE;
+  wfd->anon_thread_mutex = INVALID_HANDLE_VALUE;
+  wfd->work = -1;
+
+  switch (wfd->fd_type) {
+  case GNUNET_W32IO_UNSPECIFIED:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Handle %p is of unspecified type\n", h);
+    goto error;
+    break;
+  case GNUNET_W32IO_UNKNOWN:
+    /* Failed to find the type - should not happen, unless we're
+     * feeding unexpected handles to the function.
+     */
+    /* A special hacky logic will allow us to create W32Fds with
+     * zero handles. They will have one valid event (like sockets do).
+     * This can be used for wakeup purposes, i hope.
+     */
+    /*
+     * I've trashed wakeup-event concept in favor of normal control socket
+     * read/write, so i'm not sure this hack is necessary (besides, i've
+     * never tried to actually use it).
+     */
+    /* wfd->overlapped[0].hEvent = CreateEvent (NULL, TRUE, FALSE, NULL); */
+    goto error;
+    break;
+  case GNUNET_W32IO_FILE:
+    for (i = 0; i < POLLLAST; i++) 
+    {
+      switch (i)
+      {
+      case FILE_READY_POLL_EVENT:
+      case POLLHUP_BIT:
+      case POLLERR_BIT:
+      case POLLNVAL_BIT:
+        SetLastError (0);
+        wfd->overlapped[i].hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
+        error_code = GetLastError ();
+        if (wfd->overlapped[i].hEvent == INVALID_HANDLE_VALUE || error_code != NO_ERROR)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "CreateEvent() returned %d. GLE: %d\n", wfd->overlapped[i].hEvent, error_code);
+          goto error;
+        }
+        break;
+      default:
+        break;
+      }
+    }
+    SetLastError (0);
+    bret = SetEvent (wfd->overlapped[FILE_READY_POLL_EVENT].hEvent);
+    error_code = GetLastError ();
+    if (error_code != NO_ERROR || !bret)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "SetEvent() returned %d. GLE: %d\n", bret, error_code);
+      goto error;
+    }
+    wfd->access = access;
+    break;
+  case GNUNET_W32IO_NAMED_PIPE:
+    for (i = 0; i < POLLLAST; i++) 
+    {
+      switch (i)
+      {
+      case POLLIN_BIT:
+      case POLLOUT_BIT:
+      case FD_CONNECT_BIT:
+      case POLLHUP_BIT:
+      case POLLERR_BIT:
+      case POLLNVAL_BIT:
+        SetLastError (0);
+        wfd->overlapped[i].hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
+        error_code = GetLastError ();
+        if (wfd->overlapped[i].hEvent == INVALID_HANDLE_VALUE || error_code != NO_ERROR)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "CreateEvent() returned %d. GLE: %d\n", wfd->overlapped[i].hEvent, error_code);
+          goto error;
+        }
+        break;
+      default:
+        break;
+      }
+    }
+    /* Enable the overlapped read/write events where applicable,
+     * indicating that a write/read operation is not in progress.
+     * Enable the connect overlapped event if the pipe is not connected,
+     * indicating that a connection attempt can be made.
+     */
+    if (!connected)
+    {
+      SetLastError (0);
+      bret = SetEvent (wfd->overlapped[FD_CONNECT_BIT].hEvent);
+      error_code = GetLastError ();
+      if (error_code != NO_ERROR || !bret)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "SetEvent() returned %d. GLE: %d\n", bret, error_code);
+        goto error;
+      }
+    }
+    else
+    {
+      if (writeable && (access & GENERIC_WRITE))
+      {
+        SetLastError (0);
+        bret = SetEvent (wfd->overlapped[POLLOUT_BIT].hEvent);
+        error_code = GetLastError ();
+        if (error_code != NO_ERROR || !bret)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "SetEvent() returned %d. GLE: %d\n", bret, error_code);
+          goto error;
+        }
+      }
+      if (readable && (access & GENERIC_READ))
+      {
+        SetLastError (0);
+        bret = SetEvent (wfd->overlapped[POLLIN_BIT].hEvent);
+        error_code = GetLastError ();
+        if (error_code != NO_ERROR || !bret)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "SetEvent() returned %d. GLE: %d\n", bret, error_code);
+          goto error;
+        }
+      }
+    }
+    wfd->access = access;
+    break;
+  case GNUNET_W32IO_ANONYMOUS_PIPE:
+    SetLastError (0);
+    wfd->anon_thread_mutex = CreateMutex (NULL, FALSE, NULL);
+    error_code = GetLastError ();
+    if (wfd->anon_thread_mutex == INVALID_HANDLE_VALUE || error_code != NO_ERROR)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "CreateMutex() returned %d. GLE: %d\n", wfd->anon_thread_mutex, error_code);
+      goto error;
+    }
+    for (i = 0; i < POLLLAST; i++) 
+    {
+      switch (i)
+      {
+      case ANON_PIPE_THREAD_POLL_EVENT:
+      case ANON_PIPE_MAIN_THREAD_POLL_EVENT:
+      case ANON_PIPE_CONFIRM_POLL_EVENT:
+      case POLLHUP_BIT:
+      case POLLERR_BIT:
+      case POLLNVAL_BIT:
+        SetLastError (0);
+        wfd->overlapped[i].hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
+        error_code = GetLastError ();
+        if (wfd->overlapped[i].hEvent == INVALID_HANDLE_VALUE || error_code != NO_ERROR)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "CreateEvent() returned %d. GLE: %d\n", wfd->overlapped[i].hEvent, error_code);
+          goto error;
+        }
+        break;
+      default:
+        break;
+      }
+    }
+    wfd->alive = TRUE;
+    wfd->access = access;
+    /* The thread will be stared immediately, and will go into wait upon
+     * the wfd->overlapped[ANON_PIPE_THREAD_POLL_EVENT].hEvent (which is
+     * disabled at creation) soon after that
+     */
+    /* Reading pipes must start reading immediately */
+    if ((wfd->access & GENERIC_READ) && !(wfd->access & GENERIC_WRITE))
+    {
+      wfd->readbuffer_read_pos = 0;
+      wfd->readbuffer_write_pos = -1;
+      wfd->readbuffer = GNUNET_malloc (1024);
+      wfd->readbuffer_size = 1024;
+      wfd->work = 0;
+    }
+    {
+      ResetEvent (wfd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent);
+#if DEBUG_W32IO_THREADS
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Calling CreateThread()...\n");
+#endif
+      SetLastError (0);
+      wfd->anon_thread = CreateThread (NULL, 0, w32io_anonymous_pipe_thread_func, (LPVOID) wfd, 0, &threadID);
+      error_code = GetLastError ();
+      /* CreateThread might succeed, but the thread might fail AFTER
+       * it is created, trapping us in a later wait call forever.
+       * Instead we'll wait for 5ms (should trigger a context switch),
+       * then check that the thread IS alive with GetExitCodeThread().
+       */
+      thread_error = STILL_ACTIVE;
+      if (wfd->anon_thread != NULL)
+      {
+#if DEBUG_W32IO_THREADS
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Checking thread %08X %d...\n", wfd->anon_thread, threadID);
+#endif
+        WaitForSingleObject (wfd->anon_thread, 5);
+        GetExitCodeThread (wfd->anon_thread, &thread_error);
+#if DEBUG_W32IO_THREADS
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Thread exit code is %d.\n", thread_error);
+#endif
+      }
+      if (wfd->anon_thread == NULL || error_code != NO_ERROR || thread_error != STILL_ACTIVE)
+      {
+        if (thread_error == 0)
+        {
+#if DEBUG_W32IO_THREADS
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Thread completed its work in-place\n");
+#endif
+          SetEvent (wfd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent);
+        }
+        else
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "CreateThread() returned %d, thread status is %d, GLE: %d\n", wfd->anon_thread, thread_error, error_code);
+          goto error;
+        }
+      }
+      tw[0] = wfd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent;
+      tw[1] = wfd->anon_thread;
+#if DEBUG_W32IO_THREADS
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Waiting on %08X or %08X...\n", tw[0], tw[1]);
+#endif
+      if ((error_code = WaitForMultipleObjects (2, tw, FALSE, 1000)) != WAIT_OBJECT_0)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to wait for the worker thread to initialize, wait function returned %d, GLE: %d\n", error_code, GetLastError());
+        goto error;
+      }
+      else
+      {
+#if DEBUG_W32IO_THREADS
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Done waiting.\n");
+#endif
+      }
+    }
+    if ((writeable && (access & GENERIC_WRITE)) || (readable && (access & GENERIC_READ)))
+    {
+      SetLastError (0);
+      bret = SetEvent (wfd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent);
+      error_code = GetLastError ();
+      if (error_code != NO_ERROR || !bret)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "SetEvent() returned %d. GLE: %d\n", bret, error_code);
+        goto error;
+      }
+    }
+    else if (thread_error == STILL_ACTIVE)
+    {
+      ResetEvent (wfd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent);
+    }
+    break;
+  case GNUNET_W32IO_CONSOLE:
+    /* It's a console handle or a CRT file descriptor.
+     * FIXME: does it support async I/O? Use threads?
+     */
+    break;
+  case GNUNET_W32IO_SOCKET:
+    for (i = 0; i < POLLLAST; i++) 
+    {
+      switch (i)
+      {
+      case SOCKET_POLL_EVENT:
+      case SOCKET_WAKEUP_EVENT:
+      case SOCKET_OVERLAPPED_WRITE_EVENT:
+      case POLLHUP_BIT:
+      case POLLERR_BIT:
+      case POLLNVAL_BIT:
+        SetLastError (0);
+        wfd->overlapped[i].hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
+        error_code = GetLastError ();
+        if (wfd->overlapped[i].hEvent == INVALID_HANDLE_VALUE || error_code != NO_ERROR)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "CreateEvent() returned %d. GLE: %d\n", wfd->overlapped[i].hEvent, error_code);
+          goto error;
+        }
+        break;
+      default:
+        break;
+      }
+      if (i == SOCKET_POLL_EVENT)
+      {
+        /* Bind wfd->overlapped[SOCKET_POLL_EVENT].hEvent object to the socket wfd->fd.
+         * It will be set when one of the events from sockevents occurrs
+         * This call clears internal socket event record in wfd->fd, so
+         * any one-time events (events that are recorded only once per
+         * occurrence) will be lost. To preserve them an internal event field
+         * in W32Fd is used.
+         */
+        SetLastError (0);
+        bret = WSAEventSelect ((SOCKET) wfd->fd, wfd->overlapped[SOCKET_POLL_EVENT].hEvent, FD_ALL_EVENTS);
+        error_code = GetLastError ();
+        if (bret != 0 || error_code != NO_ERROR)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "WSAEventSelect() returned %d. GLE: %d\n", bret, error_code);
+          goto error;
+        }
+      }
+    }
+    if (connected)
+    {
+      if (writeable && (access & GENERIC_WRITE))
+      {
+        wfd->wsaevents.lNetworkEvents |= FD_WRITE;
+        SetEvent (wfd->overlapped[SOCKET_WAKEUP_EVENT].hEvent);
+      }
+      if (readable && (access & GENERIC_READ))
+      {
+        wfd->wsaevents.lNetworkEvents |= FD_READ;
+        SetEvent (wfd->overlapped[SOCKET_WAKEUP_EVENT].hEvent);
+      }
+    }
+    wfd->access = access;
+    break;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Wrong value returned from GNUNET_W32IO_find_handle_type()\n");
+    goto error;
+  }
+  goto end;
+error:
+  for (i = 0; i < POLLLAST; i++)
+    if (wfd->overlapped[i].hEvent != INVALID_HANDLE_VALUE)  
+      CloseHandle (wfd->overlapped[i].hEvent);
+  if (wfd->anon_thread != INVALID_HANDLE_VALUE)
+    CloseHandle (wfd->anon_thread);
+  if (wfd->anon_thread_mutex != INVALID_HANDLE_VALUE)
+    CloseHandle (wfd->anon_thread_mutex);
+  GNUNET_free (wfd);
+  wfd = NULL;
+end:
+  return wfd;
+}
+
+int
+GNUNET_W32IO_fd_from_handle (HANDLE h, GNUNET_W32IO_HandleType htype, DWORD access,
+    int connected, int writeable, int readable)
+{
+  struct W32Fd *fd = w32io_fd_from_handle (h, htype, access, connected, writeable, readable);
+  if (fd != NULL && fd != INVALID_POLL_FD)
+    return w32io_insert_fd (fd);
+  return -1;
+}
+
+
+int
+w32io_read_async_named_pipe (struct W32Fd *fd, void *in, size_t to_read)
+{
+  BOOL bret;
+  DWORD dwret;
+  int ret = to_read;
+  while (to_read > 0) {
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ReadFile (%x, in, %d, &dwret, &fd->overlapped[POLLIN_BIT]);\n", fd->fd, to_read);
+#endif
+    ZeroOverlappedExceptEvent(fd->overlapped[POLLIN_BIT]);
+    bret = ReadFile (fd->fd, in, to_read, &dwret,
+        &fd->overlapped[POLLIN_BIT]);
+    if (bret == 0)
+    {
+      dwret = GetLastError ();
+      if (dwret == ERROR_BROKEN_PIPE || dwret == ERROR_PIPE_NOT_CONNECTED) {
+        errno = EPIPE;
+        SetEvent (fd->overlapped[POLLHUP_BIT].hEvent);
+        return 0;
+      }
+
+      /* TODO: figure out when it is appropriate to enable [POLLERR_BIT].hEvent */
+      if (dwret != ERROR_IO_PENDING)
+        goto error_and_fail;
+#if DEBUG_W32IO
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "WaitForSingleObject (%x, INFINITE);\n", fd->overlapped[POLLIN_BIT].hEvent);
+#endif
+      dwret = WaitForSingleObject (fd->overlapped[POLLIN_BIT].hEvent,
+          INFINITE);
+#if DEBUG_W32IO
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done\n");
+#endif
+      if (dwret != WAIT_OBJECT_0)
+      {
+        dwret = GetLastError ();
+        goto error_and_fail;
+      }
+#if DEBUG_W32IO
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GetOverlappedResult (%x, &fd->overlapped[POLLIN_BIT], &dwret, TRUE);\n", fd->fd);
+#endif
+      bret = GetOverlappedResult ((HANDLE) fd->fd,
+          &fd->overlapped[POLLIN_BIT], &dwret, TRUE);
+#if DEBUG_W32IO
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got it\n");
+#endif
+      if (bret == 0)
+      {
+        dwret = GetLastError ();
+        goto error_and_fail;
+      }
+    }
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Read %d bytes\n", dwret);
+#endif
+    to_read -= dwret;
+    in += dwret;
+  }
+#if 0
+  /* If can't peek or pipe is empty - mark the pipe as unreadable.
+   * This will only affect the application if it actually checks fd for
+   * readability. It won't prevent subsequent calls to _read() from blocking.
+   */
+  if (!PeekNamedPipe ((HANDLE) fd->fd, NULL, 0, 0, &dwret, NULL) || !dwret) {
+    fd->revents &= ~FD_READ;
+    fd->wsaevents.lNetworkEvents &= ~FD_READ;
+  }
+#endif
+  return ret;
+
+error_and_fail:
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to read\n");
+  SetErrnoFromWinError (dwret);
+  return -1;
+}
+
+int
+w32io_write_async_named_pipe (struct W32Fd *fd, const void *out, size_t to_write)
+{
+  BOOL bret;
+  DWORD dwret;
+  DWORD ret;
+
+  /* writebuffer isn't NULL -> there's a writing operation going on */
+  if (fd->wrbuffer != NULL) {
+    /* Wait until event is set (meaning that operation is complete).
+     * This might block for a while (until the other end reads), that is - 
+     * you can't have more than one writing operation working at one pipe.
+     * This is somewhat mitigated by the pipe buffer (which is better be > 0).
+     * TODO: implement multiple buffering, so that it is possible to write
+     * more than once (especially if we're talking about writing small
+     * amounts of data multiple times).
+     */
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "WaitForSingleObject (%x, INFINITE);\n", fd->overlapped[POLLOUT_BIT].hEvent);
+#endif
+    if (WaitForSingleObject (fd->overlapped[POLLOUT_BIT].hEvent, INFINITE) ==
+        WAIT_OBJECT_0)
+    {
+      /* Get the operation result, free the buffer */
+      DWORD wait_ret;
+#if DEBUG_W32IO
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GetOverlappedResult (%x, %x, %x, TRUE);\n", fd->fd, &fd->overlapped[POLLOUT_BIT], &wait_ret);
+#endif
+      ret = GetOverlappedResult ((HANDLE) fd->fd,
+          &fd->overlapped[POLLOUT_BIT], &wait_ret, TRUE);
+#if DEBUG_W32IO
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got it\n");
+#endif
+      if (fd->wrbuffer) {
+        GNUNET_free (fd->wrbuffer->buf);
+        GNUNET_free (fd->wrbuffer);
+        fd->wrbuffer = NULL;
+      }
+
+      if (ret == 0) {
+        errno = EIO;
+        return -1;
+      }
+    }
+  }
+
+  if (out)
+  {
+    fd->wrbuffer = GNUNET_malloc (sizeof (WSABUF));
+    fd->wrbuffer->buf = memcpy (GNUNET_malloc (to_write), out, to_write);
+    fd->wrbuffer->len = to_write;
+  }
+#if DEBUG_W32IO
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "WriteFile (%x, %x, %d, NULL, %x);\n", fd->fd, fd->wrbuffer->buf, to_write, &fd->overlapped[POLLOUT_BIT]);
+#endif
+  ZeroOverlappedExceptEvent(fd->overlapped[POLLOUT_BIT]);
+  bret = WriteFile ((HANDLE) fd->fd, fd->wrbuffer->buf, to_write, NULL,
+      &fd->overlapped[POLLOUT_BIT]);
+  if (bret == 0) {
+    dwret = GetLastError ();
+    if (dwret != ERROR_IO_PENDING)
+      goto error_and_fail;
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Wrote into heap buffer\n");
+#endif
+  } else {
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Wrote into kernel buffer\n");
+#endif
+    GNUNET_free (fd->wrbuffer->buf);
+    GNUNET_free (fd->wrbuffer);
+    fd->wrbuffer = NULL;
+  }
+  return to_write;
+
+error_and_fail:
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to write\n");
+  GNUNET_free (fd->wrbuffer->buf);
+  GNUNET_free (fd->wrbuffer);
+  fd->wrbuffer = NULL;
+  SetErrnoFromWinError (dwret);
+  return -1;
+}
+
+int
+w32io_recv (struct W32Fd *fd, void *buffer, size_t length, int flags)
+{
+  int ret;
+  switch (fd->fd_type)
+  {
+  case GNUNET_W32IO_SOCKET:
+    ret = recv ((SOCKET) fd->fd, buffer, length, flags);
+    if (ret == SOCKET_ERROR)
+    {
+      DWORD error_code = GetLastError ();
+      if (error_code == WSAEWOULDBLOCK)
+        fd->wsaevents.lNetworkEvents &= ~FD_READ;
+      SetErrnoFromWinError (error_code);
+    }
+    else
+    {
+      fd->wsaevents.lNetworkEvents &= ~FD_READ;
+      fd->wsaevents.iErrorCode[FD_READ] = 0;
+    }
+    return ret;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Can't recv() - fd is not a socket\n");
+    return 0;
+  }
+}
+
+int
+GNUNET_W32IO_recv (int fd, void *buffer, size_t length, int flags)
+{
+  return w32io_recv (w32io_fetch_fd (fd), buffer, length, flags);
+}
+
+int
+w32io_recvfrom (struct W32Fd *fd, void *buffer, size_t length, int flags, struct sockaddr *address, int *address_len)
+{
+  int ret;
+  switch (fd->fd_type)
+  {
+  case GNUNET_W32IO_SOCKET:
+    ret = recvfrom ((SOCKET) fd->fd, buffer, length, flags, address, address_len);
+    if (ret == SOCKET_ERROR)
+    {
+      DWORD error_code = GetLastError ();
+      if (error_code == WSAEWOULDBLOCK)
+        fd->wsaevents.lNetworkEvents &= ~FD_READ;
+      SetErrnoFromWinError (error_code);
+    }
+    else
+    {
+      fd->wsaevents.iErrorCode[FD_READ] = 0;
+    }
+    return ret;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Can't recvfrom() - fd is not a socket\n");
+    return 0;
+  }
+}
+
+int
+GNUNET_W32IO_recvfrom (int fd, void *buffer, size_t length, int flags, struct sockaddr *address, int *address_len)
+{
+  return w32io_recvfrom (w32io_fetch_fd (fd), buffer, length, flags, address, address_len);
+}
+
+int
+w32io_send_async (struct W32Fd *fd, const void *buffer, size_t length, int flags)
+{
+  int ret;
+  DWORD error_code;
+  if (fd->wrbuffer)
+  {
+    DWORD t,r;
+    DWORD wait_ret = WaitForSingleObject (fd->overlapped[SOCKET_OVERLAPPED_WRITE_EVENT].hEvent, INFINITE);
+    if (wait_ret == WAIT_OBJECT_0)
+      WSAGetOverlappedResult ((SOCKET) fd->fd, &fd->overlapped[SOCKET_OVERLAPPED_WRITE_EVENT], &t, TRUE, &r);
+    GNUNET_free (fd->wrbuffer->buf);
+    GNUNET_free (fd->wrbuffer);
+    fd->wrbuffer = NULL;
+  }
+  fd->wrbuffer = GNUNET_malloc (sizeof (WSABUF));
+  fd->wrbuffer->buf = GNUNET_malloc (length);
+  fd->wrbuffer->len = length;
+  memcpy (fd->wrbuffer->buf, buffer, length);
+  SetLastError (0);
+  ret = WSASend ((SOCKET) fd->fd, fd->wrbuffer, 1, NULL, 0, &fd->overlapped[SOCKET_OVERLAPPED_WRITE_EVENT], NULL);
+  error_code = GetLastError ();
+  if (ret == -1)
+  {
+    if (error_code == WSA_IO_PENDING)
+      ret = length;
+    else
+    {
+      SetEvent (fd->overlapped[SOCKET_OVERLAPPED_WRITE_EVENT].hEvent);
+      SetErrnoFromWinError (error_code);
+    }
+  }
+  return ret;
+}
+
+int
+w32io_send (struct W32Fd *fd, const void *buffer, size_t length, int flags)
+{
+  int ret;
+  switch (fd->fd_type)
+  {
+  case GNUNET_W32IO_SOCKET:
+    ret = send ((SOCKET) fd->fd, buffer, length, flags);
+    if (ret == SOCKET_ERROR)
+    {
+      DWORD error_code = GetLastError ();
+      if (error_code == WSAEWOULDBLOCK)
+      {
+        fd->wsaevents.lNetworkEvents &= ~FD_WRITE;
+        ret = w32io_send_async (fd, buffer, length, flags);
+      }
+      else
+        SetErrnoFromWinError (error_code);
+    }
+    else
+    {
+      fd->wsaevents.iErrorCode[FD_WRITE] = 0;
+    }
+    return ret;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Can't send() - fd is not a socket\n");
+    return 0;
+  }
+}
+
+int
+GNUNET_W32IO_send (int fd, const void *buffer, size_t length, int flags)
+{
+  return w32io_send (w32io_fetch_fd (fd), buffer, length, flags);
+}
+
+int
+w32io_sendto (struct W32Fd *fd, const void *buffer, size_t length, int flags, const struct sockaddr *address, int address_len)
+{
+  int ret;
+  switch (fd->fd_type)
+  {
+  case GNUNET_W32IO_SOCKET:
+    ret = sendto ((SOCKET) fd->fd, buffer, length, flags, address, address_len);
+    if (ret == SOCKET_ERROR)
+    {
+      DWORD error_code = GetLastError ();
+      if (error_code == WSAEWOULDBLOCK)
+        fd->wsaevents.lNetworkEvents &= ~FD_WRITE;
+      SetErrnoFromWinError (error_code);
+    }
+    else
+    {
+      fd->wsaevents.iErrorCode[FD_WRITE] = 0;
+    }
+    return ret;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Can't sendto() - fd is not a socket\n");
+    return 0;
+  }
+}
+
+int
+GNUNET_W32IO_sendto (int fd, const void *buffer, size_t length, int flags, const  struct sockaddr *address, int address_len)
+{
+  return w32io_sendto (w32io_fetch_fd (fd), buffer, length, flags, address, address_len);
+}
+
+int
+w32io_connect (struct W32Fd *fd, const struct sockaddr *name,
+    int namelen)
+{
+  int ret;
+  DWORD error_code;
+  switch (fd->fd_type)
+  {
+  case GNUNET_W32IO_SOCKET:
+    SetLastError (0);
+    ret = WSAConnect ((SOCKET) fd->fd, name, namelen, NULL, NULL, NULL, NULL);
+    error_code = GetLastError ();
+    if (ret == SOCKET_ERROR && error_code != WSAEWOULDBLOCK)
+    {
+      SetErrnoFromWinError (GetLastError());
+    }
+    else
+    {
+      if (error_code == WSAEWOULDBLOCK)
+        errno = EINPROGRESS;
+      fd->wsaevents.lNetworkEvents &= ~FD_CONNECT;
+      fd->wsaevents.iErrorCode[FD_CONNECT] = 0;
+    }
+    return ret;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Can't connect() - fd is not a socket\n");
+    return 0;
+  }
+}
+
+int
+GNUNET_W32IO_connect (int fd, const struct sockaddr *name,
+    int namelen)
+{
+  return w32io_connect (w32io_fetch_fd (fd), name, namelen);
+}
+
+int
+w32io_accept (struct W32Fd *fd, struct sockaddr *name, int *namelen)
+{
+  SOCKET ret;
+  DWORD error_code;
+  switch (fd->fd_type)
+  {
+  case GNUNET_W32IO_SOCKET:
+    SetLastError (0);
+    ret = WSAAccept ((SOCKET) fd->fd, name, namelen, NULL, 0);
+    error_code = GetLastError ();
+    if (ret == SOCKET_ERROR)
+    {
+      if (error_code == WSAEWOULDBLOCK)
+      {
+        fd->wsaevents.lNetworkEvents &= ~FD_ACCEPT;
+        fd->wsaevents.iErrorCode[FD_ACCEPT] = 0;
+      }
+      SetErrnoFromWinError (GetLastError());
+    }
+    else
+    {
+      fd->wsaevents.lNetworkEvents &= ~FD_ACCEPT;
+      fd->wsaevents.iErrorCode[FD_ACCEPT] = 0;
+    }
+    return ret;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Can't accept() - fd is not a socket\n");
+    return 0;
+  }
+}
+
+int
+GNUNET_W32IO_accept (int fd, struct sockaddr *name, int *namelen)
+{
+  SOCKET s = w32io_accept (w32io_fetch_fd (fd), name, namelen);
+  if (s != INVALID_SOCKET)
+    return GNUNET_W32IO_fd_from_handle ((HANDLE) s, GNUNET_W32IO_SOCKET, GENERIC_READ | GENERIC_WRITE, 1, 1, 0);
+  return s;
+}
+
+int
+w32io_bind (struct W32Fd *fd, const struct sockaddr *name, int namelen)
+{
+  int ret;
+  switch (fd->fd_type)
+  {
+  case GNUNET_W32IO_SOCKET:
+    ret = bind ((SOCKET) fd->fd, name, namelen);
+    if (ret == SOCKET_ERROR)
+    {
+      DWORD error_code = GetLastError ();
+      SetErrnoFromWinError (error_code);
+    }
+    return ret;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Can't bind() - fd is not a socket\n");
+    return 0;
+  }
+}
+
+int
+GNUNET_W32IO_bind (int fd, const struct sockaddr *name, int namelen)
+{
+  return w32io_bind (w32io_fetch_fd (fd), name, namelen);
+}
+
+int
+w32io_listen (struct W32Fd *fd, int backlog)
+{
+  int ret;
+  switch (fd->fd_type)
+  {
+  case GNUNET_W32IO_SOCKET:
+    ret = listen ((SOCKET) fd->fd, backlog);
+    if (ret == SOCKET_ERROR)
+    {
+      SetErrnoFromWinError (GetLastError());
+    }
+    else
+    {
+      fd->wsaevents.lNetworkEvents &= ~(FD_READ | FD_WRITE | FD_ACCEPT | FD_CONNECT);
+      fd->wsaevents.iErrorCode[FD_READ] = 0;
+      fd->wsaevents.iErrorCode[FD_WRITE] = 0;
+      fd->wsaevents.iErrorCode[FD_ACCEPT] = 0;
+      fd->wsaevents.iErrorCode[FD_CONNECT] = 0;
+    }
+    return ret;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Can't listen() - fd is not a socket\n");
+    return 0;
+  }
+}
+
+int
+GNUNET_W32IO_listen (int fd, int backlog)
+{
+  return w32io_listen (w32io_fetch_fd (fd), backlog);
+}
+
+/**
+ * Anonymous pipes on NT do not support asynchronous operations, which is
+ * why we need a separate thread to perform writing and reading operations,
+ * and the state of this thread can be easily checked by waiting upon
+ * an event object.
+ */
+DWORD __stdcall
+w32io_anonymous_pipe_thread_func (void *data)
+{
+  struct W32Fd *wfd = (struct W32Fd *) data;
+  HANDLE h[2];
+  void *tmp_buffer = NULL;
+  DWORD tmp_written, dw_error;
+  int towrite = 0;
+
+  int rpos;
+  int wpos;
+  int rb;
+  size_t tmp_size;
+
+  HANDLE tmp_fd = wfd->fd;
+  HANDLE die_event;
+  HANDLE mutex;
+  BOOL bret;
+  /* Duplication will increase the reference count on the event, so even if
+   * the main thread closes it, it will live on.
+   * The Main thread will enable it before freeing the data related to
+   * this thread. If it is enabled, assume wfd to point to a freed location,
+   * and all handles and events (except die_event and mutex) to be closed.
+   */
+  DuplicateHandle(GetCurrentProcess(), wfd->overlapped[ANON_PIPE_CLOSE_POLL_EVENT].hEvent,
+      GetCurrentProcess(), &die_event, 0, FALSE, DUPLICATE_SAME_ACCESS);
+  DuplicateHandle(GetCurrentProcess(), wfd->anon_thread_mutex,
+      GetCurrentProcess(), &mutex, 0, FALSE, DUPLICATE_SAME_ACCESS);
+  h[0] = wfd->overlapped[ANON_PIPE_THREAD_POLL_EVENT].hEvent;
+  h[1] = mutex;
+/*#if DEBUG_W32IO_THREADS
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "locking\n");
+#endif*/
+  WaitForSingleObject (mutex, INFINITE);
+
+  if (wfd->work == 0)
+  {
+    tmp_buffer = GNUNET_malloc (wfd->readbuffer_size);
+    rpos = 0;
+    wpos = -1;
+    tmp_size = wfd->readbuffer_size;
+    rb = 0;
+  }
+/*#if DEBUG_W32IO_THREADS
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "locked\n");
+#endif*/
+  while (die_event != 0 && (WaitForSingleObject (die_event, 0) == WAIT_TIMEOUT) && wfd->alive)
+  {
+    while (die_event != 0 && (WaitForSingleObject (die_event, 0) == WAIT_TIMEOUT) && wfd->work < 0)
+    {
+/*#if DEBUG_W32IO_THREADS
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "waiting\n");
+#endif*/
+      ResetEvent (h[0]);
+      ReleaseMutex (h[1]);
+      SetEvent (wfd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent);
+      WaitForMultipleObjects(2, h, TRUE, INFINITE);
+/*#if DEBUG_W32IO_THREADS
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done waiting\n");
+#endif*/
+    }
+    if (die_event != 0 && (WaitForSingleObject (die_event, 0) != WAIT_TIMEOUT))
+    {
+      CloseHandle (die_event);
+      die_event = 0;
+      break;
+    }
+    switch (wfd->work) 
+    {
+    case 0: /* read */
+      SetEvent (wfd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent);
+      while (die_event != 0 && wfd->alive)
+      {
+        DWORD dwret, wait_ret;
+        /* At this point we've locked the mutex. */
+        while ((wpos == rpos - 1 && wpos >= 0) || (wpos == tmp_size - 1 && rpos == 0))
+        {
+          /* Buffer is full (we're about to re-write a byte that isn't yet
+           * consumed by the main thread) */
+          if (rb > 0)
+          {
+            /* And the main thread asked for more data than we could hold - grow the buffer */
+            void *new_buffer = NULL;
+            size_t new_buffer_size = tmp_size + rb;
+            new_buffer = GNUNET_malloc (new_buffer_size);
+            memcpy (new_buffer, &((char *) tmp_buffer)[rpos], tmp_size - rpos);
+            memcpy (&((char *) new_buffer)[tmp_size - rpos], tmp_buffer, rpos);
+            rpos = 0;
+            if (wpos >= 0)
+              wpos = tmp_size - 1;
+            GNUNET_free (tmp_buffer);
+            tmp_buffer = new_buffer;
+            tmp_size = new_buffer_size;
+            GNUNET_free (wfd->readbuffer);
+            wfd->readbuffer = tmp_buffer;
+            wfd->readbuffer_size = tmp_size;
+            wfd->readbuffer_read_pos = rpos;
+            wfd->readbuffer_write_pos = wpos;
+            wfd->bytes_read = rb;
+          }
+          else
+          {
+            /* And the main thread didn't ask for more data - wait until some
+             * data is consumed or until the main thread asks for more.
+             */
+            SetEvent (wfd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent);
+            ResetEvent (h[0]);
+            ReleaseMutex (h[1]);
+/*#if DEBUG_W32IO_THREADS
+            GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "waiting for consumer\n");
+#endif*/
+            WaitForMultipleObjects(2, h, TRUE, INFINITE);
+/*#if DEBUG_W32IO_THREADS
+            GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done waiting for consumer\n");
+#endif*/
+          }
+        }
+        if (WaitForSingleObject (die_event, 0) == WAIT_TIMEOUT)
+        {
+          SetEvent (wfd->overlapped[ANON_PIPE_CONFIRM_POLL_EVENT].hEvent);
+          /* Stash the write pos, we can't read it from wfd while the
+           * mutex is not locked by us.
+           */
+          wpos = wfd->readbuffer_write_pos;
+          /* Let the main thread consume some data while we are reading. */
+          ReleaseMutex (h[1]);
+/*#if DEBUG_W32IO_THREADS
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "anonymous read %x %d\n", wfd->fd, 1);
+#endif*/
+          /* Read one byte */
+          bret = ReadFile (tmp_fd, &((char *) tmp_buffer)[wpos + 1], 1, &dwret, NULL);
+#if DEBUG_W32IO_THREADS
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done, read %d bytes to `%02x'\n", dwret, ((char *) tmp_buffer)[wpos + 1]);
+#endif
+        }
+        else
+        {
+          bret = 1;
+        }
+        if (bret == 0)
+        {
+          dw_error = GetLastError ();
+        }
+        if (die_event != 0 && WaitForSingleObject (die_event, 0) == WAIT_TIMEOUT)
+        {
+        /* Lock the mutex */
+/*#if DEBUG_W32IO_THREADS
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "locking after reading\n");
+#endif*/
+          wait_ret = WaitForSingleObject (h[1], INFINITE);
+/*#if DEBUG_W32IO_THREADS
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "locked after reading\n");
+#endif*/
+          if (dw_error == ERROR_BROKEN_PIPE)
+          {
+            wfd->alive = 0;
+          }
+          wfd->bret = bret;
+          wfd->dwerror = dw_error;
+          ((char *) wfd->readbuffer)[wpos + 1] = ((char *) tmp_buffer)[wpos + 1];
+          /* Advance write position */
+          wfd->readbuffer_write_pos += dwret;
+          /* Reduce the number of bytes that the main thread wants us to read */
+          wfd->bytes_read -= dwret;
+          if (wfd->bytes_read <= 0)
+          {
+            SetEvent (wfd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent);
+          }
+          rpos = wfd->readbuffer_read_pos;
+          wpos = wfd->readbuffer_write_pos;
+          rb = wfd->bytes_read;
+        }
+        else if (die_event != 0)
+        {
+          CloseHandle (die_event);
+          die_event = 0;
+        }
+        /* If the main thread was waiting for us to read enough bytes, this will
+         * wake it up. wfd->bytes_read CAN go negative,
+         * as deep as -wfd->readbuffer_size (which means that the whole buffer
+         * is filled with read-ahead data).
+         * The main thread appends to wfd->bytes_read the number of bytes it
+         * wishes to read, and sleeps if wfd->bytes_read becomes positive.
+         */
+      }
+      break;
+    case 1: /* write */
+/*#if DEBUG_W32IO_THREADS
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "anonymous write %x %d\n", wfd->fd, wfd->wrbuffer->len);
+#endif*/
+      tmp_buffer = memcpy (GNUNET_malloc (wfd->wrbuffer->len), wfd->wrbuffer->buf, wfd->wrbuffer->len);
+      towrite = wfd->wrbuffer->len;
+      SetEvent (wfd->overlapped[ANON_PIPE_CONFIRM_POLL_EVENT].hEvent);
+      bret = WriteFile (tmp_fd, tmp_buffer, towrite, &tmp_written, NULL);
+/*#if DEBUG_W32IO_THREADS
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done, write %d\n", wfd->bytes_written);
+#endif*/
+      if (bret == 0)
+      {
+        dw_error = GetLastError ();
+      }
+      GNUNET_free (tmp_buffer);
+      if (WaitForSingleObject (die_event, 0) == WAIT_TIMEOUT)
+      {
+        wfd->bytes_written = tmp_written;
+        wfd->bret = bret;
+        wfd->dwerror = dw_error;
+      }
+      else
+      {
+        CloseHandle (die_event);
+        die_event = 0;
+      }
+      break;
+    case 2: /* close */
+      wfd->alive = FALSE;
+      SetEvent (wfd->overlapped[POLLHUP_BIT].hEvent);
+      break;
+    default:
+      continue;
+    }
+    if (die_event != 0)
+      wfd->work = -1;
+  }
+/*#if DEBUG_W32IO_THREADS
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "thread is about to exit\n");
+#endif*/
+  if (die_event != 0)
+  {
+    ResetEvent (h[0]);
+    SetEvent (wfd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent);
+    SetEvent (die_event);
+    CloseHandle (die_event);
+  }
+  else
+    CloseHandle (tmp_fd);
+  CloseHandle (mutex);
+  return 0;
+}
+
+int
+w32io_anonymous_pipe_read (struct W32Fd *fd, void *in, size_t to_read)
+{
+  BOOL bret;
+  DWORD dwret;
+  int ret = to_read;
+  HANDLE h[2];
+  h[0] = fd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent;
+  h[1] = fd->anon_thread_mutex;
+#if DEBUG_W32IO
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "locking\n");
+#endif
+  /* First, lock the mutex. It is available while the worker thread
+   * either waits (its buffer is full) or reads (can't access anything
+   * other than the free bytes in the buffer - no race conditions on that)
+   */
+  WaitForSingleObject (fd->anon_thread_mutex, INFINITE);
+/*
+  fd->work = 0;
+  fd->readbuffer = in;
+  fd->to_read = to_read;
+*/
+
+  /* "Read" to_read bytes from the buffer */
+  fd->bytes_read += to_read;
+  if (fd->bytes_read > 0 && fd->alive)
+  {
+    /* bytes_read is > 0 - we did not have enough bytes in the buffer */
+    /* Release the mutex, wait for the mutex and the signal that the
+     * buffer is filled.
+     */
+    ResetEvent (h[0]);
+    ReleaseMutex (h[1]);
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "waiting\n");
+#endif
+    WaitForMultipleObjects (2, h, TRUE, INFINITE);
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done waiting\n");
+#endif
+  }
+  if (fd->bytes_read > 0)
+  {
+    /* bytes_read is > 0 - we were fd-bytes_read short when we hit EOF */
+    /* If fd->alive was false, we will have here bytes_read == to_read,
+     * making it ret = 0, otherwise its a positive integer < to_read
+     */
+    ret = to_read - fd->bytes_read;
+    /* for the next read()-after-EOF */
+    fd->bytes_read = 0;
+  }
+  else
+    /* bytes_read is <= 0 - we had enough bytes in the buffer */
+    ret = to_read;
+  if (ret > 0)
+  {
+    dwret = fd->readbuffer_read_pos + ret;
+    if (dwret <= fd->readbuffer_size)
+    {
+      memcpy (in, &((char *) fd->readbuffer)[fd->readbuffer_read_pos], dwret);
+    }
+    else
+    {
+      memcpy ((char *) in, &((char *) fd->readbuffer)[fd->readbuffer_read_pos], fd->readbuffer_size - fd->readbuffer_read_pos);
+      memcpy (&((char *) in)[fd->readbuffer_size - fd->readbuffer_read_pos], fd->readbuffer, ret - (fd->readbuffer_size - fd->readbuffer_read_pos));
+    }
+    fd->readbuffer_read_pos += ret;
+    if (fd->readbuffer_read_pos >= fd->readbuffer_size)
+      fd->readbuffer_read_pos -= fd->readbuffer_size;
+  }
+  bret = fd->bret;
+  dwret = fd->dwerror;
+  /* Let the worker thread continue */
+#if DEBUG_W32IO
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "unlocking\n");
+#endif
+  ReleaseMutex (h[1]);
+
+  if (ret == 0)
+  {
+    if (dwret == ERROR_BROKEN_PIPE) {
+      errno = EPIPE;
+      return 0;
+    }
+    goto error_and_fail;
+  }
+#if 0
+  /* Mark the pipe as unreadable, because we won't know if it has any data to
+   * read until we wait on it. Of course, that will not prevent the application
+   * from trying to read it, but reading might block.
+   */
+  fd->wsaevents.lNetworkEvents &= ~FD_READ;
+  fd->revents &= ~FD_READ;
+#endif
+  /* SetEvent (fd->overlapped[FD_READ_BIT].hEvent); */
+  return ret;
+
+error_and_fail:
+  SetErrnoFromWinError (dwret);
+  return -1;
+}
+
+int
+w32io_anonymous_pipe_write (struct W32Fd *fd, const void *out, size_t to_write)
+{
+  BOOL bret;
+  DWORD dwret;
+  int ret = to_write;
+  HANDLE h[2];
+  h[0] = fd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent;
+  h[1] = fd->anon_thread_mutex;
+#if DEBUG_W32IO
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "locking\n");
+#endif
+  WaitForSingleObject (fd->anon_thread_mutex, INFINITE);
+  /* We've locked the mutex - which means that worker thread is not
+   * working at the moment. If the thread was writing at the moment of
+   * locking, g_mutex_lock() will block until writing is complete, then
+   * the worker thread will unlock for a short time, letting us get
+   * the lock.
+   */
+  if (fd->wrbuffer)
+  {
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "freeing the buffer\n");
+#endif
+    /* We've been writing somethings */
+    GNUNET_free (fd->wrbuffer->buf);
+    GNUNET_free (fd->wrbuffer);
+    fd->wrbuffer = NULL;
+
+    /* Process any error conditions from previous write operation */
+    bret = fd->bret;
+    dwret = fd->bytes_written;
+    if (bret == 0)
+    {
+      dwret = fd->dwerror;
+      if (dwret == ERROR_BROKEN_PIPE) {
+        errno = EPIPE;
+        return -1;
+      }
+      goto error_and_fail;
+    }
+  }
+
+  fd->work = 1; /* write */
+  fd->wrbuffer = GNUNET_malloc (sizeof (WSABUF));
+  fd->wrbuffer->buf = memcpy (GNUNET_malloc (to_write), out, to_write);
+  fd->wrbuffer->len = to_write;
+#if DEBUG_W32IO
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "signalling\n");
+#endif
+  SetEvent (fd->overlapped[ANON_PIPE_THREAD_POLL_EVENT].hEvent);
+  /* We've signaled the worker thread condition. Once we unlock the mutex,
+   * the worker thread will wake up.
+   */
+#if DEBUG_W32IO
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "unlocking\n");
+#endif
+  /* Unlock the mutex and let the worker thread do its thing. Return
+   * to_write, while actual writing takes place in background.
+   * If another write is attempted while thread is busy, it will block.
+   * And any other operation will block too, of course.
+   */
+  ReleaseMutex (fd->anon_thread_mutex);
+  /* Wait until the worker thead acknowledges the write request.
+   * Otherwise it would have been possible to overwrite one write
+   * request with another, because the worker thread didn't have an opportunity
+   * to wake up and block/lock on the first request
+   */
+  WaitForSingleObject (fd->overlapped[ANON_PIPE_CONFIRM_POLL_EVENT].hEvent, INFINITE);
+
+  /* We will get errorneous condition eventually, if we do another
+   * (blocking) write or wait, but not immediately.
+   * That happens because of the assumption we make about I/O things:
+   * It is always writable no matter what, but it is only readable when
+   * there is data to read. Real I/O things may not be like that -
+   * they may return an error while writing takes place.
+   * So you should assume that this function will return an error only
+   * when errorneous condition is obvious (wrong fd or a pipe broken
+   * during previous operation).
+   */
+  
+#if 0
+  /* Mark the pipe as unwritable. Of course, that will not prevent the
+   * application from trying to write into it, but writing might block.
+   */
+  
+  fd->wsaevents.lNetworkEvents &= ~FD_WRITE;
+  fd->revents &= ~FD_WRITE;
+#endif
+  /* SetEvent (fd->overlapped[FD_WRITE_BIT].hEvent); */
+  return ret;
+
+error_and_fail:
+  SetErrnoFromWinError (dwret);
+  return -1;
+}
+
+int
+w32io_anonymous_pipe_close (struct W32Fd *fd, int closehandle)
+{
+  int ret = 0, i;
+  int closewait = 100;
+  int closed = 0;
+  HANDLE h[2];
+  h[0] = fd->overlapped[ANON_PIPE_MAIN_THREAD_POLL_EVENT].hEvent;
+  h[1] = fd->anon_thread_mutex;
+  if (fd->access & GENERIC_WRITE || fd->access == 0)
+  {
+#if DEBUG_W32IO_THREADS
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking writing thread status\n");
+#endif
+    if (WaitForSingleObject (fd->anon_thread_mutex, closewait) == WAIT_OBJECT_0)
+    {
+#if DEBUG_W32IO_THREADS
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not working\n");
+#endif
+      /* We've locked the mutex - which means that worker thread is not
+       * working at the moment.
+       */
+      /* Do not check for errors - we can't report them here (any errors
+       * reported should be related to close(), not to some previous
+       * operation).
+       */
+      //SetEvent (fd->overlapped[ANON_PIPE_CLOSE_POLL_EVENT].hEvent);
+
+      if (fd->wrbuffer)
+      {
+        GNUNET_free (fd->wrbuffer->buf);
+        GNUNET_free (fd->wrbuffer);
+        fd->wrbuffer = NULL;
+      }
+
+      fd->work = 2; /* close  */
+  
+      SetEvent (fd->overlapped[ANON_PIPE_THREAD_POLL_EVENT].hEvent);
+      /* We've signaled the worker thread condition. Once we unlock the mutex,
+       * the worker thread will wake up.
+       */
+      ReleaseMutex (fd->anon_thread_mutex);
+      /* We've unlocked the mutex. The worker thread now wakes up and sees that
+       * work is 2, signals maincond, then sets ->alive to FALSE and terminates.
+       */
+#if DEBUG_W32IO_THREADS
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Waiting for the worker to die\n");
+#endif
+      WaitForSingleObject (fd->anon_thread, INFINITE);
+#if DEBUG_W32IO_THREADS
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Worker is dead\n");
+#endif
+      if (closehandle)
+        ret = ret || !CloseHandle (fd->fd);
+    }
+    else
+    {
+#if DEBUG_W32IO_THREADS
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Terminating\n");
+#endif
+      SetEvent (fd->overlapped[ANON_PIPE_CLOSE_POLL_EVENT].hEvent);
+      fd->alive = 0;
+    }
+    closed = 1;
+  }
+  if (fd->access & GENERIC_READ)
+  {
+#if DEBUG_W32IO_THREADS
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Terminating (reader)\n");
+#endif
+    SetEvent (fd->overlapped[ANON_PIPE_CLOSE_POLL_EVENT].hEvent);
+    if (fd->readbuffer)
+      GNUNET_free (fd->readbuffer);
+#if DEBUG_W32IO_THREADS
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Terminated (reader)\n");
+#endif
+  }
+  CloseHandle (fd->anon_thread);
+  CloseHandle (fd->anon_thread_mutex);
+  
+  fd->anon_thread = INVALID_HANDLE_VALUE;
+
+  for (i = 0; i < POLLLAST; i++)
+  {
+    if (fd->overlapped[i].hEvent != INVALID_HANDLE_VALUE)
+    {
+      CloseHandle (fd->overlapped[i].hEvent);
+      fd->overlapped[i].hEvent = INVALID_HANDLE_VALUE;
+    }
+  }
+  return ret;
+}
+
+off_t
+GNUNET_W32IO_lseek_handle (HANDLE fd, uint64_t new_offset, int origin)
+{
+  BOOL bret;
+  DWORD dwError;
+  LARGE_INTEGER offset;
+  LARGE_INTEGER ret;
+  LARGE_INTEGER current;
+  off_t result;
+
+  if (origin != SEEK_SET && origin != SEEK_CUR && origin != SEEK_END)
+  {
+    errno = EINVAL;
+    return -1;
+  }
+
+  offset.QuadPart = 0;
+  SetLastError (0);
+  bret = SetFilePointerEx (fd, offset, &current, FILE_CURRENT);
+
+  dwError = GetLastError ();
+
+  if (bret == 0 && dwError != NO_ERROR)
+  {
+    SetErrnoFromWinError (dwError);
+    return -1;
+  }
+
+  offset.QuadPart = new_offset;
+  SetLastError (0);
+  bret = SetFilePointerEx (fd, offset, &ret,
+      (origin == SEEK_SET ? FILE_BEGIN :
+      (origin == SEEK_CUR ? FILE_CURRENT :
+      (origin == SEEK_END ? FILE_END : origin))));
+
+  dwError = GetLastError ();
+
+  if (bret == 0 && dwError != NO_ERROR)
+  {
+    SetFilePointerEx (fd, current, NULL, FILE_BEGIN);
+    SetErrnoFromWinError (dwError);
+    return -1;
+  }
+
+  /* FIXME: make sure this check works correctly with 32-bit values */
+  result = ret.QuadPart;
+  offset.QuadPart = result;
+  if (offset.QuadPart != ret.QuadPart)
+  {
+    SetFilePointerEx (fd, current, NULL, FILE_BEGIN);
+    errno = EOVERFLOW;
+    return -1;
+  }
+
+  return ret.QuadPart;
+}
+
+off_t
+w32io_lseek (struct W32Fd *fd, uint64_t new_offset, int origin)
+{
+  off_t result;
+  if (fd->fd_type != GNUNET_W32IO_FILE)
+  {
+    errno = ESPIPE;
+    return -1;
+  }
+
+  result = GNUNET_W32IO_lseek_handle (fd->fd, new_offset, origin);
+  fd->pos = result;
+  return result;
+}
+
+off_t
+GNUNET_W32IO_lseek (int fd, uint64_t new_offset, int origin)
+{
+  return w32io_lseek (w32io_fetch_fd (fd), new_offset, origin);
+}
+
+int
+w32io_read_file (struct W32Fd *fd, void *in, size_t to_read)
+{
+  BOOL bret;
+  DWORD dwret, error_code;
+  int ret = 0;
+  
+  do
+  {
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "WaitForSingleObject (%x, INFINITE);\n", fd->overlapped[FILE_READY_POLL_EVENT].hEvent);
+#endif
+    dwret = WaitForSingleObject (fd->overlapped[FILE_READY_POLL_EVENT].hEvent,
+        INFINITE);
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done\n");
+#endif
+    if (dwret != WAIT_OBJECT_0)
+    {
+      error_code = GetLastError ();
+      goto error_and_fail;
+    }
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GetOverlappedResult (%x, &fd->overlapped[FILE_READY_POLL_EVENT], &dwret, TRUE);\n", fd->fd);
+#endif
+    SetLastError (0);
+    bret = GetOverlappedResult ((HANDLE) fd->fd,
+        &fd->overlapped[FILE_READY_POLL_EVENT], &dwret, TRUE);
+    error_code = GetLastError ();
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got it\n");
+#endif
+    if (bret == 0 || error_code != NO_ERROR)
+    {
+      if (error_code == ERROR_HANDLE_EOF) {
+         return ret;
+      }
+      goto error_and_fail;
+    }
+
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ReadFile (%x, in, %d, &dwret, &fd->overlapped[FILE_READY_POLL_EVENT]);\n", fd->fd, to_read);
+#endif
+    ZeroOverlappedExceptEvent(fd->overlapped[FILE_READY_POLL_EVENT]);
+    fd->overlapped[FILE_READY_POLL_EVENT].Offset = fd->pos & ((DWORD) -1);
+    fd->overlapped[FILE_READY_POLL_EVENT].OffsetHigh = fd->pos >> (sizeof (DWORD) * 8);
+    dwret = 0;
+    SetLastError (0);
+    bret = ReadFile (fd->fd, in, to_read, &dwret,
+        &fd->overlapped[FILE_READY_POLL_EVENT]);
+    error_code = GetLastError ();
+    if (bret == 0 || error_code != NO_ERROR)
+    {
+      if (error_code == ERROR_HANDLE_EOF) {
+        /* For some reason this will not enable the event, do it manually */
+        SetEvent (fd->overlapped[FILE_READY_POLL_EVENT].hEvent);
+        return ret;
+      }
+
+      if (error_code != ERROR_IO_PENDING)
+        goto error_and_fail;
+    }
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Read %d bytes\n", dwret);
+#endif
+    to_read -= dwret;
+    in += dwret;
+    fd->pos += dwret;
+    ret += dwret;
+  } while (to_read > 0);
+  return ret;
+
+error_and_fail:
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to read\n");
+  SetErrnoFromWinError (error_code);
+  return -1;
+}
+
+int
+w32io_write_file (struct W32Fd *fd, const void *out, size_t to_write)
+{
+  BOOL bret;
+  DWORD error_code;
+  DWORD ret;
+
+  /* writebuffer isn't NULL -> there's a writing operation going on */
+  if (fd->wrbuffer != NULL || WaitForSingleObject (fd->overlapped[FILE_READY_POLL_EVENT].hEvent, 0) == WAIT_TIMEOUT) {
+    /* Wait until event is set (meaning that operation is complete).
+     * This might block for a while (until the other end reads), that is - 
+     * you can't have more than one writing operation working at one pipe.
+     * TODO: implement multiple buffering, so that it is possible to write
+     * more than once (especially if we're talking about writing small
+     * amounts of data multiple times).
+     */
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "WaitForSingleObject (%x, INFINITE);\n", fd->overlapped[FILE_READY_POLL_EVENT].hEvent);
+#endif
+    if (WaitForSingleObject (fd->overlapped[FILE_READY_POLL_EVENT].hEvent, INFINITE) ==
+        WAIT_OBJECT_0)
+    {
+      /* Get the operation result, free the buffer */
+      DWORD wait_ret;
+#if DEBUG_W32IO
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GetOverlappedResult (%x, %x, %x, TRUE);\n", fd->fd, &fd->overlapped[FILE_READY_POLL_EVENT], &wait_ret);
+#endif
+      ret = GetOverlappedResult ((HANDLE) fd->fd,
+          &fd->overlapped[FILE_READY_POLL_EVENT], &wait_ret, TRUE);
+#if DEBUG_W32IO
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got it\n");
+#endif
+      if (fd->wrbuffer) {
+        GNUNET_free (fd->wrbuffer->buf);
+        GNUNET_free (fd->wrbuffer);
+        fd->wrbuffer = NULL;
+      }
+
+      if (ret == 0) {
+        errno = EIO;
+        return -1;
+      }
+    }
+  }
+
+  if (out)
+  {
+    fd->wrbuffer = GNUNET_malloc (sizeof (WSABUF));
+    fd->wrbuffer->buf = memcpy (GNUNET_malloc (to_write), out, to_write);
+    fd->wrbuffer->len = to_write;
+  }
+#if DEBUG_W32IO
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "WriteFile (%x, %x, %d, NULL, %x);\n", fd->fd, fd->wrbuffer->buf, to_write, &fd->overlapped[FILE_READY_POLL_EVENT]);
+#endif
+  ZeroOverlappedExceptEvent(fd->overlapped[FILE_READY_POLL_EVENT]);
+  fd->overlapped[FILE_READY_POLL_EVENT].Offset = fd->pos & ((DWORD) -1);
+  fd->overlapped[FILE_READY_POLL_EVENT].OffsetHigh = fd->pos >> (sizeof (DWORD) * 8);
+  SetLastError (0);
+  bret = WriteFile ((HANDLE) fd->fd, fd->wrbuffer->buf, to_write, NULL,
+      &fd->overlapped[FILE_READY_POLL_EVENT]);
+  error_code = GetLastError ();
+  if (bret == 0 || error_code != NO_ERROR) {
+    /* FIXME: handle ERROR_INVALID_USER_BUFFER or ERROR_NOT_ENOUGH_MEMORY as EAGAIN */
+    if (error_code != ERROR_IO_PENDING)
+      goto error_and_fail;
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Wrote into heap buffer\n");
+#endif
+  } else {
+#if DEBUG_W32IO
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Wrote into kernel buffer\n");
+#endif
+    GNUNET_free (fd->wrbuffer->buf);
+    GNUNET_free (fd->wrbuffer);
+    fd->wrbuffer = NULL;
+  }
+  fd->pos += to_write;
+  return to_write;
+
+error_and_fail:
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to write\n");
+  GNUNET_free (fd->wrbuffer->buf);
+  GNUNET_free (fd->wrbuffer);
+  fd->wrbuffer = NULL;
+  SetErrnoFromWinError (error_code);
+  return -1;
+}
+
+int
+w32io_read (struct W32Fd *ifd, void *in, size_t to_read)
+{
+  switch (ifd->fd_type)
+  {
+  case GNUNET_W32IO_NAMED_PIPE:
+    return w32io_read_async_named_pipe (ifd, in, to_read);
+    break;
+  case GNUNET_W32IO_FILE:
+    return w32io_read_file (ifd, in, to_read);
+    break;
+  case GNUNET_W32IO_SOCKET:
+    return w32io_recv (ifd, in, to_read, 0);
+  case GNUNET_W32IO_ANONYMOUS_PIPE:
+    return w32io_anonymous_pipe_read (ifd, in, to_read);
+  default:
+    return 0;
+    /* FIXME: handle other descriptor types */
+  }
+}
+
+int
+GNUNET_W32IO_read (int ifd, void *in, size_t to_read)
+{
+  return w32io_read (w32io_fetch_fd (ifd), in, to_read);
+}
+
+int
+w32io_write (struct W32Fd *ifd, const void *out, size_t to_write)
+{
+  int ret;
+  switch (ifd->fd_type)
+  {
+  case GNUNET_W32IO_NAMED_PIPE:
+    return w32io_write_async_named_pipe (ifd, out, to_write);
+    break;
+  case GNUNET_W32IO_FILE:
+    return w32io_write_file (ifd, out, to_write);
+    break;
+  case GNUNET_W32IO_SOCKET:
+    return w32io_send (ifd, out, to_write, 0);
+  case GNUNET_W32IO_ANONYMOUS_PIPE:
+    ret = w32io_anonymous_pipe_write (ifd, out, to_write);
+    return ret;
+  default:
+    return 0;
+    /* FIXME: handle other descriptor types */
+  }
+}
+
+int
+GNUNET_W32IO_write (int ifd, const void *out, size_t to_write)
+{
+  return w32io_write (w32io_fetch_fd (ifd), out, to_write);
+}
+
+/**
+ * Create a named pipe server.
+ * Server is created unconnected. To accept a connection form a client
+ * poll() the server for POLLIN or POLLOUT. Once it polls true, the pipe
+ * is connected and is readable/writable.
+ *
+ * @param name pointer to a (char *) that points to the pipe name.
+ *   if *@name is NULL, the name will be generated randomly until
+ *   a unique name is found, and upon return *@name will point to
+ *   that name (free it with GNUNET_free).
+ * @param mode mode of the pipe handle (as accepted by CreateNamedPipe ())
+ * @return a pointer to FD on success, NULL on error.
+ */
+struct W32Fd *
+w32io_named_pipe_server (char **name, int mode)
+{
+  /* POSIX equivalent: mkfifo() if it doesn't exist, then open() */
+  char pipename[255];
+  int repeat = 1;
+  struct W32Fd *result;
+  HANDLE server = NULL;
+  
+  if (name == NULL)
+    return NULL;
+  if (*name == NULL)
+    repeat = 2;
+
+  while (repeat > 0)
+  {
+    if (repeat == 2)
+      GNUNET_W32IO_generate_random_local_pipe_name (pipename);
+    else
+      strncpy (pipename, *name, 255);
+    server = CreateNamedPipeA ((LPCSTR) pipename, mode |
+        FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED |
+        PIPE_ACCESS_INBOUND, /*inbound access is necessary to read pipe info*/
+        PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
+        PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, NULL);
+    if (server == INVALID_HANDLE_VALUE)
+    {
+      DWORD err = GetLastError ();
+      switch (err)
+      {
+        case ERROR_ACCESS_DENIED:
+          server = NULL;
+          if (repeat == 2)
+            continue;
+      }
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create a named pipe. GLE: %d\n", err);
+      return NULL;
+    }
+    repeat = 0;
+  }
+  
+  result = w32io_fd_from_handle (server, GNUNET_W32IO_NAMED_PIPE, (mode & PIPE_ACCESS_OUTBOUND ? GENERIC_WRITE : 0) | (mode & PIPE_ACCESS_INBOUND ? GENERIC_READ : 0), 0, 0, 0);
+  if (result == NULL)
+  {
+    CloseHandle (server);
+  }
+  else
+  {
+    if (*name == NULL)
+      GNUNET_asprintf (name, "%s", pipename);
+  }
+  return result;
+}
+
+int 
+GNUNET_W32IO_named_pipe_server (char **name, int mode)
+{
+  struct W32Fd *fd = w32io_named_pipe_server (name, mode);
+  if (fd != NULL && fd != INVALID_POLL_FD)
+    return w32io_insert_fd (fd);
+  return -1;
+}
+
+/**
+ * Create a named pipe client.
+ * Client is created and connected atomically in one call. If it is
+ *  not possible to connect the client, it will not be created.
+ *
+ * @param name a (char *) that points to the pipe name.
+ * @param mode mode of the pipe handle (as accepted by CreateFile ())
+ * @return a pointer to FD on success, NULL on error.
+ */
+struct W32Fd *
+w32io_named_pipe_client (const char *name, int mode)
+{
+  /* POSIX equivalent: open() the pipe, but only if it exists and is opened
+   * by another process with mode opposite to @mode.
+   * Note that NT named pipes can be fully duplex, while POSIX named 
+   * pipes usually can not.
+   */
+  struct W32Fd *result;
+  HANDLE p;
+
+  p = CreateFileA ((LPCSTR) name, mode, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_READ_ATTRIBUTES, NULL);
+  if (p == INVALID_HANDLE_VALUE)
+  {
+    DWORD err = GetLastError ();
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to open client side of a named pipe. GLE: %d\n", err);
+    return NULL;
+  }
+  result = w32io_fd_from_handle (p, GNUNET_W32IO_NAMED_PIPE, (mode & PIPE_ACCESS_OUTBOUND ? GENERIC_WRITE : 0) | (mode & PIPE_ACCESS_INBOUND ? GENERIC_READ : 0), 1, mode & PIPE_ACCESS_OUTBOUND, mode & PIPE_ACCESS_INBOUND);
+  if (result == NULL)
+    CloseHandle (p);
+  return result;
+}
+
+int
+GNUNET_W32IO_named_pipe_client (const char *name, int mode)
+{
+  struct W32Fd *fd = w32io_named_pipe_client (name, mode);
+  if (fd != NULL && fd != INVALID_POLL_FD)
+    return w32io_insert_fd (fd);
+  return -1;
+}
+
+#endif /* WINDOWS */
\ No newline at end of file
diff --git a/src/util/w32io.h b/src/util/w32io.h
new file mode 100644
index 0000000..c6abe9c
--- /dev/null
+++ b/src/util/w32io.h
@@ -0,0 +1,279 @@
+/*
+     This file is part of GNUnet.
+     (C) 2001, 2002, 2005, 2006, 2009, 2010 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, 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
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+#ifndef __GNUNET_W32IO_H__
+#define __GNUNET_W32IO_H__
+#include "platform.h"
+#include "gnunet_common.h"
+
+#if WINDOWS
+
+#include <sys/types.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+
+#include <winsock2.h>
+
+/**
+ * GNUNET_W32IO_UNSPECIFIED - not specified by user. Should be
+ * autodetected when necessary
+ * GNUNET_W32IO_UNKNOWN - autodetection failed, type unknown
+ * GNUNET_W32IO_FILE - returned by CreateFile()
+ * GNUNET_W32IO_NAMED_PIPE - returned by CreateNamedPipe() (server)
+ * and CreateFile() (client)
+ * GNUNET_W32IO_ANONYMOUS_PIPE - returned by CreatePipe()
+ * GNUNET_W32IO_CONSOLE - returned by CreateFile()
+ * GNUNET_W32IO_SOCKET - returned by socket()
+ * GNUNET_W32IO_LAST - do not use
+ */
+typedef enum
+{
+  GNUNET_W32IO_UNSPECIFIED = 0,
+  GNUNET_W32IO_UNKNOWN,
+  GNUNET_W32IO_FILE,
+  GNUNET_W32IO_NAMED_PIPE,
+  GNUNET_W32IO_ANONYMOUS_PIPE,
+  GNUNET_W32IO_CONSOLE,
+  GNUNET_W32IO_SOCKET,
+  GNUNET_W32IO_LAST
+} GNUNET_W32IO_HandleType;
+
+/**
+ * 
+ */
+struct W32Fd
+{
+  /**
+   * Untyped I/O descriptor (type depends on fd_type)
+   */
+  HANDLE fd;
+
+  /**
+   * Events that have occurred on a socket
+   * (as returned by WSAEnumNetworkEvents)
+   * Used to preserve some one-time events that
+   * are not re-posted by Winsock.
+   */
+  WSANETWORKEVENTS wsaevents;
+
+  /**
+   * An array of structures for file/pipe async I/O.
+   * Its 0th member is used by sockets.
+   * Its 0th and 1st members are used by @anon_thread as, respectedly,
+   * the @anon_thread event (tells the @anon_thread to wake up and do some
+   * work) and the main thread event (tells the main thread to wake up, since
+   * the @anon_thead have finished its work).
+   */
+  OVERLAPPED overlapped[POLLLAST];
+
+  /**
+   * fd_type - type of the descriptor
+   */
+  GNUNET_W32IO_HandleType fd_type;
+
+  /**
+   * The access we have to the handle
+   */
+  DWORD access;
+
+  /**
+   * The events in which the caller is interested in.
+   * May be modified internally by ppoll()
+   */
+  int16_t events;
+
+  /**
+   * The result of a ppoll() call - contains the events
+   * that have occurred on this W32Fd.
+   */
+  int16_t revents;
+
+  /*_______Anonymous pipe I/O implementation details_______*/
+
+  /**
+   * A thread that performs operations on anonymous pipe
+   */
+  HANDLE anon_thread;
+ 
+  /**
+   * A mutex that locks this W32Fd to prevent the main thread and
+   * the @anon_thread from accessing it at the same time.
+   */
+  HANDLE anon_thread_mutex;
+
+  /**
+   * Number of bytes read
+   */
+  int bytes_read;
+
+  /**
+   * Number of bytes written
+   */
+  DWORD bytes_written;
+
+  /**
+   * A pointer to a block of memory that will receive data from a reading
+   * operation.
+   */
+  void *readbuffer;
+
+  /**
+   * Size of the read buffer
+   */
+  size_t readbuffer_size;
+
+  /**
+   * Previous write position in the read buffer (initially -1)
+   */
+  int readbuffer_write_pos;
+
+  /**
+   * Current read position in the read buffer
+   */
+  int readbuffer_read_pos;
+
+  /**
+   * A pointer to a block of memory that will provide data for a writing
+   * operation.
+   */
+  WSABUF *wrbuffer;
+
+  /**
+   * A value returned by ReadFile()/WriteFile() within @anon_thread
+   */
+  BOOL bret;
+
+  /**
+   * A value returned by GetLastError() within @anon_thread
+   */
+  DWORD dwerror;
+
+  /**
+   * A type of work to be done.
+   * -1 - none
+   *  0 - read
+   *  1 - write
+   *  2 - close
+   */
+  int work;
+
+  /**
+   * A boolean condition that can be set to FALSE to indicate that
+   * the @anon_thread must (when it wakes up) return.
+   */
+  BOOL alive;
+
+  /**
+   * Position withing a file (for files)
+   */
+  uint64_t pos;
+};
+
+int w32io_init ();
+int w32io_deinit ();
+
+struct W32Fd *w32io_fetch_fd (int fake_fd);
+int w32io_insert_fd (struct W32Fd *real_fd);
+void w32io_remove_fd (int fake_fd);
+
+HANDLE w32io_fd_get_handle (struct W32Fd *fd);
+HANDLE GNUNET_W32IO_fd_get_handle (int fd);
+
+void GNUNET_W32IO_generate_random_local_pipe_name (char *pipename);
+
+int GNUNET_W32IO_pipe (int fd[2], int server_inheritable, int client_inheritable, DWORD server_mode, DWORD client_mode);
+int w32io_pipe (struct W32Fd *fd[2], int server_inheritable, int client_inheritable, DWORD server_mode, DWORD client_mode);
+
+int GNUNET_W32IO_anonymous_pipe (int fd[2], int read_inheritable, int write_inheritable);
+int w32io_anonymous_pipe (struct W32Fd *fd[2], int read_inheritable, int write_inheritable);
+
+int GNUNET_W32IO_fsync (int wfd);
+int w32io_fsync (struct W32Fd *wfd);
+
+int GNUNET_W32IO_close (int wfd, int closehandle);
+int w32io_close (struct W32Fd *wfd, int closehandle);
+
+int w32io_shutdown (struct W32Fd *wfd, int how);
+int GNUNET_W32IO_shutdown (int fd, int how);
+
+GNUNET_W32IO_HandleType GNUNET_W32IO_find_handle_type (HANDLE h);
+
+int GNUNET_W32IO_fd_from_handle (HANDLE h, GNUNET_W32IO_HandleType htype, DWORD handle_access, int connected,
+    int writeable, int readable);
+struct W32Fd *w32io_fd_from_handle (HANDLE h, GNUNET_W32IO_HandleType htype, DWORD handle_access, int connected,
+    int writeable, int readable);
+
+int w32io_read_async_named_pipe (struct W32Fd *fd, void *in, size_t to_read);
+
+int w32io_write_async_named_pipe (struct W32Fd *fd, const void *out, size_t to_write);
+
+int GNUNET_W32IO_read (int ifd, void *in, size_t to_read);
+int w32io_read (struct W32Fd *ifd, void *in, size_t to_read);
+
+int GNUNET_W32IO_write (int ifd, const void *out, size_t to_write);
+int w32io_write (struct W32Fd *ifd, const void *out, size_t to_write);
+
+int GNUNET_W32IO_poll (struct pollfd *fds, nfds_t nfds, int timeout);
+int w32io_poll (struct W32PollFd *fds, nfds_t nfds, int timeout, int emulate_select);
+
+int GNUNET_W32IO_select (int nfds, w32fd_set *readfds, w32fd_set *writefds, w32fd_set *errorfds, struct timeval *timeout);
+
+int w32io_prepare_for_poll (struct W32PollFd *wfd, HANDLE *events);
+
+int GNUNET_W32IO_recv (int fd, void *buffer, size_t length, int flags);
+int GNUNET_W32IO_recvfrom (int fd, void *buffer, size_t length, int flags, struct sockaddr *address, int *address_len);
+int GNUNET_W32IO_send (int fd, const void *buffer, size_t length, int flags);
+int GNUNET_W32IO_sendto (int fd, const void *buffer, size_t length, int flags, const struct sockaddr *address, int address_len);
+int w32io_recv (struct W32Fd *fd, void *buffer, size_t length, int flags);
+int w32io_recvfrom (struct W32Fd *fd, void *buffer, size_t length, int flags, struct sockaddr *address, int *address_len);
+int w32io_send (struct W32Fd *fd, const void *buffer, size_t length, int flags);
+int w32io_sendto (struct W32Fd *fd, const void *buffer, size_t length, int flags, const struct sockaddr *address, int address_len);
+
+int GNUNET_W32IO_connect (int fd, const struct sockaddr *name, int namelen);
+int GNUNET_W32IO_accept (int fd, struct sockaddr *name, int *namelen);
+int GNUNET_W32IO_listen (int fd, int backlog);
+int w32io_connect (struct W32Fd *fd, const struct sockaddr *name, int namelen);
+int w32io_accept (struct W32Fd *fd, struct sockaddr *name, int *namelen);
+int w32io_listen (struct W32Fd *fd, int backlog);
+int GNUNET_W32IO_bind (int fd, const struct sockaddr *name, int namelen);
+int w32io_bind (struct W32Fd *fd, const struct sockaddr *name, int namelen);
+
+int w32io_anonymous_pipe_read (struct W32Fd *fd, void *in, size_t to_read);
+int w32io_anonymous_pipe_write (struct W32Fd *fd, const void *out, size_t to_write);
+int w32io_anonymous_pipe_close (struct W32Fd *fd, int closehandle);
+
+off_t GNUNET_W32IO_lseek_handle (HANDLE fd, uint64_t new_offset, int origin);
+off_t GNUNET_W32IO_lseek (int fd, uint64_t new_offset, int origin);
+off_t w32io_lseek (struct W32Fd *fd, uint64_t new_offset, int origin);
+
+int w32io_read_file (struct W32Fd *fd, void *in, size_t to_read);
+int w32io_write_file (struct W32Fd *fd, const void *out, size_t to_write);
+
+int GNUNET_W32IO_named_pipe_server (char **name, int mode);
+int GNUNET_W32IO_named_pipe_client (const char *name, int mode);
+struct W32Fd *w32io_named_pipe_server (char **name, int mode);
+struct W32Fd *w32io_named_pipe_client (const char *name, int mode);
+
+#endif /* WINDOWS */
+#endif /* __GNUNET_W32IO_H__ */
\ No newline at end of file
diff --git a/src/util/winproc.c b/src/util/winproc.c
index 2df6383..8a7344b 100644
--- a/src/util/winproc.c
+++ b/src/util/winproc.c
@@ -29,7 +29,8 @@
 
 #define DEBUG_WINPROC 0
 
-#ifdef MINGW
+#if WINDOWS
+#include "w32io.h"
 
 static HINSTANCE hNTDLL, hIphlpapi, hAdvapi, hNetapi;
 
@@ -91,6 +92,8 @@ GNInitWinEnv ()
   plibc_set_panic_proc (plibc_panic);
   ret = plibc_init ("GNU", PACKAGE);
 
+  w32io_init ();
+  
   /* don't load other DLLs twice */
   if (hNTDLL)
     return ret;
@@ -235,6 +238,8 @@ GNShutdownWinEnv ()
 {
   plibc_shutdown ();
 
+  w32io_deinit ();
+
   FreeLibrary (hNTDLL);
   FreeLibrary (hIphlpapi);
   FreeLibrary (hAdvapi);
@@ -243,7 +248,7 @@ GNShutdownWinEnv ()
   CoUninitialize ();
 }
 
-#endif /* MINGW */
+#endif /* WINDOWS */
 
 #if !HAVE_ATOLL
 long long
-- 
1.7.3.1.msysgit.0

