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
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
25 * Modified by the GLib Team and others 1997-2000. See the AUTHORS
26 * file for a list of people on the GLib Team. See the ChangeLog
27 * files for a list of changes. These files are distributed with
28 * GLib at ftp://ftp.gtk.org/pub/gtk/.
31 /* Define this to get (very) verbose logging of all channels */
32 /* #define G_IO_WIN32_DEBUG */
38 #include <winsock.h> /* Not everybody has winsock2 */
45 typedef struct _GIOWin32Channel GIOWin32Channel
;
46 typedef struct _GIOWin32Watch GIOWin32Watch
;
48 #define BUFFER_SIZE 4096
51 G_IO_WIN32_WINDOWS_MESSAGES
, /* Windows messages */
52 G_IO_WIN32_FILE_DESC
, /* Unix-like file descriptors from
53 * _open() or _pipe(). Read with read().
54 * Have to create separate thread to read.
56 G_IO_WIN32_SOCKET
/* Sockets. A separate thread is blocked
57 * in select() most of the time.
59 } GIOWin32ChannelType
;
61 struct _GIOWin32Channel
{
63 gint fd
; /* Either a Unix-like file handle as provided
64 * by the Microsoft C runtime, or a SOCKET
65 * as provided by WinSock.
67 GIOWin32ChannelType type
;
71 CRITICAL_SECTION mutex
;
73 /* This is used by G_IO_WIN32_WINDOWS_MESSAGES channels */
74 HWND hwnd
; /* handle of window, or NULL */
76 /* Following fields are used by both fd and socket channels. */
77 gboolean running
; /* Is reader thread running. FALSE if
78 * EOF has been reached.
80 gboolean needs_close
; /* If the channel has been closed while
81 * the reader thread was still running.
83 guint thread_id
; /* If non-NULL has a reader thread, or has
86 HANDLE data_avail_event
;
90 /* Following fields used by fd channels for input */
92 /* Data is kept in a circular buffer. To be able to distinguish between
93 * empty and full buffer, we cannot fill it completely, but have to
94 * leave a one character gap.
96 * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
99 * Full: (wrp + 1) % BUFFER_SIZE == rdp
102 guchar
*buffer
; /* (Circular) buffer */
103 gint wrp
, rdp
; /* Buffer indices for writing and reading */
104 HANDLE space_avail_event
;
106 /* Following fields used by socket channels */
108 HANDLE data_avail_noticed_event
;
111 #define LOCK(mutex) EnterCriticalSection (&mutex)
112 #define UNLOCK(mutex) LeaveCriticalSection (&mutex)
114 struct _GIOWin32Watch
{
118 GIOCondition condition
;
123 g_io_channel_win32_init (GIOWin32Channel
*channel
)
125 #ifdef G_IO_WIN32_DEBUG
126 channel
->debug
= TRUE
;
128 if (getenv ("G_IO_WIN32_DEBUG") != NULL
)
129 channel
->debug
= TRUE
;
131 channel
->debug
= FALSE
;
133 channel
->buffer
= NULL
;
134 channel
->running
= FALSE
;
135 channel
->needs_close
= FALSE
;
136 channel
->thread_id
= 0;
137 channel
->data_avail_event
= NULL
;
138 channel
->revents
= 0;
139 channel
->space_avail_event
= NULL
;
140 channel
->data_avail_noticed_event
= NULL
;
141 channel
->watches
= NULL
;
142 InitializeCriticalSection (&channel
->mutex
);
146 create_events (GIOWin32Channel
*channel
)
148 SECURITY_ATTRIBUTES sec_attrs
;
150 sec_attrs
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
151 sec_attrs
.lpSecurityDescriptor
= NULL
;
152 sec_attrs
.bInheritHandle
= FALSE
;
154 /* The data available event is manual reset, the space available event
155 * is automatic reset.
157 if (!(channel
->data_avail_event
= CreateEvent (&sec_attrs
, TRUE
, FALSE
, NULL
))
158 || !(channel
->space_avail_event
= CreateEvent (&sec_attrs
, FALSE
, FALSE
, NULL
))
159 || !(channel
->data_avail_noticed_event
= CreateEvent (&sec_attrs
, FALSE
, FALSE
, NULL
)))
161 gchar
*msg
= g_win32_error_message (GetLastError ());
162 g_error ("Error creating event: %s", msg
);
166 static unsigned __stdcall
167 read_thread (void *parameter
)
169 GIOWin32Channel
*channel
= parameter
;
174 g_io_channel_ref ((GIOChannel
*)channel
);
177 g_print ("read_thread %#x: start fd:%d, data_avail:%#x, space_avail:%#x\n",
180 (guint
) channel
->data_avail_event
,
181 (guint
) channel
->space_avail_event
);
183 channel
->buffer
= g_malloc (BUFFER_SIZE
);
184 channel
->rdp
= channel
->wrp
= 0;
185 channel
->running
= TRUE
;
187 SetEvent (channel
->space_avail_event
);
189 while (channel
->running
)
191 LOCK (channel
->mutex
);
193 g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
194 channel
->thread_id
, channel
->rdp
, channel
->wrp
);
195 if ((channel
->wrp
+ 1) % BUFFER_SIZE
== channel
->rdp
)
199 g_print ("read_thread %#x: resetting space_avail\n",
201 ResetEvent (channel
->space_avail_event
);
203 g_print ("read_thread %#x: waiting for space\n",
205 UNLOCK (channel
->mutex
);
206 WaitForSingleObject (channel
->space_avail_event
, INFINITE
);
207 LOCK (channel
->mutex
);
209 g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
210 channel
->thread_id
, channel
->rdp
, channel
->wrp
);
213 buffer
= channel
->buffer
+ channel
->wrp
;
215 /* Always leave at least one byte unused gap to be able to
216 * distinguish between the full and empty condition...
218 nbytes
= MIN ((channel
->rdp
+ BUFFER_SIZE
- channel
->wrp
- 1) % BUFFER_SIZE
,
219 BUFFER_SIZE
- channel
->wrp
);
222 g_print ("read_thread %#x: calling read() for %d bytes\n",
223 channel
->thread_id
, nbytes
);
225 UNLOCK (channel
->mutex
);
227 nbytes
= read (channel
->fd
, buffer
, nbytes
);
229 LOCK (channel
->mutex
);
231 channel
->revents
= G_IO_IN
;
233 channel
->revents
|= G_IO_HUP
;
235 channel
->revents
|= G_IO_ERR
;
238 g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
239 channel
->thread_id
, nbytes
, channel
->rdp
, channel
->wrp
);
244 channel
->wrp
= (channel
->wrp
+ nbytes
) % BUFFER_SIZE
;
246 g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
247 channel
->thread_id
, channel
->rdp
, channel
->wrp
);
248 SetEvent (channel
->data_avail_event
);
249 UNLOCK (channel
->mutex
);
252 channel
->running
= FALSE
;
253 if (channel
->needs_close
)
256 g_print ("read_thread %#x: channel fd %d needs closing\n",
257 channel
->thread_id
, channel
->fd
);
263 g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
264 channel
->thread_id
, channel
->rdp
, channel
->wrp
);
265 SetEvent (channel
->data_avail_event
);
266 UNLOCK (channel
->mutex
);
268 g_io_channel_unref((GIOChannel
*)channel
);
270 /* No need to call _endthreadex(), the actual thread starter routine
271 * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
272 * _endthreadex() for us.
275 CloseHandle (channel
->thread_handle
);
281 create_thread (GIOWin32Channel
*channel
,
282 GIOCondition condition
,
283 unsigned (__stdcall
*thread
) (void *parameter
))
285 channel
->thread_handle
=
286 (HANDLE
) _beginthreadex (NULL
, 0, thread
, channel
, 0,
287 &channel
->thread_id
);
288 if (channel
->thread_handle
== 0)
289 g_warning (G_STRLOC
": Error creating reader thread: %s",
291 WaitForSingleObject (channel
->space_avail_event
, INFINITE
);
295 buffer_read (GIOWin32Channel
*channel
,
303 LOCK (channel
->mutex
);
305 g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
306 channel
->thread_id
, count
, channel
->rdp
, channel
->wrp
);
308 if (channel
->wrp
== channel
->rdp
)
310 UNLOCK (channel
->mutex
);
312 g_print ("waiting for data from thread %#x\n", channel
->thread_id
);
313 WaitForSingleObject (channel
->data_avail_event
, INFINITE
);
315 g_print ("done waiting for data from thread %#x\n", channel
->thread_id
);
316 LOCK (channel
->mutex
);
317 if (channel
->wrp
== channel
->rdp
&& !channel
->running
)
319 UNLOCK (channel
->mutex
);
324 if (channel
->rdp
< channel
->wrp
)
325 nbytes
= channel
->wrp
- channel
->rdp
;
327 nbytes
= BUFFER_SIZE
- channel
->rdp
;
328 UNLOCK (channel
->mutex
);
329 nbytes
= MIN (left
, nbytes
);
331 g_print ("moving %d bytes from thread %#x\n",
332 nbytes
, channel
->thread_id
);
333 memcpy (dest
, channel
->buffer
+ channel
->rdp
, nbytes
);
336 LOCK (channel
->mutex
);
337 channel
->rdp
= (channel
->rdp
+ nbytes
) % BUFFER_SIZE
;
339 g_print ("setting space_avail for thread %#x\n", channel
->thread_id
);
340 SetEvent (channel
->space_avail_event
);
342 g_print ("for thread %#x: rdp=%d, wrp=%d\n",
343 channel
->thread_id
, channel
->rdp
, channel
->wrp
);
344 if (channel
->running
&& channel
->wrp
== channel
->rdp
)
347 g_print ("resetting data_avail of thread %#x\n",
349 ResetEvent (channel
->data_avail_event
);
351 UNLOCK (channel
->mutex
);
353 /* We have no way to indicate any errors form the actual
354 * read() or recv() call in the reader thread. Should we have?
356 *error
= G_IO_ERROR_NONE
;
360 static unsigned __stdcall
361 select_thread (void *parameter
)
363 GIOWin32Channel
*channel
= parameter
;
364 fd_set read_fds
, write_fds
, except_fds
;
368 g_io_channel_ref ((GIOChannel
*)channel
);
371 g_print ("select_thread %#x: start fd:%d,\n\tdata_avail:%#x, data_avail_noticed:%#x\n",
374 (guint
) channel
->data_avail_event
,
375 (guint
) channel
->data_avail_noticed_event
);
377 channel
->rdp
= channel
->wrp
= 0;
378 channel
->running
= TRUE
;
380 SetEvent (channel
->space_avail_event
);
382 while (channel
->running
)
385 FD_ZERO (&write_fds
);
386 FD_ZERO (&except_fds
);
388 tmp
= channel
->watches
;
391 GIOWin32Watch
*watch
= (GIOWin32Watch
*)tmp
->data
;
393 if (watch
->condition
& (G_IO_IN
| G_IO_HUP
))
394 FD_SET (channel
->fd
, &read_fds
);
395 if (watch
->condition
& G_IO_OUT
)
396 FD_SET (channel
->fd
, &write_fds
);
397 if (watch
->condition
& G_IO_ERR
)
398 FD_SET (channel
->fd
, &except_fds
);
403 g_print ("select_thread %#x: calling select() for%s%s%s\n",
405 (FD_ISSET (channel
->fd
, &read_fds
) ? " IN" : ""),
406 (FD_ISSET (channel
->fd
, &write_fds
) ? " OUT" : ""),
407 (FD_ISSET (channel
->fd
, &except_fds
) ? " ERR" : ""));
409 n
= select (1, &read_fds
, &write_fds
, &except_fds
, NULL
);
411 if (n
== SOCKET_ERROR
)
414 g_print ("select_thread %#x: select returned SOCKET_ERROR\n",
420 g_print ("select_thread %#x: got%s%s%s\n",
422 (FD_ISSET (channel
->fd
, &read_fds
) ? " IN" : ""),
423 (FD_ISSET (channel
->fd
, &write_fds
) ? " OUT" : ""),
424 (FD_ISSET (channel
->fd
, &except_fds
) ? " ERR" : ""));
426 if (FD_ISSET (channel
->fd
, &read_fds
))
427 channel
->revents
|= G_IO_IN
;
428 if (FD_ISSET (channel
->fd
, &write_fds
))
429 channel
->revents
|= G_IO_OUT
;
430 if (FD_ISSET (channel
->fd
, &except_fds
))
431 channel
->revents
|= G_IO_ERR
;
434 g_print ("select_thread %#x: resetting data_avail_noticed,\n"
435 "\tsetting data_avail\n",
437 ResetEvent (channel
->data_avail_noticed_event
);
438 SetEvent (channel
->data_avail_event
);
441 g_print ("select_thread %#x: waiting for data_avail_noticed\n",
444 WaitForSingleObject (channel
->data_avail_noticed_event
, INFINITE
);
446 g_print ("select_thread %#x: got data_avail_noticed\n",
450 channel
->running
= FALSE
;
451 LOCK (channel
->mutex
);
452 if (channel
->needs_close
)
455 g_print ("select_thread %#x: channel fd %d needs closing\n",
456 channel
->thread_id
, channel
->fd
);
457 closesocket (channel
->fd
);
462 g_print ("select_thread %#x: got error, setting data_avail\n",
464 SetEvent (channel
->data_avail_event
);
465 UNLOCK (channel
->mutex
);
467 g_io_channel_unref((GIOChannel
*)channel
);
469 /* No need to call _endthreadex(), the actual thread starter routine
470 * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
471 * _endthreadex() for us.
474 CloseHandle (channel
->thread_handle
);
480 g_io_win32_prepare (GSource
*source
,
483 GIOWin32Watch
*watch
= (GIOWin32Watch
*)source
;
484 GIOWin32Channel
*channel
= (GIOWin32Channel
*)watch
->channel
;
488 if (channel
->type
== G_IO_WIN32_FILE_DESC
)
490 LOCK (channel
->mutex
);
491 if (channel
->running
&& channel
->wrp
== channel
->rdp
)
492 channel
->revents
= 0;
493 UNLOCK (channel
->mutex
);
495 else if (channel
->type
== G_IO_WIN32_SOCKET
)
497 channel
->revents
= 0;
500 g_print ("g_io_win32_prepare: thread %#x, setting data_avail_noticed\n",
502 SetEvent (channel
->data_avail_noticed_event
);
504 g_print ("g_io_win32_prepare: thread %#x, there.\n",
512 g_io_win32_check (GSource
*source
)
515 GIOWin32Watch
*watch
= (GIOWin32Watch
*)source
;
516 GIOWin32Channel
*channel
= (GIOWin32Channel
*)watch
->channel
;
519 g_print ("g_io_win32_check: for thread %#x:\n"
520 "\twatch->pollfd.events:%#x, watch->pollfd.revents:%#x, channel->revents:%#x\n",
522 watch
->pollfd
.events
, watch
->pollfd
.revents
, channel
->revents
);
524 if (channel
->type
!= G_IO_WIN32_WINDOWS_MESSAGES
)
526 watch
->pollfd
.revents
= (watch
->pollfd
.events
& channel
->revents
);
530 return (PeekMessage (&msg
, channel
->hwnd
, 0, 0, PM_NOREMOVE
));
533 if (channel
->type
== G_IO_WIN32_SOCKET
)
536 g_print ("g_io_win32_check: thread %#x, resetting data_avail\n",
538 ResetEvent (channel
->data_avail_event
);
540 g_print ("g_io_win32_check: thread %#x, there.\n",
544 return (watch
->pollfd
.revents
& watch
->condition
);
548 g_io_win32_dispatch (GSource
*source
,
549 GSourceFunc callback
,
552 GIOFunc func
= (GIOFunc
)callback
;
553 GIOWin32Watch
*watch
= (GIOWin32Watch
*)source
;
557 g_warning (G_STRLOC
": GIOWin32Watch dispatched without callback\n"
558 "You must call g_source_connect().");
562 return (*func
) (watch
->channel
,
563 watch
->pollfd
.revents
& watch
->condition
,
568 g_io_win32_destroy (GSource
*source
)
570 GIOWin32Watch
*watch
= (GIOWin32Watch
*)source
;
571 GIOWin32Channel
*channel
= (GIOWin32Channel
*)watch
->channel
;
574 g_print ("g_io_win32_destroy: channel with thread %#x\n",
577 channel
->watches
= g_slist_remove (channel
->watches
, watch
);
579 g_io_channel_unref (watch
->channel
);
582 static GSourceFuncs win32_watch_funcs
= {
590 g_io_win32_create_watch (GIOChannel
*channel
,
591 GIOCondition condition
,
592 unsigned (__stdcall
*thread
) (void *parameter
))
594 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
595 GIOWin32Watch
*watch
;
598 source
= g_source_new (&win32_watch_funcs
, sizeof (GIOWin32Watch
));
599 watch
= (GIOWin32Watch
*)source
;
601 watch
->channel
= channel
;
602 g_io_channel_ref (channel
);
604 watch
->condition
= condition
;
606 if (win32_channel
->data_avail_event
== NULL
)
607 create_events (win32_channel
);
609 watch
->pollfd
.fd
= (gint
) win32_channel
->data_avail_event
;
610 watch
->pollfd
.events
= condition
;
612 if (win32_channel
->debug
)
613 g_print ("g_io_win32_create_watch: fd:%d condition:%#x handle:%#x\n",
614 win32_channel
->fd
, condition
, watch
->pollfd
.fd
);
616 win32_channel
->watches
= g_slist_append (win32_channel
->watches
, watch
);
618 if (win32_channel
->thread_id
== 0)
619 create_thread (win32_channel
, condition
, thread
);
621 g_source_add_poll (source
, &watch
->pollfd
);
627 g_io_win32_msg_read (GIOChannel
*channel
,
632 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
633 MSG msg
; /* In case of alignment problems */
635 if (count
< sizeof (MSG
))
636 return G_IO_ERROR_INVAL
;
638 if (win32_channel
->debug
)
639 g_print ("g_io_win32_msg_read: for %#x\n",
640 win32_channel
->hwnd
);
641 if (!PeekMessage (&msg
, win32_channel
->hwnd
, 0, 0, PM_REMOVE
))
642 return G_IO_ERROR_AGAIN
;
644 memmove (buf
, &msg
, sizeof (MSG
));
645 *bytes_read
= sizeof (MSG
);
646 return G_IO_ERROR_NONE
;
650 g_io_win32_msg_write (GIOChannel
*channel
,
653 guint
*bytes_written
)
655 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
658 if (count
!= sizeof (MSG
))
659 return G_IO_ERROR_INVAL
;
661 /* In case of alignment problems */
662 memmove (&msg
, buf
, sizeof (MSG
));
663 if (!PostMessage (win32_channel
->hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
))
664 return G_IO_ERROR_UNKNOWN
;
666 *bytes_written
= sizeof (MSG
);
667 return G_IO_ERROR_NONE
;
671 g_io_win32_no_seek (GIOChannel
*channel
,
675 return G_IO_ERROR_UNKNOWN
;
679 g_io_win32_msg_close (GIOChannel
*channel
)
681 /* Nothing to be done. Or should we set hwnd to some invalid value? */
685 g_io_win32_free (GIOChannel
*channel
)
687 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
689 if (win32_channel
->debug
)
690 g_print ("thread %#x: freeing channel, fd: %d\n",
691 win32_channel
->thread_id
,
694 if (win32_channel
->data_avail_event
)
695 CloseHandle (win32_channel
->data_avail_event
);
696 if (win32_channel
->space_avail_event
)
697 CloseHandle (win32_channel
->space_avail_event
);
698 if (win32_channel
->data_avail_noticed_event
)
699 CloseHandle (win32_channel
->data_avail_noticed_event
);
700 DeleteCriticalSection (&win32_channel
->mutex
);
702 g_free (win32_channel
->buffer
);
703 g_slist_free (win32_channel
->watches
);
704 g_free (win32_channel
);
708 g_io_win32_msg_create_watch (GIOChannel
*channel
,
709 GIOCondition condition
)
711 GIOWin32Watch
*watch
;
714 source
= g_source_new (&win32_watch_funcs
, sizeof (GIOWin32Watch
));
715 watch
= (GIOWin32Watch
*)source
;
717 watch
->channel
= channel
;
718 g_io_channel_ref (channel
);
720 watch
->condition
= condition
;
722 watch
->pollfd
.fd
= G_WIN32_MSG_HANDLE
;
723 watch
->pollfd
.events
= condition
;
725 g_source_add_poll (source
, &watch
->pollfd
);
731 g_io_win32_fd_read (GIOChannel
*channel
,
736 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
740 if (win32_channel
->debug
)
741 g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
742 win32_channel
->fd
, count
);
744 if (win32_channel
->thread_id
)
746 result
= buffer_read (win32_channel
, buf
, count
, &error
);
754 *bytes_read
= result
;
755 return G_IO_ERROR_NONE
;
759 result
= read (win32_channel
->fd
, buf
, count
);
765 return G_IO_ERROR_INVAL
;
767 return G_IO_ERROR_UNKNOWN
;
771 *bytes_read
= result
;
772 return G_IO_ERROR_NONE
;
777 g_io_win32_fd_write (GIOChannel
*channel
,
780 guint
*bytes_written
)
782 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
785 result
= write (win32_channel
->fd
, buf
, count
);
786 if (win32_channel
->debug
)
787 g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
788 win32_channel
->fd
, count
, result
);
796 return G_IO_ERROR_INVAL
;
798 return G_IO_ERROR_AGAIN
;
800 return G_IO_ERROR_UNKNOWN
;
805 *bytes_written
= result
;
806 return G_IO_ERROR_NONE
;
811 g_io_win32_fd_seek (GIOChannel
*channel
,
815 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
831 g_warning (G_STRLOC
": Unknown seek type %d", (int) type
);
832 return G_IO_ERROR_UNKNOWN
;
835 result
= lseek (win32_channel
->fd
, offset
, whence
);
842 return G_IO_ERROR_INVAL
;
844 return G_IO_ERROR_UNKNOWN
;
848 return G_IO_ERROR_NONE
;
852 g_io_win32_fd_close (GIOChannel
*channel
)
854 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
856 if (win32_channel
->debug
)
857 g_print ("thread %#x: closing fd %d\n",
858 win32_channel
->thread_id
,
860 LOCK (win32_channel
->mutex
);
861 if (win32_channel
->running
)
863 if (win32_channel
->debug
)
864 g_print ("thread %#x: running, marking fd %d for later close\n",
865 win32_channel
->thread_id
, win32_channel
->fd
);
866 win32_channel
->running
= FALSE
;
867 win32_channel
->needs_close
= TRUE
;
868 SetEvent (win32_channel
->data_avail_event
);
872 if (win32_channel
->debug
)
873 g_print ("closing fd %d\n", win32_channel
->fd
);
874 close (win32_channel
->fd
);
875 if (win32_channel
->debug
)
876 g_print ("closed fd %d, setting to -1\n",
878 win32_channel
->fd
= -1;
880 UNLOCK (win32_channel
->mutex
);
884 g_io_win32_fd_create_watch (GIOChannel
*channel
,
885 GIOCondition condition
)
887 return g_io_win32_create_watch (channel
, condition
, read_thread
);
891 g_io_win32_sock_read (GIOChannel
*channel
,
896 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
900 if (win32_channel
->debug
)
901 g_print ("g_io_win32_sock_read: sockfd:%d count:%d\n",
902 win32_channel
->fd
, count
);
904 result
= recv (win32_channel
->fd
, buf
, count
, 0);
906 if (win32_channel
->debug
)
907 g_print ("g_io_win32_sock_read: recv:%d\n", result
);
909 if (result
== SOCKET_ERROR
)
912 switch (WSAGetLastError ())
915 return G_IO_ERROR_INVAL
;
918 return G_IO_ERROR_AGAIN
;
920 return G_IO_ERROR_UNKNOWN
;
925 *bytes_read
= result
;
926 return G_IO_ERROR_NONE
;
931 g_io_win32_sock_write (GIOChannel
*channel
,
934 guint
*bytes_written
)
936 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
939 if (win32_channel
->debug
)
940 g_print ("g_io_win32_sock_write: sockfd:%d count:%d\n",
941 win32_channel
->fd
, count
);
943 result
= send (win32_channel
->fd
, buf
, count
, 0);
945 if (win32_channel
->debug
)
946 g_print ("g_io_win32_sock_write: send:%d\n", result
);
948 if (result
== SOCKET_ERROR
)
951 switch (WSAGetLastError ())
954 return G_IO_ERROR_INVAL
;
957 return G_IO_ERROR_AGAIN
;
959 return G_IO_ERROR_UNKNOWN
;
964 *bytes_written
= result
;
965 return G_IO_ERROR_NONE
;
970 g_io_win32_sock_close (GIOChannel
*channel
)
972 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
974 if (win32_channel
->debug
)
975 g_print ("thread %#x: closing socket %d\n",
976 win32_channel
->thread_id
,
978 closesocket (win32_channel
->fd
);
979 win32_channel
->fd
= -1;
983 g_io_win32_sock_create_watch (GIOChannel
*channel
,
984 GIOCondition condition
)
986 return g_io_win32_create_watch (channel
, condition
, select_thread
);
989 static GIOFuncs win32_channel_msg_funcs
= {
991 g_io_win32_msg_write
,
993 g_io_win32_msg_close
,
994 g_io_win32_msg_create_watch
,
998 static GIOFuncs win32_channel_fd_funcs
= {
1000 g_io_win32_fd_write
,
1002 g_io_win32_fd_close
,
1003 g_io_win32_fd_create_watch
,
1007 static GIOFuncs win32_channel_sock_funcs
= {
1008 g_io_win32_sock_read
,
1009 g_io_win32_sock_write
,
1011 g_io_win32_sock_close
,
1012 g_io_win32_sock_create_watch
,
1017 g_io_channel_win32_new_messages (guint hwnd
)
1019 GIOWin32Channel
*win32_channel
= g_new (GIOWin32Channel
, 1);
1020 GIOChannel
*channel
= (GIOChannel
*)win32_channel
;
1022 g_io_channel_init (channel
);
1023 g_io_channel_win32_init (win32_channel
);
1024 if (win32_channel
->debug
)
1025 g_print ("g_io_channel_win32_new_messages: hwnd = %ud\n", hwnd
);
1026 channel
->funcs
= &win32_channel_msg_funcs
;
1027 win32_channel
->type
= G_IO_WIN32_WINDOWS_MESSAGES
;
1028 win32_channel
->hwnd
= (HWND
) hwnd
;
1034 g_io_channel_win32_new_fd (gint fd
)
1036 GIOWin32Channel
*win32_channel
;
1037 GIOChannel
*channel
;
1040 if (fstat (fd
, &st
) == -1)
1042 g_warning (G_STRLOC
": %d isn't a (emulated) file descriptor", fd
);
1046 win32_channel
= g_new (GIOWin32Channel
, 1);
1047 channel
= (GIOChannel
*)win32_channel
;
1049 g_io_channel_init (channel
);
1050 g_io_channel_win32_init (win32_channel
);
1051 if (win32_channel
->debug
)
1052 g_print ("g_io_channel_win32_new_fd: fd = %d\n", fd
);
1053 channel
->funcs
= &win32_channel_fd_funcs
;
1054 win32_channel
->type
= G_IO_WIN32_FILE_DESC
;
1055 win32_channel
->fd
= fd
;
1061 g_io_channel_win32_get_fd (GIOChannel
*channel
)
1063 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
1065 return win32_channel
->fd
;
1069 g_io_channel_win32_new_socket (int socket
)
1071 GIOWin32Channel
*win32_channel
= g_new (GIOWin32Channel
, 1);
1072 GIOChannel
*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_socket: sockfd:%d\n", socket
);
1078 channel
->funcs
= &win32_channel_sock_funcs
;
1079 win32_channel
->type
= G_IO_WIN32_SOCKET
;
1080 win32_channel
->fd
= socket
;
1086 g_io_channel_unix_new (gint fd
)
1090 if (fstat (fd
, &st
) == 0)
1091 return g_io_channel_win32_new_fd (fd
);
1093 if (getsockopt (fd
, SOL_SOCKET
, SO_TYPE
, NULL
, NULL
) != SO_ERROR
)
1094 return g_io_channel_win32_new_socket(fd
);
1096 g_warning (G_STRLOC
": %d is neither a file descriptor or a socket", fd
);
1101 g_io_channel_unix_get_fd (GIOChannel
*channel
)
1103 return g_io_channel_win32_get_fd (channel
);
1107 g_io_channel_win32_set_debug (GIOChannel
*channel
,
1110 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
1112 win32_channel
->debug
= flag
;
1116 g_io_channel_win32_poll (GPollFD
*fds
,
1122 g_return_val_if_fail (n_fds
>= 0, 0);
1124 result
= (*g_main_context_get_poll_func (NULL
)) (fds
, n_fds
, timeout
);
1130 g_io_channel_win32_make_pollfd (GIOChannel
*channel
,
1131 GIOCondition condition
,
1134 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
1136 if (win32_channel
->data_avail_event
== NULL
)
1137 create_events (win32_channel
);
1139 fd
->fd
= (gint
) win32_channel
->data_avail_event
;
1140 fd
->events
= condition
;
1142 if (win32_channel
->thread_id
== 0)
1143 if ((condition
& G_IO_IN
) && win32_channel
->type
== G_IO_WIN32_FILE_DESC
)
1144 create_thread (win32_channel
, condition
, read_thread
);
1145 else if (win32_channel
->type
== G_IO_WIN32_SOCKET
)
1146 create_thread (win32_channel
, condition
, select_thread
);
1149 /* Binary compatibility */
1151 g_io_channel_win32_new_stream_socket (int socket
)
1153 return g_io_channel_win32_new_socket (socket
);