55de7fe4667588deff4996ec469e48b3821da9fb
[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 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 /* Define this to get (very) verbose logging of all channels */
33 /* #define G_IO_WIN32_DEBUG */
34
35 #include "glib.h"
36
37 #include <stdlib.h>
38 #include <windows.h>
39 #include <winsock.h>          /* Not everybody has winsock2 */
40 #include <fcntl.h>
41 #include <io.h>
42 #include <process.h>
43 #include <errno.h>
44 #include <sys/stat.h>
45
46 #include "glibintl.h"
47
48 typedef struct _GIOWin32Channel GIOWin32Channel;
49 typedef struct _GIOWin32Watch GIOWin32Watch;
50
51 #define BUFFER_SIZE 4096
52
53 typedef enum {
54   G_IO_WIN32_WINDOWS_MESSAGES,  /* Windows messages */
55   G_IO_WIN32_FILE_DESC,         /* Unix-like file descriptors from
56                                  * _open() or _pipe(). Read with read().
57                                  * Have to create separate thread to read.
58                                  */
59   G_IO_WIN32_SOCKET             /* Sockets. A separate thread is blocked
60                                  * in select() most of the time.
61                                  */
62 } GIOWin32ChannelType;
63
64 struct _GIOWin32Channel {
65   GIOChannel channel;
66   gint fd;                      /* Either a Unix-like file handle as provided
67                                  * by the Microsoft C runtime, or a SOCKET
68                                  * as provided by WinSock.
69                                  */
70   GIOWin32ChannelType type;
71   
72   gboolean debug;
73
74   CRITICAL_SECTION mutex;
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 both fd and socket channels. */
80   gboolean running;             /* Is reader thread running. FALSE if
81                                  * EOF has been reached.
82                                  */
83   gboolean needs_close;         /* If the channel has been closed while
84                                  * the reader thread was still running.
85                                  */
86   guint thread_id;              /* If non-NULL has a reader thread, or has
87                                  * had.*/
88   HANDLE thread_handle;
89   HANDLE data_avail_event;
90
91   gushort revents;
92
93   /* Following fields used by fd channels for input */
94   
95   /* Data is kept in a circular buffer. To be able to distinguish between
96    * empty and full buffer, we cannot fill it completely, but have to
97    * leave a one character gap.
98    *
99    * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
100    *
101    * Empty:    wrp == rdp
102    * Full:     (wrp + 1) % BUFFER_SIZE == rdp
103    * Partial:  otherwise
104    */
105   guchar *buffer;               /* (Circular) buffer */
106   gint wrp, rdp;                /* Buffer indices for writing and reading */
107   HANDLE space_avail_event;
108
109   /* Following fields used by socket channels */
110   GSList *watches;
111   HANDLE data_avail_noticed_event;
112 };
113
114 #define LOCK(mutex) EnterCriticalSection (&mutex)
115 #define UNLOCK(mutex) LeaveCriticalSection (&mutex)
116
117 struct _GIOWin32Watch {
118   GSource       source;
119   GPollFD       pollfd;
120   GIOChannel   *channel;
121   GIOCondition  condition;
122   GIOFunc       callback;
123 };
124
125 static void
126 g_win32_print_access_mode (int flags)
127 {
128   g_print ("%s%s%s%s%s%s%s%s%s%s",
129            ((flags & 0x3) == _O_RDWR ? "O_RDWR" :
130             ((flags & 0x3) == _O_RDONLY ? "O_RDONLY" :
131              ((flags & 0x3) == _O_WRONLY ? "O_WRONLY" : "0"))),
132            (flags & _O_APPEND ? "|O_APPEND" : ""),
133            (flags & _O_RANDOM ? "|O_RANDOM" : ""),
134            (flags & _O_SEQUENTIAL ? "|O_SEQUENTIAL" : ""),
135            (flags & _O_TEMPORARY ? "|O_TEMPORARY" : ""),
136            (flags & _O_CREAT ? "|O_CREAT" : ""),
137            (flags & _O_TRUNC ? "|O_TRUNC" : ""),
138            (flags & _O_EXCL ? "|O_EXCL" : ""),
139            (flags & _O_TEXT ? "|O_TEXT" : ""),
140            (flags & _O_BINARY ? "|O_BINARY" : ""));
141 }
142
143 static void
144 g_win32_print_gioflags (GIOFlags flags)
145 {
146   char *bar = "";
147
148   if (flags & G_IO_FLAG_APPEND)
149     bar = "|", g_print ("APPEND");
150   if (flags & G_IO_FLAG_NONBLOCK)
151     g_print ("%sNONBLOCK", bar), bar = "|";
152   if (flags & G_IO_FLAG_IS_READABLE)
153     g_print ("%sREADABLE", bar), bar = "|";
154   if (flags & G_IO_FLAG_IS_WRITEABLE)
155     g_print ("%sWRITEABLE", bar), bar = "|";
156   if (flags & G_IO_FLAG_IS_WRITEABLE)
157     g_print ("%sWRITEABLE", bar), bar = "|";
158   if (flags & G_IO_FLAG_IS_SEEKABLE)
159     g_print ("%sSEEKABLE", bar), bar = "|";
160 }
161
162 static gboolean
163 g_io_win32_get_debug_flag (void)
164 {
165 #ifdef G_IO_WIN32_DEBUG
166   return TRUE;
167 #else
168   if (getenv ("G_IO_WIN32_DEBUG") != NULL)
169     return TRUE;
170   else
171     return FALSE;
172 #endif
173 }  
174
175 static void
176 g_io_channel_win32_init (GIOWin32Channel *channel)
177 {
178   channel->debug = g_io_win32_get_debug_flag ();
179   channel->buffer = NULL;
180   channel->running = FALSE;
181   channel->needs_close = FALSE;
182   channel->thread_id = 0;
183   channel->data_avail_event = NULL;
184   channel->revents = 0;
185   channel->space_avail_event = NULL;
186   channel->data_avail_noticed_event = NULL;
187   channel->watches = NULL;
188   InitializeCriticalSection (&channel->mutex);
189 }
190
191 static void
192 create_events (GIOWin32Channel *channel)
193 {
194   SECURITY_ATTRIBUTES sec_attrs;
195   
196   sec_attrs.nLength = sizeof (SECURITY_ATTRIBUTES);
197   sec_attrs.lpSecurityDescriptor = NULL;
198   sec_attrs.bInheritHandle = FALSE;
199
200   /* The data available event is manual reset, the space available event
201    * is automatic reset.
202    */
203   if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
204       || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL))
205       || !(channel->data_avail_noticed_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
206     {
207       gchar *emsg = g_win32_error_message (GetLastError ());
208       g_error ("Error creating event: %s", emsg);
209       g_free (emsg);
210     }
211 }
212
213 static unsigned __stdcall
214 read_thread (void *parameter)
215 {
216   GIOWin32Channel *channel = parameter;
217   guchar *buffer;
218   guint nbytes;
219
220   g_io_channel_ref ((GIOChannel *)channel);
221
222   if (channel->debug)
223     g_print ("read_thread %#x: start fd:%d, data_avail:%#x, space_avail:%#x\n",
224              channel->thread_id,
225              channel->fd,
226              (guint) channel->data_avail_event,
227              (guint) channel->space_avail_event);
228   
229   channel->buffer = g_malloc (BUFFER_SIZE);
230   channel->rdp = channel->wrp = 0;
231   channel->running = TRUE;
232
233   SetEvent (channel->space_avail_event);
234   
235   while (channel->running)
236     {
237       LOCK (channel->mutex);
238       if (channel->debug)
239         g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
240                  channel->thread_id, channel->rdp, channel->wrp);
241       if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
242         {
243           /* Buffer is full */
244           if (channel->debug)
245             g_print ("read_thread %#x: resetting space_avail\n",
246                      channel->thread_id);
247           ResetEvent (channel->space_avail_event);
248           if (channel->debug)
249             g_print ("read_thread %#x: waiting for space\n",
250                      channel->thread_id);
251           UNLOCK (channel->mutex);
252           WaitForSingleObject (channel->space_avail_event, INFINITE);
253           LOCK (channel->mutex);
254           if (channel->debug)
255             g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
256                      channel->thread_id, channel->rdp, channel->wrp);
257         }
258       
259       buffer = channel->buffer + channel->wrp;
260       
261       /* Always leave at least one byte unused gap to be able to
262        * distinguish between the full and empty condition...
263        */
264       nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
265                     BUFFER_SIZE - channel->wrp);
266
267       if (channel->debug)
268         g_print ("read_thread %#x: calling read() for %d bytes\n",
269                  channel->thread_id, nbytes);
270
271       UNLOCK (channel->mutex);
272
273       nbytes = read (channel->fd, buffer, nbytes);
274       
275       LOCK (channel->mutex);
276
277       channel->revents = G_IO_IN;
278       if (nbytes == 0)
279         channel->revents |= G_IO_HUP;
280       else if (nbytes < 0)
281         channel->revents |= G_IO_ERR;
282
283       if (channel->debug)
284         g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
285                  channel->thread_id, nbytes, channel->rdp, channel->wrp);
286
287       if (nbytes <= 0)
288         break;
289
290       channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
291       if (channel->debug)
292         g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
293                  channel->thread_id, channel->rdp, channel->wrp);
294       SetEvent (channel->data_avail_event);
295       UNLOCK (channel->mutex);
296     }
297   
298   channel->running = FALSE;
299   if (channel->needs_close)
300     {
301       if (channel->debug)
302         g_print ("read_thread %#x: channel fd %d needs closing\n",
303                  channel->thread_id, channel->fd);
304       close (channel->fd);
305       channel->fd = -1;
306     }
307
308   if (channel->debug)
309     g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
310              channel->thread_id, channel->rdp, channel->wrp);
311   SetEvent (channel->data_avail_event);
312   UNLOCK (channel->mutex);
313   
314   g_io_channel_unref((GIOChannel *)channel);
315   
316   /* No need to call _endthreadex(), the actual thread starter routine
317    * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
318    * _endthreadex() for us.
319    */
320
321   CloseHandle (channel->thread_handle);
322
323   return 0;
324 }
325
326 static void
327 create_thread (GIOWin32Channel     *channel,
328                GIOCondition         condition,
329                unsigned (__stdcall *thread) (void *parameter))
330 {
331   channel->thread_handle =
332     (HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
333                              &channel->thread_id);
334   if (channel->thread_handle == 0)
335     g_warning (G_STRLOC ": Error creating reader thread: %s",
336                strerror (errno));
337   WaitForSingleObject (channel->space_avail_event, INFINITE);
338 }
339
340 static GIOStatus
341 buffer_read (GIOWin32Channel *channel,
342              guchar          *dest,
343              gsize            count,
344              gsize           *bytes_read,
345              GError         **err)
346 {
347   guint nbytes;
348   guint left = count;
349   
350   LOCK (channel->mutex);
351   if (channel->debug)
352     g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
353              channel->thread_id, count, channel->rdp, channel->wrp);
354   
355   if (channel->wrp == channel->rdp)
356     {
357       UNLOCK (channel->mutex);
358       if (channel->debug)
359         g_print ("waiting for data from thread %#x\n", channel->thread_id);
360       WaitForSingleObject (channel->data_avail_event, INFINITE);
361       if (channel->debug)
362         g_print ("done waiting for data from thread %#x\n", channel->thread_id);
363       LOCK (channel->mutex);
364       if (channel->wrp == channel->rdp && !channel->running)
365         {
366           UNLOCK (channel->mutex);
367           *bytes_read = 0;
368           return G_IO_STATUS_NORMAL; /* as before, normal case ? */
369         }
370     }
371   
372   if (channel->rdp < channel->wrp)
373     nbytes = channel->wrp - channel->rdp;
374   else
375     nbytes = BUFFER_SIZE - channel->rdp;
376   UNLOCK (channel->mutex);
377   nbytes = MIN (left, nbytes);
378   if (channel->debug)
379     g_print ("moving %d bytes from thread %#x\n",
380              nbytes, channel->thread_id);
381   memcpy (dest, channel->buffer + channel->rdp, nbytes);
382   dest += nbytes;
383   left -= nbytes;
384   LOCK (channel->mutex);
385   channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
386   if (channel->debug)
387     g_print ("setting space_avail for thread %#x\n", channel->thread_id);
388   SetEvent (channel->space_avail_event);
389   if (channel->debug)
390     g_print ("for thread %#x: rdp=%d, wrp=%d\n",
391              channel->thread_id, channel->rdp, channel->wrp);
392   if (channel->running && channel->wrp == channel->rdp)
393     {
394       if (channel->debug)
395         g_print ("resetting data_avail of thread %#x\n",
396                  channel->thread_id);
397       ResetEvent (channel->data_avail_event);
398     };
399   UNLOCK (channel->mutex);
400   
401   /* We have no way to indicate any errors form the actual
402    * read() or recv() call in the reader thread. Should we have?
403    */
404   *bytes_read = count - left;
405   return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
406 }
407
408 static unsigned __stdcall
409 select_thread (void *parameter)
410 {
411   GIOWin32Channel *channel = parameter;
412   fd_set read_fds, write_fds, except_fds;
413   GSList *tmp;
414   int n;
415
416   g_io_channel_ref ((GIOChannel *)channel);
417
418   if (channel->debug)
419     g_print ("select_thread %#x: start fd:%d,\n\tdata_avail:%#x, data_avail_noticed:%#x\n",
420              channel->thread_id,
421              channel->fd,
422              (guint) channel->data_avail_event,
423              (guint) channel->data_avail_noticed_event);
424   
425   channel->rdp = channel->wrp = 0;
426   channel->running = TRUE;
427
428   SetEvent (channel->space_avail_event);
429   
430   while (channel->running)
431     {
432       FD_ZERO (&read_fds);
433       FD_ZERO (&write_fds);
434       FD_ZERO (&except_fds);
435
436       tmp = channel->watches;
437       while (tmp)
438         {
439           GIOWin32Watch *watch = (GIOWin32Watch *)tmp->data;
440
441           if (watch->condition & (G_IO_IN | G_IO_HUP))
442             FD_SET (channel->fd, &read_fds);
443           if (watch->condition & G_IO_OUT)
444             FD_SET (channel->fd, &write_fds);
445           if (watch->condition & G_IO_ERR)
446             FD_SET (channel->fd, &except_fds);
447           
448           tmp = tmp->next;
449         }
450       if (channel->debug)
451         g_print ("select_thread %#x: calling select() for%s%s%s\n",
452                  channel->thread_id,
453                  (FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
454                  (FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
455                  (FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
456
457       n = select (1, &read_fds, &write_fds, &except_fds, NULL);
458       
459       if (n == SOCKET_ERROR)
460         {
461           if (channel->debug)
462             g_print ("select_thread %#x: select returned SOCKET_ERROR\n",
463                      channel->thread_id);
464           break;
465         }
466
467       if (channel->debug)
468         g_print ("select_thread %#x: got%s%s%s\n",
469                  channel->thread_id,
470                  (FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
471                  (FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
472                  (FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
473
474       if (FD_ISSET (channel->fd, &read_fds))
475         channel->revents |= G_IO_IN;
476       if (FD_ISSET (channel->fd, &write_fds))
477         channel->revents |= G_IO_OUT;
478       if (FD_ISSET (channel->fd, &except_fds))
479         channel->revents |= G_IO_ERR;
480
481       if (channel->debug)
482         g_print ("select_thread %#x: resetting data_avail_noticed,\n"
483                  "\tsetting data_avail\n",
484                  channel->thread_id);
485       ResetEvent (channel->data_avail_noticed_event);
486       SetEvent (channel->data_avail_event);
487
488       LOCK (channel->mutex);
489       if (channel->needs_close)
490         {
491           UNLOCK (channel->mutex);
492           break;
493         }
494       UNLOCK (channel->mutex);
495
496       if (channel->debug)
497         g_print ("select_thread %#x: waiting for data_avail_noticed\n",
498                  channel->thread_id);
499
500       WaitForSingleObject (channel->data_avail_noticed_event, INFINITE);
501       if (channel->debug)
502         g_print ("select_thread %#x: got data_avail_noticed\n",
503                  channel->thread_id);
504     }
505   
506   channel->running = FALSE;
507   LOCK (channel->mutex);
508   if (channel->fd != -1)
509     {
510       /* DO NOT close the fd here */
511       channel->fd = -1;
512     }
513
514   if (channel->debug)
515     g_print ("select_thread %#x: got error, setting data_avail\n",
516              channel->thread_id);
517   SetEvent (channel->data_avail_event);
518   UNLOCK (channel->mutex);
519   
520   g_io_channel_unref((GIOChannel *)channel);
521   
522   /* No need to call _endthreadex(), the actual thread starter routine
523    * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
524    * _endthreadex() for us.
525    */
526
527   CloseHandle (channel->thread_handle);
528
529   return 0;
530 }
531
532 static gboolean
533 g_io_win32_prepare (GSource *source,
534                     gint    *timeout)
535 {
536   GIOWin32Watch *watch = (GIOWin32Watch *)source;
537   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
538   
539   *timeout = -1;
540   
541   if (channel->type == G_IO_WIN32_FILE_DESC)
542     {
543       LOCK (channel->mutex);
544       if (channel->running && channel->wrp == channel->rdp)
545         channel->revents = 0;
546       UNLOCK (channel->mutex);
547     }
548   else if (channel->type == G_IO_WIN32_SOCKET)
549     {
550       channel->revents = 0;
551
552       if (channel->debug)
553         g_print ("g_io_win32_prepare: thread %#x, setting data_avail_noticed\n",
554                  channel->thread_id);
555       SetEvent (channel->data_avail_noticed_event);
556       if (channel->debug)
557         g_print ("g_io_win32_prepare: thread %#x, there.\n",
558                  channel->thread_id);
559     }
560
561   return FALSE;
562   /* XXX: why should we want to do this ? */
563   watch->condition = g_io_channel_get_buffer_condition (watch->channel);
564
565   return (watch->pollfd.revents & (G_IO_IN | G_IO_OUT)) == watch->condition;
566 }
567
568 static gboolean
569 g_io_win32_check (GSource *source)
570 {
571   MSG msg;
572   GIOWin32Watch *watch = (GIOWin32Watch *)source;
573   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
574   GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
575
576   if (channel->debug)
577     g_print ("g_io_win32_check: for thread %#x:\n"
578              "\twatch->pollfd.events:%#x, watch->pollfd.revents:%#x, channel->revents:%#x\n",
579              channel->thread_id,
580              watch->pollfd.events, watch->pollfd.revents, channel->revents);
581
582   if (channel->type != G_IO_WIN32_WINDOWS_MESSAGES)
583     {
584       watch->pollfd.revents = (watch->pollfd.events & channel->revents);
585     }
586   else
587     {
588       return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE));
589     }
590   
591   if (channel->type == G_IO_WIN32_SOCKET)
592     {
593       if (channel->debug)
594         g_print ("g_io_win32_check: thread %#x, resetting data_avail\n",
595                  channel->thread_id);
596       ResetEvent (channel->data_avail_event);
597       if (channel->debug)
598         g_print ("g_io_win32_check: thread %#x, there.\n",
599                  channel->thread_id);
600     }
601
602   return (watch->pollfd.revents & watch->condition);
603 }
604
605 static gboolean
606 g_io_win32_dispatch (GSource     *source,
607                      GSourceFunc  callback,
608                      gpointer     user_data)
609 {
610   GIOFunc func = (GIOFunc)callback;
611   GIOWin32Watch *watch = (GIOWin32Watch *)source;
612   
613   if (!func)
614     {
615       g_warning (G_STRLOC ": GIOWin32Watch dispatched without callback\n"
616                  "You must call g_source_connect().");
617       return FALSE;
618     }
619   
620   return (*func) (watch->channel,
621                   watch->pollfd.revents & watch->condition,
622                   user_data);
623 }
624
625 static void
626 g_io_win32_finalize (GSource *source)
627 {
628   GIOWin32Watch *watch = (GIOWin32Watch *)source;
629   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
630   
631   if (channel->debug)
632     g_print ("g_io_win32_finalize: channel with thread %#x\n",
633              channel->thread_id);
634
635   channel->watches = g_slist_remove (channel->watches, watch);
636
637   SetEvent (channel->data_avail_noticed_event);
638   g_io_channel_unref (watch->channel);
639 }
640
641 #if defined(G_PLATFORM_WIN32) && defined(__GNUC__)
642 __declspec(dllexport)
643 #endif
644 GSourceFuncs g_io_watch_funcs = {
645   g_io_win32_prepare,
646   g_io_win32_check,
647   g_io_win32_dispatch,
648   g_io_win32_finalize
649 };
650
651 static GSource *
652 g_io_win32_create_watch (GIOChannel    *channel,
653                          GIOCondition   condition,
654                          unsigned (__stdcall *thread) (void *parameter))
655 {
656   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
657   GIOWin32Watch *watch;
658   GSource *source;
659
660   source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
661   watch = (GIOWin32Watch *)source;
662   
663   watch->channel = channel;
664   g_io_channel_ref (channel);
665   
666   watch->condition = condition;
667   
668   if (win32_channel->data_avail_event == NULL)
669     create_events (win32_channel);
670
671   watch->pollfd.fd = (gint) win32_channel->data_avail_event;
672   watch->pollfd.events = condition;
673   
674   if (win32_channel->debug)
675     g_print ("g_io_win32_create_watch: fd:%d condition:%#x handle:%#x\n",
676              win32_channel->fd, condition, watch->pollfd.fd);
677   
678   win32_channel->watches = g_slist_append (win32_channel->watches, watch);
679
680   if (win32_channel->thread_id == 0)
681     create_thread (win32_channel, condition, thread);
682
683   g_source_add_poll (source, &watch->pollfd);
684   
685   return source;
686 }
687
688 static GIOStatus
689 g_io_win32_msg_read (GIOChannel *channel,
690                      gchar      *buf,
691                      gsize       count,
692                      gsize      *bytes_read,
693                      GError    **err)
694 {
695   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
696   MSG msg;               /* In case of alignment problems */
697   
698   if (count < sizeof (MSG))
699     {
700       g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
701         _("Incorrect message size")); /* Informative enough error message? */
702       return G_IO_STATUS_ERROR;
703     }
704   
705   if (win32_channel->debug)
706     g_print ("g_io_win32_msg_read: for %#x\n",
707              (guint) win32_channel->hwnd);
708   if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
709     return G_IO_STATUS_AGAIN;
710
711   memmove (buf, &msg, sizeof (MSG));
712   *bytes_read = sizeof (MSG);
713
714   return G_IO_STATUS_NORMAL;
715 }
716
717 static GIOStatus
718 g_io_win32_msg_write (GIOChannel  *channel,
719                       const gchar *buf,
720                       gsize        count,
721                       gsize       *bytes_written,
722                       GError     **err)
723 {
724   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
725   MSG msg;
726   
727   if (count != sizeof (MSG))
728     {
729       g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
730         _("Incorrect message size")); /* Informative enough error message? */
731       return G_IO_STATUS_ERROR;
732     }
733   
734   /* In case of alignment problems */
735   memmove (&msg, buf, sizeof (MSG));
736   if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
737     {
738       gchar *emsg = g_win32_error_message (GetLastError ());
739       g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED, emsg);
740       g_free (emsg);
741       return G_IO_STATUS_ERROR;
742     }
743
744   *bytes_written = sizeof (MSG);
745
746   return G_IO_STATUS_NORMAL;
747 }
748
749 static GIOStatus
750 g_io_win32_no_seek (GIOChannel *channel,
751                     glong       offset,
752                     GSeekType   type,
753                     GError     **err)
754 {
755   g_assert_not_reached ();
756
757   return G_IO_STATUS_ERROR;
758 }
759
760 static GIOStatus
761 g_io_win32_msg_close (GIOChannel *channel,
762                       GError    **err)
763 {
764   /* Nothing to be done. Or should we set hwnd to some invalid value? */
765
766   return G_IO_STATUS_NORMAL;
767 }
768
769 static void
770 g_io_win32_free (GIOChannel *channel)
771 {
772   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
773   
774   if (win32_channel->debug)
775     g_print ("thread %#x: freeing channel, fd: %d\n",
776              win32_channel->thread_id,
777              win32_channel->fd);
778
779   if (win32_channel->data_avail_event)
780     CloseHandle (win32_channel->data_avail_event);
781   if (win32_channel->space_avail_event)
782     CloseHandle (win32_channel->space_avail_event);
783   if (win32_channel->data_avail_noticed_event)
784     CloseHandle (win32_channel->data_avail_noticed_event);
785   DeleteCriticalSection (&win32_channel->mutex);
786
787   g_free (win32_channel->buffer);
788   g_slist_free (win32_channel->watches);
789   g_free (win32_channel);
790 }
791
792 static GSource *
793 g_io_win32_msg_create_watch (GIOChannel    *channel,
794                              GIOCondition   condition)
795 {
796   GIOWin32Watch *watch;
797   GSource *source;
798
799   source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
800   watch = (GIOWin32Watch *)source;
801   
802   watch->channel = channel;
803   g_io_channel_ref (channel);
804   
805   watch->condition = condition;
806   
807   watch->pollfd.fd = G_WIN32_MSG_HANDLE;
808   watch->pollfd.events = condition;
809   
810   g_source_add_poll (source, &watch->pollfd);
811   
812   return source;
813 }
814
815 static GIOStatus
816 g_io_win32_fd_read (GIOChannel *channel,
817                     gchar      *buf,
818                     gsize       count,
819                     gsize      *bytes_read,
820                     GError    **err)
821 {
822   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
823   gint result;
824   
825   if (win32_channel->debug)
826     g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
827              win32_channel->fd, count);
828   
829   if (win32_channel->thread_id)
830     {
831       return buffer_read (win32_channel, buf, count, bytes_read, err);
832     }
833
834   result = read (win32_channel->fd, buf, count);
835
836   if (win32_channel->debug)
837     g_print ("g_io_win32_fd_read: read() = %d\n", result);
838
839   if (result < 0)
840     {
841       *bytes_read = 0;
842
843       switch(errno)
844         {
845 #ifdef EAGAIN
846           case EAGAIN:
847             return G_IO_STATUS_AGAIN;
848 #endif
849           default:
850             g_set_error (err, G_IO_CHANNEL_ERROR,
851                          g_io_channel_error_from_errno (errno),
852                          strerror (errno));
853             return G_IO_STATUS_ERROR;
854         }
855     }
856
857   *bytes_read = result;
858
859   return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
860 }
861
862 static GIOStatus
863 g_io_win32_fd_write (GIOChannel  *channel,
864                      const gchar *buf,
865                      gsize        count,
866                      gsize       *bytes_written,
867                      GError     **err)
868 {
869   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
870   gint result;
871   
872   result = write (win32_channel->fd, buf, count);
873   if (win32_channel->debug)
874     g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
875              win32_channel->fd, count, result);
876
877   if (result < 0)
878     {
879       *bytes_written = 0;
880
881       switch(errno)
882         {
883 #ifdef EAGAIN
884           case EAGAIN:
885             return G_IO_STATUS_AGAIN;
886 #endif
887           default:
888             g_set_error (err, G_IO_CHANNEL_ERROR,
889                          g_io_channel_error_from_errno (errno),
890                          strerror (errno));
891             return G_IO_STATUS_ERROR;
892         }
893     }
894
895   *bytes_written = result;
896
897   return G_IO_STATUS_NORMAL;
898 }
899
900 static GIOStatus
901 g_io_win32_fd_seek (GIOChannel *channel,
902                     glong       offset,
903                     GSeekType   type,
904                     GError    **err)
905 {
906   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
907   int whence;
908   off_t result;
909   
910   switch (type)
911     {
912     case G_SEEK_SET:
913       whence = SEEK_SET;
914       break;
915     case G_SEEK_CUR:
916       whence = SEEK_CUR;
917       break;
918     case G_SEEK_END:
919       whence = SEEK_END;
920       break;
921     default:
922       whence = -1; /* Keep the compiler quiet */
923       g_assert_not_reached();
924     }
925   
926   result = lseek (win32_channel->fd, offset, whence);
927   
928   if (result < 0)
929     {
930       g_set_error (err, G_IO_CHANNEL_ERROR,
931                    g_io_channel_error_from_errno (errno),
932                    strerror (errno));
933       return G_IO_STATUS_ERROR;
934     }
935
936   return G_IO_STATUS_NORMAL;
937 }
938
939 static GIOStatus
940 g_io_win32_fd_close (GIOChannel *channel,
941                      GError    **err)
942 {
943   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
944   
945   if (win32_channel->debug)
946     g_print ("thread %#x: closing fd %d\n",
947              win32_channel->thread_id,
948              win32_channel->fd);
949   LOCK (win32_channel->mutex);
950   if (win32_channel->running)
951     {
952       if (win32_channel->debug)
953         g_print ("thread %#x: running, marking fd %d for later close\n",
954                  win32_channel->thread_id, win32_channel->fd);
955       win32_channel->running = FALSE;
956       win32_channel->needs_close = TRUE;
957       SetEvent (win32_channel->data_avail_event);
958     }
959   else
960     {
961       if (win32_channel->debug)
962         g_print ("closing fd %d\n", win32_channel->fd);
963       close (win32_channel->fd);
964       if (win32_channel->debug)
965         g_print ("closed fd %d, setting to -1\n",
966                  win32_channel->fd);
967       win32_channel->fd = -1;
968     }
969   UNLOCK (win32_channel->mutex);
970
971   /* FIXME error detection? */
972
973   return G_IO_STATUS_NORMAL;
974 }
975
976 static GSource *
977 g_io_win32_fd_create_watch (GIOChannel    *channel,
978                             GIOCondition   condition)
979 {
980   return g_io_win32_create_watch (channel, condition, read_thread);
981 }
982
983 static GIOStatus
984 g_io_win32_sock_read (GIOChannel *channel,
985                       gchar      *buf,
986                       gsize       count,
987                       gsize      *bytes_read,
988                       GError    **err)
989 {
990   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
991   gint result;
992   GIOChannelError error;
993
994   if (win32_channel->debug)
995     g_print ("g_io_win32_sock_read: sockfd:%d count:%d\n",
996              win32_channel->fd, count);
997 #ifdef WE_NEED_TO_HANDLE_WSAEINTR
998 repeat:
999 #endif
1000   result = recv (win32_channel->fd, buf, count, 0);
1001
1002   if (win32_channel->debug)
1003     g_print ("g_io_win32_sock_read: recv:%d\n", result);
1004   
1005   if (result == SOCKET_ERROR)
1006     {
1007       *bytes_read = 0;
1008
1009       switch (WSAGetLastError ())
1010         {
1011         case WSAEINVAL:
1012           error = G_IO_CHANNEL_ERROR_INVAL;
1013           break;
1014         case WSAEWOULDBLOCK:
1015           return G_IO_STATUS_AGAIN;
1016 #ifdef WE_NEED_TO_HANDLE_WSAEINTR /* not anymore with wsock2 ? */
1017         case WSAEINTR:
1018           goto repeat;
1019 #endif
1020         default:
1021           error = G_IO_CHANNEL_ERROR_FAILED;
1022           break;
1023         }
1024       g_set_error(err, G_IO_CHANNEL_ERROR, error, _("Socket error"));
1025       return G_IO_STATUS_ERROR;
1026       /* FIXME get all errors, better error messages */
1027     }
1028   else
1029     {
1030       *bytes_read = result;
1031
1032       return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
1033     }
1034 }
1035
1036 static GIOStatus
1037 g_io_win32_sock_write (GIOChannel  *channel,
1038                        const gchar *buf,
1039                        gsize        count,
1040                        gsize       *bytes_written,
1041                        GError     **err)
1042 {
1043   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1044   gint result;
1045   GIOChannelError error;
1046   
1047   if (win32_channel->debug)
1048     g_print ("g_io_win32_sock_write: sockfd:%d count:%d\n",
1049              win32_channel->fd, count);
1050 #ifdef WE_NEED_TO_HANDLE_WSAEINTR
1051 repeat:
1052 #endif
1053   result = send (win32_channel->fd, buf, count, 0);
1054   
1055   if (win32_channel->debug)
1056     g_print ("g_io_win32_sock_write: send:%d\n", result);
1057   
1058   if (result == SOCKET_ERROR)
1059     {
1060       *bytes_written = 0;
1061
1062       switch (WSAGetLastError ())
1063         {
1064         case WSAEINVAL:
1065           error = G_IO_CHANNEL_ERROR_INVAL;
1066           break;
1067         case WSAEWOULDBLOCK:
1068           return G_IO_STATUS_AGAIN;
1069 #ifdef WE_NEED_TO_HANDLE_WSAEINTR /* not anymore with wsock2 ? */
1070         case WSAEINTR:
1071           goto repeat;
1072 #endif
1073         default:
1074           error = G_IO_CHANNEL_ERROR_FAILED;
1075           break;
1076         }
1077       g_set_error(err, G_IO_CHANNEL_ERROR, error, _("Socket error"));
1078       return G_IO_STATUS_ERROR;
1079       /* FIXME get all errors, better error messages */
1080     }
1081   else
1082     {
1083       *bytes_written = result;
1084
1085       return G_IO_STATUS_NORMAL;
1086     }
1087 }
1088
1089 static GIOStatus
1090 g_io_win32_sock_close (GIOChannel *channel,
1091                        GError    **err)
1092 {
1093   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1094
1095   LOCK(win32_channel->mutex);
1096   if (win32_channel->running)
1097   {
1098     if (win32_channel->debug)
1099         g_print ("thread %#x: running, marking for later close\n",
1100                  win32_channel->thread_id);
1101     win32_channel->running = FALSE;
1102     win32_channel->needs_close = TRUE;
1103     SetEvent(win32_channel->data_avail_noticed_event);
1104   }
1105   if (win32_channel->fd != -1)
1106   {
1107     if (win32_channel->debug)
1108        g_print ("thread %#x: closing socket %d\n",
1109              win32_channel->thread_id,
1110              win32_channel->fd);
1111   
1112     closesocket (win32_channel->fd);
1113     win32_channel->fd = -1;
1114   }
1115   UNLOCK(win32_channel->mutex);
1116
1117   /* FIXME error detection? */
1118
1119   return G_IO_STATUS_NORMAL;
1120 }
1121
1122 static GSource *
1123 g_io_win32_sock_create_watch (GIOChannel    *channel,
1124                               GIOCondition   condition)
1125 {
1126   return g_io_win32_create_watch (channel, condition, select_thread);
1127 }
1128
1129 GIOChannel *
1130 g_io_channel_new_file (const gchar  *filename,
1131                        const gchar  *mode,
1132                        GError      **error)
1133 {
1134   int fid, flags, pmode;
1135   GIOChannel *channel;
1136
1137   enum { /* Cheesy hack */
1138     MODE_R = 1 << 0,
1139     MODE_W = 1 << 1,
1140     MODE_A = 1 << 2,
1141     MODE_PLUS = 1 << 3,
1142   } mode_num;
1143
1144   g_return_val_if_fail (filename != NULL, NULL);
1145   g_return_val_if_fail (mode != NULL, NULL);
1146   g_return_val_if_fail ((error == NULL) || (*error == NULL), NULL);
1147
1148   switch (mode[0])
1149     {
1150       case 'r':
1151         mode_num = MODE_R;
1152         break;
1153       case 'w':
1154         mode_num = MODE_W;
1155         break;
1156       case 'a':
1157         mode_num = MODE_A;
1158         break;
1159       default:
1160         g_warning (G_STRLOC ": Invalid GIOFileMode %s.\n", mode);
1161         return NULL;
1162     }
1163
1164   switch (mode[1])
1165     {
1166       case '\0':
1167         break;
1168       case '+':
1169         if (mode[2] == '\0')
1170           {
1171             mode_num |= MODE_PLUS;
1172             break;
1173           }
1174         /* Fall through */
1175       default:
1176         g_warning (G_STRLOC ": Invalid GIOFileMode %s.\n", mode);
1177         return NULL;
1178     }
1179
1180   switch (mode_num)
1181     {
1182       case MODE_R:
1183         flags = O_RDONLY;
1184         pmode = _S_IREAD;
1185         break;
1186       case MODE_W:
1187         flags = O_WRONLY | O_TRUNC | O_CREAT;
1188         pmode = _S_IWRITE;
1189         break;
1190       case MODE_A:
1191         flags = O_WRONLY | O_APPEND | O_CREAT;
1192         pmode = _S_IWRITE;
1193         break;
1194       case MODE_R | MODE_PLUS:
1195         flags = O_RDWR;
1196         pmode = _S_IREAD | _S_IWRITE;
1197         break;
1198       case MODE_W | MODE_PLUS:
1199         flags = O_RDWR | O_TRUNC | O_CREAT;
1200         pmode = _S_IREAD | _S_IWRITE;
1201         break;
1202       case MODE_A | MODE_PLUS:
1203         flags = O_RDWR | O_APPEND | O_CREAT;
1204         pmode = _S_IREAD | _S_IWRITE;
1205         break;
1206       default:
1207         g_assert_not_reached ();
1208         flags = 0;
1209         pmode = 0;
1210     }
1211
1212   /* always open 'untranslated' */
1213   fid = open (filename, flags | _O_BINARY, pmode);
1214
1215   if (g_io_win32_get_debug_flag ())
1216     {
1217       g_print ("g_io_channel_win32_new_file: open(\"%s\", ", filename);
1218       g_win32_print_access_mode (flags|_O_BINARY);
1219       g_print (",%#o)=%d\n", pmode, fid);
1220     }
1221
1222   if (fid < 0)
1223     {
1224       g_set_error (error, G_FILE_ERROR,
1225                    g_file_error_from_errno (errno),
1226                    strerror (errno));
1227       return (GIOChannel *)NULL;
1228     }
1229
1230   channel = g_io_channel_win32_new_fd (fid);
1231
1232   /* XXX: move this to g_io_channel_win32_new_fd () */
1233   channel->close_on_unref = TRUE;
1234   channel->is_seekable = TRUE;
1235
1236   switch (mode_num)
1237     {
1238       case MODE_R:
1239         channel->is_readable = TRUE;
1240         channel->is_writeable = FALSE;
1241         break;
1242       case MODE_W:
1243       case MODE_A:
1244         channel->is_readable = FALSE;
1245         channel->is_writeable = TRUE;
1246         break;
1247       case MODE_R | MODE_PLUS:
1248       case MODE_W | MODE_PLUS:
1249       case MODE_A | MODE_PLUS:
1250         channel->is_readable = TRUE;
1251         channel->is_writeable = TRUE;
1252         break;
1253       default:
1254         g_assert_not_reached ();
1255     }
1256
1257   return channel;
1258 }
1259
1260 GIOStatus
1261 g_io_win32_set_flags (GIOChannel     *channel,
1262                       GIOFlags        flags,
1263                       GError        **err)
1264 {
1265   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1266
1267   if (win32_channel->debug)
1268     {
1269       g_print ("g_io_win32_set_flags: ");
1270       g_win32_print_gioflags (flags);
1271       g_print ("\n");
1272     }
1273
1274   g_set_error (err, 
1275                G_IO_CHANNEL_ERROR, 
1276                g_file_error_from_errno (EACCES), 
1277                _("Channel set flags unsupported"));
1278   return G_IO_STATUS_ERROR;
1279 }
1280
1281 GIOFlags
1282 g_io_win32_fd_get_flags (GIOChannel     *channel)
1283 {
1284   GIOFlags flags = 0;
1285   struct _stat st;
1286   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1287
1288   g_return_val_if_fail (win32_channel != NULL, 0);
1289   g_return_val_if_fail (win32_channel->type == G_IO_WIN32_FILE_DESC, 0);
1290
1291   if (0 == _fstat (win32_channel->fd, &st))
1292     {
1293        /* XXX: G_IO_FLAG_APPEND */
1294        /* XXX: G_IO_FLAG_NONBLOCK */
1295        if (st.st_mode & _S_IREAD)    flags |= G_IO_FLAG_IS_READABLE;
1296        if (st.st_mode & _S_IWRITE)   flags |= G_IO_FLAG_IS_WRITEABLE;
1297        /* XXX: */
1298        if (!(st.st_mode & _S_IFIFO)) flags |= G_IO_FLAG_IS_SEEKABLE;
1299     }
1300
1301   return flags;
1302 }
1303
1304 /*
1305  * Generic implementation, just translating createion flags
1306  */
1307 GIOFlags
1308 g_io_win32_get_flags (GIOChannel     *channel)
1309 {
1310   GIOFlags flags;
1311
1312   flags =   (channel->is_readable ? G_IO_FLAG_IS_READABLE : 0)
1313           | (channel->is_writeable ? G_IO_FLAG_IS_READABLE : 0)
1314           | (channel->is_seekable ? G_IO_FLAG_IS_SEEKABLE : 0);
1315
1316   return flags;
1317 }
1318
1319 static GIOFuncs win32_channel_msg_funcs = {
1320   g_io_win32_msg_read,
1321   g_io_win32_msg_write,
1322   g_io_win32_no_seek,
1323   g_io_win32_msg_close,
1324   g_io_win32_msg_create_watch,
1325   g_io_win32_free,
1326   g_io_win32_set_flags,
1327   g_io_win32_get_flags,
1328 };
1329
1330 static GIOFuncs win32_channel_fd_funcs = {
1331   g_io_win32_fd_read,
1332   g_io_win32_fd_write,
1333   g_io_win32_fd_seek,
1334   g_io_win32_fd_close,
1335   g_io_win32_fd_create_watch,
1336   g_io_win32_free,
1337   g_io_win32_set_flags,
1338   g_io_win32_fd_get_flags,
1339 };
1340
1341 static GIOFuncs win32_channel_sock_funcs = {
1342   g_io_win32_sock_read,
1343   g_io_win32_sock_write,
1344   g_io_win32_no_seek,
1345   g_io_win32_sock_close,
1346   g_io_win32_sock_create_watch,
1347   g_io_win32_free,
1348   g_io_win32_set_flags,
1349   g_io_win32_get_flags,
1350 };
1351
1352 GIOChannel *
1353 g_io_channel_win32_new_messages (guint hwnd)
1354 {
1355   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1356   GIOChannel *channel = (GIOChannel *)win32_channel;
1357
1358   g_io_channel_init (channel);
1359   g_io_channel_win32_init (win32_channel);
1360   if (win32_channel->debug)
1361     g_print ("g_io_channel_win32_new_messages: hwnd = %ud\n", hwnd);
1362   channel->funcs = &win32_channel_msg_funcs;
1363   win32_channel->type = G_IO_WIN32_WINDOWS_MESSAGES;
1364   win32_channel->hwnd = (HWND) hwnd;
1365
1366   /* XXX: check this. */
1367   channel->is_readable = IsWindow (win32_channel->hwnd);
1368   channel->is_writeable = IsWindow (win32_channel->hwnd);
1369
1370   channel->is_seekable = FALSE;
1371
1372   return channel;
1373 }
1374
1375 GIOChannel *
1376 g_io_channel_win32_new_fd (gint fd)
1377 {
1378   GIOWin32Channel *win32_channel;
1379   GIOChannel *channel;
1380   struct stat st;
1381
1382   if (fstat (fd, &st) == -1)
1383     {
1384       g_warning (G_STRLOC ": %d isn't a (emulated) file descriptor", fd);
1385       return NULL;
1386     }
1387
1388   win32_channel = g_new (GIOWin32Channel, 1);
1389   channel = (GIOChannel *)win32_channel;
1390
1391   g_io_channel_init (channel);
1392   g_io_channel_win32_init (win32_channel);
1393   if (win32_channel->debug)
1394     g_print ("g_io_channel_win32_new_fd: %u\n", fd);
1395   channel->funcs = &win32_channel_fd_funcs;
1396   win32_channel->type = G_IO_WIN32_FILE_DESC;
1397   win32_channel->fd = fd;
1398
1399
1400   /* fstat doesn't deliver senseful values, but
1401    * fcntl isn't available, so guess ...
1402    */
1403   if (st.st_mode & _S_IFIFO)
1404     {
1405       channel->is_readable  = TRUE;
1406       channel->is_writeable = TRUE;
1407       channel->is_seekable  = FALSE;
1408     }
1409   else
1410     {
1411       channel->is_readable  = !!(st.st_mode & _S_IREAD);
1412       channel->is_writeable = !!(st.st_mode & _S_IWRITE);
1413       /* XXX What about "device files" (COM1: and the like) */
1414       channel->is_seekable = TRUE;
1415     }
1416
1417   return channel;
1418 }
1419
1420 gint
1421 g_io_channel_win32_get_fd (GIOChannel *channel)
1422 {
1423   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1424
1425   return win32_channel->fd;
1426 }
1427
1428 GIOChannel *
1429 g_io_channel_win32_new_socket (int socket)
1430 {
1431   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1432   GIOChannel *channel = (GIOChannel *)win32_channel;
1433
1434   g_io_channel_init (channel);
1435   g_io_channel_win32_init (win32_channel);
1436   if (win32_channel->debug)
1437     g_print ("g_io_channel_win32_new_socket: sockfd:%d\n", socket);
1438   channel->funcs = &win32_channel_sock_funcs;
1439   win32_channel->type = G_IO_WIN32_SOCKET;
1440   win32_channel->fd = socket;
1441
1442   /* XXX: check this */
1443   channel->is_readable = TRUE;
1444   channel->is_writeable = TRUE;
1445   channel->is_seekable = FALSE;
1446
1447   return channel;
1448 }
1449
1450 GIOChannel *
1451 g_io_channel_unix_new (gint fd)
1452 {
1453   struct stat st;
1454
1455   if (fstat (fd, &st) == 0)
1456     return g_io_channel_win32_new_fd (fd);
1457   
1458   if (getsockopt (fd, SOL_SOCKET, SO_TYPE, NULL, NULL) != SO_ERROR)
1459     return g_io_channel_win32_new_socket(fd);
1460
1461   g_warning (G_STRLOC ": %d is neither a file descriptor or a socket", fd);
1462   return NULL;
1463 }
1464
1465 gint
1466 g_io_channel_unix_get_fd (GIOChannel *channel)
1467 {
1468   return g_io_channel_win32_get_fd (channel);
1469 }
1470
1471 void
1472 g_io_channel_win32_set_debug (GIOChannel *channel,
1473                               gboolean    flag)
1474 {
1475   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1476
1477   win32_channel->debug = flag;
1478 }
1479
1480 gint
1481 g_io_channel_win32_poll (GPollFD *fds,
1482                          gint     n_fds,
1483                          gint     timeout)
1484 {
1485   int result;
1486
1487   g_return_val_if_fail (n_fds >= 0, 0);
1488
1489   result = (*g_main_context_get_poll_func (NULL)) (fds, n_fds, timeout);
1490
1491   return result;
1492 }
1493
1494 void
1495 g_io_channel_win32_make_pollfd (GIOChannel   *channel,
1496                                 GIOCondition  condition,
1497                                 GPollFD      *fd)
1498 {
1499   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1500
1501   if (win32_channel->data_avail_event == NULL)
1502     create_events (win32_channel);
1503   
1504   fd->fd = (gint) win32_channel->data_avail_event;
1505   fd->events = condition;
1506
1507   if (win32_channel->thread_id == 0)
1508     {
1509       if ((condition & G_IO_IN) && win32_channel->type == G_IO_WIN32_FILE_DESC)
1510         create_thread (win32_channel, condition, read_thread);
1511       else if (win32_channel->type == G_IO_WIN32_SOCKET)
1512         create_thread (win32_channel, condition, select_thread);
1513     }
1514 }
1515
1516 /* Binary compatibility */
1517 GIOChannel *
1518 g_io_channel_win32_new_stream_socket (int socket)
1519 {
1520   return g_io_channel_win32_new_socket (socket);
1521 }