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.
24 * Modified by the GLib Team and others 1997-1999. 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/.
34 #include <winsock.h> /* Not everybody has winsock2 */
38 #include <sys/types.h>
42 typedef struct _GIOWin32Channel GIOWin32Channel;
43 typedef struct _GIOWin32Watch GIOWin32Watch;
45 guint g_pipe_readable_msg;
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;
54 struct _GIOWin32Channel {
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.
60 GIOWin32ChannelType type;
62 /* This is used by G_IO_WINDOWS_MESSAGES channels */
63 HWND hwnd; /* handle of window, or NULL */
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
74 struct _GIOWin32Watch {
77 GIOCondition condition;
81 static gboolean g_io_win32_msg_prepare (gpointer source_data,
82 GTimeVal *current_time,
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,
90 static gboolean g_io_win32_fd_prepare (gpointer source_data,
91 GTimeVal *current_time,
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,
99 static gboolean g_io_win32_pipe_prepare (gpointer source_data,
100 GTimeVal *current_time,
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,
107 static void g_io_win32_pipe_destroy (gpointer source_data);
109 static gboolean g_io_win32_sock_prepare (gpointer source_data,
110 GTimeVal *current_time,
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,
118 static void g_io_win32_destroy (gpointer source_data);
120 static GIOError g_io_win32_msg_read (GIOChannel *channel,
123 guint *bytes_written);
125 static GIOError g_io_win32_msg_write(GIOChannel *channel,
128 guint *bytes_written);
129 static GIOError g_io_win32_msg_seek (GIOChannel *channel,
132 static void g_io_win32_msg_close (GIOChannel *channel);
133 static guint g_io_win32_msg_add_watch (GIOChannel *channel,
135 GIOCondition condition,
138 GDestroyNotify notify);
140 static GIOError g_io_win32_fd_read (GIOChannel *channel,
143 guint *bytes_written);
144 static GIOError g_io_win32_fd_write(GIOChannel *channel,
147 guint *bytes_written);
148 static GIOError g_io_win32_fd_seek (GIOChannel *channel,
151 static void g_io_win32_fd_close (GIOChannel *channel);
153 static void g_io_win32_free (GIOChannel *channel);
155 static guint g_io_win32_fd_add_watch (GIOChannel *channel,
157 GIOCondition condition,
160 GDestroyNotify notify);
162 static GIOError g_io_win32_no_seek (GIOChannel *channel,
166 static GIOError g_io_win32_pipe_read (GIOChannel *channel,
169 guint *bytes_written);
170 static GIOError g_io_win32_pipe_write (GIOChannel *channel,
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,
177 GIOCondition condition,
180 GDestroyNotify notify);
181 static void g_io_win32_pipe_free (GIOChannel *channel);
183 static GIOError g_io_win32_sock_read (GIOChannel *channel,
186 guint *bytes_written);
187 static GIOError g_io_win32_sock_write(GIOChannel *channel,
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,
194 GIOCondition condition,
197 GDestroyNotify notify);
199 GSourceFuncs win32_watch_msg_funcs = {
200 g_io_win32_msg_prepare,
201 g_io_win32_msg_check,
202 g_io_win32_msg_dispatch,
206 GSourceFuncs win32_watch_fd_funcs = {
207 g_io_win32_fd_prepare,
209 g_io_win32_fd_dispatch,
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
220 GSourceFuncs win32_watch_sock_funcs = {
221 g_io_win32_sock_prepare,
222 g_io_win32_sock_check,
223 g_io_win32_sock_dispatch,
227 GIOFuncs win32_channel_msg_funcs = {
229 g_io_win32_msg_write,
231 g_io_win32_msg_close,
232 g_io_win32_msg_add_watch,
236 GIOFuncs win32_channel_fd_funcs = {
241 g_io_win32_fd_add_watch,
245 GIOFuncs win32_channel_pipe_funcs = {
246 g_io_win32_pipe_read,
247 g_io_win32_pipe_write,
249 g_io_win32_pipe_close,
250 g_io_win32_pipe_add_watch,
254 GIOFuncs win32_channel_sock_funcs = {
255 g_io_win32_sock_read,
256 g_io_win32_sock_write,
258 g_io_win32_sock_close,
259 g_io_win32_sock_add_watch,
263 #define N_WATCHED_PIPES 4
267 GIOWin32Watch *watch;
268 GIOWin32Channel *channel;
270 } watched_pipes[N_WATCHED_PIPES];
272 static gint n_watched_pipes = 0;
275 g_io_win32_msg_prepare (gpointer source_data,
276 GTimeVal *current_time,
279 GIOWin32Watch *data = source_data;
280 GIOWin32Channel *win32_channel = (GIOWin32Channel *) data->channel;
285 return PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_NOREMOVE) == TRUE;
289 g_io_win32_msg_check (gpointer source_data,
290 GTimeVal *current_time)
292 GIOWin32Watch *data = source_data;
293 GIOWin32Channel *win32_channel = (GIOWin32Channel *) data->channel;
296 return PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_NOREMOVE) == TRUE;
300 g_io_win32_msg_dispatch (gpointer source_data,
301 GTimeVal *current_time,
305 GIOWin32Watch *data = source_data;
307 return (*data->callback)(data->channel,
308 data->pollfd.revents & data->condition,
313 g_io_win32_destroy (gpointer source_data)
315 GIOWin32Watch *data = source_data;
317 g_main_remove_poll (&data->pollfd);
318 g_io_channel_unref (data->channel);
323 g_io_win32_fd_prepare (gpointer source_data,
324 GTimeVal *current_time,
333 g_io_win32_fd_check (gpointer source_data,
334 GTimeVal *current_time)
336 GIOWin32Watch *data = source_data;
338 return (data->pollfd.revents & data->condition);
342 g_io_win32_fd_dispatch (gpointer source_data,
343 GTimeVal *current_time,
347 GIOWin32Watch *data = source_data;
349 return (*data->callback)(data->channel,
350 data->pollfd.revents & data->condition,
355 g_io_win32_msg_read (GIOChannel *channel,
360 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
361 MSG msg; /* In case of alignment problems */
363 if (count < sizeof (MSG))
364 return G_IO_ERROR_INVAL;
366 if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
367 return G_IO_ERROR_AGAIN;
369 memmove (buf, &msg, sizeof (MSG));
370 *bytes_read = sizeof (MSG);
371 return G_IO_ERROR_NONE;
375 g_io_win32_msg_write(GIOChannel *channel,
378 guint *bytes_written)
380 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
384 if (count != sizeof (MSG))
385 return G_IO_ERROR_INVAL;
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;
392 *bytes_written = sizeof (MSG);
393 return G_IO_ERROR_NONE;
397 g_io_win32_no_seek (GIOChannel *channel,
401 g_warning ("g_io_win32_no_seek: unseekable IO channel type");
402 return G_IO_ERROR_UNKNOWN;
407 g_io_win32_msg_close (GIOChannel *channel)
409 /* Nothing to be done. Or should we set hwnd to some invalid value? */
413 g_io_win32_free (GIOChannel *channel)
415 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
417 g_free (win32_channel);
421 g_io_win32_msg_add_watch (GIOChannel *channel,
423 GIOCondition condition,
426 GDestroyNotify notify)
428 GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
429 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
431 watch->channel = channel;
432 g_io_channel_ref (channel);
434 watch->callback = func;
435 watch->condition = condition;
437 watch->pollfd.fd = G_WIN32_MSG_HANDLE;
438 watch->pollfd.events = condition;
440 g_main_add_poll (&watch->pollfd, priority);
442 return g_source_add (priority, TRUE, &win32_watch_msg_funcs,
443 watch, user_data, notify);
447 g_io_win32_pipe_prepare (gpointer source_data,
448 GTimeVal *current_time,
457 g_io_win32_pipe_check (gpointer source_data,
458 GTimeVal *current_time)
460 GIOWin32Watch *data = source_data;
465 g_io_win32_pipe_dispatch (gpointer source_data,
466 GTimeVal *current_time,
470 GIOWin32Watch *data = source_data;
472 return (*data->callback)(data->channel,
473 data->pollfd.revents & data->condition,
478 g_io_win32_pipe_destroy (gpointer source_data)
480 GIOWin32Watch *data = source_data;
482 g_io_channel_unref (data->channel);
487 g_io_win32_sock_prepare (gpointer source_data,
488 GTimeVal *current_time,
497 g_io_win32_sock_check (gpointer source_data,
498 GTimeVal *current_time)
500 GIOWin32Watch *data = source_data;
502 return (data->pollfd.revents & data->condition);
506 g_io_win32_sock_dispatch (gpointer source_data,
507 GTimeVal *current_time,
511 GIOWin32Watch *data = source_data;
513 return (*data->callback)(data->channel,
514 data->pollfd.revents & data->condition,
519 g_io_win32_fd_read (GIOChannel *channel,
524 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
527 result = read (win32_channel->fd, buf, count);
534 return G_IO_ERROR_INVAL;
536 return G_IO_ERROR_AGAIN;
538 return G_IO_ERROR_UNKNOWN;
543 *bytes_read = result;
544 return G_IO_ERROR_NONE;
549 g_io_win32_fd_write(GIOChannel *channel,
552 guint *bytes_written)
554 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
557 result = write (win32_channel->fd, buf, count);
565 return G_IO_ERROR_INVAL;
567 return G_IO_ERROR_AGAIN;
569 return G_IO_ERROR_UNKNOWN;
574 *bytes_written = result;
575 return G_IO_ERROR_NONE;
580 g_io_win32_fd_seek (GIOChannel *channel,
584 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
600 g_warning ("g_io_win32_fd_seek: unknown seek type");
601 return G_IO_ERROR_UNKNOWN;
604 result = lseek (win32_channel->fd, offset, whence);
611 return G_IO_ERROR_INVAL;
613 return G_IO_ERROR_UNKNOWN;
617 return G_IO_ERROR_NONE;
621 g_io_win32_fd_close (GIOChannel *channel)
623 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
625 close (win32_channel->fd);
630 g_io_win32_fd_add_watch (GIOChannel *channel,
632 GIOCondition condition,
635 GDestroyNotify notify)
637 GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
638 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
640 watch->channel = channel;
641 g_io_channel_ref (channel);
643 watch->callback = func;
644 watch->condition = condition;
646 /* This probably does not work, except for CONIN$. */
647 watch->pollfd.fd = _get_osfhandle (win32_channel->fd);
648 watch->pollfd.events = condition;
650 g_main_add_poll (&watch->pollfd, priority);
652 return g_source_add (priority, TRUE, &win32_watch_fd_funcs,
653 watch, user_data, notify);
657 g_io_win32_pipe_read (GIOChannel *channel,
662 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
667 handle = (HANDLE) _get_osfhandle (win32_channel->fd);
668 if (!PeekNamedPipe (handle, NULL, 0, NULL, &avail, NULL))
670 return G_IO_ERROR_UNKNOWN;
673 count = MIN (count, avail);
675 count = MAX (count, 1); /* Must read at least one byte, or
676 * caller will think it's EOF.
678 /* g_print ("g_io_win32_pipe_read: %d %d\n", win32_channel->fd, count); */
682 result = read (win32_channel->fd, buf, count);
689 return G_IO_ERROR_INVAL;
691 return G_IO_ERROR_AGAIN;
693 return G_IO_ERROR_UNKNOWN;
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;
706 g_io_win32_pipe_write(GIOChannel *channel,
709 guint *bytes_written)
711 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
715 /* g_print ("g_io_win32_pipe_write: %d %d\n", win32_channel->fd, count); */
716 result = write (win32_channel->fd, buf, count);
723 return G_IO_ERROR_INVAL;
725 return G_IO_ERROR_AGAIN;
727 return G_IO_ERROR_UNKNOWN;
732 if (g_pipe_readable_msg == 0)
733 g_pipe_readable_msg = RegisterWindowMessage ("g-pipe-readable");
735 win32_channel->offset += result;
736 /* g_print ("=%d (%d)\n", result, win32_channel->offset); */
737 if (win32_channel->need_wakeups)
739 PostThreadMessage (win32_channel->peer,
741 win32_channel->peer_fd,
742 win32_channel->offset);
744 *bytes_written = result;
745 return G_IO_ERROR_NONE;
750 g_io_win32_pipe_close (GIOChannel *channel)
752 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
754 /* g_print ("g_io_win32_pipe_close: %#x %d\n", channel, win32_channel->fd); */
756 close (win32_channel->fd);
761 g_io_win32_pipe_add_watch (GIOChannel *channel,
763 GIOCondition condition,
766 GDestroyNotify notify)
768 GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
769 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
772 /* g_print ("g_io_win32_pipe_add_watch: %d\n", win32_channel->fd); */
774 watch->channel = channel;
775 g_io_channel_ref (channel);
777 watch->callback = func;
778 watch->condition = condition;
780 watch->pollfd.fd = win32_channel->fd;
781 watch->pollfd.events = condition;
783 for (i = 0; i < n_watched_pipes; i++)
784 if (watched_pipes[i].fd == -1)
786 if (i == N_WATCHED_PIPES)
787 g_error ("Too many watched pipes");
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);
796 return g_source_add (priority, FALSE, &win32_watch_pipe_funcs, watch, user_data, notify);
800 g_io_win32_pipe_free (GIOChannel *channel)
802 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
805 /* g_print ("g_io_win32_pipe_free: %#x %#x\n", channel, channel->channel_data); */
807 for (i = 0; i < n_watched_pipes; i++)
808 if (watched_pipes[i].fd == win32_channel->fd)
810 watched_pipes[i].fd = -1;
813 g_io_win32_free (channel);
817 g_io_win32_sock_read (GIOChannel *channel,
822 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
825 result = recv (win32_channel->fd, buf, count, 0);
826 if (result == SOCKET_ERROR)
829 switch (WSAGetLastError ())
832 return G_IO_ERROR_INVAL;
835 return G_IO_ERROR_AGAIN;
837 return G_IO_ERROR_UNKNOWN;
842 *bytes_read = result;
843 return G_IO_ERROR_NONE;
848 g_io_win32_sock_write(GIOChannel *channel,
851 guint *bytes_written)
853 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
856 result = send (win32_channel->fd, buf, count, 0);
858 if (result == SOCKET_ERROR)
861 switch (WSAGetLastError ())
864 return G_IO_ERROR_INVAL;
867 return G_IO_ERROR_AGAIN;
869 return G_IO_ERROR_UNKNOWN;
874 *bytes_written = result;
875 return G_IO_ERROR_NONE;
880 g_io_win32_sock_close (GIOChannel *channel)
882 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
884 closesocket (win32_channel->fd);
889 g_io_win32_sock_add_watch (GIOChannel *channel,
891 GIOCondition condition,
894 GDestroyNotify notify)
896 GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
897 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
899 watch->channel = channel;
900 g_io_channel_ref (channel);
902 watch->callback = func;
903 watch->condition = condition;
905 watch->pollfd.fd = win32_channel->fd;
906 watch->pollfd.events = condition;
908 g_main_add_poll (&watch->pollfd, priority);
910 return g_source_add (priority, TRUE, &win32_watch_sock_funcs, watch, user_data, notify);
914 g_io_channel_win32_new_messages (guint hwnd)
916 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
917 GIOChannel *channel = (GIOChannel *) win32_channel;
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;
929 g_io_channel_unix_new (gint fd)
931 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
932 GIOChannel *channel = (GIOChannel *) win32_channel;
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;
943 g_io_channel_unix_get_fd (GIOChannel *channel)
945 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
947 return win32_channel->fd;
951 g_io_channel_win32_new_pipe_with_wakeups (int fd,
955 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
956 GIOChannel *channel = (GIOChannel *) win32_channel;
958 /* g_print ("g_io_channel_win32_new_pipe_with_wakeups %d %#x %d\n", fd, peer, peer_fd); */
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;
973 g_io_channel_win32_new_pipe (int fd)
975 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
976 GIOChannel *channel = (GIOChannel *) win32_channel;
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;
989 g_io_channel_win32_new_stream_socket (int socket)
991 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
992 GIOChannel *channel = (GIOChannel *) win32_channel;
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;
1003 g_io_channel_win32_get_fd (GIOChannel *channel)
1005 return g_io_channel_unix_get_fd (channel);
1009 g_io_channel_win32_pipe_request_wakeups (GIOChannel *channel,
1013 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
1015 win32_channel->peer = peer;
1016 win32_channel->peer_fd = peer_fd;
1017 win32_channel->need_wakeups = TRUE;
1021 g_io_channel_win32_pipe_readable (gint fd,
1026 for (i = 0; i < n_watched_pipes; i++)
1027 if (watched_pipes[i].fd == fd)
1029 if (watched_pipes[i].channel->offset < offset)
1030 (*watched_pipes[i].watch->callback) (watched_pipes[i].watch->channel,
1032 watched_pipes[i].user_data);