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