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 */
46 typedef struct _GIOWin32Channel GIOWin32Channel;
47 typedef struct _GIOWin32Watch GIOWin32Watch;
49 #define BUFFER_SIZE 4096
52 G_IO_WIN32_WINDOWS_MESSAGES, /* Windows messages */
53 G_IO_WIN32_FILE_DESC, /* Unix-like file descriptors from
54 * _open() or _pipe(). Read with read().
55 * Have to create separate thread to read.
57 G_IO_WIN32_SOCKET /* Sockets. A separate thread is blocked
58 * in select() most of the time.
60 } GIOWin32ChannelType;
62 struct _GIOWin32Channel {
64 gint fd; /* Either a Unix-like file handle as provided
65 * by the Microsoft C runtime, or a SOCKET
66 * as provided by WinSock.
68 GIOWin32ChannelType type;
72 CRITICAL_SECTION mutex;
74 /* This is used by G_IO_WIN32_WINDOWS_MESSAGES channels */
75 HWND hwnd; /* handle of window, or NULL */
77 /* Following fields are used by both fd and socket channels. */
78 gboolean running; /* Is reader thread running. FALSE if
79 * EOF has been reached.
81 gboolean needs_close; /* If the channel has been closed while
82 * the reader thread was still running.
84 guint thread_id; /* If non-NULL has a reader thread, or has
87 HANDLE data_avail_event;
91 /* Following fields used by fd channels for input */
93 /* Data is kept in a circular buffer. To be able to distinguish between
94 * empty and full buffer, we cannot fill it completely, but have to
95 * leave a one character gap.
97 * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
100 * Full: (wrp + 1) % BUFFER_SIZE == rdp
103 guchar *buffer; /* (Circular) buffer */
104 gint wrp, rdp; /* Buffer indices for writing and reading */
105 HANDLE space_avail_event;
107 /* Following fields used by socket channels */
109 HANDLE data_avail_noticed_event;
112 #define LOCK(mutex) EnterCriticalSection (&mutex)
113 #define UNLOCK(mutex) LeaveCriticalSection (&mutex)
115 struct _GIOWin32Watch {
119 GIOCondition condition;
124 g_io_channel_win32_init (GIOWin32Channel *channel)
126 #ifdef G_IO_WIN32_DEBUG
127 channel->debug = TRUE;
129 if (getenv ("G_IO_WIN32_DEBUG") != NULL)
130 channel->debug = TRUE;
132 channel->debug = FALSE;
134 channel->buffer = NULL;
135 channel->running = FALSE;
136 channel->needs_close = FALSE;
137 channel->thread_id = 0;
138 channel->data_avail_event = NULL;
139 channel->revents = 0;
140 channel->space_avail_event = NULL;
141 channel->data_avail_noticed_event = NULL;
142 channel->watches = NULL;
143 InitializeCriticalSection (&channel->mutex);
147 create_events (GIOWin32Channel *channel)
149 SECURITY_ATTRIBUTES sec_attrs;
151 sec_attrs.nLength = sizeof(SECURITY_ATTRIBUTES);
152 sec_attrs.lpSecurityDescriptor = NULL;
153 sec_attrs.bInheritHandle = FALSE;
155 /* The data available event is manual reset, the space available event
156 * is automatic reset.
158 if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
159 || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL))
160 || !(channel->data_avail_noticed_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
162 gchar *msg = g_win32_error_message (GetLastError ());
163 g_error ("Error creating event: %s", msg);
167 static unsigned __stdcall
168 read_thread (void *parameter)
170 GIOWin32Channel *channel = parameter;
175 g_io_channel_ref ((GIOChannel *)channel);
178 g_print ("read_thread %#x: start fd:%d, data_avail:%#x, space_avail:%#x\n",
181 (guint) channel->data_avail_event,
182 (guint) channel->space_avail_event);
184 channel->buffer = g_malloc (BUFFER_SIZE);
185 channel->rdp = channel->wrp = 0;
186 channel->running = TRUE;
188 SetEvent (channel->space_avail_event);
190 while (channel->running)
192 LOCK (channel->mutex);
194 g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
195 channel->thread_id, channel->rdp, channel->wrp);
196 if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
200 g_print ("read_thread %#x: resetting space_avail\n",
202 ResetEvent (channel->space_avail_event);
204 g_print ("read_thread %#x: waiting for space\n",
206 UNLOCK (channel->mutex);
207 WaitForSingleObject (channel->space_avail_event, INFINITE);
208 LOCK (channel->mutex);
210 g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
211 channel->thread_id, channel->rdp, channel->wrp);
214 buffer = channel->buffer + channel->wrp;
216 /* Always leave at least one byte unused gap to be able to
217 * distinguish between the full and empty condition...
219 nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
220 BUFFER_SIZE - channel->wrp);
223 g_print ("read_thread %#x: calling read() for %d bytes\n",
224 channel->thread_id, nbytes);
226 UNLOCK (channel->mutex);
228 nbytes = read (channel->fd, buffer, nbytes);
230 LOCK (channel->mutex);
232 channel->revents = G_IO_IN;
234 channel->revents |= G_IO_HUP;
236 channel->revents |= G_IO_ERR;
239 g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
240 channel->thread_id, nbytes, channel->rdp, channel->wrp);
245 channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
247 g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
248 channel->thread_id, channel->rdp, channel->wrp);
249 SetEvent (channel->data_avail_event);
250 UNLOCK (channel->mutex);
253 channel->running = FALSE;
254 if (channel->needs_close)
257 g_print ("read_thread %#x: channel fd %d needs closing\n",
258 channel->thread_id, channel->fd);
264 g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
265 channel->thread_id, channel->rdp, channel->wrp);
266 SetEvent (channel->data_avail_event);
267 UNLOCK (channel->mutex);
269 g_io_channel_unref((GIOChannel *)channel);
271 /* No need to call _endthreadex(), the actual thread starter routine
272 * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
273 * _endthreadex() for us.
276 CloseHandle (channel->thread_handle);
282 create_thread (GIOWin32Channel *channel,
283 GIOCondition condition,
284 unsigned (__stdcall *thread) (void *parameter))
286 channel->thread_handle =
287 (HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
288 &channel->thread_id);
289 if (channel->thread_handle == 0)
290 g_warning (G_STRLOC ": Error creating reader thread: %s",
292 WaitForSingleObject (channel->space_avail_event, INFINITE);
296 buffer_read (GIOWin32Channel *channel,
304 LOCK (channel->mutex);
306 g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
307 channel->thread_id, count, channel->rdp, channel->wrp);
309 if (channel->wrp == channel->rdp)
311 UNLOCK (channel->mutex);
313 g_print ("waiting for data from thread %#x\n", channel->thread_id);
314 WaitForSingleObject (channel->data_avail_event, INFINITE);
316 g_print ("done waiting for data from thread %#x\n", channel->thread_id);
317 LOCK (channel->mutex);
318 if (channel->wrp == channel->rdp && !channel->running)
320 UNLOCK (channel->mutex);
325 if (channel->rdp < channel->wrp)
326 nbytes = channel->wrp - channel->rdp;
328 nbytes = BUFFER_SIZE - channel->rdp;
329 UNLOCK (channel->mutex);
330 nbytes = MIN (left, nbytes);
332 g_print ("moving %d bytes from thread %#x\n",
333 nbytes, channel->thread_id);
334 memcpy (dest, channel->buffer + channel->rdp, nbytes);
337 LOCK (channel->mutex);
338 channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
340 g_print ("setting space_avail for thread %#x\n", channel->thread_id);
341 SetEvent (channel->space_avail_event);
343 g_print ("for thread %#x: rdp=%d, wrp=%d\n",
344 channel->thread_id, channel->rdp, channel->wrp);
345 if (channel->running && channel->wrp == channel->rdp)
348 g_print ("resetting data_avail of thread %#x\n",
350 ResetEvent (channel->data_avail_event);
352 UNLOCK (channel->mutex);
354 /* We have no way to indicate any errors form the actual
355 * read() or recv() call in the reader thread. Should we have?
357 *error = G_IO_ERROR_NONE;
361 static unsigned __stdcall
362 select_thread (void *parameter)
364 GIOWin32Channel *channel = parameter;
365 fd_set read_fds, write_fds, except_fds;
369 g_io_channel_ref ((GIOChannel *)channel);
372 g_print ("select_thread %#x: start fd:%d,\n\tdata_avail:%#x, data_avail_noticed:%#x\n",
375 (guint) channel->data_avail_event,
376 (guint) channel->data_avail_noticed_event);
378 channel->rdp = channel->wrp = 0;
379 channel->running = TRUE;
381 SetEvent (channel->space_avail_event);
383 while (channel->running)
386 FD_ZERO (&write_fds);
387 FD_ZERO (&except_fds);
389 tmp = channel->watches;
392 GIOWin32Watch *watch = (GIOWin32Watch *)tmp->data;
394 if (watch->condition & (G_IO_IN | G_IO_HUP))
395 FD_SET (channel->fd, &read_fds);
396 if (watch->condition & G_IO_OUT)
397 FD_SET (channel->fd, &write_fds);
398 if (watch->condition & G_IO_ERR)
399 FD_SET (channel->fd, &except_fds);
404 g_print ("select_thread %#x: calling select() for%s%s%s\n",
406 (FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
407 (FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
408 (FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
410 n = select (1, &read_fds, &write_fds, &except_fds, NULL);
412 if (n == SOCKET_ERROR)
415 g_print ("select_thread %#x: select returned SOCKET_ERROR\n",
421 g_print ("select_thread %#x: got%s%s%s\n",
423 (FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
424 (FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
425 (FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
427 if (FD_ISSET (channel->fd, &read_fds))
428 channel->revents |= G_IO_IN;
429 if (FD_ISSET (channel->fd, &write_fds))
430 channel->revents |= G_IO_OUT;
431 if (FD_ISSET (channel->fd, &except_fds))
432 channel->revents |= G_IO_ERR;
435 g_print ("select_thread %#x: resetting data_avail_noticed,\n"
436 "\tsetting data_avail\n",
438 ResetEvent (channel->data_avail_noticed_event);
439 SetEvent (channel->data_avail_event);
441 LOCK (channel->mutex);
442 if (channel->needs_close)
444 UNLOCK (channel->mutex);
447 UNLOCK (channel->mutex);
450 g_print ("select_thread %#x: waiting for data_avail_noticed\n",
453 WaitForSingleObject (channel->data_avail_noticed_event, INFINITE);
455 g_print ("select_thread %#x: got data_avail_noticed\n",
459 channel->running = FALSE;
460 LOCK (channel->mutex);
461 if (channel->fd != -1)
464 g_print ("select_thread %#x: channel fd %d needs closing\n",
465 channel->thread_id, channel->fd);
466 closesocket (channel->fd);
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",
521 g_io_win32_check (GSource *source)
524 GIOWin32Watch *watch = (GIOWin32Watch *)source;
525 GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
528 g_print ("g_io_win32_check: for thread %#x:\n"
529 "\twatch->pollfd.events:%#x, watch->pollfd.revents:%#x, channel->revents:%#x\n",
531 watch->pollfd.events, watch->pollfd.revents, channel->revents);
533 if (channel->type != G_IO_WIN32_WINDOWS_MESSAGES)
535 watch->pollfd.revents = (watch->pollfd.events & channel->revents);
539 return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE));
542 if (channel->type == G_IO_WIN32_SOCKET)
545 g_print ("g_io_win32_check: thread %#x, resetting data_avail\n",
547 ResetEvent (channel->data_avail_event);
549 g_print ("g_io_win32_check: thread %#x, there.\n",
553 return (watch->pollfd.revents & watch->condition);
557 g_io_win32_dispatch (GSource *source,
558 GSourceFunc callback,
561 GIOFunc func = (GIOFunc)callback;
562 GIOWin32Watch *watch = (GIOWin32Watch *)source;
566 g_warning (G_STRLOC ": GIOWin32Watch dispatched without callback\n"
567 "You must call g_source_connect().");
571 return (*func) (watch->channel,
572 watch->pollfd.revents & watch->condition,
577 g_io_win32_destroy (GSource *source)
579 GIOWin32Watch *watch = (GIOWin32Watch *)source;
580 GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
583 g_print ("g_io_win32_destroy: channel with thread %#x\n",
586 channel->watches = g_slist_remove (channel->watches, watch);
588 SetEvent (channel->data_avail_noticed_event);
589 g_io_channel_unref (watch->channel);
592 static GSourceFuncs win32_watch_funcs = {
600 g_io_win32_create_watch (GIOChannel *channel,
601 GIOCondition condition,
602 unsigned (__stdcall *thread) (void *parameter))
604 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
605 GIOWin32Watch *watch;
608 source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
609 watch = (GIOWin32Watch *)source;
611 watch->channel = channel;
612 g_io_channel_ref (channel);
614 watch->condition = condition;
616 if (win32_channel->data_avail_event == NULL)
617 create_events (win32_channel);
619 watch->pollfd.fd = (gint) win32_channel->data_avail_event;
620 watch->pollfd.events = condition;
622 if (win32_channel->debug)
623 g_print ("g_io_win32_create_watch: fd:%d condition:%#x handle:%#x\n",
624 win32_channel->fd, condition, watch->pollfd.fd);
626 win32_channel->watches = g_slist_append (win32_channel->watches, watch);
628 if (win32_channel->thread_id == 0)
629 create_thread (win32_channel, condition, thread);
631 g_source_add_poll (source, &watch->pollfd);
637 g_io_win32_msg_read (GIOChannel *channel,
642 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
643 MSG msg; /* In case of alignment problems */
645 if (count < sizeof (MSG))
646 return G_IO_ERROR_INVAL;
648 if (win32_channel->debug)
649 g_print ("g_io_win32_msg_read: for %#x\n",
650 win32_channel->hwnd);
651 if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
652 return G_IO_ERROR_AGAIN;
654 memmove (buf, &msg, sizeof (MSG));
655 *bytes_read = sizeof (MSG);
656 return G_IO_ERROR_NONE;
660 g_io_win32_msg_write (GIOChannel *channel,
663 guint *bytes_written)
665 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
668 if (count != sizeof (MSG))
669 return G_IO_ERROR_INVAL;
671 /* In case of alignment problems */
672 memmove (&msg, buf, sizeof (MSG));
673 if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
674 return G_IO_ERROR_UNKNOWN;
676 *bytes_written = sizeof (MSG);
677 return G_IO_ERROR_NONE;
681 g_io_win32_no_seek (GIOChannel *channel,
685 return G_IO_ERROR_UNKNOWN;
689 g_io_win32_msg_close (GIOChannel *channel)
691 /* Nothing to be done. Or should we set hwnd to some invalid value? */
695 g_io_win32_free (GIOChannel *channel)
697 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
699 if (win32_channel->debug)
700 g_print ("thread %#x: freeing channel, fd: %d\n",
701 win32_channel->thread_id,
704 if (win32_channel->data_avail_event)
705 CloseHandle (win32_channel->data_avail_event);
706 if (win32_channel->space_avail_event)
707 CloseHandle (win32_channel->space_avail_event);
708 if (win32_channel->data_avail_noticed_event)
709 CloseHandle (win32_channel->data_avail_noticed_event);
710 DeleteCriticalSection (&win32_channel->mutex);
712 g_free (win32_channel->buffer);
713 g_slist_free (win32_channel->watches);
714 g_free (win32_channel);
718 g_io_win32_msg_create_watch (GIOChannel *channel,
719 GIOCondition condition)
721 GIOWin32Watch *watch;
724 source = g_source_new (&win32_watch_funcs, sizeof (GIOWin32Watch));
725 watch = (GIOWin32Watch *)source;
727 watch->channel = channel;
728 g_io_channel_ref (channel);
730 watch->condition = condition;
732 watch->pollfd.fd = G_WIN32_MSG_HANDLE;
733 watch->pollfd.events = condition;
735 g_source_add_poll (source, &watch->pollfd);
741 g_io_win32_fd_read (GIOChannel *channel,
746 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
750 if (win32_channel->debug)
751 g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
752 win32_channel->fd, count);
754 if (win32_channel->thread_id)
756 result = buffer_read (win32_channel, buf, count, &error);
764 *bytes_read = result;
765 return G_IO_ERROR_NONE;
769 result = read (win32_channel->fd, buf, count);
775 return G_IO_ERROR_INVAL;
777 return G_IO_ERROR_UNKNOWN;
781 *bytes_read = result;
782 return G_IO_ERROR_NONE;
787 g_io_win32_fd_write (GIOChannel *channel,
790 guint *bytes_written)
792 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
795 result = write (win32_channel->fd, buf, count);
796 if (win32_channel->debug)
797 g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
798 win32_channel->fd, count, result);
806 return G_IO_ERROR_INVAL;
808 return G_IO_ERROR_AGAIN;
810 return G_IO_ERROR_UNKNOWN;
815 *bytes_written = result;
816 return G_IO_ERROR_NONE;
821 g_io_win32_fd_seek (GIOChannel *channel,
825 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
841 g_warning (G_STRLOC ": Unknown seek type %d", (int) type);
842 return G_IO_ERROR_UNKNOWN;
845 result = lseek (win32_channel->fd, offset, whence);
852 return G_IO_ERROR_INVAL;
854 return G_IO_ERROR_UNKNOWN;
858 return G_IO_ERROR_NONE;
862 g_io_win32_fd_close (GIOChannel *channel)
864 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
866 if (win32_channel->debug)
867 g_print ("thread %#x: closing fd %d\n",
868 win32_channel->thread_id,
870 LOCK (win32_channel->mutex);
871 if (win32_channel->running)
873 if (win32_channel->debug)
874 g_print ("thread %#x: running, marking fd %d for later close\n",
875 win32_channel->thread_id, win32_channel->fd);
876 win32_channel->running = FALSE;
877 win32_channel->needs_close = TRUE;
878 SetEvent (win32_channel->data_avail_event);
882 if (win32_channel->debug)
883 g_print ("closing fd %d\n", win32_channel->fd);
884 close (win32_channel->fd);
885 if (win32_channel->debug)
886 g_print ("closed fd %d, setting to -1\n",
888 win32_channel->fd = -1;
890 UNLOCK (win32_channel->mutex);
894 g_io_win32_fd_create_watch (GIOChannel *channel,
895 GIOCondition condition)
897 return g_io_win32_create_watch (channel, condition, read_thread);
901 g_io_win32_sock_read (GIOChannel *channel,
906 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
910 if (win32_channel->debug)
911 g_print ("g_io_win32_sock_read: sockfd:%d count:%d\n",
912 win32_channel->fd, count);
914 result = recv (win32_channel->fd, buf, count, 0);
916 if (win32_channel->debug)
917 g_print ("g_io_win32_sock_read: recv:%d\n", result);
919 if (result == SOCKET_ERROR)
922 switch (WSAGetLastError ())
925 return G_IO_ERROR_INVAL;
928 return G_IO_ERROR_AGAIN;
930 return G_IO_ERROR_UNKNOWN;
935 *bytes_read = result;
936 return G_IO_ERROR_NONE;
941 g_io_win32_sock_write (GIOChannel *channel,
944 guint *bytes_written)
946 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
949 if (win32_channel->debug)
950 g_print ("g_io_win32_sock_write: sockfd:%d count:%d\n",
951 win32_channel->fd, count);
953 result = send (win32_channel->fd, buf, count, 0);
955 if (win32_channel->debug)
956 g_print ("g_io_win32_sock_write: send:%d\n", result);
958 if (result == SOCKET_ERROR)
961 switch (WSAGetLastError ())
964 return G_IO_ERROR_INVAL;
967 return G_IO_ERROR_AGAIN;
969 return G_IO_ERROR_UNKNOWN;
974 *bytes_written = result;
975 return G_IO_ERROR_NONE;
980 g_io_win32_sock_close (GIOChannel *channel)
982 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
984 LOCK(win32_channel->mutex);
985 if (win32_channel->running)
987 if (win32_channel->debug)
988 g_print ("thread %#x: running, marking for later close\n",
989 win32_channel->thread_id);
990 win32_channel->running = FALSE;
991 win32_channel->needs_close = TRUE;
992 SetEvent(win32_channel->data_avail_noticed_event);
994 if (win32_channel->fd != -1)
996 if (win32_channel->debug)
997 g_print ("thread %#x: closing socket %d\n",
998 win32_channel->thread_id,
1001 closesocket (win32_channel->fd);
1002 win32_channel->fd = -1;
1004 UNLOCK(win32_channel->mutex);
1008 g_io_win32_sock_create_watch (GIOChannel *channel,
1009 GIOCondition condition)
1011 return g_io_win32_create_watch (channel, condition, select_thread);
1014 static GIOFuncs win32_channel_msg_funcs = {
1015 g_io_win32_msg_read,
1016 g_io_win32_msg_write,
1018 g_io_win32_msg_close,
1019 g_io_win32_msg_create_watch,
1023 static GIOFuncs win32_channel_fd_funcs = {
1025 g_io_win32_fd_write,
1027 g_io_win32_fd_close,
1028 g_io_win32_fd_create_watch,
1032 static GIOFuncs win32_channel_sock_funcs = {
1033 g_io_win32_sock_read,
1034 g_io_win32_sock_write,
1036 g_io_win32_sock_close,
1037 g_io_win32_sock_create_watch,
1042 g_io_channel_win32_new_messages (guint hwnd)
1044 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1045 GIOChannel *channel = (GIOChannel *)win32_channel;
1047 g_io_channel_init (channel);
1048 g_io_channel_win32_init (win32_channel);
1049 if (win32_channel->debug)
1050 g_print ("g_io_channel_win32_new_messages: hwnd = %ud\n", hwnd);
1051 channel->funcs = &win32_channel_msg_funcs;
1052 win32_channel->type = G_IO_WIN32_WINDOWS_MESSAGES;
1053 win32_channel->hwnd = (HWND) hwnd;
1059 g_io_channel_win32_new_fd (gint fd)
1061 GIOWin32Channel *win32_channel;
1062 GIOChannel *channel;
1065 if (fstat (fd, &st) == -1)
1067 g_warning (G_STRLOC ": %d isn't a (emulated) file descriptor", fd);
1071 win32_channel = g_new (GIOWin32Channel, 1);
1072 channel = (GIOChannel *)win32_channel;
1074 g_io_channel_init (channel);
1075 g_io_channel_win32_init (win32_channel);
1076 if (win32_channel->debug)
1077 g_print ("g_io_channel_win32_new_fd: fd = %d\n", fd);
1078 channel->funcs = &win32_channel_fd_funcs;
1079 win32_channel->type = G_IO_WIN32_FILE_DESC;
1080 win32_channel->fd = fd;
1086 g_io_channel_win32_get_fd (GIOChannel *channel)
1088 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1090 return win32_channel->fd;
1094 g_io_channel_win32_new_socket (int socket)
1096 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1097 GIOChannel *channel = (GIOChannel *)win32_channel;
1099 g_io_channel_init (channel);
1100 g_io_channel_win32_init (win32_channel);
1101 if (win32_channel->debug)
1102 g_print ("g_io_channel_win32_new_socket: sockfd:%d\n", socket);
1103 channel->funcs = &win32_channel_sock_funcs;
1104 win32_channel->type = G_IO_WIN32_SOCKET;
1105 win32_channel->fd = socket;
1111 g_io_channel_unix_new (gint fd)
1115 if (fstat (fd, &st) == 0)
1116 return g_io_channel_win32_new_fd (fd);
1118 if (getsockopt (fd, SOL_SOCKET, SO_TYPE, NULL, NULL) != SO_ERROR)
1119 return g_io_channel_win32_new_socket(fd);
1121 g_warning (G_STRLOC ": %d is neither a file descriptor or a socket", fd);
1126 g_io_channel_unix_get_fd (GIOChannel *channel)
1128 return g_io_channel_win32_get_fd (channel);
1132 g_io_channel_win32_set_debug (GIOChannel *channel,
1135 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1137 win32_channel->debug = flag;
1141 g_io_channel_win32_poll (GPollFD *fds,
1147 g_return_val_if_fail (n_fds >= 0, 0);
1149 result = (*g_main_context_get_poll_func (NULL)) (fds, n_fds, timeout);
1155 g_io_channel_win32_make_pollfd (GIOChannel *channel,
1156 GIOCondition condition,
1159 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1161 if (win32_channel->data_avail_event == NULL)
1162 create_events (win32_channel);
1164 fd->fd = (gint) win32_channel->data_avail_event;
1165 fd->events = condition;
1167 if (win32_channel->thread_id == 0)
1168 if ((condition & G_IO_IN) && win32_channel->type == G_IO_WIN32_FILE_DESC)
1169 create_thread (win32_channel, condition, read_thread);
1170 else if (win32_channel->type == G_IO_WIN32_SOCKET)
1171 create_thread (win32_channel, condition, select_thread);
1174 /* Binary compatibility */
1176 g_io_channel_win32_new_stream_socket (int socket)
1178 return g_io_channel_win32_new_socket (socket);