giochannel.h giowin32.c Stylistic cleanups. Use G_STRLOC in g_warning()
[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  *
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   GIOWin32Watch *watch = (GIOWin32Watch *)source;
515   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
516   
517   if (channel->debug)
518     g_print ("g_io_win32_check: for thread %#x:\n"
519              "\twatch->pollfd.events:%#x, watch->pollfd.revents:%#x, channel->revents:%#x\n",
520              channel->thread_id,
521              watch->pollfd.events, watch->pollfd.revents, channel->revents);
522
523   if (channel->type != G_IO_WIN32_WINDOWS_MESSAGES)
524     watch->pollfd.revents = (watch->pollfd.events & channel->revents);
525
526   if (channel->type == G_IO_WIN32_SOCKET)
527     {
528       if (channel->debug)
529         g_print ("g_io_win32_check: thread %#x, resetting data_avail\n",
530                  channel->thread_id);
531       ResetEvent (channel->data_avail_event);
532       if (channel->debug)
533         g_print ("g_io_win32_check: thread %#x, there.\n",
534                  channel->thread_id);
535     }
536   
537   return (watch->pollfd.revents & watch->condition);
538 }
539
540 static gboolean
541 g_io_win32_dispatch (GSource     *source,
542                      GSourceFunc  callback,
543                      gpointer     user_data)
544 {
545   GIOFunc func = (GIOFunc)callback;
546   GIOWin32Watch *watch = (GIOWin32Watch *)source;
547   
548   if (!func)
549     {
550       g_warning (G_STRLOC ": GIOWin32Watch dispatched without callback\n"
551                  "You must call g_source_connect().");
552       return FALSE;
553     }
554   
555   return (*func) (watch->channel,
556                   watch->pollfd.revents & watch->condition,
557                   user_data);
558 }
559
560 static void
561 g_io_win32_destroy (GSource *source)
562 {
563   GIOWin32Watch *watch = (GIOWin32Watch *)source;
564   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
565   
566   if (channel->debug)
567     g_print ("g_io_win32_destroy: channel with thread %#x\n",
568              channel->thread_id);
569
570   channel->watches = g_slist_remove (channel->watches, watch);
571
572   g_io_channel_unref (watch->channel);
573 }
574
575 static GSourceFuncs win32_watch_funcs = {
576   g_io_win32_prepare,
577   g_io_win32_check,
578   g_io_win32_dispatch,
579   g_io_win32_destroy
580 };
581
582 static GSource *
583 g_io_win32_create_watch (GIOChannel    *channel,
584                          GIOCondition   condition,
585                          unsigned (__stdcall *thread) (void *parameter))
586 {
587   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
588   GIOWin32Watch *watch;
589   GSource *source;
590
591   source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
592   watch = (GIOWin32Watch *)source;
593   
594   watch->channel = channel;
595   g_io_channel_ref (channel);
596   
597   watch->condition = condition;
598   
599   if (win32_channel->data_avail_event == NULL)
600     create_events (win32_channel);
601
602   watch->pollfd.fd = (gint) win32_channel->data_avail_event;
603   watch->pollfd.events = condition;
604   
605   if (win32_channel->debug)
606     g_print ("g_io_win32_create_watch: fd:%d condition:%#x handle:%#x\n",
607              win32_channel->fd, condition, watch->pollfd.fd);
608   
609   win32_channel->watches = g_slist_append (win32_channel->watches, watch);
610
611   if (win32_channel->thread_id == 0)
612     create_thread (win32_channel, condition, thread);
613
614   g_source_add_poll (source, &watch->pollfd);
615   
616   return source;
617 }
618
619 static GIOError
620 g_io_win32_msg_read (GIOChannel *channel,
621                      gchar      *buf,
622                      guint       count,
623                      guint      *bytes_read)
624 {
625   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
626   MSG msg;               /* In case of alignment problems */
627   
628   if (count < sizeof (MSG))
629     return G_IO_ERROR_INVAL;
630   
631   if (win32_channel->debug)
632     g_print ("g_io_win32_msg_read: for %#x\n",
633              win32_channel->hwnd);
634   if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
635     return G_IO_ERROR_AGAIN;
636   
637   memmove (buf, &msg, sizeof (MSG));
638   *bytes_read = sizeof (MSG);
639   return G_IO_ERROR_NONE;
640 }
641
642 static GIOError
643 g_io_win32_msg_write (GIOChannel *channel,
644                       gchar      *buf,
645                       guint       count,
646                       guint      *bytes_written)
647 {
648   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
649   MSG msg;
650   
651   if (count != sizeof (MSG))
652     return G_IO_ERROR_INVAL;
653   
654   /* In case of alignment problems */
655   memmove (&msg, buf, sizeof (MSG));
656   if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
657     return G_IO_ERROR_UNKNOWN;
658   
659   *bytes_written = sizeof (MSG);
660   return G_IO_ERROR_NONE;
661 }
662
663 static GIOError
664 g_io_win32_no_seek (GIOChannel *channel,
665                     gint        offset,
666                     GSeekType   type)
667 {
668   return G_IO_ERROR_UNKNOWN;
669 }
670
671 static void
672 g_io_win32_msg_close (GIOChannel *channel)
673 {
674   /* Nothing to be done. Or should we set hwnd to some invalid value? */
675 }
676
677 static void
678 g_io_win32_free (GIOChannel *channel)
679 {
680   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
681   
682   if (win32_channel->debug)
683     g_print ("thread %#x: freeing channel, fd: %d\n",
684              win32_channel->thread_id,
685              win32_channel->fd);
686
687   if (win32_channel->data_avail_event)
688     CloseHandle (win32_channel->data_avail_event);
689   if (win32_channel->space_avail_event)
690     CloseHandle (win32_channel->space_avail_event);
691   if (win32_channel->data_avail_noticed_event)
692     CloseHandle (win32_channel->data_avail_noticed_event);
693   DeleteCriticalSection (&win32_channel->mutex);
694
695   g_free (win32_channel->buffer);
696   g_slist_free (win32_channel->watches);
697   g_free (win32_channel);
698 }
699
700 static GSource *
701 g_io_win32_msg_create_watch (GIOChannel    *channel,
702                              GIOCondition   condition)
703 {
704   GIOWin32Watch *watch;
705   GSource *source;
706
707   source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
708   watch = (GIOWin32Watch *)source;
709   
710   watch->channel = channel;
711   g_io_channel_ref (channel);
712   
713   watch->condition = condition;
714   
715   watch->pollfd.fd = G_WIN32_MSG_HANDLE;
716   watch->pollfd.events = condition;
717   
718   g_source_add_poll (source, &watch->pollfd);
719   
720   return source;
721 }
722
723 static GIOError
724 g_io_win32_fd_read (GIOChannel *channel,
725                     gchar      *buf,
726                     guint       count,
727                     guint      *bytes_read)
728 {
729   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
730   gint result;
731   GIOError error;
732   
733   if (win32_channel->debug)
734     g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
735              win32_channel->fd, count);
736   
737   if (win32_channel->thread_id)
738     {
739       result = buffer_read (win32_channel, buf, count, &error);
740       if (result < 0)
741         {
742           *bytes_read = 0;
743           return error;
744         }
745       else
746         {
747           *bytes_read = result;
748           return G_IO_ERROR_NONE;
749         }
750     }
751
752   result = read (win32_channel->fd, buf, count);
753
754   if (result < 0)
755     {
756       *bytes_read = 0;
757       if (errno == EINVAL)
758         return G_IO_ERROR_INVAL;
759       else
760         return G_IO_ERROR_UNKNOWN;
761     }
762   else
763     {
764       *bytes_read = result;
765       return G_IO_ERROR_NONE;
766     }
767 }
768
769 static GIOError
770 g_io_win32_fd_write (GIOChannel *channel,
771                      gchar      *buf,
772                      guint       count,
773                      guint      *bytes_written)
774 {
775   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
776   gint result;
777   
778   result = write (win32_channel->fd, buf, count);
779   if (win32_channel->debug)
780     g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
781              win32_channel->fd, count, result);
782   
783   if (result < 0)
784     {
785       *bytes_written = 0;
786       switch (errno)
787         {
788         case EINVAL:
789           return G_IO_ERROR_INVAL;
790         case EAGAIN:
791           return G_IO_ERROR_AGAIN;
792         default:
793           return G_IO_ERROR_UNKNOWN;
794         }
795     }
796   else
797     {
798       *bytes_written = result;
799       return G_IO_ERROR_NONE;
800     }
801 }
802
803 static GIOError
804 g_io_win32_fd_seek (GIOChannel *channel,
805                     gint        offset,
806                     GSeekType   type)
807 {
808   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
809   int whence;
810   off_t result;
811   
812   switch (type)
813     {
814     case G_SEEK_SET:
815       whence = SEEK_SET;
816       break;
817     case G_SEEK_CUR:
818       whence = SEEK_CUR;
819       break;
820     case G_SEEK_END:
821       whence = SEEK_END;
822       break;
823     default:
824       g_warning (G_STRLOC ": Unknown seek type %d", (int) type);
825       return G_IO_ERROR_UNKNOWN;
826     }
827   
828   result = lseek (win32_channel->fd, offset, whence);
829   
830   if (result < 0)
831     {
832       switch (errno)
833         {
834         case EINVAL:
835           return G_IO_ERROR_INVAL;
836         default:
837           return G_IO_ERROR_UNKNOWN;
838         }
839     }
840   else
841     return G_IO_ERROR_NONE;
842 }
843
844 static void
845 g_io_win32_fd_close (GIOChannel *channel)
846 {
847   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
848   
849   if (win32_channel->debug)
850     g_print ("thread %#x: closing fd %d\n",
851              win32_channel->thread_id,
852              win32_channel->fd);
853   LOCK (win32_channel->mutex);
854   if (win32_channel->running)
855     {
856       if (win32_channel->debug)
857         g_print ("thread %#x: running, marking fd %d for later close\n",
858                  win32_channel->thread_id, win32_channel->fd);
859       win32_channel->running = FALSE;
860       win32_channel->needs_close = TRUE;
861       SetEvent (win32_channel->data_avail_event);
862     }
863   else
864     {
865       if (win32_channel->debug)
866         g_print ("closing fd %d\n", win32_channel->fd);
867       close (win32_channel->fd);
868       if (win32_channel->debug)
869         g_print ("closed fd %d, setting to -1\n",
870                  win32_channel->fd);
871       win32_channel->fd = -1;
872     }
873   UNLOCK (win32_channel->mutex);
874 }
875
876 static GSource *
877 g_io_win32_fd_create_watch (GIOChannel    *channel,
878                             GIOCondition   condition)
879 {
880   return g_io_win32_create_watch (channel, condition, read_thread);
881 }
882
883 static GIOError
884 g_io_win32_sock_read (GIOChannel *channel,
885                       gchar      *buf,
886                       guint       count,
887                       guint      *bytes_read)
888 {
889   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
890   gint result;
891   GIOError error;
892
893   if (win32_channel->debug)
894     g_print ("g_io_win32_sock_read: sockfd:%d count:%d\n",
895              win32_channel->fd, count);
896   
897   result = recv (win32_channel->fd, buf, count, 0);
898
899   if (win32_channel->debug)
900     g_print ("g_io_win32_sock_read: recv:%d\n", result);
901   
902   if (result == SOCKET_ERROR)
903     {
904       *bytes_read = 0;
905       switch (WSAGetLastError ())
906         {
907         case WSAEINVAL:
908           return G_IO_ERROR_INVAL;
909         case WSAEWOULDBLOCK:
910         case WSAEINTR:
911           return G_IO_ERROR_AGAIN;
912         default:
913           return G_IO_ERROR_UNKNOWN;
914         }
915     }
916   else
917     {
918       *bytes_read = result;
919       return G_IO_ERROR_NONE;
920     }
921 }
922
923 static GIOError
924 g_io_win32_sock_write (GIOChannel *channel,
925                        gchar      *buf,
926                        guint       count,
927                        guint      *bytes_written)
928 {
929   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
930   gint result;
931   
932   if (win32_channel->debug)
933     g_print ("g_io_win32_sock_write: sockfd:%d count:%d\n",
934              win32_channel->fd, count);
935   
936   result = send (win32_channel->fd, buf, count, 0);
937   
938   if (win32_channel->debug)
939     g_print ("g_io_win32_sock_write: send:%d\n", result);
940   
941   if (result == SOCKET_ERROR)
942     {
943       *bytes_written = 0;
944       switch (WSAGetLastError ())
945         {
946         case WSAEINVAL:
947           return G_IO_ERROR_INVAL;
948         case WSAEWOULDBLOCK:
949         case WSAEINTR:
950           return G_IO_ERROR_AGAIN;
951         default:
952           return G_IO_ERROR_UNKNOWN;
953         }
954     }
955   else
956     {
957       *bytes_written = result;
958       return G_IO_ERROR_NONE;
959     }
960 }
961
962 static void
963 g_io_win32_sock_close (GIOChannel *channel)
964 {
965   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
966
967   if (win32_channel->debug)
968     g_print ("thread %#x: closing socket %d\n",
969              win32_channel->thread_id,
970              win32_channel->fd);
971   closesocket (win32_channel->fd);
972   win32_channel->fd = -1;
973 }
974
975 static GSource *
976 g_io_win32_sock_create_watch (GIOChannel    *channel,
977                               GIOCondition   condition)
978 {
979   return g_io_win32_create_watch (channel, condition, select_thread);
980 }
981
982 static GIOFuncs win32_channel_msg_funcs = {
983   g_io_win32_msg_read,
984   g_io_win32_msg_write,
985   g_io_win32_no_seek,
986   g_io_win32_msg_close,
987   g_io_win32_msg_create_watch,
988   g_io_win32_free
989 };
990
991 static GIOFuncs win32_channel_fd_funcs = {
992   g_io_win32_fd_read,
993   g_io_win32_fd_write,
994   g_io_win32_fd_seek,
995   g_io_win32_fd_close,
996   g_io_win32_fd_create_watch,
997   g_io_win32_free
998 };
999
1000 static GIOFuncs win32_channel_sock_funcs = {
1001   g_io_win32_sock_read,
1002   g_io_win32_sock_write,
1003   g_io_win32_no_seek,
1004   g_io_win32_sock_close,
1005   g_io_win32_sock_create_watch,
1006   g_io_win32_free
1007 };
1008
1009 GIOChannel *
1010 g_io_channel_win32_new_messages (guint hwnd)
1011 {
1012   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1013   GIOChannel *channel = (GIOChannel *)win32_channel;
1014
1015   g_io_channel_init (channel);
1016   g_io_channel_win32_init (win32_channel);
1017   if (win32_channel->debug)
1018     g_print ("g_io_channel_win32_new_messages: hwnd = %ud\n", hwnd);
1019   channel->funcs = &win32_channel_msg_funcs;
1020   win32_channel->type = G_IO_WIN32_WINDOWS_MESSAGES;
1021   win32_channel->hwnd = (HWND) hwnd;
1022
1023   return channel;
1024 }
1025
1026 GIOChannel *
1027 g_io_channel_win32_new_fd (gint fd)
1028 {
1029   GIOWin32Channel *win32_channel;
1030   GIOChannel *channel;
1031   struct stat st;
1032
1033   if (fstat (fd, &st) == -1)
1034     {
1035       g_warning (G_STRLOC ": %d isn't a (emulated) file descriptor", fd);
1036       return NULL;
1037     }
1038
1039   win32_channel = g_new (GIOWin32Channel, 1);
1040   channel = (GIOChannel *)win32_channel;
1041
1042   g_io_channel_init (channel);
1043   g_io_channel_win32_init (win32_channel);
1044   if (win32_channel->debug)
1045     g_print ("g_io_channel_win32_new_fd: fd = %d\n", fd);
1046   channel->funcs = &win32_channel_fd_funcs;
1047   win32_channel->type = G_IO_WIN32_FILE_DESC;
1048   win32_channel->fd = fd;
1049
1050   return channel;
1051 }
1052
1053 gint
1054 g_io_channel_win32_get_fd (GIOChannel *channel)
1055 {
1056   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1057
1058   return win32_channel->fd;
1059 }
1060
1061 GIOChannel *
1062 g_io_channel_win32_new_socket (int socket)
1063 {
1064   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1065   GIOChannel *channel = (GIOChannel *)win32_channel;
1066
1067   g_io_channel_init (channel);
1068   g_io_channel_win32_init (win32_channel);
1069   if (win32_channel->debug)
1070     g_print ("g_io_channel_win32_new_socket: sockfd:%d\n", socket);
1071   channel->funcs = &win32_channel_sock_funcs;
1072   win32_channel->type = G_IO_WIN32_SOCKET;
1073   win32_channel->fd = socket;
1074
1075   return channel;
1076 }
1077
1078 GIOChannel *
1079 g_io_channel_unix_new (gint fd)
1080 {
1081   struct stat st;
1082
1083   if (fstat (fd, &st) == 0)
1084     return g_io_channel_win32_new_fd (fd);
1085   
1086   if (getsockopt (fd, SOL_SOCKET, SO_TYPE, NULL, NULL) != SO_ERROR)
1087     return g_io_channel_win32_new_socket(fd);
1088
1089   g_warning (G_STRLOC ": %d is neither a file descriptor or a socket", fd);
1090   return NULL;
1091 }
1092
1093 gint
1094 g_io_channel_unix_get_fd (GIOChannel *channel)
1095 {
1096   return g_io_channel_win32_get_fd (channel);
1097 }
1098
1099 void
1100 g_io_channel_win32_set_debug (GIOChannel *channel,
1101                               gboolean    flag)
1102 {
1103   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1104
1105   win32_channel->debug = flag;
1106 }
1107
1108 gint
1109 g_io_channel_win32_poll (GPollFD *fds,
1110                          gint     n_fds,
1111                          gint     timeout)
1112 {
1113   int result;
1114
1115   g_return_val_if_fail (n_fds >= 0, 0);
1116
1117   result = (*g_main_context_get_poll_func (NULL)) (fds, n_fds, timeout);
1118
1119   return result;
1120 }
1121
1122 void
1123 g_io_channel_win32_make_pollfd (GIOChannel   *channel,
1124                                 GIOCondition  condition,
1125                                 GPollFD      *fd)
1126 {
1127   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1128
1129   if (win32_channel->data_avail_event == NULL)
1130     create_events (win32_channel);
1131   
1132   fd->fd = (gint) win32_channel->data_avail_event;
1133   fd->events = condition;
1134
1135   if (win32_channel->thread_id == 0)
1136     if ((condition & G_IO_IN) && win32_channel->type == G_IO_WIN32_FILE_DESC)
1137       create_thread (win32_channel, condition, read_thread);
1138     else if (win32_channel->type == G_IO_WIN32_SOCKET)
1139       create_thread (win32_channel, condition, select_thread);
1140 }
1141
1142 /* Binary compatibility */
1143 GIOChannel *
1144 g_io_channel_win32_new_stream_socket (int socket)
1145 {
1146   return g_io_channel_win32_new_socket (socket);
1147 }