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