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