Free the callback (g_source_set_callback): Initialize the callback
[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_WINDOWS_MESSAGES,        /* Windows messages */
52   G_IO_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_STREAM_SOCKET            /* Stream sockets. Similar as fds, but
57                                  * read with recv().
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   /* This is used by G_IO_WINDOWS_MESSAGES channels */
72   HWND hwnd;                    /* handle of window, or NULL */
73   
74   /* Following fields used by fd and socket channels for input */
75   
76   /* Data is kept in a circular buffer. To be able to distinguish between
77    * empty and full buffer, we cannot fill it completely, but have to
78    * leave a one character gap.
79    *
80    * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
81    *
82    * Empty:    wrp == rdp
83    * Full:     (wrp + 1) % BUFFER_SIZE == rdp
84    * Partial:  otherwise
85    */
86   guchar *buffer;               /* (Circular) buffer */
87   gint wrp, rdp;                /* Buffer indices for writing and reading */
88   gboolean running;             /* Is reader thread running. FALSE if
89                                  * EOF has been reached.
90                                  */
91   gboolean needs_close;         /* If the channel has been closed while
92                                  * the reader thread was still running.
93                                  */
94   guint thread_id;              /* If non-NULL has a reader thread, or has
95                                  * had.*/
96   HANDLE thread_handle;
97   HANDLE data_avail_event;
98   HANDLE space_avail_event;
99   CRITICAL_SECTION mutex;
100   
101   /* Function that actually reads from fd */
102   int (*reader) (int fd, guchar *buf, int len);
103 };
104
105 #define LOCK(mutex) EnterCriticalSection (&mutex)
106 #define UNLOCK(mutex) LeaveCriticalSection (&mutex)
107
108 struct _GIOWin32Watch {
109   GSource       source;
110   GPollFD       pollfd;
111   GIOChannel   *channel;
112   GIOCondition  condition;
113   GIOFunc       callback;
114 };
115
116 static void
117 g_io_channel_win32_init (GIOWin32Channel *channel)
118 {
119 #ifdef G_IO_WIN32_DEBUG
120   channel->debug = TRUE;
121 #else
122   if (getenv ("G_IO_WIN32_DEBUG") != NULL)
123     channel->debug = TRUE;
124   else
125     channel->debug = FALSE;
126 #endif
127   channel->buffer = NULL;
128   channel->running = FALSE;
129   channel->needs_close = FALSE;
130   channel->thread_id = 0;
131   channel->data_avail_event = NULL;
132   channel->space_avail_event = NULL;
133   InitializeCriticalSection (&channel->mutex);
134 }
135
136 static void
137 create_events (GIOWin32Channel *channel)
138 {
139   SECURITY_ATTRIBUTES sec_attrs;
140   
141   sec_attrs.nLength = sizeof(SECURITY_ATTRIBUTES);
142   sec_attrs.lpSecurityDescriptor = NULL;
143   sec_attrs.bInheritHandle = FALSE;
144
145   /* The data available event is manual reset, the space available event
146    * is automatic reset.
147    */
148   if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
149       || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
150     {
151       gchar *msg = g_win32_error_message (GetLastError ());
152       g_error ("Error creating event: %s", msg);
153     }
154 }
155
156 static unsigned __stdcall
157 reader_thread (void *parameter)
158 {
159   GIOWin32Channel *channel = parameter;
160   guchar *buffer;
161   guint nbytes;
162
163   g_io_channel_ref ((GIOChannel *) channel);
164
165   if (channel->debug)
166     g_print ("thread %#x: starting. pid:%#x, fd:%d, data_avail:%#x, space_avail:%#x\n",
167              channel->thread_id,
168              (guint) GetCurrentProcessId (),
169              channel->fd,
170              (guint) channel->data_avail_event,
171              (guint) channel->space_avail_event);
172   
173   channel->buffer = g_malloc (BUFFER_SIZE);
174   channel->rdp = channel->wrp = 0;
175   channel->running = TRUE;
176
177   SetEvent (channel->space_avail_event);
178   
179   while (channel->running)
180     {
181       LOCK (channel->mutex);
182       if (channel->debug)
183         g_print ("thread %#x: rdp=%d, wrp=%d\n",
184                  channel->thread_id, channel->rdp, channel->wrp);
185       if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
186         {
187           /* Buffer is full */
188           if (channel->debug)
189             g_print ("thread %#x: resetting space_available\n",
190                      channel->thread_id);
191           ResetEvent (channel->space_avail_event);
192           if (channel->debug)
193             g_print ("thread %#x: waiting for space\n", channel->thread_id);
194           UNLOCK (channel->mutex);
195           WaitForSingleObject (channel->space_avail_event, INFINITE);
196           LOCK (channel->mutex);
197           if (channel->debug)
198             g_print ("thread %#x: rdp=%d, wrp=%d\n",
199                      channel->thread_id, channel->rdp, channel->wrp);
200         }
201       
202       buffer = channel->buffer + channel->wrp;
203       
204       /* Always leave at least one byte unused gap to be able to
205        * distinguish between the full and empty condition...
206        */
207       nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
208                     BUFFER_SIZE - channel->wrp);
209
210       if (channel->debug)
211         g_print ("thread %#x: calling reader for %d bytes\n",
212                  channel->thread_id, nbytes);
213
214       UNLOCK (channel->mutex);
215
216       nbytes = (*channel->reader) (channel->fd, buffer, nbytes);
217       
218       LOCK (channel->mutex);
219
220       if (channel->debug)
221         g_print ("thread %#x: got %d bytes, rdp=%d, wrp=%d\n",
222                  channel->thread_id, nbytes, channel->rdp, channel->wrp);
223
224       if (nbytes <= 0)
225         break;
226
227       channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
228       if (channel->debug)
229         g_print ("thread %#x: rdp=%d, wrp=%d, setting data available\n",
230                  channel->thread_id, channel->rdp, channel->wrp);
231       SetEvent (channel->data_avail_event);
232       UNLOCK (channel->mutex);
233     }
234   
235   channel->running = FALSE;
236   if (channel->debug)
237     g_print ("thread %#x: got EOF, rdp=%d, wrp=%d, setting data available\n",
238              channel->thread_id, channel->rdp, channel->wrp);
239
240   if (channel->needs_close)
241     {
242       if (channel->debug)
243         g_print ("thread %#x: channel fd %d needs closing\n",
244                  channel->thread_id, channel->fd);
245       if (channel->type == G_IO_FILE_DESC)
246         close (channel->fd);
247       else if (channel->type == G_IO_STREAM_SOCKET)
248         closesocket (channel->fd);
249       channel->fd = -1;
250     }
251
252   SetEvent (channel->data_avail_event);
253   UNLOCK (channel->mutex);
254   
255   g_io_channel_unref((GIOChannel *) channel);
256   
257   /* No need to call _endthreadex(), the actual thread starter routine
258    * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
259    * _endthreadex() for us.
260    */
261
262   CloseHandle (channel->thread_handle);
263
264   return 0;
265 }
266
267 static void
268 create_reader_thread (GIOWin32Channel *channel,
269                       gpointer         reader)
270 {
271   channel->reader = reader;
272
273   if ((channel->thread_handle =
274        (HANDLE) _beginthreadex (NULL, 0, reader_thread, channel, 0,
275                                 &channel->thread_id)) == 0)
276     g_warning ("Error creating reader thread: %s", strerror (errno));
277   WaitForSingleObject (channel->space_avail_event, INFINITE);
278 }
279
280 static int
281 buffer_read (GIOWin32Channel *channel,
282              guchar          *dest,
283              guint            count,
284              GIOError        *error)
285 {
286   guint nbytes;
287   guint left = count;
288   
289   LOCK (channel->mutex);
290   if (channel->debug)
291     g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
292              channel->thread_id, count, channel->rdp, channel->wrp);
293   
294   if (channel->rdp == channel->wrp)
295     {
296       UNLOCK (channel->mutex);
297       if (channel->debug)
298         g_print ("waiting for data from thread %#x\n", channel->thread_id);
299       WaitForSingleObject (channel->data_avail_event, INFINITE);
300       if (channel->debug)
301         g_print ("done waiting for data from thread %#x\n", channel->thread_id);
302       LOCK (channel->mutex);
303       if (channel->rdp == channel->wrp && !channel->running)
304         {
305           UNLOCK (channel->mutex);
306           return 0;
307         }
308     }
309   
310   if (channel->rdp < channel->wrp)
311     nbytes = channel->wrp - channel->rdp;
312   else
313     nbytes = BUFFER_SIZE - channel->rdp;
314   UNLOCK (channel->mutex);
315   nbytes = MIN (left, nbytes);
316   if (channel->debug)
317     g_print ("moving %d bytes from thread %#x\n",
318              nbytes, channel->thread_id);
319   memcpy (dest, channel->buffer + channel->rdp, nbytes);
320   dest += nbytes;
321   left -= nbytes;
322   LOCK (channel->mutex);
323   channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
324   if (channel->debug)
325     g_print ("setting space available for thread %#x\n", channel->thread_id);
326   SetEvent (channel->space_avail_event);
327   if (channel->debug)
328     g_print ("for thread %#x: rdp=%d, wrp=%d\n",
329              channel->thread_id, channel->rdp, channel->wrp);
330   if (channel->running && channel->rdp == channel->wrp)
331     {
332       if (channel->debug)
333         g_print ("resetting data_available of thread %#x\n",
334                  channel->thread_id);
335       ResetEvent (channel->data_avail_event);
336     };
337   UNLOCK (channel->mutex);
338   
339   /* We have no way to indicate any errors form the actual
340    * read() or recv() call in the reader thread. Should we have?
341    */
342   *error = G_IO_ERROR_NONE;
343   return count - left;
344 }
345
346 static gboolean
347 g_io_win32_prepare (GSource *source,
348                     gint    *timeout)
349 {
350   *timeout = -1;
351   
352   return FALSE;
353 }
354
355 static gboolean
356 g_io_win32_check (GSource *source)
357 {
358   GIOWin32Watch *watch = (GIOWin32Watch *)source;
359   GIOWin32Channel *channel = (GIOWin32Channel *) watch->channel;
360   
361   /* If the thread has died, we have encountered EOF. If the buffer
362    * also is emtpty set the HUP bit.
363    */
364   if (!channel->running && channel->rdp == channel->wrp)
365     {
366       if (channel->debug)
367         g_print ("g_io_win32_check: setting G_IO_HUP thread %#x rdp=%d wrp=%d\n",
368                  channel->thread_id, channel->rdp, channel->wrp);
369       watch->pollfd.revents |= G_IO_HUP;
370       return TRUE;
371     }
372   
373   return (watch->pollfd.revents & watch->condition);
374 }
375
376 static gboolean
377 g_io_win32_dispatch (GSource     *source,
378                      GSourceFunc  callback,
379                      gpointer     user_data)
380 {
381   GIOFunc func = (GIOFunc)callback;
382   GIOWin32Watch *watch = (GIOWin32Watch *)source;
383   
384   if (!func)
385     {
386       g_warning ("GIOWin32Watch dispatched without callback\n"
387                  "You must call g_source_connect().");
388       return FALSE;
389     }
390   
391   return (*func) (watch->channel,
392                   watch->pollfd.revents & watch->condition,
393                   user_data);
394 }
395
396 static void
397 g_io_win32_destroy (GSource *source)
398 {
399   GIOWin32Watch *watch = (GIOWin32Watch *)source;
400   
401   g_io_channel_unref (watch->channel);
402 }
403
404 static GSourceFuncs win32_watch_funcs = {
405   g_io_win32_prepare,
406   g_io_win32_check,
407   g_io_win32_dispatch,
408   g_io_win32_destroy
409 };
410
411 static GSource *
412 g_io_win32_create_watch (GIOChannel    *channel,
413                          GIOCondition   condition,
414                          int (*reader) (int, guchar *, int))
415 {
416   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
417   GIOWin32Watch *watch;
418   GSource *source;
419
420   source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
421   watch = (GIOWin32Watch *)source;
422   
423   watch->channel = channel;
424   g_io_channel_ref (channel);
425   
426   watch->condition = condition;
427   
428   if (win32_channel->data_avail_event == NULL)
429     create_events (win32_channel);
430
431   watch->pollfd.fd = (gint) win32_channel->data_avail_event;
432   watch->pollfd.events = condition;
433   
434   if (win32_channel->debug)
435     g_print ("g_io_win32_create_watch: fd:%d handle:%#x\n",
436              win32_channel->fd, watch->pollfd.fd);
437   
438   if (win32_channel->thread_id == 0)
439     create_reader_thread (win32_channel, reader);
440
441   g_source_add_poll (source, &watch->pollfd);
442   
443   return source;
444 }
445
446 static GIOError
447 g_io_win32_msg_read (GIOChannel *channel,
448                      gchar      *buf,
449                      guint       count,
450                      guint      *bytes_read)
451 {
452   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
453   MSG msg;               /* In case of alignment problems */
454   
455   if (count < sizeof (MSG))
456     return G_IO_ERROR_INVAL;
457   
458   if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
459     return G_IO_ERROR_AGAIN;
460   
461   memmove (buf, &msg, sizeof (MSG));
462   *bytes_read = sizeof (MSG);
463   return G_IO_ERROR_NONE;
464 }
465
466 static GIOError
467 g_io_win32_msg_write (GIOChannel *channel,
468                       gchar      *buf,
469                       guint       count,
470                       guint      *bytes_written)
471 {
472   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
473   MSG msg;
474   
475   if (count != sizeof (MSG))
476     return G_IO_ERROR_INVAL;
477   
478   /* In case of alignment problems */
479   memmove (&msg, buf, sizeof (MSG));
480   if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
481     return G_IO_ERROR_UNKNOWN;
482   
483   *bytes_written = sizeof (MSG);
484   return G_IO_ERROR_NONE;
485 }
486
487 static GIOError
488 g_io_win32_no_seek (GIOChannel *channel,
489                     gint        offset,
490                     GSeekType   type)
491 {
492   return G_IO_ERROR_UNKNOWN;
493 }
494
495 static void
496 g_io_win32_msg_close (GIOChannel *channel)
497 {
498   /* Nothing to be done. Or should we set hwnd to some invalid value? */
499 }
500
501 static void
502 g_io_win32_free (GIOChannel *channel)
503 {
504   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
505   
506   if (win32_channel->debug)
507     g_print ("thread %#x: freeing channel, fd: %d\n",
508              win32_channel->thread_id,
509              win32_channel->fd);
510
511   if (win32_channel->buffer)
512     {
513       CloseHandle (win32_channel->data_avail_event);
514       CloseHandle (win32_channel->space_avail_event);
515       DeleteCriticalSection (&win32_channel->mutex);
516     }
517
518   g_free (win32_channel->buffer);
519   g_free (win32_channel);
520 }
521
522 static GSource *
523 g_io_win32_msg_create_watch (GIOChannel    *channel,
524                              GIOCondition   condition)
525 {
526   GIOWin32Watch *watch;
527   GSource *source;
528
529   source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
530   watch = (GIOWin32Watch *)source;
531   
532   watch->channel = channel;
533   g_io_channel_ref (channel);
534   
535   watch->condition = condition;
536   
537   watch->pollfd.fd = G_WIN32_MSG_HANDLE;
538   watch->pollfd.events = condition;
539   
540   g_source_add_poll (source, &watch->pollfd);
541   
542   return source;
543 }
544
545 static GIOError
546 g_io_win32_fd_read (GIOChannel *channel,
547                     gchar      *buf,
548                     guint       count,
549                     guint      *bytes_read)
550 {
551   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
552   gint result;
553   GIOError error;
554   
555   if (win32_channel->debug)
556     g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
557              win32_channel->fd, count);
558   
559   if (win32_channel->thread_id)
560     {
561       result = buffer_read (win32_channel, buf, count, &error);
562       if (result < 0)
563         {
564           *bytes_read = 0;
565           return error;
566         }
567       else
568         {
569           *bytes_read = result;
570           return G_IO_ERROR_NONE;
571         }
572     }
573
574   result = read (win32_channel->fd, buf, count);
575
576   if (result < 0)
577     {
578       *bytes_read = 0;
579       if (errno == EINVAL)
580         return G_IO_ERROR_INVAL;
581       else
582         return G_IO_ERROR_UNKNOWN;
583     }
584   else
585     {
586       *bytes_read = result;
587       return G_IO_ERROR_NONE;
588     }
589 }
590
591 static GIOError
592 g_io_win32_fd_write (GIOChannel *channel,
593                      gchar      *buf,
594                      guint       count,
595                      guint      *bytes_written)
596 {
597   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
598   gint result;
599   
600   result = write (win32_channel->fd, buf, count);
601   if (win32_channel->debug)
602     g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
603              win32_channel->fd, count, result);
604   
605   if (result < 0)
606     {
607       *bytes_written = 0;
608       switch (errno)
609         {
610         case EINVAL:
611           return G_IO_ERROR_INVAL;
612         case EAGAIN:
613           return G_IO_ERROR_AGAIN;
614         default:
615           return G_IO_ERROR_UNKNOWN;
616         }
617     }
618   else
619     {
620       *bytes_written = result;
621       return G_IO_ERROR_NONE;
622     }
623 }
624
625 static GIOError
626 g_io_win32_fd_seek (GIOChannel *channel,
627                     gint        offset,
628                     GSeekType   type)
629 {
630   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
631   int whence;
632   off_t result;
633   
634   switch (type)
635     {
636     case G_SEEK_SET:
637       whence = SEEK_SET;
638       break;
639     case G_SEEK_CUR:
640       whence = SEEK_CUR;
641       break;
642     case G_SEEK_END:
643       whence = SEEK_END;
644       break;
645     default:
646       g_warning ("g_io_win32_fd_seek: unknown seek type");
647       return G_IO_ERROR_UNKNOWN;
648     }
649   
650   result = lseek (win32_channel->fd, offset, whence);
651   
652   if (result < 0)
653     {
654       switch (errno)
655         {
656         case EINVAL:
657           return G_IO_ERROR_INVAL;
658         default:
659           return G_IO_ERROR_UNKNOWN;
660         }
661     }
662   else
663     return G_IO_ERROR_NONE;
664 }
665
666 static void
667 g_io_win32_fd_close (GIOChannel *channel)
668 {
669   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
670   
671   if (win32_channel->debug)
672     g_print ("thread %#x: closing fd %d\n",
673              win32_channel->thread_id,
674              win32_channel->fd);
675   LOCK (win32_channel->mutex);
676   if (win32_channel->running)
677     {
678       if (win32_channel->debug)
679         g_print ("thread %#x: running, marking fd %d for later close\n",
680                  win32_channel->thread_id, win32_channel->fd);
681       win32_channel->running = FALSE;
682       win32_channel->needs_close = TRUE;
683       SetEvent (win32_channel->data_avail_event);
684     }
685   else
686     {
687       if (win32_channel->debug)
688         g_print ("closing fd %d\n", win32_channel->fd);
689       close (win32_channel->fd);
690       if (win32_channel->debug)
691         g_print ("closed fd %d, setting to -1\n",
692                  win32_channel->fd);
693       win32_channel->fd = -1;
694     }
695   UNLOCK (win32_channel->mutex);
696 }
697
698 static int
699 fd_reader (int     fd,
700            guchar *buf,
701            int     len)
702 {
703   return read (fd, buf, len);
704 }
705
706 static GSource *
707 g_io_win32_fd_create_watch (GIOChannel    *channel,
708                             GIOCondition   condition)
709 {
710   return g_io_win32_create_watch (channel, condition, fd_reader);
711 }
712
713 static GIOError
714 g_io_win32_sock_read (GIOChannel *channel,
715                       gchar      *buf,
716                       guint       count,
717                       guint      *bytes_read)
718 {
719   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
720   gint result;
721   GIOError error;
722   
723   if (win32_channel->thread_id)
724     {
725       result = buffer_read (win32_channel, buf, count, &error);
726       if (result < 0)
727         {
728           *bytes_read = 0;
729           return error;
730         }
731       else
732         {
733           *bytes_read = result;
734           return G_IO_ERROR_NONE;
735         }
736     }
737
738   result = recv (win32_channel->fd, buf, count, 0);
739
740   if (result < 0)
741     {
742       *bytes_read = 0;
743       return G_IO_ERROR_UNKNOWN;
744     }
745   else
746     {
747       *bytes_read = result;
748       return G_IO_ERROR_NONE;
749     }
750 }
751
752 static GIOError
753 g_io_win32_sock_write (GIOChannel *channel,
754                        gchar      *buf,
755                        guint       count,
756                        guint      *bytes_written)
757 {
758   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
759   gint result;
760   
761   result = send (win32_channel->fd, buf, count, 0);
762   
763   if (result == SOCKET_ERROR)
764     {
765       *bytes_written = 0;
766       switch (WSAGetLastError ())
767         {
768         case WSAEINVAL:
769           return G_IO_ERROR_INVAL;
770         case WSAEWOULDBLOCK:
771         case WSAEINTR:
772           return G_IO_ERROR_AGAIN;
773         default:
774           return G_IO_ERROR_UNKNOWN;
775         }
776     }
777   else
778     {
779       *bytes_written = result;
780       return G_IO_ERROR_NONE;
781     }
782 }
783
784 static void
785 g_io_win32_sock_close (GIOChannel *channel)
786 {
787   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
788
789   if (win32_channel->debug)
790     g_print ("thread %#x: closing socket %d\n",
791              win32_channel->thread_id,
792              win32_channel->fd);
793   closesocket (win32_channel->fd);
794   win32_channel->fd = -1;
795 }
796
797 static int
798 sock_reader (int     fd,
799              guchar *buf,
800              int     len)
801 {
802   return recv (fd, buf, len, 0);
803 }
804
805 static GSource *
806 g_io_win32_sock_create_watch (GIOChannel    *channel,
807                               GIOCondition   condition)
808 {
809   return g_io_win32_create_watch (channel, condition, sock_reader);
810 }
811
812 static GIOFuncs win32_channel_msg_funcs = {
813   g_io_win32_msg_read,
814   g_io_win32_msg_write,
815   g_io_win32_no_seek,
816   g_io_win32_msg_close,
817   g_io_win32_msg_create_watch,
818   g_io_win32_free
819 };
820
821 static GIOFuncs win32_channel_fd_funcs = {
822   g_io_win32_fd_read,
823   g_io_win32_fd_write,
824   g_io_win32_fd_seek,
825   g_io_win32_fd_close,
826   g_io_win32_fd_create_watch,
827   g_io_win32_free
828 };
829
830 static GIOFuncs win32_channel_sock_funcs = {
831   g_io_win32_sock_read,
832   g_io_win32_sock_write,
833   g_io_win32_no_seek,
834   g_io_win32_sock_close,
835   g_io_win32_sock_create_watch,
836   g_io_win32_free
837 };
838
839 GIOChannel *
840 g_io_channel_win32_new_messages (guint hwnd)
841 {
842   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
843   GIOChannel *channel = (GIOChannel *) win32_channel;
844
845   g_io_channel_init (channel);
846   g_io_channel_win32_init (win32_channel);
847   if (win32_channel->debug)
848     g_print ("g_io_channel_win32_new_messages: hwnd = %ud\n", hwnd);
849   channel->funcs = &win32_channel_msg_funcs;
850   win32_channel->type = G_IO_WINDOWS_MESSAGES;
851   win32_channel->hwnd = (HWND) hwnd;
852
853   return channel;
854 }
855
856 GIOChannel *
857 g_io_channel_win32_new_fd (gint fd)
858 {
859   GIOWin32Channel *win32_channel;
860   GIOChannel *channel;
861   struct stat st;
862
863   if (fstat (fd, &st) == -1)
864     {
865       g_warning ("%d isn't a (emulated) file descriptor", fd);
866       return NULL;
867     }
868
869   win32_channel = g_new (GIOWin32Channel, 1);
870   channel = (GIOChannel *) win32_channel;
871
872   g_io_channel_init (channel);
873   g_io_channel_win32_init (win32_channel);
874   if (win32_channel->debug)
875     g_print ("g_io_channel_win32_new_fd: fd = %d\n", fd);
876   channel->funcs = &win32_channel_fd_funcs;
877   win32_channel->type = G_IO_FILE_DESC;
878   win32_channel->fd = fd;
879
880   return channel;
881 }
882
883 gint
884 g_io_channel_win32_get_fd (GIOChannel *channel)
885 {
886   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
887
888   return win32_channel->fd;
889 }
890
891 GIOChannel *
892 g_io_channel_win32_new_stream_socket (int socket)
893 {
894   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
895   GIOChannel *channel = (GIOChannel *) win32_channel;
896
897   g_io_channel_init (channel);
898   g_io_channel_win32_init (win32_channel);
899   if (win32_channel->debug)
900     g_print ("g_io_channel_win32_new_stream_socket: socket = %d\n", socket);
901   channel->funcs = &win32_channel_sock_funcs;
902   win32_channel->type = G_IO_STREAM_SOCKET;
903   win32_channel->fd = socket;
904
905   return channel;
906 }
907
908 GIOChannel *
909 g_io_channel_unix_new (gint fd)
910 {
911   struct stat st;
912
913   if (fstat (fd, &st) == 0)
914     return g_io_channel_win32_new_fd (fd);
915   
916   if (getsockopt (fd, SOL_SOCKET, SO_TYPE, NULL, NULL) != SO_ERROR)
917     return g_io_channel_win32_new_stream_socket(fd);
918
919   g_warning ("%d isn't a file descriptor or a socket", fd);
920   return NULL;
921 }
922
923 gint
924 g_io_channel_unix_get_fd (GIOChannel *channel)
925 {
926   return g_io_channel_win32_get_fd (channel);
927 }
928
929 void
930 g_io_channel_win32_set_debug (GIOChannel *channel,
931                               gboolean    flag)
932 {
933   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
934
935   win32_channel->debug = flag;
936 }
937
938 gint
939 g_io_channel_win32_poll (GPollFD *fds,
940                          gint     n_fds,
941                          gint     timeout)
942 {
943   int result;
944
945   g_return_val_if_fail (n_fds >= 0, 0);
946
947   result = (*g_main_context_get_poll_func (NULL)) (fds, n_fds, timeout);
948
949   return result;
950 }
951
952 void
953 g_io_channel_win32_make_pollfd (GIOChannel   *channel,
954                                 GIOCondition  condition,
955                                 GPollFD      *fd)
956 {
957   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
958
959   if (win32_channel->data_avail_event == NULL)
960     create_events (win32_channel);
961   
962   fd->fd = (gint) win32_channel->data_avail_event;
963   fd->events = condition;
964
965   if (win32_channel->thread_id == 0)
966     if (win32_channel->type == G_IO_FILE_DESC)
967       create_reader_thread (win32_channel, fd_reader);
968     else if (win32_channel->type == G_IO_STREAM_SOCKET)
969       create_reader_thread (win32_channel, sock_reader);
970 }