Hmm, the parameter to g_io_channel_win32_poll() should be a GPollFD array,
[platform/upstream/glib.git] / glib / giowin32.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * giowin32.c: IO Channels for Win32.
5  * Copyright 1998 Owen Taylor and Tor Lillqvist
6  * Copyright 1999-2000 Tor Lillqvist and Craig Setera
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 /*
25  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
26  * file for a list of people on the GLib Team.  See the ChangeLog
27  * files for a list of changes.  These files are distributed with
28  * GLib at ftp://ftp.gtk.org/pub/gtk/.
29  */
30
31 /* Define this to get (very) verbose logging of all channels */
32 /* #define G_IO_WIN32_DEBUG */
33
34 #include "glib.h"
35
36 #include <stdlib.h>
37 #include <windows.h>
38 #include <winsock.h>          /* Not everybody has winsock2 */
39 #include <fcntl.h>
40 #include <io.h>
41 #include <process.h>
42 #include <errno.h>
43 #include <sys/stat.h>
44
45 typedef struct _GIOWin32Channel GIOWin32Channel;
46 typedef struct _GIOWin32Watch GIOWin32Watch;
47
48 #define BUFFER_SIZE 4096
49
50 typedef enum {
51   G_IO_WINDOWS_MESSAGES,        /* Windows messages */
52   G_IO_FILE_DESC,               /* Unix-like file descriptors from
53                                  * _open() or _pipe(). Read with read().
54                                  * Have to create separate thread to read.
55                                  */
56   G_IO_STREAM_SOCKET            /* Stream sockets. Similar as fds, but
57                                  * read with recv().
58                                  */
59 } GIOWin32ChannelType;
60
61 struct _GIOWin32Channel {
62   GIOChannel channel;
63   gint fd;                      /* Either a Unix-like file handle as provided
64                                  * by the Microsoft C runtime, or a SOCKET
65                                  * as provided by WinSock.
66                                  */
67   GIOWin32ChannelType type;
68   
69   gboolean debug;
70
71   /* This is used by G_IO_WINDOWS_MESSAGES channels */
72   HWND hwnd;                    /* handle of window, or NULL */
73   
74   /* Following fields used by fd and socket channels for input */
75   
76   /* Data is kept in a circular buffer. To be able to distinguish between
77    * empty and full buffer, we cannot fill it completely, but have to
78    * leave a one character gap.
79    *
80    * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
81    *
82    * Empty:    wrp == rdp
83    * Full:     (wrp + 1) % BUFFER_SIZE == rdp
84    * Partial:  otherwise
85    */
86   guchar *buffer;               /* (Circular) buffer */
87   gint wrp, rdp;                /* Buffer indices for writing and reading */
88   gboolean running;             /* Is reader thread running. FALSE if
89                                  * EOF has been reached.
90                                  */
91   guint thread_id;              /* If non-NULL has a reader thread, or has
92                                  * had.*/
93   HANDLE data_avail_event;
94   HANDLE space_avail_event;
95   CRITICAL_SECTION mutex;
96   
97   /* Function that actually reads from fd */
98   int (*reader) (int fd, guchar *buf, int len);
99 };
100
101 #define LOCK(mutex) EnterCriticalSection (&mutex)
102 #define UNLOCK(mutex) LeaveCriticalSection (&mutex)
103
104 struct _GIOWin32Watch {
105   GPollFD       pollfd;
106   GIOChannel   *channel;
107   GIOCondition  condition;
108   GIOFunc       callback;
109 };
110
111 static void
112 g_io_channel_win32_init (GIOWin32Channel *channel)
113 {
114 #ifdef G_IO_WIN32_DEBUG
115   channel->debug = TRUE;
116 #else
117   if (getenv ("G_IO_WIN32_DEBUG") != NULL)
118     channel->debug = TRUE;
119   else
120     channel->debug = FALSE;
121 #endif
122   channel->buffer = NULL;
123   channel->running = FALSE;
124   channel->thread_id = 0;
125   channel->data_avail_event = NULL;
126   channel->space_avail_event = NULL;
127 }
128
129 static void
130 create_events (GIOWin32Channel *channel)
131 {
132   SECURITY_ATTRIBUTES sec_attrs;
133   
134   sec_attrs.nLength = sizeof(SECURITY_ATTRIBUTES);
135   sec_attrs.lpSecurityDescriptor = NULL;
136   sec_attrs.bInheritHandle = FALSE;
137
138   /* The data available event is manual reset, the space available event
139    * is automatic reset.
140    */
141   if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
142       || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
143     {
144       gchar *msg = g_win32_error_message (GetLastError ());
145       g_error ("Error creating event: %s", msg);
146     }
147   InitializeCriticalSection (&channel->mutex);
148 }
149
150 static unsigned __stdcall
151 reader_thread (void *parameter)
152 {
153   GIOWin32Channel *channel = parameter;
154   guchar *buffer;
155   guint nbytes;
156
157   g_io_channel_ref ((GIOChannel *) channel);
158
159   if (channel->debug)
160     g_print ("thread %#x: starting. pid:%#x, fd:%d, data_avail:%#x, space_avail:%#x\n",
161              channel->thread_id,
162              (guint) GetCurrentProcessId (),
163              channel->fd,
164              (guint) channel->data_avail_event,
165              (guint) channel->space_avail_event);
166   
167   channel->buffer = g_malloc (BUFFER_SIZE);
168   channel->rdp = channel->wrp = 0;
169   channel->running = TRUE;
170
171   SetEvent (channel->space_avail_event);
172   
173   while (channel->running)
174     {
175       LOCK (channel->mutex);
176       if (channel->debug)
177         g_print ("thread %#x: rdp=%d, wrp=%d\n",
178                  channel->thread_id, channel->rdp, channel->wrp);
179       if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
180         {
181           /* Buffer is full */
182           if (channel->debug)
183             g_print ("thread %#x: resetting space_available\n",
184                      channel->thread_id);
185           ResetEvent (channel->space_avail_event);
186           if (channel->debug)
187             g_print ("thread %#x: waiting for space\n", channel->thread_id);
188           UNLOCK (channel->mutex);
189           WaitForSingleObject (channel->space_avail_event, INFINITE);
190           LOCK (channel->mutex);
191           if (channel->debug)
192             g_print ("thread %#x: rdp=%d, wrp=%d\n",
193                      channel->thread_id, channel->rdp, channel->wrp);
194         }
195       
196       buffer = channel->buffer + channel->wrp;
197       
198       /* Always leave at least one byte unused gap to be able to
199        * distinguish between the full and empty condition...
200        */
201       nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
202                     BUFFER_SIZE - channel->wrp);
203
204       UNLOCK (channel->mutex);
205
206       nbytes = (*channel->reader) (channel->fd, buffer, nbytes);
207       
208       if (nbytes <= 0)
209         break;
210
211       LOCK (channel->mutex);
212       if (channel->debug)
213         g_print ("thread %#x: got %d bytes, rdp=%d, wrp=%d\n",
214                  channel->thread_id, nbytes, channel->rdp, channel->wrp);
215       channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
216       if (channel->debug)
217         g_print ("thread %#x: rdp=%d, wrp=%d, setting data available\n",
218                  channel->thread_id, channel->rdp, channel->wrp);
219       SetEvent (channel->data_avail_event);
220       UNLOCK (channel->mutex);
221     }
222   
223   LOCK (channel->mutex);
224   channel->running = FALSE;
225   if (channel->debug)
226     g_print ("thread %#x: got EOF, rdp=%d, wrp=%d, setting data available\n",
227              channel->thread_id, channel->rdp, channel->wrp);
228   SetEvent (channel->data_avail_event);
229   UNLOCK (channel->mutex);
230   
231   g_io_channel_unref((GIOChannel *) channel);
232   
233   /* All of the Microsoft docs say we should explicitly
234    * end the thread...
235    */
236   _endthreadex(1);
237   
238   return 0;
239 }
240
241 static void
242 create_reader_thread (GIOWin32Channel *channel,
243                       gpointer         reader)
244 {
245   channel->reader = reader;
246
247   if (_beginthreadex (NULL, 0, reader_thread, channel, 0,
248                       &channel->thread_id) == 0)
249     g_warning ("Error creating reader thread: %s", strerror (errno));
250   WaitForSingleObject (channel->space_avail_event, INFINITE);
251 }
252
253 static int
254 buffer_read (GIOWin32Channel *channel,
255              guchar          *dest,
256              guint            count,
257              GIOError        *error)
258 {
259   guint nbytes;
260   guint left = count;
261   
262   LOCK (channel->mutex);
263   if (channel->debug)
264     g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
265              channel->thread_id, count, channel->rdp, channel->wrp);
266   
267   if (channel->rdp == channel->wrp)
268     {
269       UNLOCK (channel->mutex);
270       if (channel->debug)
271         g_print ("waiting for data from thread %#x\n", channel->thread_id);
272       WaitForSingleObject (channel->data_avail_event, INFINITE);
273       LOCK (channel->mutex);
274       if (channel->rdp == channel->wrp && !channel->running)
275         {
276           UNLOCK (channel->mutex);
277           return 0;
278         }
279     }
280   
281   if (channel->rdp < channel->wrp)
282     nbytes = channel->wrp - channel->rdp;
283   else
284     nbytes = BUFFER_SIZE - channel->rdp;
285   UNLOCK (channel->mutex);
286   nbytes = MIN (left, nbytes);
287   if (channel->debug)
288     g_print ("moving %d bytes from thread %#x\n",
289              nbytes, channel->thread_id);
290   memcpy (dest, channel->buffer + channel->rdp, nbytes);
291   dest += nbytes;
292   left -= nbytes;
293   LOCK (channel->mutex);
294   channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
295   if (channel->debug)
296     g_print ("setting space available for thread %#x\n", channel->thread_id);
297   SetEvent (channel->space_avail_event);
298   if (channel->debug)
299     g_print ("for thread %#x: rdp=%d, wrp=%d\n",
300              channel->thread_id, channel->rdp, channel->wrp);
301   if (channel->running && channel->rdp == channel->wrp)
302     {
303       if (channel->debug)
304         g_print ("resetting data_available of thread %#x\n",
305                  channel->thread_id);
306       ResetEvent (channel->data_avail_event);
307     };
308   UNLOCK (channel->mutex);
309   
310   /* We have no way to indicate any errors form the actual
311    * read() or recv() call in the reader thread. Should we have?
312    */
313   *error = G_IO_ERROR_NONE;
314   return count - left;
315 }
316
317 static gboolean
318 g_io_win32_prepare (gpointer  source_data,
319                     GTimeVal *current_time,
320                     gint     *timeout,
321                     gpointer  user_data)
322 {
323   *timeout = -1;
324   
325   return FALSE;
326 }
327
328 static gboolean
329 g_io_win32_check (gpointer  source_data,
330                   GTimeVal *current_time,
331                   gpointer  user_data)
332 {
333   GIOWin32Watch *data = source_data;
334   GIOWin32Channel *channel = (GIOWin32Channel *) data->channel;
335   
336   /* If the thread has died, we have encountered EOF. If the buffer
337    * also is emtpty set the HUP bit.
338    */
339   if (!channel->running && channel->rdp == channel->wrp)
340     {
341       if (channel->debug)
342         g_print ("g_io_win32_check: setting G_IO_HUP thread %#x rdp=%d wrp=%d\n",
343                  channel->thread_id, channel->rdp, channel->wrp);
344       data->pollfd.revents |= G_IO_HUP;
345       return TRUE;
346     }
347   
348   return (data->pollfd.revents & data->condition);
349 }
350
351 static gboolean
352 g_io_win32_dispatch (gpointer  source_data,
353                      GTimeVal *current_time,
354                      gpointer  user_data)
355      
356 {
357   GIOWin32Watch *data = source_data;
358   
359   return (*data->callback) (data->channel,
360                             data->pollfd.revents & data->condition,
361                             user_data);
362 }
363
364 static void
365 g_io_win32_destroy (gpointer source_data)
366 {
367   GIOWin32Watch *data = source_data;
368   
369   g_main_remove_poll (&data->pollfd);
370   g_io_channel_unref (data->channel);
371   g_free (data);
372 }
373
374 static GSourceFuncs win32_watch_funcs = {
375   g_io_win32_prepare,
376   g_io_win32_check,
377   g_io_win32_dispatch,
378   g_io_win32_destroy
379 };
380
381 static guint
382 g_io_win32_add_watch (GIOChannel    *channel,
383                       gint           priority,
384                       GIOCondition   condition,
385                       GIOFunc        func,
386                       gpointer       user_data,
387                       GDestroyNotify notify,
388                       int (*reader) (int, guchar *, int))
389 {
390   GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
391   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
392   
393   watch->channel = channel;
394   g_io_channel_ref (channel);
395   
396   watch->callback = func;
397   watch->condition = condition;
398   
399   if (win32_channel->data_avail_event == NULL)
400     create_events (win32_channel);
401
402   watch->pollfd.fd = (gint) win32_channel->data_avail_event;
403   watch->pollfd.events = condition;
404   
405   if (win32_channel->debug)
406     g_print ("g_io_win32_add_watch: fd:%d handle:%#x\n",
407              win32_channel->fd, watch->pollfd.fd);
408   
409   if (win32_channel->thread_id == 0)
410     create_reader_thread (win32_channel, reader);
411
412   g_main_add_poll (&watch->pollfd, priority);
413   
414   return g_source_add (priority, TRUE, &win32_watch_funcs, watch,
415                        user_data, notify);
416 }
417
418 static GIOError
419 g_io_win32_msg_read (GIOChannel *channel,
420                      gchar      *buf,
421                      guint       count,
422                      guint      *bytes_read)
423 {
424   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
425   MSG msg;               /* In case of alignment problems */
426   
427   if (count < sizeof (MSG))
428     return G_IO_ERROR_INVAL;
429   
430   if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
431     return G_IO_ERROR_AGAIN;
432   
433   memmove (buf, &msg, sizeof (MSG));
434   *bytes_read = sizeof (MSG);
435   return G_IO_ERROR_NONE;
436 }
437
438 static GIOError
439 g_io_win32_msg_write (GIOChannel *channel,
440                       gchar      *buf,
441                       guint       count,
442                       guint      *bytes_written)
443 {
444   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
445   MSG msg;
446   
447   if (count != sizeof (MSG))
448     return G_IO_ERROR_INVAL;
449   
450   /* In case of alignment problems */
451   memmove (&msg, buf, sizeof (MSG));
452   if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
453     return G_IO_ERROR_UNKNOWN;
454   
455   *bytes_written = sizeof (MSG);
456   return G_IO_ERROR_NONE;
457 }
458
459 static GIOError
460 g_io_win32_no_seek (GIOChannel *channel,
461                     gint        offset,
462                     GSeekType   type)
463 {
464   return G_IO_ERROR_UNKNOWN;
465 }
466
467 static void
468 g_io_win32_msg_close (GIOChannel *channel)
469 {
470   /* Nothing to be done. Or should we set hwnd to some invalid value? */
471 }
472
473 static void
474 g_io_win32_free (GIOChannel *channel)
475 {
476   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
477   
478   if (win32_channel->buffer)
479     {
480       CloseHandle (win32_channel->data_avail_event);
481       CloseHandle (win32_channel->space_avail_event);
482       DeleteCriticalSection (&win32_channel->mutex);
483     }
484
485   g_free (win32_channel->buffer);
486   g_free (win32_channel);
487 }
488
489 static guint
490 g_io_win32_msg_add_watch (GIOChannel    *channel,
491                           gint           priority,
492                           GIOCondition   condition,
493                           GIOFunc        func,
494                           gpointer       user_data,
495                           GDestroyNotify notify)
496 {
497   GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
498   
499   watch->channel = channel;
500   g_io_channel_ref (channel);
501   
502   watch->callback = func;
503   watch->condition = condition;
504   
505   watch->pollfd.fd = G_WIN32_MSG_HANDLE;
506   watch->pollfd.events = condition;
507   
508   g_main_add_poll (&watch->pollfd, priority);
509   
510   return g_source_add (priority, TRUE, &win32_watch_funcs,
511                        watch, user_data, notify);
512 }
513
514 static GIOError
515 g_io_win32_fd_read (GIOChannel *channel,
516                     gchar      *buf,
517                     guint       count,
518                     guint      *bytes_read)
519 {
520   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
521   gint result;
522   GIOError error;
523   
524   if (win32_channel->debug)
525     g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
526              win32_channel->fd, count);
527   
528   if (win32_channel->thread_id)
529     {
530       result = buffer_read (win32_channel, buf, count, &error);
531       if (result < 0)
532         {
533           *bytes_read = 0;
534           return error;
535         }
536       else
537         {
538           *bytes_read = result;
539           return G_IO_ERROR_NONE;
540         }
541     }
542
543   result = read (win32_channel->fd, buf, count);
544
545   if (result < 0)
546     {
547       *bytes_read = 0;
548       if (errno == EINVAL)
549         return G_IO_ERROR_INVAL;
550       else
551         return G_IO_ERROR_UNKNOWN;
552     }
553   else
554     {
555       *bytes_read = result;
556       return G_IO_ERROR_NONE;
557     }
558 }
559
560 static GIOError
561 g_io_win32_fd_write (GIOChannel *channel,
562                      gchar      *buf,
563                      guint       count,
564                      guint      *bytes_written)
565 {
566   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
567   gint result;
568   
569   result = write (win32_channel->fd, buf, count);
570   if (win32_channel->debug)
571     g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
572              win32_channel->fd, count, result);
573   
574   if (result < 0)
575     {
576       *bytes_written = 0;
577       switch (errno)
578         {
579         case EINVAL:
580           return G_IO_ERROR_INVAL;
581         case EAGAIN:
582           return G_IO_ERROR_AGAIN;
583         default:
584           return G_IO_ERROR_UNKNOWN;
585         }
586     }
587   else
588     {
589       *bytes_written = result;
590       return G_IO_ERROR_NONE;
591     }
592 }
593
594 static GIOError
595 g_io_win32_fd_seek (GIOChannel *channel,
596                     gint        offset,
597                     GSeekType   type)
598 {
599   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
600   int whence;
601   off_t result;
602   
603   switch (type)
604     {
605     case G_SEEK_SET:
606       whence = SEEK_SET;
607       break;
608     case G_SEEK_CUR:
609       whence = SEEK_CUR;
610       break;
611     case G_SEEK_END:
612       whence = SEEK_END;
613       break;
614     default:
615       g_warning ("g_io_win32_fd_seek: unknown seek type");
616       return G_IO_ERROR_UNKNOWN;
617     }
618   
619   result = lseek (win32_channel->fd, offset, whence);
620   
621   if (result < 0)
622     {
623       switch (errno)
624         {
625         case EINVAL:
626           return G_IO_ERROR_INVAL;
627         default:
628           return G_IO_ERROR_UNKNOWN;
629         }
630     }
631   else
632     return G_IO_ERROR_NONE;
633 }
634
635 static void
636 g_io_win32_fd_close (GIOChannel *channel)
637 {
638   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
639   
640   close (win32_channel->fd);
641   return;
642 }
643
644 static int
645 fd_reader (int     fd,
646            guchar *buf,
647            int     len)
648 {
649   return read (fd, buf, len);
650 }
651
652 static guint
653 g_io_win32_fd_add_watch (GIOChannel    *channel,
654                          gint           priority,
655                          GIOCondition   condition,
656                          GIOFunc        func,
657                          gpointer       user_data,
658                          GDestroyNotify notify)
659 {
660   return g_io_win32_add_watch (channel, priority, condition,
661                                func, user_data, notify, fd_reader);
662 }
663
664 static GIOError
665 g_io_win32_sock_read (GIOChannel *channel,
666                       gchar      *buf,
667                       guint       count,
668                       guint      *bytes_read)
669 {
670   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
671   gint result;
672   GIOError error;
673   
674   if (win32_channel->thread_id)
675     {
676       result = buffer_read (win32_channel, buf, count, &error);
677       if (result < 0)
678         {
679           *bytes_read = 0;
680           return error;
681         }
682       else
683         {
684           *bytes_read = result;
685           return G_IO_ERROR_NONE;
686         }
687     }
688
689   result = recv (win32_channel->fd, buf, count, 0);
690
691   if (result < 0)
692     {
693       *bytes_read = 0;
694       return G_IO_ERROR_UNKNOWN;
695     }
696   else
697     {
698       *bytes_read = result;
699       return G_IO_ERROR_NONE;
700     }
701 }
702
703 static GIOError
704 g_io_win32_sock_write (GIOChannel *channel,
705                        gchar      *buf,
706                        guint       count,
707                        guint      *bytes_written)
708 {
709   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
710   gint result;
711   
712   result = send (win32_channel->fd, buf, count, 0);
713   
714   if (result == SOCKET_ERROR)
715     {
716       *bytes_written = 0;
717       switch (WSAGetLastError ())
718         {
719         case WSAEINVAL:
720           return G_IO_ERROR_INVAL;
721         case WSAEWOULDBLOCK:
722         case WSAEINTR:
723           return G_IO_ERROR_AGAIN;
724         default:
725           return G_IO_ERROR_UNKNOWN;
726         }
727     }
728   else
729     {
730       *bytes_written = result;
731       return G_IO_ERROR_NONE;
732     }
733 }
734
735 static void
736 g_io_win32_sock_close (GIOChannel *channel)
737 {
738   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
739
740   closesocket (win32_channel->fd);
741 }
742
743 static int
744 sock_reader (int     fd,
745              guchar *buf,
746              int     len)
747 {
748   return recv (fd, buf, len, 0);
749 }
750
751 static guint
752 g_io_win32_sock_add_watch (GIOChannel    *channel,
753                            gint           priority,
754                            GIOCondition   condition,
755                            GIOFunc        func,
756                            gpointer       user_data,
757                            GDestroyNotify notify)
758 {
759   return g_io_win32_add_watch (channel, priority, condition,
760                                func, user_data, notify, sock_reader);
761 }
762
763 static GIOFuncs win32_channel_msg_funcs = {
764   g_io_win32_msg_read,
765   g_io_win32_msg_write,
766   g_io_win32_no_seek,
767   g_io_win32_msg_close,
768   g_io_win32_msg_add_watch,
769   g_io_win32_free
770 };
771
772 static GIOFuncs win32_channel_fd_funcs = {
773   g_io_win32_fd_read,
774   g_io_win32_fd_write,
775   g_io_win32_fd_seek,
776   g_io_win32_fd_close,
777   g_io_win32_fd_add_watch,
778   g_io_win32_free
779 };
780
781 static GIOFuncs win32_channel_sock_funcs = {
782   g_io_win32_sock_read,
783   g_io_win32_sock_write,
784   g_io_win32_no_seek,
785   g_io_win32_sock_close,
786   g_io_win32_sock_add_watch,
787   g_io_win32_free
788 };
789
790 GIOChannel *
791 g_io_channel_win32_new_messages (guint hwnd)
792 {
793   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
794   GIOChannel *channel = (GIOChannel *) win32_channel;
795
796   g_io_channel_init (channel);
797   g_io_channel_win32_init (win32_channel);
798   channel->funcs = &win32_channel_msg_funcs;
799   win32_channel->type = G_IO_WINDOWS_MESSAGES;
800   win32_channel->hwnd = (HWND) hwnd;
801
802   return channel;
803 }
804
805 GIOChannel *
806 g_io_channel_win32_new_fd (gint fd)
807 {
808   GIOWin32Channel *win32_channel;
809   GIOChannel *channel;
810   struct stat st;
811
812   if (fstat (fd, &st) == -1)
813     {
814       g_warning ("%d isn't a (emulated) file descriptor", fd);
815       return NULL;
816     }
817
818   win32_channel = g_new (GIOWin32Channel, 1);
819   channel = (GIOChannel *) win32_channel;
820
821   g_io_channel_init (channel);
822   g_io_channel_win32_init (win32_channel);
823   channel->funcs = &win32_channel_fd_funcs;
824   win32_channel->type = G_IO_FILE_DESC;
825   win32_channel->fd = fd;
826
827   return channel;
828 }
829
830 gint
831 g_io_channel_win32_get_fd (GIOChannel *channel)
832 {
833   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
834
835   return win32_channel->fd;
836 }
837
838 GIOChannel *
839 g_io_channel_win32_new_stream_socket (int socket)
840 {
841   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
842   GIOChannel *channel = (GIOChannel *) win32_channel;
843
844   g_io_channel_init (channel);
845   g_io_channel_win32_init (win32_channel);
846   channel->funcs = &win32_channel_sock_funcs;
847   win32_channel->type = G_IO_STREAM_SOCKET;
848   win32_channel->fd = socket;
849
850   return channel;
851 }
852
853 GIOChannel *
854 g_io_channel_unix_new (gint fd)
855 {
856   return g_io_channel_win32_new_fd (fd);
857 }
858
859 gint
860 g_io_channel_unix_get_fd (GIOChannel *channel)
861 {
862   return g_io_channel_win32_get_fd (channel);
863 }
864
865 void
866 g_io_channel_win32_set_debug (GIOChannel *channel,
867                               gboolean    flag)
868 {
869   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
870
871   win32_channel->debug = flag;
872 }
873
874 gint
875 g_io_channel_win32_poll (GPollFD     *fds,
876                          gint         n_fds,
877                          GIOCondition condition,
878                          gint         timeout)
879 {
880   int i;
881   int result;
882   gboolean debug = FALSE;
883
884   g_return_val_if_fail (n_fds >= 0, 0);
885
886   result = (*g_main_win32_get_poll_func ()) (fds, n_fds, timeout);
887
888   return result;
889 }
890
891 gint
892 g_io_channel_win32_wait_for_condition (GIOChannel  *channel,
893                                        GIOCondition condition,
894                                        gint         timeout)
895 {
896   GPollFD pollfd;
897   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
898
899   pollfd.fd = (gint) win32_channel->data_avail_event;
900   pollfd.events = condition;
901   
902   return g_io_channel_win32_poll (&pollfd, 1, condition, timeout);
903 }
904
905 /* This variable and the functions below are present just to be 
906  * binary compatible with old clients... But note that in GIMP, the
907  * libgimp/gimp.c:gimp_extension_process() function will have to be modified
908  * anyhow for this new approach.
909  *
910  * These will be removed after some weeks.
911  */
912 guint g_pipe_readable_msg = 0;
913
914 GIOChannel *
915 g_io_channel_win32_new_pipe (int fd)
916 {
917   return g_io_channel_win32_new_fd (fd);
918 }
919
920 GIOChannel *
921 g_io_channel_win32_new_pipe_with_wakeups (int   fd,
922                                           guint peer,
923                                           int   peer_fd)
924 {
925   return g_io_channel_win32_new_fd (fd);
926 }
927
928 void
929 g_io_channel_win32_pipe_request_wakeups (GIOChannel *channel,
930                                          guint       peer,
931                                          int         peer_fd)
932 {
933   /* Nothing needed now */
934 }
935
936 void
937 g_io_channel_win32_pipe_readable (gint  fd,
938                                   guint offset)
939 {
940   /* Nothing needed now */
941 }
942