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