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