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