Removed g_param_spec_stringc.
[platform/upstream/glib.git] / 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  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 /*
25  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
26  * file for a list of people on the GLib Team.  See the ChangeLog
27  * files for a list of changes.  These files are distributed with
28  * GLib at ftp://ftp.gtk.org/pub/gtk/.
29  */
30
31 /* Define this to get (very) verbose logging of all channels */
32 /* #define G_IO_WIN32_DEBUG */
33
34 #include "glib.h"
35
36 #include <stdlib.h>
37 #include <windows.h>
38 #include <winsock.h>          /* Not everybody has winsock2 */
39 #include <fcntl.h>
40 #include <io.h>
41 #include <process.h>
42 #include <errno.h>
43 #include <sys/stat.h>
44
45 typedef struct _GIOWin32Channel GIOWin32Channel;
46 typedef struct _GIOWin32Watch GIOWin32Watch;
47
48 #define BUFFER_SIZE 4096
49
50 typedef enum {
51   G_IO_WIN32_WINDOWS_MESSAGES,  /* Windows messages */
52   G_IO_WIN32_FILE_DESC,         /* Unix-like file descriptors from
53                                  * _open() or _pipe(). Read with read().
54                                  * Have to create separate thread to read.
55                                  */
56   G_IO_WIN32_SOCKET             /* Sockets. A separate thread is blocked
57                                  * in select() most of the time.
58                                  */
59 } GIOWin32ChannelType;
60
61 struct _GIOWin32Channel {
62   GIOChannel channel;
63   gint fd;                      /* Either a Unix-like file handle as provided
64                                  * by the Microsoft C runtime, or a SOCKET
65                                  * as provided by WinSock.
66                                  */
67   GIOWin32ChannelType type;
68   
69   gboolean debug;
70
71   CRITICAL_SECTION mutex;
72
73   /* This is used by G_IO_WIN32_WINDOWS_MESSAGES channels */
74   HWND hwnd;                    /* handle of window, or NULL */
75   
76   /* Following fields are used by both fd and socket channels. */
77   gboolean running;             /* Is reader thread running. FALSE if
78                                  * EOF has been reached.
79                                  */
80   gboolean needs_close;         /* If the channel has been closed while
81                                  * the reader thread was still running.
82                                  */
83   guint thread_id;              /* If non-NULL has a reader thread, or has
84                                  * had.*/
85   HANDLE thread_handle;
86   HANDLE data_avail_event;
87
88   gushort revents;
89
90   /* Following fields used by fd channels for input */
91   
92   /* Data is kept in a circular buffer. To be able to distinguish between
93    * empty and full buffer, we cannot fill it completely, but have to
94    * leave a one character gap.
95    *
96    * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
97    *
98    * Empty:    wrp == rdp
99    * Full:     (wrp + 1) % BUFFER_SIZE == rdp
100    * Partial:  otherwise
101    */
102   guchar *buffer;               /* (Circular) buffer */
103   gint wrp, rdp;                /* Buffer indices for writing and reading */
104   HANDLE space_avail_event;
105
106   /* Following fields used by socket channels */
107   GSList *watches;
108   HANDLE data_avail_noticed_event;
109 };
110
111 #define LOCK(mutex) EnterCriticalSection (&mutex)
112 #define UNLOCK(mutex) LeaveCriticalSection (&mutex)
113
114 struct _GIOWin32Watch {
115   GSource       source;
116   GPollFD       pollfd;
117   GIOChannel   *channel;
118   GIOCondition  condition;
119   GIOFunc       callback;
120 };
121
122 static void
123 g_io_channel_win32_init (GIOWin32Channel *channel)
124 {
125 #ifdef G_IO_WIN32_DEBUG
126   channel->debug = TRUE;
127 #else
128   if (getenv ("G_IO_WIN32_DEBUG") != NULL)
129     channel->debug = TRUE;
130   else
131     channel->debug = FALSE;
132 #endif
133   channel->buffer = NULL;
134   channel->running = FALSE;
135   channel->needs_close = FALSE;
136   channel->thread_id = 0;
137   channel->data_avail_event = NULL;
138   channel->revents = 0;
139   channel->space_avail_event = NULL;
140   channel->data_avail_noticed_event = NULL;
141   channel->watches = NULL;
142   InitializeCriticalSection (&channel->mutex);
143 }
144
145 static void
146 create_events (GIOWin32Channel *channel)
147 {
148   SECURITY_ATTRIBUTES sec_attrs;
149   
150   sec_attrs.nLength = sizeof(SECURITY_ATTRIBUTES);
151   sec_attrs.lpSecurityDescriptor = NULL;
152   sec_attrs.bInheritHandle = FALSE;
153
154   /* The data available event is manual reset, the space available event
155    * is automatic reset.
156    */
157   if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
158       || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL))
159       || !(channel->data_avail_noticed_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
160     {
161       gchar *msg = g_win32_error_message (GetLastError ());
162       g_error ("Error creating event: %s", msg);
163     }
164 }
165
166 static unsigned __stdcall
167 read_thread (void *parameter)
168 {
169   GIOWin32Channel *channel = parameter;
170   GSList *tmp;
171   guchar *buffer;
172   guint nbytes;
173
174   g_io_channel_ref ((GIOChannel *)channel);
175
176   if (channel->debug)
177     g_print ("read_thread %#x: start fd:%d, data_avail:%#x, space_avail:%#x\n",
178              channel->thread_id,
179              channel->fd,
180              (guint) channel->data_avail_event,
181              (guint) channel->space_avail_event);
182   
183   channel->buffer = g_malloc (BUFFER_SIZE);
184   channel->rdp = channel->wrp = 0;
185   channel->running = TRUE;
186
187   SetEvent (channel->space_avail_event);
188   
189   while (channel->running)
190     {
191       LOCK (channel->mutex);
192       if (channel->debug)
193         g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
194                  channel->thread_id, channel->rdp, channel->wrp);
195       if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
196         {
197           /* Buffer is full */
198           if (channel->debug)
199             g_print ("read_thread %#x: resetting space_avail\n",
200                      channel->thread_id);
201           ResetEvent (channel->space_avail_event);
202           if (channel->debug)
203             g_print ("read_thread %#x: waiting for space\n",
204                      channel->thread_id);
205           UNLOCK (channel->mutex);
206           WaitForSingleObject (channel->space_avail_event, INFINITE);
207           LOCK (channel->mutex);
208           if (channel->debug)
209             g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
210                      channel->thread_id, channel->rdp, channel->wrp);
211         }
212       
213       buffer = channel->buffer + channel->wrp;
214       
215       /* Always leave at least one byte unused gap to be able to
216        * distinguish between the full and empty condition...
217        */
218       nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
219                     BUFFER_SIZE - channel->wrp);
220
221       if (channel->debug)
222         g_print ("read_thread %#x: calling read() for %d bytes\n",
223                  channel->thread_id, nbytes);
224
225       UNLOCK (channel->mutex);
226
227       nbytes = read (channel->fd, buffer, nbytes);
228       
229       LOCK (channel->mutex);
230
231       channel->revents = G_IO_IN;
232       if (nbytes == 0)
233         channel->revents |= G_IO_HUP;
234       else if (nbytes < 0)
235         channel->revents |= G_IO_ERR;
236
237       if (channel->debug)
238         g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
239                  channel->thread_id, nbytes, channel->rdp, channel->wrp);
240
241       if (nbytes <= 0)
242         break;
243
244       channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
245       if (channel->debug)
246         g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
247                  channel->thread_id, channel->rdp, channel->wrp);
248       SetEvent (channel->data_avail_event);
249       UNLOCK (channel->mutex);
250     }
251   
252   channel->running = FALSE;
253   if (channel->needs_close)
254     {
255       if (channel->debug)
256         g_print ("read_thread %#x: channel fd %d needs closing\n",
257                  channel->thread_id, channel->fd);
258       close (channel->fd);
259       channel->fd = -1;
260     }
261
262   if (channel->debug)
263     g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
264              channel->thread_id, channel->rdp, channel->wrp);
265   SetEvent (channel->data_avail_event);
266   UNLOCK (channel->mutex);
267   
268   g_io_channel_unref((GIOChannel *)channel);
269   
270   /* No need to call _endthreadex(), the actual thread starter routine
271    * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
272    * _endthreadex() for us.
273    */
274
275   CloseHandle (channel->thread_handle);
276
277   return 0;
278 }
279
280 static void
281 create_thread (GIOWin32Channel     *channel,
282                GIOCondition         condition,
283                unsigned (__stdcall *thread) (void *parameter))
284 {
285   channel->thread_handle =
286     (HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
287                              &channel->thread_id);
288   if (channel->thread_handle == 0)
289     g_warning (G_STRLOC ": Error creating reader thread: %s",
290                strerror (errno));
291   WaitForSingleObject (channel->space_avail_event, INFINITE);
292 }
293
294 static int
295 buffer_read (GIOWin32Channel *channel,
296              guchar          *dest,
297              guint            count,
298              GIOError        *error)
299 {
300   guint nbytes;
301   guint left = count;
302   
303   LOCK (channel->mutex);
304   if (channel->debug)
305     g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
306              channel->thread_id, count, channel->rdp, channel->wrp);
307   
308   if (channel->wrp == channel->rdp)
309     {
310       UNLOCK (channel->mutex);
311       if (channel->debug)
312         g_print ("waiting for data from thread %#x\n", channel->thread_id);
313       WaitForSingleObject (channel->data_avail_event, INFINITE);
314       if (channel->debug)
315         g_print ("done waiting for data from thread %#x\n", channel->thread_id);
316       LOCK (channel->mutex);
317       if (channel->wrp == channel->rdp && !channel->running)
318         {
319           UNLOCK (channel->mutex);
320           return 0;
321         }
322     }
323   
324   if (channel->rdp < channel->wrp)
325     nbytes = channel->wrp - channel->rdp;
326   else
327     nbytes = BUFFER_SIZE - channel->rdp;
328   UNLOCK (channel->mutex);
329   nbytes = MIN (left, nbytes);
330   if (channel->debug)
331     g_print ("moving %d bytes from thread %#x\n",
332              nbytes, channel->thread_id);
333   memcpy (dest, channel->buffer + channel->rdp, nbytes);
334   dest += nbytes;
335   left -= nbytes;
336   LOCK (channel->mutex);
337   channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
338   if (channel->debug)
339     g_print ("setting space_avail for thread %#x\n", channel->thread_id);
340   SetEvent (channel->space_avail_event);
341   if (channel->debug)
342     g_print ("for thread %#x: rdp=%d, wrp=%d\n",
343              channel->thread_id, channel->rdp, channel->wrp);
344   if (channel->running && channel->wrp == channel->rdp)
345     {
346       if (channel->debug)
347         g_print ("resetting data_avail of thread %#x\n",
348                  channel->thread_id);
349       ResetEvent (channel->data_avail_event);
350     };
351   UNLOCK (channel->mutex);
352   
353   /* We have no way to indicate any errors form the actual
354    * read() or recv() call in the reader thread. Should we have?
355    */
356   *error = G_IO_ERROR_NONE;
357   return count - left;
358 }
359
360 static unsigned __stdcall
361 select_thread (void *parameter)
362 {
363   GIOWin32Channel *channel = parameter;
364   fd_set read_fds, write_fds, except_fds;
365   GSList *tmp;
366   int n;
367
368   g_io_channel_ref ((GIOChannel *)channel);
369
370   if (channel->debug)
371     g_print ("select_thread %#x: start fd:%d,\n\tdata_avail:%#x, data_avail_noticed:%#x\n",
372              channel->thread_id,
373              channel->fd,
374              (guint) channel->data_avail_event,
375              (guint) channel->data_avail_noticed_event);
376   
377   channel->rdp = channel->wrp = 0;
378   channel->running = TRUE;
379
380   SetEvent (channel->space_avail_event);
381   
382   while (channel->running)
383     {
384       FD_ZERO (&read_fds);
385       FD_ZERO (&write_fds);
386       FD_ZERO (&except_fds);
387
388       tmp = channel->watches;
389       while (tmp)
390         {
391           GIOWin32Watch *watch = (GIOWin32Watch *)tmp->data;
392
393           if (watch->condition & (G_IO_IN | G_IO_HUP))
394             FD_SET (channel->fd, &read_fds);
395           if (watch->condition & G_IO_OUT)
396             FD_SET (channel->fd, &write_fds);
397           if (watch->condition & G_IO_ERR)
398             FD_SET (channel->fd, &except_fds);
399           
400           tmp = tmp->next;
401         }
402       if (channel->debug)
403         g_print ("select_thread %#x: calling select() for%s%s%s\n",
404                  channel->thread_id,
405                  (FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
406                  (FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
407                  (FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
408
409       n = select (1, &read_fds, &write_fds, &except_fds, NULL);
410       
411       if (n == SOCKET_ERROR)
412         {
413           if (channel->debug)
414             g_print ("select_thread %#x: select returned SOCKET_ERROR\n",
415                      channel->thread_id);
416           break;
417         }
418
419       if (channel->debug)
420         g_print ("select_thread %#x: got%s%s%s\n",
421                  channel->thread_id,
422                  (FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
423                  (FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
424                  (FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
425
426       if (FD_ISSET (channel->fd, &read_fds))
427         channel->revents |= G_IO_IN;
428       if (FD_ISSET (channel->fd, &write_fds))
429         channel->revents |= G_IO_OUT;
430       if (FD_ISSET (channel->fd, &except_fds))
431         channel->revents |= G_IO_ERR;
432
433       if (channel->debug)
434         g_print ("select_thread %#x: resetting data_avail_noticed,\n"
435                  "\tsetting data_avail\n",
436                  channel->thread_id);
437       ResetEvent (channel->data_avail_noticed_event);
438       SetEvent (channel->data_avail_event);
439
440       if (channel->debug)
441         g_print ("select_thread %#x: waiting for data_avail_noticed\n",
442                  channel->thread_id);
443
444       WaitForSingleObject (channel->data_avail_noticed_event, INFINITE);
445       if (channel->debug)
446         g_print ("select_thread %#x: got data_avail_noticed\n",
447                  channel->thread_id);
448     }
449   
450   channel->running = FALSE;
451   LOCK (channel->mutex);
452   if (channel->needs_close)
453     {
454       if (channel->debug)
455         g_print ("select_thread %#x: channel fd %d needs closing\n",
456                  channel->thread_id, channel->fd);
457       closesocket (channel->fd);
458       channel->fd = -1;
459     }
460
461   if (channel->debug)
462     g_print ("select_thread %#x: got error, setting data_avail\n",
463              channel->thread_id);
464   SetEvent (channel->data_avail_event);
465   UNLOCK (channel->mutex);
466   
467   g_io_channel_unref((GIOChannel *)channel);
468   
469   /* No need to call _endthreadex(), the actual thread starter routine
470    * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
471    * _endthreadex() for us.
472    */
473
474   CloseHandle (channel->thread_handle);
475
476   return 0;
477 }
478
479 static gboolean
480 g_io_win32_prepare (GSource *source,
481                     gint    *timeout)
482 {
483   GIOWin32Watch *watch = (GIOWin32Watch *)source;
484   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
485   
486   *timeout = -1;
487   
488   if (channel->type == G_IO_WIN32_FILE_DESC)
489     {
490       LOCK (channel->mutex);
491       if (channel->running && channel->wrp == channel->rdp)
492         channel->revents = 0;
493       UNLOCK (channel->mutex);
494     }
495   else if (channel->type == G_IO_WIN32_SOCKET)
496     {
497       channel->revents = 0;
498
499       if (channel->debug)
500         g_print ("g_io_win32_prepare: thread %#x, setting data_avail_noticed\n",
501                  channel->thread_id);
502       SetEvent (channel->data_avail_noticed_event);
503       if (channel->debug)
504         g_print ("g_io_win32_prepare: thread %#x, there.\n",
505                  channel->thread_id);
506     }
507
508   return FALSE;
509 }
510
511 static gboolean
512 g_io_win32_check (GSource *source)
513 {
514         MSG msg;
515   GIOWin32Watch *watch = (GIOWin32Watch *)source;
516   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
517   
518   if (channel->debug)
519     g_print ("g_io_win32_check: for thread %#x:\n"
520              "\twatch->pollfd.events:%#x, watch->pollfd.revents:%#x, channel->revents:%#x\n",
521              channel->thread_id,
522              watch->pollfd.events, watch->pollfd.revents, channel->revents);
523
524   if (channel->type != G_IO_WIN32_WINDOWS_MESSAGES)
525         {
526      watch->pollfd.revents = (watch->pollfd.events & channel->revents);
527         }
528         else
529         {
530     return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE));
531         }
532
533   if (channel->type == G_IO_WIN32_SOCKET)
534     {
535       if (channel->debug)
536         g_print ("g_io_win32_check: thread %#x, resetting data_avail\n",
537                  channel->thread_id);
538       ResetEvent (channel->data_avail_event);
539       if (channel->debug)
540         g_print ("g_io_win32_check: thread %#x, there.\n",
541                  channel->thread_id);
542     }
543   
544   return (watch->pollfd.revents & watch->condition);
545 }
546
547 static gboolean
548 g_io_win32_dispatch (GSource     *source,
549                      GSourceFunc  callback,
550                      gpointer     user_data)
551 {
552   GIOFunc func = (GIOFunc)callback;
553   GIOWin32Watch *watch = (GIOWin32Watch *)source;
554   
555   if (!func)
556     {
557       g_warning (G_STRLOC ": GIOWin32Watch dispatched without callback\n"
558                  "You must call g_source_connect().");
559       return FALSE;
560     }
561   
562   return (*func) (watch->channel,
563                   watch->pollfd.revents & watch->condition,
564                   user_data);
565 }
566
567 static void
568 g_io_win32_destroy (GSource *source)
569 {
570   GIOWin32Watch *watch = (GIOWin32Watch *)source;
571   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
572   
573   if (channel->debug)
574     g_print ("g_io_win32_destroy: channel with thread %#x\n",
575              channel->thread_id);
576
577   channel->watches = g_slist_remove (channel->watches, watch);
578
579   g_io_channel_unref (watch->channel);
580 }
581
582 static GSourceFuncs win32_watch_funcs = {
583   g_io_win32_prepare,
584   g_io_win32_check,
585   g_io_win32_dispatch,
586   g_io_win32_destroy
587 };
588
589 static GSource *
590 g_io_win32_create_watch (GIOChannel    *channel,
591                          GIOCondition   condition,
592                          unsigned (__stdcall *thread) (void *parameter))
593 {
594   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
595   GIOWin32Watch *watch;
596   GSource *source;
597
598   source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
599   watch = (GIOWin32Watch *)source;
600   
601   watch->channel = channel;
602   g_io_channel_ref (channel);
603   
604   watch->condition = condition;
605   
606   if (win32_channel->data_avail_event == NULL)
607     create_events (win32_channel);
608
609   watch->pollfd.fd = (gint) win32_channel->data_avail_event;
610   watch->pollfd.events = condition;
611   
612   if (win32_channel->debug)
613     g_print ("g_io_win32_create_watch: fd:%d condition:%#x handle:%#x\n",
614              win32_channel->fd, condition, watch->pollfd.fd);
615   
616   win32_channel->watches = g_slist_append (win32_channel->watches, watch);
617
618   if (win32_channel->thread_id == 0)
619     create_thread (win32_channel, condition, thread);
620
621   g_source_add_poll (source, &watch->pollfd);
622   
623   return source;
624 }
625
626 static GIOError
627 g_io_win32_msg_read (GIOChannel *channel,
628                      gchar      *buf,
629                      guint       count,
630                      guint      *bytes_read)
631 {
632   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
633   MSG msg;               /* In case of alignment problems */
634   
635   if (count < sizeof (MSG))
636     return G_IO_ERROR_INVAL;
637   
638   if (win32_channel->debug)
639     g_print ("g_io_win32_msg_read: for %#x\n",
640              win32_channel->hwnd);
641   if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
642     return G_IO_ERROR_AGAIN;
643   
644   memmove (buf, &msg, sizeof (MSG));
645   *bytes_read = sizeof (MSG);
646   return G_IO_ERROR_NONE;
647 }
648
649 static GIOError
650 g_io_win32_msg_write (GIOChannel *channel,
651                       gchar      *buf,
652                       guint       count,
653                       guint      *bytes_written)
654 {
655   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
656   MSG msg;
657   
658   if (count != sizeof (MSG))
659     return G_IO_ERROR_INVAL;
660   
661   /* In case of alignment problems */
662   memmove (&msg, buf, sizeof (MSG));
663   if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
664     return G_IO_ERROR_UNKNOWN;
665   
666   *bytes_written = sizeof (MSG);
667   return G_IO_ERROR_NONE;
668 }
669
670 static GIOError
671 g_io_win32_no_seek (GIOChannel *channel,
672                     gint        offset,
673                     GSeekType   type)
674 {
675   return G_IO_ERROR_UNKNOWN;
676 }
677
678 static void
679 g_io_win32_msg_close (GIOChannel *channel)
680 {
681   /* Nothing to be done. Or should we set hwnd to some invalid value? */
682 }
683
684 static void
685 g_io_win32_free (GIOChannel *channel)
686 {
687   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
688   
689   if (win32_channel->debug)
690     g_print ("thread %#x: freeing channel, fd: %d\n",
691              win32_channel->thread_id,
692              win32_channel->fd);
693
694   if (win32_channel->data_avail_event)
695     CloseHandle (win32_channel->data_avail_event);
696   if (win32_channel->space_avail_event)
697     CloseHandle (win32_channel->space_avail_event);
698   if (win32_channel->data_avail_noticed_event)
699     CloseHandle (win32_channel->data_avail_noticed_event);
700   DeleteCriticalSection (&win32_channel->mutex);
701
702   g_free (win32_channel->buffer);
703   g_slist_free (win32_channel->watches);
704   g_free (win32_channel);
705 }
706
707 static GSource *
708 g_io_win32_msg_create_watch (GIOChannel    *channel,
709                              GIOCondition   condition)
710 {
711   GIOWin32Watch *watch;
712   GSource *source;
713
714   source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
715   watch = (GIOWin32Watch *)source;
716   
717   watch->channel = channel;
718   g_io_channel_ref (channel);
719   
720   watch->condition = condition;
721   
722   watch->pollfd.fd = G_WIN32_MSG_HANDLE;
723   watch->pollfd.events = condition;
724   
725   g_source_add_poll (source, &watch->pollfd);
726   
727   return source;
728 }
729
730 static GIOError
731 g_io_win32_fd_read (GIOChannel *channel,
732                     gchar      *buf,
733                     guint       count,
734                     guint      *bytes_read)
735 {
736   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
737   gint result;
738   GIOError error;
739   
740   if (win32_channel->debug)
741     g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
742              win32_channel->fd, count);
743   
744   if (win32_channel->thread_id)
745     {
746       result = buffer_read (win32_channel, buf, count, &error);
747       if (result < 0)
748         {
749           *bytes_read = 0;
750           return error;
751         }
752       else
753         {
754           *bytes_read = result;
755           return G_IO_ERROR_NONE;
756         }
757     }
758
759   result = read (win32_channel->fd, buf, count);
760
761   if (result < 0)
762     {
763       *bytes_read = 0;
764       if (errno == EINVAL)
765         return G_IO_ERROR_INVAL;
766       else
767         return G_IO_ERROR_UNKNOWN;
768     }
769   else
770     {
771       *bytes_read = result;
772       return G_IO_ERROR_NONE;
773     }
774 }
775
776 static GIOError
777 g_io_win32_fd_write (GIOChannel *channel,
778                      gchar      *buf,
779                      guint       count,
780                      guint      *bytes_written)
781 {
782   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
783   gint result;
784   
785   result = write (win32_channel->fd, buf, count);
786   if (win32_channel->debug)
787     g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
788              win32_channel->fd, count, result);
789   
790   if (result < 0)
791     {
792       *bytes_written = 0;
793       switch (errno)
794         {
795         case EINVAL:
796           return G_IO_ERROR_INVAL;
797         case EAGAIN:
798           return G_IO_ERROR_AGAIN;
799         default:
800           return G_IO_ERROR_UNKNOWN;
801         }
802     }
803   else
804     {
805       *bytes_written = result;
806       return G_IO_ERROR_NONE;
807     }
808 }
809
810 static GIOError
811 g_io_win32_fd_seek (GIOChannel *channel,
812                     gint        offset,
813                     GSeekType   type)
814 {
815   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
816   int whence;
817   off_t result;
818   
819   switch (type)
820     {
821     case G_SEEK_SET:
822       whence = SEEK_SET;
823       break;
824     case G_SEEK_CUR:
825       whence = SEEK_CUR;
826       break;
827     case G_SEEK_END:
828       whence = SEEK_END;
829       break;
830     default:
831       g_warning (G_STRLOC ": Unknown seek type %d", (int) type);
832       return G_IO_ERROR_UNKNOWN;
833     }
834   
835   result = lseek (win32_channel->fd, offset, whence);
836   
837   if (result < 0)
838     {
839       switch (errno)
840         {
841         case EINVAL:
842           return G_IO_ERROR_INVAL;
843         default:
844           return G_IO_ERROR_UNKNOWN;
845         }
846     }
847   else
848     return G_IO_ERROR_NONE;
849 }
850
851 static void
852 g_io_win32_fd_close (GIOChannel *channel)
853 {
854   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
855   
856   if (win32_channel->debug)
857     g_print ("thread %#x: closing fd %d\n",
858              win32_channel->thread_id,
859              win32_channel->fd);
860   LOCK (win32_channel->mutex);
861   if (win32_channel->running)
862     {
863       if (win32_channel->debug)
864         g_print ("thread %#x: running, marking fd %d for later close\n",
865                  win32_channel->thread_id, win32_channel->fd);
866       win32_channel->running = FALSE;
867       win32_channel->needs_close = TRUE;
868       SetEvent (win32_channel->data_avail_event);
869     }
870   else
871     {
872       if (win32_channel->debug)
873         g_print ("closing fd %d\n", win32_channel->fd);
874       close (win32_channel->fd);
875       if (win32_channel->debug)
876         g_print ("closed fd %d, setting to -1\n",
877                  win32_channel->fd);
878       win32_channel->fd = -1;
879     }
880   UNLOCK (win32_channel->mutex);
881 }
882
883 static GSource *
884 g_io_win32_fd_create_watch (GIOChannel    *channel,
885                             GIOCondition   condition)
886 {
887   return g_io_win32_create_watch (channel, condition, read_thread);
888 }
889
890 static GIOError
891 g_io_win32_sock_read (GIOChannel *channel,
892                       gchar      *buf,
893                       guint       count,
894                       guint      *bytes_read)
895 {
896   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
897   gint result;
898   GIOError error;
899
900   if (win32_channel->debug)
901     g_print ("g_io_win32_sock_read: sockfd:%d count:%d\n",
902              win32_channel->fd, count);
903   
904   result = recv (win32_channel->fd, buf, count, 0);
905
906   if (win32_channel->debug)
907     g_print ("g_io_win32_sock_read: recv:%d\n", result);
908   
909   if (result == SOCKET_ERROR)
910     {
911       *bytes_read = 0;
912       switch (WSAGetLastError ())
913         {
914         case WSAEINVAL:
915           return G_IO_ERROR_INVAL;
916         case WSAEWOULDBLOCK:
917         case WSAEINTR:
918           return G_IO_ERROR_AGAIN;
919         default:
920           return G_IO_ERROR_UNKNOWN;
921         }
922     }
923   else
924     {
925       *bytes_read = result;
926       return G_IO_ERROR_NONE;
927     }
928 }
929
930 static GIOError
931 g_io_win32_sock_write (GIOChannel *channel,
932                        gchar      *buf,
933                        guint       count,
934                        guint      *bytes_written)
935 {
936   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
937   gint result;
938   
939   if (win32_channel->debug)
940     g_print ("g_io_win32_sock_write: sockfd:%d count:%d\n",
941              win32_channel->fd, count);
942   
943   result = send (win32_channel->fd, buf, count, 0);
944   
945   if (win32_channel->debug)
946     g_print ("g_io_win32_sock_write: send:%d\n", result);
947   
948   if (result == SOCKET_ERROR)
949     {
950       *bytes_written = 0;
951       switch (WSAGetLastError ())
952         {
953         case WSAEINVAL:
954           return G_IO_ERROR_INVAL;
955         case WSAEWOULDBLOCK:
956         case WSAEINTR:
957           return G_IO_ERROR_AGAIN;
958         default:
959           return G_IO_ERROR_UNKNOWN;
960         }
961     }
962   else
963     {
964       *bytes_written = result;
965       return G_IO_ERROR_NONE;
966     }
967 }
968
969 static void
970 g_io_win32_sock_close (GIOChannel *channel)
971 {
972   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
973
974   if (win32_channel->debug)
975     g_print ("thread %#x: closing socket %d\n",
976              win32_channel->thread_id,
977              win32_channel->fd);
978   closesocket (win32_channel->fd);
979   win32_channel->fd = -1;
980 }
981
982 static GSource *
983 g_io_win32_sock_create_watch (GIOChannel    *channel,
984                               GIOCondition   condition)
985 {
986   return g_io_win32_create_watch (channel, condition, select_thread);
987 }
988
989 static GIOFuncs win32_channel_msg_funcs = {
990   g_io_win32_msg_read,
991   g_io_win32_msg_write,
992   g_io_win32_no_seek,
993   g_io_win32_msg_close,
994   g_io_win32_msg_create_watch,
995   g_io_win32_free
996 };
997
998 static GIOFuncs win32_channel_fd_funcs = {
999   g_io_win32_fd_read,
1000   g_io_win32_fd_write,
1001   g_io_win32_fd_seek,
1002   g_io_win32_fd_close,
1003   g_io_win32_fd_create_watch,
1004   g_io_win32_free
1005 };
1006
1007 static GIOFuncs win32_channel_sock_funcs = {
1008   g_io_win32_sock_read,
1009   g_io_win32_sock_write,
1010   g_io_win32_no_seek,
1011   g_io_win32_sock_close,
1012   g_io_win32_sock_create_watch,
1013   g_io_win32_free
1014 };
1015
1016 GIOChannel *
1017 g_io_channel_win32_new_messages (guint hwnd)
1018 {
1019   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1020   GIOChannel *channel = (GIOChannel *)win32_channel;
1021
1022   g_io_channel_init (channel);
1023   g_io_channel_win32_init (win32_channel);
1024   if (win32_channel->debug)
1025     g_print ("g_io_channel_win32_new_messages: hwnd = %ud\n", hwnd);
1026   channel->funcs = &win32_channel_msg_funcs;
1027   win32_channel->type = G_IO_WIN32_WINDOWS_MESSAGES;
1028   win32_channel->hwnd = (HWND) hwnd;
1029
1030   return channel;
1031 }
1032
1033 GIOChannel *
1034 g_io_channel_win32_new_fd (gint fd)
1035 {
1036   GIOWin32Channel *win32_channel;
1037   GIOChannel *channel;
1038   struct stat st;
1039
1040   if (fstat (fd, &st) == -1)
1041     {
1042       g_warning (G_STRLOC ": %d isn't a (emulated) file descriptor", fd);
1043       return NULL;
1044     }
1045
1046   win32_channel = g_new (GIOWin32Channel, 1);
1047   channel = (GIOChannel *)win32_channel;
1048
1049   g_io_channel_init (channel);
1050   g_io_channel_win32_init (win32_channel);
1051   if (win32_channel->debug)
1052     g_print ("g_io_channel_win32_new_fd: fd = %d\n", fd);
1053   channel->funcs = &win32_channel_fd_funcs;
1054   win32_channel->type = G_IO_WIN32_FILE_DESC;
1055   win32_channel->fd = fd;
1056
1057   return channel;
1058 }
1059
1060 gint
1061 g_io_channel_win32_get_fd (GIOChannel *channel)
1062 {
1063   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1064
1065   return win32_channel->fd;
1066 }
1067
1068 GIOChannel *
1069 g_io_channel_win32_new_socket (int socket)
1070 {
1071   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1072   GIOChannel *channel = (GIOChannel *)win32_channel;
1073
1074   g_io_channel_init (channel);
1075   g_io_channel_win32_init (win32_channel);
1076   if (win32_channel->debug)
1077     g_print ("g_io_channel_win32_new_socket: sockfd:%d\n", socket);
1078   channel->funcs = &win32_channel_sock_funcs;
1079   win32_channel->type = G_IO_WIN32_SOCKET;
1080   win32_channel->fd = socket;
1081
1082   return channel;
1083 }
1084
1085 GIOChannel *
1086 g_io_channel_unix_new (gint fd)
1087 {
1088   struct stat st;
1089
1090   if (fstat (fd, &st) == 0)
1091     return g_io_channel_win32_new_fd (fd);
1092   
1093   if (getsockopt (fd, SOL_SOCKET, SO_TYPE, NULL, NULL) != SO_ERROR)
1094     return g_io_channel_win32_new_socket(fd);
1095
1096   g_warning (G_STRLOC ": %d is neither a file descriptor or a socket", fd);
1097   return NULL;
1098 }
1099
1100 gint
1101 g_io_channel_unix_get_fd (GIOChannel *channel)
1102 {
1103   return g_io_channel_win32_get_fd (channel);
1104 }
1105
1106 void
1107 g_io_channel_win32_set_debug (GIOChannel *channel,
1108                               gboolean    flag)
1109 {
1110   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1111
1112   win32_channel->debug = flag;
1113 }
1114
1115 gint
1116 g_io_channel_win32_poll (GPollFD *fds,
1117                          gint     n_fds,
1118                          gint     timeout)
1119 {
1120   int result;
1121
1122   g_return_val_if_fail (n_fds >= 0, 0);
1123
1124   result = (*g_main_context_get_poll_func (NULL)) (fds, n_fds, timeout);
1125
1126   return result;
1127 }
1128
1129 void
1130 g_io_channel_win32_make_pollfd (GIOChannel   *channel,
1131                                 GIOCondition  condition,
1132                                 GPollFD      *fd)
1133 {
1134   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1135
1136   if (win32_channel->data_avail_event == NULL)
1137     create_events (win32_channel);
1138   
1139   fd->fd = (gint) win32_channel->data_avail_event;
1140   fd->events = condition;
1141
1142   if (win32_channel->thread_id == 0)
1143     if ((condition & G_IO_IN) && win32_channel->type == G_IO_WIN32_FILE_DESC)
1144       create_thread (win32_channel, condition, read_thread);
1145     else if (win32_channel->type == G_IO_WIN32_SOCKET)
1146       create_thread (win32_channel, condition, select_thread);
1147 }
1148
1149 /* Binary compatibility */
1150 GIOChannel *
1151 g_io_channel_win32_new_stream_socket (int socket)
1152 {
1153   return g_io_channel_win32_new_socket (socket);
1154 }