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