Warn if no callback. Call callback correctly. (g_io_win32_create_watch):
[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   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   GIOFunc func = (GIOFunc)callback;
358   GIOWin32Watch *watch = (GIOWin32Watch *)source;
359   
360   if (!func)
361     {
362       g_warning ("GIOWin32Watch dispatched without callback\n"
363                  "You must call g_source_connect().");
364       return FALSE;
365     }
366   
367   return (*func) (watch->channel,
368                   watch->pollfd.revents & watch->condition,
369                   user_data);
370 }
371
372 static void
373 g_io_win32_destroy (GSource *source)
374 {
375   GIOWin32Watch *watch = (GIOWin32Watch *)source;
376   
377   g_io_channel_unref (watch->channel);
378 }
379
380 static GSourceFuncs win32_watch_funcs = {
381   g_io_win32_prepare,
382   g_io_win32_check,
383   g_io_win32_dispatch,
384   g_io_win32_destroy
385 };
386
387 static GSource *
388 g_io_win32_create_watch (GIOChannel    *channel,
389                          GIOCondition   condition,
390                          int (*reader) (int, guchar *, int))
391 {
392   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
393   GIOWin32Watch *watch;
394   GSource *source;
395
396   source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
397   watch = (GIOWin32Watch *)source;
398   
399   watch->channel = channel;
400   g_io_channel_ref (channel);
401   
402   watch->condition = condition;
403   
404   if (win32_channel->data_avail_event == NULL)
405     create_events (win32_channel);
406
407   watch->pollfd.fd = (gint) win32_channel->data_avail_event;
408   watch->pollfd.events = condition;
409   
410   if (win32_channel->debug)
411     g_print ("g_io_win32_create_watch: fd:%d handle:%#x\n",
412              win32_channel->fd, watch->pollfd.fd);
413   
414   if (win32_channel->thread_id == 0)
415     create_reader_thread (win32_channel, reader);
416
417   g_source_add_poll (source, &watch->pollfd);
418   
419   return source;
420 }
421
422 static GIOError
423 g_io_win32_msg_read (GIOChannel *channel,
424                      gchar      *buf,
425                      guint       count,
426                      guint      *bytes_read)
427 {
428   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
429   MSG msg;               /* In case of alignment problems */
430   
431   if (count < sizeof (MSG))
432     return G_IO_ERROR_INVAL;
433   
434   if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
435     return G_IO_ERROR_AGAIN;
436   
437   memmove (buf, &msg, sizeof (MSG));
438   *bytes_read = sizeof (MSG);
439   return G_IO_ERROR_NONE;
440 }
441
442 static GIOError
443 g_io_win32_msg_write (GIOChannel *channel,
444                       gchar      *buf,
445                       guint       count,
446                       guint      *bytes_written)
447 {
448   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
449   MSG msg;
450   
451   if (count != sizeof (MSG))
452     return G_IO_ERROR_INVAL;
453   
454   /* In case of alignment problems */
455   memmove (&msg, buf, sizeof (MSG));
456   if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
457     return G_IO_ERROR_UNKNOWN;
458   
459   *bytes_written = sizeof (MSG);
460   return G_IO_ERROR_NONE;
461 }
462
463 static GIOError
464 g_io_win32_no_seek (GIOChannel *channel,
465                     gint        offset,
466                     GSeekType   type)
467 {
468   return G_IO_ERROR_UNKNOWN;
469 }
470
471 static void
472 g_io_win32_msg_close (GIOChannel *channel)
473 {
474   /* Nothing to be done. Or should we set hwnd to some invalid value? */
475 }
476
477 static void
478 g_io_win32_free (GIOChannel *channel)
479 {
480   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
481   
482   if (win32_channel->buffer)
483     {
484       CloseHandle (win32_channel->data_avail_event);
485       CloseHandle (win32_channel->space_avail_event);
486       DeleteCriticalSection (&win32_channel->mutex);
487     }
488
489   g_free (win32_channel->buffer);
490   g_free (win32_channel);
491 }
492
493 static GSource *
494 g_io_win32_msg_create_watch (GIOChannel    *channel,
495                              GIOCondition   condition)
496 {
497   GIOWin32Watch *watch;
498   GSource *source;
499
500   source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
501   watch = (GIOWin32Watch *)source;
502   
503   watch->channel = channel;
504   g_io_channel_ref (channel);
505   
506   watch->condition = condition;
507   
508   watch->pollfd.fd = G_WIN32_MSG_HANDLE;
509   watch->pollfd.events = condition;
510   
511   g_source_add_poll (source, &watch->pollfd);
512   
513   return source;
514 }
515
516 static GIOError
517 g_io_win32_fd_read (GIOChannel *channel,
518                     gchar      *buf,
519                     guint       count,
520                     guint      *bytes_read)
521 {
522   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
523   gint result;
524   GIOError error;
525   
526   if (win32_channel->debug)
527     g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
528              win32_channel->fd, count);
529   
530   if (win32_channel->thread_id)
531     {
532       result = buffer_read (win32_channel, buf, count, &error);
533       if (result < 0)
534         {
535           *bytes_read = 0;
536           return error;
537         }
538       else
539         {
540           *bytes_read = result;
541           return G_IO_ERROR_NONE;
542         }
543     }
544
545   result = read (win32_channel->fd, buf, count);
546
547   if (result < 0)
548     {
549       *bytes_read = 0;
550       if (errno == EINVAL)
551         return G_IO_ERROR_INVAL;
552       else
553         return G_IO_ERROR_UNKNOWN;
554     }
555   else
556     {
557       *bytes_read = result;
558       return G_IO_ERROR_NONE;
559     }
560 }
561
562 static GIOError
563 g_io_win32_fd_write (GIOChannel *channel,
564                      gchar      *buf,
565                      guint       count,
566                      guint      *bytes_written)
567 {
568   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
569   gint result;
570   
571   result = write (win32_channel->fd, buf, count);
572   if (win32_channel->debug)
573     g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
574              win32_channel->fd, count, result);
575   
576   if (result < 0)
577     {
578       *bytes_written = 0;
579       switch (errno)
580         {
581         case EINVAL:
582           return G_IO_ERROR_INVAL;
583         case EAGAIN:
584           return G_IO_ERROR_AGAIN;
585         default:
586           return G_IO_ERROR_UNKNOWN;
587         }
588     }
589   else
590     {
591       *bytes_written = result;
592       return G_IO_ERROR_NONE;
593     }
594 }
595
596 static GIOError
597 g_io_win32_fd_seek (GIOChannel *channel,
598                     gint        offset,
599                     GSeekType   type)
600 {
601   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
602   int whence;
603   off_t result;
604   
605   switch (type)
606     {
607     case G_SEEK_SET:
608       whence = SEEK_SET;
609       break;
610     case G_SEEK_CUR:
611       whence = SEEK_CUR;
612       break;
613     case G_SEEK_END:
614       whence = SEEK_END;
615       break;
616     default:
617       g_warning ("g_io_win32_fd_seek: unknown seek type");
618       return G_IO_ERROR_UNKNOWN;
619     }
620   
621   result = lseek (win32_channel->fd, offset, whence);
622   
623   if (result < 0)
624     {
625       switch (errno)
626         {
627         case EINVAL:
628           return G_IO_ERROR_INVAL;
629         default:
630           return G_IO_ERROR_UNKNOWN;
631         }
632     }
633   else
634     return G_IO_ERROR_NONE;
635 }
636
637 static void
638 g_io_win32_fd_close (GIOChannel *channel)
639 {
640   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
641   
642   close (win32_channel->fd);
643   return;
644 }
645
646 static int
647 fd_reader (int     fd,
648            guchar *buf,
649            int     len)
650 {
651   return read (fd, buf, len);
652 }
653
654 static GSource *
655 g_io_win32_fd_create_watch (GIOChannel    *channel,
656                             GIOCondition   condition)
657 {
658   return g_io_win32_create_watch (channel, condition, fd_reader);
659 }
660
661 static GIOError
662 g_io_win32_sock_read (GIOChannel *channel,
663                       gchar      *buf,
664                       guint       count,
665                       guint      *bytes_read)
666 {
667   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
668   gint result;
669   GIOError error;
670   
671   if (win32_channel->thread_id)
672     {
673       result = buffer_read (win32_channel, buf, count, &error);
674       if (result < 0)
675         {
676           *bytes_read = 0;
677           return error;
678         }
679       else
680         {
681           *bytes_read = result;
682           return G_IO_ERROR_NONE;
683         }
684     }
685
686   result = recv (win32_channel->fd, buf, count, 0);
687
688   if (result < 0)
689     {
690       *bytes_read = 0;
691       return G_IO_ERROR_UNKNOWN;
692     }
693   else
694     {
695       *bytes_read = result;
696       return G_IO_ERROR_NONE;
697     }
698 }
699
700 static GIOError
701 g_io_win32_sock_write (GIOChannel *channel,
702                        gchar      *buf,
703                        guint       count,
704                        guint      *bytes_written)
705 {
706   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
707   gint result;
708   
709   result = send (win32_channel->fd, buf, count, 0);
710   
711   if (result == SOCKET_ERROR)
712     {
713       *bytes_written = 0;
714       switch (WSAGetLastError ())
715         {
716         case WSAEINVAL:
717           return G_IO_ERROR_INVAL;
718         case WSAEWOULDBLOCK:
719         case WSAEINTR:
720           return G_IO_ERROR_AGAIN;
721         default:
722           return G_IO_ERROR_UNKNOWN;
723         }
724     }
725   else
726     {
727       *bytes_written = result;
728       return G_IO_ERROR_NONE;
729     }
730 }
731
732 static void
733 g_io_win32_sock_close (GIOChannel *channel)
734 {
735   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
736
737   closesocket (win32_channel->fd);
738 }
739
740 static int
741 sock_reader (int     fd,
742              guchar *buf,
743              int     len)
744 {
745   return recv (fd, buf, len, 0);
746 }
747
748 static GSource *
749 g_io_win32_sock_create_watch (GIOChannel    *channel,
750                               GIOCondition   condition)
751 {
752   return g_io_win32_create_watch (channel, condition, sock_reader);
753 }
754
755 static GIOFuncs win32_channel_msg_funcs = {
756   g_io_win32_msg_read,
757   g_io_win32_msg_write,
758   g_io_win32_no_seek,
759   g_io_win32_msg_close,
760   g_io_win32_msg_create_watch,
761   g_io_win32_free
762 };
763
764 static GIOFuncs win32_channel_fd_funcs = {
765   g_io_win32_fd_read,
766   g_io_win32_fd_write,
767   g_io_win32_fd_seek,
768   g_io_win32_fd_close,
769   g_io_win32_fd_create_watch,
770   g_io_win32_free
771 };
772
773 static GIOFuncs win32_channel_sock_funcs = {
774   g_io_win32_sock_read,
775   g_io_win32_sock_write,
776   g_io_win32_no_seek,
777   g_io_win32_sock_close,
778   g_io_win32_sock_create_watch,
779   g_io_win32_free
780 };
781
782 GIOChannel *
783 g_io_channel_win32_new_messages (guint hwnd)
784 {
785   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
786   GIOChannel *channel = (GIOChannel *) win32_channel;
787
788   g_io_channel_init (channel);
789   g_io_channel_win32_init (win32_channel);
790   channel->funcs = &win32_channel_msg_funcs;
791   win32_channel->type = G_IO_WINDOWS_MESSAGES;
792   win32_channel->hwnd = (HWND) hwnd;
793
794   return channel;
795 }
796
797 GIOChannel *
798 g_io_channel_win32_new_fd (gint fd)
799 {
800   GIOWin32Channel *win32_channel;
801   GIOChannel *channel;
802   struct stat st;
803
804   if (fstat (fd, &st) == -1)
805     {
806       g_warning ("%d isn't a (emulated) file descriptor", fd);
807       return NULL;
808     }
809
810   win32_channel = g_new (GIOWin32Channel, 1);
811   channel = (GIOChannel *) win32_channel;
812
813   g_io_channel_init (channel);
814   g_io_channel_win32_init (win32_channel);
815   channel->funcs = &win32_channel_fd_funcs;
816   win32_channel->type = G_IO_FILE_DESC;
817   win32_channel->fd = fd;
818
819   return channel;
820 }
821
822 gint
823 g_io_channel_win32_get_fd (GIOChannel *channel)
824 {
825   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
826
827   return win32_channel->fd;
828 }
829
830 GIOChannel *
831 g_io_channel_win32_new_stream_socket (int socket)
832 {
833   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
834   GIOChannel *channel = (GIOChannel *) win32_channel;
835
836   g_io_channel_init (channel);
837   g_io_channel_win32_init (win32_channel);
838   channel->funcs = &win32_channel_sock_funcs;
839   win32_channel->type = G_IO_STREAM_SOCKET;
840   win32_channel->fd = socket;
841
842   return channel;
843 }
844
845 GIOChannel *
846 g_io_channel_unix_new (gint fd)
847 {
848   struct stat st;
849
850   if (fstat (fd, &st) == 0)
851     return g_io_channel_win32_new_fd (fd);
852   
853   if (getsockopt (fd, SOL_SOCKET, SO_TYPE, NULL, NULL) != SO_ERROR)
854     return g_io_channel_win32_new_stream_socket(fd);
855
856   g_warning ("%d isn't a file descriptor or a socket", fd);
857   return NULL;
858 }
859
860 gint
861 g_io_channel_unix_get_fd (GIOChannel *channel)
862 {
863   return g_io_channel_win32_get_fd (channel);
864 }
865
866 void
867 g_io_channel_win32_set_debug (GIOChannel *channel,
868                               gboolean    flag)
869 {
870   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
871
872   win32_channel->debug = flag;
873 }
874
875 gint
876 g_io_channel_win32_poll (GPollFD *fds,
877                          gint     n_fds,
878                          gint     timeout)
879 {
880   int result;
881
882   g_return_val_if_fail (n_fds >= 0, 0);
883
884   result = (*g_main_context_get_poll_func (NULL)) (fds, n_fds, timeout);
885
886   return result;
887 }
888
889 void
890 g_io_channel_win32_make_pollfd (GIOChannel   *channel,
891                                 GIOCondition  condition,
892                                 GPollFD      *fd)
893 {
894   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
895
896   if (win32_channel->data_avail_event == NULL)
897     create_events (win32_channel);
898   
899   fd->fd = (gint) win32_channel->data_avail_event;
900   fd->events = condition;
901
902   if (win32_channel->thread_id == 0)
903     if (win32_channel->type == G_IO_FILE_DESC)
904       create_reader_thread (win32_channel, fd_reader);
905     else if (win32_channel->type == G_IO_STREAM_SOCKET)
906       create_reader_thread (win32_channel, sock_reader);
907 }
908
909 /* This variable and the functions below are present just to be 
910  * binary compatible with old clients... But note that in GIMP, the
911  * libgimp/gimp.c:gimp_extension_process() function will have to be modified
912  * anyhow for this new approach.
913  *
914  * These will be removed after some weeks.
915  */
916 guint g_pipe_readable_msg = 0;
917
918 GIOChannel *
919 g_io_channel_win32_new_pipe (int fd)
920 {
921   return g_io_channel_win32_new_fd (fd);
922 }
923
924 GIOChannel *
925 g_io_channel_win32_new_pipe_with_wakeups (int   fd,
926                                           guint peer,
927                                           int   peer_fd)
928 {
929   return g_io_channel_win32_new_fd (fd);
930 }
931
932 void
933 g_io_channel_win32_pipe_request_wakeups (GIOChannel *channel,
934                                          guint       peer,
935                                          int         peer_fd)
936 {
937   /* Nothing needed now */
938 }
939
940 void
941 g_io_channel_win32_pipe_readable (gint  fd,
942                                   guint offset)
943 {
944   /* Nothing needed now */
945 }
946