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-2003 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 */
42 #include <winsock.h> /* Not everybody has winsock2 */
52 typedef struct _GIOWin32Channel GIOWin32Channel
;
53 typedef struct _GIOWin32Watch GIOWin32Watch
;
55 #define BUFFER_SIZE 4096
58 G_IO_WIN32_WINDOWS_MESSAGES
, /* Windows messages */
59 G_IO_WIN32_FILE_DESC
, /* Unix-like file descriptors from
60 * _open() or _pipe(). Read with read().
61 * Have to create separate thread to read.
63 G_IO_WIN32_SOCKET
/* Sockets. A separate thread is blocked
64 * in select() most of the time.
66 } GIOWin32ChannelType
;
68 struct _GIOWin32Channel
{
70 gint fd
; /* Either a Unix-like file handle as provided
71 * by the Microsoft C runtime, or a SOCKET
72 * as provided by WinSock.
74 GIOWin32ChannelType type
;
78 CRITICAL_SECTION mutex
;
80 /* This is used by G_IO_WIN32_WINDOWS_MESSAGES channels */
81 HWND hwnd
; /* handle of window, or NULL */
83 /* Following fields are used by both fd and socket channels. */
84 gboolean running
; /* Is reader thread running. FALSE if
85 * EOF has been reached.
87 gboolean needs_close
; /* If the channel has been closed while
88 * the reader thread was still running.
90 guint thread_id
; /* If non-NULL has a reader thread, or has
92 HANDLE data_avail_event
;
96 /* Following fields used by fd channels for input */
98 /* Data is kept in a circular buffer. To be able to distinguish between
99 * empty and full buffer, we cannot fill it completely, but have to
100 * leave a one character gap.
102 * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
105 * Full: (wrp + 1) % BUFFER_SIZE == rdp
108 guchar
*buffer
; /* (Circular) buffer */
109 gint wrp
, rdp
; /* Buffer indices for writing and reading */
110 HANDLE space_avail_event
;
112 /* Following fields used by socket channels */
114 HANDLE data_avail_noticed_event
;
115 gint reset_send
; /* socket used to send data so select_thread() can reset/re-loop */
116 gint reset_recv
; /* socket used to recv data so select_thread() can reset/re-loop */
119 #define LOCK(mutex) EnterCriticalSection (&mutex)
120 #define UNLOCK(mutex) LeaveCriticalSection (&mutex)
122 struct _GIOWin32Watch
{
126 GIOCondition condition
;
130 g_win32_print_access_mode (int flags
)
132 g_print ("%s%s%s%s%s%s%s%s%s%s",
133 ((flags
& 0x3) == _O_RDWR
? "O_RDWR" :
134 ((flags
& 0x3) == _O_RDONLY
? "O_RDONLY" :
135 ((flags
& 0x3) == _O_WRONLY
? "O_WRONLY" : "0"))),
136 (flags
& _O_APPEND
? "|O_APPEND" : ""),
137 (flags
& _O_RANDOM
? "|O_RANDOM" : ""),
138 (flags
& _O_SEQUENTIAL
? "|O_SEQUENTIAL" : ""),
139 (flags
& _O_TEMPORARY
? "|O_TEMPORARY" : ""),
140 (flags
& _O_CREAT
? "|O_CREAT" : ""),
141 (flags
& _O_TRUNC
? "|O_TRUNC" : ""),
142 (flags
& _O_EXCL
? "|O_EXCL" : ""),
143 (flags
& _O_TEXT
? "|O_TEXT" : ""),
144 (flags
& _O_BINARY
? "|O_BINARY" : ""));
148 g_win32_print_gioflags (GIOFlags flags
)
152 if (flags
& G_IO_FLAG_APPEND
)
153 bar
= "|", g_print ("APPEND");
154 if (flags
& G_IO_FLAG_NONBLOCK
)
155 g_print ("%sNONBLOCK", bar
), bar
= "|";
156 if (flags
& G_IO_FLAG_IS_READABLE
)
157 g_print ("%sREADABLE", bar
), bar
= "|";
158 if (flags
& G_IO_FLAG_IS_WRITEABLE
)
159 g_print ("%sWRITEABLE", bar
), bar
= "|";
160 if (flags
& G_IO_FLAG_IS_SEEKABLE
)
161 g_print ("%sSEEKABLE", bar
), bar
= "|";
165 g_io_win32_get_debug_flag (void)
167 #ifdef G_IO_WIN32_DEBUG
170 if (getenv ("G_IO_WIN32_DEBUG") != NULL
)
178 g_io_channel_win32_init (GIOWin32Channel
*channel
)
180 channel
->debug
= g_io_win32_get_debug_flag ();
181 channel
->buffer
= NULL
;
182 channel
->running
= FALSE
;
183 channel
->needs_close
= FALSE
;
184 channel
->thread_id
= 0;
185 channel
->data_avail_event
= NULL
;
186 channel
->revents
= 0;
187 channel
->space_avail_event
= NULL
;
188 channel
->reset_send
= INVALID_SOCKET
;
189 channel
->reset_recv
= INVALID_SOCKET
;
190 channel
->data_avail_noticed_event
= NULL
;
191 channel
->watches
= NULL
;
192 InitializeCriticalSection (&channel
->mutex
);
196 create_events (GIOWin32Channel
*channel
)
198 SECURITY_ATTRIBUTES sec_attrs
;
200 sec_attrs
.nLength
= sizeof (SECURITY_ATTRIBUTES
);
201 sec_attrs
.lpSecurityDescriptor
= NULL
;
202 sec_attrs
.bInheritHandle
= FALSE
;
204 /* The data available event is manual reset, the space available event
205 * is automatic reset.
207 if (!(channel
->data_avail_event
= CreateEvent (&sec_attrs
, TRUE
, FALSE
, NULL
))
208 || !(channel
->space_avail_event
= CreateEvent (&sec_attrs
, FALSE
, FALSE
, NULL
))
209 || !(channel
->data_avail_noticed_event
= CreateEvent (&sec_attrs
, FALSE
, FALSE
, NULL
)))
211 gchar
*emsg
= g_win32_error_message (GetLastError ());
212 g_error ("Error creating event: %s", emsg
);
217 static unsigned __stdcall
218 read_thread (void *parameter
)
220 GIOWin32Channel
*channel
= parameter
;
224 g_io_channel_ref ((GIOChannel
*)channel
);
227 g_print ("read_thread %#x: start fd:%d, data_avail:%#x space_avail:%#x\n",
230 (guint
) channel
->data_avail_event
,
231 (guint
) channel
->space_avail_event
);
233 channel
->buffer
= g_malloc (BUFFER_SIZE
);
234 channel
->rdp
= channel
->wrp
= 0;
235 channel
->running
= TRUE
;
237 SetEvent (channel
->space_avail_event
);
239 LOCK (channel
->mutex
);
240 while (channel
->running
)
243 g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
244 channel
->thread_id
, channel
->rdp
, channel
->wrp
);
245 if ((channel
->wrp
+ 1) % BUFFER_SIZE
== channel
->rdp
)
249 g_print ("read_thread %#x: resetting space_avail\n",
251 ResetEvent (channel
->space_avail_event
);
253 g_print ("read_thread %#x: waiting for space\n",
255 UNLOCK (channel
->mutex
);
256 WaitForSingleObject (channel
->space_avail_event
, INFINITE
);
257 LOCK (channel
->mutex
);
259 g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
260 channel
->thread_id
, channel
->rdp
, channel
->wrp
);
263 buffer
= channel
->buffer
+ channel
->wrp
;
265 /* Always leave at least one byte unused gap to be able to
266 * distinguish between the full and empty condition...
268 nbytes
= MIN ((channel
->rdp
+ BUFFER_SIZE
- channel
->wrp
- 1) % BUFFER_SIZE
,
269 BUFFER_SIZE
- channel
->wrp
);
272 g_print ("read_thread %#x: calling read() for %d bytes\n",
273 channel
->thread_id
, nbytes
);
275 UNLOCK (channel
->mutex
);
277 nbytes
= read (channel
->fd
, buffer
, nbytes
);
279 LOCK (channel
->mutex
);
281 channel
->revents
= G_IO_IN
;
283 channel
->revents
|= G_IO_HUP
;
285 channel
->revents
|= G_IO_ERR
;
288 g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
289 channel
->thread_id
, nbytes
, channel
->rdp
, channel
->wrp
);
294 channel
->wrp
= (channel
->wrp
+ nbytes
) % BUFFER_SIZE
;
296 g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
297 channel
->thread_id
, channel
->rdp
, channel
->wrp
);
298 SetEvent (channel
->data_avail_event
);
301 channel
->running
= FALSE
;
302 if (channel
->needs_close
)
305 g_print ("read_thread %#x: channel fd %d needs closing\n",
306 channel
->thread_id
, channel
->fd
);
312 g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
313 channel
->thread_id
, channel
->rdp
, channel
->wrp
);
314 SetEvent (channel
->data_avail_event
);
315 UNLOCK (channel
->mutex
);
317 g_io_channel_unref ((GIOChannel
*)channel
);
319 /* No need to call _endthreadex(), the actual thread starter routine
320 * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
321 * _endthreadex() for us.
328 create_thread (GIOWin32Channel
*channel
,
329 GIOCondition condition
,
330 unsigned (__stdcall
*thread
) (void *parameter
))
332 HANDLE thread_handle
;
334 thread_handle
= (HANDLE
) _beginthreadex (NULL
, 0, thread
, channel
, 0,
335 &channel
->thread_id
);
336 if (thread_handle
== 0)
337 g_warning (G_STRLOC
": Error creating reader thread: %s",
339 else if (!CloseHandle (thread_handle
))
340 g_warning (G_STRLOC
": Error closing thread handle: %s\n",
341 g_win32_error_message (GetLastError ()));
343 WaitForSingleObject (channel
->space_avail_event
, INFINITE
);
347 init_reset_sockets (GIOWin32Channel
*channel
)
349 struct sockaddr_in local
, local2
, server
;
352 channel
->reset_send
= (gint
) socket (AF_INET
, SOCK_DGRAM
, 0);
353 if (channel
->reset_send
== INVALID_SOCKET
)
355 g_warning (G_STRLOC
": Error creating reset_send socket: %s\n",
356 g_win32_error_message (WSAGetLastError ()));
359 local
.sin_family
= AF_INET
;
361 local
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
363 if (bind (channel
->reset_send
, (struct sockaddr
*)&local
, sizeof (local
)) == SOCKET_ERROR
)
365 g_warning (G_STRLOC
": Error binding to reset_send socket: %s\n",
366 g_win32_error_message (WSAGetLastError ()));
369 local2
.sin_family
= AF_INET
;
371 local2
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
373 channel
->reset_recv
= (gint
) socket (AF_INET
, SOCK_DGRAM
, 0);
374 if (channel
->reset_recv
== INVALID_SOCKET
)
376 g_warning (G_STRLOC
": Error creating reset_recv socket: %s\n",
377 g_win32_error_message (WSAGetLastError ()));
380 if (bind (channel
->reset_recv
, (struct sockaddr
*)&local2
, sizeof (local
)) == SOCKET_ERROR
)
382 g_warning (G_STRLOC
": Error binding to reset_recv socket: %s\n",
383 g_win32_error_message (WSAGetLastError ()));
386 len
= sizeof (local2
);
387 if (getsockname (channel
->reset_recv
, (struct sockaddr
*)&local2
, &len
) == SOCKET_ERROR
)
389 g_warning (G_STRLOC
": Error getsockname with reset_recv socket: %s\n",
390 g_win32_error_message (WSAGetLastError ()));
393 memset (&server
, 0, sizeof (server
));
394 server
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
395 server
.sin_family
= AF_INET
;
396 server
.sin_port
= local2
.sin_port
;
398 if (connect (channel
->reset_send
, (struct sockaddr
*)&server
, sizeof (server
)) == SOCKET_ERROR
)
400 g_warning (G_STRLOC
": connect to reset_recv socket: %s\n",
401 g_win32_error_message (WSAGetLastError ()));
407 buffer_read (GIOWin32Channel
*channel
,
416 LOCK (channel
->mutex
);
418 g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
419 channel
->thread_id
, count
, channel
->rdp
, channel
->wrp
);
421 if (channel
->wrp
== channel
->rdp
)
423 UNLOCK (channel
->mutex
);
425 g_print ("waiting for data from thread %#x\n", channel
->thread_id
);
426 WaitForSingleObject (channel
->data_avail_event
, INFINITE
);
428 g_print ("done waiting for data from thread %#x\n", channel
->thread_id
);
429 LOCK (channel
->mutex
);
430 if (channel
->wrp
== channel
->rdp
&& !channel
->running
)
433 g_print ("wrp==rdp, !running\n");
434 UNLOCK (channel
->mutex
);
436 return G_IO_STATUS_EOF
;
440 if (channel
->rdp
< channel
->wrp
)
441 nbytes
= channel
->wrp
- channel
->rdp
;
443 nbytes
= BUFFER_SIZE
- channel
->rdp
;
444 UNLOCK (channel
->mutex
);
445 nbytes
= MIN (left
, nbytes
);
447 g_print ("moving %d bytes from thread %#x\n",
448 nbytes
, channel
->thread_id
);
449 memcpy (dest
, channel
->buffer
+ channel
->rdp
, nbytes
);
452 LOCK (channel
->mutex
);
453 channel
->rdp
= (channel
->rdp
+ nbytes
) % BUFFER_SIZE
;
455 g_print ("setting space_avail for thread %#x\n", channel
->thread_id
);
456 SetEvent (channel
->space_avail_event
);
458 g_print ("for thread %#x: rdp=%d, wrp=%d\n",
459 channel
->thread_id
, channel
->rdp
, channel
->wrp
);
460 if (channel
->running
&& channel
->wrp
== channel
->rdp
)
463 g_print ("resetting data_avail of thread %#x\n",
465 ResetEvent (channel
->data_avail_event
);
467 UNLOCK (channel
->mutex
);
469 /* We have no way to indicate any errors form the actual
470 * read() or recv() call in the reader thread. Should we have?
472 *bytes_read
= count
- left
;
473 return (*bytes_read
> 0) ? G_IO_STATUS_NORMAL
: G_IO_STATUS_EOF
;
476 static unsigned __stdcall
477 select_thread (void *parameter
)
479 GIOWin32Channel
*channel
= parameter
;
480 fd_set read_fds
, write_fds
, except_fds
;
485 g_io_channel_ref ((GIOChannel
*)channel
);
488 g_print ("select_thread %#x: start fd:%d data_avail:%#x data_avail_noticed:%#x\n",
491 (guint
) channel
->data_avail_event
,
492 (guint
) channel
->data_avail_noticed_event
);
494 channel
->rdp
= channel
->wrp
= 0;
495 channel
->running
= TRUE
;
497 SetEvent (channel
->space_avail_event
);
499 while (channel
->running
)
502 FD_ZERO (&write_fds
);
503 FD_ZERO (&except_fds
);
504 FD_SET (channel
->reset_recv
, &read_fds
);
506 LOCK (channel
->mutex
);
507 tmp
= channel
->watches
;
510 GIOWin32Watch
*watch
= (GIOWin32Watch
*)tmp
->data
;
512 if (watch
->condition
& (G_IO_IN
| G_IO_HUP
))
513 FD_SET (channel
->fd
, &read_fds
);
514 if (watch
->condition
& G_IO_OUT
)
515 FD_SET (channel
->fd
, &write_fds
);
516 if (watch
->condition
& G_IO_ERR
)
517 FD_SET (channel
->fd
, &except_fds
);
521 UNLOCK (channel
->mutex
);
524 g_print ("select_thread %#x: calling select() for%s%s%s\n",
526 (FD_ISSET (channel
->fd
, &read_fds
) ? " IN" : ""),
527 (FD_ISSET (channel
->fd
, &write_fds
) ? " OUT" : ""),
528 (FD_ISSET (channel
->fd
, &except_fds
) ? " ERR" : ""));
530 n
= select (1, &read_fds
, &write_fds
, &except_fds
, NULL
);
532 LOCK (channel
->mutex
);
533 if (channel
->needs_close
)
535 UNLOCK (channel
->mutex
);
538 UNLOCK (channel
->mutex
);
540 if (n
== SOCKET_ERROR
)
543 g_print ("select_thread %#x: select returned SOCKET_ERROR\n",
548 if (FD_ISSET (channel
->reset_recv
, &read_fds
))
551 g_print ("select_thread %#x: re-looping\n",
553 recv (channel
->reset_recv
, (char *)&buffer
, (int) sizeof (buffer
), 0);
558 g_print ("select_thread %#x: got%s%s%s\n",
560 (FD_ISSET (channel
->fd
, &read_fds
) ? " IN" : ""),
561 (FD_ISSET (channel
->fd
, &write_fds
) ? " OUT" : ""),
562 (FD_ISSET (channel
->fd
, &except_fds
) ? " ERR" : ""));
564 if (FD_ISSET (channel
->fd
, &read_fds
))
565 channel
->revents
|= G_IO_IN
;
566 if (FD_ISSET (channel
->fd
, &write_fds
))
567 channel
->revents
|= G_IO_OUT
;
568 if (FD_ISSET (channel
->fd
, &except_fds
))
569 channel
->revents
|= G_IO_ERR
;
572 g_print ("select_thread %#x: resetting data_avail_noticed, setting data_avail\n",
575 LOCK (channel
->mutex
);
576 ResetEvent (channel
->data_avail_noticed_event
);
577 SetEvent (channel
->data_avail_event
);
578 if (channel
->needs_close
)
580 UNLOCK (channel
->mutex
);
583 UNLOCK (channel
->mutex
);
586 g_print ("select_thread %#x: waiting for data_avail_noticed\n",
589 WaitForSingleObject (channel
->data_avail_noticed_event
, INFINITE
);
591 g_print ("select_thread %#x: got data_avail_noticed\n",
595 LOCK (channel
->mutex
);
596 channel
->running
= FALSE
;
598 g_print ("select_thread %#x: got error, setting data_avail\n",
600 SetEvent (channel
->data_avail_event
);
601 g_io_channel_unref ((GIOChannel
*)channel
);
602 UNLOCK (channel
->mutex
);
604 /* No need to call _endthreadex(), the actual thread starter routine
605 * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
606 * _endthreadex() for us.
613 g_io_win32_prepare (GSource
*source
,
616 GIOWin32Watch
*watch
= (GIOWin32Watch
*)source
;
617 GIOCondition buffer_condition
= g_io_channel_get_buffer_condition (watch
->channel
);
618 GIOWin32Channel
*channel
= (GIOWin32Channel
*)watch
->channel
;
623 g_print ("g_io_win32_prepare: for thread %#x buffer_condition:%#x\n"
624 " watch->pollfd.events:%#x watch->pollfd.revents:%#x channel->revents:%#x\n",
625 channel
->thread_id
, buffer_condition
,
626 watch
->pollfd
.events
, watch
->pollfd
.revents
, channel
->revents
);
628 if (channel
->type
== G_IO_WIN32_FILE_DESC
)
630 LOCK (channel
->mutex
);
631 if (channel
->running
&& channel
->wrp
== channel
->rdp
)
634 g_print ("g_io_win32_prepare: for thread %#x, setting channel->revents = 0\n",
636 channel
->revents
= 0;
638 UNLOCK (channel
->mutex
);
640 else if (channel
->type
== G_IO_WIN32_SOCKET
)
642 LOCK (channel
->mutex
);
643 channel
->revents
= 0;
645 g_print ("g_io_win32_prepare: for thread %#x, setting data_avail_noticed\n",
647 SetEvent (channel
->data_avail_noticed_event
);
649 g_print ("g_io_win32_prepare: thread %#x, there.\n",
651 UNLOCK (channel
->mutex
);
654 return ((watch
->condition
& buffer_condition
) == watch
->condition
);
658 g_io_win32_check (GSource
*source
)
661 GIOWin32Watch
*watch
= (GIOWin32Watch
*)source
;
662 GIOWin32Channel
*channel
= (GIOWin32Channel
*)watch
->channel
;
663 GIOCondition buffer_condition
= g_io_channel_get_buffer_condition (watch
->channel
);
666 g_print ("g_io_win32_check: for thread %#x buffer_condition:%#x\n"
667 " watch->pollfd.events:%#x watch->pollfd.revents:%#x channel->revents:%#x\n",
668 channel
->thread_id
, buffer_condition
,
669 watch
->pollfd
.events
, watch
->pollfd
.revents
, channel
->revents
);
671 if (channel
->type
!= G_IO_WIN32_WINDOWS_MESSAGES
)
673 watch
->pollfd
.revents
= (watch
->pollfd
.events
& channel
->revents
);
677 return (PeekMessage (&msg
, channel
->hwnd
, 0, 0, PM_NOREMOVE
));
680 if (channel
->type
== G_IO_WIN32_SOCKET
)
682 LOCK (channel
->mutex
);
684 g_print ("g_io_win32_check: thread %#x, resetting data_avail\n",
686 ResetEvent (channel
->data_avail_event
);
688 g_print ("g_io_win32_check: thread %#x, there.\n",
690 UNLOCK (channel
->mutex
);
693 return ((watch
->pollfd
.revents
| buffer_condition
) & watch
->condition
);
697 g_io_win32_dispatch (GSource
*source
,
698 GSourceFunc callback
,
701 GIOFunc func
= (GIOFunc
)callback
;
702 GIOWin32Watch
*watch
= (GIOWin32Watch
*)source
;
703 GIOCondition buffer_condition
= g_io_channel_get_buffer_condition (watch
->channel
);
707 g_warning (G_STRLOC
": GIOWin32Watch dispatched without callback\n"
708 "You must call g_source_connect().");
712 return (*func
) (watch
->channel
,
713 (watch
->pollfd
.revents
| buffer_condition
) & watch
->condition
,
718 g_io_win32_finalize (GSource
*source
)
720 GIOWin32Watch
*watch
= (GIOWin32Watch
*)source
;
721 GIOWin32Channel
*channel
= (GIOWin32Channel
*)watch
->channel
;
722 char send_buffer
[] = "f";
724 LOCK (channel
->mutex
);
726 g_print ("g_io_win32_finalize: channel with thread %#x\n",
729 channel
->watches
= g_slist_remove (channel
->watches
, watch
);
731 SetEvent (channel
->data_avail_noticed_event
);
732 if (channel
->type
== G_IO_WIN32_SOCKET
)
734 /* Tell select_thread() to exit */
735 channel
->needs_close
= 1;
736 /* Wake up select_thread() from its blocking select() */
737 send (channel
->reset_send
, send_buffer
, sizeof (send_buffer
), 0);
740 g_io_channel_unref (watch
->channel
);
741 UNLOCK (channel
->mutex
);
744 GSourceFuncs g_io_watch_funcs
= {
752 g_io_win32_create_watch (GIOChannel
*channel
,
753 GIOCondition condition
,
754 unsigned (__stdcall
*thread
) (void *parameter
))
756 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
757 GIOWin32Watch
*watch
;
759 char send_buffer
[] = "c";
761 source
= g_source_new (&g_io_watch_funcs
, sizeof (GIOWin32Watch
));
762 watch
= (GIOWin32Watch
*)source
;
764 watch
->channel
= channel
;
765 g_io_channel_ref (channel
);
767 watch
->condition
= condition
;
769 if (win32_channel
->data_avail_event
== NULL
)
770 create_events (win32_channel
);
772 watch
->pollfd
.fd
= (gint
) win32_channel
->data_avail_event
;
773 watch
->pollfd
.events
= condition
;
775 if (win32_channel
->debug
)
776 g_print ("g_io_win32_create_watch: fd:%d condition:%#x handle:%#x\n",
777 win32_channel
->fd
, condition
, watch
->pollfd
.fd
);
779 LOCK (win32_channel
->mutex
);
780 win32_channel
->watches
= g_slist_append (win32_channel
->watches
, watch
);
782 if (win32_channel
->thread_id
== 0)
783 create_thread (win32_channel
, condition
, thread
);
785 send (win32_channel
->reset_send
, send_buffer
, sizeof (send_buffer
), 0);
787 g_source_add_poll (source
, &watch
->pollfd
);
788 UNLOCK (win32_channel
->mutex
);
794 g_io_win32_msg_read (GIOChannel
*channel
,
800 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
801 MSG msg
; /* In case of alignment problems */
803 if (count
< sizeof (MSG
))
805 g_set_error (err
, G_IO_CHANNEL_ERROR
, G_IO_CHANNEL_ERROR_INVAL
,
806 "Incorrect message size"); /* Informative enough error message? */
807 return G_IO_STATUS_ERROR
;
810 if (win32_channel
->debug
)
811 g_print ("g_io_win32_msg_read: for %#x\n",
812 (guint
) win32_channel
->hwnd
);
813 if (!PeekMessage (&msg
, win32_channel
->hwnd
, 0, 0, PM_REMOVE
))
814 return G_IO_STATUS_AGAIN
;
816 memmove (buf
, &msg
, sizeof (MSG
));
817 *bytes_read
= sizeof (MSG
);
819 return G_IO_STATUS_NORMAL
;
823 g_io_win32_msg_write (GIOChannel
*channel
,
826 gsize
*bytes_written
,
829 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
832 if (count
!= sizeof (MSG
))
834 g_set_error (err
, G_IO_CHANNEL_ERROR
, G_IO_CHANNEL_ERROR_INVAL
,
835 "Incorrect message size"); /* Informative enough error message? */
836 return G_IO_STATUS_ERROR
;
839 /* In case of alignment problems */
840 memmove (&msg
, buf
, sizeof (MSG
));
841 if (!PostMessage (win32_channel
->hwnd
, msg
.message
, msg
.wParam
, msg
.lParam
))
843 gchar
*emsg
= g_win32_error_message (GetLastError ());
844 g_set_error (err
, G_IO_CHANNEL_ERROR
, G_IO_CHANNEL_ERROR_FAILED
, emsg
);
846 return G_IO_STATUS_ERROR
;
849 *bytes_written
= sizeof (MSG
);
851 return G_IO_STATUS_NORMAL
;
855 g_io_win32_msg_close (GIOChannel
*channel
,
858 /* Nothing to be done. Or should we set hwnd to some invalid value? */
860 return G_IO_STATUS_NORMAL
;
864 g_io_win32_free (GIOChannel
*channel
)
866 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
868 if (win32_channel
->debug
)
869 g_print ("thread %#x: freeing channel, fd: %d\n",
870 win32_channel
->thread_id
,
873 if (win32_channel
->reset_send
&& win32_channel
->reset_send
!= INVALID_SOCKET
)
874 closesocket (win32_channel
->reset_send
);
875 if (win32_channel
->reset_recv
&& win32_channel
->reset_recv
!= INVALID_SOCKET
)
876 closesocket (win32_channel
->reset_recv
);
877 if (win32_channel
->data_avail_event
)
878 CloseHandle (win32_channel
->data_avail_event
);
879 if (win32_channel
->space_avail_event
)
880 CloseHandle (win32_channel
->space_avail_event
);
881 if (win32_channel
->data_avail_noticed_event
)
882 CloseHandle (win32_channel
->data_avail_noticed_event
);
883 DeleteCriticalSection (&win32_channel
->mutex
);
885 g_free (win32_channel
->buffer
);
886 g_slist_free (win32_channel
->watches
);
887 g_free (win32_channel
);
891 g_io_win32_msg_create_watch (GIOChannel
*channel
,
892 GIOCondition condition
)
894 GIOWin32Watch
*watch
;
897 source
= g_source_new (&g_io_watch_funcs
, sizeof (GIOWin32Watch
));
898 watch
= (GIOWin32Watch
*)source
;
900 watch
->channel
= channel
;
901 g_io_channel_ref (channel
);
903 watch
->condition
= condition
;
905 watch
->pollfd
.fd
= G_WIN32_MSG_HANDLE
;
906 watch
->pollfd
.events
= condition
;
908 g_source_add_poll (source
, &watch
->pollfd
);
914 g_io_win32_fd_read (GIOChannel
*channel
,
920 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
923 if (win32_channel
->debug
)
924 g_print ("g_io_win32_fd_read: fd:%d count:%d\n",
925 win32_channel
->fd
, count
);
927 if (win32_channel
->thread_id
)
929 return buffer_read (win32_channel
, buf
, count
, bytes_read
, err
);
932 result
= read (win32_channel
->fd
, buf
, count
);
934 if (win32_channel
->debug
)
935 g_print ("g_io_win32_fd_read: read() = %d\n", result
);
945 return G_IO_STATUS_AGAIN
;
948 g_set_error (err
, G_IO_CHANNEL_ERROR
,
949 g_io_channel_error_from_errno (errno
),
951 return G_IO_STATUS_ERROR
;
955 *bytes_read
= result
;
957 return (result
> 0) ? G_IO_STATUS_NORMAL
: G_IO_STATUS_EOF
;
961 g_io_win32_fd_write (GIOChannel
*channel
,
964 gsize
*bytes_written
,
967 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
970 result
= write (win32_channel
->fd
, buf
, count
);
971 if (win32_channel
->debug
)
972 g_print ("g_io_win32_fd_write: fd:%d count:%d = %d\n",
973 win32_channel
->fd
, count
, result
);
983 return G_IO_STATUS_AGAIN
;
986 g_set_error (err
, G_IO_CHANNEL_ERROR
,
987 g_io_channel_error_from_errno (errno
),
989 return G_IO_STATUS_ERROR
;
993 *bytes_written
= result
;
995 return G_IO_STATUS_NORMAL
;
999 g_io_win32_fd_seek (GIOChannel
*channel
,
1004 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
1021 whence
= -1; /* Keep the compiler quiet */
1022 g_assert_not_reached ();
1025 tmp_offset
= offset
;
1026 if (tmp_offset
!= offset
)
1028 g_set_error (err
, G_IO_CHANNEL_ERROR
,
1029 g_io_channel_error_from_errno (EINVAL
),
1030 g_strerror (EINVAL
));
1031 return G_IO_STATUS_ERROR
;
1034 result
= lseek (win32_channel
->fd
, tmp_offset
, whence
);
1038 g_set_error (err
, G_IO_CHANNEL_ERROR
,
1039 g_io_channel_error_from_errno (errno
),
1040 g_strerror (errno
));
1041 return G_IO_STATUS_ERROR
;
1044 return G_IO_STATUS_NORMAL
;
1048 g_io_win32_fd_close (GIOChannel
*channel
,
1051 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
1053 if (win32_channel
->debug
)
1054 g_print ("thread %#x: closing fd %d\n",
1055 win32_channel
->thread_id
,
1057 LOCK (win32_channel
->mutex
);
1058 if (win32_channel
->running
)
1060 if (win32_channel
->debug
)
1061 g_print ("thread %#x: running, marking fd %d for later close\n",
1062 win32_channel
->thread_id
, win32_channel
->fd
);
1063 win32_channel
->running
= FALSE
;
1064 win32_channel
->needs_close
= TRUE
;
1065 SetEvent (win32_channel
->data_avail_event
);
1069 if (win32_channel
->debug
)
1070 g_print ("closing fd %d\n", win32_channel
->fd
);
1071 close (win32_channel
->fd
);
1072 if (win32_channel
->debug
)
1073 g_print ("closed fd %d, setting to -1\n",
1075 win32_channel
->fd
= -1;
1077 UNLOCK (win32_channel
->mutex
);
1079 /* FIXME error detection? */
1081 return G_IO_STATUS_NORMAL
;
1085 g_io_win32_fd_create_watch (GIOChannel
*channel
,
1086 GIOCondition condition
)
1088 return g_io_win32_create_watch (channel
, condition
, read_thread
);
1092 g_io_win32_sock_read (GIOChannel
*channel
,
1098 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
1100 GIOChannelError error
= G_IO_STATUS_NORMAL
;
1101 GIOStatus internal_status
= G_IO_STATUS_NORMAL
;
1102 char send_buffer
[] = "sr";
1104 if (win32_channel
->debug
)
1105 g_print ("g_io_win32_sock_read: sockfd:%d count:%d\n",
1106 win32_channel
->fd
, count
);
1107 #ifdef WE_NEED_TO_HANDLE_WSAEINTR
1110 result
= recv (win32_channel
->fd
, buf
, count
, 0);
1112 if (win32_channel
->debug
)
1113 g_print ("g_io_win32_sock_read: recv:%d\n", result
);
1115 if (result
== SOCKET_ERROR
)
1119 switch (WSAGetLastError ())
1122 error
= G_IO_CHANNEL_ERROR_INVAL
;
1124 case WSAEWOULDBLOCK
:
1125 return G_IO_STATUS_AGAIN
;
1126 #ifdef WE_NEED_TO_HANDLE_WSAEINTR /* not anymore with wsock2 ? */
1131 error
= G_IO_CHANNEL_ERROR_FAILED
;
1134 g_set_error (err
, G_IO_CHANNEL_ERROR
, error
, "Socket read error");
1135 internal_status
= G_IO_STATUS_ERROR
;
1136 /* FIXME get all errors, better error messages */
1140 *bytes_read
= result
;
1142 internal_status
= G_IO_STATUS_EOF
;
1145 if ((internal_status
== G_IO_STATUS_EOF
) ||
1146 (internal_status
== G_IO_STATUS_ERROR
))
1148 LOCK (win32_channel
->mutex
);
1149 SetEvent (win32_channel
->data_avail_noticed_event
);
1150 win32_channel
->needs_close
= 1;
1151 send (win32_channel
->reset_send
, send_buffer
, sizeof (send_buffer
), 0);
1152 UNLOCK (win32_channel
->mutex
);
1154 return internal_status
;
1158 g_io_win32_sock_write (GIOChannel
*channel
,
1161 gsize
*bytes_written
,
1164 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
1166 GIOChannelError error
= G_IO_STATUS_NORMAL
;
1167 char send_buffer
[] = "sw";
1169 if (win32_channel
->debug
)
1170 g_print ("g_io_win32_sock_write: sockfd:%d count:%d\n",
1171 win32_channel
->fd
, count
);
1172 #ifdef WE_NEED_TO_HANDLE_WSAEINTR
1175 result
= send (win32_channel
->fd
, buf
, count
, 0);
1177 if (win32_channel
->debug
)
1178 g_print ("g_io_win32_sock_write: send:%d\n", result
);
1180 if (result
== SOCKET_ERROR
)
1184 switch (WSAGetLastError ())
1187 error
= G_IO_CHANNEL_ERROR_INVAL
;
1189 case WSAEWOULDBLOCK
:
1190 return G_IO_STATUS_AGAIN
;
1191 #ifdef WE_NEED_TO_HANDLE_WSAEINTR /* not anymore with wsock2 ? */
1196 error
= G_IO_CHANNEL_ERROR_FAILED
;
1199 g_set_error (err
, G_IO_CHANNEL_ERROR
, error
, "Socket write error");
1200 LOCK (win32_channel
->mutex
);
1201 SetEvent (win32_channel
->data_avail_noticed_event
);
1202 win32_channel
->needs_close
= 1;
1203 send (win32_channel
->reset_send
, send_buffer
, sizeof (send_buffer
), 0);
1204 UNLOCK (win32_channel
->mutex
);
1205 return G_IO_STATUS_ERROR
;
1206 /* FIXME get all errors, better error messages */
1210 *bytes_written
= result
;
1212 return G_IO_STATUS_NORMAL
;
1217 g_io_win32_sock_close (GIOChannel
*channel
,
1220 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
1222 LOCK (win32_channel
->mutex
);
1223 if (win32_channel
->running
)
1225 if (win32_channel
->debug
)
1226 g_print ("thread %#x: running, marking for later close\n",
1227 win32_channel
->thread_id
);
1228 win32_channel
->running
= FALSE
;
1229 win32_channel
->needs_close
= TRUE
;
1230 SetEvent(win32_channel
->data_avail_noticed_event
);
1232 if (win32_channel
->fd
!= -1)
1234 if (win32_channel
->debug
)
1235 g_print ("thread %#x: closing socket %d\n",
1236 win32_channel
->thread_id
,
1239 closesocket (win32_channel
->fd
);
1240 win32_channel
->fd
= -1;
1242 UNLOCK (win32_channel
->mutex
);
1244 /* FIXME error detection? */
1246 return G_IO_STATUS_NORMAL
;
1250 g_io_win32_sock_create_watch (GIOChannel
*channel
,
1251 GIOCondition condition
)
1253 return g_io_win32_create_watch (channel
, condition
, select_thread
);
1257 g_io_channel_new_file (const gchar
*filename
,
1261 int fid
, flags
, pmode
;
1262 GIOChannel
*channel
;
1264 enum { /* Cheesy hack */
1271 g_return_val_if_fail (filename
!= NULL
, NULL
);
1272 g_return_val_if_fail (mode
!= NULL
, NULL
);
1273 g_return_val_if_fail ((error
== NULL
) || (*error
== NULL
), NULL
);
1287 g_warning ("Invalid GIOFileMode %s.\n", mode
);
1296 if (mode
[2] == '\0')
1298 mode_num
|= MODE_PLUS
;
1303 g_warning ("Invalid GIOFileMode %s.\n", mode
);
1314 flags
= O_WRONLY
| O_TRUNC
| O_CREAT
;
1318 flags
= O_WRONLY
| O_APPEND
| O_CREAT
;
1321 case MODE_R
| MODE_PLUS
:
1323 pmode
= _S_IREAD
| _S_IWRITE
;
1325 case MODE_W
| MODE_PLUS
:
1326 flags
= O_RDWR
| O_TRUNC
| O_CREAT
;
1327 pmode
= _S_IREAD
| _S_IWRITE
;
1329 case MODE_A
| MODE_PLUS
:
1330 flags
= O_RDWR
| O_APPEND
| O_CREAT
;
1331 pmode
= _S_IREAD
| _S_IWRITE
;
1334 g_assert_not_reached ();
1339 /* always open 'untranslated' */
1340 fid
= g_open (filename
, flags
| _O_BINARY
, pmode
);
1342 if (g_io_win32_get_debug_flag ())
1344 g_print ("g_io_channel_win32_new_file: open(\"%s\", ", filename
);
1345 g_win32_print_access_mode (flags
|_O_BINARY
);
1346 g_print (",%#o)=%d\n", pmode
, fid
);
1351 g_set_error (error
, G_FILE_ERROR
,
1352 g_file_error_from_errno (errno
),
1353 g_strerror (errno
));
1354 return (GIOChannel
*)NULL
;
1357 channel
= g_io_channel_win32_new_fd (fid
);
1359 /* XXX: move this to g_io_channel_win32_new_fd () */
1360 channel
->close_on_unref
= TRUE
;
1361 channel
->is_seekable
= TRUE
;
1363 /* g_io_channel_win32_new_fd sets is_readable and is_writeable to
1364 * correspond to actual readability/writeability. Set to FALSE those
1365 * that mode doesn't allow
1370 channel
->is_writeable
= FALSE
;
1374 channel
->is_readable
= FALSE
;
1376 case MODE_R
| MODE_PLUS
:
1377 case MODE_W
| MODE_PLUS
:
1378 case MODE_A
| MODE_PLUS
:
1381 g_assert_not_reached ();
1389 #undef g_io_channel_new_file
1391 /* Binary compatibility version. Not for newly compiled code. */
1394 g_io_channel_new_file (const gchar
*filename
,
1398 gchar
*utf8_filename
= g_locale_to_utf8 (filename
, -1, NULL
, NULL
, error
);
1401 if (utf8_filename
== NULL
)
1404 retval
= g_io_channel_new_file_utf8 (utf8_filename
, mode
, error
);
1406 g_free (utf8_filename
);
1414 g_io_win32_set_flags (GIOChannel
*channel
,
1418 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
1420 if (win32_channel
->debug
)
1422 g_print ("g_io_win32_set_flags: ");
1423 g_win32_print_gioflags (flags
);
1427 g_warning ("g_io_win32_set_flags () not implemented.\n");
1429 return G_IO_STATUS_NORMAL
;
1433 g_io_win32_fd_get_flags_internal (GIOChannel
*channel
,
1436 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*) channel
;
1440 if (st
->st_mode
& _S_IFIFO
)
1442 channel
->is_readable
=
1443 (PeekNamedPipe ((HANDLE
) _get_osfhandle (win32_channel
->fd
), &c
, 0, &count
, NULL
, NULL
) != 0) || GetLastError () == ERROR_BROKEN_PIPE
;
1444 channel
->is_writeable
=
1445 (WriteFile ((HANDLE
) _get_osfhandle (win32_channel
->fd
), &c
, 0, &count
, NULL
) != 0);
1446 channel
->is_seekable
= FALSE
;
1448 else if (st
->st_mode
& _S_IFCHR
)
1450 /* XXX Seems there is no way to find out the readability of file
1451 * handles to device files (consoles, mostly) without doing a
1452 * blocking read. So punt, use st->st_mode.
1454 channel
->is_readable
= !!(st
->st_mode
& _S_IREAD
);
1456 channel
->is_writeable
=
1457 (WriteFile ((HANDLE
) _get_osfhandle (win32_channel
->fd
), &c
, 0, &count
, NULL
) != 0);
1459 /* XXX What about devices that actually *are* seekable? But
1460 * those would probably not be handled using the C runtime
1461 * anyway, but using Windows-specific code.
1463 channel
->is_seekable
= FALSE
;
1467 channel
->is_readable
=
1468 (ReadFile ((HANDLE
) _get_osfhandle (win32_channel
->fd
), &c
, 0, &count
, NULL
) != 0);
1469 channel
->is_writeable
=
1470 (WriteFile ((HANDLE
) _get_osfhandle (win32_channel
->fd
), &c
, 0, &count
, NULL
) != 0);
1471 channel
->is_seekable
= TRUE
;
1474 /* XXX: G_IO_FLAG_APPEND */
1475 /* XXX: G_IO_FLAG_NONBLOCK */
1481 g_io_win32_fd_get_flags (GIOChannel
*channel
)
1484 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
1486 g_return_val_if_fail (win32_channel
!= NULL
, 0);
1487 g_return_val_if_fail (win32_channel
->type
== G_IO_WIN32_FILE_DESC
, 0);
1489 if (0 == fstat (win32_channel
->fd
, &st
))
1490 return g_io_win32_fd_get_flags_internal (channel
, &st
);
1496 g_io_win32_msg_get_flags (GIOChannel
*channel
)
1502 g_io_win32_sock_get_flags (GIOChannel
*channel
)
1504 /* XXX Could do something here. */
1508 static GIOFuncs win32_channel_msg_funcs
= {
1509 g_io_win32_msg_read
,
1510 g_io_win32_msg_write
,
1512 g_io_win32_msg_close
,
1513 g_io_win32_msg_create_watch
,
1515 g_io_win32_set_flags
,
1516 g_io_win32_msg_get_flags
,
1519 static GIOFuncs win32_channel_fd_funcs
= {
1521 g_io_win32_fd_write
,
1523 g_io_win32_fd_close
,
1524 g_io_win32_fd_create_watch
,
1526 g_io_win32_set_flags
,
1527 g_io_win32_fd_get_flags
,
1530 static GIOFuncs win32_channel_sock_funcs
= {
1531 g_io_win32_sock_read
,
1532 g_io_win32_sock_write
,
1534 g_io_win32_sock_close
,
1535 g_io_win32_sock_create_watch
,
1537 g_io_win32_set_flags
,
1538 g_io_win32_sock_get_flags
,
1542 g_io_channel_win32_new_messages (guint hwnd
)
1544 GIOWin32Channel
*win32_channel
= g_new (GIOWin32Channel
, 1);
1545 GIOChannel
*channel
= (GIOChannel
*)win32_channel
;
1547 g_io_channel_init (channel
);
1548 g_io_channel_win32_init (win32_channel
);
1549 if (win32_channel
->debug
)
1550 g_print ("g_io_channel_win32_new_messages: hwnd = %ud\n", hwnd
);
1551 channel
->funcs
= &win32_channel_msg_funcs
;
1552 win32_channel
->type
= G_IO_WIN32_WINDOWS_MESSAGES
;
1553 win32_channel
->hwnd
= (HWND
) hwnd
;
1555 /* XXX: check this. */
1556 channel
->is_readable
= IsWindow (win32_channel
->hwnd
);
1557 channel
->is_writeable
= IsWindow (win32_channel
->hwnd
);
1559 channel
->is_seekable
= FALSE
;
1565 g_io_channel_win32_new_fd_internal (gint fd
,
1568 GIOWin32Channel
*win32_channel
;
1569 GIOChannel
*channel
;
1571 win32_channel
= g_new (GIOWin32Channel
, 1);
1572 channel
= (GIOChannel
*)win32_channel
;
1574 g_io_channel_init (channel
);
1575 g_io_channel_win32_init (win32_channel
);
1576 if (win32_channel
->debug
)
1577 g_print ("g_io_channel_win32_new_fd: %u\n", fd
);
1578 channel
->funcs
= &win32_channel_fd_funcs
;
1579 win32_channel
->type
= G_IO_WIN32_FILE_DESC
;
1580 win32_channel
->fd
= fd
;
1582 g_io_win32_fd_get_flags_internal (channel
, st
);
1588 g_io_channel_win32_new_fd (gint fd
)
1592 if (fstat (fd
, &st
) == -1)
1594 g_warning (G_STRLOC
": %d isn't a C library file descriptor", fd
);
1598 return g_io_channel_win32_new_fd_internal (fd
, &st
);
1602 g_io_channel_win32_get_fd (GIOChannel
*channel
)
1604 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
1606 return win32_channel
->fd
;
1610 g_io_channel_win32_new_socket (int socket
)
1612 GIOWin32Channel
*win32_channel
= g_new (GIOWin32Channel
, 1);
1613 GIOChannel
*channel
= (GIOChannel
*)win32_channel
;
1615 g_io_channel_init (channel
);
1616 g_io_channel_win32_init (win32_channel
);
1617 init_reset_sockets (win32_channel
);
1618 if (win32_channel
->debug
)
1619 g_print ("g_io_channel_win32_new_socket: sockfd:%d\n", socket
);
1620 channel
->funcs
= &win32_channel_sock_funcs
;
1621 win32_channel
->type
= G_IO_WIN32_SOCKET
;
1622 win32_channel
->fd
= socket
;
1624 /* XXX: check this */
1625 channel
->is_readable
= TRUE
;
1626 channel
->is_writeable
= TRUE
;
1628 channel
->is_seekable
= FALSE
;
1634 g_io_channel_unix_new (gint fd
)
1636 gboolean is_fd
, is_socket
;
1640 is_fd
= (fstat (fd
, &st
) == 0);
1642 optlen
= sizeof (optval
);
1643 is_socket
= (getsockopt (fd
, SOL_SOCKET
, SO_TYPE
, (char *) &optval
, &optlen
) != SOCKET_ERROR
);
1645 if (is_fd
&& is_socket
)
1646 g_warning (G_STRLOC
": %d is both a file descriptor and a socket, file descriptor interpretation assumed.", fd
);
1649 return g_io_channel_win32_new_fd_internal (fd
, &st
);
1652 return g_io_channel_win32_new_socket(fd
);
1654 g_warning (G_STRLOC
": %d is neither a file descriptor or a socket", fd
);
1660 g_io_channel_unix_get_fd (GIOChannel
*channel
)
1662 return g_io_channel_win32_get_fd (channel
);
1666 g_io_channel_win32_set_debug (GIOChannel
*channel
,
1669 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
1671 win32_channel
->debug
= flag
;
1675 g_io_channel_win32_poll (GPollFD
*fds
,
1681 g_return_val_if_fail (n_fds
>= 0, 0);
1683 result
= (*g_main_context_get_poll_func (NULL
)) (fds
, n_fds
, timeout
);
1689 g_io_channel_win32_make_pollfd (GIOChannel
*channel
,
1690 GIOCondition condition
,
1693 GIOWin32Channel
*win32_channel
= (GIOWin32Channel
*)channel
;
1695 if (win32_channel
->data_avail_event
== NULL
)
1696 create_events (win32_channel
);
1698 fd
->fd
= (gint
) win32_channel
->data_avail_event
;
1699 fd
->events
= condition
;
1701 if (win32_channel
->thread_id
== 0)
1703 if ((condition
& G_IO_IN
) && win32_channel
->type
== G_IO_WIN32_FILE_DESC
)
1704 create_thread (win32_channel
, condition
, read_thread
);
1705 else if (win32_channel
->type
== G_IO_WIN32_SOCKET
)
1706 create_thread (win32_channel
, condition
, select_thread
);
1710 /* Binary compatibility */
1712 g_io_channel_win32_new_stream_socket (int socket
)
1714 return g_io_channel_win32_new_socket (socket
);