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