Coding style cleanups and doc improvements. (#491979, Areg Beketovski)
[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-2003 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 #include "config.h"
33
34 #include "glib.h"
35
36 #include <stdlib.h>
37 #include <winsock2.h>
38 #include <windows.h>
39 #include <conio.h>
40 #include <fcntl.h>
41 #include <io.h>
42 #include <process.h>
43 #include <errno.h>
44 #include <sys/stat.h>
45
46 #include "gstdio.h"
47 #include "glibintl.h"
48
49 #include "galias.h"
50
51 typedef struct _GIOWin32Channel GIOWin32Channel;
52 typedef struct _GIOWin32Watch GIOWin32Watch;
53
54 #define BUFFER_SIZE 4096
55
56 typedef enum {
57   G_IO_WIN32_WINDOWS_MESSAGES,  /* Windows messages */
58   G_IO_WIN32_FILE_DESC,         /* Unix-like file descriptors from
59                                  * _open() or _pipe(), except for console IO.
60                                  * Have to create separate thread to read.
61                                  */
62   G_IO_WIN32_CONSOLE,           /* Console IO (usually stdin, stdout, stderr) */
63   G_IO_WIN32_SOCKET             /* Sockets. No separate thread */
64 } GIOWin32ChannelType;
65
66 struct _GIOWin32Channel {
67   GIOChannel channel;
68   gint fd;                      /* Either a Unix-like file handle as provided
69                                  * by the Microsoft C runtime, or a SOCKET
70                                  * as provided by WinSock.
71                                  */
72   GIOWin32ChannelType type;
73   
74   gboolean debug;
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 fd channels. */
80   CRITICAL_SECTION mutex;
81
82   int direction;                /* 0 means we read from it,
83                                  * 1 means we write to it.
84                                  */
85
86   gboolean running;             /* Is reader thread running. FALSE if
87                                  * EOF has been reached.
88                                  */
89   gboolean needs_close;         /* If the channel has been closed while
90                                  * the reader thread was still running.
91                                  */
92   guint thread_id;              /* If non-NULL has a reader thread, or has
93                                  * had.*/
94   HANDLE data_avail_event;
95
96   gushort revents;
97
98   /* Following fields used by fd channels for input */
99   
100   /* Data is kept in a circular buffer. To be able to distinguish between
101    * empty and full buffer, we cannot fill it completely, but have to
102    * leave a one character gap.
103    *
104    * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
105    *
106    * Empty:    wrp == rdp
107    * Full:     (wrp + 1) % BUFFER_SIZE == rdp
108    * Partial:  otherwise
109    */
110   guchar *buffer;               /* (Circular) buffer */
111   gint wrp, rdp;                /* Buffer indices for writing and reading */
112   HANDLE space_avail_event;
113
114   /* Following fields used by socket channels */
115   int event_mask;
116   int last_events;
117   int event;
118   gboolean write_would_have_blocked;
119 };
120
121 #define LOCK(mutex) EnterCriticalSection (&mutex)
122 #define UNLOCK(mutex) LeaveCriticalSection (&mutex)
123
124 struct _GIOWin32Watch {
125   GSource       source;
126   GPollFD       pollfd;
127   GIOChannel   *channel;
128   GIOCondition  condition;
129 };
130
131 static void
132 g_win32_print_access_mode (int flags)
133 {
134   g_print ("%s%s%s%s%s%s%s%s%s%s",
135            ((flags & 0x3) == _O_RDWR ? "O_RDWR" :
136             ((flags & 0x3) == _O_RDONLY ? "O_RDONLY" :
137              ((flags & 0x3) == _O_WRONLY ? "O_WRONLY" : "0"))),
138            (flags & _O_APPEND ? "|O_APPEND" : ""),
139            (flags & _O_RANDOM ? "|O_RANDOM" : ""),
140            (flags & _O_SEQUENTIAL ? "|O_SEQUENTIAL" : ""),
141            (flags & _O_TEMPORARY ? "|O_TEMPORARY" : ""),
142            (flags & _O_CREAT ? "|O_CREAT" : ""),
143            (flags & _O_TRUNC ? "|O_TRUNC" : ""),
144            (flags & _O_EXCL ? "|O_EXCL" : ""),
145            (flags & _O_TEXT ? "|O_TEXT" : ""),
146            (flags & _O_BINARY ? "|O_BINARY" : ""));
147 }
148
149 static void
150 g_win32_print_gioflags (GIOFlags flags)
151 {
152   char *bar = "";
153
154   if (flags & G_IO_FLAG_APPEND)
155     bar = "|", g_print ("APPEND");
156   if (flags & G_IO_FLAG_NONBLOCK)
157     g_print ("%sNONBLOCK", bar), bar = "|";
158   if (flags & G_IO_FLAG_IS_READABLE)
159     g_print ("%sREADABLE", bar), bar = "|";
160   if (flags & G_IO_FLAG_IS_WRITEABLE)
161     g_print ("%sWRITEABLE", bar), bar = "|";
162   if (flags & G_IO_FLAG_IS_SEEKABLE)
163     g_print ("%sSEEKABLE", bar), bar = "|";
164 }
165
166 static const char *
167 event_mask_to_string (int mask)
168 {
169   char buf[100];
170   int checked_bits = 0;
171   char *bufp = buf;
172
173   if (mask == 0)
174     return "";
175
176 #define BIT(n) checked_bits |= FD_##n; if (mask & FD_##n) bufp += sprintf (bufp, "%s" #n, (bufp>buf ? "|" : ""))
177
178   BIT (READ);
179   BIT (WRITE);
180   BIT (OOB);
181   BIT (ACCEPT);
182   BIT (CONNECT);
183   BIT (CLOSE);
184   BIT (QOS);
185   BIT (GROUP_QOS);
186   BIT (ROUTING_INTERFACE_CHANGE);
187   BIT (ADDRESS_LIST_CHANGE);
188   
189 #undef BIT
190
191   if ((mask & ~checked_bits) != 0)
192           bufp += sprintf (bufp, "|%#x", mask & ~checked_bits);
193   
194   return g_quark_to_string (g_quark_from_string (buf));
195 }
196
197 static const char *
198 condition_to_string (GIOCondition condition)
199 {
200   char buf[100];
201   int checked_bits = 0;
202   char *bufp = buf;
203
204   if (condition == 0)
205     return "";
206
207 #define BIT(n) checked_bits |= G_IO_##n; if (condition & G_IO_##n) bufp += sprintf (bufp, "%s" #n, (bufp>buf ? "|" : ""))
208
209   BIT (IN);
210   BIT (OUT);
211   BIT (PRI);
212   BIT (ERR);
213   BIT (HUP);
214   BIT (NVAL);
215   
216 #undef BIT
217
218   if ((condition & ~checked_bits) != 0)
219           bufp += sprintf (bufp, "|%#x", condition & ~checked_bits);
220   
221   return g_quark_to_string (g_quark_from_string (buf));
222 }
223
224 static gboolean
225 g_io_win32_get_debug_flag (void)
226 {
227   return (getenv ("G_IO_WIN32_DEBUG") != NULL);
228 }
229
230 static char *
231 winsock_error_message (int number)
232 {
233   static char unk[100];
234
235   switch (number) {
236   case WSAEINTR:
237     return "Interrupted function call";
238   case WSAEACCES:
239     return "Permission denied";
240   case WSAEFAULT:
241     return "Bad address";
242   case WSAEINVAL:
243     return "Invalid argument";
244   case WSAEMFILE:
245     return "Too many open sockets";
246   case WSAEWOULDBLOCK:
247     return "Resource temporarily unavailable";
248   case WSAEINPROGRESS:
249     return "Operation now in progress";
250   case WSAEALREADY:
251     return "Operation already in progress";
252   case WSAENOTSOCK:
253     return "Socket operation on nonsocket";
254   case WSAEDESTADDRREQ:
255     return "Destination address required";
256   case WSAEMSGSIZE:
257     return "Message too long";
258   case WSAEPROTOTYPE:
259     return "Protocol wrong type for socket";
260   case WSAENOPROTOOPT:
261     return "Bad protocol option";
262   case WSAEPROTONOSUPPORT:
263     return "Protocol not supported";
264   case WSAESOCKTNOSUPPORT:
265     return "Socket type not supported";
266   case WSAEOPNOTSUPP:
267     return "Operation not supported on transport endpoint";
268   case WSAEPFNOSUPPORT:
269     return "Protocol family not supported";
270   case WSAEAFNOSUPPORT:
271     return "Address family not supported by protocol family";
272   case WSAEADDRINUSE:
273     return "Address already in use";
274   case WSAEADDRNOTAVAIL:
275     return "Address not available";
276   case WSAENETDOWN:
277     return "Network interface is not configured";
278   case WSAENETUNREACH:
279     return "Network is unreachable";
280   case WSAENETRESET:
281     return "Network dropped connection on reset";
282   case WSAECONNABORTED:
283     return "Software caused connection abort";
284   case WSAECONNRESET:
285     return "Connection reset by peer";
286   case WSAENOBUFS:
287     return "No buffer space available";
288   case WSAEISCONN:
289     return "Socket is already connected";
290   case WSAENOTCONN:
291     return "Socket is not connected";
292   case WSAESHUTDOWN:
293     return "Can't send after socket shutdown";
294   case WSAETIMEDOUT:
295     return "Connection timed out";
296   case WSAECONNREFUSED:
297     return "Connection refused";
298   case WSAEHOSTDOWN:
299     return "Host is down";
300   case WSAEHOSTUNREACH:
301     return "Host is unreachable";
302   case WSAEPROCLIM:
303     return "Too many processes";
304   case WSASYSNOTREADY:
305     return "Network subsystem is unavailable";
306   case WSAVERNOTSUPPORTED:
307     return "Winsock.dll version out of range";
308   case WSANOTINITIALISED:
309     return "Successful WSAStartup not yet performed";
310   case WSAEDISCON:
311     return "Graceful shutdown in progress";
312   case WSATYPE_NOT_FOUND:
313     return "Class type not found";
314   case WSAHOST_NOT_FOUND:
315     return "Host not found";
316   case WSATRY_AGAIN:
317     return "Nonauthoritative host not found";
318   case WSANO_RECOVERY:
319     return "This is a nonrecoverable error";
320   case WSANO_DATA:
321     return "Valid name, no data record of requested type";
322   case WSA_INVALID_HANDLE:
323     return "Specified event object handle is invalid";
324   case WSA_INVALID_PARAMETER:
325     return "One or more parameters are invalid";
326   case WSA_IO_INCOMPLETE:
327     return "Overlapped I/O event object not in signaled state";
328   case WSA_NOT_ENOUGH_MEMORY:
329     return "Insufficient memory available";
330   case WSA_OPERATION_ABORTED:
331     return "Overlapped operation aborted";
332   case WSAEINVALIDPROCTABLE:
333     return "Invalid procedure table from service provider";
334   case WSAEINVALIDPROVIDER:
335     return "Invalid service provider version number";
336   case WSAEPROVIDERFAILEDINIT:
337     return "Unable to initialize a service provider";
338   case WSASYSCALLFAILURE:
339     return "System call failure";
340   default:
341     sprintf (unk, "Unknown WinSock error %d", number);
342     return unk;
343   }
344 }
345
346 static void
347 g_io_channel_win32_init (GIOWin32Channel *channel)
348 {
349   channel->debug = g_io_win32_get_debug_flag ();
350   channel->buffer = NULL;
351   channel->running = FALSE;
352   channel->needs_close = FALSE;
353   channel->thread_id = 0;
354   channel->data_avail_event = NULL;
355   channel->revents = 0;
356   channel->space_avail_event = NULL;
357   channel->event_mask = 0;
358   channel->last_events = 0;
359   channel->event = 0;
360   channel->write_would_have_blocked = FALSE;
361   InitializeCriticalSection (&channel->mutex);
362 }
363
364 static void
365 create_events (GIOWin32Channel *channel)
366 {
367   SECURITY_ATTRIBUTES sec_attrs;
368   
369   sec_attrs.nLength = sizeof (SECURITY_ATTRIBUTES);
370   sec_attrs.lpSecurityDescriptor = NULL;
371   sec_attrs.bInheritHandle = FALSE;
372
373   /* The data available event is manual reset, the space available event
374    * is automatic reset.
375    */
376   if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
377       || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
378     {
379       gchar *emsg = g_win32_error_message (GetLastError ());
380       g_error ("Error creating event: %s", emsg);
381       g_free (emsg);
382     }
383 }
384
385 static unsigned __stdcall
386 read_thread (void *parameter)
387 {
388   GIOWin32Channel *channel = parameter;
389   guchar *buffer;
390   guint nbytes;
391
392   g_io_channel_ref ((GIOChannel *)channel);
393
394   if (channel->debug)
395     g_print ("read_thread %#x: start fd=%d, data_avail=%#x space_avail=%#x\n",
396              channel->thread_id,
397              channel->fd,
398              (guint) channel->data_avail_event,
399              (guint) channel->space_avail_event);
400
401   channel->direction = 0;
402   channel->buffer = g_malloc (BUFFER_SIZE);
403   channel->rdp = channel->wrp = 0;
404   channel->running = TRUE;
405
406   SetEvent (channel->space_avail_event);
407   
408   LOCK (channel->mutex);
409   while (channel->running)
410     {
411       if (channel->debug)
412         g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
413                  channel->thread_id, channel->rdp, channel->wrp);
414       if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
415         {
416           /* Buffer is full */
417           if (channel->debug)
418             g_print ("read_thread %#x: resetting space_avail\n",
419                      channel->thread_id);
420           ResetEvent (channel->space_avail_event);
421           if (channel->debug)
422             g_print ("read_thread %#x: waiting for space\n",
423                      channel->thread_id);
424           UNLOCK (channel->mutex);
425           WaitForSingleObject (channel->space_avail_event, INFINITE);
426           LOCK (channel->mutex);
427           if (channel->debug)
428             g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
429                      channel->thread_id, channel->rdp, channel->wrp);
430         }
431       
432       buffer = channel->buffer + channel->wrp;
433       
434       /* Always leave at least one byte unused gap to be able to
435        * distinguish between the full and empty condition...
436        */
437       nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
438                     BUFFER_SIZE - channel->wrp);
439
440       if (channel->debug)
441         g_print ("read_thread %#x: calling read() for %d bytes\n",
442                  channel->thread_id, nbytes);
443
444       UNLOCK (channel->mutex);
445
446       nbytes = read (channel->fd, buffer, nbytes);
447       
448       LOCK (channel->mutex);
449
450       channel->revents = G_IO_IN;
451       if (nbytes == 0)
452         channel->revents |= G_IO_HUP;
453       else if (nbytes < 0)
454         channel->revents |= G_IO_ERR;
455
456       if (channel->debug)
457         g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
458                  channel->thread_id, nbytes, channel->rdp, channel->wrp);
459
460       if (nbytes <= 0)
461         break;
462
463       channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
464       if (channel->debug)
465         g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
466                  channel->thread_id, channel->rdp, channel->wrp);
467       SetEvent (channel->data_avail_event);
468     }
469   
470   channel->running = FALSE;
471   if (channel->needs_close)
472     {
473       if (channel->debug)
474         g_print ("read_thread %#x: channel fd %d needs closing\n",
475                  channel->thread_id, channel->fd);
476       close (channel->fd);
477       channel->fd = -1;
478     }
479
480   if (channel->debug)
481     g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
482              channel->thread_id, channel->rdp, channel->wrp);
483   SetEvent (channel->data_avail_event);
484   UNLOCK (channel->mutex);
485   
486   g_io_channel_unref ((GIOChannel *)channel);
487   
488   /* No need to call _endthreadex(), the actual thread starter routine
489    * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
490    * _endthreadex() for us.
491    */
492
493   return 0;
494 }
495
496 static unsigned __stdcall
497 write_thread (void *parameter)
498 {
499   GIOWin32Channel *channel = parameter;
500   guchar *buffer;
501   guint nbytes;
502
503   g_io_channel_ref ((GIOChannel *)channel);
504
505   if (channel->debug)
506     g_print ("write_thread %#x: start fd=%d, data_avail=%#x space_avail=%#x\n",
507              channel->thread_id,
508              channel->fd,
509              (guint) channel->data_avail_event,
510              (guint) channel->space_avail_event);
511   
512   channel->direction = 1;
513   channel->buffer = g_malloc (BUFFER_SIZE);
514   channel->rdp = channel->wrp = 0;
515   channel->running = TRUE;
516
517   SetEvent (channel->space_avail_event);
518
519   /* We use the same event objects as for a reader thread, but with
520    * reversed meaning. So, space_avail is used if data is available
521    * for writing, and data_avail is used if space is available in the
522    * write buffer.
523    */
524
525   LOCK (channel->mutex);
526   while (channel->running || channel->rdp != channel->wrp)
527     {
528       if (channel->debug)
529         g_print ("write_thread %#x: rdp=%d, wrp=%d\n",
530                  channel->thread_id, channel->rdp, channel->wrp);
531       if (channel->wrp == channel->rdp)
532         {
533           /* Buffer is empty. */
534           if (channel->debug)
535             g_print ("write_thread %#x: resetting space_avail\n",
536                      channel->thread_id);
537           ResetEvent (channel->space_avail_event);
538           if (channel->debug)
539             g_print ("write_thread %#x: waiting for data\n",
540                      channel->thread_id);
541           channel->revents = G_IO_OUT;
542           SetEvent (channel->data_avail_event);
543           UNLOCK (channel->mutex);
544           WaitForSingleObject (channel->space_avail_event, INFINITE);
545
546           LOCK (channel->mutex);
547           if (channel->rdp == channel->wrp)
548             break;
549
550           if (channel->debug)
551             g_print ("write_thread %#x: rdp=%d, wrp=%d\n",
552                      channel->thread_id, channel->rdp, channel->wrp);
553         }
554       
555       buffer = channel->buffer + channel->rdp;
556       if (channel->rdp < channel->wrp)
557         nbytes = channel->wrp - channel->rdp;
558       else
559         nbytes = BUFFER_SIZE - channel->rdp;
560
561       if (channel->debug)
562         g_print ("write_thread %#x: calling write() for %d bytes\n",
563                  channel->thread_id, nbytes);
564
565       UNLOCK (channel->mutex);
566       nbytes = write (channel->fd, buffer, nbytes);
567       LOCK (channel->mutex);
568
569       if (channel->debug)
570         g_print ("write_thread %#x: write(%i) returned %d, rdp=%d, wrp=%d\n",
571                  channel->thread_id, channel->fd, nbytes, channel->rdp, channel->wrp);
572
573       channel->revents = 0;
574       if (nbytes > 0)
575         channel->revents |= G_IO_OUT;
576       else if (nbytes <= 0)
577         channel->revents |= G_IO_ERR;
578
579       channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
580
581       if (nbytes <= 0)
582         break;
583
584       if (channel->debug)
585         g_print ("write_thread: setting data_avail for thread %#x\n",
586                  channel->thread_id);
587       SetEvent (channel->data_avail_event);
588     }
589   
590   channel->running = FALSE;
591   if (channel->needs_close)
592     {
593       if (channel->debug)
594         g_print ("write_thread %#x: channel fd %d needs closing\n",
595                  channel->thread_id, channel->fd);
596       close (channel->fd);
597       channel->fd = -1;
598     }
599
600   UNLOCK (channel->mutex);
601   
602   g_io_channel_unref ((GIOChannel *)channel);
603   
604   return 0;
605 }
606
607 static void
608 create_thread (GIOWin32Channel     *channel,
609                GIOCondition         condition,
610                unsigned (__stdcall *thread) (void *parameter))
611 {
612   HANDLE thread_handle;
613
614   thread_handle = (HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
615                                            &channel->thread_id);
616   if (thread_handle == 0)
617     g_warning (G_STRLOC ": Error creating reader thread: %s",
618                g_strerror (errno));
619   else if (!CloseHandle (thread_handle))
620     g_warning (G_STRLOC ": Error closing thread handle: %s\n",
621                g_win32_error_message (GetLastError ()));
622
623   WaitForSingleObject (channel->space_avail_event, INFINITE);
624 }
625
626 static GIOStatus
627 buffer_read (GIOWin32Channel *channel,
628              guchar          *dest,
629              gsize            count,
630              gsize           *bytes_read,
631              GError         **err)
632 {
633   guint nbytes;
634   guint left = count;
635   
636   LOCK (channel->mutex);
637   if (channel->debug)
638     g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
639              channel->thread_id, count, channel->rdp, channel->wrp);
640   
641   if (channel->wrp == channel->rdp)
642     {
643       UNLOCK (channel->mutex);
644       if (channel->debug)
645         g_print ("waiting for data from thread %#x\n", channel->thread_id);
646       WaitForSingleObject (channel->data_avail_event, INFINITE);
647       if (channel->debug)
648         g_print ("done waiting for data from thread %#x\n", channel->thread_id);
649       LOCK (channel->mutex);
650       if (channel->wrp == channel->rdp && !channel->running)
651         {
652           if (channel->debug)
653             g_print ("wrp==rdp, !running\n");
654           UNLOCK (channel->mutex);
655           *bytes_read = 0;
656           return G_IO_STATUS_EOF;
657         }
658     }
659   
660   if (channel->rdp < channel->wrp)
661     nbytes = channel->wrp - channel->rdp;
662   else
663     nbytes = BUFFER_SIZE - channel->rdp;
664   UNLOCK (channel->mutex);
665   nbytes = MIN (left, nbytes);
666   if (channel->debug)
667     g_print ("moving %d bytes from thread %#x\n",
668              nbytes, channel->thread_id);
669   memcpy (dest, channel->buffer + channel->rdp, nbytes);
670   dest += nbytes;
671   left -= nbytes;
672   LOCK (channel->mutex);
673   channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
674   if (channel->debug)
675     g_print ("setting space_avail for thread %#x\n", channel->thread_id);
676   SetEvent (channel->space_avail_event);
677   if (channel->debug)
678     g_print ("for thread %#x: rdp=%d, wrp=%d\n",
679              channel->thread_id, channel->rdp, channel->wrp);
680   if (channel->running && channel->wrp == channel->rdp)
681     {
682       if (channel->debug)
683         g_print ("resetting data_avail of thread %#x\n",
684                  channel->thread_id);
685       ResetEvent (channel->data_avail_event);
686     };
687   UNLOCK (channel->mutex);
688   
689   /* We have no way to indicate any errors form the actual
690    * read() or recv() call in the reader thread. Should we have?
691    */
692   *bytes_read = count - left;
693   return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
694 }
695
696
697 static GIOStatus
698 buffer_write (GIOWin32Channel *channel,
699               const guchar    *dest,
700               gsize            count,
701               gsize           *bytes_written,
702               GError         **err)
703 {
704   guint nbytes;
705   guint left = count;
706   
707   LOCK (channel->mutex);
708   if (channel->debug)
709     g_print ("buffer_write: writing to thread %#x %d bytes, rdp=%d, wrp=%d\n",
710              channel->thread_id, count, channel->rdp, channel->wrp);
711   
712   if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
713     {
714       /* Buffer is full */
715       if (channel->debug)
716         g_print ("buffer_write: tid %#x: resetting data_avail\n",
717                  channel->thread_id);
718       ResetEvent (channel->data_avail_event);
719       if (channel->debug)
720         g_print ("buffer_write: tid %#x: waiting for space\n",
721                  channel->thread_id);
722       UNLOCK (channel->mutex);
723       WaitForSingleObject (channel->data_avail_event, INFINITE);
724       LOCK (channel->mutex);
725       if (channel->debug)
726         g_print ("buffer_write: tid %#x: rdp=%d, wrp=%d\n",
727                  channel->thread_id, channel->rdp, channel->wrp);
728     }
729    
730   nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
731                 BUFFER_SIZE - channel->wrp);
732
733   UNLOCK (channel->mutex);
734   nbytes = MIN (left, nbytes);
735   if (channel->debug)
736     g_print ("buffer_write: tid %#x: writing %d bytes\n",
737              channel->thread_id, nbytes);
738   memcpy (channel->buffer + channel->wrp, dest, nbytes);
739   dest += nbytes;
740   left -= nbytes;
741   LOCK (channel->mutex);
742
743   channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
744   if (channel->debug)
745     g_print ("buffer_write: tid %#x: rdp=%d, wrp=%d, setting space_avail\n",
746              channel->thread_id, channel->rdp, channel->wrp);
747   SetEvent (channel->space_avail_event);
748
749   if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
750     {
751       /* Buffer is full */
752       if (channel->debug)
753         g_print ("buffer_write: tid %#x: resetting data_avail\n",
754                  channel->thread_id);
755       ResetEvent (channel->data_avail_event);
756     }
757
758   UNLOCK (channel->mutex);
759   
760   /* We have no way to indicate any errors form the actual
761    * write() call in the writer thread. Should we have?
762    */
763   *bytes_written = count - left;
764   return (*bytes_written > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
765 }
766
767
768 static gboolean
769 g_io_win32_prepare (GSource *source,
770                     gint    *timeout)
771 {
772   GIOWin32Watch *watch = (GIOWin32Watch *)source;
773   GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
774   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
775   int event_mask;
776   
777   *timeout = -1;
778   
779   switch (channel->type)
780     {
781     case G_IO_WIN32_WINDOWS_MESSAGES:
782     case G_IO_WIN32_CONSOLE:
783       break;
784
785     case G_IO_WIN32_FILE_DESC:
786       if (channel->debug)
787         g_print ("g_io_win32_prepare: for thread %#x buffer_condition:{%s}\n"
788                  "  watch->pollfd.events:{%s} watch->pollfd.revents:{%s} channel->revents:{%s}\n",
789                  channel->thread_id, condition_to_string (buffer_condition),
790                  condition_to_string (watch->pollfd.events),
791                  condition_to_string (watch->pollfd.revents),
792                  condition_to_string (channel->revents));
793       
794       LOCK (channel->mutex);
795       if (channel->running)
796         {
797           if (channel->direction == 0 && channel->wrp == channel->rdp)
798             {
799               if (channel->debug)
800                 g_print ("g_io_win32_prepare: for thread %#x, setting channel->revents = 0\n",
801                          channel->thread_id);
802               channel->revents = 0;
803             }
804         }
805       else
806         {
807           if (channel->direction == 1
808               && (channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
809             {
810               if (channel->debug)
811                 g_print ("g_io_win32_prepare: for thread %#x, setting channel->revents = %i\n",
812                          channel->thread_id, 0);
813               channel->revents = 0;
814             }
815         }         
816       UNLOCK (channel->mutex);
817       break;
818
819     case G_IO_WIN32_SOCKET:
820       event_mask = 0;
821       if (watch->condition & G_IO_IN)
822         event_mask |= (FD_READ | FD_ACCEPT);
823       if (watch->condition & G_IO_OUT)
824         event_mask |= (FD_WRITE | FD_CONNECT);
825       event_mask |= FD_CLOSE;
826
827       if (channel->event_mask != event_mask /* || channel->event != watch->pollfd.fd*/)
828         {
829           if (channel->debug)
830             g_print ("g_io_win32_prepare: WSAEventSelect(%d, %#x, {%s}\n",
831                      channel->fd, watch->pollfd.fd,
832                      event_mask_to_string (event_mask));
833           if (WSAEventSelect (channel->fd, (HANDLE) watch->pollfd.fd,
834                               event_mask) == SOCKET_ERROR)
835             ;                   /* What? */
836           channel->event_mask = event_mask;
837 #if 0
838           channel->event = watch->pollfd.fd;
839 #endif
840           channel->last_events = 0;
841         }
842       break;
843
844     default:
845       g_assert_not_reached ();
846       abort ();
847     }
848   return ((watch->condition & buffer_condition) == watch->condition);
849 }
850
851 static gboolean
852 g_io_win32_check (GSource *source)
853 {
854   MSG msg;
855   GIOWin32Watch *watch = (GIOWin32Watch *)source;
856   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
857   GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
858   WSANETWORKEVENTS events;
859
860   switch (channel->type)
861     {
862     case G_IO_WIN32_WINDOWS_MESSAGES:
863       return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE));
864
865     case G_IO_WIN32_FILE_DESC:
866       if (channel->debug)
867         g_print ("g_io_win32_check: for thread %#x buffer_condition=%s\n"
868                  "  watch->pollfd.events={%s} watch->pollfd.revents={%s} channel->revents={%s}\n",
869                  channel->thread_id, condition_to_string (buffer_condition),
870                  condition_to_string (watch->pollfd.events),
871                  condition_to_string (watch->pollfd.revents),
872                  condition_to_string (channel->revents));
873       
874       watch->pollfd.revents = (watch->pollfd.events & channel->revents);
875
876       return ((watch->pollfd.revents | buffer_condition) & watch->condition);
877
878     case G_IO_WIN32_CONSOLE:
879       if (watch->channel->is_writeable)
880         return TRUE;
881       else if (watch->channel->is_readable)
882         {
883           INPUT_RECORD buffer;
884           DWORD n;
885           if (PeekConsoleInput ((HANDLE) watch->pollfd.fd, &buffer, 1, &n) &&
886               n == 1)
887             {
888               /* _kbhit() does quite complex processing to find out
889                * whether at least one of the key events pending corresponds
890                * to a "real" character that can be read.
891                */
892               if (_kbhit ())
893                 return TRUE;
894               
895               /* Discard all other kinds of events */
896               ReadConsoleInput ((HANDLE) watch->pollfd.fd, &buffer, 1, &n);
897             }
898         }
899       return FALSE;
900
901     case G_IO_WIN32_SOCKET:
902       if (channel->last_events & FD_WRITE)
903         {
904           if (channel->debug)
905             g_print ("g_io_win32_check: sock=%d event=%#x last_events has FD_WRITE\n",
906                      channel->fd, watch->pollfd.fd);
907         }
908       else
909         {
910           WSAEnumNetworkEvents (channel->fd, 0, &events);
911
912           if (channel->debug)
913             g_print ("g_io_win32_check: WSAEnumNetworkEvents (%d, %#x) revents={%s} condition={%s} events={%s}\n",
914                      channel->fd, watch->pollfd.fd,
915                      condition_to_string (watch->pollfd.revents),
916                      condition_to_string (watch->condition),
917                      event_mask_to_string (events.lNetworkEvents));
918           
919           if (watch->pollfd.revents != 0 &&
920               events.lNetworkEvents == 0 &&
921               !(channel->event_mask & FD_WRITE))
922             {
923               channel->event_mask = 0;
924               if (channel->debug)
925                 g_print ("g_io_win32_check: WSAEventSelect(%d, %#x, {})\n",
926                          channel->fd, watch->pollfd.fd);
927               WSAEventSelect (channel->fd, (HANDLE) watch->pollfd.fd, 0);
928               if (channel->debug)
929                 g_print ("g_io_win32_check: ResetEvent(%#x)\n",
930                          watch->pollfd.fd);
931               ResetEvent ((HANDLE) watch->pollfd.fd);
932             }
933           channel->last_events = events.lNetworkEvents;
934         }
935       watch->pollfd.revents = 0;
936       if (channel->last_events & (FD_READ | FD_ACCEPT))
937         watch->pollfd.revents |= G_IO_IN;
938       if (channel->last_events & FD_WRITE)
939         watch->pollfd.revents |= G_IO_OUT;
940       else
941         {
942           /* We have called WSAEnumNetworkEvents() above but it didn't
943            * set FD_WRITE.
944            */
945           if (events.lNetworkEvents & FD_CONNECT)
946             {
947               if (events.iErrorCode[FD_CONNECT_BIT] == 0)
948                 watch->pollfd.revents |= G_IO_OUT;
949               else
950                 watch->pollfd.revents |= (G_IO_HUP | G_IO_ERR);
951             }
952           if (watch->pollfd.revents == 0 && (channel->last_events & (FD_CLOSE)))
953             watch->pollfd.revents |= G_IO_HUP;
954         }
955
956       /* Regardless of WSAEnumNetworkEvents() result, if watching for
957        * writability, unless last write would have blocked set
958        * G_IO_OUT. But never set both G_IO_OUT and G_IO_HUP.
959        */
960       if (!(watch->pollfd.revents & G_IO_HUP) &&
961           !channel->write_would_have_blocked &&
962           (channel->event_mask & FD_WRITE))
963         watch->pollfd.revents |= G_IO_OUT;
964
965       return ((watch->pollfd.revents | buffer_condition) & watch->condition);
966
967     default:
968       g_assert_not_reached ();
969       abort ();
970     }
971 }
972
973 static gboolean
974 g_io_win32_dispatch (GSource     *source,
975                      GSourceFunc  callback,
976                      gpointer     user_data)
977 {
978   GIOFunc func = (GIOFunc)callback;
979   GIOWin32Watch *watch = (GIOWin32Watch *)source;
980   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
981   GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
982   
983   if (!func)
984     {
985       g_warning (G_STRLOC ": GIOWin32Watch dispatched without callback\n"
986                  "You must call g_source_connect().");
987       return FALSE;
988     }
989   
990   if (channel->debug)
991     g_print ("g_io_win32_dispatch: pollfd.revents=%s condition=%s result=%s\n",
992              condition_to_string (watch->pollfd.revents),
993              condition_to_string (watch->condition),
994              condition_to_string ((watch->pollfd.revents | buffer_condition) & watch->condition));
995
996   return (*func) (watch->channel,
997                   (watch->pollfd.revents | buffer_condition) & watch->condition,
998                   user_data);
999 }
1000
1001 static void
1002 g_io_win32_finalize (GSource *source)
1003 {
1004   GIOWin32Watch *watch = (GIOWin32Watch *)source;
1005   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
1006   
1007   switch (channel->type)
1008     {
1009     case G_IO_WIN32_WINDOWS_MESSAGES:
1010     case G_IO_WIN32_CONSOLE:
1011       break;
1012
1013     case G_IO_WIN32_FILE_DESC:
1014       LOCK (channel->mutex);
1015       if (channel->debug)
1016         g_print ("g_io_win32_finalize: channel with thread %#x\n",
1017                  channel->thread_id);
1018       UNLOCK (channel->mutex);
1019       break;
1020
1021     case G_IO_WIN32_SOCKET:
1022       if (channel->debug)
1023         g_print ("g_io_win32_finalize: channel is for sock=%d\n", channel->fd);
1024 #if 0
1025       CloseHandle ((HANDLE) watch->pollfd.fd);
1026       channel->event = 0;
1027       channel->event_mask = 0;
1028 #endif
1029       break;
1030
1031     default:
1032       g_assert_not_reached ();
1033       abort ();
1034     }
1035   g_io_channel_unref (watch->channel);
1036 }
1037
1038 GSourceFuncs g_io_watch_funcs = {
1039   g_io_win32_prepare,
1040   g_io_win32_check,
1041   g_io_win32_dispatch,
1042   g_io_win32_finalize
1043 };
1044
1045 static GIOStatus
1046 g_io_win32_msg_read (GIOChannel *channel,
1047                      gchar      *buf,
1048                      gsize       count,
1049                      gsize      *bytes_read,
1050                      GError    **err)
1051 {
1052   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1053   MSG msg;               /* In case of alignment problems */
1054   
1055   if (count < sizeof (MSG))
1056     {
1057       g_set_error (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
1058                    "Incorrect message size"); /* Informative enough error message? */
1059       return G_IO_STATUS_ERROR;
1060     }
1061   
1062   if (win32_channel->debug)
1063     g_print ("g_io_win32_msg_read: for %#x\n",
1064              (guint) win32_channel->hwnd);
1065   if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
1066     return G_IO_STATUS_AGAIN;
1067
1068   memmove (buf, &msg, sizeof (MSG));
1069   *bytes_read = sizeof (MSG);
1070
1071   return G_IO_STATUS_NORMAL;
1072 }
1073
1074 static GIOStatus
1075 g_io_win32_msg_write (GIOChannel  *channel,
1076                       const gchar *buf,
1077                       gsize        count,
1078                       gsize       *bytes_written,
1079                       GError     **err)
1080 {
1081   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1082   MSG msg;
1083   
1084   if (count != sizeof (MSG))
1085     {
1086       g_set_error (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
1087                    "Incorrect message size"); /* Informative enough error message? */
1088       return G_IO_STATUS_ERROR;
1089     }
1090   
1091   /* In case of alignment problems */
1092   memmove (&msg, buf, sizeof (MSG));
1093   if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
1094     {
1095       gchar *emsg = g_win32_error_message (GetLastError ());
1096       g_set_error (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED, emsg);
1097       g_free (emsg);
1098       return G_IO_STATUS_ERROR;
1099     }
1100
1101   *bytes_written = sizeof (MSG);
1102
1103   return G_IO_STATUS_NORMAL;
1104 }
1105
1106 static GIOStatus
1107 g_io_win32_msg_close (GIOChannel *channel,
1108                       GError    **err)
1109 {
1110   /* Nothing to be done. Or should we set hwnd to some invalid value? */
1111
1112   return G_IO_STATUS_NORMAL;
1113 }
1114
1115 static void
1116 g_io_win32_free (GIOChannel *channel)
1117 {
1118   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1119   
1120   if (win32_channel->debug)
1121     g_print ("g_io_win32_free channel fd=%d\n", win32_channel->fd);
1122
1123   if (win32_channel->data_avail_event)
1124     CloseHandle (win32_channel->data_avail_event);
1125   if (win32_channel->space_avail_event)
1126     CloseHandle (win32_channel->space_avail_event);
1127   if (win32_channel->type == G_IO_WIN32_SOCKET)
1128     WSAEventSelect (win32_channel->fd, NULL, 0);
1129   DeleteCriticalSection (&win32_channel->mutex);
1130
1131   g_free (win32_channel->buffer);
1132   g_free (win32_channel);
1133 }
1134
1135 static GSource *
1136 g_io_win32_msg_create_watch (GIOChannel   *channel,
1137                              GIOCondition  condition)
1138 {
1139   GIOWin32Watch *watch;
1140   GSource *source;
1141
1142   source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
1143   watch = (GIOWin32Watch *)source;
1144   
1145   watch->channel = channel;
1146   g_io_channel_ref (channel);
1147   
1148   watch->condition = condition;
1149   
1150   watch->pollfd.fd = G_WIN32_MSG_HANDLE;
1151   watch->pollfd.events = condition;
1152   
1153   g_source_add_poll (source, &watch->pollfd);
1154   
1155   return source;
1156 }
1157
1158 static GIOStatus
1159 g_io_win32_fd_and_console_read (GIOChannel *channel,
1160                                 gchar      *buf,
1161                                 gsize       count,
1162                                 gsize      *bytes_read,
1163                                 GError    **err)
1164 {
1165   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1166   gint result;
1167   
1168   if (win32_channel->debug)
1169     g_print ("g_io_win32_fd_read: fd=%d count=%d\n",
1170              win32_channel->fd, count);
1171   
1172   if (win32_channel->thread_id)
1173     {
1174       return buffer_read (win32_channel, buf, count, bytes_read, err);
1175     }
1176
1177   result = read (win32_channel->fd, buf, count);
1178
1179   if (win32_channel->debug)
1180     g_print ("g_io_win32_fd_read: read() => %d\n", result);
1181
1182   if (result < 0)
1183     {
1184       *bytes_read = 0;
1185
1186       switch (errno)
1187         {
1188 #ifdef EAGAIN
1189         case EAGAIN:
1190           return G_IO_STATUS_AGAIN;
1191 #endif
1192         default:
1193           g_set_error (err, G_IO_CHANNEL_ERROR,
1194                        g_io_channel_error_from_errno (errno),
1195                        g_strerror (errno));
1196           return G_IO_STATUS_ERROR;
1197         }
1198     }
1199
1200   *bytes_read = result;
1201
1202   return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
1203 }
1204
1205 static GIOStatus
1206 g_io_win32_fd_and_console_write (GIOChannel  *channel,
1207                                  const gchar *buf,
1208                                  gsize        count,
1209                                  gsize       *bytes_written,
1210                                  GError     **err)
1211 {
1212   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1213   gint result;
1214
1215   if (win32_channel->thread_id)
1216     {
1217       return buffer_write (win32_channel, buf, count, bytes_written, err);
1218     }
1219   
1220   result = write (win32_channel->fd, buf, count);
1221   if (win32_channel->debug)
1222     g_print ("g_io_win32_fd_write: fd=%d count=%d => %d\n",
1223              win32_channel->fd, count, result);
1224
1225   if (result < 0)
1226     {
1227       *bytes_written = 0;
1228
1229       switch (errno)
1230         {
1231 #ifdef EAGAIN
1232         case EAGAIN:
1233           return G_IO_STATUS_AGAIN;
1234 #endif
1235         default:
1236           g_set_error (err, G_IO_CHANNEL_ERROR,
1237                        g_io_channel_error_from_errno (errno),
1238                        g_strerror (errno));
1239           return G_IO_STATUS_ERROR;
1240         }
1241     }
1242
1243   *bytes_written = result;
1244
1245   return G_IO_STATUS_NORMAL;
1246 }
1247
1248 static GIOStatus
1249 g_io_win32_fd_seek (GIOChannel *channel,
1250                     gint64      offset,
1251                     GSeekType   type,
1252                     GError    **err)
1253 {
1254   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1255   int whence;
1256   off_t tmp_offset;
1257   off_t result;
1258   
1259   switch (type)
1260     {
1261     case G_SEEK_SET:
1262       whence = SEEK_SET;
1263       break;
1264     case G_SEEK_CUR:
1265       whence = SEEK_CUR;
1266       break;
1267     case G_SEEK_END:
1268       whence = SEEK_END;
1269       break;
1270     default:
1271       whence = -1; /* Keep the compiler quiet */
1272       g_assert_not_reached ();
1273       abort ();
1274     }
1275
1276   tmp_offset = offset;
1277   if (tmp_offset != offset)
1278     {
1279       g_set_error (err, G_IO_CHANNEL_ERROR,
1280                    g_io_channel_error_from_errno (EINVAL),
1281                    g_strerror (EINVAL));
1282       return G_IO_STATUS_ERROR;
1283     }
1284   
1285   result = lseek (win32_channel->fd, tmp_offset, whence);
1286   
1287   if (result < 0)
1288     {
1289       g_set_error (err, G_IO_CHANNEL_ERROR,
1290                    g_io_channel_error_from_errno (errno),
1291                    g_strerror (errno));
1292       return G_IO_STATUS_ERROR;
1293     }
1294
1295   return G_IO_STATUS_NORMAL;
1296 }
1297
1298 static GIOStatus
1299 g_io_win32_fd_close (GIOChannel *channel,
1300                      GError    **err)
1301 {
1302   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1303   
1304   if (win32_channel->debug)
1305     g_print ("thread %#x: closing fd %d\n",
1306              win32_channel->thread_id,
1307              win32_channel->fd);
1308   LOCK (win32_channel->mutex);
1309   if (win32_channel->running)
1310     {
1311       if (win32_channel->debug)
1312         g_print ("thread %#x: running, marking fd %d for later close\n",
1313                  win32_channel->thread_id, win32_channel->fd);
1314       win32_channel->running = FALSE;
1315       win32_channel->needs_close = TRUE;
1316       if (win32_channel->direction == 0)
1317         SetEvent (win32_channel->data_avail_event);
1318       else
1319         SetEvent (win32_channel->space_avail_event);
1320     }
1321   else
1322     {
1323       if (win32_channel->debug)
1324         g_print ("closing fd %d\n", win32_channel->fd);
1325       close (win32_channel->fd);
1326       if (win32_channel->debug)
1327         g_print ("closed fd %d, setting to -1\n",
1328                  win32_channel->fd);
1329       win32_channel->fd = -1;
1330     }
1331   UNLOCK (win32_channel->mutex);
1332
1333   /* FIXME error detection? */
1334
1335   return G_IO_STATUS_NORMAL;
1336 }
1337
1338 static GSource *
1339 g_io_win32_fd_create_watch (GIOChannel    *channel,
1340                             GIOCondition   condition)
1341 {
1342   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1343   GSource *source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
1344   GIOWin32Watch *watch = (GIOWin32Watch *)source;
1345
1346   watch->channel = channel;
1347   g_io_channel_ref (channel);
1348   
1349   watch->condition = condition;
1350   
1351   if (win32_channel->data_avail_event == NULL)
1352     create_events (win32_channel);
1353
1354   watch->pollfd.fd = (gint) win32_channel->data_avail_event;
1355   watch->pollfd.events = condition;
1356   
1357   if (win32_channel->debug)
1358     g_print ("g_io_win32_fd_create_watch: fd=%d condition={%s} handle=%#x\n",
1359              win32_channel->fd, condition_to_string (condition), watch->pollfd.fd);
1360
1361   LOCK (win32_channel->mutex);
1362   if (win32_channel->thread_id == 0)
1363     {
1364       if (condition & G_IO_IN)
1365         create_thread (win32_channel, condition, read_thread);
1366       else if (condition & G_IO_OUT)
1367         create_thread (win32_channel, condition, write_thread);
1368     }
1369
1370   g_source_add_poll (source, &watch->pollfd);
1371   UNLOCK (win32_channel->mutex);
1372
1373   return source;
1374 }
1375
1376 static GIOStatus
1377 g_io_win32_console_close (GIOChannel *channel,
1378                           GError    **err)
1379 {
1380   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1381   
1382   if (close (win32_channel->fd) < 0)
1383     {
1384       g_set_error (err, G_IO_CHANNEL_ERROR,
1385                    g_io_channel_error_from_errno (errno),
1386                    g_strerror (errno));
1387       return G_IO_STATUS_ERROR;
1388     }
1389
1390   return G_IO_STATUS_NORMAL;
1391 }
1392
1393 static GSource *
1394 g_io_win32_console_create_watch (GIOChannel    *channel,
1395                                  GIOCondition   condition)
1396 {
1397   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1398   GSource *source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
1399   GIOWin32Watch *watch = (GIOWin32Watch *)source;
1400
1401   watch->channel = channel;
1402   g_io_channel_ref (channel);
1403   
1404   watch->condition = condition;
1405   
1406   watch->pollfd.fd = (gint) _get_osfhandle (win32_channel->fd);
1407   watch->pollfd.events = condition;
1408   
1409   g_source_add_poll (source, &watch->pollfd);
1410
1411   return source;
1412 }
1413
1414 static GIOStatus
1415 g_io_win32_sock_read (GIOChannel *channel,
1416                       gchar      *buf,
1417                       gsize       count,
1418                       gsize      *bytes_read,
1419                       GError    **err)
1420 {
1421   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1422   gint result;
1423   GIOChannelError error;
1424   int winsock_error;
1425
1426   if (win32_channel->debug)
1427     g_print ("g_io_win32_sock_read: sockfd=%d count=%d\n",
1428              win32_channel->fd, count);
1429
1430   result = recv (win32_channel->fd, buf, count, 0);
1431   if (result == SOCKET_ERROR)
1432     winsock_error = WSAGetLastError ();
1433
1434   if (win32_channel->debug)
1435     g_print ("g_io_win32_sock_read: recv=%d %s\n",
1436              result,
1437              (result == SOCKET_ERROR ? winsock_error_message (winsock_error) : ""));
1438   
1439   if (result == SOCKET_ERROR)
1440     {
1441       *bytes_read = 0;
1442
1443       switch (winsock_error)
1444         {
1445         case WSAEINVAL:
1446           error = G_IO_CHANNEL_ERROR_INVAL;
1447           break;
1448         case WSAEWOULDBLOCK:
1449           return G_IO_STATUS_AGAIN;
1450         default:
1451           error = G_IO_CHANNEL_ERROR_FAILED;
1452           break;
1453         }
1454       g_set_error (err, G_IO_CHANNEL_ERROR, error,
1455                    winsock_error_message (winsock_error));
1456       return G_IO_STATUS_ERROR;
1457     }
1458   else
1459     {
1460       *bytes_read = result;
1461       if (result == 0)
1462         return G_IO_STATUS_EOF;
1463       else
1464         return G_IO_STATUS_NORMAL;
1465     }
1466 }
1467
1468 static GIOStatus
1469 g_io_win32_sock_write (GIOChannel  *channel,
1470                        const gchar *buf,
1471                        gsize        count,
1472                        gsize       *bytes_written,
1473                        GError     **err)
1474 {
1475   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1476   gint result;
1477   GIOChannelError error;
1478   int winsock_error;
1479   
1480   if (win32_channel->debug)
1481     g_print ("g_io_win32_sock_write: sockfd=%d count=%d\n",
1482              win32_channel->fd, count);
1483
1484   result = send (win32_channel->fd, buf, count, 0);
1485   if (result == SOCKET_ERROR)
1486     winsock_error = WSAGetLastError ();
1487
1488   if (win32_channel->debug)
1489     g_print ("g_io_win32_sock_write: send=%d %s\n",
1490              result,
1491              (result == SOCKET_ERROR ? winsock_error_message (winsock_error) : ""));
1492   
1493   if (result == SOCKET_ERROR)
1494     {
1495       *bytes_written = 0;
1496
1497       switch (winsock_error)
1498         {
1499         case WSAEINVAL:
1500           error = G_IO_CHANNEL_ERROR_INVAL;
1501           break;
1502         case WSAEWOULDBLOCK:
1503           win32_channel->write_would_have_blocked = TRUE;
1504           win32_channel->last_events = 0;
1505           return G_IO_STATUS_AGAIN;
1506         default:
1507           error = G_IO_CHANNEL_ERROR_FAILED;
1508           break;
1509         }
1510       g_set_error (err, G_IO_CHANNEL_ERROR, error,
1511                    winsock_error_message (winsock_error));
1512
1513       return G_IO_STATUS_ERROR;
1514     }
1515   else
1516     {
1517       *bytes_written = result;
1518       win32_channel->write_would_have_blocked = FALSE;
1519
1520       return G_IO_STATUS_NORMAL;
1521     }
1522 }
1523
1524 static GIOStatus
1525 g_io_win32_sock_close (GIOChannel *channel,
1526                        GError    **err)
1527 {
1528   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1529
1530   if (win32_channel->fd != -1)
1531     {
1532       if (win32_channel->debug)
1533         g_print ("g_io_win32_sock_close: closing socket %d\n",
1534                  win32_channel->fd);
1535       
1536       closesocket (win32_channel->fd);
1537       win32_channel->fd = -1;
1538     }
1539
1540   /* FIXME error detection? */
1541
1542   return G_IO_STATUS_NORMAL;
1543 }
1544
1545 static GSource *
1546 g_io_win32_sock_create_watch (GIOChannel    *channel,
1547                               GIOCondition   condition)
1548 {
1549   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1550   GSource *source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
1551   GIOWin32Watch *watch = (GIOWin32Watch *)source;
1552   
1553   watch->channel = channel;
1554   g_io_channel_ref (channel);
1555   
1556   watch->condition = condition;
1557
1558   if (win32_channel->event == 0)
1559     win32_channel->event = (int) WSACreateEvent ();
1560
1561   watch->pollfd.fd = win32_channel->event;
1562   watch->pollfd.events = condition;
1563   
1564   if (win32_channel->debug)
1565     g_print ("g_io_win32_sock_create_watch: sock=%d handle=%#x condition={%s}\n",
1566              win32_channel->fd, watch->pollfd.fd,
1567              condition_to_string (watch->condition));
1568
1569   g_source_add_poll (source, &watch->pollfd);
1570
1571   return source;
1572 }
1573
1574 GIOChannel *
1575 g_io_channel_new_file (const gchar  *filename,
1576                        const gchar  *mode,
1577                        GError      **error)
1578 {
1579   int fid, flags, pmode;
1580   GIOChannel *channel;
1581
1582   enum { /* Cheesy hack */
1583     MODE_R = 1 << 0,
1584     MODE_W = 1 << 1,
1585     MODE_A = 1 << 2,
1586     MODE_PLUS = 1 << 3,
1587   } mode_num;
1588
1589   g_return_val_if_fail (filename != NULL, NULL);
1590   g_return_val_if_fail (mode != NULL, NULL);
1591   g_return_val_if_fail ((error == NULL) || (*error == NULL), NULL);
1592
1593   switch (mode[0])
1594     {
1595       case 'r':
1596         mode_num = MODE_R;
1597         break;
1598       case 'w':
1599         mode_num = MODE_W;
1600         break;
1601       case 'a':
1602         mode_num = MODE_A;
1603         break;
1604       default:
1605         g_warning ("Invalid GIOFileMode %s.\n", mode);
1606         return NULL;
1607     }
1608
1609   switch (mode[1])
1610     {
1611       case '\0':
1612         break;
1613       case '+':
1614         if (mode[2] == '\0')
1615           {
1616             mode_num |= MODE_PLUS;
1617             break;
1618           }
1619         /* Fall through */
1620       default:
1621         g_warning ("Invalid GIOFileMode %s.\n", mode);
1622         return NULL;
1623     }
1624
1625   switch (mode_num)
1626     {
1627       case MODE_R:
1628         flags = O_RDONLY;
1629         pmode = _S_IREAD;
1630         break;
1631       case MODE_W:
1632         flags = O_WRONLY | O_TRUNC | O_CREAT;
1633         pmode = _S_IWRITE;
1634         break;
1635       case MODE_A:
1636         flags = O_WRONLY | O_APPEND | O_CREAT;
1637         pmode = _S_IWRITE;
1638         break;
1639       case MODE_R | MODE_PLUS:
1640         flags = O_RDWR;
1641         pmode = _S_IREAD | _S_IWRITE;
1642         break;
1643       case MODE_W | MODE_PLUS:
1644         flags = O_RDWR | O_TRUNC | O_CREAT;
1645         pmode = _S_IREAD | _S_IWRITE;
1646         break;
1647       case MODE_A | MODE_PLUS:
1648         flags = O_RDWR | O_APPEND | O_CREAT;
1649         pmode = _S_IREAD | _S_IWRITE;
1650         break;
1651       default:
1652         g_assert_not_reached ();
1653         abort ();
1654     }
1655
1656   /* always open 'untranslated' */
1657   fid = g_open (filename, flags | _O_BINARY, pmode);
1658
1659   if (g_io_win32_get_debug_flag ())
1660     {
1661       g_print ("g_io_channel_win32_new_file: open(\"%s\", ", filename);
1662       g_win32_print_access_mode (flags|_O_BINARY);
1663       g_print (",%#o)=%d\n", pmode, fid);
1664     }
1665
1666   if (fid < 0)
1667     {
1668       g_set_error (error, G_FILE_ERROR,
1669                    g_file_error_from_errno (errno),
1670                    g_strerror (errno));
1671       return (GIOChannel *)NULL;
1672     }
1673
1674   channel = g_io_channel_win32_new_fd (fid);
1675
1676   /* XXX: move this to g_io_channel_win32_new_fd () */
1677   channel->close_on_unref = TRUE;
1678   channel->is_seekable = TRUE;
1679
1680   /* g_io_channel_win32_new_fd sets is_readable and is_writeable to
1681    * correspond to actual readability/writeability. Set to FALSE those
1682    * that mode doesn't allow
1683    */
1684   switch (mode_num)
1685     {
1686       case MODE_R:
1687         channel->is_writeable = FALSE;
1688         break;
1689       case MODE_W:
1690       case MODE_A:
1691         channel->is_readable = FALSE;
1692         break;
1693       case MODE_R | MODE_PLUS:
1694       case MODE_W | MODE_PLUS:
1695       case MODE_A | MODE_PLUS:
1696         break;
1697       default:
1698         g_assert_not_reached ();
1699         abort ();
1700     }
1701
1702   return channel;
1703 }
1704
1705 #ifdef G_OS_WIN32
1706
1707 #undef g_io_channel_new_file
1708
1709 /* Binary compatibility version. Not for newly compiled code. */
1710
1711 GIOChannel *
1712 g_io_channel_new_file (const gchar  *filename,
1713                        const gchar  *mode,
1714                        GError      **error)
1715 {
1716   gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, error);
1717   GIOChannel *retval;
1718
1719   if (utf8_filename == NULL)
1720     return NULL;
1721
1722   retval = g_io_channel_new_file_utf8 (utf8_filename, mode, error);
1723
1724   g_free (utf8_filename);
1725
1726   return retval;
1727 }
1728
1729 #endif
1730
1731 static GIOStatus
1732 g_io_win32_unimpl_set_flags (GIOChannel *channel,
1733                              GIOFlags    flags,
1734                              GError    **err)
1735 {
1736   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1737
1738   if (win32_channel->debug)
1739     {
1740       g_print ("g_io_win32_unimpl_set_flags: ");
1741       g_win32_print_gioflags (flags);
1742       g_print ("\n");
1743     }
1744
1745   g_set_error (err, G_IO_CHANNEL_ERROR,
1746                G_IO_CHANNEL_ERROR_FAILED,
1747                "Not implemented on Win32");
1748
1749   return G_IO_STATUS_ERROR;
1750 }
1751
1752 static GIOFlags
1753 g_io_win32_fd_get_flags_internal (GIOChannel  *channel,
1754                                   struct stat *st)
1755 {
1756   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
1757   gchar c;
1758   DWORD count;
1759
1760   if (st->st_mode & _S_IFIFO)
1761     {
1762       channel->is_readable =
1763         (PeekNamedPipe ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL, NULL) != 0) || GetLastError () == ERROR_BROKEN_PIPE;
1764       channel->is_writeable =
1765         (WriteFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
1766       channel->is_seekable  = FALSE;
1767     }
1768   else
1769     {
1770       channel->is_readable =
1771         (ReadFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
1772       channel->is_writeable =
1773         (WriteFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
1774       channel->is_seekable = TRUE;
1775     }
1776
1777   /* XXX: G_IO_FLAG_APPEND */
1778   /* XXX: G_IO_FLAG_NONBLOCK */
1779
1780   return 0;
1781 }
1782
1783 static GIOFlags
1784 g_io_win32_fd_get_flags (GIOChannel *channel)
1785 {
1786   struct stat st;
1787   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1788
1789   g_return_val_if_fail (win32_channel != NULL, 0);
1790   g_return_val_if_fail (win32_channel->type == G_IO_WIN32_FILE_DESC, 0);
1791
1792   if (0 == fstat (win32_channel->fd, &st))
1793     return g_io_win32_fd_get_flags_internal (channel, &st);
1794   else
1795     return 0;
1796 }
1797
1798 static GIOFlags
1799 g_io_win32_console_get_flags_internal (GIOChannel  *channel)
1800 {
1801   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
1802   HANDLE handle = (HANDLE) _get_osfhandle (win32_channel->fd);
1803   gchar c;
1804   DWORD count;
1805   INPUT_RECORD record;
1806
1807   channel->is_readable = PeekConsoleInput (handle, &record, 1, &count);
1808   channel->is_writeable = WriteFile (handle, &c, 0, &count, NULL);
1809   channel->is_seekable = FALSE;
1810
1811   return 0;
1812 }
1813
1814 static GIOFlags
1815 g_io_win32_console_get_flags (GIOChannel *channel)
1816 {
1817   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1818
1819   g_return_val_if_fail (win32_channel != NULL, 0);
1820   g_return_val_if_fail (win32_channel->type == G_IO_WIN32_CONSOLE, 0);
1821
1822   return g_io_win32_console_get_flags_internal (channel);
1823 }
1824
1825 static GIOFlags
1826 g_io_win32_msg_get_flags (GIOChannel *channel)
1827 {
1828   return 0;
1829 }
1830
1831 static GIOStatus
1832 g_io_win32_sock_set_flags (GIOChannel *channel,
1833                            GIOFlags    flags,
1834                            GError    **err)
1835 {
1836   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1837   u_long arg;
1838
1839   if (win32_channel->debug)
1840     {
1841       g_print ("g_io_win32_sock_set_flags: ");
1842       g_win32_print_gioflags (flags);
1843       g_print ("\n");
1844     }
1845
1846   if (flags & G_IO_FLAG_NONBLOCK)
1847     {
1848       arg = 1;
1849       if (ioctlsocket (win32_channel->fd, FIONBIO, &arg) == SOCKET_ERROR)
1850         {
1851           g_set_error (err, G_IO_CHANNEL_ERROR,
1852                        G_IO_CHANNEL_ERROR_FAILED,
1853                        winsock_error_message (WSAGetLastError ()));
1854           return G_IO_STATUS_ERROR;
1855         }
1856     }
1857   else
1858     {
1859       arg = 0;
1860       if (ioctlsocket (win32_channel->fd, FIONBIO, &arg) == SOCKET_ERROR)
1861         {
1862           g_set_error (err, G_IO_CHANNEL_ERROR,
1863                        G_IO_CHANNEL_ERROR_FAILED,
1864                        winsock_error_message (WSAGetLastError ()));
1865           return G_IO_STATUS_ERROR;
1866         }
1867     }
1868
1869   return G_IO_STATUS_NORMAL;
1870 }
1871
1872 static GIOFlags
1873 g_io_win32_sock_get_flags (GIOChannel *channel)
1874 {
1875   /* Could we do something here? */
1876   return 0;
1877 }
1878
1879 static GIOFuncs win32_channel_msg_funcs = {
1880   g_io_win32_msg_read,
1881   g_io_win32_msg_write,
1882   NULL,
1883   g_io_win32_msg_close,
1884   g_io_win32_msg_create_watch,
1885   g_io_win32_free,
1886   g_io_win32_unimpl_set_flags,
1887   g_io_win32_msg_get_flags,
1888 };
1889
1890 static GIOFuncs win32_channel_fd_funcs = {
1891   g_io_win32_fd_and_console_read,
1892   g_io_win32_fd_and_console_write,
1893   g_io_win32_fd_seek,
1894   g_io_win32_fd_close,
1895   g_io_win32_fd_create_watch,
1896   g_io_win32_free,
1897   g_io_win32_unimpl_set_flags,
1898   g_io_win32_fd_get_flags,
1899 };
1900
1901 static GIOFuncs win32_channel_console_funcs = {
1902   g_io_win32_fd_and_console_read,
1903   g_io_win32_fd_and_console_write,
1904   NULL,
1905   g_io_win32_console_close,
1906   g_io_win32_console_create_watch,
1907   g_io_win32_free,
1908   g_io_win32_unimpl_set_flags,
1909   g_io_win32_console_get_flags,
1910 };
1911
1912 static GIOFuncs win32_channel_sock_funcs = {
1913   g_io_win32_sock_read,
1914   g_io_win32_sock_write,
1915   NULL,
1916   g_io_win32_sock_close,
1917   g_io_win32_sock_create_watch,
1918   g_io_win32_free,
1919   g_io_win32_sock_set_flags,
1920   g_io_win32_sock_get_flags,
1921 };
1922
1923 GIOChannel *
1924 g_io_channel_win32_new_messages (guint hwnd)
1925 {
1926   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1927   GIOChannel *channel = (GIOChannel *)win32_channel;
1928
1929   g_io_channel_init (channel);
1930   g_io_channel_win32_init (win32_channel);
1931   if (win32_channel->debug)
1932     g_print ("g_io_channel_win32_new_messages: hwnd=%#x\n", hwnd);
1933   channel->funcs = &win32_channel_msg_funcs;
1934   win32_channel->type = G_IO_WIN32_WINDOWS_MESSAGES;
1935   win32_channel->hwnd = (HWND) hwnd;
1936
1937   /* XXX: check this. */
1938   channel->is_readable = IsWindow (win32_channel->hwnd);
1939   channel->is_writeable = IsWindow (win32_channel->hwnd);
1940
1941   channel->is_seekable = FALSE;
1942
1943   return channel;
1944 }
1945
1946 static GIOChannel *
1947 g_io_channel_win32_new_fd_internal (gint         fd,
1948                                     struct stat *st)
1949 {
1950   GIOWin32Channel *win32_channel;
1951   GIOChannel *channel;
1952
1953   win32_channel = g_new (GIOWin32Channel, 1);
1954   channel = (GIOChannel *)win32_channel;
1955
1956   g_io_channel_init (channel);
1957   g_io_channel_win32_init (win32_channel);
1958
1959   win32_channel->fd = fd;
1960
1961   if (win32_channel->debug)
1962     g_print ("g_io_channel_win32_new_fd: %u\n", fd);
1963   if (st->st_mode & _S_IFCHR) /* console */
1964     {
1965       channel->funcs = &win32_channel_console_funcs;
1966       win32_channel->type = G_IO_WIN32_CONSOLE;
1967       g_io_win32_console_get_flags_internal (channel);
1968     }
1969   else
1970     {
1971       channel->funcs = &win32_channel_fd_funcs;
1972       win32_channel->type = G_IO_WIN32_FILE_DESC;
1973       g_io_win32_fd_get_flags_internal (channel, st);
1974     }
1975   
1976   return channel;
1977 }
1978
1979 GIOChannel *
1980 g_io_channel_win32_new_fd (gint fd)
1981 {
1982   struct stat st;
1983
1984   if (fstat (fd, &st) == -1)
1985     {
1986       g_warning (G_STRLOC ": %d isn't a C library file descriptor", fd);
1987       return NULL;
1988     }
1989
1990   return g_io_channel_win32_new_fd_internal (fd, &st);
1991 }
1992
1993 gint
1994 g_io_channel_win32_get_fd (GIOChannel *channel)
1995 {
1996   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1997
1998   return win32_channel->fd;
1999 }
2000
2001 GIOChannel *
2002 g_io_channel_win32_new_socket (int socket)
2003 {
2004   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
2005   GIOChannel *channel = (GIOChannel *)win32_channel;
2006
2007   g_io_channel_init (channel);
2008   g_io_channel_win32_init (win32_channel);
2009   if (win32_channel->debug)
2010     g_print ("g_io_channel_win32_new_socket: sockfd=%d\n", socket);
2011   channel->funcs = &win32_channel_sock_funcs;
2012   win32_channel->type = G_IO_WIN32_SOCKET;
2013   win32_channel->fd = socket;
2014
2015   channel->is_readable = TRUE;
2016   channel->is_writeable = TRUE;
2017   channel->is_seekable = FALSE;
2018
2019   return channel;
2020 }
2021
2022 GIOChannel *
2023 g_io_channel_unix_new (gint fd)
2024 {
2025   gboolean is_fd, is_socket;
2026   struct stat st;
2027   int optval, optlen;
2028
2029   is_fd = (fstat (fd, &st) == 0);
2030
2031   optlen = sizeof (optval);
2032   is_socket = (getsockopt (fd, SOL_SOCKET, SO_TYPE, (char *) &optval, &optlen) != SOCKET_ERROR);
2033
2034   if (is_fd && is_socket)
2035     g_warning (G_STRLOC ": %d is both a file descriptor and a socket, file descriptor interpretation assumed.", fd);
2036
2037   if (is_fd)
2038     return g_io_channel_win32_new_fd_internal (fd, &st);
2039
2040   if (is_socket)
2041     return g_io_channel_win32_new_socket(fd);
2042
2043   g_warning (G_STRLOC ": %d is neither a file descriptor or a socket", fd);
2044
2045   return NULL;
2046 }
2047
2048 gint
2049 g_io_channel_unix_get_fd (GIOChannel *channel)
2050 {
2051   return g_io_channel_win32_get_fd (channel);
2052 }
2053
2054 void
2055 g_io_channel_win32_set_debug (GIOChannel *channel,
2056                               gboolean    flag)
2057 {
2058   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
2059
2060   win32_channel->debug = flag;
2061 }
2062
2063 gint
2064 g_io_channel_win32_poll (GPollFD *fds,
2065                          gint     n_fds,
2066                          gint     timeout)
2067 {
2068   int result;
2069
2070   g_return_val_if_fail (n_fds >= 0, 0);
2071
2072   result = (*g_main_context_get_poll_func (NULL)) (fds, n_fds, timeout);
2073
2074   return result;
2075 }
2076
2077 void
2078 g_io_channel_win32_make_pollfd (GIOChannel   *channel,
2079                                 GIOCondition  condition,
2080                                 GPollFD      *fd)
2081 {
2082   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
2083
2084   switch (win32_channel->type)
2085     {
2086     case G_IO_WIN32_FILE_DESC:
2087       if (win32_channel->data_avail_event == NULL)
2088         create_events (win32_channel);
2089
2090       fd->fd = (gint) win32_channel->data_avail_event;
2091
2092       if (win32_channel->thread_id == 0 && (condition & G_IO_IN))
2093         {
2094           if (condition & G_IO_IN)
2095             create_thread (win32_channel, condition, read_thread);
2096           else if (condition & G_IO_OUT)
2097             create_thread (win32_channel, condition, write_thread);
2098         }
2099       break;
2100
2101     case G_IO_WIN32_CONSOLE:
2102       fd->fd = (gint) _get_osfhandle (win32_channel->fd);
2103       break;
2104
2105     case G_IO_WIN32_SOCKET:
2106       fd->fd = (int) WSACreateEvent ();
2107       break;
2108       
2109     case G_IO_WIN32_WINDOWS_MESSAGES:
2110       fd->fd = G_WIN32_MSG_HANDLE;
2111       break;
2112
2113     default:
2114       g_assert_not_reached ();
2115       abort ();
2116     }
2117   
2118   fd->events = condition;
2119 }
2120
2121 /* Binary compatibility */
2122 GIOChannel *
2123 g_io_channel_win32_new_stream_socket (int socket)
2124 {
2125   return g_io_channel_win32_new_socket (socket);
2126 }
2127
2128 #define __G_IO_WIN32_C__
2129 #include "galiasdef.c"