00e16408606b5739473a59a02ecb73cdb43bc502
[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_NORMAL; /* as before, normal case ? */
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   return FALSE;
518   /* XXX: why should we want to do this ? */
519   watch->condition = g_io_channel_get_buffer_condition (watch->channel);
520
521   return (watch->pollfd.revents & (G_IO_IN | G_IO_OUT)) == watch->condition;
522 }
523
524 static gboolean
525 g_io_win32_check (GSource *source)
526 {
527         MSG msg;
528   GIOWin32Watch *watch = (GIOWin32Watch *)source;
529   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
530   GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
531
532   
533   if (channel->debug)
534     g_print ("g_io_win32_check: for thread %#x:\n"
535              "\twatch->pollfd.events:%#x, watch->pollfd.revents:%#x, channel->revents:%#x\n",
536              channel->thread_id,
537              watch->pollfd.events, watch->pollfd.revents, channel->revents);
538
539   if (channel->type != G_IO_WIN32_WINDOWS_MESSAGES)
540         {
541      watch->pollfd.revents = (watch->pollfd.events & channel->revents);
542         }
543         else
544         {
545     return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE));
546         }
547
548   if (channel->type == G_IO_WIN32_SOCKET)
549     {
550       if (channel->debug)
551         g_print ("g_io_win32_check: thread %#x, resetting data_avail\n",
552                  channel->thread_id);
553       ResetEvent (channel->data_avail_event);
554       if (channel->debug)
555         g_print ("g_io_win32_check: thread %#x, there.\n",
556                  channel->thread_id);
557     }
558
559   return (watch->pollfd.revents & watch->condition);
560 }
561
562 static gboolean
563 g_io_win32_dispatch (GSource     *source,
564                      GSourceFunc  callback,
565                      gpointer     user_data)
566 {
567   GIOFunc func = (GIOFunc)callback;
568   GIOWin32Watch *watch = (GIOWin32Watch *)source;
569   
570   if (!func)
571     {
572       g_warning (G_STRLOC ": GIOWin32Watch dispatched without callback\n"
573                  "You must call g_source_connect().");
574       return FALSE;
575     }
576   
577   return (*func) (watch->channel,
578                   watch->pollfd.revents & watch->condition,
579                   user_data);
580 }
581
582 static void
583 g_io_win32_finalize (GSource *source)
584 {
585   GIOWin32Watch *watch = (GIOWin32Watch *)source;
586   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
587   
588   if (channel->debug)
589     g_print ("g_io_win32_finalize: channel with thread %#x\n",
590              channel->thread_id);
591
592   channel->watches = g_slist_remove (channel->watches, watch);
593
594   SetEvent (channel->data_avail_noticed_event);
595   g_io_channel_unref (watch->channel);
596 }
597
598 GSourceFuncs g_io_watch_funcs = {
599   g_io_win32_prepare,
600   g_io_win32_check,
601   g_io_win32_dispatch,
602   g_io_win32_finalize
603 };
604
605 static GSource *
606 g_io_win32_create_watch (GIOChannel    *channel,
607                          GIOCondition   condition,
608                          unsigned (__stdcall *thread) (void *parameter))
609 {
610   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
611   GIOWin32Watch *watch;
612   GSource *source;
613
614   source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
615   watch = (GIOWin32Watch *)source;
616   
617   watch->channel = channel;
618   g_io_channel_ref (channel);
619   
620   watch->condition = condition;
621   
622   if (win32_channel->data_avail_event == NULL)
623     create_events (win32_channel);
624
625   watch->pollfd.fd = (gint) win32_channel->data_avail_event;
626   watch->pollfd.events = condition;
627   
628   if (win32_channel->debug)
629     g_print ("g_io_win32_create_watch: fd:%d condition:%#x handle:%#x\n",
630              win32_channel->fd, condition, watch->pollfd.fd);
631   
632   win32_channel->watches = g_slist_append (win32_channel->watches, watch);
633
634   if (win32_channel->thread_id == 0)
635     create_thread (win32_channel, condition, thread);
636
637   g_source_add_poll (source, &watch->pollfd);
638   
639   return source;
640 }
641
642 static GIOStatus
643 g_io_win32_msg_read (GIOChannel *channel,
644                      gchar      *buf,
645                      gsize       count,
646                      gsize      *bytes_read,
647                      GError    **err)
648 {
649   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
650   MSG msg;               /* In case of alignment problems */
651   
652   if (count < sizeof (MSG))
653     {
654       g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
655         _("Incorrect message size")); /* Correct error message? FIXME */
656       return G_IO_STATUS_ERROR;
657     }
658   
659   if (win32_channel->debug)
660     g_print ("g_io_win32_msg_read: for %#x\n",
661              win32_channel->hwnd);
662   if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
663     return G_IO_STATUS_AGAIN;
664
665   memmove (buf, &msg, sizeof (MSG));
666   *bytes_read = sizeof (MSG);
667
668   return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
669 }
670
671 static GIOStatus
672 g_io_win32_msg_write (GIOChannel  *channel,
673                       const gchar *buf,
674                       gsize        count,
675                       gsize       *bytes_written,
676                       GError     **err)
677 {
678   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
679   MSG msg;
680   
681   if (count != sizeof (MSG))
682     {
683       g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
684         _("Incorrect message size")); /* Correct error message? FIXME */
685       return G_IO_STATUS_ERROR;
686     }
687   
688   /* In case of alignment problems */
689   memmove (&msg, buf, sizeof (MSG));
690   if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
691     {
692       g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED,
693         _("Unknown error")); /* Correct error message? FIXME */
694       return G_IO_STATUS_ERROR;
695     }
696
697   *bytes_written = sizeof (MSG);
698
699   return G_IO_STATUS_NORMAL;
700 }
701
702 static GIOStatus
703 g_io_win32_no_seek (GIOChannel *channel,
704                     glong       offset,
705                     GSeekType   type,
706                     GError     **err)
707 {
708   g_assert_not_reached ();
709
710   return G_IO_STATUS_ERROR;
711 }
712
713 static GIOStatus
714 g_io_win32_msg_close (GIOChannel *channel,
715                       GError    **err)
716 {
717   /* Nothing to be done. Or should we set hwnd to some invalid value? */
718
719   return G_IO_STATUS_NORMAL;
720 }
721
722 static void
723 g_io_win32_free (GIOChannel *channel)
724 {
725   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
726   
727   if (win32_channel->debug)
728     g_print ("thread %#x: freeing channel, fd: %d\n",
729              win32_channel->thread_id,
730              win32_channel->fd);
731
732   if (win32_channel->data_avail_event)
733     CloseHandle (win32_channel->data_avail_event);
734   if (win32_channel->space_avail_event)
735     CloseHandle (win32_channel->space_avail_event);
736   if (win32_channel->data_avail_noticed_event)
737     CloseHandle (win32_channel->data_avail_noticed_event);
738   DeleteCriticalSection (&win32_channel->mutex);
739
740   g_free (win32_channel->buffer);
741   g_slist_free (win32_channel->watches);
742   g_free (win32_channel);
743 }
744
745 static GSource *
746 g_io_win32_msg_create_watch (GIOChannel    *channel,
747                              GIOCondition   condition)
748 {
749   GIOWin32Watch *watch;
750   GSource *source;
751
752   source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
753   watch = (GIOWin32Watch *)source;
754   
755   watch->channel = channel;
756   g_io_channel_ref (channel);
757   
758   watch->condition = condition;
759   
760   watch->pollfd.fd = G_WIN32_MSG_HANDLE;
761   watch->pollfd.events = condition;
762   
763   g_source_add_poll (source, &watch->pollfd);
764   
765   return source;
766 }
767
768 static GIOStatus
769 g_io_win32_fd_read (GIOChannel *channel,
770                     gchar      *buf,
771                     gsize       count,
772                     gsize      *bytes_read,
773                     GError    **err)
774 {
775   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
776   gint result;
777   
778   if (win32_channel->debug)
779     g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
780              win32_channel->fd, count);
781   
782   if (win32_channel->thread_id)
783     {
784       return buffer_read (win32_channel, buf, count, bytes_read, err);
785     }
786
787   result = read (win32_channel->fd, buf, count);
788
789   if (result < 0)
790     {
791       *bytes_read = 0;
792
793       switch(errno)
794         {
795 #ifdef EAGAIN
796           case EAGAIN:
797             return G_IO_STATUS_AGAIN;
798 #endif
799           default:
800             g_set_error (err, G_IO_CHANNEL_ERROR,
801                          g_io_channel_error_from_errno (errno),
802                          strerror (errno));
803             return G_IO_STATUS_ERROR;
804         }
805     }
806
807   *bytes_read = result;
808
809   return G_IO_STATUS_NORMAL; /* XXX: 0 byte read an error ?? */
810   return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
811 }
812
813 static GIOStatus
814 g_io_win32_fd_write (GIOChannel  *channel,
815                      const gchar *buf,
816                      gsize        count,
817                      gsize       *bytes_written,
818                      GError     **err)
819 {
820   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
821   gint result;
822   
823   result = write (win32_channel->fd, buf, count);
824   if (win32_channel->debug)
825     g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
826              win32_channel->fd, count, result);
827
828   if (result < 0)
829     {
830       *bytes_written = 0;
831
832       switch(errno)
833         {
834 #ifdef EAGAIN
835           case EAGAIN:
836             return G_IO_STATUS_AGAIN;
837 #endif
838           default:
839             g_set_error (err, G_IO_CHANNEL_ERROR,
840                          g_io_channel_error_from_errno (errno),
841                          strerror (errno));
842             return G_IO_STATUS_ERROR;
843         }
844     }
845
846   *bytes_written = result;
847
848   return G_IO_STATUS_NORMAL;
849 }
850
851 static GIOStatus
852 g_io_win32_fd_seek (GIOChannel *channel,
853                     glong       offset,
854                     GSeekType   type,
855                     GError    **err)
856 {
857   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
858   int whence;
859   off_t result;
860   
861   switch (type)
862     {
863     case G_SEEK_SET:
864       whence = SEEK_SET;
865       break;
866     case G_SEEK_CUR:
867       whence = SEEK_CUR;
868       break;
869     case G_SEEK_END:
870       whence = SEEK_END;
871       break;
872     default:
873       whence = -1; /* Keep the compiler quiet */
874       g_assert_not_reached();
875     }
876   
877   result = lseek (win32_channel->fd, offset, whence);
878   
879   if (result < 0)
880     {
881       g_set_error (err, G_IO_CHANNEL_ERROR,
882                    g_io_channel_error_from_errno (errno),
883                    strerror (errno));
884       return G_IO_STATUS_ERROR;
885     }
886
887   return G_IO_STATUS_NORMAL;
888 }
889
890 static GIOStatus
891 g_io_win32_fd_close (GIOChannel *channel,
892                      GError    **err)
893 {
894   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
895   
896   if (win32_channel->debug)
897     g_print ("thread %#x: closing fd %d\n",
898              win32_channel->thread_id,
899              win32_channel->fd);
900   LOCK (win32_channel->mutex);
901   if (win32_channel->running)
902     {
903       if (win32_channel->debug)
904         g_print ("thread %#x: running, marking fd %d for later close\n",
905                  win32_channel->thread_id, win32_channel->fd);
906       win32_channel->running = FALSE;
907       win32_channel->needs_close = TRUE;
908       SetEvent (win32_channel->data_avail_event);
909     }
910   else
911     {
912       if (win32_channel->debug)
913         g_print ("closing fd %d\n", win32_channel->fd);
914       close (win32_channel->fd);
915       if (win32_channel->debug)
916         g_print ("closed fd %d, setting to -1\n",
917                  win32_channel->fd);
918       win32_channel->fd = -1;
919     }
920   UNLOCK (win32_channel->mutex);
921
922   /* FIXME error detection? */
923
924   return G_IO_STATUS_NORMAL;
925 }
926
927 static GSource *
928 g_io_win32_fd_create_watch (GIOChannel    *channel,
929                             GIOCondition   condition)
930 {
931   return g_io_win32_create_watch (channel, condition, read_thread);
932 }
933
934 static GIOStatus
935 g_io_win32_sock_read (GIOChannel *channel,
936                       gchar      *buf,
937                       gsize       count,
938                       gsize      *bytes_read,
939                       GError    **err)
940 {
941   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
942   gint result;
943   GIOChannelError error;
944
945   if (win32_channel->debug)
946     g_print ("g_io_win32_sock_read: sockfd:%d count:%d\n",
947              win32_channel->fd, count);
948 repeat: 
949   result = recv (win32_channel->fd, buf, count, 0);
950
951   if (win32_channel->debug)
952     g_print ("g_io_win32_sock_read: recv:%d\n", result);
953   
954   if (result == SOCKET_ERROR)
955     {
956       *bytes_read = 0;
957
958       switch (WSAGetLastError ())
959         {
960         case WSAEINVAL:
961           error = G_IO_CHANNEL_ERROR_INVAL;
962           break;
963         case WSAEWOULDBLOCK:
964           return G_IO_STATUS_AGAIN;
965 #ifdef WE_NEED_TO_HANDLE_WSAEINTR /* not anymore with wsock2 ? */
966         case WSAEINTR:
967           goto repeat;
968 #endif
969         default:
970           error = G_IO_CHANNEL_ERROR_FAILED;
971           break;
972         }
973       g_set_error(err, G_IO_CHANNEL_ERROR, error, _("Socket error"));
974       return G_IO_STATUS_ERROR;
975       /* FIXME get all errors, better error messages */
976     }
977   else
978     {
979       *bytes_read = result;
980
981       return G_IO_STATUS_NORMAL; /* XXX: 0 byte read an error ?? */
982       return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
983     }
984 }
985
986 static GIOStatus
987 g_io_win32_sock_write (GIOChannel  *channel,
988                        const gchar *buf,
989                        gsize        count,
990                        gsize       *bytes_written,
991                        GError     **err)
992 {
993   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
994   gint result;
995   GIOChannelError error;
996   
997   if (win32_channel->debug)
998     g_print ("g_io_win32_sock_write: sockfd:%d count:%d\n",
999              win32_channel->fd, count);
1000 repeat:
1001   result = send (win32_channel->fd, buf, count, 0);
1002   
1003   if (win32_channel->debug)
1004     g_print ("g_io_win32_sock_write: send:%d\n", result);
1005   
1006   if (result == SOCKET_ERROR)
1007     {
1008       *bytes_written = 0;
1009
1010       switch (WSAGetLastError ())
1011         {
1012         case WSAEINVAL:
1013           error = G_IO_CHANNEL_ERROR_INVAL;
1014           break;
1015         case WSAEWOULDBLOCK:
1016           return G_IO_STATUS_AGAIN;
1017 #ifdef WE_NEED_TO_HANDLE_WSAEINTR /* not anymore with wsock2 ? */
1018         case WSAEINTR:
1019           goto repeat;
1020 #endif
1021         default:
1022           error = G_IO_CHANNEL_ERROR_FAILED;
1023           break;
1024         }
1025       g_set_error(err, G_IO_CHANNEL_ERROR, error, _("Socket error"));
1026       return G_IO_STATUS_ERROR;
1027       /* FIXME get all errors, better error messages */
1028     }
1029   else
1030     {
1031       *bytes_written = result;
1032
1033       return G_IO_STATUS_NORMAL;
1034     }
1035 }
1036
1037 static GIOStatus
1038 g_io_win32_sock_close (GIOChannel *channel,
1039                        GError    **err)
1040 {
1041   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1042
1043   LOCK(win32_channel->mutex);
1044   if (win32_channel->running)
1045   {
1046     if (win32_channel->debug)
1047         g_print ("thread %#x: running, marking for later close\n",
1048                  win32_channel->thread_id);
1049     win32_channel->running = FALSE;
1050     win32_channel->needs_close = TRUE;
1051     SetEvent(win32_channel->data_avail_noticed_event);
1052   }
1053   if (win32_channel->fd != -1)
1054   {
1055     if (win32_channel->debug)
1056        g_print ("thread %#x: closing socket %d\n",
1057              win32_channel->thread_id,
1058              win32_channel->fd);
1059   
1060     closesocket (win32_channel->fd);
1061     win32_channel->fd = -1;
1062   }
1063   UNLOCK(win32_channel->mutex);
1064
1065   /* FIXME error detection? */
1066
1067   return G_IO_STATUS_NORMAL;
1068 }
1069
1070 static GSource *
1071 g_io_win32_sock_create_watch (GIOChannel    *channel,
1072                               GIOCondition   condition)
1073 {
1074   return g_io_win32_create_watch (channel, condition, select_thread);
1075 }
1076
1077 GIOChannel *
1078 g_io_channel_new_file (const gchar  *filename,
1079                        const gchar  *mode,
1080                        GError      **error)
1081 {
1082   int fid, flags, pmode;
1083   GIOChannel *channel;
1084
1085   enum { /* Cheesy hack */
1086     MODE_R = 1 << 0,
1087     MODE_W = 1 << 1,
1088     MODE_A = 1 << 2,
1089     MODE_PLUS = 1 << 3,
1090   } mode_num;
1091
1092   g_return_val_if_fail (filename != NULL, NULL);
1093   g_return_val_if_fail (mode != NULL, NULL);
1094   g_return_val_if_fail ((error == NULL) || (*error == NULL), NULL);
1095
1096   switch (mode[0])
1097     {
1098       case 'r':
1099         mode_num = MODE_R;
1100         break;
1101       case 'w':
1102         mode_num = MODE_W;
1103         break;
1104       case 'a':
1105         mode_num = MODE_A;
1106         break;
1107       default:
1108         g_warning (G_STRLOC ": Invalid GIOFileMode %s.\n", mode);
1109         return NULL;
1110     }
1111
1112   switch (mode[1])
1113     {
1114       case '\0':
1115         break;
1116       case '+':
1117         if (mode[2] == '\0')
1118           {
1119             mode_num |= MODE_PLUS;
1120             break;
1121           }
1122         /* Fall through */
1123       default:
1124         g_warning (G_STRLOC ": Invalid GIOFileMode %s.\n", mode);
1125         return NULL;
1126     }
1127
1128   switch (mode_num)
1129     {
1130       case MODE_R:
1131         flags = O_RDONLY;
1132         pmode = _S_IREAD;
1133         break;
1134       case MODE_W:
1135         flags = O_WRONLY | O_TRUNC | O_CREAT;
1136         pmode = _S_IWRITE;
1137         break;
1138       case MODE_A:
1139         flags = O_WRONLY | O_APPEND | O_CREAT;
1140         pmode = _S_IWRITE;
1141         break;
1142       case MODE_R | MODE_PLUS:
1143         flags = O_RDWR;
1144         pmode = _S_IREAD | _S_IWRITE;
1145         break;
1146       case MODE_W | MODE_PLUS:
1147         flags = O_RDWR | O_TRUNC | O_CREAT;
1148         pmode = _S_IREAD | _S_IWRITE;
1149         break;
1150       case MODE_A | MODE_PLUS:
1151         flags = O_RDWR | O_APPEND | O_CREAT;
1152         pmode = _S_IREAD | _S_IWRITE;
1153         break;
1154       default:
1155         g_assert_not_reached ();
1156         flags = 0;
1157         pmode = 0;
1158     }
1159
1160
1161   fid = open (filename, flags, pmode);
1162   if (fid < 0)
1163     {
1164       g_set_error (error, G_FILE_ERROR,
1165                    g_file_error_from_errno (errno),
1166                    strerror (errno));
1167       return (GIOChannel *)NULL;
1168     }
1169
1170   channel = g_io_channel_win32_new_fd (fid);
1171
1172   /* XXX: move this to g_io_channel_win32_new_fd () */
1173   channel->close_on_unref = TRUE;
1174   channel->is_seekable = TRUE;
1175
1176   switch (mode_num)
1177     {
1178       case MODE_R:
1179         channel->is_readable = TRUE;
1180         channel->is_writeable = FALSE;
1181         break;
1182       case MODE_W:
1183       case MODE_A:
1184         channel->is_readable = FALSE;
1185         channel->is_writeable = TRUE;
1186         break;
1187       case MODE_R | MODE_PLUS:
1188       case MODE_W | MODE_PLUS:
1189       case MODE_A | MODE_PLUS:
1190         channel->is_readable = TRUE;
1191         channel->is_writeable = TRUE;
1192         break;
1193       default:
1194         g_assert_not_reached ();
1195     }
1196
1197   if (((GIOWin32Channel *)channel)->debug)
1198     g_print ("g_io_channel_win32_new_file: fd = %ud\n", fid);
1199
1200   return channel;
1201 }
1202
1203 GIOStatus
1204 g_io_win32_set_flags (GIOChannel     *channel,
1205                       GIOFlags        flags,
1206                       GError        **err)
1207 {
1208   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1209
1210   g_set_error (err, 
1211                G_IO_CHANNEL_ERROR, 
1212                g_file_error_from_errno (EACCES), 
1213                _("Channel set flags unsupported"));
1214   return G_IO_STATUS_ERROR;
1215 }
1216
1217 GIOFlags
1218 g_io_win32_fd_get_flags (GIOChannel     *channel)
1219 {
1220   GIOFlags flags = 0;
1221   struct _stat st;
1222   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1223
1224   g_return_val_if_fail (win32_channel != NULL, 0);
1225   g_return_val_if_fail (win32_channel->type == G_IO_WIN32_FILE_DESC, 0);
1226
1227   if (0 == _fstat (win32_channel->fd, &st))
1228     {
1229        /* XXX: G_IO_FLAG_APPEND */
1230        /* XXX: G_IO_FLAG_NONBLOCK */
1231        if (st.st_mode & _S_IREAD)    flags |= G_IO_FLAG_IS_READABLE;
1232        if (st.st_mode & _S_IWRITE)   flags |= G_IO_FLAG_IS_WRITEABLE;
1233        /* XXX: */
1234        if (!(st.st_mode & _S_IFIFO)) flags |= G_IO_FLAG_IS_SEEKABLE;
1235     }
1236
1237   return flags;
1238 }
1239
1240 /*
1241  * Generic implementation, just translating createion flags
1242  */
1243 GIOFlags
1244 g_io_win32_get_flags (GIOChannel     *channel)
1245 {
1246   GIOFlags flags;
1247
1248   flags =   (channel->is_readable ? G_IO_FLAG_IS_READABLE : 0)
1249           | (channel->is_writeable ? G_IO_FLAG_IS_READABLE : 0)
1250           | (channel->is_seekable ? G_IO_FLAG_IS_SEEKABLE : 0);
1251
1252   return flags;
1253 }
1254
1255 static GIOFuncs win32_channel_msg_funcs = {
1256   g_io_win32_msg_read,
1257   g_io_win32_msg_write,
1258   g_io_win32_no_seek,
1259   g_io_win32_msg_close,
1260   g_io_win32_msg_create_watch,
1261   g_io_win32_free,
1262   g_io_win32_set_flags,
1263   g_io_win32_get_flags,
1264 };
1265
1266 static GIOFuncs win32_channel_fd_funcs = {
1267   g_io_win32_fd_read,
1268   g_io_win32_fd_write,
1269   g_io_win32_fd_seek,
1270   g_io_win32_fd_close,
1271   g_io_win32_fd_create_watch,
1272   g_io_win32_free,
1273   g_io_win32_set_flags,
1274   g_io_win32_fd_get_flags,
1275 };
1276
1277 static GIOFuncs win32_channel_sock_funcs = {
1278   g_io_win32_sock_read,
1279   g_io_win32_sock_write,
1280   g_io_win32_no_seek,
1281   g_io_win32_sock_close,
1282   g_io_win32_sock_create_watch,
1283   g_io_win32_free,
1284   g_io_win32_set_flags,
1285   g_io_win32_get_flags,
1286 };
1287
1288 GIOChannel *
1289 g_io_channel_win32_new_messages (guint hwnd)
1290 {
1291   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1292   GIOChannel *channel = (GIOChannel *)win32_channel;
1293
1294   g_io_channel_init (channel);
1295   g_io_channel_win32_init (win32_channel);
1296   if (win32_channel->debug)
1297     g_print ("g_io_channel_win32_new_messages: hwnd = %ud\n", hwnd);
1298   channel->funcs = &win32_channel_msg_funcs;
1299   win32_channel->type = G_IO_WIN32_WINDOWS_MESSAGES;
1300   win32_channel->hwnd = (HWND) hwnd;
1301
1302   /* XXX: check this. */
1303   channel->is_readable = IsWindow (win32_channel->hwnd);
1304   channel->is_writeable = IsWindow (win32_channel->hwnd);
1305
1306   channel->is_seekable = FALSE;
1307
1308   return channel;
1309 }
1310
1311 GIOChannel *
1312 g_io_channel_win32_new_fd (gint fd)
1313 {
1314   GIOWin32Channel *win32_channel;
1315   GIOChannel *channel;
1316   struct stat st;
1317
1318   if (fstat (fd, &st) == -1)
1319     {
1320       g_warning (G_STRLOC ": %d isn't a (emulated) file descriptor", fd);
1321       return NULL;
1322     }
1323
1324   win32_channel = g_new (GIOWin32Channel, 1);
1325   channel = (GIOChannel *)win32_channel;
1326
1327   g_io_channel_init (channel);
1328   g_io_channel_win32_init (win32_channel);
1329   if (win32_channel->debug)
1330     g_print ("g_io_channel_win32_new_fd: fd = %d\n", fd);
1331   channel->funcs = &win32_channel_fd_funcs;
1332   win32_channel->type = G_IO_WIN32_FILE_DESC;
1333   win32_channel->fd = fd;
1334
1335
1336   channel->is_readable  = !!(st.st_mode & _S_IREAD);
1337   channel->is_writeable = !!(st.st_mode & _S_IWRITE);
1338   /* XXX: pipes aren't seeakable, are they ? */
1339   channel->is_seekable = !(st.st_mode & _S_IFIFO);
1340
1341   return channel;
1342 }
1343
1344 gint
1345 g_io_channel_win32_get_fd (GIOChannel *channel)
1346 {
1347   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1348
1349   return win32_channel->fd;
1350 }
1351
1352 GIOChannel *
1353 g_io_channel_win32_new_socket (int socket)
1354 {
1355   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1356   GIOChannel *channel = (GIOChannel *)win32_channel;
1357
1358   g_io_channel_init (channel);
1359   g_io_channel_win32_init (win32_channel);
1360   if (win32_channel->debug)
1361     g_print ("g_io_channel_win32_new_socket: sockfd:%d\n", socket);
1362   channel->funcs = &win32_channel_sock_funcs;
1363   win32_channel->type = G_IO_WIN32_SOCKET;
1364   win32_channel->fd = socket;
1365
1366   /* XXX: check this */
1367   channel->is_readable = TRUE;
1368   channel->is_writeable = TRUE;
1369   channel->is_seekable = FALSE;
1370
1371   return channel;
1372 }
1373
1374 GIOChannel *
1375 g_io_channel_unix_new (gint fd)
1376 {
1377   struct stat st;
1378
1379   if (fstat (fd, &st) == 0)
1380     return g_io_channel_win32_new_fd (fd);
1381   
1382   if (getsockopt (fd, SOL_SOCKET, SO_TYPE, NULL, NULL) != SO_ERROR)
1383     return g_io_channel_win32_new_socket(fd);
1384
1385   g_warning (G_STRLOC ": %d is neither a file descriptor or a socket", fd);
1386   return NULL;
1387 }
1388
1389 gint
1390 g_io_channel_unix_get_fd (GIOChannel *channel)
1391 {
1392   return g_io_channel_win32_get_fd (channel);
1393 }
1394
1395 void
1396 g_io_channel_win32_set_debug (GIOChannel *channel,
1397                               gboolean    flag)
1398 {
1399   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1400
1401   win32_channel->debug = flag;
1402 }
1403
1404 gint
1405 g_io_channel_win32_poll (GPollFD *fds,
1406                          gint     n_fds,
1407                          gint     timeout)
1408 {
1409   int result;
1410
1411   g_return_val_if_fail (n_fds >= 0, 0);
1412
1413   result = (*g_main_context_get_poll_func (NULL)) (fds, n_fds, timeout);
1414
1415   return result;
1416 }
1417
1418 void
1419 g_io_channel_win32_make_pollfd (GIOChannel   *channel,
1420                                 GIOCondition  condition,
1421                                 GPollFD      *fd)
1422 {
1423   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1424
1425   if (win32_channel->data_avail_event == NULL)
1426     create_events (win32_channel);
1427   
1428   fd->fd = (gint) win32_channel->data_avail_event;
1429   fd->events = condition;
1430
1431   if (win32_channel->thread_id == 0)
1432     if ((condition & G_IO_IN) && win32_channel->type == G_IO_WIN32_FILE_DESC)
1433       create_thread (win32_channel, condition, read_thread);
1434     else if (win32_channel->type == G_IO_WIN32_SOCKET)
1435       create_thread (win32_channel, condition, select_thread);
1436 }
1437
1438 /* Binary compatibility */
1439 GIOChannel *
1440 g_io_channel_win32_new_stream_socket (int socket)
1441 {
1442   return g_io_channel_win32_new_socket (socket);
1443 }