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
6 * Copyright 1999-2000 Tor Lillqvist and Craig Setera
7 * Copyright 2001 Andrew Lanoix
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
26 * Modified by the GLib Team and others 1997-2000. See the AUTHORS
27 * file for a list of people on the GLib Team. See the ChangeLog
28 * files for a list of changes. These files are distributed with
29 * GLib at ftp://ftp.gtk.org/pub/gtk/.
32 /* Define this to get (very) verbose logging of all channels */
33 /* #define G_IO_WIN32_DEBUG */
39 #include <winsock.h> /* Not everybody has winsock2 */
48 typedef struct _GIOWin32Channel GIOWin32Channel;
49 typedef struct _GIOWin32Watch GIOWin32Watch;
51 #define BUFFER_SIZE 4096
54 G_IO_WIN32_WINDOWS_MESSAGES, /* Windows messages */
55 G_IO_WIN32_FILE_DESC, /* Unix-like file descriptors from
56 * _open() or _pipe(). Read with read().
57 * Have to create separate thread to read.
59 G_IO_WIN32_SOCKET /* Sockets. A separate thread is blocked
60 * in select() most of the time.
62 } GIOWin32ChannelType;
64 struct _GIOWin32Channel {
66 gint fd; /* Either a Unix-like file handle as provided
67 * by the Microsoft C runtime, or a SOCKET
68 * as provided by WinSock.
70 GIOWin32ChannelType type;
74 CRITICAL_SECTION mutex;
76 /* This is used by G_IO_WIN32_WINDOWS_MESSAGES channels */
77 HWND hwnd; /* handle of window, or NULL */
79 /* Following fields are used by both fd and socket channels. */
80 gboolean running; /* Is reader thread running. FALSE if
81 * EOF has been reached.
83 gboolean needs_close; /* If the channel has been closed while
84 * the reader thread was still running.
86 guint thread_id; /* If non-NULL has a reader thread, or has
89 HANDLE data_avail_event;
93 /* Following fields used by fd channels for input */
95 /* Data is kept in a circular buffer. To be able to distinguish between
96 * empty and full buffer, we cannot fill it completely, but have to
97 * leave a one character gap.
99 * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
102 * Full: (wrp + 1) % BUFFER_SIZE == rdp
105 guchar *buffer; /* (Circular) buffer */
106 gint wrp, rdp; /* Buffer indices for writing and reading */
107 HANDLE space_avail_event;
109 /* Following fields used by socket channels */
111 HANDLE data_avail_noticed_event;
114 #define LOCK(mutex) EnterCriticalSection (&mutex)
115 #define UNLOCK(mutex) LeaveCriticalSection (&mutex)
117 struct _GIOWin32Watch {
121 GIOCondition condition;
126 g_io_channel_win32_init (GIOWin32Channel *channel)
128 #ifdef G_IO_WIN32_DEBUG
129 channel->debug = TRUE;
131 if (getenv ("G_IO_WIN32_DEBUG") != NULL)
132 channel->debug = TRUE;
134 channel->debug = FALSE;
136 channel->buffer = NULL;
137 channel->running = FALSE;
138 channel->needs_close = FALSE;
139 channel->thread_id = 0;
140 channel->data_avail_event = NULL;
141 channel->revents = 0;
142 channel->space_avail_event = NULL;
143 channel->data_avail_noticed_event = NULL;
144 channel->watches = NULL;
145 InitializeCriticalSection (&channel->mutex);
149 create_events (GIOWin32Channel *channel)
151 SECURITY_ATTRIBUTES sec_attrs;
153 sec_attrs.nLength = sizeof(SECURITY_ATTRIBUTES);
154 sec_attrs.lpSecurityDescriptor = NULL;
155 sec_attrs.bInheritHandle = FALSE;
157 /* The data available event is manual reset, the space available event
158 * is automatic reset.
160 if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
161 || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL))
162 || !(channel->data_avail_noticed_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
164 gchar *msg = g_win32_error_message (GetLastError ());
165 g_error ("Error creating event: %s", msg);
169 static unsigned __stdcall
170 read_thread (void *parameter)
172 GIOWin32Channel *channel = parameter;
176 g_io_channel_ref ((GIOChannel *)channel);
179 g_print ("read_thread %#x: start fd:%d, data_avail:%#x, space_avail:%#x\n",
182 (guint) channel->data_avail_event,
183 (guint) channel->space_avail_event);
185 channel->buffer = g_malloc (BUFFER_SIZE);
186 channel->rdp = channel->wrp = 0;
187 channel->running = TRUE;
189 SetEvent (channel->space_avail_event);
191 while (channel->running)
193 LOCK (channel->mutex);
195 g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
196 channel->thread_id, channel->rdp, channel->wrp);
197 if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
201 g_print ("read_thread %#x: resetting space_avail\n",
203 ResetEvent (channel->space_avail_event);
205 g_print ("read_thread %#x: waiting for space\n",
207 UNLOCK (channel->mutex);
208 WaitForSingleObject (channel->space_avail_event, INFINITE);
209 LOCK (channel->mutex);
211 g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
212 channel->thread_id, channel->rdp, channel->wrp);
215 buffer = channel->buffer + channel->wrp;
217 /* Always leave at least one byte unused gap to be able to
218 * distinguish between the full and empty condition...
220 nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
221 BUFFER_SIZE - channel->wrp);
224 g_print ("read_thread %#x: calling read() for %d bytes\n",
225 channel->thread_id, nbytes);
227 UNLOCK (channel->mutex);
229 nbytes = read (channel->fd, buffer, nbytes);
231 LOCK (channel->mutex);
233 channel->revents = G_IO_IN;
235 channel->revents |= G_IO_HUP;
237 channel->revents |= G_IO_ERR;
240 g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
241 channel->thread_id, nbytes, channel->rdp, channel->wrp);
246 channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
248 g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
249 channel->thread_id, channel->rdp, channel->wrp);
250 SetEvent (channel->data_avail_event);
251 UNLOCK (channel->mutex);
254 channel->running = FALSE;
255 if (channel->needs_close)
258 g_print ("read_thread %#x: channel fd %d needs closing\n",
259 channel->thread_id, channel->fd);
265 g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
266 channel->thread_id, channel->rdp, channel->wrp);
267 SetEvent (channel->data_avail_event);
268 UNLOCK (channel->mutex);
270 g_io_channel_unref((GIOChannel *)channel);
272 /* No need to call _endthreadex(), the actual thread starter routine
273 * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
274 * _endthreadex() for us.
277 CloseHandle (channel->thread_handle);
283 create_thread (GIOWin32Channel *channel,
284 GIOCondition condition,
285 unsigned (__stdcall *thread) (void *parameter))
287 channel->thread_handle =
288 (HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
289 &channel->thread_id);
290 if (channel->thread_handle == 0)
291 g_warning (G_STRLOC ": Error creating reader thread: %s",
293 WaitForSingleObject (channel->space_avail_event, INFINITE);
297 buffer_read (GIOWin32Channel *channel,
306 LOCK (channel->mutex);
308 g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
309 channel->thread_id, count, channel->rdp, channel->wrp);
311 if (channel->wrp == channel->rdp)
313 UNLOCK (channel->mutex);
315 g_print ("waiting for data from thread %#x\n", channel->thread_id);
316 WaitForSingleObject (channel->data_avail_event, INFINITE);
318 g_print ("done waiting for data from thread %#x\n", channel->thread_id);
319 LOCK (channel->mutex);
320 if (channel->wrp == channel->rdp && !channel->running)
322 UNLOCK (channel->mutex);
324 return G_IO_STATUS_NORMAL; /* as before, normal case ? */
328 if (channel->rdp < channel->wrp)
329 nbytes = channel->wrp - channel->rdp;
331 nbytes = BUFFER_SIZE - channel->rdp;
332 UNLOCK (channel->mutex);
333 nbytes = MIN (left, nbytes);
335 g_print ("moving %d bytes from thread %#x\n",
336 nbytes, channel->thread_id);
337 memcpy (dest, channel->buffer + channel->rdp, nbytes);
340 LOCK (channel->mutex);
341 channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
343 g_print ("setting space_avail for thread %#x\n", channel->thread_id);
344 SetEvent (channel->space_avail_event);
346 g_print ("for thread %#x: rdp=%d, wrp=%d\n",
347 channel->thread_id, channel->rdp, channel->wrp);
348 if (channel->running && channel->wrp == channel->rdp)
351 g_print ("resetting data_avail of thread %#x\n",
353 ResetEvent (channel->data_avail_event);
355 UNLOCK (channel->mutex);
357 /* We have no way to indicate any errors form the actual
358 * read() or recv() call in the reader thread. Should we have?
360 *bytes_read = count - left;
361 return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
364 static unsigned __stdcall
365 select_thread (void *parameter)
367 GIOWin32Channel *channel = parameter;
368 fd_set read_fds, write_fds, except_fds;
372 g_io_channel_ref ((GIOChannel *)channel);
375 g_print ("select_thread %#x: start fd:%d,\n\tdata_avail:%#x, data_avail_noticed:%#x\n",
378 (guint) channel->data_avail_event,
379 (guint) channel->data_avail_noticed_event);
381 channel->rdp = channel->wrp = 0;
382 channel->running = TRUE;
384 SetEvent (channel->space_avail_event);
386 while (channel->running)
389 FD_ZERO (&write_fds);
390 FD_ZERO (&except_fds);
392 tmp = channel->watches;
395 GIOWin32Watch *watch = (GIOWin32Watch *)tmp->data;
397 if (watch->condition & (G_IO_IN | G_IO_HUP))
398 FD_SET (channel->fd, &read_fds);
399 if (watch->condition & G_IO_OUT)
400 FD_SET (channel->fd, &write_fds);
401 if (watch->condition & G_IO_ERR)
402 FD_SET (channel->fd, &except_fds);
407 g_print ("select_thread %#x: calling select() for%s%s%s\n",
409 (FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
410 (FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
411 (FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
413 n = select (1, &read_fds, &write_fds, &except_fds, NULL);
415 if (n == SOCKET_ERROR)
418 g_print ("select_thread %#x: select returned SOCKET_ERROR\n",
424 g_print ("select_thread %#x: got%s%s%s\n",
426 (FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
427 (FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
428 (FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
430 if (FD_ISSET (channel->fd, &read_fds))
431 channel->revents |= G_IO_IN;
432 if (FD_ISSET (channel->fd, &write_fds))
433 channel->revents |= G_IO_OUT;
434 if (FD_ISSET (channel->fd, &except_fds))
435 channel->revents |= G_IO_ERR;
438 g_print ("select_thread %#x: resetting data_avail_noticed,\n"
439 "\tsetting data_avail\n",
441 ResetEvent (channel->data_avail_noticed_event);
442 SetEvent (channel->data_avail_event);
444 LOCK (channel->mutex);
445 if (channel->needs_close)
447 UNLOCK (channel->mutex);
450 UNLOCK (channel->mutex);
453 g_print ("select_thread %#x: waiting for data_avail_noticed\n",
456 WaitForSingleObject (channel->data_avail_noticed_event, INFINITE);
458 g_print ("select_thread %#x: got data_avail_noticed\n",
462 channel->running = FALSE;
463 LOCK (channel->mutex);
464 if (channel->fd != -1)
466 /* DO NOT close the fd here */
471 g_print ("select_thread %#x: got error, setting data_avail\n",
473 SetEvent (channel->data_avail_event);
474 UNLOCK (channel->mutex);
476 g_io_channel_unref((GIOChannel *)channel);
478 /* No need to call _endthreadex(), the actual thread starter routine
479 * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
480 * _endthreadex() for us.
483 CloseHandle (channel->thread_handle);
489 g_io_win32_prepare (GSource *source,
492 GIOWin32Watch *watch = (GIOWin32Watch *)source;
493 GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
497 if (channel->type == G_IO_WIN32_FILE_DESC)
499 LOCK (channel->mutex);
500 if (channel->running && channel->wrp == channel->rdp)
501 channel->revents = 0;
502 UNLOCK (channel->mutex);
504 else if (channel->type == G_IO_WIN32_SOCKET)
506 channel->revents = 0;
509 g_print ("g_io_win32_prepare: thread %#x, setting data_avail_noticed\n",
511 SetEvent (channel->data_avail_noticed_event);
513 g_print ("g_io_win32_prepare: thread %#x, there.\n",
518 /* XXX: why should we want to do this ? */
519 watch->condition = g_io_channel_get_buffer_condition (watch->channel);
521 return (watch->pollfd.revents & (G_IO_IN | G_IO_OUT)) == watch->condition;
525 g_io_win32_check (GSource *source)
528 GIOWin32Watch *watch = (GIOWin32Watch *)source;
529 GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
530 GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
534 g_print ("g_io_win32_check: for thread %#x:\n"
535 "\twatch->pollfd.events:%#x, watch->pollfd.revents:%#x, channel->revents:%#x\n",
537 watch->pollfd.events, watch->pollfd.revents, channel->revents);
539 if (channel->type != G_IO_WIN32_WINDOWS_MESSAGES)
541 watch->pollfd.revents = (watch->pollfd.events & channel->revents);
545 return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE));
548 if (channel->type == G_IO_WIN32_SOCKET)
551 g_print ("g_io_win32_check: thread %#x, resetting data_avail\n",
553 ResetEvent (channel->data_avail_event);
555 g_print ("g_io_win32_check: thread %#x, there.\n",
559 return (watch->pollfd.revents & watch->condition);
563 g_io_win32_dispatch (GSource *source,
564 GSourceFunc callback,
567 GIOFunc func = (GIOFunc)callback;
568 GIOWin32Watch *watch = (GIOWin32Watch *)source;
572 g_warning (G_STRLOC ": GIOWin32Watch dispatched without callback\n"
573 "You must call g_source_connect().");
577 return (*func) (watch->channel,
578 watch->pollfd.revents & watch->condition,
583 g_io_win32_finalize (GSource *source)
585 GIOWin32Watch *watch = (GIOWin32Watch *)source;
586 GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
589 g_print ("g_io_win32_finalize: channel with thread %#x\n",
592 channel->watches = g_slist_remove (channel->watches, watch);
594 SetEvent (channel->data_avail_noticed_event);
595 g_io_channel_unref (watch->channel);
598 #if defined(G_PLATFORM_WIN32) && defined(__GNUC__)
599 __declspec(dllexport)
601 GSourceFuncs g_io_watch_funcs = {
609 g_io_win32_create_watch (GIOChannel *channel,
610 GIOCondition condition,
611 unsigned (__stdcall *thread) (void *parameter))
613 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
614 GIOWin32Watch *watch;
617 source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
618 watch = (GIOWin32Watch *)source;
620 watch->channel = channel;
621 g_io_channel_ref (channel);
623 watch->condition = condition;
625 if (win32_channel->data_avail_event == NULL)
626 create_events (win32_channel);
628 watch->pollfd.fd = (gint) win32_channel->data_avail_event;
629 watch->pollfd.events = condition;
631 if (win32_channel->debug)
632 g_print ("g_io_win32_create_watch: fd:%d condition:%#x handle:%#x\n",
633 win32_channel->fd, condition, watch->pollfd.fd);
635 win32_channel->watches = g_slist_append (win32_channel->watches, watch);
637 if (win32_channel->thread_id == 0)
638 create_thread (win32_channel, condition, thread);
640 g_source_add_poll (source, &watch->pollfd);
646 g_io_win32_msg_read (GIOChannel *channel,
652 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
653 MSG msg; /* In case of alignment problems */
655 if (count < sizeof (MSG))
657 g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
658 _("Incorrect message size")); /* Correct error message? FIXME */
659 return G_IO_STATUS_ERROR;
662 if (win32_channel->debug)
663 g_print ("g_io_win32_msg_read: for %#x\n",
664 win32_channel->hwnd);
665 if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
666 return G_IO_STATUS_AGAIN;
668 memmove (buf, &msg, sizeof (MSG));
669 *bytes_read = sizeof (MSG);
671 return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
675 g_io_win32_msg_write (GIOChannel *channel,
678 gsize *bytes_written,
681 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
684 if (count != sizeof (MSG))
686 g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
687 _("Incorrect message size")); /* Correct error message? FIXME */
688 return G_IO_STATUS_ERROR;
691 /* In case of alignment problems */
692 memmove (&msg, buf, sizeof (MSG));
693 if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
695 g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED,
696 _("Unknown error")); /* Correct error message? FIXME */
697 return G_IO_STATUS_ERROR;
700 *bytes_written = sizeof (MSG);
702 return G_IO_STATUS_NORMAL;
706 g_io_win32_no_seek (GIOChannel *channel,
711 g_assert_not_reached ();
713 return G_IO_STATUS_ERROR;
717 g_io_win32_msg_close (GIOChannel *channel,
720 /* Nothing to be done. Or should we set hwnd to some invalid value? */
722 return G_IO_STATUS_NORMAL;
726 g_io_win32_free (GIOChannel *channel)
728 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
730 if (win32_channel->debug)
731 g_print ("thread %#x: freeing channel, fd: %d\n",
732 win32_channel->thread_id,
735 if (win32_channel->data_avail_event)
736 CloseHandle (win32_channel->data_avail_event);
737 if (win32_channel->space_avail_event)
738 CloseHandle (win32_channel->space_avail_event);
739 if (win32_channel->data_avail_noticed_event)
740 CloseHandle (win32_channel->data_avail_noticed_event);
741 DeleteCriticalSection (&win32_channel->mutex);
743 g_free (win32_channel->buffer);
744 g_slist_free (win32_channel->watches);
745 g_free (win32_channel);
749 g_io_win32_msg_create_watch (GIOChannel *channel,
750 GIOCondition condition)
752 GIOWin32Watch *watch;
755 source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
756 watch = (GIOWin32Watch *)source;
758 watch->channel = channel;
759 g_io_channel_ref (channel);
761 watch->condition = condition;
763 watch->pollfd.fd = G_WIN32_MSG_HANDLE;
764 watch->pollfd.events = condition;
766 g_source_add_poll (source, &watch->pollfd);
772 g_io_win32_fd_read (GIOChannel *channel,
778 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
781 if (win32_channel->debug)
782 g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
783 win32_channel->fd, count);
785 if (win32_channel->thread_id)
787 return buffer_read (win32_channel, buf, count, bytes_read, err);
790 result = read (win32_channel->fd, buf, count);
800 return G_IO_STATUS_AGAIN;
803 g_set_error (err, G_IO_CHANNEL_ERROR,
804 g_io_channel_error_from_errno (errno),
806 return G_IO_STATUS_ERROR;
810 *bytes_read = result;
812 return G_IO_STATUS_NORMAL; /* XXX: 0 byte read an error ?? */
813 return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
817 g_io_win32_fd_write (GIOChannel *channel,
820 gsize *bytes_written,
823 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
826 result = write (win32_channel->fd, buf, count);
827 if (win32_channel->debug)
828 g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
829 win32_channel->fd, count, result);
839 return G_IO_STATUS_AGAIN;
842 g_set_error (err, G_IO_CHANNEL_ERROR,
843 g_io_channel_error_from_errno (errno),
845 return G_IO_STATUS_ERROR;
849 *bytes_written = result;
851 return G_IO_STATUS_NORMAL;
855 g_io_win32_fd_seek (GIOChannel *channel,
860 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
876 whence = -1; /* Keep the compiler quiet */
877 g_assert_not_reached();
880 result = lseek (win32_channel->fd, offset, whence);
884 g_set_error (err, G_IO_CHANNEL_ERROR,
885 g_io_channel_error_from_errno (errno),
887 return G_IO_STATUS_ERROR;
890 return G_IO_STATUS_NORMAL;
894 g_io_win32_fd_close (GIOChannel *channel,
897 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
899 if (win32_channel->debug)
900 g_print ("thread %#x: closing fd %d\n",
901 win32_channel->thread_id,
903 LOCK (win32_channel->mutex);
904 if (win32_channel->running)
906 if (win32_channel->debug)
907 g_print ("thread %#x: running, marking fd %d for later close\n",
908 win32_channel->thread_id, win32_channel->fd);
909 win32_channel->running = FALSE;
910 win32_channel->needs_close = TRUE;
911 SetEvent (win32_channel->data_avail_event);
915 if (win32_channel->debug)
916 g_print ("closing fd %d\n", win32_channel->fd);
917 close (win32_channel->fd);
918 if (win32_channel->debug)
919 g_print ("closed fd %d, setting to -1\n",
921 win32_channel->fd = -1;
923 UNLOCK (win32_channel->mutex);
925 /* FIXME error detection? */
927 return G_IO_STATUS_NORMAL;
931 g_io_win32_fd_create_watch (GIOChannel *channel,
932 GIOCondition condition)
934 return g_io_win32_create_watch (channel, condition, read_thread);
938 g_io_win32_sock_read (GIOChannel *channel,
944 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
946 GIOChannelError error;
948 if (win32_channel->debug)
949 g_print ("g_io_win32_sock_read: sockfd:%d count:%d\n",
950 win32_channel->fd, count);
952 result = recv (win32_channel->fd, buf, count, 0);
954 if (win32_channel->debug)
955 g_print ("g_io_win32_sock_read: recv:%d\n", result);
957 if (result == SOCKET_ERROR)
961 switch (WSAGetLastError ())
964 error = G_IO_CHANNEL_ERROR_INVAL;
967 return G_IO_STATUS_AGAIN;
968 #ifdef WE_NEED_TO_HANDLE_WSAEINTR /* not anymore with wsock2 ? */
973 error = G_IO_CHANNEL_ERROR_FAILED;
976 g_set_error(err, G_IO_CHANNEL_ERROR, error, _("Socket error"));
977 return G_IO_STATUS_ERROR;
978 /* FIXME get all errors, better error messages */
982 *bytes_read = result;
984 return G_IO_STATUS_NORMAL; /* XXX: 0 byte read an error ?? */
985 return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
990 g_io_win32_sock_write (GIOChannel *channel,
993 gsize *bytes_written,
996 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
998 GIOChannelError error;
1000 if (win32_channel->debug)
1001 g_print ("g_io_win32_sock_write: sockfd:%d count:%d\n",
1002 win32_channel->fd, count);
1004 result = send (win32_channel->fd, buf, count, 0);
1006 if (win32_channel->debug)
1007 g_print ("g_io_win32_sock_write: send:%d\n", result);
1009 if (result == SOCKET_ERROR)
1013 switch (WSAGetLastError ())
1016 error = G_IO_CHANNEL_ERROR_INVAL;
1018 case WSAEWOULDBLOCK:
1019 return G_IO_STATUS_AGAIN;
1020 #ifdef WE_NEED_TO_HANDLE_WSAEINTR /* not anymore with wsock2 ? */
1025 error = G_IO_CHANNEL_ERROR_FAILED;
1028 g_set_error(err, G_IO_CHANNEL_ERROR, error, _("Socket error"));
1029 return G_IO_STATUS_ERROR;
1030 /* FIXME get all errors, better error messages */
1034 *bytes_written = result;
1036 return G_IO_STATUS_NORMAL;
1041 g_io_win32_sock_close (GIOChannel *channel,
1044 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1046 LOCK(win32_channel->mutex);
1047 if (win32_channel->running)
1049 if (win32_channel->debug)
1050 g_print ("thread %#x: running, marking for later close\n",
1051 win32_channel->thread_id);
1052 win32_channel->running = FALSE;
1053 win32_channel->needs_close = TRUE;
1054 SetEvent(win32_channel->data_avail_noticed_event);
1056 if (win32_channel->fd != -1)
1058 if (win32_channel->debug)
1059 g_print ("thread %#x: closing socket %d\n",
1060 win32_channel->thread_id,
1063 closesocket (win32_channel->fd);
1064 win32_channel->fd = -1;
1066 UNLOCK(win32_channel->mutex);
1068 /* FIXME error detection? */
1070 return G_IO_STATUS_NORMAL;
1074 g_io_win32_sock_create_watch (GIOChannel *channel,
1075 GIOCondition condition)
1077 return g_io_win32_create_watch (channel, condition, select_thread);
1081 g_io_channel_new_file (const gchar *filename,
1085 int fid, flags, pmode;
1086 GIOChannel *channel;
1088 enum { /* Cheesy hack */
1095 g_return_val_if_fail (filename != NULL, NULL);
1096 g_return_val_if_fail (mode != NULL, NULL);
1097 g_return_val_if_fail ((error == NULL) || (*error == NULL), NULL);
1111 g_warning (G_STRLOC ": Invalid GIOFileMode %s.\n", mode);
1120 if (mode[2] == '\0')
1122 mode_num |= MODE_PLUS;
1127 g_warning (G_STRLOC ": Invalid GIOFileMode %s.\n", mode);
1138 flags = O_WRONLY | O_TRUNC | O_CREAT;
1142 flags = O_WRONLY | O_APPEND | O_CREAT;
1145 case MODE_R | MODE_PLUS:
1147 pmode = _S_IREAD | _S_IWRITE;
1149 case MODE_W | MODE_PLUS:
1150 flags = O_RDWR | O_TRUNC | O_CREAT;
1151 pmode = _S_IREAD | _S_IWRITE;
1153 case MODE_A | MODE_PLUS:
1154 flags = O_RDWR | O_APPEND | O_CREAT;
1155 pmode = _S_IREAD | _S_IWRITE;
1158 g_assert_not_reached ();
1164 fid = open (filename, flags, pmode);
1167 g_set_error (error, G_FILE_ERROR,
1168 g_file_error_from_errno (errno),
1170 return (GIOChannel *)NULL;
1173 channel = g_io_channel_win32_new_fd (fid);
1175 /* XXX: move this to g_io_channel_win32_new_fd () */
1176 channel->close_on_unref = TRUE;
1177 channel->is_seekable = TRUE;
1182 channel->is_readable = TRUE;
1183 channel->is_writeable = FALSE;
1187 channel->is_readable = FALSE;
1188 channel->is_writeable = TRUE;
1190 case MODE_R | MODE_PLUS:
1191 case MODE_W | MODE_PLUS:
1192 case MODE_A | MODE_PLUS:
1193 channel->is_readable = TRUE;
1194 channel->is_writeable = TRUE;
1197 g_assert_not_reached ();
1200 if (((GIOWin32Channel *)channel)->debug)
1201 g_print ("g_io_channel_win32_new_file: fd = %ud\n", fid);
1207 g_io_win32_set_flags (GIOChannel *channel,
1211 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1215 g_file_error_from_errno (EACCES),
1216 _("Channel set flags unsupported"));
1217 return G_IO_STATUS_ERROR;
1221 g_io_win32_fd_get_flags (GIOChannel *channel)
1225 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1227 g_return_val_if_fail (win32_channel != NULL, 0);
1228 g_return_val_if_fail (win32_channel->type == G_IO_WIN32_FILE_DESC, 0);
1230 if (0 == _fstat (win32_channel->fd, &st))
1232 /* XXX: G_IO_FLAG_APPEND */
1233 /* XXX: G_IO_FLAG_NONBLOCK */
1234 if (st.st_mode & _S_IREAD) flags |= G_IO_FLAG_IS_READABLE;
1235 if (st.st_mode & _S_IWRITE) flags |= G_IO_FLAG_IS_WRITEABLE;
1237 if (!(st.st_mode & _S_IFIFO)) flags |= G_IO_FLAG_IS_SEEKABLE;
1244 * Generic implementation, just translating createion flags
1247 g_io_win32_get_flags (GIOChannel *channel)
1251 flags = (channel->is_readable ? G_IO_FLAG_IS_READABLE : 0)
1252 | (channel->is_writeable ? G_IO_FLAG_IS_READABLE : 0)
1253 | (channel->is_seekable ? G_IO_FLAG_IS_SEEKABLE : 0);
1258 static GIOFuncs win32_channel_msg_funcs = {
1259 g_io_win32_msg_read,
1260 g_io_win32_msg_write,
1262 g_io_win32_msg_close,
1263 g_io_win32_msg_create_watch,
1265 g_io_win32_set_flags,
1266 g_io_win32_get_flags,
1269 static GIOFuncs win32_channel_fd_funcs = {
1271 g_io_win32_fd_write,
1273 g_io_win32_fd_close,
1274 g_io_win32_fd_create_watch,
1276 g_io_win32_set_flags,
1277 g_io_win32_fd_get_flags,
1280 static GIOFuncs win32_channel_sock_funcs = {
1281 g_io_win32_sock_read,
1282 g_io_win32_sock_write,
1284 g_io_win32_sock_close,
1285 g_io_win32_sock_create_watch,
1287 g_io_win32_set_flags,
1288 g_io_win32_get_flags,
1292 g_io_channel_win32_new_messages (guint hwnd)
1294 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1295 GIOChannel *channel = (GIOChannel *)win32_channel;
1297 g_io_channel_init (channel);
1298 g_io_channel_win32_init (win32_channel);
1299 if (win32_channel->debug)
1300 g_print ("g_io_channel_win32_new_messages: hwnd = %ud\n", hwnd);
1301 channel->funcs = &win32_channel_msg_funcs;
1302 win32_channel->type = G_IO_WIN32_WINDOWS_MESSAGES;
1303 win32_channel->hwnd = (HWND) hwnd;
1305 /* XXX: check this. */
1306 channel->is_readable = IsWindow (win32_channel->hwnd);
1307 channel->is_writeable = IsWindow (win32_channel->hwnd);
1309 channel->is_seekable = FALSE;
1315 g_io_channel_win32_new_fd (gint fd)
1317 GIOWin32Channel *win32_channel;
1318 GIOChannel *channel;
1321 if (fstat (fd, &st) == -1)
1323 g_warning (G_STRLOC ": %d isn't a (emulated) file descriptor", fd);
1327 win32_channel = g_new (GIOWin32Channel, 1);
1328 channel = (GIOChannel *)win32_channel;
1330 g_io_channel_init (channel);
1331 g_io_channel_win32_init (win32_channel);
1332 if (win32_channel->debug)
1333 g_print ("g_io_channel_win32_new_fd: fd = %d\n", fd);
1334 channel->funcs = &win32_channel_fd_funcs;
1335 win32_channel->type = G_IO_WIN32_FILE_DESC;
1336 win32_channel->fd = fd;
1339 channel->is_readable = !!(st.st_mode & _S_IREAD);
1340 channel->is_writeable = !!(st.st_mode & _S_IWRITE);
1341 /* XXX: pipes aren't seeakable, are they ? */
1342 channel->is_seekable = !(st.st_mode & _S_IFIFO);
1348 g_io_channel_win32_get_fd (GIOChannel *channel)
1350 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1352 return win32_channel->fd;
1356 g_io_channel_win32_new_socket (int socket)
1358 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1359 GIOChannel *channel = (GIOChannel *)win32_channel;
1361 g_io_channel_init (channel);
1362 g_io_channel_win32_init (win32_channel);
1363 if (win32_channel->debug)
1364 g_print ("g_io_channel_win32_new_socket: sockfd:%d\n", socket);
1365 channel->funcs = &win32_channel_sock_funcs;
1366 win32_channel->type = G_IO_WIN32_SOCKET;
1367 win32_channel->fd = socket;
1369 /* XXX: check this */
1370 channel->is_readable = TRUE;
1371 channel->is_writeable = TRUE;
1372 channel->is_seekable = FALSE;
1378 g_io_channel_unix_new (gint fd)
1382 if (fstat (fd, &st) == 0)
1383 return g_io_channel_win32_new_fd (fd);
1385 if (getsockopt (fd, SOL_SOCKET, SO_TYPE, NULL, NULL) != SO_ERROR)
1386 return g_io_channel_win32_new_socket(fd);
1388 g_warning (G_STRLOC ": %d is neither a file descriptor or a socket", fd);
1393 g_io_channel_unix_get_fd (GIOChannel *channel)
1395 return g_io_channel_win32_get_fd (channel);
1399 g_io_channel_win32_set_debug (GIOChannel *channel,
1402 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1404 win32_channel->debug = flag;
1408 g_io_channel_win32_poll (GPollFD *fds,
1414 g_return_val_if_fail (n_fds >= 0, 0);
1416 result = (*g_main_context_get_poll_func (NULL)) (fds, n_fds, timeout);
1422 g_io_channel_win32_make_pollfd (GIOChannel *channel,
1423 GIOCondition condition,
1426 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1428 if (win32_channel->data_avail_event == NULL)
1429 create_events (win32_channel);
1431 fd->fd = (gint) win32_channel->data_avail_event;
1432 fd->events = condition;
1434 if (win32_channel->thread_id == 0)
1435 if ((condition & G_IO_IN) && win32_channel->type == G_IO_WIN32_FILE_DESC)
1436 create_thread (win32_channel, condition, read_thread);
1437 else if (win32_channel->type == G_IO_WIN32_SOCKET)
1438 create_thread (win32_channel, condition, select_thread);
1441 /* Binary compatibility */
1443 g_io_channel_win32_new_stream_socket (int socket)
1445 return g_io_channel_win32_new_socket (socket);