applied patch from Andreas Persenius <ndap@swipnet.se> that updates the
[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  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /*
24  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
25  * file for a list of people on the GLib Team.  See the ChangeLog
26  * files for a list of changes.  These files are distributed with
27  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
28  */
29
30
31 #include "config.h"
32 #include "glib.h"
33 #include <windows.h>
34 #include <winsock.h>            /* Not everybody has winsock2 */
35 #include <fcntl.h>
36 #include <io.h>
37 #include <errno.h>
38 #include <sys/types.h>
39
40 #include <stdio.h>
41
42 typedef struct _GIOWin32Channel GIOWin32Channel;
43 typedef struct _GIOWin32Watch GIOWin32Watch;
44
45 guint g_pipe_readable_msg;
46
47 typedef enum {
48   G_IO_WINDOWS_MESSAGES,        /* Windows messages */
49   G_IO_FILE_DESC,               /* Unix-like file descriptors from _open*/
50   G_IO_PIPE,                    /* pipe, with windows messages for signalling */
51   G_IO_STREAM_SOCKET            /* Stream sockets */
52 } GIOWin32ChannelType;
53
54 struct _GIOWin32Channel {
55   GIOChannel channel;
56   gint fd;                      /* Either a Unix-like file handle as provided
57                                  * by the Microsoft C runtime, or a SOCKET
58                                  * as provided by WinSock.
59                                  */
60   GIOWin32ChannelType type;
61
62   /* This is used by G_IO_WINDOWS_MESSAGES channels */
63   HWND hwnd;                    /* handle of window, or NULL */
64
65   /* This is used by G_IO_PIPE channels */
66   guint peer;                   /* thread id of reader */
67   guint peer_fd;                /* fd in the reader */
68   guint offset;                 /* counter of accumulated bytes */
69   guint need_wakeups;           /* in output channels whether the
70                                  * reader needs wakeups
71                                  */
72 };
73
74 struct _GIOWin32Watch {
75   GPollFD       pollfd;
76   GIOChannel   *channel;
77   GIOCondition  condition;
78   GIOFunc       callback;
79 };
80
81 static gboolean g_io_win32_msg_prepare  (gpointer  source_data, 
82                                          GTimeVal *current_time,
83                                          gint     *timeout);
84 static gboolean g_io_win32_msg_check    (gpointer  source_data,
85                                          GTimeVal *current_time);
86 static gboolean g_io_win32_msg_dispatch (gpointer  source_data,
87                                          GTimeVal *current_time,
88                                          gpointer  user_data);
89
90 static gboolean g_io_win32_fd_prepare  (gpointer  source_data, 
91                                         GTimeVal *current_time,
92                                         gint     *timeout);
93 static gboolean g_io_win32_fd_check    (gpointer  source_data,
94                                         GTimeVal *current_time);
95 static gboolean g_io_win32_fd_dispatch (gpointer  source_data,
96                                         GTimeVal *current_time,
97                                         gpointer  user_data);
98
99 static gboolean g_io_win32_pipe_prepare  (gpointer  source_data, 
100                                           GTimeVal *current_time,
101                                           gint     *timeout);
102 static gboolean g_io_win32_pipe_check    (gpointer  source_data,
103                                           GTimeVal *current_time);
104 static gboolean g_io_win32_pipe_dispatch (gpointer  source_data,
105                                           GTimeVal *current_time,
106                                           gpointer  user_data);
107 static void g_io_win32_pipe_destroy      (gpointer source_data);
108
109 static gboolean g_io_win32_sock_prepare  (gpointer  source_data, 
110                                           GTimeVal *current_time,
111                                           gint     *timeout);
112 static gboolean g_io_win32_sock_check    (gpointer  source_data,
113                                           GTimeVal *current_time);
114 static gboolean g_io_win32_sock_dispatch (gpointer  source_data,
115                                           GTimeVal *current_time,
116                                           gpointer  user_data);
117
118 static void g_io_win32_destroy (gpointer source_data);
119
120 static GIOError g_io_win32_msg_read (GIOChannel *channel, 
121                                      gchar      *buf, 
122                                      guint       count,
123                                      guint      *bytes_written);
124
125 static GIOError g_io_win32_msg_write(GIOChannel *channel, 
126                                      gchar      *buf, 
127                                      guint       count,
128                                      guint      *bytes_written);
129 static GIOError g_io_win32_msg_seek (GIOChannel *channel,
130                                      gint        offset, 
131                                      GSeekType   type);
132 static void g_io_win32_msg_close    (GIOChannel *channel);
133 static guint g_io_win32_msg_add_watch (GIOChannel      *channel,
134                                        gint             priority,
135                                        GIOCondition     condition,
136                                        GIOFunc          func,
137                                        gpointer         user_data,
138                                        GDestroyNotify   notify);
139
140 static GIOError g_io_win32_fd_read (GIOChannel *channel, 
141                                     gchar      *buf, 
142                                     guint       count,
143                                     guint      *bytes_written);
144 static GIOError g_io_win32_fd_write(GIOChannel *channel, 
145                                     gchar      *buf, 
146                                     guint       count,
147                                     guint      *bytes_written);
148 static GIOError g_io_win32_fd_seek (GIOChannel *channel,
149                                     gint        offset, 
150                                     GSeekType   type);
151 static void g_io_win32_fd_close (GIOChannel *channel);
152
153 static void g_io_win32_free (GIOChannel *channel);
154
155 static guint g_io_win32_fd_add_watch (GIOChannel      *channel,
156                                       gint             priority,
157                                       GIOCondition     condition,
158                                       GIOFunc          func,
159                                       gpointer         user_data,
160                                       GDestroyNotify   notify);
161
162 static GIOError g_io_win32_no_seek (GIOChannel *channel,
163                                     gint        offset, 
164                                     GSeekType   type);
165
166 static GIOError g_io_win32_pipe_read (GIOChannel *channel, 
167                                       gchar      *buf, 
168                                       guint       count,
169                                       guint      *bytes_written);
170 static GIOError g_io_win32_pipe_write (GIOChannel *channel, 
171                                        gchar      *buf, 
172                                        guint       count,
173                                        guint      *bytes_written);
174 static void g_io_win32_pipe_close    (GIOChannel *channel);
175 static guint g_io_win32_pipe_add_watch (GIOChannel      *channel,
176                                         gint             priority,
177                                         GIOCondition     condition,
178                                         GIOFunc          func,
179                                         gpointer         user_data,
180                                         GDestroyNotify   notify);
181 static void g_io_win32_pipe_free (GIOChannel *channel);
182
183 static GIOError g_io_win32_sock_read (GIOChannel *channel, 
184                                       gchar      *buf, 
185                                       guint       count,
186                                       guint      *bytes_written);
187 static GIOError g_io_win32_sock_write(GIOChannel *channel, 
188                                       gchar      *buf, 
189                                       guint       count,
190                                       guint      *bytes_written);
191 static void g_io_win32_sock_close    (GIOChannel *channel);
192 static guint g_io_win32_sock_add_watch (GIOChannel      *channel,
193                                         gint             priority,
194                                         GIOCondition     condition,
195                                         GIOFunc          func,
196                                         gpointer         user_data,
197                                         GDestroyNotify   notify);
198
199 GSourceFuncs win32_watch_msg_funcs = {
200   g_io_win32_msg_prepare,
201   g_io_win32_msg_check,
202   g_io_win32_msg_dispatch,
203   g_io_win32_destroy
204 };
205
206 GSourceFuncs win32_watch_fd_funcs = {
207   g_io_win32_fd_prepare,
208   g_io_win32_fd_check,
209   g_io_win32_fd_dispatch,
210   g_io_win32_destroy
211 };
212
213 GSourceFuncs win32_watch_pipe_funcs = {
214   g_io_win32_pipe_prepare,
215   g_io_win32_pipe_check,
216   g_io_win32_pipe_dispatch,
217   g_io_win32_pipe_destroy
218 };
219
220 GSourceFuncs win32_watch_sock_funcs = {
221   g_io_win32_sock_prepare,
222   g_io_win32_sock_check,
223   g_io_win32_sock_dispatch,
224   g_io_win32_destroy
225 };
226
227 GIOFuncs win32_channel_msg_funcs = {
228   g_io_win32_msg_read,
229   g_io_win32_msg_write,
230   g_io_win32_no_seek,
231   g_io_win32_msg_close,
232   g_io_win32_msg_add_watch,
233   g_io_win32_free
234 };
235
236 GIOFuncs win32_channel_fd_funcs = {
237   g_io_win32_fd_read,
238   g_io_win32_fd_write,
239   g_io_win32_fd_seek,
240   g_io_win32_fd_close,
241   g_io_win32_fd_add_watch,
242   g_io_win32_free
243 };
244
245 GIOFuncs win32_channel_pipe_funcs = {
246   g_io_win32_pipe_read,
247   g_io_win32_pipe_write,
248   g_io_win32_no_seek,
249   g_io_win32_pipe_close,
250   g_io_win32_pipe_add_watch,
251   g_io_win32_pipe_free
252 };
253
254 GIOFuncs win32_channel_sock_funcs = {
255   g_io_win32_sock_read,
256   g_io_win32_sock_write,
257   g_io_win32_no_seek,
258   g_io_win32_sock_close,
259   g_io_win32_sock_add_watch,
260   g_io_win32_free
261 };
262
263 #define N_WATCHED_PIPES 4
264
265 static struct {
266   gint fd;
267   GIOWin32Watch *watch;
268   GIOWin32Channel *channel;
269   gpointer user_data;
270 } watched_pipes[N_WATCHED_PIPES];
271
272 static gint n_watched_pipes = 0;
273
274 static gboolean
275 g_io_win32_msg_prepare  (gpointer source_data, 
276                          GTimeVal *current_time,
277                          gint    *timeout)
278 {
279   GIOWin32Watch *data = source_data;
280   GIOWin32Channel *win32_channel = (GIOWin32Channel *) data->channel;
281   MSG msg;
282
283   *timeout = -1;
284
285   return PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_NOREMOVE) == TRUE;
286 }
287
288 static gboolean 
289 g_io_win32_msg_check    (gpointer source_data,
290                          GTimeVal *current_time)
291 {
292   GIOWin32Watch *data = source_data;
293   GIOWin32Channel *win32_channel = (GIOWin32Channel *) data->channel;
294   MSG msg;
295
296   return PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_NOREMOVE) == TRUE;
297 }
298
299 static gboolean
300 g_io_win32_msg_dispatch (gpointer source_data, 
301                          GTimeVal *current_time,
302                          gpointer user_data)
303
304 {
305   GIOWin32Watch *data = source_data;
306
307   return (*data->callback)(data->channel,
308                            data->pollfd.revents & data->condition,
309                            user_data);
310 }
311
312 static void
313 g_io_win32_destroy (gpointer source_data)
314 {
315   GIOWin32Watch *data = source_data;
316
317   g_main_remove_poll (&data->pollfd);
318   g_io_channel_unref (data->channel);
319   g_free (data);
320 }
321
322 static gboolean
323 g_io_win32_fd_prepare  (gpointer source_data, 
324                         GTimeVal *current_time,
325                         gint    *timeout)
326 {
327   *timeout = -1;
328
329   return FALSE;
330 }
331
332 static gboolean 
333 g_io_win32_fd_check    (gpointer source_data,
334                         GTimeVal *current_time)
335 {
336   GIOWin32Watch *data = source_data;
337
338   return (data->pollfd.revents & data->condition);
339 }
340
341 static gboolean
342 g_io_win32_fd_dispatch (gpointer source_data, 
343                         GTimeVal *current_time,
344                         gpointer user_data)
345
346 {
347   GIOWin32Watch *data = source_data;
348
349   return (*data->callback)(data->channel,
350                            data->pollfd.revents & data->condition,
351                            user_data);
352 }
353
354 static GIOError
355 g_io_win32_msg_read (GIOChannel *channel, 
356                      gchar     *buf, 
357                      guint      count,
358                      guint     *bytes_read)
359 {
360   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
361   MSG msg;                      /* In case of alignment problems */
362
363   if (count < sizeof (MSG))
364     return G_IO_ERROR_INVAL;
365   
366   if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
367     return G_IO_ERROR_AGAIN;
368
369   memmove (buf, &msg, sizeof (MSG));
370   *bytes_read = sizeof (MSG);
371   return G_IO_ERROR_NONE;
372 }
373                        
374 static GIOError 
375 g_io_win32_msg_write(GIOChannel *channel, 
376                      gchar     *buf, 
377                      guint      count,
378                      guint     *bytes_written)
379 {
380   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
381   MSG msg;
382   gint result;
383
384   if (count != sizeof (MSG))
385     return G_IO_ERROR_INVAL;
386
387   /* In case of alignment problems */
388   memmove (&msg, buf, sizeof (MSG));
389   if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
390     return G_IO_ERROR_UNKNOWN;
391
392   *bytes_written = sizeof (MSG);
393   return G_IO_ERROR_NONE; 
394 }
395
396 static GIOError 
397 g_io_win32_no_seek (GIOChannel *channel,
398                     gint      offset, 
399                     GSeekType type)
400 {
401   g_warning ("g_io_win32_no_seek: unseekable IO channel type");
402   return G_IO_ERROR_UNKNOWN;
403 }
404
405
406 static void 
407 g_io_win32_msg_close (GIOChannel *channel)
408 {
409   /* Nothing to be done. Or should we set hwnd to some invalid value? */
410 }
411
412 static void 
413 g_io_win32_free (GIOChannel *channel)
414 {
415   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
416
417   g_free (win32_channel);
418 }
419
420 static guint 
421 g_io_win32_msg_add_watch (GIOChannel    *channel,
422                           gint           priority,
423                           GIOCondition   condition,
424                           GIOFunc        func,
425                           gpointer       user_data,
426                           GDestroyNotify notify)
427 {
428   GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
429   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
430   
431   watch->channel = channel;
432   g_io_channel_ref (channel);
433
434   watch->callback = func;
435   watch->condition = condition;
436
437   watch->pollfd.fd = G_WIN32_MSG_HANDLE;
438   watch->pollfd.events = condition;
439
440   g_main_add_poll (&watch->pollfd, priority);
441
442   return g_source_add (priority, TRUE, &win32_watch_msg_funcs,
443                        watch, user_data, notify);
444 }
445
446 static gboolean
447 g_io_win32_pipe_prepare  (gpointer source_data, 
448                           GTimeVal *current_time,
449                           gint    *timeout)
450 {
451   *timeout = -1;
452
453   return FALSE;
454 }
455
456 static gboolean 
457 g_io_win32_pipe_check    (gpointer source_data,
458                           GTimeVal *current_time)
459 {
460   GIOWin32Watch *data = source_data;
461   return FALSE;
462 }
463
464 static gboolean
465 g_io_win32_pipe_dispatch (gpointer source_data, 
466                           GTimeVal *current_time,
467                           gpointer user_data)
468
469 {
470   GIOWin32Watch *data = source_data;
471
472   return (*data->callback)(data->channel,
473                            data->pollfd.revents & data->condition,
474                            user_data);
475 }
476
477 static void
478 g_io_win32_pipe_destroy (gpointer source_data)
479 {
480   GIOWin32Watch *data = source_data;
481
482   g_io_channel_unref (data->channel);
483   g_free (data);
484 }
485
486 static gboolean
487 g_io_win32_sock_prepare  (gpointer source_data, 
488                         GTimeVal *current_time,
489                         gint    *timeout)
490 {
491   *timeout = -1;
492
493   return FALSE;
494 }
495
496 static gboolean 
497 g_io_win32_sock_check    (gpointer source_data,
498                         GTimeVal *current_time)
499 {
500   GIOWin32Watch *data = source_data;
501
502   return (data->pollfd.revents & data->condition);
503 }
504
505 static gboolean
506 g_io_win32_sock_dispatch (gpointer source_data, 
507                         GTimeVal *current_time,
508                         gpointer user_data)
509
510 {
511   GIOWin32Watch *data = source_data;
512
513   return (*data->callback)(data->channel,
514                            data->pollfd.revents & data->condition,
515                            user_data);
516 }
517
518 static GIOError
519 g_io_win32_fd_read (GIOChannel *channel, 
520                     gchar     *buf, 
521                     guint      count,
522                     guint     *bytes_read)
523 {
524   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
525   gint result;
526
527   result = read (win32_channel->fd, buf, count);
528   if (result < 0)
529     {
530       *bytes_read = 0;
531       switch (errno)
532         {
533         case EINVAL:
534           return G_IO_ERROR_INVAL;
535         case EAGAIN:
536           return G_IO_ERROR_AGAIN;
537         default:
538           return G_IO_ERROR_UNKNOWN;
539         }
540     }
541   else
542     {
543       *bytes_read = result;
544       return G_IO_ERROR_NONE;
545     }
546 }
547                        
548 static GIOError 
549 g_io_win32_fd_write(GIOChannel *channel, 
550                     gchar     *buf, 
551                     guint      count,
552                     guint     *bytes_written)
553 {
554   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
555   gint result;
556
557   result = write (win32_channel->fd, buf, count);
558       
559   if (result < 0)
560     {
561       *bytes_written = 0;
562       switch (errno)
563         {
564         case EINVAL:
565           return G_IO_ERROR_INVAL;
566         case EAGAIN:
567           return G_IO_ERROR_AGAIN;
568         default:
569           return G_IO_ERROR_UNKNOWN;
570         }
571     }
572   else
573     {
574       *bytes_written = result;
575       return G_IO_ERROR_NONE;
576     }
577 }
578
579 static GIOError 
580 g_io_win32_fd_seek (GIOChannel *channel,
581                     gint      offset, 
582                     GSeekType type)
583 {
584   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
585   int whence;
586   off_t result;
587
588   switch (type)
589     {
590     case G_SEEK_SET:
591       whence = SEEK_SET;
592       break;
593     case G_SEEK_CUR:
594       whence = SEEK_CUR;
595       break;
596     case G_SEEK_END:
597       whence = SEEK_END;
598       break;
599     default:
600       g_warning ("g_io_win32_fd_seek: unknown seek type");
601       return G_IO_ERROR_UNKNOWN;
602     }
603   
604   result = lseek (win32_channel->fd, offset, whence);
605   
606   if (result < 0)
607     {
608       switch (errno)
609         {
610         case EINVAL:
611           return G_IO_ERROR_INVAL;
612         default:
613           return G_IO_ERROR_UNKNOWN;
614         }
615     }
616   else
617     return G_IO_ERROR_NONE;
618 }
619
620 static void 
621 g_io_win32_fd_close (GIOChannel *channel)
622 {
623   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
624
625   close (win32_channel->fd);
626   return;
627 }
628
629 static guint 
630 g_io_win32_fd_add_watch (GIOChannel    *channel,
631                          gint           priority,
632                          GIOCondition   condition,
633                          GIOFunc        func,
634                          gpointer       user_data,
635                          GDestroyNotify notify)
636 {
637   GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
638   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
639   
640   watch->channel = channel;
641   g_io_channel_ref (channel);
642
643   watch->callback = func;
644   watch->condition = condition;
645
646   /* This probably does not work, except for CONIN$. */
647   watch->pollfd.fd = _get_osfhandle (win32_channel->fd);
648   watch->pollfd.events = condition;
649
650   g_main_add_poll (&watch->pollfd, priority);
651
652   return g_source_add (priority, TRUE, &win32_watch_fd_funcs,
653                        watch, user_data, notify);
654 }
655
656 static GIOError
657 g_io_win32_pipe_read (GIOChannel *channel, 
658                       gchar     *buf, 
659                       guint      count,
660                       guint     *bytes_read)
661 {
662   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
663   HANDLE handle;
664   DWORD avail;
665   gint result;
666
667   handle = (HANDLE) _get_osfhandle (win32_channel->fd);
668   if (!PeekNamedPipe (handle, NULL, 0, NULL, &avail, NULL))
669     {
670       return G_IO_ERROR_UNKNOWN;
671     }
672
673   count = MIN (count, avail);
674
675   count = MAX (count, 1);       /* Must read at least one byte, or
676                                  * caller will think it's EOF.
677                                  */
678   /* g_print ("g_io_win32_pipe_read: %d %d\n", win32_channel->fd, count); */
679   if (count == 0)
680     result = 0;
681   else
682     result = read (win32_channel->fd, buf, count);
683   if (result < 0)
684     {
685       *bytes_read = 0;
686       switch (errno)
687         {
688         case EINVAL:
689           return G_IO_ERROR_INVAL;
690         case EAGAIN:
691           return G_IO_ERROR_AGAIN;
692         default:
693           return G_IO_ERROR_UNKNOWN;
694         }
695     }
696   else
697     {
698       *bytes_read = result;
699       win32_channel->offset += result;
700       /* g_print ("=%d (%d)\n", result, win32_channel->offset); */
701       return G_IO_ERROR_NONE;
702     }
703 }
704                        
705 static GIOError 
706 g_io_win32_pipe_write(GIOChannel *channel, 
707                       gchar     *buf, 
708                       guint      count,
709                       guint     *bytes_written)
710 {
711   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
712   LONG prevcnt;
713   gint result;
714
715   /* g_print ("g_io_win32_pipe_write: %d %d\n", win32_channel->fd, count); */
716   result = write (win32_channel->fd, buf, count);
717   if (result < 0)
718     {
719       *bytes_written = 0;
720       switch (errno)
721         {
722         case EINVAL:
723           return G_IO_ERROR_INVAL;
724         case EAGAIN:
725           return G_IO_ERROR_AGAIN;
726         default:
727           return G_IO_ERROR_UNKNOWN;
728         }
729     }
730   else
731     {
732       if (g_pipe_readable_msg == 0)
733         g_pipe_readable_msg = RegisterWindowMessage ("g-pipe-readable");
734
735       win32_channel->offset += result;
736       /* g_print ("=%d (%d)\n", result, win32_channel->offset); */
737       if (win32_channel->need_wakeups)
738         {
739           PostThreadMessage (win32_channel->peer,
740                              g_pipe_readable_msg,
741                              win32_channel->peer_fd,
742                              win32_channel->offset);
743         }
744       *bytes_written = result;
745       return G_IO_ERROR_NONE;
746     }
747 }
748
749 static void 
750 g_io_win32_pipe_close (GIOChannel *channel)
751 {
752   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
753
754   /* g_print ("g_io_win32_pipe_close: %#x %d\n", channel, win32_channel->fd); */
755
756   close (win32_channel->fd);
757   return;
758 }
759
760 static guint 
761 g_io_win32_pipe_add_watch (GIOChannel    *channel,
762                            gint           priority,
763                            GIOCondition   condition,
764                            GIOFunc        func,
765                            gpointer       user_data,
766                            GDestroyNotify notify)
767 {
768   GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
769   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
770   gint i;
771   
772   /* g_print ("g_io_win32_pipe_add_watch: %d\n", win32_channel->fd); */
773
774   watch->channel = channel;
775   g_io_channel_ref (channel);
776
777   watch->callback = func;
778   watch->condition = condition;
779
780   watch->pollfd.fd = win32_channel->fd;
781   watch->pollfd.events = condition;
782
783   for (i = 0; i < n_watched_pipes; i++)
784     if (watched_pipes[i].fd == -1)
785       break;
786   if (i == N_WATCHED_PIPES)
787     g_error ("Too many watched pipes");
788   else
789     {
790       watched_pipes[i].fd = win32_channel->fd;
791       watched_pipes[i].watch = watch;
792       watched_pipes[i].channel = win32_channel;
793       watched_pipes[i].user_data = user_data;
794       n_watched_pipes = MAX (i + 1, n_watched_pipes);
795     }
796   return g_source_add (priority, FALSE, &win32_watch_pipe_funcs, watch, user_data, notify);
797 }
798
799 static void
800 g_io_win32_pipe_free (GIOChannel *channel)
801 {
802   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
803   gint i;
804
805   /* g_print ("g_io_win32_pipe_free: %#x %#x\n", channel, channel->channel_data); */
806
807   for (i = 0; i < n_watched_pipes; i++)
808     if (watched_pipes[i].fd == win32_channel->fd)
809       {
810         watched_pipes[i].fd = -1;
811         break;
812       }
813   g_io_win32_free (channel);
814 }
815
816 static GIOError 
817 g_io_win32_sock_read (GIOChannel *channel, 
818                       gchar      *buf, 
819                       guint       count,
820                       guint      *bytes_read)
821 {
822   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
823   gint result;
824
825   result = recv (win32_channel->fd, buf, count, 0);
826   if (result == SOCKET_ERROR)
827     {
828       *bytes_read = 0;
829       switch (WSAGetLastError ())
830         {
831         case WSAEINVAL:
832           return G_IO_ERROR_INVAL;
833         case WSAEWOULDBLOCK:
834         case WSAEINTR:
835           return G_IO_ERROR_AGAIN;
836         default:
837           return G_IO_ERROR_UNKNOWN;
838         }
839     }
840   else
841     {
842       *bytes_read = result;
843       return G_IO_ERROR_NONE;
844     }
845 }
846                        
847 static GIOError 
848 g_io_win32_sock_write(GIOChannel *channel, 
849                       gchar      *buf, 
850                       guint       count,
851                       guint      *bytes_written)
852 {
853   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
854   gint result;
855
856   result = send (win32_channel->fd, buf, count, 0);
857       
858   if (result == SOCKET_ERROR)
859     {
860       *bytes_written = 0;
861       switch (WSAGetLastError ())
862         {
863         case WSAEINVAL:
864           return G_IO_ERROR_INVAL;
865         case WSAEWOULDBLOCK:
866         case WSAEINTR:
867           return G_IO_ERROR_AGAIN;
868         default:
869           return G_IO_ERROR_UNKNOWN;
870         }
871     }
872   else
873     {
874       *bytes_written = result;
875       return G_IO_ERROR_NONE;
876     }
877 }
878
879 static void 
880 g_io_win32_sock_close (GIOChannel *channel)
881 {
882   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
883
884   closesocket (win32_channel->fd);
885   return;
886 }
887
888 static guint 
889 g_io_win32_sock_add_watch (GIOChannel    *channel,
890                            gint           priority,
891                            GIOCondition   condition,
892                            GIOFunc        func,
893                            gpointer       user_data,
894                            GDestroyNotify notify)
895 {
896   GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
897   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
898   
899   watch->channel = channel;
900   g_io_channel_ref (channel);
901
902   watch->callback = func;
903   watch->condition = condition;
904
905   watch->pollfd.fd = win32_channel->fd;
906   watch->pollfd.events = condition;
907
908   g_main_add_poll (&watch->pollfd, priority);
909
910   return g_source_add (priority, TRUE, &win32_watch_sock_funcs, watch, user_data, notify);
911 }
912
913 GIOChannel *
914 g_io_channel_win32_new_messages (guint hwnd)
915 {
916   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
917   GIOChannel *channel = (GIOChannel *) win32_channel;
918
919   g_io_channel_init (channel);
920   channel->funcs = &win32_channel_msg_funcs;
921   win32_channel->fd = -1;
922   win32_channel->type = G_IO_WINDOWS_MESSAGES;
923   win32_channel->hwnd = (HWND) hwnd;
924
925   return channel;
926 }
927
928 GIOChannel *
929 g_io_channel_unix_new (gint fd)
930 {
931   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
932   GIOChannel *channel = (GIOChannel *) win32_channel;
933
934   g_io_channel_init (channel);
935   channel->funcs = &win32_channel_fd_funcs;
936   win32_channel->fd = fd;
937   win32_channel->type = G_IO_FILE_DESC;
938
939   return channel;
940 }
941
942 gint
943 g_io_channel_unix_get_fd (GIOChannel *channel)
944 {
945   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
946
947   return win32_channel->fd;
948 }
949
950 GIOChannel *
951 g_io_channel_win32_new_pipe_with_wakeups (int   fd,
952                                           guint peer,
953                                           int   peer_fd)
954 {
955   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
956   GIOChannel *channel = (GIOChannel *) win32_channel;
957
958   /* g_print ("g_io_channel_win32_new_pipe_with_wakeups %d %#x %d\n", fd, peer, peer_fd); */
959
960   g_io_channel_init (channel);
961   channel->funcs = &win32_channel_pipe_funcs;
962   win32_channel->fd = fd;
963   win32_channel->type = G_IO_PIPE;
964   win32_channel->peer = peer;
965   win32_channel->peer_fd = peer_fd;
966   win32_channel->offset = 0;
967   win32_channel->need_wakeups = TRUE;
968
969   return channel;
970 }
971
972 GIOChannel *
973 g_io_channel_win32_new_pipe (int fd)
974 {
975   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
976   GIOChannel *channel = (GIOChannel *) win32_channel;
977
978   g_io_channel_init (channel);
979   channel->funcs = &win32_channel_pipe_funcs;
980   win32_channel->fd = fd;
981   win32_channel->type = G_IO_PIPE;
982   win32_channel->offset = 0;
983   win32_channel->need_wakeups = FALSE;
984
985   return channel;
986 }
987
988 GIOChannel *
989 g_io_channel_win32_new_stream_socket (int socket)
990 {
991   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
992   GIOChannel *channel = (GIOChannel *) win32_channel;
993
994   g_io_channel_init (channel);
995   channel->funcs = &win32_channel_sock_funcs;
996   win32_channel->fd = socket;
997   win32_channel->type = G_IO_STREAM_SOCKET;
998
999   return channel;
1000 }
1001
1002 gint
1003 g_io_channel_win32_get_fd (GIOChannel *channel)
1004 {
1005   return g_io_channel_unix_get_fd (channel);
1006 }
1007
1008 void
1009 g_io_channel_win32_pipe_request_wakeups (GIOChannel *channel,
1010                                          guint       peer,
1011                                          int         peer_fd)
1012 {
1013   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
1014
1015   win32_channel->peer = peer;
1016   win32_channel->peer_fd = peer_fd;
1017   win32_channel->need_wakeups = TRUE;
1018 }
1019
1020 void
1021 g_io_channel_win32_pipe_readable (gint  fd,
1022                                   guint offset)
1023 {
1024   gint i;
1025
1026   for (i = 0; i < n_watched_pipes; i++)
1027     if (watched_pipes[i].fd == fd)
1028       {
1029         if ((watched_pipes[i].watch->condition & G_IO_IN)
1030             && watched_pipes[i].channel->offset < offset)
1031           (*watched_pipes[i].watch->callback) (watched_pipes[i].watch->channel,
1032                                                G_IO_IN,
1033                                                watched_pipes[i].user_data);
1034       }
1035 }