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