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