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_EOF; /* Is this correct? FIXME */
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",
517 watch->condition = g_io_channel_get_buffer_condition (watch->channel);
519 return (watch->pollfd.revents & (G_IO_IN | G_IO_OUT)) == watch->condition;
523 g_io_win32_check (GSource *source)
526 GIOWin32Watch *watch = (GIOWin32Watch *)source;
527 GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
530 g_print ("g_io_win32_check: for thread %#x:\n"
531 "\twatch->pollfd.events:%#x, watch->pollfd.revents:%#x, channel->revents:%#x\n",
533 watch->pollfd.events, watch->pollfd.revents, channel->revents);
535 if (channel->type != G_IO_WIN32_WINDOWS_MESSAGES)
537 watch->pollfd.revents = (watch->pollfd.events & channel->revents);
541 return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE));
544 if (channel->type == G_IO_WIN32_SOCKET)
547 g_print ("g_io_win32_check: thread %#x, resetting data_avail\n",
549 ResetEvent (channel->data_avail_event);
551 g_print ("g_io_win32_check: thread %#x, there.\n",
555 watch->condition &= g_io_channel_get_buffer_condition (watch->channel);
557 return (watch->pollfd.revents & watch->condition);
561 g_io_win32_dispatch (GSource *source,
562 GSourceFunc callback,
565 GIOFunc func = (GIOFunc)callback;
566 GIOWin32Watch *watch = (GIOWin32Watch *)source;
570 g_warning (G_STRLOC ": GIOWin32Watch dispatched without callback\n"
571 "You must call g_source_connect().");
575 return (*func) (watch->channel,
576 watch->pollfd.revents & watch->condition,
581 g_io_win32_finalize (GSource *source)
583 GIOWin32Watch *watch = (GIOWin32Watch *)source;
584 GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
587 g_print ("g_io_win32_finalize: channel with thread %#x\n",
590 channel->watches = g_slist_remove (channel->watches, watch);
592 SetEvent (channel->data_avail_noticed_event);
593 g_io_channel_unref (watch->channel);
596 static GSourceFuncs win32_watch_funcs = {
604 g_io_win32_create_watch (GIOChannel *channel,
605 GIOCondition condition,
606 unsigned (__stdcall *thread) (void *parameter))
608 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
609 GIOWin32Watch *watch;
612 source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
613 watch = (GIOWin32Watch *)source;
615 watch->channel = channel;
616 g_io_channel_ref (channel);
618 watch->condition = condition;
620 if (win32_channel->data_avail_event == NULL)
621 create_events (win32_channel);
623 watch->pollfd.fd = (gint) win32_channel->data_avail_event;
624 watch->pollfd.events = condition;
626 if (win32_channel->debug)
627 g_print ("g_io_win32_create_watch: fd:%d condition:%#x handle:%#x\n",
628 win32_channel->fd, condition, watch->pollfd.fd);
630 win32_channel->watches = g_slist_append (win32_channel->watches, watch);
632 if (win32_channel->thread_id == 0)
633 create_thread (win32_channel, condition, thread);
635 g_source_add_poll (source, &watch->pollfd);
641 g_io_win32_msg_read (GIOChannel *channel,
647 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
648 MSG msg; /* In case of alignment problems */
650 if (count < sizeof (MSG))
652 g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
653 _("Incorrect message size")); /* Correct error message? FIXME */
654 return G_IO_STATUS_ERROR;
657 if (win32_channel->debug)
658 g_print ("g_io_win32_msg_read: for %#x\n",
659 win32_channel->hwnd);
660 if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
661 return G_IO_STATUS_AGAIN;
663 memmove (buf, &msg, sizeof (MSG));
664 *bytes_read = sizeof (MSG);
666 return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
670 g_io_win32_msg_write (GIOChannel *channel,
673 gsize *bytes_written,
676 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
679 if (count != sizeof (MSG))
681 g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
682 _("Incorrect message size")); /* Correct error message? FIXME */
683 return G_IO_STATUS_ERROR;
686 /* In case of alignment problems */
687 memmove (&msg, buf, sizeof (MSG));
688 if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
690 g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED,
691 _("Unknown error")); /* Correct error message? FIXME */
692 return G_IO_STATUS_ERROR;
695 *bytes_written = sizeof (MSG);
697 return G_IO_STATUS_NORMAL;
701 g_io_win32_no_seek (GIOChannel *channel,
706 g_set_error(err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_SPIPE,
707 _("Seeking not allowed on this type of channel"));
709 return G_IO_STATUS_ERROR;
713 g_io_win32_msg_close (GIOChannel *channel)
715 /* Nothing to be done. Or should we set hwnd to some invalid value? */
719 g_io_win32_free (GIOChannel *channel)
721 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
723 if (win32_channel->debug)
724 g_print ("thread %#x: freeing channel, fd: %d\n",
725 win32_channel->thread_id,
728 if (win32_channel->data_avail_event)
729 CloseHandle (win32_channel->data_avail_event);
730 if (win32_channel->space_avail_event)
731 CloseHandle (win32_channel->space_avail_event);
732 if (win32_channel->data_avail_noticed_event)
733 CloseHandle (win32_channel->data_avail_noticed_event);
734 DeleteCriticalSection (&win32_channel->mutex);
736 g_free (win32_channel->buffer);
737 g_slist_free (win32_channel->watches);
738 g_free (win32_channel);
742 g_io_win32_msg_create_watch (GIOChannel *channel,
743 GIOCondition condition)
745 GIOWin32Watch *watch;
748 source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
749 watch = (GIOWin32Watch *)source;
751 watch->channel = channel;
752 g_io_channel_ref (channel);
754 watch->condition = condition;
756 watch->pollfd.fd = G_WIN32_MSG_HANDLE;
757 watch->pollfd.events = condition;
759 g_source_add_poll (source, &watch->pollfd);
765 g_io_win32_fd_read (GIOChannel *channel,
771 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
774 if (win32_channel->debug)
775 g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
776 win32_channel->fd, count);
778 if (win32_channel->thread_id)
780 return buffer_read (win32_channel, buf, count, bytes_read, err);
783 result = read (win32_channel->fd, buf, count);
793 return G_IO_STATUS_AGAIN;
796 g_set_error (err, G_IO_CHANNEL_ERROR,
797 g_channel_error_from_errno (errno),
799 return G_IO_STATUS_ERROR;
803 *bytes_read = result;
805 return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
809 g_io_win32_fd_write (GIOChannel *channel,
812 gsize *bytes_written,
815 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
818 result = write (win32_channel->fd, buf, count);
819 if (win32_channel->debug)
820 g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
821 win32_channel->fd, count, result);
831 return G_IO_STATUS_AGAIN;
834 g_set_error (err, G_IO_CHANNEL_ERROR,
835 g_channel_error_from_errno (errno),
837 return G_IO_STATUS_ERROR;
841 *bytes_written = result;
843 return G_IO_STATUS_NORMAL;
847 g_io_win32_fd_seek (GIOChannel *channel,
852 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
868 whence = -1; /* Keep the compiler quiet */
869 g_assert_not_reached();
872 result = lseek (win32_channel->fd, offset, whence);
876 g_set_error (err, G_IO_CHANNEL_ERROR,
877 g_channel_error_from_errno (errno),
879 return G_IO_STATUS_ERROR;
882 return G_IO_STATUS_NORMAL;
886 g_io_win32_fd_close (GIOChannel *channel)
888 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
890 if (win32_channel->debug)
891 g_print ("thread %#x: closing fd %d\n",
892 win32_channel->thread_id,
894 LOCK (win32_channel->mutex);
895 if (win32_channel->running)
897 if (win32_channel->debug)
898 g_print ("thread %#x: running, marking fd %d for later close\n",
899 win32_channel->thread_id, win32_channel->fd);
900 win32_channel->running = FALSE;
901 win32_channel->needs_close = TRUE;
902 SetEvent (win32_channel->data_avail_event);
906 if (win32_channel->debug)
907 g_print ("closing fd %d\n", win32_channel->fd);
908 close (win32_channel->fd);
909 if (win32_channel->debug)
910 g_print ("closed fd %d, setting to -1\n",
912 win32_channel->fd = -1;
914 UNLOCK (win32_channel->mutex);
918 g_io_win32_fd_create_watch (GIOChannel *channel,
919 GIOCondition condition)
921 return g_io_win32_create_watch (channel, condition, read_thread);
925 g_io_win32_sock_read (GIOChannel *channel,
931 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
933 GIOChannelError error;
935 if (win32_channel->debug)
936 g_print ("g_io_win32_sock_read: sockfd:%d count:%d\n",
937 win32_channel->fd, count);
939 result = recv (win32_channel->fd, buf, count, 0);
941 if (win32_channel->debug)
942 g_print ("g_io_win32_sock_read: recv:%d\n", result);
944 if (result == SOCKET_ERROR)
948 switch (WSAGetLastError ())
951 error = G_IO_CHANNEL_ERROR_INVAL;
954 return G_IO_STATUS_AGAIN;
955 #ifdef WE_NEED_TO_HANDLE_WSAEINTR /* not anymore with wsock2 ? */
957 return G_IO_STATUS_INTR;
960 error = G_IO_CHANNEL_ERROR_FAILED;
963 g_set_error(err, G_IO_CHANNEL_ERROR, error, _("Socket error"));
964 return G_IO_STATUS_ERROR;
965 /* FIXME get all errors, better error messages */
969 *bytes_read = result;
971 return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
976 g_io_win32_sock_write (GIOChannel *channel,
979 gsize *bytes_written,
982 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
984 GIOChannelError error;
986 if (win32_channel->debug)
987 g_print ("g_io_win32_sock_write: sockfd:%d count:%d\n",
988 win32_channel->fd, count);
990 result = send (win32_channel->fd, buf, count, 0);
992 if (win32_channel->debug)
993 g_print ("g_io_win32_sock_write: send:%d\n", result);
995 if (result == SOCKET_ERROR)
999 switch (WSAGetLastError ())
1002 error = G_IO_CHANNEL_ERROR_INVAL;
1004 case WSAEWOULDBLOCK:
1005 return G_IO_STATUS_AGAIN;
1006 #ifdef WE_NEED_TO_HANDLE_WSAEINTR /* not anymore with wsock2 ? */
1008 return G_IO_STATUS_INTR;
1011 error = G_IO_CHANNEL_ERROR_FAILED;
1014 g_set_error(err, G_IO_CHANNEL_ERROR, error, _("Socket error"));
1015 return G_IO_STATUS_ERROR;
1016 /* FIXME get all errors, better error messages */
1020 *bytes_written = result;
1022 return G_IO_STATUS_NORMAL;
1027 g_io_win32_sock_close (GIOChannel *channel)
1029 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1031 LOCK(win32_channel->mutex);
1032 if (win32_channel->running)
1034 if (win32_channel->debug)
1035 g_print ("thread %#x: running, marking for later close\n",
1036 win32_channel->thread_id);
1037 win32_channel->running = FALSE;
1038 win32_channel->needs_close = TRUE;
1039 SetEvent(win32_channel->data_avail_noticed_event);
1041 if (win32_channel->fd != -1)
1043 if (win32_channel->debug)
1044 g_print ("thread %#x: closing socket %d\n",
1045 win32_channel->thread_id,
1048 closesocket (win32_channel->fd);
1049 win32_channel->fd = -1;
1051 UNLOCK(win32_channel->mutex);
1055 g_io_win32_sock_create_watch (GIOChannel *channel,
1056 GIOCondition condition)
1058 return g_io_win32_create_watch (channel, condition, select_thread);
1061 /* Some functions prototypes so win32 will (hopefully) still compile FIXME */
1064 g_io_channel_new_file (const gchar *filename,
1068 g_warning("Function unimplemented: %s", G_GNUC_FUNCTION);
1074 g_io_win32_set_flags (GIOChannel *channel,
1078 g_message("Function %s unimplemented.\n", G_GNUC_FUNCTION);
1080 return G_IO_STATUS_NORMAL; /* Can't return error, haven't set err */
1084 g_io_win32_get_flags (GIOChannel *channel)
1086 g_message("Function %s unimplemented.\n", G_GNUC_FUNCTION);
1091 static GIOFuncs win32_channel_msg_funcs = {
1092 g_io_win32_msg_read,
1093 g_io_win32_msg_write,
1095 g_io_win32_msg_close,
1096 g_io_win32_msg_create_watch,
1098 g_io_win32_set_flags,
1099 g_io_win32_get_flags,
1102 static GIOFuncs win32_channel_fd_funcs = {
1104 g_io_win32_fd_write,
1106 g_io_win32_fd_close,
1107 g_io_win32_fd_create_watch,
1109 g_io_win32_set_flags,
1110 g_io_win32_get_flags,
1113 static GIOFuncs win32_channel_sock_funcs = {
1114 g_io_win32_sock_read,
1115 g_io_win32_sock_write,
1117 g_io_win32_sock_close,
1118 g_io_win32_sock_create_watch,
1120 g_io_win32_set_flags,
1121 g_io_win32_get_flags,
1125 g_io_channel_win32_new_messages (guint hwnd)
1127 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1128 GIOChannel *channel = (GIOChannel *)win32_channel;
1130 g_io_channel_init (channel);
1131 g_io_channel_win32_init (win32_channel);
1132 if (win32_channel->debug)
1133 g_print ("g_io_channel_win32_new_messages: hwnd = %ud\n", hwnd);
1134 channel->funcs = &win32_channel_msg_funcs;
1135 win32_channel->type = G_IO_WIN32_WINDOWS_MESSAGES;
1136 win32_channel->hwnd = (HWND) hwnd;
1142 g_io_channel_win32_new_fd (gint fd)
1144 GIOWin32Channel *win32_channel;
1145 GIOChannel *channel;
1148 if (fstat (fd, &st) == -1)
1150 g_warning (G_STRLOC ": %d isn't a (emulated) file descriptor", fd);
1154 win32_channel = g_new (GIOWin32Channel, 1);
1155 channel = (GIOChannel *)win32_channel;
1157 g_io_channel_init (channel);
1158 g_io_channel_win32_init (win32_channel);
1159 if (win32_channel->debug)
1160 g_print ("g_io_channel_win32_new_fd: fd = %d\n", fd);
1161 channel->funcs = &win32_channel_fd_funcs;
1162 win32_channel->type = G_IO_WIN32_FILE_DESC;
1163 win32_channel->fd = fd;
1169 g_io_channel_win32_get_fd (GIOChannel *channel)
1171 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1173 return win32_channel->fd;
1177 g_io_channel_win32_new_socket (int socket)
1179 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1180 GIOChannel *channel = (GIOChannel *)win32_channel;
1182 g_io_channel_init (channel);
1183 g_io_channel_win32_init (win32_channel);
1184 if (win32_channel->debug)
1185 g_print ("g_io_channel_win32_new_socket: sockfd:%d\n", socket);
1186 channel->funcs = &win32_channel_sock_funcs;
1187 win32_channel->type = G_IO_WIN32_SOCKET;
1188 win32_channel->fd = socket;
1194 g_io_channel_unix_new (gint fd)
1198 if (fstat (fd, &st) == 0)
1199 return g_io_channel_win32_new_fd (fd);
1201 if (getsockopt (fd, SOL_SOCKET, SO_TYPE, NULL, NULL) != SO_ERROR)
1202 return g_io_channel_win32_new_socket(fd);
1204 g_warning (G_STRLOC ": %d is neither a file descriptor or a socket", fd);
1209 g_io_channel_unix_get_fd (GIOChannel *channel)
1211 return g_io_channel_win32_get_fd (channel);
1215 g_io_channel_win32_set_debug (GIOChannel *channel,
1218 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1220 win32_channel->debug = flag;
1224 g_io_channel_win32_poll (GPollFD *fds,
1230 g_return_val_if_fail (n_fds >= 0, 0);
1232 result = (*g_main_context_get_poll_func (NULL)) (fds, n_fds, timeout);
1238 g_io_channel_win32_make_pollfd (GIOChannel *channel,
1239 GIOCondition condition,
1242 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1244 if (win32_channel->data_avail_event == NULL)
1245 create_events (win32_channel);
1247 fd->fd = (gint) win32_channel->data_avail_event;
1248 fd->events = condition;
1250 if (win32_channel->thread_id == 0)
1251 if ((condition & G_IO_IN) && win32_channel->type == G_IO_WIN32_FILE_DESC)
1252 create_thread (win32_channel, condition, read_thread);
1253 else if (win32_channel->type == G_IO_WIN32_SOCKET)
1254 create_thread (win32_channel, condition, select_thread);
1257 /* Binary compatibility */
1259 g_io_channel_win32_new_stream_socket (int socket)
1261 return g_io_channel_win32_new_socket (socket);