Merge remote-tracking branch 'gvdb/master'
[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 #include "gstdio.h"
85 #include "glibintl.h"
86
87
88 typedef struct _GIOWin32Channel GIOWin32Channel;
89 typedef struct _GIOWin32Watch GIOWin32Watch;
90
91 #define BUFFER_SIZE 4096
92
93 typedef enum {
94   G_IO_WIN32_WINDOWS_MESSAGES,  /* Windows messages */
95
96   G_IO_WIN32_FILE_DESC,         /* Unix-like file descriptors from
97                                  * _open() or _pipe(), except for
98                                  * console IO. Separate thread to read
99                                  * or write.
100                                  */
101
102   G_IO_WIN32_CONSOLE,           /* Console IO (usually stdin, stdout, stderr) */
103
104   G_IO_WIN32_SOCKET             /* Sockets. No separate thread. */
105 } GIOWin32ChannelType;
106
107 struct _GIOWin32Channel {
108   GIOChannel channel;
109   gint fd;                      /* Either a Unix-like file handle as provided
110                                  * by the Microsoft C runtime, or a SOCKET
111                                  * as provided by WinSock.
112                                  */
113   GIOWin32ChannelType type;
114   
115   gboolean debug;
116
117   /* Field used by G_IO_WIN32_WINDOWS_MESSAGES channels */
118   HWND hwnd;                    /* Handle of window, or NULL */
119   
120   /* Fields used by G_IO_WIN32_FILE_DESC channels. */
121   CRITICAL_SECTION mutex;
122
123   int direction;                /* 0 means we read from it,
124                                  * 1 means we write to it.
125                                  */
126
127   gboolean running;             /* Is reader or writer thread
128                                  * running. FALSE if EOF has been
129                                  * reached by the reader thread.
130                                  */
131
132   gboolean needs_close;         /* If the channel has been closed while
133                                  * the reader thread was still running.
134                                  */
135
136   guint thread_id;              /* If non-NULL the channel has or has
137                                  * had a reader or writer thread.
138                                  */
139   HANDLE data_avail_event;
140
141   gushort revents;
142
143   /* Data is kept in a circular buffer. To be able to distinguish between
144    * empty and full buffers, we cannot fill it completely, but have to
145    * leave a one character gap.
146    *
147    * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
148    *
149    * Empty:    wrp == rdp
150    * Full:     (wrp + 1) % BUFFER_SIZE == rdp
151    * Partial:  otherwise
152    */
153   guchar *buffer;               /* (Circular) buffer */
154   gint wrp, rdp;                /* Buffer indices for writing and reading */
155   HANDLE space_avail_event;
156
157   /* Fields used by G_IO_WIN32_SOCKET channels */
158   int event_mask;
159   int last_events;
160   HANDLE event;
161   gboolean write_would_have_blocked;
162   gboolean ever_writable;
163 };
164
165 struct _GIOWin32Watch {
166   GSource       source;
167   GPollFD       pollfd;
168   GIOChannel   *channel;
169   GIOCondition  condition;
170 };
171
172 static void
173 g_win32_print_access_mode (int flags)
174 {
175   g_print ("%s%s%s%s%s%s%s%s%s%s",
176            ((flags & 0x3) == _O_RDWR ? "O_RDWR" :
177             ((flags & 0x3) == _O_RDONLY ? "O_RDONLY" :
178              ((flags & 0x3) == _O_WRONLY ? "O_WRONLY" : "0"))),
179            (flags & _O_APPEND ? "|O_APPEND" : ""),
180            (flags & _O_RANDOM ? "|O_RANDOM" : ""),
181            (flags & _O_SEQUENTIAL ? "|O_SEQUENTIAL" : ""),
182            (flags & _O_TEMPORARY ? "|O_TEMPORARY" : ""),
183            (flags & _O_CREAT ? "|O_CREAT" : ""),
184            (flags & _O_TRUNC ? "|O_TRUNC" : ""),
185            (flags & _O_EXCL ? "|O_EXCL" : ""),
186            (flags & _O_TEXT ? "|O_TEXT" : ""),
187            (flags & _O_BINARY ? "|O_BINARY" : ""));
188 }
189
190 static void
191 g_win32_print_gioflags (GIOFlags flags)
192 {
193   char *bar = "";
194
195   if (flags & G_IO_FLAG_APPEND)
196     bar = "|", g_print ("APPEND");
197   if (flags & G_IO_FLAG_NONBLOCK)
198     g_print ("%sNONBLOCK", bar), bar = "|";
199   if (flags & G_IO_FLAG_IS_READABLE)
200     g_print ("%sREADABLE", bar), bar = "|";
201   if (flags & G_IO_FLAG_IS_WRITABLE)
202     g_print ("%sWRITABLE", bar), bar = "|";
203   if (flags & G_IO_FLAG_IS_SEEKABLE)
204     g_print ("%sSEEKABLE", bar), bar = "|";
205 }
206
207 static const char *
208 event_mask_to_string (int mask)
209 {
210   char buf[100];
211   int checked_bits = 0;
212   char *bufp = buf;
213
214   if (mask == 0)
215     return "";
216
217 #define BIT(n) checked_bits |= FD_##n; if (mask & FD_##n) bufp += sprintf (bufp, "%s" #n, (bufp>buf ? "|" : ""))
218
219   BIT (READ);
220   BIT (WRITE);
221   BIT (OOB);
222   BIT (ACCEPT);
223   BIT (CONNECT);
224   BIT (CLOSE);
225   BIT (QOS);
226   BIT (GROUP_QOS);
227   BIT (ROUTING_INTERFACE_CHANGE);
228   BIT (ADDRESS_LIST_CHANGE);
229   
230 #undef BIT
231
232   if ((mask & ~checked_bits) != 0)
233           bufp += sprintf (bufp, "|%#x", mask & ~checked_bits);
234   
235   return g_quark_to_string (g_quark_from_string (buf));
236 }
237
238 static const char *
239 condition_to_string (GIOCondition condition)
240 {
241   char buf[100];
242   int checked_bits = 0;
243   char *bufp = buf;
244
245   if (condition == 0)
246     return "";
247
248 #define BIT(n) checked_bits |= G_IO_##n; if (condition & G_IO_##n) bufp += sprintf (bufp, "%s" #n, (bufp>buf ? "|" : ""))
249
250   BIT (IN);
251   BIT (OUT);
252   BIT (PRI);
253   BIT (ERR);
254   BIT (HUP);
255   BIT (NVAL);
256   
257 #undef BIT
258
259   if ((condition & ~checked_bits) != 0)
260           bufp += sprintf (bufp, "|%#x", condition & ~checked_bits);
261   
262   return g_quark_to_string (g_quark_from_string (buf));
263 }
264
265 static gboolean
266 g_io_win32_get_debug_flag (void)
267 {
268   return (getenv ("G_IO_WIN32_DEBUG") != NULL);
269 }
270
271 static void
272 g_io_channel_win32_init (GIOWin32Channel *channel)
273 {
274   channel->debug = g_io_win32_get_debug_flag ();
275
276   InitializeCriticalSection (&channel->mutex);
277   channel->running = FALSE;
278   channel->needs_close = FALSE;
279   channel->thread_id = 0;
280   channel->data_avail_event = NULL;
281   channel->revents = 0;
282   channel->buffer = NULL;
283   channel->space_avail_event = NULL;
284
285   channel->event_mask = 0;
286   channel->last_events = 0;
287   channel->event = NULL;
288   channel->write_would_have_blocked = FALSE;
289   channel->ever_writable = FALSE;
290 }
291
292 static void
293 create_events (GIOWin32Channel *channel)
294 {
295   SECURITY_ATTRIBUTES sec_attrs;
296   
297   sec_attrs.nLength = sizeof (SECURITY_ATTRIBUTES);
298   sec_attrs.lpSecurityDescriptor = NULL;
299   sec_attrs.bInheritHandle = FALSE;
300
301   /* The data available event is manual reset, the space available event
302    * is automatic reset.
303    */
304   if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
305       || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
306     {
307       gchar *emsg = g_win32_error_message (GetLastError ());
308
309       g_error ("Error creating event: %s", emsg);
310       g_free (emsg);
311     }
312 }
313
314 static unsigned __stdcall
315 read_thread (void *parameter)
316 {
317   GIOWin32Channel *channel = parameter;
318   guchar *buffer;
319   gint nbytes;
320
321   g_io_channel_ref ((GIOChannel *)channel);
322
323   if (channel->debug)
324     g_print ("read_thread %#x: start fd=%d, data_avail=%p space_avail=%p\n",
325              channel->thread_id,
326              channel->fd,
327              channel->data_avail_event,
328              channel->space_avail_event);
329
330   channel->direction = 0;
331   channel->buffer = g_malloc (BUFFER_SIZE);
332   channel->rdp = channel->wrp = 0;
333   channel->running = TRUE;
334
335   SetEvent (channel->space_avail_event);
336   
337   EnterCriticalSection (&channel->mutex);
338   while (channel->running)
339     {
340       if (channel->debug)
341         g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
342                  channel->thread_id, channel->rdp, channel->wrp);
343       if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
344         {
345           /* Buffer is full */
346           if (channel->debug)
347             g_print ("read_thread %#x: resetting space_avail\n",
348                      channel->thread_id);
349           ResetEvent (channel->space_avail_event);
350           if (channel->debug)
351             g_print ("read_thread %#x: waiting for space\n",
352                      channel->thread_id);
353           LeaveCriticalSection (&channel->mutex);
354           WaitForSingleObject (channel->space_avail_event, INFINITE);
355           EnterCriticalSection (&channel->mutex);
356           if (channel->debug)
357             g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
358                      channel->thread_id, channel->rdp, channel->wrp);
359         }
360       
361       buffer = channel->buffer + channel->wrp;
362       
363       /* Always leave at least one byte unused gap to be able to
364        * distinguish between the full and empty condition...
365        */
366       nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
367                     BUFFER_SIZE - channel->wrp);
368
369       if (channel->debug)
370         g_print ("read_thread %#x: calling read() for %d bytes\n",
371                  channel->thread_id, nbytes);
372
373       LeaveCriticalSection (&channel->mutex);
374
375       nbytes = read (channel->fd, buffer, nbytes);
376       
377       EnterCriticalSection (&channel->mutex);
378
379       channel->revents = G_IO_IN;
380       if (nbytes == 0)
381         channel->revents |= G_IO_HUP;
382       else if (nbytes < 0)
383         channel->revents |= G_IO_ERR;
384
385       if (channel->debug)
386         g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
387                  channel->thread_id, nbytes, channel->rdp, channel->wrp);
388
389       if (nbytes <= 0)
390         break;
391
392       channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
393       if (channel->debug)
394         g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
395                  channel->thread_id, channel->rdp, channel->wrp);
396       SetEvent (channel->data_avail_event);
397     }
398   
399   channel->running = FALSE;
400   if (channel->needs_close)
401     {
402       if (channel->debug)
403         g_print ("read_thread %#x: channel fd %d needs closing\n",
404                  channel->thread_id, channel->fd);
405       close (channel->fd);
406       channel->fd = -1;
407     }
408
409   if (channel->debug)
410     g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
411              channel->thread_id, channel->rdp, channel->wrp);
412   SetEvent (channel->data_avail_event);
413   LeaveCriticalSection (&channel->mutex);
414   
415   g_io_channel_unref ((GIOChannel *)channel);
416   
417   /* No need to call _endthreadex(), the actual thread starter routine
418    * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
419    * _endthreadex() for us.
420    */
421
422   return 0;
423 }
424
425 static unsigned __stdcall
426 write_thread (void *parameter)
427 {
428   GIOWin32Channel *channel = parameter;
429   guchar *buffer;
430   gint nbytes;
431
432   g_io_channel_ref ((GIOChannel *)channel);
433
434   if (channel->debug)
435     g_print ("write_thread %#x: start fd=%d, data_avail=%p space_avail=%p\n",
436              channel->thread_id,
437              channel->fd,
438              channel->data_avail_event,
439              channel->space_avail_event);
440   
441   channel->direction = 1;
442   channel->buffer = g_malloc (BUFFER_SIZE);
443   channel->rdp = channel->wrp = 0;
444   channel->running = TRUE;
445
446   SetEvent (channel->space_avail_event);
447
448   /* We use the same event objects as for a reader thread, but with
449    * reversed meaning. So, space_avail is used if data is available
450    * for writing, and data_avail is used if space is available in the
451    * write buffer.
452    */
453
454   EnterCriticalSection (&channel->mutex);
455   while (channel->running || channel->rdp != channel->wrp)
456     {
457       if (channel->debug)
458         g_print ("write_thread %#x: rdp=%d, wrp=%d\n",
459                  channel->thread_id, channel->rdp, channel->wrp);
460       if (channel->wrp == channel->rdp)
461         {
462           /* Buffer is empty. */
463           if (channel->debug)
464             g_print ("write_thread %#x: resetting space_avail\n",
465                      channel->thread_id);
466           ResetEvent (channel->space_avail_event);
467           if (channel->debug)
468             g_print ("write_thread %#x: waiting for data\n",
469                      channel->thread_id);
470           channel->revents = G_IO_OUT;
471           SetEvent (channel->data_avail_event);
472           LeaveCriticalSection (&channel->mutex);
473           WaitForSingleObject (channel->space_avail_event, INFINITE);
474
475           EnterCriticalSection (&channel->mutex);
476           if (channel->rdp == channel->wrp)
477             break;
478
479           if (channel->debug)
480             g_print ("write_thread %#x: rdp=%d, wrp=%d\n",
481                      channel->thread_id, channel->rdp, channel->wrp);
482         }
483       
484       buffer = channel->buffer + channel->rdp;
485       if (channel->rdp < channel->wrp)
486         nbytes = channel->wrp - channel->rdp;
487       else
488         nbytes = BUFFER_SIZE - channel->rdp;
489
490       if (channel->debug)
491         g_print ("write_thread %#x: calling write() for %d bytes\n",
492                  channel->thread_id, nbytes);
493
494       LeaveCriticalSection (&channel->mutex);
495       nbytes = write (channel->fd, buffer, nbytes);
496       EnterCriticalSection (&channel->mutex);
497
498       if (channel->debug)
499         g_print ("write_thread %#x: write(%i) returned %d, rdp=%d, wrp=%d\n",
500                  channel->thread_id, channel->fd, nbytes, channel->rdp, channel->wrp);
501
502       channel->revents = 0;
503       if (nbytes > 0)
504         channel->revents |= G_IO_OUT;
505       else if (nbytes <= 0)
506         channel->revents |= G_IO_ERR;
507
508       channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
509
510       if (nbytes <= 0)
511         break;
512
513       if (channel->debug)
514         g_print ("write_thread: setting data_avail for thread %#x\n",
515                  channel->thread_id);
516       SetEvent (channel->data_avail_event);
517     }
518   
519   channel->running = FALSE;
520   if (channel->needs_close)
521     {
522       if (channel->debug)
523         g_print ("write_thread %#x: channel fd %d needs closing\n",
524                  channel->thread_id, channel->fd);
525       close (channel->fd);
526       channel->fd = -1;
527     }
528
529   LeaveCriticalSection (&channel->mutex);
530   
531   g_io_channel_unref ((GIOChannel *)channel);
532   
533   return 0;
534 }
535
536 static void
537 create_thread (GIOWin32Channel     *channel,
538                GIOCondition         condition,
539                unsigned (__stdcall *thread) (void *parameter))
540 {
541   HANDLE thread_handle;
542
543   thread_handle = (HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
544                                            &channel->thread_id);
545   if (thread_handle == 0)
546     g_warning ("Error creating thread: %s.",
547                g_strerror (errno));
548   else if (!CloseHandle (thread_handle))
549     {
550       gchar *emsg = g_win32_error_message (GetLastError ());
551
552       g_warning ("Error closing thread handle: %s.", emsg);
553       g_free (emsg);
554     }
555
556   WaitForSingleObject (channel->space_avail_event, INFINITE);
557 }
558
559 static GIOStatus
560 buffer_read (GIOWin32Channel *channel,
561              gchar           *dest,
562              gsize            count,
563              gsize           *bytes_read,
564              GError         **err)
565 {
566   guint nbytes;
567   guint left = count;
568   
569   EnterCriticalSection (&channel->mutex);
570   if (channel->debug)
571     g_print ("reading from thread %#x %" G_GSIZE_FORMAT " bytes, rdp=%d, wrp=%d\n",
572              channel->thread_id, count, channel->rdp, channel->wrp);
573   
574   if (channel->wrp == channel->rdp)
575     {
576       LeaveCriticalSection (&channel->mutex);
577       if (channel->debug)
578         g_print ("waiting for data from thread %#x\n", channel->thread_id);
579       WaitForSingleObject (channel->data_avail_event, INFINITE);
580       if (channel->debug)
581         g_print ("done waiting for data from thread %#x\n", channel->thread_id);
582       EnterCriticalSection (&channel->mutex);
583       if (channel->wrp == channel->rdp && !channel->running)
584         {
585           if (channel->debug)
586             g_print ("wrp==rdp, !running\n");
587           LeaveCriticalSection (&channel->mutex);
588           *bytes_read = 0;
589           return G_IO_STATUS_EOF;
590         }
591     }
592   
593   if (channel->rdp < channel->wrp)
594     nbytes = channel->wrp - channel->rdp;
595   else
596     nbytes = BUFFER_SIZE - channel->rdp;
597   LeaveCriticalSection (&channel->mutex);
598   nbytes = MIN (left, nbytes);
599   if (channel->debug)
600     g_print ("moving %d bytes from thread %#x\n",
601              nbytes, channel->thread_id);
602   memcpy (dest, channel->buffer + channel->rdp, nbytes);
603   dest += nbytes;
604   left -= nbytes;
605   EnterCriticalSection (&channel->mutex);
606   channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
607   if (channel->debug)
608     g_print ("setting space_avail for thread %#x\n", channel->thread_id);
609   SetEvent (channel->space_avail_event);
610   if (channel->debug)
611     g_print ("for thread %#x: rdp=%d, wrp=%d\n",
612              channel->thread_id, channel->rdp, channel->wrp);
613   if (channel->running && channel->wrp == channel->rdp)
614     {
615       if (channel->debug)
616         g_print ("resetting data_avail of thread %#x\n",
617                  channel->thread_id);
618       ResetEvent (channel->data_avail_event);
619     };
620   LeaveCriticalSection (&channel->mutex);
621   
622   /* We have no way to indicate any errors form the actual
623    * read() or recv() call in the reader thread. Should we have?
624    */
625   *bytes_read = count - left;
626   return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
627 }
628
629
630 static GIOStatus
631 buffer_write (GIOWin32Channel *channel,
632               const gchar     *dest,
633               gsize            count,
634               gsize           *bytes_written,
635               GError         **err)
636 {
637   guint nbytes;
638   guint left = count;
639   
640   EnterCriticalSection (&channel->mutex);
641   if (channel->debug)
642     g_print ("buffer_write: writing to thread %#x %" G_GSIZE_FORMAT " bytes, rdp=%d, wrp=%d\n",
643              channel->thread_id, count, channel->rdp, channel->wrp);
644   
645   if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
646     {
647       /* Buffer is full */
648       if (channel->debug)
649         g_print ("buffer_write: tid %#x: resetting data_avail\n",
650                  channel->thread_id);
651       ResetEvent (channel->data_avail_event);
652       if (channel->debug)
653         g_print ("buffer_write: tid %#x: waiting for space\n",
654                  channel->thread_id);
655       LeaveCriticalSection (&channel->mutex);
656       WaitForSingleObject (channel->data_avail_event, INFINITE);
657       EnterCriticalSection (&channel->mutex);
658       if (channel->debug)
659         g_print ("buffer_write: tid %#x: rdp=%d, wrp=%d\n",
660                  channel->thread_id, channel->rdp, channel->wrp);
661     }
662    
663   nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
664                 BUFFER_SIZE - channel->wrp);
665
666   LeaveCriticalSection (&channel->mutex);
667   nbytes = MIN (left, nbytes);
668   if (channel->debug)
669     g_print ("buffer_write: tid %#x: writing %d bytes\n",
670              channel->thread_id, nbytes);
671   memcpy (channel->buffer + channel->wrp, dest, nbytes);
672   dest += nbytes;
673   left -= nbytes;
674   EnterCriticalSection (&channel->mutex);
675
676   channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
677   if (channel->debug)
678     g_print ("buffer_write: tid %#x: rdp=%d, wrp=%d, setting space_avail\n",
679              channel->thread_id, channel->rdp, channel->wrp);
680   SetEvent (channel->space_avail_event);
681
682   if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
683     {
684       /* Buffer is full */
685       if (channel->debug)
686         g_print ("buffer_write: tid %#x: resetting data_avail\n",
687                  channel->thread_id);
688       ResetEvent (channel->data_avail_event);
689     }
690
691   LeaveCriticalSection (&channel->mutex);
692   
693   /* We have no way to indicate any errors form the actual
694    * write() call in the writer thread. Should we have?
695    */
696   *bytes_written = count - left;
697   return (*bytes_written > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
698 }
699
700
701 static gboolean
702 g_io_win32_prepare (GSource *source,
703                     gint    *timeout)
704 {
705   GIOWin32Watch *watch = (GIOWin32Watch *)source;
706   GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
707   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
708   int event_mask;
709   
710   *timeout = -1;
711   
712   if (channel->debug)
713     g_print ("g_io_win32_prepare: source=%p channel=%p", source, channel);
714
715   switch (channel->type)
716     {
717     case G_IO_WIN32_WINDOWS_MESSAGES:
718       if (channel->debug)
719         g_print (" MSG");
720       break;
721
722     case G_IO_WIN32_CONSOLE:
723       if (channel->debug)
724         g_print (" CON");
725       break;
726
727     case G_IO_WIN32_FILE_DESC:
728       if (channel->debug)
729         g_print (" FD thread=%#x buffer_condition:{%s}"
730                  "\n  watch->pollfd.events:{%s} watch->pollfd.revents:{%s} channel->revents:{%s}",
731                  channel->thread_id, condition_to_string (buffer_condition),
732                  condition_to_string (watch->pollfd.events),
733                  condition_to_string (watch->pollfd.revents),
734                  condition_to_string (channel->revents));
735       
736       EnterCriticalSection (&channel->mutex);
737       if (channel->running)
738         {
739           if (channel->direction == 0 && channel->wrp == channel->rdp)
740             {
741               if (channel->debug)
742                 g_print ("\n  setting revents=0");
743               channel->revents = 0;
744             }
745         }
746       else
747         {
748           if (channel->direction == 1
749               && (channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
750             {
751               if (channel->debug)
752                 g_print ("\n setting revents=0");
753               channel->revents = 0;
754             }
755         }         
756       LeaveCriticalSection (&channel->mutex);
757       break;
758
759     case G_IO_WIN32_SOCKET:
760       if (channel->debug)
761         g_print (" SOCK");
762       event_mask = 0;
763       if (watch->condition & G_IO_IN)
764         event_mask |= (FD_READ | FD_ACCEPT);
765       if (watch->condition & G_IO_OUT)
766         event_mask |= (FD_WRITE | FD_CONNECT);
767       event_mask |= FD_CLOSE;
768
769       if (channel->event_mask != event_mask)
770         {
771           if (channel->debug)
772             g_print ("\n  WSAEventSelect(%d,%p,{%s})",
773                      channel->fd, (HANDLE) watch->pollfd.fd,
774                      event_mask_to_string (event_mask));
775           if (WSAEventSelect (channel->fd, (HANDLE) watch->pollfd.fd,
776                               event_mask) == SOCKET_ERROR)
777             if (channel->debug)
778               {
779                 gchar *emsg = g_win32_error_message (WSAGetLastError ());
780
781                 g_print (" failed: %s", emsg);
782                 g_free (emsg);
783               }
784           channel->event_mask = event_mask;
785
786           if (channel->debug)
787             g_print ("\n  setting last_events=0");
788           channel->last_events = 0;
789
790           if ((event_mask & FD_WRITE) &&
791               channel->ever_writable &&
792               !channel->write_would_have_blocked)
793             {
794               if (channel->debug)
795                 g_print (" WSASetEvent(%p)", (WSAEVENT) watch->pollfd.fd);
796               WSASetEvent ((WSAEVENT) watch->pollfd.fd);
797             }
798         }
799       break;
800
801     default:
802       g_assert_not_reached ();
803       abort ();
804     }
805   if (channel->debug)
806     g_print ("\n");
807
808   return ((watch->condition & buffer_condition) == watch->condition);
809 }
810
811 static gboolean
812 g_io_win32_check (GSource *source)
813 {
814   MSG msg;
815   GIOWin32Watch *watch = (GIOWin32Watch *)source;
816   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
817   GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
818   WSANETWORKEVENTS events;
819
820   if (channel->debug)
821     g_print ("g_io_win32_check: source=%p channel=%p", source, channel);
822
823   switch (channel->type)
824     {
825     case G_IO_WIN32_WINDOWS_MESSAGES:
826       if (channel->debug)
827         g_print (" MSG\n");
828       return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE));
829
830     case G_IO_WIN32_FILE_DESC:
831       if (channel->debug)
832         g_print (" FD thread=%#x buffer_condition=%s\n"
833                  "  watch->pollfd.events={%s} watch->pollfd.revents={%s} channel->revents={%s}\n",
834                  channel->thread_id, condition_to_string (buffer_condition),
835                  condition_to_string (watch->pollfd.events),
836                  condition_to_string (watch->pollfd.revents),
837                  condition_to_string (channel->revents));
838       
839       watch->pollfd.revents = (watch->pollfd.events & channel->revents);
840
841       return ((watch->pollfd.revents | buffer_condition) & watch->condition);
842
843     case G_IO_WIN32_CONSOLE:
844       if (channel->debug)
845         g_print (" CON\n");
846       if (watch->channel->is_writeable)
847         return TRUE;
848       else if (watch->channel->is_readable)
849         {
850           INPUT_RECORD buffer;
851           DWORD n;
852           if (PeekConsoleInput ((HANDLE) watch->pollfd.fd, &buffer, 1, &n) &&
853               n == 1)
854             {
855               /* _kbhit() does quite complex processing to find out
856                * whether at least one of the key events pending corresponds
857                * to a "real" character that can be read.
858                */
859               if (_kbhit ())
860                 return TRUE;
861               
862               /* Discard all other kinds of events */
863               ReadConsoleInput ((HANDLE) watch->pollfd.fd, &buffer, 1, &n);
864             }
865         }
866       return FALSE;
867
868     case G_IO_WIN32_SOCKET:
869       if (channel->debug)
870         g_print (" SOCK");
871       if (channel->last_events & FD_WRITE)
872         {
873           if (channel->debug)
874             g_print (" sock=%d event=%p last_events has FD_WRITE",
875                      channel->fd, (HANDLE) watch->pollfd.fd);
876         }
877       else
878         {
879           WSAEnumNetworkEvents (channel->fd, 0, &events);
880
881           if (channel->debug)
882             g_print ("\n  revents={%s} condition={%s}"
883                      "\n  WSAEnumNetworkEvents(%d,0) sets events={%s}",
884                      condition_to_string (watch->pollfd.revents),
885                      condition_to_string (watch->condition),
886                      channel->fd, 
887                      event_mask_to_string (events.lNetworkEvents));
888           
889           if (watch->pollfd.revents != 0 &&
890               events.lNetworkEvents == 0 &&
891               !(channel->event_mask & FD_WRITE))
892             {
893               channel->event_mask = 0;
894               if (channel->debug)
895                 g_print ("\n  WSAEventSelect(%d,%p,{})",
896                          channel->fd, (HANDLE) watch->pollfd.fd);
897               WSAEventSelect (channel->fd, (HANDLE) watch->pollfd.fd, 0);
898               if (channel->debug)
899                 g_print ("  ResetEvent(%p)",
900                          (HANDLE) watch->pollfd.fd);
901               ResetEvent ((HANDLE) watch->pollfd.fd);
902             }
903           else if (events.lNetworkEvents & FD_WRITE)
904             channel->ever_writable = TRUE;
905           channel->last_events = events.lNetworkEvents;
906         }
907
908       watch->pollfd.revents = 0;
909       if (channel->last_events & (FD_READ | FD_ACCEPT))
910         watch->pollfd.revents |= G_IO_IN;
911
912       if (channel->last_events & FD_WRITE)
913         watch->pollfd.revents |= G_IO_OUT;
914       else
915         {
916           /* We have called WSAEnumNetworkEvents() above but it didn't
917            * set FD_WRITE.
918            */
919           if (events.lNetworkEvents & FD_CONNECT)
920             {
921               if (events.iErrorCode[FD_CONNECT_BIT] == 0)
922                 watch->pollfd.revents |= G_IO_OUT;
923               else
924                 watch->pollfd.revents |= (G_IO_HUP | G_IO_ERR);
925             }
926           if (watch->pollfd.revents == 0 && (channel->last_events & (FD_CLOSE)))
927             watch->pollfd.revents |= G_IO_HUP;
928         }
929
930       /* Regardless of WSAEnumNetworkEvents() result, if watching for
931        * writability, and if we have ever got a FD_WRITE event, and
932        * unless last write would have blocked, set G_IO_OUT. But never
933        * set both G_IO_OUT and G_IO_HUP.
934        */
935       if (!(watch->pollfd.revents & G_IO_HUP) &&
936           channel->ever_writable &&
937           !channel->write_would_have_blocked &&
938           (channel->event_mask & FD_WRITE))
939         watch->pollfd.revents |= G_IO_OUT;
940
941       if (channel->debug)
942         g_print ("\n  revents={%s} retval={%s}\n",
943                  condition_to_string (watch->pollfd.revents),
944                  condition_to_string ((watch->pollfd.revents | buffer_condition) & watch->condition));
945
946       return ((watch->pollfd.revents | buffer_condition) & watch->condition);
947
948     default:
949       g_assert_not_reached ();
950       abort ();
951     }
952 }
953
954 static gboolean
955 g_io_win32_dispatch (GSource     *source,
956                      GSourceFunc  callback,
957                      gpointer     user_data)
958 {
959   GIOFunc func = (GIOFunc)callback;
960   GIOWin32Watch *watch = (GIOWin32Watch *)source;
961   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
962   GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
963   
964   if (!func)
965     {
966       g_warning ("IO Watch dispatched without callback\n"
967                  "You must call g_source_connect().");
968       return FALSE;
969     }
970   
971   if (channel->debug)
972     g_print ("g_io_win32_dispatch: pollfd.revents=%s condition=%s result=%s\n",
973              condition_to_string (watch->pollfd.revents),
974              condition_to_string (watch->condition),
975              condition_to_string ((watch->pollfd.revents | buffer_condition) & watch->condition));
976
977   return (*func) (watch->channel,
978                   (watch->pollfd.revents | buffer_condition) & watch->condition,
979                   user_data);
980 }
981
982 static void
983 g_io_win32_finalize (GSource *source)
984 {
985   GIOWin32Watch *watch = (GIOWin32Watch *)source;
986   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
987   
988   if (channel->debug)
989     g_print ("g_io_win32_finalize: source=%p channel=%p", source, channel);
990
991   switch (channel->type)
992     {
993     case G_IO_WIN32_WINDOWS_MESSAGES:
994       if (channel->debug)
995         g_print (" MSG");
996       break;
997
998     case G_IO_WIN32_CONSOLE:
999       if (channel->debug)
1000         g_print (" CON");
1001       break;
1002
1003     case G_IO_WIN32_FILE_DESC:
1004       if (channel->debug)
1005         g_print (" FD thread=%#x", channel->thread_id);
1006       break;
1007
1008     case G_IO_WIN32_SOCKET:
1009       if (channel->debug)
1010         g_print (" SOCK sock=%d", channel->fd);
1011       break;
1012
1013     default:
1014       g_assert_not_reached ();
1015       abort ();
1016     }
1017   if (channel->debug)
1018     g_print ("\n");
1019   g_io_channel_unref (watch->channel);
1020 }
1021
1022 GSourceFuncs g_io_watch_funcs = {
1023   g_io_win32_prepare,
1024   g_io_win32_check,
1025   g_io_win32_dispatch,
1026   g_io_win32_finalize
1027 };
1028
1029 static GIOStatus
1030 g_io_win32_msg_read (GIOChannel *channel,
1031                      gchar      *buf,
1032                      gsize       count,
1033                      gsize      *bytes_read,
1034                      GError    **err)
1035 {
1036   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1037   MSG msg;               /* In case of alignment problems */
1038   
1039   if (count < sizeof (MSG))
1040     {
1041       g_set_error_literal (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
1042                            "Incorrect message size"); /* Informative enough error message? */
1043       return G_IO_STATUS_ERROR;
1044     }
1045   
1046   if (win32_channel->debug)
1047     g_print ("g_io_win32_msg_read: channel=%p hwnd=%p\n",
1048              channel, win32_channel->hwnd);
1049   if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
1050     return G_IO_STATUS_AGAIN;
1051
1052   memmove (buf, &msg, sizeof (MSG));
1053   *bytes_read = sizeof (MSG);
1054
1055   return G_IO_STATUS_NORMAL;
1056 }
1057
1058 static GIOStatus
1059 g_io_win32_msg_write (GIOChannel  *channel,
1060                       const gchar *buf,
1061                       gsize        count,
1062                       gsize       *bytes_written,
1063                       GError     **err)
1064 {
1065   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1066   MSG msg;
1067   
1068   if (count != sizeof (MSG))
1069     {
1070       g_set_error_literal (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
1071                            "Incorrect message size"); /* Informative enough error message? */
1072       return G_IO_STATUS_ERROR;
1073     }
1074   
1075   /* In case of alignment problems */
1076   memmove (&msg, buf, sizeof (MSG));
1077   if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
1078     {
1079       gchar *emsg = g_win32_error_message (GetLastError ());
1080
1081       g_set_error_literal (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED, emsg);
1082       g_free (emsg);
1083
1084       return G_IO_STATUS_ERROR;
1085     }
1086
1087   *bytes_written = sizeof (MSG);
1088
1089   return G_IO_STATUS_NORMAL;
1090 }
1091
1092 static GIOStatus
1093 g_io_win32_msg_close (GIOChannel *channel,
1094                       GError    **err)
1095 {
1096   /* Nothing to be done. Or should we set hwnd to some invalid value? */
1097
1098   return G_IO_STATUS_NORMAL;
1099 }
1100
1101 static void
1102 g_io_win32_free (GIOChannel *channel)
1103 {
1104   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1105   
1106   if (win32_channel->debug)
1107     g_print ("g_io_win32_free channel=%p fd=%d\n", channel, win32_channel->fd);
1108
1109   DeleteCriticalSection (&win32_channel->mutex);
1110
1111   if (win32_channel->data_avail_event)
1112     if (!CloseHandle (win32_channel->data_avail_event))
1113       if (win32_channel->debug)
1114         {
1115           gchar *emsg = g_win32_error_message (GetLastError ());
1116
1117           g_print ("  CloseHandle(%p) failed: %s\n",
1118                    win32_channel->data_avail_event, emsg);
1119           g_free (emsg);
1120         }
1121
1122   g_free (win32_channel->buffer);
1123
1124   if (win32_channel->space_avail_event)
1125     if (!CloseHandle (win32_channel->space_avail_event))
1126       if (win32_channel->debug)
1127         {
1128           gchar *emsg = g_win32_error_message (GetLastError ());
1129
1130           g_print ("  CloseHandle(%p) failed: %s\n",
1131                    win32_channel->space_avail_event, emsg);
1132           g_free (emsg);
1133         }
1134
1135   if (win32_channel->type == G_IO_WIN32_SOCKET &&
1136       win32_channel->fd != -1)
1137     if (WSAEventSelect (win32_channel->fd, NULL, 0) == SOCKET_ERROR)
1138       if (win32_channel->debug)
1139         {
1140           gchar *emsg = g_win32_error_message (WSAGetLastError ());
1141
1142           g_print ("  WSAEventSelect(%d,NULL,{}) failed: %s\n",
1143                    win32_channel->fd, emsg);
1144           g_free (emsg);
1145         }
1146
1147   if (win32_channel->event)
1148     if (!WSACloseEvent (win32_channel->event))
1149       if (win32_channel->debug)
1150         {
1151           gchar *emsg = g_win32_error_message (WSAGetLastError ());
1152
1153           g_print ("  WSACloseEvent(%p) failed: %s\n",
1154                    win32_channel->event, emsg);
1155           g_free (emsg);
1156         }
1157
1158   g_free (win32_channel);
1159 }
1160
1161 static GSource *
1162 g_io_win32_msg_create_watch (GIOChannel   *channel,
1163                              GIOCondition  condition)
1164 {
1165   GIOWin32Watch *watch;
1166   GSource *source;
1167
1168   source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
1169   g_source_set_name (source, "GIOChannel (Win32)");
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