Drop a few unused variables.
[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 }
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   
624   watch->channel = channel;
625   g_io_channel_ref (channel);
626   
627   watch->callback = func;
628   watch->condition = condition;
629   
630   create_events (win32_channel);
631
632   watch->pollfd.fd = (gint) win32_channel->data_avail_event;
633   watch->pollfd.events = condition;
634   
635   if (win32_channel->debug)
636     g_print ("g_io_win32_fd_add_watch: fd:%d handle:%#x\n",
637              win32_channel->fd, watch->pollfd.fd);
638   
639   create_reader_thread (win32_channel, fd_reader);
640
641   g_main_add_poll (&watch->pollfd, priority);
642   
643   return g_source_add (priority, TRUE, &win32_watch_funcs,
644                        watch, user_data, notify);
645 }
646
647 static GIOError
648 g_io_win32_sock_read (GIOChannel *channel,
649                       gchar      *buf,
650                       guint       count,
651                       guint      *bytes_read)
652 {
653   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
654   gint result;
655   GIOError error;
656   
657   if (win32_channel->thread_id)
658     {
659       result = buffer_read (win32_channel, buf, count, &error);
660       if (result < 0)
661         {
662           *bytes_read = 0;
663           return error;
664         }
665       else
666         {
667           *bytes_read = result;
668           return G_IO_ERROR_NONE;
669         }
670     }
671
672   result = recv (win32_channel->fd, buf, count, 0);
673
674   if (result < 0)
675     {
676       *bytes_read = 0;
677       return G_IO_ERROR_UNKNOWN;
678     }
679   else
680     {
681       *bytes_read = result;
682       return G_IO_ERROR_NONE;
683     }
684 }
685
686 static GIOError
687 g_io_win32_sock_write(GIOChannel *channel,
688                       gchar      *buf,
689                       guint       count,
690                       guint      *bytes_written)
691 {
692   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
693   gint result;
694   
695   result = send (win32_channel->fd, buf, count, 0);
696   
697   if (result == SOCKET_ERROR)
698     {
699       *bytes_written = 0;
700       switch (WSAGetLastError ())
701         {
702         case WSAEINVAL:
703           return G_IO_ERROR_INVAL;
704         case WSAEWOULDBLOCK:
705         case WSAEINTR:
706           return G_IO_ERROR_AGAIN;
707         default:
708           return G_IO_ERROR_UNKNOWN;
709         }
710     }
711   else
712     {
713       *bytes_written = result;
714       return G_IO_ERROR_NONE;
715     }
716 }
717
718 static void
719 g_io_win32_sock_close (GIOChannel *channel)
720 {
721   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
722
723   closesocket (win32_channel->fd);
724 }
725
726 static int
727 sock_reader (int     fd,
728              guchar *buf,
729              int     len)
730 {
731   return recv (fd, buf, len, 0);
732 }
733
734 static guint
735 g_io_win32_sock_add_watch (GIOChannel    *channel,
736                            gint           priority,
737                            GIOCondition   condition,
738                            GIOFunc        func,
739                            gpointer       user_data,
740                            GDestroyNotify notify)
741 {
742   GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
743   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
744
745   watch->channel = channel;
746   g_io_channel_ref (channel);
747
748   watch->callback = func;
749   watch->condition = condition;
750
751   create_events (win32_channel);
752
753   watch->pollfd.fd = (gint) win32_channel->data_avail_event;
754   watch->pollfd.events = condition;
755
756   /* Sockets are always readable, aren't they? */
757   create_reader_thread (win32_channel, sock_reader);
758
759   g_main_add_poll (&watch->pollfd, priority);
760
761   return g_source_add (priority, TRUE, &win32_watch_funcs, watch,
762                        user_data, notify);
763 }
764
765 static GIOFuncs win32_channel_msg_funcs = {
766   g_io_win32_msg_read,
767   g_io_win32_msg_write,
768   g_io_win32_no_seek,
769   g_io_win32_msg_close,
770   g_io_win32_msg_add_watch,
771   g_io_win32_free
772 };
773
774 static GIOFuncs win32_channel_fd_funcs = {
775   g_io_win32_fd_read,
776   g_io_win32_fd_write,
777   g_io_win32_fd_seek,
778   g_io_win32_fd_close,
779   g_io_win32_fd_add_watch,
780   g_io_win32_free
781 };
782
783 static GIOFuncs win32_channel_sock_funcs = {
784   g_io_win32_sock_read,
785   g_io_win32_sock_write,
786   g_io_win32_no_seek,
787   g_io_win32_sock_close,
788   g_io_win32_sock_add_watch,
789   g_io_win32_free
790 };
791
792 GIOChannel *
793 g_io_channel_win32_new_messages (guint hwnd)
794 {
795   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
796   GIOChannel *channel = (GIOChannel *) win32_channel;
797
798   g_io_channel_init (channel);
799   g_io_channel_win32_init (win32_channel);
800   channel->funcs = &win32_channel_msg_funcs;
801   win32_channel->type = G_IO_WINDOWS_MESSAGES;
802   win32_channel->hwnd = (HWND) hwnd;
803
804   return channel;
805 }
806
807 GIOChannel *
808 g_io_channel_win32_new_fd (gint fd)
809 {
810   GIOWin32Channel *win32_channel;
811   GIOChannel *channel;
812   struct stat st;
813
814   if (fstat (fd, &st) == -1)
815     {
816       g_warning ("%d isn't a (emulated) file descriptor", fd);
817       return NULL;
818     }
819
820   win32_channel = g_new (GIOWin32Channel, 1);
821   channel = (GIOChannel *) win32_channel;
822
823   g_io_channel_init (channel);
824   g_io_channel_win32_init (win32_channel);
825   channel->funcs = &win32_channel_fd_funcs;
826   win32_channel->type = G_IO_FILE_DESC;
827   win32_channel->fd = fd;
828
829   return channel;
830 }
831
832 gint
833 g_io_channel_win32_get_fd (GIOChannel *channel)
834 {
835   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
836
837   return win32_channel->fd;
838 }
839
840 GIOChannel *
841 g_io_channel_win32_new_stream_socket (int socket)
842 {
843   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
844   GIOChannel *channel = (GIOChannel *) win32_channel;
845
846   g_io_channel_init (channel);
847   g_io_channel_win32_init (win32_channel);
848   channel->funcs = &win32_channel_sock_funcs;
849   win32_channel->type = G_IO_STREAM_SOCKET;
850   win32_channel->fd = socket;
851
852   return channel;
853 }
854
855 GIOChannel *
856 g_io_channel_unix_new (gint fd)
857 {
858   return g_io_channel_win32_new_fd (fd);
859 }
860
861 gint
862 g_io_channel_unix_get_fd (GIOChannel *channel)
863 {
864   return g_io_channel_win32_get_fd (channel);
865 }
866
867 void
868 g_io_channel_win32_set_debug (GIOChannel *channel,
869                               gboolean    flag)
870 {
871   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
872
873   win32_channel->debug = flag;
874 }
875
876 gint
877 g_io_channel_win32_wait_for_condition (GIOChannel  *channel,
878                                        GIOCondition condition,
879                                        gint         timeout)
880 {
881   GPollFD pollfd;
882   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
883   int result;
884
885   pollfd.fd = (gint) win32_channel->data_avail_event;
886   pollfd.events = condition;
887
888   if (win32_channel->debug)
889     g_print ("g_io_channel_win32_wait_for_condition: fd:%d event:%#x timeout:%d\n",
890              win32_channel->fd, pollfd.fd, timeout);
891
892   result = (*g_main_win32_get_poll_func ()) (&pollfd, 1, timeout);
893
894   if (win32_channel->debug)
895     g_print ("g_io_channel_win32_wait_for_condition: done:%d\n", result);
896
897   return result;
898 }
899
900
901 /* This variable and the functions below are present just to be 
902  * binary compatible with old clients... But note that in GIMP, the
903  * libgimp/gimp.c:gimp_extension_process() function will have to be modified
904  * anyhow for this new approach.
905  *
906  * These will be removed after some weeks.
907  */
908 guint g_pipe_readable_msg = 0;
909
910 GIOChannel *
911 g_io_channel_win32_new_pipe (int fd)
912 {
913   return g_io_channel_win32_new_fd (fd);
914 }
915
916 GIOChannel *
917 g_io_channel_win32_new_pipe_with_wakeups (int   fd,
918                            guint peer,
919                            int   peer_fd)
920 {
921   return g_io_channel_win32_new_fd (fd);
922 }
923
924 void
925 g_io_channel_win32_pipe_request_wakeups (GIOChannel *channel,
926                           guint       peer,
927                           int         peer_fd)
928 {
929   /* Nothing needed now */
930 }
931
932 void
933 g_io_channel_win32_pipe_readable (gint  fd,
934                       guint offset)
935 {
936   /* Nothing needed now */
937 }
938