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