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