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