1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * giowin32.c: IO Channels for Win32.
5 * Copyright 1998 Owen Taylor and Tor Lillqvist
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.
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.
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.
26 #include <winsock.h> /* Not everybody has winsock2 */
30 #include <sys/types.h>
34 typedef struct _GIOWin32Channel GIOWin32Channel;
35 typedef struct _GIOWin32Watch GIOWin32Watch;
37 guint g_pipe_readable_msg;
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;
46 struct _GIOWin32Channel {
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.
52 GIOWin32ChannelType type;
54 /* This is used by G_IO_WINDOWS_MESSAGES channels */
55 HWND hwnd; /* handle of window, or NULL */
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
66 struct _GIOWin32Watch {
69 GIOCondition condition;
73 static gboolean g_io_win32_msg_prepare (gpointer source_data,
74 GTimeVal *current_time,
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,
82 static gboolean g_io_win32_fd_prepare (gpointer source_data,
83 GTimeVal *current_time,
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,
91 static gboolean g_io_win32_pipe_prepare (gpointer source_data,
92 GTimeVal *current_time,
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,
99 static void g_io_win32_pipe_destroy (gpointer source_data);
101 static gboolean g_io_win32_sock_prepare (gpointer source_data,
102 GTimeVal *current_time,
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,
110 static void g_io_win32_destroy (gpointer source_data);
112 static GIOError g_io_win32_msg_read (GIOChannel *channel,
115 guint *bytes_written);
117 static GIOError g_io_win32_msg_write(GIOChannel *channel,
120 guint *bytes_written);
121 static GIOError g_io_win32_msg_seek (GIOChannel *channel,
124 static void g_io_win32_msg_close (GIOChannel *channel);
125 static guint g_io_win32_msg_add_watch (GIOChannel *channel,
127 GIOCondition condition,
130 GDestroyNotify notify);
132 static GIOError g_io_win32_fd_read (GIOChannel *channel,
135 guint *bytes_written);
136 static GIOError g_io_win32_fd_write(GIOChannel *channel,
139 guint *bytes_written);
140 static GIOError g_io_win32_fd_seek (GIOChannel *channel,
143 static void g_io_win32_fd_close (GIOChannel *channel);
145 static void g_io_win32_free (GIOChannel *channel);
147 static guint g_io_win32_fd_add_watch (GIOChannel *channel,
149 GIOCondition condition,
152 GDestroyNotify notify);
154 static GIOError g_io_win32_no_seek (GIOChannel *channel,
158 static GIOError g_io_win32_pipe_read (GIOChannel *channel,
161 guint *bytes_written);
162 static GIOError g_io_win32_pipe_write (GIOChannel *channel,
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,
169 GIOCondition condition,
172 GDestroyNotify notify);
173 static void g_io_win32_pipe_free (GIOChannel *channel);
175 static GIOError g_io_win32_sock_read (GIOChannel *channel,
178 guint *bytes_written);
179 static GIOError g_io_win32_sock_write(GIOChannel *channel,
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,
186 GIOCondition condition,
189 GDestroyNotify notify);
191 GSourceFuncs win32_watch_msg_funcs = {
192 g_io_win32_msg_prepare,
193 g_io_win32_msg_check,
194 g_io_win32_msg_dispatch,
198 GSourceFuncs win32_watch_fd_funcs = {
199 g_io_win32_fd_prepare,
201 g_io_win32_fd_dispatch,
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
212 GSourceFuncs win32_watch_sock_funcs = {
213 g_io_win32_sock_prepare,
214 g_io_win32_sock_check,
215 g_io_win32_sock_dispatch,
219 GIOFuncs win32_channel_msg_funcs = {
221 g_io_win32_msg_write,
223 g_io_win32_msg_close,
224 g_io_win32_msg_add_watch,
228 GIOFuncs win32_channel_fd_funcs = {
233 g_io_win32_fd_add_watch,
237 GIOFuncs win32_channel_pipe_funcs = {
238 g_io_win32_pipe_read,
239 g_io_win32_pipe_write,
241 g_io_win32_pipe_close,
242 g_io_win32_pipe_add_watch,
246 GIOFuncs win32_channel_sock_funcs = {
247 g_io_win32_sock_read,
248 g_io_win32_sock_write,
250 g_io_win32_sock_close,
251 g_io_win32_sock_add_watch,
255 #define N_WATCHED_PIPES 4
259 GIOWin32Watch *watch;
260 GIOWin32Channel *channel;
262 } watched_pipes[N_WATCHED_PIPES];
264 static gint n_watched_pipes = 0;
267 g_io_win32_msg_prepare (gpointer source_data,
268 GTimeVal *current_time,
271 GIOWin32Watch *data = source_data;
272 GIOWin32Channel *win32_channel = (GIOWin32Channel *) data->channel;
277 return PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_NOREMOVE) == TRUE;
281 g_io_win32_msg_check (gpointer source_data,
282 GTimeVal *current_time)
284 GIOWin32Watch *data = source_data;
285 GIOWin32Channel *win32_channel = (GIOWin32Channel *) data->channel;
288 return PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_NOREMOVE) == TRUE;
292 g_io_win32_msg_dispatch (gpointer source_data,
293 GTimeVal *current_time,
297 GIOWin32Watch *data = source_data;
299 return (*data->callback)(data->channel,
300 data->pollfd.revents & data->condition,
305 g_io_win32_destroy (gpointer source_data)
307 GIOWin32Watch *data = source_data;
309 g_main_remove_poll (&data->pollfd);
310 g_io_channel_unref (data->channel);
315 g_io_win32_fd_prepare (gpointer source_data,
316 GTimeVal *current_time,
325 g_io_win32_fd_check (gpointer source_data,
326 GTimeVal *current_time)
328 GIOWin32Watch *data = source_data;
330 return (data->pollfd.revents & data->condition);
334 g_io_win32_fd_dispatch (gpointer source_data,
335 GTimeVal *current_time,
339 GIOWin32Watch *data = source_data;
341 return (*data->callback)(data->channel,
342 data->pollfd.revents & data->condition,
347 g_io_win32_msg_read (GIOChannel *channel,
352 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
353 MSG msg; /* In case of alignment problems */
355 if (count < sizeof (MSG))
356 return G_IO_ERROR_INVAL;
358 if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
359 return G_IO_ERROR_AGAIN;
361 memmove (buf, &msg, sizeof (MSG));
362 *bytes_read = sizeof (MSG);
363 return G_IO_ERROR_NONE;
367 g_io_win32_msg_write(GIOChannel *channel,
370 guint *bytes_written)
372 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
376 if (count != sizeof (MSG))
377 return G_IO_ERROR_INVAL;
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;
384 *bytes_written = sizeof (MSG);
385 return G_IO_ERROR_NONE;
389 g_io_win32_no_seek (GIOChannel *channel,
393 g_warning ("g_io_win32_no_seek: unseekable IO channel type");
394 return G_IO_ERROR_UNKNOWN;
399 g_io_win32_msg_close (GIOChannel *channel)
401 /* Nothing to be done. Or should we set hwnd to some invalid value? */
405 g_io_win32_free (GIOChannel *channel)
407 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
409 g_free (win32_channel);
413 g_io_win32_msg_add_watch (GIOChannel *channel,
415 GIOCondition condition,
418 GDestroyNotify notify)
420 GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
421 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
423 watch->channel = channel;
424 g_io_channel_ref (channel);
426 watch->callback = func;
427 watch->condition = condition;
429 watch->pollfd.fd = G_WIN32_MSG_HANDLE;
430 watch->pollfd.events = condition;
432 g_main_add_poll (&watch->pollfd, priority);
434 return g_source_add (priority, TRUE, &win32_watch_msg_funcs,
435 watch, user_data, notify);
439 g_io_win32_pipe_prepare (gpointer source_data,
440 GTimeVal *current_time,
449 g_io_win32_pipe_check (gpointer source_data,
450 GTimeVal *current_time)
452 GIOWin32Watch *data = source_data;
457 g_io_win32_pipe_dispatch (gpointer source_data,
458 GTimeVal *current_time,
462 GIOWin32Watch *data = source_data;
464 return (*data->callback)(data->channel,
465 data->pollfd.revents & data->condition,
470 g_io_win32_pipe_destroy (gpointer source_data)
472 GIOWin32Watch *data = source_data;
474 g_io_channel_unref (data->channel);
479 g_io_win32_sock_prepare (gpointer source_data,
480 GTimeVal *current_time,
489 g_io_win32_sock_check (gpointer source_data,
490 GTimeVal *current_time)
492 GIOWin32Watch *data = source_data;
494 return (data->pollfd.revents & data->condition);
498 g_io_win32_sock_dispatch (gpointer source_data,
499 GTimeVal *current_time,
503 GIOWin32Watch *data = source_data;
505 return (*data->callback)(data->channel,
506 data->pollfd.revents & data->condition,
511 g_io_win32_fd_read (GIOChannel *channel,
516 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
519 result = read (win32_channel->fd, buf, count);
526 return G_IO_ERROR_INVAL;
528 return G_IO_ERROR_AGAIN;
530 return G_IO_ERROR_UNKNOWN;
535 *bytes_read = result;
536 return G_IO_ERROR_NONE;
541 g_io_win32_fd_write(GIOChannel *channel,
544 guint *bytes_written)
546 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
549 result = write (win32_channel->fd, buf, count);
557 return G_IO_ERROR_INVAL;
559 return G_IO_ERROR_AGAIN;
561 return G_IO_ERROR_UNKNOWN;
566 *bytes_written = result;
567 return G_IO_ERROR_NONE;
572 g_io_win32_fd_seek (GIOChannel *channel,
576 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
592 g_warning ("g_io_win32_fd_seek: unknown seek type");
593 return G_IO_ERROR_UNKNOWN;
596 result = lseek (win32_channel->fd, offset, whence);
603 return G_IO_ERROR_INVAL;
605 return G_IO_ERROR_UNKNOWN;
609 return G_IO_ERROR_NONE;
613 g_io_win32_fd_close (GIOChannel *channel)
615 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
617 close (win32_channel->fd);
622 g_io_win32_fd_add_watch (GIOChannel *channel,
624 GIOCondition condition,
627 GDestroyNotify notify)
629 GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
630 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
632 watch->channel = channel;
633 g_io_channel_ref (channel);
635 watch->callback = func;
636 watch->condition = condition;
638 /* This probably does not work, except for CONIN$. */
639 watch->pollfd.fd = _get_osfhandle (win32_channel->fd);
640 watch->pollfd.events = condition;
642 g_main_add_poll (&watch->pollfd, priority);
644 return g_source_add (priority, TRUE, &win32_watch_fd_funcs,
645 watch, user_data, notify);
649 g_io_win32_pipe_read (GIOChannel *channel,
654 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
659 handle = (HANDLE) _get_osfhandle (win32_channel->fd);
660 if (!PeekNamedPipe (handle, NULL, 0, NULL, &avail, NULL))
662 return G_IO_ERROR_UNKNOWN;
665 count = MIN (count, avail);
667 count = MAX (count, 1); /* Must read at least one byte, or
668 * caller will think it's EOF.
670 /* g_print ("g_io_win32_pipe_read: %d %d\n", win32_channel->fd, count); */
674 result = read (win32_channel->fd, buf, count);
681 return G_IO_ERROR_INVAL;
683 return G_IO_ERROR_AGAIN;
685 return G_IO_ERROR_UNKNOWN;
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;
698 g_io_win32_pipe_write(GIOChannel *channel,
701 guint *bytes_written)
703 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
707 /* g_print ("g_io_win32_pipe_write: %d %d\n", win32_channel->fd, count); */
708 result = write (win32_channel->fd, buf, count);
715 return G_IO_ERROR_INVAL;
717 return G_IO_ERROR_AGAIN;
719 return G_IO_ERROR_UNKNOWN;
724 if (g_pipe_readable_msg == 0)
725 g_pipe_readable_msg = RegisterWindowMessage ("g-pipe-readable");
727 win32_channel->offset += result;
728 /* g_print ("=%d (%d)\n", result, win32_channel->offset); */
729 if (win32_channel->need_wakeups)
731 PostThreadMessage (win32_channel->peer,
733 win32_channel->peer_fd,
734 win32_channel->offset);
736 *bytes_written = result;
737 return G_IO_ERROR_NONE;
742 g_io_win32_pipe_close (GIOChannel *channel)
744 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
746 /* g_print ("g_io_win32_pipe_close: %#x %d\n", channel, win32_channel->fd); */
748 close (win32_channel->fd);
753 g_io_win32_pipe_add_watch (GIOChannel *channel,
755 GIOCondition condition,
758 GDestroyNotify notify)
760 GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
761 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
764 /* g_print ("g_io_win32_pipe_add_watch: %d\n", win32_channel->fd); */
766 watch->channel = channel;
767 g_io_channel_ref (channel);
769 watch->callback = func;
770 watch->condition = condition;
772 watch->pollfd.fd = win32_channel->fd;
773 watch->pollfd.events = condition;
775 for (i = 0; i < n_watched_pipes; i++)
776 if (watched_pipes[i].fd == -1)
778 if (i == N_WATCHED_PIPES)
779 g_error ("Too many watched pipes");
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);
788 return g_source_add (priority, FALSE, &win32_watch_pipe_funcs, watch, user_data, notify);
792 g_io_win32_pipe_free (GIOChannel *channel)
794 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
797 /* g_print ("g_io_win32_pipe_free: %#x %#x\n", channel, channel->channel_data); */
799 for (i = 0; i < n_watched_pipes; i++)
800 if (watched_pipes[i].fd == win32_channel->fd)
802 watched_pipes[i].fd = -1;
805 g_io_win32_free (channel);
809 g_io_win32_sock_read (GIOChannel *channel,
814 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
817 result = recv (win32_channel->fd, buf, count, 0);
818 if (result == SOCKET_ERROR)
821 switch (WSAGetLastError ())
824 return G_IO_ERROR_INVAL;
827 return G_IO_ERROR_AGAIN;
829 return G_IO_ERROR_UNKNOWN;
834 *bytes_read = result;
835 return G_IO_ERROR_NONE;
840 g_io_win32_sock_write(GIOChannel *channel,
843 guint *bytes_written)
845 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
848 result = send (win32_channel->fd, buf, count, 0);
850 if (result == SOCKET_ERROR)
853 switch (WSAGetLastError ())
856 return G_IO_ERROR_INVAL;
859 return G_IO_ERROR_AGAIN;
861 return G_IO_ERROR_UNKNOWN;
866 *bytes_written = result;
867 return G_IO_ERROR_NONE;
872 g_io_win32_sock_close (GIOChannel *channel)
874 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
876 closesocket (win32_channel->fd);
881 g_io_win32_sock_add_watch (GIOChannel *channel,
883 GIOCondition condition,
886 GDestroyNotify notify)
888 GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
889 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
891 watch->channel = channel;
892 g_io_channel_ref (channel);
894 watch->callback = func;
895 watch->condition = condition;
897 watch->pollfd.fd = win32_channel->fd;
898 watch->pollfd.events = condition;
900 g_main_add_poll (&watch->pollfd, priority);
902 return g_source_add (priority, TRUE, &win32_watch_sock_funcs, watch, user_data, notify);
906 g_io_channel_win32_new_messages (guint hwnd)
908 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
909 GIOChannel *channel = (GIOChannel *) win32_channel;
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;
921 g_io_channel_unix_new (gint fd)
923 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
924 GIOChannel *channel = (GIOChannel *) win32_channel;
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;
935 g_io_channel_unix_get_fd (GIOChannel *channel)
937 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
939 return win32_channel->fd;
943 g_io_channel_win32_new_pipe_with_wakeups (int fd,
947 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
948 GIOChannel *channel = (GIOChannel *) win32_channel;
950 /* g_print ("g_io_channel_win32_new_pipe_with_wakeups %d %#x %d\n", fd, peer, peer_fd); */
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;
965 g_io_channel_win32_new_pipe (int fd)
967 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
968 GIOChannel *channel = (GIOChannel *) win32_channel;
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;
981 g_io_channel_win32_new_stream_socket (int socket)
983 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
984 GIOChannel *channel = (GIOChannel *) win32_channel;
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;
995 g_io_channel_win32_get_fd (GIOChannel *channel)
997 return g_io_channel_unix_get_fd (channel);
1001 g_io_channel_win32_pipe_request_wakeups (GIOChannel *channel,
1005 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
1007 win32_channel->peer = peer;
1008 win32_channel->peer_fd = peer_fd;
1009 win32_channel->need_wakeups = TRUE;
1013 g_io_channel_win32_pipe_readable (gint fd,
1018 for (i = 0; i < n_watched_pipes; i++)
1019 if (watched_pipes[i].fd == fd)
1021 if (watched_pipes[i].channel->offset < offset)
1022 (*watched_pipes[i].watch->callback) (watched_pipes[i].watch->channel,
1024 watched_pipes[i].user_data);