intial implementation of new API functions. Not sure if it behaves as
[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  * Copyright 2001 Andrew Lanoix
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24
25 /*
26  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
27  * file for a list of people on the GLib Team.  See the ChangeLog
28  * files for a list of changes.  These files are distributed with
29  * GLib at ftp://ftp.gtk.org/pub/gtk/.
30  */
31
32 /* Define this to get (very) verbose logging of all channels */
33 /* #define G_IO_WIN32_DEBUG */
34
35 #include "glib.h"
36
37 #include <stdlib.h>
38 #include <windows.h>
39 #include <winsock.h>          /* Not everybody has winsock2 */
40 #include <fcntl.h>
41 #include <io.h>
42 #include <process.h>
43 #include <errno.h>
44 #include <sys/stat.h>
45
46 #include "glibintl.h"
47
48 typedef struct _GIOWin32Channel GIOWin32Channel;
49 typedef struct _GIOWin32Watch GIOWin32Watch;
50
51 #define BUFFER_SIZE 4096
52
53 typedef enum {
54   G_IO_WIN32_WINDOWS_MESSAGES,  /* Windows messages */
55   G_IO_WIN32_FILE_DESC,         /* Unix-like file descriptors from
56                                  * _open() or _pipe(). Read with read().
57                                  * Have to create separate thread to read.
58                                  */
59   G_IO_WIN32_SOCKET             /* Sockets. A separate thread is blocked
60                                  * in select() most of the time.
61                                  */
62 } GIOWin32ChannelType;
63
64 struct _GIOWin32Channel {
65   GIOChannel channel;
66   gint fd;                      /* Either a Unix-like file handle as provided
67                                  * by the Microsoft C runtime, or a SOCKET
68                                  * as provided by WinSock.
69                                  */
70   GIOWin32ChannelType type;
71   
72   gboolean debug;
73
74   CRITICAL_SECTION mutex;
75
76   /* This is used by G_IO_WIN32_WINDOWS_MESSAGES channels */
77   HWND hwnd;                    /* handle of window, or NULL */
78   
79   /* Following fields are used by both fd and socket channels. */
80   gboolean running;             /* Is reader thread running. FALSE if
81                                  * EOF has been reached.
82                                  */
83   gboolean needs_close;         /* If the channel has been closed while
84                                  * the reader thread was still running.
85                                  */
86   guint thread_id;              /* If non-NULL has a reader thread, or has
87                                  * had.*/
88   HANDLE thread_handle;
89   HANDLE data_avail_event;
90
91   gushort revents;
92
93   /* Following fields used by fd channels for input */
94   
95   /* Data is kept in a circular buffer. To be able to distinguish between
96    * empty and full buffer, we cannot fill it completely, but have to
97    * leave a one character gap.
98    *
99    * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
100    *
101    * Empty:    wrp == rdp
102    * Full:     (wrp + 1) % BUFFER_SIZE == rdp
103    * Partial:  otherwise
104    */
105   guchar *buffer;               /* (Circular) buffer */
106   gint wrp, rdp;                /* Buffer indices for writing and reading */
107   HANDLE space_avail_event;
108
109   /* Following fields used by socket channels */
110   GSList *watches;
111   HANDLE data_avail_noticed_event;
112 };
113
114 #define LOCK(mutex) EnterCriticalSection (&mutex)
115 #define UNLOCK(mutex) LeaveCriticalSection (&mutex)
116
117 struct _GIOWin32Watch {
118   GSource       source;
119   GPollFD       pollfd;
120   GIOChannel   *channel;
121   GIOCondition  condition;
122   GIOFunc       callback;
123 };
124
125 static void
126 g_io_channel_win32_init (GIOWin32Channel *channel)
127 {
128 #ifdef G_IO_WIN32_DEBUG
129   channel->debug = TRUE;
130 #else
131   if (getenv ("G_IO_WIN32_DEBUG") != NULL)
132     channel->debug = TRUE;
133   else
134     channel->debug = FALSE;
135 #endif
136   channel->buffer = NULL;
137   channel->running = FALSE;
138   channel->needs_close = FALSE;
139   channel->thread_id = 0;
140   channel->data_avail_event = NULL;
141   channel->revents = 0;
142   channel->space_avail_event = NULL;
143   channel->data_avail_noticed_event = NULL;
144   channel->watches = NULL;
145   InitializeCriticalSection (&channel->mutex);
146 }
147
148 static void
149 create_events (GIOWin32Channel *channel)
150 {
151   SECURITY_ATTRIBUTES sec_attrs;
152   
153   sec_attrs.nLength = sizeof(SECURITY_ATTRIBUTES);
154   sec_attrs.lpSecurityDescriptor = NULL;
155   sec_attrs.bInheritHandle = FALSE;
156
157   /* The data available event is manual reset, the space available event
158    * is automatic reset.
159    */
160   if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
161       || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL))
162       || !(channel->data_avail_noticed_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
163     {
164       gchar *msg = g_win32_error_message (GetLastError ());
165       g_error ("Error creating event: %s", msg);
166     }
167 }
168
169 static unsigned __stdcall
170 read_thread (void *parameter)
171 {
172   GIOWin32Channel *channel = parameter;
173   guchar *buffer;
174   guint nbytes;
175
176   g_io_channel_ref ((GIOChannel *)channel);
177
178   if (channel->debug)
179     g_print ("read_thread %#x: start fd:%d, data_avail:%#x, space_avail:%#x\n",
180              channel->thread_id,
181              channel->fd,
182              (guint) channel->data_avail_event,
183              (guint) channel->space_avail_event);
184   
185   channel->buffer = g_malloc (BUFFER_SIZE);
186   channel->rdp = channel->wrp = 0;
187   channel->running = TRUE;
188
189   SetEvent (channel->space_avail_event);
190   
191   while (channel->running)
192     {
193       LOCK (channel->mutex);
194       if (channel->debug)
195         g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
196                  channel->thread_id, channel->rdp, channel->wrp);
197       if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
198         {
199           /* Buffer is full */
200           if (channel->debug)
201             g_print ("read_thread %#x: resetting space_avail\n",
202                      channel->thread_id);
203           ResetEvent (channel->space_avail_event);
204           if (channel->debug)
205             g_print ("read_thread %#x: waiting for space\n",
206                      channel->thread_id);
207           UNLOCK (channel->mutex);
208           WaitForSingleObject (channel->space_avail_event, INFINITE);
209           LOCK (channel->mutex);
210           if (channel->debug)
211             g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
212                      channel->thread_id, channel->rdp, channel->wrp);
213         }
214       
215       buffer = channel->buffer + channel->wrp;
216       
217       /* Always leave at least one byte unused gap to be able to
218        * distinguish between the full and empty condition...
219        */
220       nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
221                     BUFFER_SIZE - channel->wrp);
222
223       if (channel->debug)
224         g_print ("read_thread %#x: calling read() for %d bytes\n",
225                  channel->thread_id, nbytes);
226
227       UNLOCK (channel->mutex);
228
229       nbytes = read (channel->fd, buffer, nbytes);
230       
231       LOCK (channel->mutex);
232
233       channel->revents = G_IO_IN;
234       if (nbytes == 0)
235         channel->revents |= G_IO_HUP;
236       else if (nbytes < 0)
237         channel->revents |= G_IO_ERR;
238
239       if (channel->debug)
240         g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
241                  channel->thread_id, nbytes, channel->rdp, channel->wrp);
242
243       if (nbytes <= 0)
244         break;
245
246       channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
247       if (channel->debug)
248         g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
249                  channel->thread_id, channel->rdp, channel->wrp);
250       SetEvent (channel->data_avail_event);
251       UNLOCK (channel->mutex);
252     }
253   
254   channel->running = FALSE;
255   if (channel->needs_close)
256     {
257       if (channel->debug)
258         g_print ("read_thread %#x: channel fd %d needs closing\n",
259                  channel->thread_id, channel->fd);
260       close (channel->fd);
261       channel->fd = -1;
262     }
263
264   if (channel->debug)
265     g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
266              channel->thread_id, channel->rdp, channel->wrp);
267   SetEvent (channel->data_avail_event);
268   UNLOCK (channel->mutex);
269   
270   g_io_channel_unref((GIOChannel *)channel);
271   
272   /* No need to call _endthreadex(), the actual thread starter routine
273    * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
274    * _endthreadex() for us.
275    */
276
277   CloseHandle (channel->thread_handle);
278
279   return 0;
280 }
281
282 static void
283 create_thread (GIOWin32Channel     *channel,
284                GIOCondition         condition,
285                unsigned (__stdcall *thread) (void *parameter))
286 {
287   channel->thread_handle =
288     (HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
289                              &channel->thread_id);
290   if (channel->thread_handle == 0)
291     g_warning (G_STRLOC ": Error creating reader thread: %s",
292                strerror (errno));
293   WaitForSingleObject (channel->space_avail_event, INFINITE);
294 }
295
296 static GIOStatus
297 buffer_read (GIOWin32Channel *channel,
298              guchar          *dest,
299              gsize            count,
300              gsize           *bytes_read,
301              GError         **err)
302 {
303   guint nbytes;
304   guint left = count;
305   
306   LOCK (channel->mutex);
307   if (channel->debug)
308     g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
309              channel->thread_id, count, channel->rdp, channel->wrp);
310   
311   if (channel->wrp == channel->rdp)
312     {
313       UNLOCK (channel->mutex);
314       if (channel->debug)
315         g_print ("waiting for data from thread %#x\n", channel->thread_id);
316       WaitForSingleObject (channel->data_avail_event, INFINITE);
317       if (channel->debug)
318         g_print ("done waiting for data from thread %#x\n", channel->thread_id);
319       LOCK (channel->mutex);
320       if (channel->wrp == channel->rdp && !channel->running)
321         {
322           UNLOCK (channel->mutex);
323           *bytes_read = 0;
324           return G_IO_STATUS_EOF; /* Is this correct? FIXME */
325         }
326     }
327   
328   if (channel->rdp < channel->wrp)
329     nbytes = channel->wrp - channel->rdp;
330   else
331     nbytes = BUFFER_SIZE - channel->rdp;
332   UNLOCK (channel->mutex);
333   nbytes = MIN (left, nbytes);
334   if (channel->debug)
335     g_print ("moving %d bytes from thread %#x\n",
336              nbytes, channel->thread_id);
337   memcpy (dest, channel->buffer + channel->rdp, nbytes);
338   dest += nbytes;
339   left -= nbytes;
340   LOCK (channel->mutex);
341   channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
342   if (channel->debug)
343     g_print ("setting space_avail for thread %#x\n", channel->thread_id);
344   SetEvent (channel->space_avail_event);
345   if (channel->debug)
346     g_print ("for thread %#x: rdp=%d, wrp=%d\n",
347              channel->thread_id, channel->rdp, channel->wrp);
348   if (channel->running && channel->wrp == channel->rdp)
349     {
350       if (channel->debug)
351         g_print ("resetting data_avail of thread %#x\n",
352                  channel->thread_id);
353       ResetEvent (channel->data_avail_event);
354     };
355   UNLOCK (channel->mutex);
356   
357   /* We have no way to indicate any errors form the actual
358    * read() or recv() call in the reader thread. Should we have?
359    */
360   *bytes_read = count - left;
361   return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
362 }
363
364 static unsigned __stdcall
365 select_thread (void *parameter)
366 {
367   GIOWin32Channel *channel = parameter;
368   fd_set read_fds, write_fds, except_fds;
369   GSList *tmp;
370   int n;
371
372   g_io_channel_ref ((GIOChannel *)channel);
373
374   if (channel->debug)
375     g_print ("select_thread %#x: start fd:%d,\n\tdata_avail:%#x, data_avail_noticed:%#x\n",
376              channel->thread_id,
377              channel->fd,
378              (guint) channel->data_avail_event,
379              (guint) channel->data_avail_noticed_event);
380   
381   channel->rdp = channel->wrp = 0;
382   channel->running = TRUE;
383
384   SetEvent (channel->space_avail_event);
385   
386   while (channel->running)
387     {
388       FD_ZERO (&read_fds);
389       FD_ZERO (&write_fds);
390       FD_ZERO (&except_fds);
391
392       tmp = channel->watches;
393       while (tmp)
394         {
395           GIOWin32Watch *watch = (GIOWin32Watch *)tmp->data;
396
397           if (watch->condition & (G_IO_IN | G_IO_HUP))
398             FD_SET (channel->fd, &read_fds);
399           if (watch->condition & G_IO_OUT)
400             FD_SET (channel->fd, &write_fds);
401           if (watch->condition & G_IO_ERR)
402             FD_SET (channel->fd, &except_fds);
403           
404           tmp = tmp->next;
405         }
406       if (channel->debug)
407         g_print ("select_thread %#x: calling select() for%s%s%s\n",
408                  channel->thread_id,
409                  (FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
410                  (FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
411                  (FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
412
413       n = select (1, &read_fds, &write_fds, &except_fds, NULL);
414       
415       if (n == SOCKET_ERROR)
416         {
417           if (channel->debug)
418             g_print ("select_thread %#x: select returned SOCKET_ERROR\n",
419                      channel->thread_id);
420           break;
421         }
422
423       if (channel->debug)
424         g_print ("select_thread %#x: got%s%s%s\n",
425                  channel->thread_id,
426                  (FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
427                  (FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
428                  (FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
429
430       if (FD_ISSET (channel->fd, &read_fds))
431         channel->revents |= G_IO_IN;
432       if (FD_ISSET (channel->fd, &write_fds))
433         channel->revents |= G_IO_OUT;
434       if (FD_ISSET (channel->fd, &except_fds))
435         channel->revents |= G_IO_ERR;
436
437       if (channel->debug)
438         g_print ("select_thread %#x: resetting data_avail_noticed,\n"
439                  "\tsetting data_avail\n",
440                  channel->thread_id);
441       ResetEvent (channel->data_avail_noticed_event);
442       SetEvent (channel->data_avail_event);
443
444       LOCK (channel->mutex);
445       if (channel->needs_close)
446         {
447           UNLOCK (channel->mutex);
448           break;
449         }
450       UNLOCK (channel->mutex);
451
452       if (channel->debug)
453         g_print ("select_thread %#x: waiting for data_avail_noticed\n",
454                  channel->thread_id);
455
456       WaitForSingleObject (channel->data_avail_noticed_event, INFINITE);
457       if (channel->debug)
458         g_print ("select_thread %#x: got data_avail_noticed\n",
459                  channel->thread_id);
460     }
461   
462   channel->running = FALSE;
463   LOCK (channel->mutex);
464   if (channel->fd != -1)
465     {
466       /* DO NOT close the fd here */
467       channel->fd = -1;
468     }
469
470   if (channel->debug)
471     g_print ("select_thread %#x: got error, setting data_avail\n",
472              channel->thread_id);
473   SetEvent (channel->data_avail_event);
474   UNLOCK (channel->mutex);
475   
476   g_io_channel_unref((GIOChannel *)channel);
477   
478   /* No need to call _endthreadex(), the actual thread starter routine
479    * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
480    * _endthreadex() for us.
481    */
482
483   CloseHandle (channel->thread_handle);
484
485   return 0;
486 }
487
488 static gboolean
489 g_io_win32_prepare (GSource *source,
490                     gint    *timeout)
491 {
492   GIOWin32Watch *watch = (GIOWin32Watch *)source;
493   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
494   
495   *timeout = -1;
496   
497   if (channel->type == G_IO_WIN32_FILE_DESC)
498     {
499       LOCK (channel->mutex);
500       if (channel->running && channel->wrp == channel->rdp)
501         channel->revents = 0;
502       UNLOCK (channel->mutex);
503     }
504   else if (channel->type == G_IO_WIN32_SOCKET)
505     {
506       channel->revents = 0;
507
508       if (channel->debug)
509         g_print ("g_io_win32_prepare: thread %#x, setting data_avail_noticed\n",
510                  channel->thread_id);
511       SetEvent (channel->data_avail_noticed_event);
512       if (channel->debug)
513         g_print ("g_io_win32_prepare: thread %#x, there.\n",
514                  channel->thread_id);
515     }
516
517   watch->condition = g_io_channel_get_buffer_condition (watch->channel);
518
519   return (watch->pollfd.revents & (G_IO_IN | G_IO_OUT)) == watch->condition;
520 }
521
522 static gboolean
523 g_io_win32_check (GSource *source)
524 {
525         MSG msg;
526   GIOWin32Watch *watch = (GIOWin32Watch *)source;
527   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
528   
529   if (channel->debug)
530     g_print ("g_io_win32_check: for thread %#x:\n"
531              "\twatch->pollfd.events:%#x, watch->pollfd.revents:%#x, channel->revents:%#x\n",
532              channel->thread_id,
533              watch->pollfd.events, watch->pollfd.revents, channel->revents);
534
535   if (channel->type != G_IO_WIN32_WINDOWS_MESSAGES)
536         {
537      watch->pollfd.revents = (watch->pollfd.events & channel->revents);
538         }
539         else
540         {
541     return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE));
542         }
543
544   if (channel->type == G_IO_WIN32_SOCKET)
545     {
546       if (channel->debug)
547         g_print ("g_io_win32_check: thread %#x, resetting data_avail\n",
548                  channel->thread_id);
549       ResetEvent (channel->data_avail_event);
550       if (channel->debug)
551         g_print ("g_io_win32_check: thread %#x, there.\n",
552                  channel->thread_id);
553     }
554
555   watch->condition &= g_io_channel_get_buffer_condition (watch->channel);
556   
557   return (watch->pollfd.revents & watch->condition);
558 }
559
560 static gboolean
561 g_io_win32_dispatch (GSource     *source,
562                      GSourceFunc  callback,
563                      gpointer     user_data)
564 {
565   GIOFunc func = (GIOFunc)callback;
566   GIOWin32Watch *watch = (GIOWin32Watch *)source;
567   
568   if (!func)
569     {
570       g_warning (G_STRLOC ": GIOWin32Watch dispatched without callback\n"
571                  "You must call g_source_connect().");
572       return FALSE;
573     }
574   
575   return (*func) (watch->channel,
576                   watch->pollfd.revents & watch->condition,
577                   user_data);
578 }
579
580 static void
581 g_io_win32_finalize (GSource *source)
582 {
583   GIOWin32Watch *watch = (GIOWin32Watch *)source;
584   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
585   
586   if (channel->debug)
587     g_print ("g_io_win32_finalize: channel with thread %#x\n",
588              channel->thread_id);
589
590   channel->watches = g_slist_remove (channel->watches, watch);
591
592   SetEvent (channel->data_avail_noticed_event);
593   g_io_channel_unref (watch->channel);
594 }
595
596 static GSourceFuncs win32_watch_funcs = {
597   g_io_win32_prepare,
598   g_io_win32_check,
599   g_io_win32_dispatch,
600   g_io_win32_finalize
601 };
602
603 static GSource *
604 g_io_win32_create_watch (GIOChannel    *channel,
605                          GIOCondition   condition,
606                          unsigned (__stdcall *thread) (void *parameter))
607 {
608   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
609   GIOWin32Watch *watch;
610   GSource *source;
611
612   source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
613   watch = (GIOWin32Watch *)source;
614   
615   watch->channel = channel;
616   g_io_channel_ref (channel);
617   
618   watch->condition = condition;
619   
620   if (win32_channel->data_avail_event == NULL)
621     create_events (win32_channel);
622
623   watch->pollfd.fd = (gint) win32_channel->data_avail_event;
624   watch->pollfd.events = condition;
625   
626   if (win32_channel->debug)
627     g_print ("g_io_win32_create_watch: fd:%d condition:%#x handle:%#x\n",
628              win32_channel->fd, condition, watch->pollfd.fd);
629   
630   win32_channel->watches = g_slist_append (win32_channel->watches, watch);
631
632   if (win32_channel->thread_id == 0)
633     create_thread (win32_channel, condition, thread);
634
635   g_source_add_poll (source, &watch->pollfd);
636   
637   return source;
638 }
639
640 static GIOStatus
641 g_io_win32_msg_read (GIOChannel *channel,
642                      gchar      *buf,
643                      gsize       count,
644                      gsize      *bytes_read,
645                      GError    **err)
646 {
647   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
648   MSG msg;               /* In case of alignment problems */
649   
650   if (count < sizeof (MSG))
651     {
652       g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
653         _("Incorrect message size")); /* Correct error message? FIXME */
654       return G_IO_STATUS_ERROR;
655     }
656   
657   if (win32_channel->debug)
658     g_print ("g_io_win32_msg_read: for %#x\n",
659              win32_channel->hwnd);
660   if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
661     return G_IO_STATUS_AGAIN;
662   
663   memmove (buf, &msg, sizeof (MSG));
664   *bytes_read = sizeof (MSG);
665
666   return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
667 }
668
669 static GIOStatus
670 g_io_win32_msg_write (GIOChannel  *channel,
671                       const gchar *buf,
672                       gsize        count,
673                       gsize       *bytes_written,
674                       GError     **err)
675 {
676   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
677   MSG msg;
678   
679   if (count != sizeof (MSG))
680     {
681       g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
682         _("Incorrect message size")); /* Correct error message? FIXME */
683       return G_IO_STATUS_ERROR;
684     }
685   
686   /* In case of alignment problems */
687   memmove (&msg, buf, sizeof (MSG));
688   if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
689     {
690       g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED,
691         _("Unknown error")); /* Correct error message? FIXME */
692       return G_IO_STATUS_ERROR;
693     }
694
695   *bytes_written = sizeof (MSG);
696
697   return G_IO_STATUS_NORMAL;
698 }
699
700 static GIOStatus
701 g_io_win32_no_seek (GIOChannel *channel,
702                     glong       offset,
703                     GSeekType   type,
704                     GError     **err)
705 {
706   g_assert_not_reached ();
707
708   return G_IO_STATUS_ERROR;
709 }
710
711 static GIOStatus
712 g_io_win32_msg_close (GIOChannel *channel,
713                       GError    **err)
714 {
715   /* Nothing to be done. Or should we set hwnd to some invalid value? */
716
717   return G_IO_STATUS_NORMAL;
718 }
719
720 static void
721 g_io_win32_free (GIOChannel *channel)
722 {
723   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
724   
725   if (win32_channel->debug)
726     g_print ("thread %#x: freeing channel, fd: %d\n",
727              win32_channel->thread_id,
728              win32_channel->fd);
729
730   if (win32_channel->data_avail_event)
731     CloseHandle (win32_channel->data_avail_event);
732   if (win32_channel->space_avail_event)
733     CloseHandle (win32_channel->space_avail_event);
734   if (win32_channel->data_avail_noticed_event)
735     CloseHandle (win32_channel->data_avail_noticed_event);
736   DeleteCriticalSection (&win32_channel->mutex);
737
738   g_free (win32_channel->buffer);
739   g_slist_free (win32_channel->watches);
740   g_free (win32_channel);
741 }
742
743 static GSource *
744 g_io_win32_msg_create_watch (GIOChannel    *channel,
745                              GIOCondition   condition)
746 {
747   GIOWin32Watch *watch;
748   GSource *source;
749
750   source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
751   watch = (GIOWin32Watch *)source;
752   
753   watch->channel = channel;
754   g_io_channel_ref (channel);
755   
756   watch->condition = condition;
757   
758   watch->pollfd.fd = G_WIN32_MSG_HANDLE;
759   watch->pollfd.events = condition;
760   
761   g_source_add_poll (source, &watch->pollfd);
762   
763   return source;
764 }
765
766 static GIOStatus
767 g_io_win32_fd_read (GIOChannel *channel,
768                     gchar      *buf,
769                     gsize       count,
770                     gsize      *bytes_read,
771                     GError    **err)
772 {
773   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
774   gint result;
775   
776   if (win32_channel->debug)
777     g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
778              win32_channel->fd, count);
779   
780   if (win32_channel->thread_id)
781     {
782       return buffer_read (win32_channel, buf, count, bytes_read, err);
783     }
784
785   result = read (win32_channel->fd, buf, count);
786
787   if (result < 0)
788     {
789       *bytes_read = 0;
790
791       switch(errno)
792         {
793 #ifdef EAGAIN
794           case EAGAIN:
795             return G_IO_STATUS_AGAIN;
796 #endif
797           default:
798             g_set_error (err, G_IO_CHANNEL_ERROR,
799                          g_io_channel_error_from_errno (errno),
800                          strerror (errno));
801             return G_IO_STATUS_ERROR;
802         }
803     }
804
805   *bytes_read = result;
806
807   return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
808 }
809
810 static GIOStatus
811 g_io_win32_fd_write (GIOChannel  *channel,
812                      const gchar *buf,
813                      gsize        count,
814                      gsize       *bytes_written,
815                      GError     **err)
816 {
817   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
818   gint result;
819   
820   result = write (win32_channel->fd, buf, count);
821   if (win32_channel->debug)
822     g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
823              win32_channel->fd, count, result);
824
825   if (result < 0)
826     {
827       *bytes_written = 0;
828
829       switch(errno)
830         {
831 #ifdef EAGAIN
832           case EAGAIN:
833             return G_IO_STATUS_AGAIN;
834 #endif
835           default:
836             g_set_error (err, G_IO_CHANNEL_ERROR,
837                          g_io_channel_error_from_errno (errno),
838                          strerror (errno));
839             return G_IO_STATUS_ERROR;
840         }
841     }
842
843   *bytes_written = result;
844
845   return G_IO_STATUS_NORMAL;
846 }
847
848 static GIOStatus
849 g_io_win32_fd_seek (GIOChannel *channel,
850                     glong       offset,
851                     GSeekType   type,
852                     GError    **err)
853 {
854   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
855   int whence;
856   off_t result;
857   
858   switch (type)
859     {
860     case G_SEEK_SET:
861       whence = SEEK_SET;
862       break;
863     case G_SEEK_CUR:
864       whence = SEEK_CUR;
865       break;
866     case G_SEEK_END:
867       whence = SEEK_END;
868       break;
869     default:
870       whence = -1; /* Keep the compiler quiet */
871       g_assert_not_reached();
872     }
873   
874   result = lseek (win32_channel->fd, offset, whence);
875   
876   if (result < 0)
877     {
878       g_set_error (err, G_IO_CHANNEL_ERROR,
879                    g_io_channel_error_from_errno (errno),
880                    strerror (errno));
881       return G_IO_STATUS_ERROR;
882     }
883
884   return G_IO_STATUS_NORMAL;
885 }
886
887 static GIOStatus
888 g_io_win32_fd_close (GIOChannel *channel,
889                      GError    **err)
890 {
891   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
892   
893   if (win32_channel->debug)
894     g_print ("thread %#x: closing fd %d\n",
895              win32_channel->thread_id,
896              win32_channel->fd);
897   LOCK (win32_channel->mutex);
898   if (win32_channel->running)
899     {
900       if (win32_channel->debug)
901         g_print ("thread %#x: running, marking fd %d for later close\n",
902                  win32_channel->thread_id, win32_channel->fd);
903       win32_channel->running = FALSE;
904       win32_channel->needs_close = TRUE;
905       SetEvent (win32_channel->data_avail_event);
906     }
907   else
908     {
909       if (win32_channel->debug)
910         g_print ("closing fd %d\n", win32_channel->fd);
911       close (win32_channel->fd);
912       if (win32_channel->debug)
913         g_print ("closed fd %d, setting to -1\n",
914                  win32_channel->fd);
915       win32_channel->fd = -1;
916     }
917   UNLOCK (win32_channel->mutex);
918
919   /* FIXME error detection? */
920
921   return G_IO_STATUS_NORMAL;
922 }
923
924 static GSource *
925 g_io_win32_fd_create_watch (GIOChannel    *channel,
926                             GIOCondition   condition)
927 {
928   return g_io_win32_create_watch (channel, condition, read_thread);
929 }
930
931 static GIOStatus
932 g_io_win32_sock_read (GIOChannel *channel,
933                       gchar      *buf,
934                       gsize       count,
935                       gsize      *bytes_read,
936                       GError    **err)
937 {
938   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
939   gint result;
940   GIOChannelError error;
941
942   if (win32_channel->debug)
943     g_print ("g_io_win32_sock_read: sockfd:%d count:%d\n",
944              win32_channel->fd, count);
945 repeat: 
946   result = recv (win32_channel->fd, buf, count, 0);
947
948   if (win32_channel->debug)
949     g_print ("g_io_win32_sock_read: recv:%d\n", result);
950   
951   if (result == SOCKET_ERROR)
952     {
953       *bytes_read = 0;
954
955       switch (WSAGetLastError ())
956         {
957         case WSAEINVAL:
958           error = G_IO_CHANNEL_ERROR_INVAL;
959           break;
960         case WSAEWOULDBLOCK:
961           return G_IO_STATUS_AGAIN;
962 #ifdef WE_NEED_TO_HANDLE_WSAEINTR /* not anymore with wsock2 ? */
963         case WSAEINTR:
964           goto repeat;
965 #endif
966         default:
967           error = G_IO_CHANNEL_ERROR_FAILED;
968           break;
969         }
970       g_set_error(err, G_IO_CHANNEL_ERROR, error, _("Socket error"));
971       return G_IO_STATUS_ERROR;
972       /* FIXME get all errors, better error messages */
973     }
974   else
975     {
976       *bytes_read = result;
977
978       return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
979     }
980 }
981
982 static GIOStatus
983 g_io_win32_sock_write (GIOChannel  *channel,
984                        const gchar *buf,
985                        gsize        count,
986                        gsize       *bytes_written,
987                        GError     **err)
988 {
989   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
990   gint result;
991   GIOChannelError error;
992   
993   if (win32_channel->debug)
994     g_print ("g_io_win32_sock_write: sockfd:%d count:%d\n",
995              win32_channel->fd, count);
996 repeat:
997   result = send (win32_channel->fd, buf, count, 0);
998   
999   if (win32_channel->debug)
1000     g_print ("g_io_win32_sock_write: send:%d\n", result);
1001   
1002   if (result == SOCKET_ERROR)
1003     {
1004       *bytes_written = 0;
1005
1006       switch (WSAGetLastError ())
1007         {
1008         case WSAEINVAL:
1009           error = G_IO_CHANNEL_ERROR_INVAL;
1010           break;
1011         case WSAEWOULDBLOCK:
1012           return G_IO_STATUS_AGAIN;
1013 #ifdef WE_NEED_TO_HANDLE_WSAEINTR /* not anymore with wsock2 ? */
1014         case WSAEINTR:
1015           goto repeat;
1016 #endif
1017         default:
1018           error = G_IO_CHANNEL_ERROR_FAILED;
1019           break;
1020         }
1021       g_set_error(err, G_IO_CHANNEL_ERROR, error, _("Socket error"));
1022       return G_IO_STATUS_ERROR;
1023       /* FIXME get all errors, better error messages */
1024     }
1025   else
1026     {
1027       *bytes_written = result;
1028
1029       return G_IO_STATUS_NORMAL;
1030     }
1031 }
1032
1033 static GIOStatus
1034 g_io_win32_sock_close (GIOChannel *channel,
1035                        GError    **err)
1036 {
1037   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1038
1039   LOCK(win32_channel->mutex);
1040   if (win32_channel->running)
1041   {
1042     if (win32_channel->debug)
1043         g_print ("thread %#x: running, marking for later close\n",
1044                  win32_channel->thread_id);
1045     win32_channel->running = FALSE;
1046     win32_channel->needs_close = TRUE;
1047     SetEvent(win32_channel->data_avail_noticed_event);
1048   }
1049   if (win32_channel->fd != -1)
1050   {
1051     if (win32_channel->debug)
1052        g_print ("thread %#x: closing socket %d\n",
1053              win32_channel->thread_id,
1054              win32_channel->fd);
1055   
1056     closesocket (win32_channel->fd);
1057     win32_channel->fd = -1;
1058   }
1059   UNLOCK(win32_channel->mutex);
1060
1061   /* FIXME error detection? */
1062
1063   return G_IO_STATUS_NORMAL;
1064 }
1065
1066 static GSource *
1067 g_io_win32_sock_create_watch (GIOChannel    *channel,
1068                               GIOCondition   condition)
1069 {
1070   return g_io_win32_create_watch (channel, condition, select_thread);
1071 }
1072
1073 GIOChannel *
1074 g_io_channel_new_file (const gchar  *filename,
1075                        const gchar  *mode,
1076                        GError      **error)
1077 {
1078   int fid, flags;
1079   GIOChannel *channel;
1080
1081   enum { /* Cheesy hack */
1082     MODE_R = 1 << 0,
1083     MODE_W = 1 << 1,
1084     MODE_A = 1 << 2,
1085     MODE_PLUS = 1 << 3,
1086   } mode_num;
1087
1088   g_return_val_if_fail (filename != NULL, NULL);
1089   g_return_val_if_fail (mode != NULL, NULL);
1090   g_return_val_if_fail ((error == NULL) || (*error == NULL), NULL);
1091
1092   switch (mode[0])
1093     {
1094       case 'r':
1095         mode_num = MODE_R;
1096         break;
1097       case 'w':
1098         mode_num = MODE_W;
1099         break;
1100       case 'a':
1101         mode_num = MODE_A;
1102         break;
1103       default:
1104         g_warning ("Invalid GIOFileMode %s.\n", mode);
1105         return NULL;
1106     }
1107
1108   switch (mode[1])
1109     {
1110       case '\0':
1111         break;
1112       case '+':
1113         if (mode[2] == '\0')
1114           {
1115             mode_num |= MODE_PLUS;
1116             break;
1117           }
1118         /* Fall through */
1119       default:
1120         g_warning ("Invalid GIOFileMode %s.\n", mode);
1121         return NULL;
1122     }
1123
1124   switch (mode_num)
1125     {
1126       case MODE_R:
1127         flags = O_RDONLY;
1128         break;
1129       case MODE_W:
1130         flags = O_WRONLY | O_TRUNC | O_CREAT;
1131         break;
1132       case MODE_A:
1133         flags = O_WRONLY | O_APPEND | O_CREAT;
1134         break;
1135       case MODE_R | MODE_PLUS:
1136         flags = O_RDWR;
1137         break;
1138       case MODE_W | MODE_PLUS:
1139         flags = O_RDWR | O_TRUNC | O_CREAT;
1140         break;
1141       case MODE_A | MODE_PLUS:
1142         flags = O_RDWR | O_APPEND | O_CREAT;
1143         break;
1144       default:
1145         g_assert_not_reached ();
1146         flags = 0;
1147     }
1148
1149
1150   fid = open (filename, flags);
1151   if (fid < 0)
1152     {
1153       g_set_error (error, G_FILE_ERROR,
1154                    g_file_error_from_errno (errno),
1155                    strerror (errno));
1156       return (GIOChannel *)NULL;
1157     }
1158
1159   channel = g_io_channel_win32_new_fd (fid);
1160
1161   /* XXX: move this to g_io_channel_win32_new_fd () */
1162   channel->close_on_unref = TRUE;
1163   channel->is_seekable = TRUE;
1164
1165   switch (mode_num)
1166     {
1167       case MODE_R:
1168         channel->is_readable = TRUE;
1169         channel->is_writeable = FALSE;
1170         break;
1171       case MODE_W:
1172       case MODE_A:
1173         channel->is_readable = FALSE;
1174         channel->is_writeable = TRUE;
1175         break;
1176       case MODE_R | MODE_PLUS:
1177       case MODE_W | MODE_PLUS:
1178       case MODE_A | MODE_PLUS:
1179         channel->is_readable = TRUE;
1180         channel->is_writeable = TRUE;
1181         break;
1182       default:
1183         g_assert_not_reached ();
1184     }
1185
1186   if (((GIOWin32Channel *)channel)->debug)
1187     g_print ("g_io_channel_win32_new_file: fd = %ud\n", fid);
1188
1189   return channel;
1190 }
1191
1192 GIOStatus
1193 g_io_win32_set_flags (GIOChannel     *channel,
1194                       GIOFlags        flags,
1195                       GError        **err)
1196 {
1197   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1198
1199   g_set_error (err, 
1200                G_IO_CHANNEL_ERROR, 
1201                g_file_error_from_errno (EACCES), 
1202                _("Channel set flags unsupported"));
1203   return G_IO_STATUS_ERROR;
1204 }
1205
1206 GIOFlags
1207 g_io_win32_fd_get_flags (GIOChannel     *channel)
1208 {
1209   GIOFlags flags = 0;
1210   struct _stat st;
1211   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1212
1213   g_return_val_if_fail (win32_channel != NULL, 0);
1214   g_return_val_if_fail (win32_channel->type == G_IO_WIN32_FILE_DESC, 0);
1215
1216   if (0 == _fstat (win32_channel->fd, &st))
1217     {
1218        /* XXX: G_IO_FLAG_APPEND */
1219        /* XXX: G_IO_FLAG_NONBLOCK */
1220        if (st.st_mode & _S_IREAD)    flags |= G_IO_FLAG_IS_READABLE;
1221        if (st.st_mode & _S_IWRITE)   flags |= G_IO_FLAG_IS_WRITEABLE;
1222        /* XXX: */
1223        if (!(st.st_mode & _S_IFIFO)) flags |= G_IO_FLAG_IS_SEEKABLE;
1224     }
1225
1226   return flags;
1227 }
1228
1229 /*
1230  * Generic implementation, just translating createion flags
1231  */
1232 GIOFlags
1233 g_io_win32_get_flags (GIOChannel     *channel)
1234 {
1235   GIOFlags flags;
1236
1237   flags =   (channel->is_readable ? G_IO_FLAG_IS_READABLE : 0)
1238           | (channel->is_writeable ? G_IO_FLAG_IS_READABLE : 0)
1239           | (channel->is_seekable ? G_IO_FLAG_IS_SEEKABLE : 0);
1240
1241   return flags;
1242 }
1243
1244 static GIOFuncs win32_channel_msg_funcs = {
1245   g_io_win32_msg_read,
1246   g_io_win32_msg_write,
1247   g_io_win32_no_seek,
1248   g_io_win32_msg_close,
1249   g_io_win32_msg_create_watch,
1250   g_io_win32_free,
1251   g_io_win32_set_flags,
1252   g_io_win32_get_flags,
1253 };
1254
1255 static GIOFuncs win32_channel_fd_funcs = {
1256   g_io_win32_fd_read,
1257   g_io_win32_fd_write,
1258   g_io_win32_fd_seek,
1259   g_io_win32_fd_close,
1260   g_io_win32_fd_create_watch,
1261   g_io_win32_free,
1262   g_io_win32_set_flags,
1263   g_io_win32_fd_get_flags,
1264 };
1265
1266 static GIOFuncs win32_channel_sock_funcs = {
1267   g_io_win32_sock_read,
1268   g_io_win32_sock_write,
1269   g_io_win32_no_seek,
1270   g_io_win32_sock_close,
1271   g_io_win32_sock_create_watch,
1272   g_io_win32_free,
1273   g_io_win32_set_flags,
1274   g_io_win32_get_flags,
1275 };
1276
1277 GIOChannel *
1278 g_io_channel_win32_new_messages (guint hwnd)
1279 {
1280   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1281   GIOChannel *channel = (GIOChannel *)win32_channel;
1282
1283   g_io_channel_init (channel);
1284   g_io_channel_win32_init (win32_channel);
1285   if (win32_channel->debug)
1286     g_print ("g_io_channel_win32_new_messages: hwnd = %ud\n", hwnd);
1287   channel->funcs = &win32_channel_msg_funcs;
1288   win32_channel->type = G_IO_WIN32_WINDOWS_MESSAGES;
1289   win32_channel->hwnd = (HWND) hwnd;
1290
1291   /* XXX: check this. */
1292   channel->is_readable = IsWindow (win32_channel->hwnd);
1293   channel->is_writeable = IsWindow (win32_channel->hwnd);
1294
1295   channel->is_seekable = FALSE;
1296
1297   return channel;
1298 }
1299
1300 GIOChannel *
1301 g_io_channel_win32_new_fd (gint fd)
1302 {
1303   GIOWin32Channel *win32_channel;
1304   GIOChannel *channel;
1305   struct stat st;
1306
1307   if (fstat (fd, &st) == -1)
1308     {
1309       g_warning (G_STRLOC ": %d isn't a (emulated) file descriptor", fd);
1310       return NULL;
1311     }
1312
1313   win32_channel = g_new (GIOWin32Channel, 1);
1314   channel = (GIOChannel *)win32_channel;
1315
1316   g_io_channel_init (channel);
1317   g_io_channel_win32_init (win32_channel);
1318   if (win32_channel->debug)
1319     g_print ("g_io_channel_win32_new_fd: fd = %d\n", fd);
1320   channel->funcs = &win32_channel_fd_funcs;
1321   win32_channel->type = G_IO_WIN32_FILE_DESC;
1322   win32_channel->fd = fd;
1323
1324
1325   channel->is_readable  = !!(st.st_mode & _S_IREAD);
1326   channel->is_writeable = !!(st.st_mode & _S_IWRITE);
1327   /* XXX: pipes aren't seeakable, are they ? */
1328   channel->is_seekable = !(st.st_mode & _S_IFIFO);
1329
1330   return channel;
1331 }
1332
1333 gint
1334 g_io_channel_win32_get_fd (GIOChannel *channel)
1335 {
1336   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1337
1338   return win32_channel->fd;
1339 }
1340
1341 GIOChannel *
1342 g_io_channel_win32_new_socket (int socket)
1343 {
1344   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1345   GIOChannel *channel = (GIOChannel *)win32_channel;
1346
1347   g_io_channel_init (channel);
1348   g_io_channel_win32_init (win32_channel);
1349   if (win32_channel->debug)
1350     g_print ("g_io_channel_win32_new_socket: sockfd:%d\n", socket);
1351   channel->funcs = &win32_channel_sock_funcs;
1352   win32_channel->type = G_IO_WIN32_SOCKET;
1353   win32_channel->fd = socket;
1354
1355   /* XXX: check this */
1356   channel->is_readable = TRUE;
1357   channel->is_writeable = TRUE;
1358   channel->is_seekable = FALSE;
1359
1360   return channel;
1361 }
1362
1363 GIOChannel *
1364 g_io_channel_unix_new (gint fd)
1365 {
1366   struct stat st;
1367
1368   if (fstat (fd, &st) == 0)
1369     return g_io_channel_win32_new_fd (fd);
1370   
1371   if (getsockopt (fd, SOL_SOCKET, SO_TYPE, NULL, NULL) != SO_ERROR)
1372     return g_io_channel_win32_new_socket(fd);
1373
1374   g_warning (G_STRLOC ": %d is neither a file descriptor or a socket", fd);
1375   return NULL;
1376 }
1377
1378 gint
1379 g_io_channel_unix_get_fd (GIOChannel *channel)
1380 {
1381   return g_io_channel_win32_get_fd (channel);
1382 }
1383
1384 void
1385 g_io_channel_win32_set_debug (GIOChannel *channel,
1386                               gboolean    flag)
1387 {
1388   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1389
1390   win32_channel->debug = flag;
1391 }
1392
1393 gint
1394 g_io_channel_win32_poll (GPollFD *fds,
1395                          gint     n_fds,
1396                          gint     timeout)
1397 {
1398   int result;
1399
1400   g_return_val_if_fail (n_fds >= 0, 0);
1401
1402   result = (*g_main_context_get_poll_func (NULL)) (fds, n_fds, timeout);
1403
1404   return result;
1405 }
1406
1407 void
1408 g_io_channel_win32_make_pollfd (GIOChannel   *channel,
1409                                 GIOCondition  condition,
1410                                 GPollFD      *fd)
1411 {
1412   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1413
1414   if (win32_channel->data_avail_event == NULL)
1415     create_events (win32_channel);
1416   
1417   fd->fd = (gint) win32_channel->data_avail_event;
1418   fd->events = condition;
1419
1420   if (win32_channel->thread_id == 0)
1421     if ((condition & G_IO_IN) && win32_channel->type == G_IO_WIN32_FILE_DESC)
1422       create_thread (win32_channel, condition, read_thread);
1423     else if (win32_channel->type == G_IO_WIN32_SOCKET)
1424       create_thread (win32_channel, condition, select_thread);
1425 }
1426
1427 /* Binary compatibility */
1428 GIOChannel *
1429 g_io_channel_win32_new_stream_socket (int socket)
1430 {
1431   return g_io_channel_win32_new_socket (socket);
1432 }