Some more debugging output. (g_io_channel_win32_poll): Remove unused vars.
[platform/upstream/glib.git] / giowin32.c
index 36fa82c..560d714 100644 (file)
@@ -3,6 +3,7 @@
  *
  * giowin32.c: IO Channels for Win32.
  * Copyright 1998 Owen Taylor and Tor Lillqvist
+ * Copyright 1999-2000 Tor Lillqvist and Craig Setera
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -11,7 +12,7 @@
  *
  * This library 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
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
  * file for a list of people on the GLib Team.  See the ChangeLog
  * files for a list of changes.  These files are distributed with
- * GLib at ftp://ftp.gtk.org/pub/gtk/. 
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
  */
 
+/* Define this to get (very) verbose logging of all channels */
+/* #define G_IO_WIN32_DEBUG */
 
-#include "config.h"
 #include "glib.h"
+
+#include <stdlib.h>
 #include <windows.h>
-#include <winsock.h>           /* Not everybody has winsock2 */
+#include <winsock.h>          /* Not everybody has winsock2 */
 #include <fcntl.h>
 #include <io.h>
+#include <process.h>
 #include <errno.h>
-#include <sys/types.h>
-
-#include <stdio.h>
+#include <sys/stat.h>
 
 typedef struct _GIOWin32Channel GIOWin32Channel;
 typedef struct _GIOWin32Watch GIOWin32Watch;
 
-guint g_pipe_readable_msg;
+#define BUFFER_SIZE 4096
 
 typedef enum {
   G_IO_WINDOWS_MESSAGES,       /* Windows messages */
-  G_IO_FILE_DESC,              /* Unix-like file descriptors from _open*/
-  G_IO_PIPE,                   /* pipe, with windows messages for signalling */
-  G_IO_STREAM_SOCKET           /* Stream sockets */
+  G_IO_FILE_DESC,              /* Unix-like file descriptors from
+                                * _open() or _pipe(). Read with read().
+                                * Have to create separate thread to read.
+                                */
+  G_IO_STREAM_SOCKET           /* Stream sockets. Similar as fds, but
+                                * read with recv().
+                                */
 } GIOWin32ChannelType;
 
 struct _GIOWin32Channel {
@@ -58,19 +65,42 @@ struct _GIOWin32Channel {
                                 * as provided by WinSock.
                                 */
   GIOWin32ChannelType type;
+  
+  gboolean debug;
 
   /* This is used by G_IO_WINDOWS_MESSAGES channels */
   HWND hwnd;                   /* handle of window, or NULL */
-
-  /* This is used by G_IO_PIPE channels */
-  guint peer;                  /* thread id of reader */
-  guint peer_fd;               /* fd in the reader */
-  guint offset;                        /* counter of accumulated bytes */
-  guint need_wakeups;          /* in output channels whether the
-                                * reader needs wakeups
+  
+  /* Following fields used by fd and socket channels for input */
+  
+  /* Data is kept in a circular buffer. To be able to distinguish between
+   * empty and full buffer, we cannot fill it completely, but have to
+   * leave a one character gap.
+   *
+   * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
+   *
+   * Empty:    wrp == rdp
+   * Full:     (wrp + 1) % BUFFER_SIZE == rdp
+   * Partial:  otherwise
+   */
+  guchar *buffer;              /* (Circular) buffer */
+  gint wrp, rdp;               /* Buffer indices for writing and reading */
+  gboolean running;            /* Is reader thread running. FALSE if
+                                * EOF has been reached.
                                 */
+  guint thread_id;             /* If non-NULL has a reader thread, or has
+                                * had.*/
+  HANDLE data_avail_event;
+  HANDLE space_avail_event;
+  CRITICAL_SECTION mutex;
+  
+  /* Function that actually reads from fd */
+  int (*reader) (int fd, guchar *buf, int len);
 };
 
+#define LOCK(mutex) EnterCriticalSection (&mutex)
+#define UNLOCK(mutex) LeaveCriticalSection (&mutex)
+
 struct _GIOWin32Watch {
   GPollFD       pollfd;
   GIOChannel   *channel;
@@ -78,346 +108,389 @@ struct _GIOWin32Watch {
   GIOFunc       callback;
 };
 
-static gboolean g_io_win32_msg_prepare  (gpointer  source_data, 
-                                        GTimeVal *current_time,
-                                        gint     *timeout);
-static gboolean g_io_win32_msg_check    (gpointer  source_data,
-                                        GTimeVal *current_time);
-static gboolean g_io_win32_msg_dispatch (gpointer  source_data,
-                                        GTimeVal *current_time,
-                                        gpointer  user_data);
-
-static gboolean g_io_win32_fd_prepare  (gpointer  source_data, 
-                                       GTimeVal *current_time,
-                                       gint     *timeout);
-static gboolean g_io_win32_fd_check    (gpointer  source_data,
-                                       GTimeVal *current_time);
-static gboolean g_io_win32_fd_dispatch (gpointer  source_data,
-                                       GTimeVal *current_time,
-                                       gpointer  user_data);
-
-static gboolean g_io_win32_pipe_prepare  (gpointer  source_data, 
-                                         GTimeVal *current_time,
-                                         gint     *timeout);
-static gboolean g_io_win32_pipe_check    (gpointer  source_data,
-                                         GTimeVal *current_time);
-static gboolean g_io_win32_pipe_dispatch (gpointer  source_data,
-                                         GTimeVal *current_time,
-                                         gpointer  user_data);
-static void g_io_win32_pipe_destroy     (gpointer source_data);
-
-static gboolean g_io_win32_sock_prepare  (gpointer  source_data, 
-                                         GTimeVal *current_time,
-                                         gint     *timeout);
-static gboolean g_io_win32_sock_check    (gpointer  source_data,
-                                         GTimeVal *current_time);
-static gboolean g_io_win32_sock_dispatch (gpointer  source_data,
-                                         GTimeVal *current_time,
-                                         gpointer  user_data);
-
-static void g_io_win32_destroy (gpointer source_data);
-
-static GIOError g_io_win32_msg_read (GIOChannel *channel, 
-                                    gchar      *buf, 
-                                    guint       count,
-                                    guint      *bytes_written);
-
-static GIOError g_io_win32_msg_write(GIOChannel *channel, 
-                                    gchar      *buf, 
-                                    guint       count,
-                                    guint      *bytes_written);
-static GIOError g_io_win32_msg_seek (GIOChannel *channel,
-                                    gint        offset, 
-                                    GSeekType   type);
-static void g_io_win32_msg_close    (GIOChannel *channel);
-static guint g_io_win32_msg_add_watch (GIOChannel      *channel,
-                                      gint             priority,
-                                      GIOCondition     condition,
-                                      GIOFunc          func,
-                                      gpointer         user_data,
-                                      GDestroyNotify   notify);
-
-static GIOError g_io_win32_fd_read (GIOChannel *channel, 
-                                   gchar      *buf, 
-                                   guint       count,
-                                   guint      *bytes_written);
-static GIOError g_io_win32_fd_write(GIOChannel *channel, 
-                                   gchar      *buf, 
-                                   guint       count,
-                                   guint      *bytes_written);
-static GIOError g_io_win32_fd_seek (GIOChannel *channel,
-                                   gint        offset, 
-                                   GSeekType   type);
-static void g_io_win32_fd_close (GIOChannel *channel);
-
-static void g_io_win32_free (GIOChannel *channel);
-
-static guint g_io_win32_fd_add_watch (GIOChannel      *channel,
-                                     gint             priority,
-                                     GIOCondition     condition,
-                                     GIOFunc          func,
-                                     gpointer         user_data,
-                                     GDestroyNotify   notify);
-
-static GIOError g_io_win32_no_seek (GIOChannel *channel,
-                                   gint        offset, 
-                                   GSeekType   type);
-
-static GIOError g_io_win32_pipe_read (GIOChannel *channel, 
-                                     gchar      *buf, 
-                                     guint       count,
-                                     guint      *bytes_written);
-static GIOError g_io_win32_pipe_write (GIOChannel *channel, 
-                                      gchar      *buf, 
-                                      guint       count,
-                                      guint      *bytes_written);
-static void g_io_win32_pipe_close    (GIOChannel *channel);
-static guint g_io_win32_pipe_add_watch (GIOChannel      *channel,
-                                       gint             priority,
-                                       GIOCondition     condition,
-                                       GIOFunc          func,
-                                       gpointer         user_data,
-                                       GDestroyNotify   notify);
-static void g_io_win32_pipe_free (GIOChannel *channel);
-
-static GIOError g_io_win32_sock_read (GIOChannel *channel, 
-                                     gchar      *buf, 
-                                     guint       count,
-                                     guint      *bytes_written);
-static GIOError g_io_win32_sock_write(GIOChannel *channel, 
-                                     gchar      *buf, 
-                                     guint       count,
-                                     guint      *bytes_written);
-static void g_io_win32_sock_close    (GIOChannel *channel);
-static guint g_io_win32_sock_add_watch (GIOChannel      *channel,
-                                       gint             priority,
-                                       GIOCondition     condition,
-                                       GIOFunc          func,
-                                       gpointer         user_data,
-                                       GDestroyNotify   notify);
-
-GSourceFuncs win32_watch_msg_funcs = {
-  g_io_win32_msg_prepare,
-  g_io_win32_msg_check,
-  g_io_win32_msg_dispatch,
-  g_io_win32_destroy
-};
+static void
+g_io_channel_win32_init (GIOWin32Channel *channel)
+{
+#ifdef G_IO_WIN32_DEBUG
+  channel->debug = TRUE;
+#else
+  if (getenv ("G_IO_WIN32_DEBUG") != NULL)
+    channel->debug = TRUE;
+  else
+    channel->debug = FALSE;
+#endif
+  channel->buffer = NULL;
+  channel->running = FALSE;
+  channel->thread_id = 0;
+  channel->data_avail_event = NULL;
+  channel->space_avail_event = NULL;
+}
 
-GSourceFuncs win32_watch_fd_funcs = {
-  g_io_win32_fd_prepare,
-  g_io_win32_fd_check,
-  g_io_win32_fd_dispatch,
-  g_io_win32_destroy
-};
+static void
+create_events (GIOWin32Channel *channel)
+{
+  SECURITY_ATTRIBUTES sec_attrs;
+  
+  sec_attrs.nLength = sizeof(SECURITY_ATTRIBUTES);
+  sec_attrs.lpSecurityDescriptor = NULL;
+  sec_attrs.bInheritHandle = FALSE;
+
+  /* The data available event is manual reset, the space available event
+   * is automatic reset.
+   */
+  if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
+      || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
+    {
+      gchar *msg = g_win32_error_message (GetLastError ());
+      g_error ("Error creating event: %s", msg);
+    }
+  InitializeCriticalSection (&channel->mutex);
+}
 
-GSourceFuncs win32_watch_pipe_funcs = {
-  g_io_win32_pipe_prepare,
-  g_io_win32_pipe_check,
-  g_io_win32_pipe_dispatch,
-  g_io_win32_pipe_destroy
-};
+static unsigned __stdcall
+reader_thread (void *parameter)
+{
+  GIOWin32Channel *channel = parameter;
+  guchar *buffer;
+  guint nbytes;
 
-GSourceFuncs win32_watch_sock_funcs = {
-  g_io_win32_sock_prepare,
-  g_io_win32_sock_check,
-  g_io_win32_sock_dispatch,
-  g_io_win32_destroy
-};
+  g_io_channel_ref ((GIOChannel *) channel);
 
-GIOFuncs win32_channel_msg_funcs = {
-  g_io_win32_msg_read,
-  g_io_win32_msg_write,
-  g_io_win32_no_seek,
-  g_io_win32_msg_close,
-  g_io_win32_msg_add_watch,
-  g_io_win32_free
-};
+  if (channel->debug)
+    g_print ("thread %#x: starting. pid:%#x, fd:%d, data_avail:%#x, space_avail:%#x\n",
+            channel->thread_id,
+            (guint) GetCurrentProcessId (),
+            channel->fd,
+            (guint) channel->data_avail_event,
+            (guint) channel->space_avail_event);
+  
+  channel->buffer = g_malloc (BUFFER_SIZE);
+  channel->rdp = channel->wrp = 0;
+  channel->running = TRUE;
 
-GIOFuncs win32_channel_fd_funcs = {
-  g_io_win32_fd_read,
-  g_io_win32_fd_write,
-  g_io_win32_fd_seek,
-  g_io_win32_fd_close,
-  g_io_win32_fd_add_watch,
-  g_io_win32_free
-};
+  SetEvent (channel->space_avail_event);
+  
+  while (channel->running)
+    {
+      LOCK (channel->mutex);
+      if (channel->debug)
+       g_print ("thread %#x: rdp=%d, wrp=%d\n",
+                channel->thread_id, channel->rdp, channel->wrp);
+      if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
+       {
+         /* Buffer is full */
+         if (channel->debug)
+           g_print ("thread %#x: resetting space_available\n",
+                    channel->thread_id);
+         ResetEvent (channel->space_avail_event);
+         if (channel->debug)
+           g_print ("thread %#x: waiting for space\n", channel->thread_id);
+         UNLOCK (channel->mutex);
+         WaitForSingleObject (channel->space_avail_event, INFINITE);
+         LOCK (channel->mutex);
+         if (channel->debug)
+           g_print ("thread %#x: rdp=%d, wrp=%d\n",
+                    channel->thread_id, channel->rdp, channel->wrp);
+       }
+      
+      buffer = channel->buffer + channel->wrp;
+      
+      /* Always leave at least one byte unused gap to be able to
+       * distinguish between the full and empty condition...
+       */
+      nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
+                   BUFFER_SIZE - channel->wrp);
 
-GIOFuncs win32_channel_pipe_funcs = {
-  g_io_win32_pipe_read,
-  g_io_win32_pipe_write,
-  g_io_win32_no_seek,
-  g_io_win32_pipe_close,
-  g_io_win32_pipe_add_watch,
-  g_io_win32_pipe_free
-};
+      if (channel->debug)
+       g_print ("thread %#x: calling reader for %d bytes\n",
+                channel->thread_id, nbytes);
 
-GIOFuncs win32_channel_sock_funcs = {
-  g_io_win32_sock_read,
-  g_io_win32_sock_write,
-  g_io_win32_no_seek,
-  g_io_win32_sock_close,
-  g_io_win32_sock_add_watch,
-  g_io_win32_free
-};
+      UNLOCK (channel->mutex);
+
+      nbytes = (*channel->reader) (channel->fd, buffer, nbytes);
+      
+      if (nbytes <= 0)
+       break;
 
-#define N_WATCHED_PIPES 4
+      LOCK (channel->mutex);
+      if (channel->debug)
+       g_print ("thread %#x: got %d bytes, rdp=%d, wrp=%d\n",
+                channel->thread_id, nbytes, channel->rdp, channel->wrp);
+      channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
+      if (channel->debug)
+       g_print ("thread %#x: rdp=%d, wrp=%d, setting data available\n",
+                channel->thread_id, channel->rdp, channel->wrp);
+      SetEvent (channel->data_avail_event);
+      UNLOCK (channel->mutex);
+    }
+  
+  LOCK (channel->mutex);
+  channel->running = FALSE;
+  if (channel->debug)
+    g_print ("thread %#x: got EOF, rdp=%d, wrp=%d, setting data available\n",
+            channel->thread_id, channel->rdp, channel->wrp);
+  SetEvent (channel->data_avail_event);
+  UNLOCK (channel->mutex);
+  
+  g_io_channel_unref((GIOChannel *) channel);
+  
+  /* All of the Microsoft docs say we should explicitly
+   * end the thread...
+   */
+  _endthreadex(1);
+  
+  return 0;
+}
 
-static struct {
-  gint fd;
-  GIOWin32Watch *watch;
-  GIOWin32Channel *channel;
-  gpointer user_data;
-} watched_pipes[N_WATCHED_PIPES];
+static void
+create_reader_thread (GIOWin32Channel *channel,
+                     gpointer         reader)
+{
+  channel->reader = reader;
 
-static gint n_watched_pipes = 0;
+  if (_beginthreadex (NULL, 0, reader_thread, channel, 0,
+                     &channel->thread_id) == 0)
+    g_warning ("Error creating reader thread: %s", strerror (errno));
+  WaitForSingleObject (channel->space_avail_event, INFINITE);
+}
 
-static gboolean
-g_io_win32_msg_prepare  (gpointer source_data, 
-                        GTimeVal *current_time,
-                        gint    *timeout)
+static int
+buffer_read (GIOWin32Channel *channel,
+            guchar          *dest,
+            guint            count,
+            GIOError        *error)
 {
-  GIOWin32Watch *data = source_data;
-  GIOWin32Channel *win32_channel = (GIOWin32Channel *) data->channel;
-  MSG msg;
+  guint nbytes;
+  guint left = count;
+  
+  LOCK (channel->mutex);
+  if (channel->debug)
+    g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
+            channel->thread_id, count, channel->rdp, channel->wrp);
+  
+  if (channel->rdp == channel->wrp)
+    {
+      UNLOCK (channel->mutex);
+      if (channel->debug)
+       g_print ("waiting for data from thread %#x\n", channel->thread_id);
+      WaitForSingleObject (channel->data_avail_event, INFINITE);
+      LOCK (channel->mutex);
+      if (channel->rdp == channel->wrp && !channel->running)
+       {
+         UNLOCK (channel->mutex);
+         return 0;
+       }
+    }
+  
+  if (channel->rdp < channel->wrp)
+    nbytes = channel->wrp - channel->rdp;
+  else
+    nbytes = BUFFER_SIZE - channel->rdp;
+  UNLOCK (channel->mutex);
+  nbytes = MIN (left, nbytes);
+  if (channel->debug)
+    g_print ("moving %d bytes from thread %#x\n",
+            nbytes, channel->thread_id);
+  memcpy (dest, channel->buffer + channel->rdp, nbytes);
+  dest += nbytes;
+  left -= nbytes;
+  LOCK (channel->mutex);
+  channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
+  if (channel->debug)
+    g_print ("setting space available for thread %#x\n", channel->thread_id);
+  SetEvent (channel->space_avail_event);
+  if (channel->debug)
+    g_print ("for thread %#x: rdp=%d, wrp=%d\n",
+            channel->thread_id, channel->rdp, channel->wrp);
+  if (channel->running && channel->rdp == channel->wrp)
+    {
+      if (channel->debug)
+       g_print ("resetting data_available of thread %#x\n",
+                channel->thread_id);
+      ResetEvent (channel->data_avail_event);
+    };
+  UNLOCK (channel->mutex);
+  
+  /* We have no way to indicate any errors form the actual
+   * read() or recv() call in the reader thread. Should we have?
+   */
+  *error = G_IO_ERROR_NONE;
+  return count - left;
+}
 
+static gboolean
+g_io_win32_prepare (gpointer  source_data,
+                   GTimeVal *current_time,
+                   gint     *timeout,
+                   gpointer  user_data)
+{
   *timeout = -1;
-
-  return PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_NOREMOVE) == TRUE;
+  
+  return FALSE;
 }
 
-static gboolean 
-g_io_win32_msg_check    (gpointer source_data,
-                        GTimeVal *current_time)
+static gboolean
+g_io_win32_check (gpointer  source_data,
+                 GTimeVal *current_time,
+                 gpointer  user_data)
 {
   GIOWin32Watch *data = source_data;
-  GIOWin32Channel *win32_channel = (GIOWin32Channel *) data->channel;
-  MSG msg;
-
-  return PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_NOREMOVE) == TRUE;
+  GIOWin32Channel *channel = (GIOWin32Channel *) data->channel;
+  
+  /* If the thread has died, we have encountered EOF. If the buffer
+   * also is emtpty set the HUP bit.
+   */
+  if (!channel->running && channel->rdp == channel->wrp)
+    {
+      if (channel->debug)
+       g_print ("g_io_win32_check: setting G_IO_HUP thread %#x rdp=%d wrp=%d\n",
+                channel->thread_id, channel->rdp, channel->wrp);
+      data->pollfd.revents |= G_IO_HUP;
+      return TRUE;
+    }
+  
+  return (data->pollfd.revents & data->condition);
 }
 
 static gboolean
-g_io_win32_msg_dispatch (gpointer source_data, 
-                        GTimeVal *current_time,
-                        gpointer user_data)
-
+g_io_win32_dispatch (gpointer  source_data,
+                    GTimeVal *current_time,
+                    gpointer  user_data)
+     
 {
   GIOWin32Watch *data = source_data;
-
-  return (*data->callback)(data->channel,
-                          data->pollfd.revents & data->condition,
-                          user_data);
+  
+  return (*data->callback) (data->channel,
+                           data->pollfd.revents & data->condition,
+                           user_data);
 }
 
 static void
 g_io_win32_destroy (gpointer source_data)
 {
   GIOWin32Watch *data = source_data;
-
+  
   g_main_remove_poll (&data->pollfd);
   g_io_channel_unref (data->channel);
   g_free (data);
 }
 
-static gboolean
-g_io_win32_fd_prepare  (gpointer source_data, 
-                       GTimeVal *current_time,
-                       gint    *timeout)
-{
-  *timeout = -1;
-
-  return FALSE;
-}
+static GSourceFuncs win32_watch_funcs = {
+  g_io_win32_prepare,
+  g_io_win32_check,
+  g_io_win32_dispatch,
+  g_io_win32_destroy
+};
 
-static gboolean 
-g_io_win32_fd_check    (gpointer source_data,
-                       GTimeVal *current_time)
+static guint
+g_io_win32_add_watch (GIOChannel    *channel,
+                     gint           priority,
+                     GIOCondition   condition,
+                     GIOFunc        func,
+                     gpointer       user_data,
+                     GDestroyNotify notify,
+                     int (*reader) (int, guchar *, int))
 {
-  GIOWin32Watch *data = source_data;
-
-  return (data->pollfd.revents & data->condition);
-}
-
-static gboolean
-g_io_win32_fd_dispatch (gpointer source_data, 
-                       GTimeVal *current_time,
-                       gpointer user_data)
+  GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  
+  watch->channel = channel;
+  g_io_channel_ref (channel);
+  
+  watch->callback = func;
+  watch->condition = condition;
+  
+  if (win32_channel->data_avail_event == NULL)
+    create_events (win32_channel);
 
-{
-  GIOWin32Watch *data = source_data;
+  watch->pollfd.fd = (gint) win32_channel->data_avail_event;
+  watch->pollfd.events = condition;
+  
+  if (win32_channel->debug)
+    g_print ("g_io_win32_add_watch: fd:%d handle:%#x\n",
+            win32_channel->fd, watch->pollfd.fd);
+  
+  if (win32_channel->thread_id == 0)
+    create_reader_thread (win32_channel, reader);
 
-  return (*data->callback)(data->channel,
-                          data->pollfd.revents & data->condition,
-                          user_data);
+  g_main_add_poll (&watch->pollfd, priority);
+  
+  return g_source_add (priority, TRUE, &win32_watch_funcs, watch,
+                      user_data, notify);
 }
 
 static GIOError
-g_io_win32_msg_read (GIOChannel *channel, 
-                    gchar     *buf, 
-                    guint      count,
-                    guint     *bytes_read)
+g_io_win32_msg_read (GIOChannel *channel,
+                    gchar      *buf,
+                    guint       count,
+                    guint      *bytes_read)
 {
   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
-  MSG msg;                     /* In case of alignment problems */
-
+  MSG msg;               /* In case of alignment problems */
+  
   if (count < sizeof (MSG))
     return G_IO_ERROR_INVAL;
   
   if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
     return G_IO_ERROR_AGAIN;
-
+  
   memmove (buf, &msg, sizeof (MSG));
   *bytes_read = sizeof (MSG);
   return G_IO_ERROR_NONE;
 }
-                      
-static GIOError 
-g_io_win32_msg_write(GIOChannel *channel, 
-                    gchar     *buf, 
-                    guint      count,
-                    guint     *bytes_written)
+
+static GIOError
+g_io_win32_msg_write (GIOChannel *channel,
+                     gchar      *buf,
+                     guint       count,
+                     guint      *bytes_written)
 {
   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
   MSG msg;
-  gint result;
-
+  
   if (count != sizeof (MSG))
     return G_IO_ERROR_INVAL;
-
+  
   /* In case of alignment problems */
   memmove (&msg, buf, sizeof (MSG));
   if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
     return G_IO_ERROR_UNKNOWN;
-
+  
   *bytes_written = sizeof (MSG);
-  return G_IO_ERROR_NONE; 
+  return G_IO_ERROR_NONE;
 }
 
-static GIOError 
+static GIOError
 g_io_win32_no_seek (GIOChannel *channel,
-                   gint      offset, 
-                   GSeekType type)
+                   gint        offset,
+                   GSeekType   type)
 {
-  g_warning ("g_io_win32_no_seek: unseekable IO channel type");
   return G_IO_ERROR_UNKNOWN;
 }
 
-
-static void 
+static void
 g_io_win32_msg_close (GIOChannel *channel)
 {
   /* Nothing to be done. Or should we set hwnd to some invalid value? */
 }
 
-static void 
+static void
 g_io_win32_free (GIOChannel *channel)
 {
   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  
+  if (win32_channel->buffer)
+    {
+      CloseHandle (win32_channel->data_avail_event);
+      CloseHandle (win32_channel->space_avail_event);
+      DeleteCriticalSection (&win32_channel->mutex);
+    }
 
+  g_free (win32_channel->buffer);
   g_free (win32_channel);
 }
 
-static guint 
+static guint
 g_io_win32_msg_add_watch (GIOChannel    *channel,
                          gint           priority,
                          GIOCondition   condition,
@@ -426,117 +499,60 @@ g_io_win32_msg_add_watch (GIOChannel    *channel,
                          GDestroyNotify notify)
 {
   GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
-  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
   
   watch->channel = channel;
   g_io_channel_ref (channel);
-
+  
   watch->callback = func;
   watch->condition = condition;
-
+  
   watch->pollfd.fd = G_WIN32_MSG_HANDLE;
   watch->pollfd.events = condition;
-
+  
   g_main_add_poll (&watch->pollfd, priority);
-
-  return g_source_add (priority, TRUE, &win32_watch_msg_funcs,
+  
+  return g_source_add (priority, TRUE, &win32_watch_funcs,
                       watch, user_data, notify);
 }
 
-static gboolean
-g_io_win32_pipe_prepare  (gpointer source_data, 
-                         GTimeVal *current_time,
-                         gint    *timeout)
-{
-  *timeout = -1;
-
-  return FALSE;
-}
-
-static gboolean 
-g_io_win32_pipe_check    (gpointer source_data,
-                         GTimeVal *current_time)
-{
-  GIOWin32Watch *data = source_data;
-  return FALSE;
-}
-
-static gboolean
-g_io_win32_pipe_dispatch (gpointer source_data, 
-                         GTimeVal *current_time,
-                         gpointer user_data)
-
-{
-  GIOWin32Watch *data = source_data;
-
-  return (*data->callback)(data->channel,
-                          data->pollfd.revents & data->condition,
-                          user_data);
-}
-
-static void
-g_io_win32_pipe_destroy (gpointer source_data)
-{
-  GIOWin32Watch *data = source_data;
-
-  g_io_channel_unref (data->channel);
-  g_free (data);
-}
-
-static gboolean
-g_io_win32_sock_prepare  (gpointer source_data, 
-                       GTimeVal *current_time,
-                       gint    *timeout)
-{
-  *timeout = -1;
-
-  return FALSE;
-}
-
-static gboolean 
-g_io_win32_sock_check    (gpointer source_data,
-                       GTimeVal *current_time)
-{
-  GIOWin32Watch *data = source_data;
-
-  return (data->pollfd.revents & data->condition);
-}
-
-static gboolean
-g_io_win32_sock_dispatch (gpointer source_data, 
-                       GTimeVal *current_time,
-                       gpointer user_data)
-
-{
-  GIOWin32Watch *data = source_data;
-
-  return (*data->callback)(data->channel,
-                          data->pollfd.revents & data->condition,
-                          user_data);
-}
-
 static GIOError
-g_io_win32_fd_read (GIOChannel *channel, 
-                   gchar     *buf, 
-                   guint      count,
-                   guint     *bytes_read)
+g_io_win32_fd_read (GIOChannel *channel,
+                   gchar      *buf,
+                   guint       count,
+                   guint      *bytes_read)
 {
   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
   gint result;
+  GIOError error;
+  
+  if (win32_channel->debug)
+    g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
+            win32_channel->fd, count);
+  
+  if (win32_channel->thread_id)
+    {
+      result = buffer_read (win32_channel, buf, count, &error);
+      if (result < 0)
+       {
+         *bytes_read = 0;
+         return error;
+       }
+      else
+       {
+         *bytes_read = result;
+         return G_IO_ERROR_NONE;
+       }
+    }
 
   result = read (win32_channel->fd, buf, count);
+
   if (result < 0)
     {
       *bytes_read = 0;
-      switch (errno)
-       {
-       case EINVAL:
-         return G_IO_ERROR_INVAL;
-       case EAGAIN:
-         return G_IO_ERROR_AGAIN;
-       default:
-         return G_IO_ERROR_UNKNOWN;
-       }
+      if (errno == EINVAL)
+       return G_IO_ERROR_INVAL;
+      else
+       return G_IO_ERROR_UNKNOWN;
     }
   else
     {
@@ -544,18 +560,21 @@ g_io_win32_fd_read (GIOChannel *channel,
       return G_IO_ERROR_NONE;
     }
 }
-                      
-static GIOError 
-g_io_win32_fd_write(GIOChannel *channel, 
-                   gchar     *buf, 
-                   guint      count,
-                   guint     *bytes_written)
+
+static GIOError
+g_io_win32_fd_write (GIOChannel *channel,
+                    gchar      *buf,
+                    guint       count,
+                    guint      *bytes_written)
 {
   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
   gint result;
-
+  
   result = write (win32_channel->fd, buf, count);
-      
+  if (win32_channel->debug)
+    g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
+            win32_channel->fd, count, result);
+  
   if (result < 0)
     {
       *bytes_written = 0;
@@ -576,15 +595,15 @@ g_io_win32_fd_write(GIOChannel *channel,
     }
 }
 
-static GIOError 
+static GIOError
 g_io_win32_fd_seek (GIOChannel *channel,
-                   gint      offset, 
-                   GSeekType type)
+                   gint        offset,
+                   GSeekType   type)
 {
   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
   int whence;
   off_t result;
-
+  
   switch (type)
     {
     case G_SEEK_SET:
@@ -617,16 +636,24 @@ g_io_win32_fd_seek (GIOChannel *channel,
     return G_IO_ERROR_NONE;
 }
 
-static void 
+static void
 g_io_win32_fd_close (GIOChannel *channel)
 {
   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
-
+  
   close (win32_channel->fd);
   return;
 }
 
-static guint 
+static int
+fd_reader (int     fd,
+          guchar *buf,
+          int     len)
+{
+  return read (fd, buf, len);
+}
+
+static guint
 g_io_win32_fd_add_watch (GIOChannel    *channel,
                         gint           priority,
                         GIOCondition   condition,
@@ -634,208 +661,41 @@ g_io_win32_fd_add_watch (GIOChannel    *channel,
                         gpointer       user_data,
                         GDestroyNotify notify)
 {
-  GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
-  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
-  
-  watch->channel = channel;
-  g_io_channel_ref (channel);
-
-  watch->callback = func;
-  watch->condition = condition;
-
-  /* This probably does not work, except for CONIN$. */
-  watch->pollfd.fd = _get_osfhandle (win32_channel->fd);
-  watch->pollfd.events = condition;
-
-  g_main_add_poll (&watch->pollfd, priority);
-
-  return g_source_add (priority, TRUE, &win32_watch_fd_funcs,
-                      watch, user_data, notify);
+  return g_io_win32_add_watch (channel, priority, condition,
+                              func, user_data, notify, fd_reader);
 }
 
 static GIOError
-g_io_win32_pipe_read (GIOChannel *channel, 
-                     gchar     *buf, 
-                     guint      count,
-                     guint     *bytes_read)
-{
-  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
-  HANDLE handle;
-  DWORD avail;
-  gint result;
-
-  handle = (HANDLE) _get_osfhandle (win32_channel->fd);
-  if (!PeekNamedPipe (handle, NULL, 0, NULL, &avail, NULL))
-    {
-      return G_IO_ERROR_UNKNOWN;
-    }
-
-  count = MIN (count, avail);
-
-  count = MAX (count, 1);      /* Must read at least one byte, or
-                                * caller will think it's EOF.
-                                */
-  /* g_print ("g_io_win32_pipe_read: %d %d\n", win32_channel->fd, count); */
-  if (count == 0)
-    result = 0;
-  else
-    result = read (win32_channel->fd, buf, count);
-  if (result < 0)
-    {
-      *bytes_read = 0;
-      switch (errno)
-       {
-       case EINVAL:
-         return G_IO_ERROR_INVAL;
-       case EAGAIN:
-         return G_IO_ERROR_AGAIN;
-       default:
-         return G_IO_ERROR_UNKNOWN;
-       }
-    }
-  else
-    {
-      *bytes_read = result;
-      win32_channel->offset += result;
-      /* g_print ("=%d (%d)\n", result, win32_channel->offset); */
-      return G_IO_ERROR_NONE;
-    }
-}
-                      
-static GIOError 
-g_io_win32_pipe_write(GIOChannel *channel, 
-                     gchar     *buf, 
-                     guint      count,
-                     guint     *bytes_written)
+g_io_win32_sock_read (GIOChannel *channel,
+                     gchar      *buf,
+                     guint       count,
+                     guint      *bytes_read)
 {
   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
-  LONG prevcnt;
   gint result;
-
-  /* g_print ("g_io_win32_pipe_write: %d %d\n", win32_channel->fd, count); */
-  result = write (win32_channel->fd, buf, count);
-  if (result < 0)
+  GIOError error;
+  
+  if (win32_channel->thread_id)
     {
-      *bytes_written = 0;
-      switch (errno)
+      result = buffer_read (win32_channel, buf, count, &error);
+      if (result < 0)
        {
-       case EINVAL:
-         return G_IO_ERROR_INVAL;
-       case EAGAIN:
-         return G_IO_ERROR_AGAIN;
-       default:
-         return G_IO_ERROR_UNKNOWN;
+         *bytes_read = 0;
+         return error;
        }
-    }
-  else
-    {
-      if (g_pipe_readable_msg == 0)
-       g_pipe_readable_msg = RegisterWindowMessage ("g-pipe-readable");
-
-      win32_channel->offset += result;
-      /* g_print ("=%d (%d)\n", result, win32_channel->offset); */
-      if (win32_channel->need_wakeups)
+      else
        {
-         PostThreadMessage (win32_channel->peer,
-                            g_pipe_readable_msg,
-                            win32_channel->peer_fd,
-                            win32_channel->offset);
+         *bytes_read = result;
+         return G_IO_ERROR_NONE;
        }
-      *bytes_written = result;
-      return G_IO_ERROR_NONE;
     }
-}
-
-static void 
-g_io_win32_pipe_close (GIOChannel *channel)
-{
-  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
-
-  /* g_print ("g_io_win32_pipe_close: %#x %d\n", channel, win32_channel->fd); */
-
-  close (win32_channel->fd);
-  return;
-}
-
-static guint 
-g_io_win32_pipe_add_watch (GIOChannel    *channel,
-                          gint           priority,
-                          GIOCondition   condition,
-                          GIOFunc        func,
-                          gpointer       user_data,
-                          GDestroyNotify notify)
-{
-  GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
-  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
-  gint i;
-  
-  /* g_print ("g_io_win32_pipe_add_watch: %d\n", win32_channel->fd); */
-
-  watch->channel = channel;
-  g_io_channel_ref (channel);
-
-  watch->callback = func;
-  watch->condition = condition;
-
-  watch->pollfd.fd = win32_channel->fd;
-  watch->pollfd.events = condition;
-
-  for (i = 0; i < n_watched_pipes; i++)
-    if (watched_pipes[i].fd == -1)
-      break;
-  if (i == N_WATCHED_PIPES)
-    g_error ("Too many watched pipes");
-  else
-    {
-      watched_pipes[i].fd = win32_channel->fd;
-      watched_pipes[i].watch = watch;
-      watched_pipes[i].channel = win32_channel;
-      watched_pipes[i].user_data = user_data;
-      n_watched_pipes = MAX (i + 1, n_watched_pipes);
-    }
-  return g_source_add (priority, FALSE, &win32_watch_pipe_funcs, watch, user_data, notify);
-}
-
-static void
-g_io_win32_pipe_free (GIOChannel *channel)
-{
-  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
-  gint i;
-
-  /* g_print ("g_io_win32_pipe_free: %#x %#x\n", channel, channel->channel_data); */
-
-  for (i = 0; i < n_watched_pipes; i++)
-    if (watched_pipes[i].fd == win32_channel->fd)
-      {
-       watched_pipes[i].fd = -1;
-       break;
-      }
-  g_io_win32_free (channel);
-}
-
-static GIOError 
-g_io_win32_sock_read (GIOChannel *channel, 
-                     gchar      *buf, 
-                     guint       count,
-                     guint      *bytes_read)
-{
-  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
-  gint result;
 
   result = recv (win32_channel->fd, buf, count, 0);
-  if (result == SOCKET_ERROR)
+
+  if (result < 0)
     {
       *bytes_read = 0;
-      switch (WSAGetLastError ())
-       {
-       case WSAEINVAL:
-         return G_IO_ERROR_INVAL;
-       case WSAEWOULDBLOCK:
-       case WSAEINTR:
-         return G_IO_ERROR_AGAIN;
-       default:
-         return G_IO_ERROR_UNKNOWN;
-       }
+      return G_IO_ERROR_UNKNOWN;
     }
   else
     {
@@ -843,18 +703,18 @@ g_io_win32_sock_read (GIOChannel *channel,
       return G_IO_ERROR_NONE;
     }
 }
-                      
-static GIOError 
-g_io_win32_sock_write(GIOChannel *channel, 
-                     gchar      *buf, 
-                     guint       count,
-                     guint      *bytes_written)
+
+static GIOError
+g_io_win32_sock_write (GIOChannel *channel,
+                      gchar      *buf,
+                      guint       count,
+                      guint      *bytes_written)
 {
   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
   gint result;
-
+  
   result = send (win32_channel->fd, buf, count, 0);
-      
+  
   if (result == SOCKET_ERROR)
     {
       *bytes_written = 0;
@@ -876,16 +736,23 @@ g_io_win32_sock_write(GIOChannel *channel,
     }
 }
 
-static void 
+static void
 g_io_win32_sock_close (GIOChannel *channel)
 {
   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
 
   closesocket (win32_channel->fd);
-  return;
 }
 
-static guint 
+static int
+sock_reader (int     fd,
+            guchar *buf,
+            int     len)
+{
+  return recv (fd, buf, len, 0);
+}
+
+static guint
 g_io_win32_sock_add_watch (GIOChannel    *channel,
                           gint           priority,
                           GIOCondition   condition,
@@ -893,22 +760,36 @@ g_io_win32_sock_add_watch (GIOChannel    *channel,
                           gpointer       user_data,
                           GDestroyNotify notify)
 {
-  GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
-  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
-  
-  watch->channel = channel;
-  g_io_channel_ref (channel);
-
-  watch->callback = func;
-  watch->condition = condition;
+  return g_io_win32_add_watch (channel, priority, condition,
+                              func, user_data, notify, sock_reader);
+}
 
-  watch->pollfd.fd = win32_channel->fd;
-  watch->pollfd.events = condition;
+static GIOFuncs win32_channel_msg_funcs = {
+  g_io_win32_msg_read,
+  g_io_win32_msg_write,
+  g_io_win32_no_seek,
+  g_io_win32_msg_close,
+  g_io_win32_msg_add_watch,
+  g_io_win32_free
+};
 
-  g_main_add_poll (&watch->pollfd, priority);
+static GIOFuncs win32_channel_fd_funcs = {
+  g_io_win32_fd_read,
+  g_io_win32_fd_write,
+  g_io_win32_fd_seek,
+  g_io_win32_fd_close,
+  g_io_win32_fd_add_watch,
+  g_io_win32_free
+};
 
-  return g_source_add (priority, TRUE, &win32_watch_sock_funcs, watch, user_data, notify);
-}
+static GIOFuncs win32_channel_sock_funcs = {
+  g_io_win32_sock_read,
+  g_io_win32_sock_write,
+  g_io_win32_no_seek,
+  g_io_win32_sock_close,
+  g_io_win32_sock_add_watch,
+  g_io_win32_free
+};
 
 GIOChannel *
 g_io_channel_win32_new_messages (guint hwnd)
@@ -917,8 +798,8 @@ g_io_channel_win32_new_messages (guint hwnd)
   GIOChannel *channel = (GIOChannel *) win32_channel;
 
   g_io_channel_init (channel);
+  g_io_channel_win32_init (win32_channel);
   channel->funcs = &win32_channel_msg_funcs;
-  win32_channel->fd = -1;
   win32_channel->type = G_IO_WINDOWS_MESSAGES;
   win32_channel->hwnd = (HWND) hwnd;
 
@@ -926,21 +807,32 @@ g_io_channel_win32_new_messages (guint hwnd)
 }
 
 GIOChannel *
-g_io_channel_unix_new (gint fd)
+g_io_channel_win32_new_fd (gint fd)
 {
-  GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
-  GIOChannel *channel = (GIOChannel *) win32_channel;
+  GIOWin32Channel *win32_channel;
+  GIOChannel *channel;
+  struct stat st;
+
+  if (fstat (fd, &st) == -1)
+    {
+      g_warning ("%d isn't a (emulated) file descriptor", fd);
+      return NULL;
+    }
+
+  win32_channel = g_new (GIOWin32Channel, 1);
+  channel = (GIOChannel *) win32_channel;
 
   g_io_channel_init (channel);
+  g_io_channel_win32_init (win32_channel);
   channel->funcs = &win32_channel_fd_funcs;
-  win32_channel->fd = fd;
   win32_channel->type = G_IO_FILE_DESC;
+  win32_channel->fd = fd;
 
   return channel;
 }
 
 gint
-g_io_channel_unix_get_fd (GIOChannel *channel)
+g_io_channel_win32_get_fd (GIOChannel *channel)
 {
   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
 
@@ -948,61 +840,96 @@ g_io_channel_unix_get_fd (GIOChannel *channel)
 }
 
 GIOChannel *
-g_io_channel_win32_new_pipe_with_wakeups (int   fd,
-                                         guint peer,
-                                         int   peer_fd)
+g_io_channel_win32_new_stream_socket (int socket)
 {
   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
   GIOChannel *channel = (GIOChannel *) win32_channel;
 
-  /* g_print ("g_io_channel_win32_new_pipe_with_wakeups %d %#x %d\n", fd, peer, peer_fd); */
-
   g_io_channel_init (channel);
-  channel->funcs = &win32_channel_pipe_funcs;
-  win32_channel->fd = fd;
-  win32_channel->type = G_IO_PIPE;
-  win32_channel->peer = peer;
-  win32_channel->peer_fd = peer_fd;
-  win32_channel->offset = 0;
-  win32_channel->need_wakeups = TRUE;
+  g_io_channel_win32_init (win32_channel);
+  channel->funcs = &win32_channel_sock_funcs;
+  win32_channel->type = G_IO_STREAM_SOCKET;
+  win32_channel->fd = socket;
 
   return channel;
 }
 
 GIOChannel *
-g_io_channel_win32_new_pipe (int fd)
+g_io_channel_unix_new (gint fd)
 {
-  GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
-  GIOChannel *channel = (GIOChannel *) win32_channel;
+  return g_io_channel_win32_new_fd (fd);
+}
 
-  g_io_channel_init (channel);
-  channel->funcs = &win32_channel_pipe_funcs;
-  win32_channel->fd = fd;
-  win32_channel->type = G_IO_PIPE;
-  win32_channel->offset = 0;
-  win32_channel->need_wakeups = FALSE;
+gint
+g_io_channel_unix_get_fd (GIOChannel *channel)
+{
+  return g_io_channel_win32_get_fd (channel);
+}
 
-  return channel;
+void
+g_io_channel_win32_set_debug (GIOChannel *channel,
+                             gboolean    flag)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+
+  win32_channel->debug = flag;
 }
 
-GIOChannel *
-g_io_channel_win32_new_stream_socket (int socket)
+gint
+g_io_channel_win32_poll (GPollFD *fds,
+                        gint     n_fds,
+                        gint     timeout)
 {
-  GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
-  GIOChannel *channel = (GIOChannel *) win32_channel;
+  int result;
 
-  g_io_channel_init (channel);
-  channel->funcs = &win32_channel_sock_funcs;
-  win32_channel->fd = socket;
-  win32_channel->type = G_IO_STREAM_SOCKET;
+  g_return_val_if_fail (n_fds >= 0, 0);
 
-  return channel;
+  result = (*g_main_win32_get_poll_func ()) (fds, n_fds, timeout);
+
+  return result;
 }
 
-gint
-g_io_channel_win32_get_fd (GIOChannel *channel)
+void
+g_io_channel_win32_make_pollfd (GIOChannel   *channel,
+                               GIOCondition  condition,
+                               GPollFD      *fd)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+
+  if (win32_channel->data_avail_event == NULL)
+    create_events (win32_channel);
+  
+  fd->fd = (gint) win32_channel->data_avail_event;
+  fd->events = condition;
+
+  if (win32_channel->thread_id == 0)
+    if (win32_channel->type == G_IO_FILE_DESC)
+      create_reader_thread (win32_channel, fd_reader);
+    else if (win32_channel->type == G_IO_STREAM_SOCKET)
+      create_reader_thread (win32_channel, sock_reader);
+}
+
+/* This variable and the functions below are present just to be 
+ * binary compatible with old clients... But note that in GIMP, the
+ * libgimp/gimp.c:gimp_extension_process() function will have to be modified
+ * anyhow for this new approach.
+ *
+ * These will be removed after some weeks.
+ */
+guint g_pipe_readable_msg = 0;
+
+GIOChannel *
+g_io_channel_win32_new_pipe (int fd)
 {
-  return g_io_channel_unix_get_fd (channel);
+  return g_io_channel_win32_new_fd (fd);
+}
+
+GIOChannel *
+g_io_channel_win32_new_pipe_with_wakeups (int   fd,
+                                         guint peer,
+                                         int   peer_fd)
+{
+  return g_io_channel_win32_new_fd (fd);
 }
 
 void
@@ -1010,26 +937,13 @@ g_io_channel_win32_pipe_request_wakeups (GIOChannel *channel,
                                         guint       peer,
                                         int         peer_fd)
 {
-  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
-
-  win32_channel->peer = peer;
-  win32_channel->peer_fd = peer_fd;
-  win32_channel->need_wakeups = TRUE;
+  /* Nothing needed now */
 }
 
 void
 g_io_channel_win32_pipe_readable (gint  fd,
                                  guint offset)
 {
-  gint i;
-
-  for (i = 0; i < n_watched_pipes; i++)
-    if (watched_pipes[i].fd == fd)
-      {
-       if ((watched_pipes[i].watch->condition & G_IO_IN)
-           && watched_pipes[i].channel->offset < offset)
-         (*watched_pipes[i].watch->callback) (watched_pipes[i].watch->channel,
-                                              G_IO_IN,
-                                              watched_pipes[i].user_data);
-      }
+  /* Nothing needed now */
 }
+