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