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