Major change in API for creating sources to handle multiple main loops
[platform/upstream/glib.git] / 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   GSource       source;
106   GPollFD       pollfd;
107   GIOChannel   *channel;
108   GIOCondition  condition;
109   GIOFunc       callback;
110 };
111
112 static void
113 g_io_channel_win32_init (GIOWin32Channel *channel)
114 {
115 #ifdef G_IO_WIN32_DEBUG
116   channel->debug = TRUE;
117 #else
118   if (getenv ("G_IO_WIN32_DEBUG") != NULL)
119     channel->debug = TRUE;
120   else
121     channel->debug = FALSE;
122 #endif
123   channel->buffer = NULL;
124   channel->running = FALSE;
125   channel->thread_id = 0;
126   channel->data_avail_event = NULL;
127   channel->space_avail_event = NULL;
128 }
129
130 static void
131 create_events (GIOWin32Channel *channel)
132 {
133   SECURITY_ATTRIBUTES sec_attrs;
134   
135   sec_attrs.nLength = sizeof(SECURITY_ATTRIBUTES);
136   sec_attrs.lpSecurityDescriptor = NULL;
137   sec_attrs.bInheritHandle = FALSE;
138
139   /* The data available event is manual reset, the space available event
140    * is automatic reset.
141    */
142   if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
143       || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
144     {
145       gchar *msg = g_win32_error_message (GetLastError ());
146       g_error ("Error creating event: %s", msg);
147     }
148   InitializeCriticalSection (&channel->mutex);
149 }
150
151 static unsigned __stdcall
152 reader_thread (void *parameter)
153 {
154   GIOWin32Channel *channel = parameter;
155   guchar *buffer;
156   guint nbytes;
157
158   g_io_channel_ref ((GIOChannel *) channel);
159
160   if (channel->debug)
161     g_print ("thread %#x: starting. pid:%#x, fd:%d, data_avail:%#x, space_avail:%#x\n",
162              channel->thread_id,
163              (guint) GetCurrentProcessId (),
164              channel->fd,
165              (guint) channel->data_avail_event,
166              (guint) channel->space_avail_event);
167   
168   channel->buffer = g_malloc (BUFFER_SIZE);
169   channel->rdp = channel->wrp = 0;
170   channel->running = TRUE;
171
172   SetEvent (channel->space_avail_event);
173   
174   while (channel->running)
175     {
176       LOCK (channel->mutex);
177       if (channel->debug)
178         g_print ("thread %#x: rdp=%d, wrp=%d\n",
179                  channel->thread_id, channel->rdp, channel->wrp);
180       if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
181         {
182           /* Buffer is full */
183           if (channel->debug)
184             g_print ("thread %#x: resetting space_available\n",
185                      channel->thread_id);
186           ResetEvent (channel->space_avail_event);
187           if (channel->debug)
188             g_print ("thread %#x: waiting for space\n", channel->thread_id);
189           UNLOCK (channel->mutex);
190           WaitForSingleObject (channel->space_avail_event, INFINITE);
191           LOCK (channel->mutex);
192           if (channel->debug)
193             g_print ("thread %#x: rdp=%d, wrp=%d\n",
194                      channel->thread_id, channel->rdp, channel->wrp);
195         }
196       
197       buffer = channel->buffer + channel->wrp;
198       
199       /* Always leave at least one byte unused gap to be able to
200        * distinguish between the full and empty condition...
201        */
202       nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
203                     BUFFER_SIZE - channel->wrp);
204
205       if (channel->debug)
206         g_print ("thread %#x: calling reader for %d bytes\n",
207                  channel->thread_id, nbytes);
208
209       UNLOCK (channel->mutex);
210
211       nbytes = (*channel->reader) (channel->fd, buffer, nbytes);
212       
213       if (nbytes <= 0)
214         break;
215
216       LOCK (channel->mutex);
217       if (channel->debug)
218         g_print ("thread %#x: got %d bytes, rdp=%d, wrp=%d\n",
219                  channel->thread_id, nbytes, channel->rdp, channel->wrp);
220       channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
221       if (channel->debug)
222         g_print ("thread %#x: rdp=%d, wrp=%d, setting data available\n",
223                  channel->thread_id, channel->rdp, channel->wrp);
224       SetEvent (channel->data_avail_event);
225       UNLOCK (channel->mutex);
226     }
227   
228   LOCK (channel->mutex);
229   channel->running = FALSE;
230   if (channel->debug)
231     g_print ("thread %#x: got EOF, rdp=%d, wrp=%d, setting data available\n",
232              channel->thread_id, channel->rdp, channel->wrp);
233   SetEvent (channel->data_avail_event);
234   UNLOCK (channel->mutex);
235   
236   g_io_channel_unref((GIOChannel *) channel);
237   
238   /* All of the Microsoft docs say we should explicitly
239    * end the thread...
240    */
241   _endthreadex(1);
242   
243   return 0;
244 }
245
246 static void
247 create_reader_thread (GIOWin32Channel *channel,
248                       gpointer         reader)
249 {
250   channel->reader = reader;
251
252   if (_beginthreadex (NULL, 0, reader_thread, channel, 0,
253                       &channel->thread_id) == 0)
254     g_warning ("Error creating reader thread: %s", strerror (errno));
255   WaitForSingleObject (channel->space_avail_event, INFINITE);
256 }
257
258 static int
259 buffer_read (GIOWin32Channel *channel,
260              guchar          *dest,
261              guint            count,
262              GIOError        *error)
263 {
264   guint nbytes;
265   guint left = count;
266   
267   LOCK (channel->mutex);
268   if (channel->debug)
269     g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
270              channel->thread_id, count, channel->rdp, channel->wrp);
271   
272   if (channel->rdp == channel->wrp)
273     {
274       UNLOCK (channel->mutex);
275       if (channel->debug)
276         g_print ("waiting for data from thread %#x\n", channel->thread_id);
277       WaitForSingleObject (channel->data_avail_event, INFINITE);
278       LOCK (channel->mutex);
279       if (channel->rdp == channel->wrp && !channel->running)
280         {
281           UNLOCK (channel->mutex);
282           return 0;
283         }
284     }
285   
286   if (channel->rdp < channel->wrp)
287     nbytes = channel->wrp - channel->rdp;
288   else
289     nbytes = BUFFER_SIZE - channel->rdp;
290   UNLOCK (channel->mutex);
291   nbytes = MIN (left, nbytes);
292   if (channel->debug)
293     g_print ("moving %d bytes from thread %#x\n",
294              nbytes, channel->thread_id);
295   memcpy (dest, channel->buffer + channel->rdp, nbytes);
296   dest += nbytes;
297   left -= nbytes;
298   LOCK (channel->mutex);
299   channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
300   if (channel->debug)
301     g_print ("setting space available for thread %#x\n", channel->thread_id);
302   SetEvent (channel->space_avail_event);
303   if (channel->debug)
304     g_print ("for thread %#x: rdp=%d, wrp=%d\n",
305              channel->thread_id, channel->rdp, channel->wrp);
306   if (channel->running && channel->rdp == channel->wrp)
307     {
308       if (channel->debug)
309         g_print ("resetting data_available of thread %#x\n",
310                  channel->thread_id);
311       ResetEvent (channel->data_avail_event);
312     };
313   UNLOCK (channel->mutex);
314   
315   /* We have no way to indicate any errors form the actual
316    * read() or recv() call in the reader thread. Should we have?
317    */
318   *error = G_IO_ERROR_NONE;
319   return count - left;
320 }
321
322 static gboolean
323 g_io_win32_prepare (GSource *source,
324                     gint    *timeout)
325 {
326   *timeout = -1;
327   
328   return FALSE;
329 }
330
331 static gboolean
332 g_io_win32_check (GSource *source)
333 {
334   GIOWin32Watch *watch = (GIOWin32Watch *)source;
335   GIOWin32Channel *channel = (GIOWin32Channel *) watch->channel;
336   
337   /* If the thread has died, we have encountered EOF. If the buffer
338    * also is emtpty set the HUP bit.
339    */
340   if (!channel->running && channel->rdp == channel->wrp)
341     {
342       if (channel->debug)
343         g_print ("g_io_win32_check: setting G_IO_HUP thread %#x rdp=%d wrp=%d\n",
344                  channel->thread_id, channel->rdp, channel->wrp);
345       watch->pollfd.revents |= G_IO_HUP;
346       return TRUE;
347     }
348   
349   return (watch->pollfd.revents & watch->condition);
350 }
351
352 static gboolean
353 g_io_win32_dispatch (GSource     *source,
354                      GSourceFunc  callback,
355                      gpointer     user_data)
356 {
357   GIOWin32Watch *watch = (GIOWin32Watch *)source;
358   
359   return (*callback) (watch->channel,
360                       watch->pollfd.revents & watch->condition,
361                       user_data);
362 }
363
364 static void
365 g_io_win32_destroy (GSource *source)
366 {
367   GIOWin32Watch *watch = (GIOWin32Watch *)source;
368   
369   g_io_channel_unref (watch->channel);
370 }
371
372 static GSourceFuncs win32_watch_funcs = {
373   g_io_win32_prepare,
374   g_io_win32_check,
375   g_io_win32_dispatch,
376   g_io_win32_destroy
377 };
378
379 static GSource *
380 g_io_win32_create_watch (GIOChannel    *channel,
381                          GIOCondition   condition,
382                          int (*reader) (int, guchar *, int)))
383 {
384   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
385   GIOWin32Watch *watch;
386   GSource *source;
387
388   source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
389   watch = (GIOWin32Watch *)source;
390   
391   watch->channel = channel;
392   g_io_channel_ref (channel);
393   
394   watch->condition = condition;
395   
396   if (win32_channel->data_avail_event == NULL)
397     create_events (win32_channel);
398
399   watch->pollfd.fd = (gint) win32_channel->data_avail_event;
400   watch->pollfd.events = condition;
401   
402   if (win32_channel->debug)
403     g_print ("g_io_win32_create_watch: fd:%d handle:%#x\n",
404              win32_channel->fd, watch->pollfd.fd);
405   
406   if (win32_channel->thread_id == 0)
407     create_reader_thread (win32_channel, reader);
408
409   g_source_add_poll (source, &watch->pollfd);
410   
411   return source;
412 }
413
414 static GIOError
415 g_io_win32_msg_read (GIOChannel *channel,
416                      gchar      *buf,
417                      guint       count,
418                      guint      *bytes_read)
419 {
420   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
421   MSG msg;               /* In case of alignment problems */
422   
423   if (count < sizeof (MSG))
424     return G_IO_ERROR_INVAL;
425   
426   if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
427     return G_IO_ERROR_AGAIN;
428   
429   memmove (buf, &msg, sizeof (MSG));
430   *bytes_read = sizeof (MSG);
431   return G_IO_ERROR_NONE;
432 }
433
434 static GIOError
435 g_io_win32_msg_write (GIOChannel *channel,
436                       gchar      *buf,
437                       guint       count,
438                       guint      *bytes_written)
439 {
440   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
441   MSG msg;
442   
443   if (count != sizeof (MSG))
444     return G_IO_ERROR_INVAL;
445   
446   /* In case of alignment problems */
447   memmove (&msg, buf, sizeof (MSG));
448   if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
449     return G_IO_ERROR_UNKNOWN;
450   
451   *bytes_written = sizeof (MSG);
452   return G_IO_ERROR_NONE;
453 }
454
455 static GIOError
456 g_io_win32_no_seek (GIOChannel *channel,
457                     gint        offset,
458                     GSeekType   type)
459 {
460   return G_IO_ERROR_UNKNOWN;
461 }
462
463 static void
464 g_io_win32_msg_close (GIOChannel *channel)
465 {
466   /* Nothing to be done. Or should we set hwnd to some invalid value? */
467 }
468
469 static void
470 g_io_win32_free (GIOChannel *channel)
471 {
472   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
473   
474   if (win32_channel->buffer)
475     {
476       CloseHandle (win32_channel->data_avail_event);
477       CloseHandle (win32_channel->space_avail_event);
478       DeleteCriticalSection (&win32_channel->mutex);
479     }
480
481   g_free (win32_channel->buffer);
482   g_free (win32_channel);
483 }
484
485 static GSource *
486 g_io_win32_msg_create_watch (GIOChannel    *channel,
487                              GIOCondition   condition)
488 {
489   GIOWin32Watch *watch;
490   GSource *source;
491
492   source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
493   watch = (GIOWin32Watch *)source;
494   
495   watch->channel = channel;
496   g_io_channel_ref (channel);
497   
498   watch->condition = condition;
499   
500   watch->pollfd.fd = G_WIN32_MSG_HANDLE;
501   watch->pollfd.events = condition;
502   
503   g_source_add_poll (source, &watch->pollfd);
504   
505   return source;
506 }
507
508 static GIOError
509 g_io_win32_fd_read (GIOChannel *channel,
510                     gchar      *buf,
511                     guint       count,
512                     guint      *bytes_read)
513 {
514   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
515   gint result;
516   GIOError error;
517   
518   if (win32_channel->debug)
519     g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
520              win32_channel->fd, count);
521   
522   if (win32_channel->thread_id)
523     {
524       result = buffer_read (win32_channel, buf, count, &error);
525       if (result < 0)
526         {
527           *bytes_read = 0;
528           return error;
529         }
530       else
531         {
532           *bytes_read = result;
533           return G_IO_ERROR_NONE;
534         }
535     }
536
537   result = read (win32_channel->fd, buf, count);
538
539   if (result < 0)
540     {
541       *bytes_read = 0;
542       if (errno == EINVAL)
543         return G_IO_ERROR_INVAL;
544       else
545         return G_IO_ERROR_UNKNOWN;
546     }
547   else
548     {
549       *bytes_read = result;
550       return G_IO_ERROR_NONE;
551     }
552 }
553
554 static GIOError
555 g_io_win32_fd_write (GIOChannel *channel,
556                      gchar      *buf,
557                      guint       count,
558                      guint      *bytes_written)
559 {
560   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
561   gint result;
562   
563   result = write (win32_channel->fd, buf, count);
564   if (win32_channel->debug)
565     g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
566              win32_channel->fd, count, result);
567   
568   if (result < 0)
569     {
570       *bytes_written = 0;
571       switch (errno)
572         {
573         case EINVAL:
574           return G_IO_ERROR_INVAL;
575         case EAGAIN:
576           return G_IO_ERROR_AGAIN;
577         default:
578           return G_IO_ERROR_UNKNOWN;
579         }
580     }
581   else
582     {
583       *bytes_written = result;
584       return G_IO_ERROR_NONE;
585     }
586 }
587
588 static GIOError
589 g_io_win32_fd_seek (GIOChannel *channel,
590                     gint        offset,
591                     GSeekType   type)
592 {
593   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
594   int whence;
595   off_t result;
596   
597   switch (type)
598     {
599     case G_SEEK_SET:
600       whence = SEEK_SET;
601       break;
602     case G_SEEK_CUR:
603       whence = SEEK_CUR;
604       break;
605     case G_SEEK_END:
606       whence = SEEK_END;
607       break;
608     default:
609       g_warning ("g_io_win32_fd_seek: unknown seek type");
610       return G_IO_ERROR_UNKNOWN;
611     }
612   
613   result = lseek (win32_channel->fd, offset, whence);
614   
615   if (result < 0)
616     {
617       switch (errno)
618         {
619         case EINVAL:
620           return G_IO_ERROR_INVAL;
621         default:
622           return G_IO_ERROR_UNKNOWN;
623         }
624     }
625   else
626     return G_IO_ERROR_NONE;
627 }
628
629 static void
630 g_io_win32_fd_close (GIOChannel *channel)
631 {
632   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
633   
634   close (win32_channel->fd);
635   return;
636 }
637
638 static int
639 fd_reader (int     fd,
640            guchar *buf,
641            int     len)
642 {
643   return read (fd, buf, len);
644 }
645
646 static GSource *
647 g_io_win32_fd_create_watch (GIOChannel    *channel,
648                             GIOCondition   condition)
649 {
650   return g_io_win32_create_watch (channel, condition, fd_reader);
651 }
652
653 static GIOError
654 g_io_win32_sock_read (GIOChannel *channel,
655                       gchar      *buf,
656                       guint       count,
657                       guint      *bytes_read)
658 {
659   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
660   gint result;
661   GIOError error;
662   
663   if (win32_channel->thread_id)
664     {
665       result = buffer_read (win32_channel, buf, count, &error);
666       if (result < 0)
667         {
668           *bytes_read = 0;
669           return error;
670         }
671       else
672         {
673           *bytes_read = result;
674           return G_IO_ERROR_NONE;
675         }
676     }
677
678   result = recv (win32_channel->fd, buf, count, 0);
679
680   if (result < 0)
681     {
682       *bytes_read = 0;
683       return G_IO_ERROR_UNKNOWN;
684     }
685   else
686     {
687       *bytes_read = result;
688       return G_IO_ERROR_NONE;
689     }
690 }
691
692 static GIOError
693 g_io_win32_sock_write (GIOChannel *channel,
694                        gchar      *buf,
695                        guint       count,
696                        guint      *bytes_written)
697 {
698   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
699   gint result;
700   
701   result = send (win32_channel->fd, buf, count, 0);
702   
703   if (result == SOCKET_ERROR)
704     {
705       *bytes_written = 0;
706       switch (WSAGetLastError ())
707         {
708         case WSAEINVAL:
709           return G_IO_ERROR_INVAL;
710         case WSAEWOULDBLOCK:
711         case WSAEINTR:
712           return G_IO_ERROR_AGAIN;
713         default:
714           return G_IO_ERROR_UNKNOWN;
715         }
716     }
717   else
718     {
719       *bytes_written = result;
720       return G_IO_ERROR_NONE;
721     }
722 }
723
724 static void
725 g_io_win32_sock_close (GIOChannel *channel)
726 {
727   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
728
729   closesocket (win32_channel->fd);
730 }
731
732 static int
733 sock_reader (int     fd,
734              guchar *buf,
735              int     len)
736 {
737   return recv (fd, buf, len, 0);
738 }
739
740 static GSource *
741 g_io_win32_sock_create_watch (GIOChannel    *channel,
742                               GIOCondition   condition)
743 {
744   return g_io_win32_add_watch (channel, condition, sock_reader);
745 }
746
747 static GIOFuncs win32_channel_msg_funcs = {
748   g_io_win32_msg_read,
749   g_io_win32_msg_write,
750   g_io_win32_no_seek,
751   g_io_win32_msg_close,
752   g_io_win32_msg_create_watch,
753   g_io_win32_free
754 };
755
756 static GIOFuncs win32_channel_fd_funcs = {
757   g_io_win32_fd_read,
758   g_io_win32_fd_write,
759   g_io_win32_fd_seek,
760   g_io_win32_fd_close,
761   g_io_win32_fd_create_watch,
762   g_io_win32_free
763 };
764
765 static GIOFuncs win32_channel_sock_funcs = {
766   g_io_win32_sock_read,
767   g_io_win32_sock_write,
768   g_io_win32_no_seek,
769   g_io_win32_sock_close,
770   g_io_win32_sock_create_watch,
771   g_io_win32_free
772 };
773
774 GIOChannel *
775 g_io_channel_win32_new_messages (guint hwnd)
776 {
777   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
778   GIOChannel *channel = (GIOChannel *) win32_channel;
779
780   g_io_channel_init (channel);
781   g_io_channel_win32_init (win32_channel);
782   channel->funcs = &win32_channel_msg_funcs;
783   win32_channel->type = G_IO_WINDOWS_MESSAGES;
784   win32_channel->hwnd = (HWND) hwnd;
785
786   return channel;
787 }
788
789 GIOChannel *
790 g_io_channel_win32_new_fd (gint fd)
791 {
792   GIOWin32Channel *win32_channel;
793   GIOChannel *channel;
794   struct stat st;
795
796   if (fstat (fd, &st) == -1)
797     {
798       g_warning ("%d isn't a (emulated) file descriptor", fd);
799       return NULL;
800     }
801
802   win32_channel = g_new (GIOWin32Channel, 1);
803   channel = (GIOChannel *) win32_channel;
804
805   g_io_channel_init (channel);
806   g_io_channel_win32_init (win32_channel);
807   channel->funcs = &win32_channel_fd_funcs;
808   win32_channel->type = G_IO_FILE_DESC;
809   win32_channel->fd = fd;
810
811   return channel;
812 }
813
814 gint
815 g_io_channel_win32_get_fd (GIOChannel *channel)
816 {
817   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
818
819   return win32_channel->fd;
820 }
821
822 GIOChannel *
823 g_io_channel_win32_new_stream_socket (int socket)
824 {
825   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
826   GIOChannel *channel = (GIOChannel *) win32_channel;
827
828   g_io_channel_init (channel);
829   g_io_channel_win32_init (win32_channel);
830   channel->funcs = &win32_channel_sock_funcs;
831   win32_channel->type = G_IO_STREAM_SOCKET;
832   win32_channel->fd = socket;
833
834   return channel;
835 }
836
837 GIOChannel *
838 g_io_channel_unix_new (gint fd)
839 {
840   return g_io_channel_win32_new_fd (fd);
841 }
842
843 gint
844 g_io_channel_unix_get_fd (GIOChannel *channel)
845 {
846   return g_io_channel_win32_get_fd (channel);
847 }
848
849 void
850 g_io_channel_win32_set_debug (GIOChannel *channel,
851                               gboolean    flag)
852 {
853   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
854
855   win32_channel->debug = flag;
856 }
857
858 gint
859 g_io_channel_win32_poll (GPollFD *fds,
860                          gint     n_fds,
861                          gint     timeout)
862 {
863   int result;
864
865   g_return_val_if_fail (n_fds >= 0, 0);
866
867   result = (*g_main_win32_get_poll_func ()) (fds, n_fds, timeout);
868
869   return result;
870 }
871
872 void
873 g_io_channel_win32_make_pollfd (GIOChannel   *channel,
874                                 GIOCondition  condition,
875                                 GPollFD      *fd)
876 {
877   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
878
879   if (win32_channel->data_avail_event == NULL)
880     create_events (win32_channel);
881   
882   fd->fd = (gint) win32_channel->data_avail_event;
883   fd->events = condition;
884
885   if (win32_channel->thread_id == 0)
886     if (win32_channel->type == G_IO_FILE_DESC)
887       create_reader_thread (win32_channel, fd_reader);
888     else if (win32_channel->type == G_IO_STREAM_SOCKET)
889       create_reader_thread (win32_channel, sock_reader);
890 }
891
892 /* This variable and the functions below are present just to be 
893  * binary compatible with old clients... But note that in GIMP, the
894  * libgimp/gimp.c:gimp_extension_process() function will have to be modified
895  * anyhow for this new approach.
896  *
897  * These will be removed after some weeks.
898  */
899 guint g_pipe_readable_msg = 0;
900
901 GIOChannel *
902 g_io_channel_win32_new_pipe (int fd)
903 {
904   return g_io_channel_win32_new_fd (fd);
905 }
906
907 GIOChannel *
908 g_io_channel_win32_new_pipe_with_wakeups (int   fd,
909                                           guint peer,
910                                           int   peer_fd)
911 {
912   return g_io_channel_win32_new_fd (fd);
913 }
914
915 void
916 g_io_channel_win32_pipe_request_wakeups (GIOChannel *channel,
917                                          guint       peer,
918                                          int         peer_fd)
919 {
920   /* Nothing needed now */
921 }
922
923 void
924 g_io_channel_win32_pipe_readable (gint  fd,
925                                   guint offset)
926 {
927   /* Nothing needed now */
928 }
929