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/.
50 typedef struct _GIOWin32Channel GIOWin32Channel;
51 typedef struct _GIOWin32Watch GIOWin32Watch;
53 #define BUFFER_SIZE 4096
56 G_IO_WIN32_WINDOWS_MESSAGES, /* Windows messages */
57 G_IO_WIN32_FILE_DESC, /* Unix-like file descriptors from
58 * _open() or _pipe(). Read with read().
59 * Have to create separate thread to read.
61 G_IO_WIN32_SOCKET /* Sockets. No separate thread */
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 /* This is used by G_IO_WIN32_WINDOWS_MESSAGES channels */
75 HWND hwnd; /* handle of window, or NULL */
77 /* Following fields are used by fd channels. */
78 CRITICAL_SECTION mutex;
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
88 HANDLE data_avail_event;
92 /* Following fields used by fd channels for input */
94 /* Data is kept in a circular buffer. To be able to distinguish between
95 * empty and full buffer, we cannot fill it completely, but have to
96 * leave a one character gap.
98 * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
101 * Full: (wrp + 1) % BUFFER_SIZE == rdp
104 guchar *buffer; /* (Circular) buffer */
105 gint wrp, rdp; /* Buffer indices for writing and reading */
106 HANDLE space_avail_event;
108 /* Following fields used by socket channels */
112 gboolean write_would_have_blocked;
115 #define LOCK(mutex) EnterCriticalSection (&mutex)
116 #define UNLOCK(mutex) LeaveCriticalSection (&mutex)
118 struct _GIOWin32Watch {
122 GIOCondition condition;
126 g_win32_print_access_mode (int flags)
128 g_print ("%s%s%s%s%s%s%s%s%s%s",
129 ((flags & 0x3) == _O_RDWR ? "O_RDWR" :
130 ((flags & 0x3) == _O_RDONLY ? "O_RDONLY" :
131 ((flags & 0x3) == _O_WRONLY ? "O_WRONLY" : "0"))),
132 (flags & _O_APPEND ? "|O_APPEND" : ""),
133 (flags & _O_RANDOM ? "|O_RANDOM" : ""),
134 (flags & _O_SEQUENTIAL ? "|O_SEQUENTIAL" : ""),
135 (flags & _O_TEMPORARY ? "|O_TEMPORARY" : ""),
136 (flags & _O_CREAT ? "|O_CREAT" : ""),
137 (flags & _O_TRUNC ? "|O_TRUNC" : ""),
138 (flags & _O_EXCL ? "|O_EXCL" : ""),
139 (flags & _O_TEXT ? "|O_TEXT" : ""),
140 (flags & _O_BINARY ? "|O_BINARY" : ""));
144 g_win32_print_gioflags (GIOFlags flags)
148 if (flags & G_IO_FLAG_APPEND)
149 bar = "|", g_print ("APPEND");
150 if (flags & G_IO_FLAG_NONBLOCK)
151 g_print ("%sNONBLOCK", bar), bar = "|";
152 if (flags & G_IO_FLAG_IS_READABLE)
153 g_print ("%sREADABLE", bar), bar = "|";
154 if (flags & G_IO_FLAG_IS_WRITEABLE)
155 g_print ("%sWRITEABLE", bar), bar = "|";
156 if (flags & G_IO_FLAG_IS_SEEKABLE)
157 g_print ("%sSEEKABLE", bar), bar = "|";
161 event_mask_to_string (int mask)
164 int checked_bits = 0;
170 #define BIT(n) checked_bits |= FD_##n; if (mask & FD_##n) bufp += sprintf (bufp, "%s" #n, (bufp>buf ? "|" : ""))
180 BIT (ROUTING_INTERFACE_CHANGE);
181 BIT (ADDRESS_LIST_CHANGE);
185 if ((mask & ~checked_bits) != 0)
186 bufp += sprintf (bufp, "|%#x", mask & ~checked_bits);
188 return g_quark_to_string (g_quark_from_string (buf));
192 condition_to_string (GIOCondition condition)
195 int checked_bits = 0;
201 #define BIT(n) checked_bits |= G_IO_##n; if (condition & G_IO_##n) bufp += sprintf (bufp, "%s" #n, (bufp>buf ? "|" : ""))
212 if ((condition & ~checked_bits) != 0)
213 bufp += sprintf (bufp, "|%#x", condition & ~checked_bits);
215 return g_quark_to_string (g_quark_from_string (buf));
219 g_io_win32_get_debug_flag (void)
221 return (getenv ("G_IO_WIN32_DEBUG") != NULL);
225 winsock_error_message (int number)
227 static char unk[100];
231 return "Interrupted function call";
233 return "Permission denied";
235 return "Bad address";
237 return "Invalid argument";
239 return "Too many open sockets";
241 return "Resource temporarily unavailable";
243 return "Operation now in progress";
245 return "Operation already in progress";
247 return "Socket operation on nonsocket";
248 case WSAEDESTADDRREQ:
249 return "Destination address required";
251 return "Message too long";
253 return "Protocol wrong type for socket";
255 return "Bad protocol option";
256 case WSAEPROTONOSUPPORT:
257 return "Protocol not supported";
258 case WSAESOCKTNOSUPPORT:
259 return "Socket type not supported";
261 return "Operation not supported on transport endpoint";
262 case WSAEPFNOSUPPORT:
263 return "Protocol family not supported";
264 case WSAEAFNOSUPPORT:
265 return "Address family not supported by protocol family";
267 return "Address already in use";
268 case WSAEADDRNOTAVAIL:
269 return "Address not available";
271 return "Network interface is not configured";
273 return "Network is unreachable";
275 return "Network dropped connection on reset";
276 case WSAECONNABORTED:
277 return "Software caused connection abort";
279 return "Connection reset by peer";
281 return "No buffer space available";
283 return "Socket is already connected";
285 return "Socket is not connected";
287 return "Can't send after socket shutdown";
289 return "Connection timed out";
290 case WSAECONNREFUSED:
291 return "Connection refused";
293 return "Host is down";
294 case WSAEHOSTUNREACH:
295 return "Host is unreachable";
297 return "Too many processes";
299 return "Network subsystem is unavailable";
300 case WSAVERNOTSUPPORTED:
301 return "Winsock.dll version out of range";
302 case WSANOTINITIALISED:
303 return "Successful WSAStartup not yet performed";
305 return "Graceful shutdown in progress";
306 case WSATYPE_NOT_FOUND:
307 return "Class type not found";
308 case WSAHOST_NOT_FOUND:
309 return "Host not found";
311 return "Nonauthoritative host not found";
313 return "This is a nonrecoverable error";
315 return "Valid name, no data record of requested type";
316 case WSA_INVALID_HANDLE:
317 return "Specified event object handle is invalid";
318 case WSA_INVALID_PARAMETER:
319 return "One or more parameters are invalid";
320 case WSA_IO_INCOMPLETE:
321 return "Overlapped I/O event object not in signaled state";
322 case WSA_NOT_ENOUGH_MEMORY:
323 return "Insufficient memory available";
324 case WSA_OPERATION_ABORTED:
325 return "Overlapped operation aborted";
326 case WSAEINVALIDPROCTABLE:
327 return "Invalid procedure table from service provider";
328 case WSAEINVALIDPROVIDER:
329 return "Invalid service provider version number";
330 case WSAEPROVIDERFAILEDINIT:
331 return "Unable to initialize a service provider";
332 case WSASYSCALLFAILURE:
333 return "System call failure";
335 sprintf (unk, "Unknown WinSock error %d", number);
341 g_io_channel_win32_init (GIOWin32Channel *channel)
343 channel->debug = g_io_win32_get_debug_flag ();
344 channel->buffer = NULL;
345 channel->running = FALSE;
346 channel->needs_close = FALSE;
347 channel->thread_id = 0;
348 channel->data_avail_event = NULL;
349 channel->revents = 0;
350 channel->space_avail_event = NULL;
351 channel->event_mask = 0;
352 channel->last_events = 0;
354 channel->write_would_have_blocked = FALSE;
355 InitializeCriticalSection (&channel->mutex);
359 create_events (GIOWin32Channel *channel)
361 SECURITY_ATTRIBUTES sec_attrs;
363 sec_attrs.nLength = sizeof (SECURITY_ATTRIBUTES);
364 sec_attrs.lpSecurityDescriptor = NULL;
365 sec_attrs.bInheritHandle = FALSE;
367 /* The data available event is manual reset, the space available event
368 * is automatic reset.
370 if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
371 || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
373 gchar *emsg = g_win32_error_message (GetLastError ());
374 g_error ("Error creating event: %s", emsg);
379 static unsigned __stdcall
380 read_thread (void *parameter)
382 GIOWin32Channel *channel = parameter;
386 g_io_channel_ref ((GIOChannel *)channel);
389 g_print ("read_thread %#x: start fd=%d, data_avail=%#x space_avail=%#x\n",
392 (guint) channel->data_avail_event,
393 (guint) channel->space_avail_event);
395 channel->buffer = g_malloc (BUFFER_SIZE);
396 channel->rdp = channel->wrp = 0;
397 channel->running = TRUE;
399 SetEvent (channel->space_avail_event);
401 LOCK (channel->mutex);
402 while (channel->running)
405 g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
406 channel->thread_id, channel->rdp, channel->wrp);
407 if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
411 g_print ("read_thread %#x: resetting space_avail\n",
413 ResetEvent (channel->space_avail_event);
415 g_print ("read_thread %#x: waiting for space\n",
417 UNLOCK (channel->mutex);
418 WaitForSingleObject (channel->space_avail_event, INFINITE);
419 LOCK (channel->mutex);
421 g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
422 channel->thread_id, channel->rdp, channel->wrp);
425 buffer = channel->buffer + channel->wrp;
427 /* Always leave at least one byte unused gap to be able to
428 * distinguish between the full and empty condition...
430 nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
431 BUFFER_SIZE - channel->wrp);
434 g_print ("read_thread %#x: calling read() for %d bytes\n",
435 channel->thread_id, nbytes);
437 UNLOCK (channel->mutex);
439 nbytes = read (channel->fd, buffer, nbytes);
441 LOCK (channel->mutex);
443 channel->revents = G_IO_IN;
445 channel->revents |= G_IO_HUP;
447 channel->revents |= G_IO_ERR;
450 g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
451 channel->thread_id, nbytes, channel->rdp, channel->wrp);
456 channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
458 g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
459 channel->thread_id, channel->rdp, channel->wrp);
460 SetEvent (channel->data_avail_event);
463 channel->running = FALSE;
464 if (channel->needs_close)
467 g_print ("read_thread %#x: channel fd %d needs closing\n",
468 channel->thread_id, channel->fd);
474 g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
475 channel->thread_id, channel->rdp, channel->wrp);
476 SetEvent (channel->data_avail_event);
477 UNLOCK (channel->mutex);
479 g_io_channel_unref ((GIOChannel *)channel);
481 /* No need to call _endthreadex(), the actual thread starter routine
482 * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
483 * _endthreadex() for us.
490 create_thread (GIOWin32Channel *channel,
491 GIOCondition condition,
492 unsigned (__stdcall *thread) (void *parameter))
494 HANDLE thread_handle;
496 thread_handle = (HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
497 &channel->thread_id);
498 if (thread_handle == 0)
499 g_warning (G_STRLOC ": Error creating reader thread: %s",
501 else if (!CloseHandle (thread_handle))
502 g_warning (G_STRLOC ": Error closing thread handle: %s\n",
503 g_win32_error_message (GetLastError ()));
505 WaitForSingleObject (channel->space_avail_event, INFINITE);
509 buffer_read (GIOWin32Channel *channel,
518 LOCK (channel->mutex);
520 g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
521 channel->thread_id, count, channel->rdp, channel->wrp);
523 if (channel->wrp == channel->rdp)
525 UNLOCK (channel->mutex);
527 g_print ("waiting for data from thread %#x\n", channel->thread_id);
528 WaitForSingleObject (channel->data_avail_event, INFINITE);
530 g_print ("done waiting for data from thread %#x\n", channel->thread_id);
531 LOCK (channel->mutex);
532 if (channel->wrp == channel->rdp && !channel->running)
535 g_print ("wrp==rdp, !running\n");
536 UNLOCK (channel->mutex);
538 return G_IO_STATUS_EOF;
542 if (channel->rdp < channel->wrp)
543 nbytes = channel->wrp - channel->rdp;
545 nbytes = BUFFER_SIZE - channel->rdp;
546 UNLOCK (channel->mutex);
547 nbytes = MIN (left, nbytes);
549 g_print ("moving %d bytes from thread %#x\n",
550 nbytes, channel->thread_id);
551 memcpy (dest, channel->buffer + channel->rdp, nbytes);
554 LOCK (channel->mutex);
555 channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
557 g_print ("setting space_avail for thread %#x\n", channel->thread_id);
558 SetEvent (channel->space_avail_event);
560 g_print ("for thread %#x: rdp=%d, wrp=%d\n",
561 channel->thread_id, channel->rdp, channel->wrp);
562 if (channel->running && channel->wrp == channel->rdp)
565 g_print ("resetting data_avail of thread %#x\n",
567 ResetEvent (channel->data_avail_event);
569 UNLOCK (channel->mutex);
571 /* We have no way to indicate any errors form the actual
572 * read() or recv() call in the reader thread. Should we have?
574 *bytes_read = count - left;
575 return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
579 g_io_win32_prepare (GSource *source,
582 GIOWin32Watch *watch = (GIOWin32Watch *)source;
583 GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
584 GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
589 switch (channel->type)
591 case G_IO_WIN32_WINDOWS_MESSAGES:
594 case G_IO_WIN32_FILE_DESC:
596 g_print ("g_io_win32_prepare: for thread %#x buffer_condition:{%s}\n"
597 " watch->pollfd.events:{%s} watch->pollfd.revents:{%s} channel->revents:{%s}\n",
598 channel->thread_id, condition_to_string (buffer_condition),
599 condition_to_string (watch->pollfd.events),
600 condition_to_string (watch->pollfd.revents),
601 condition_to_string (channel->revents));
603 LOCK (channel->mutex);
604 if (channel->running && channel->wrp == channel->rdp)
607 g_print ("g_io_win32_prepare: for thread %#x, setting channel->revents = 0\n",
609 channel->revents = 0;
611 UNLOCK (channel->mutex);
614 case G_IO_WIN32_SOCKET:
616 if (watch->condition & G_IO_IN)
617 event_mask |= (FD_READ | FD_ACCEPT);
618 if (watch->condition & G_IO_OUT)
619 event_mask |= (FD_WRITE | FD_CONNECT);
620 if (watch->condition & G_IO_HUP)
621 event_mask |= FD_CLOSE;
623 if (channel->event_mask != event_mask /* || channel->event != watch->pollfd.fd*/)
626 g_print ("g_io_win32_prepare: WSAEventSelect(%d, %#x, {%s}\n",
627 channel->fd, watch->pollfd.fd,
628 event_mask_to_string (event_mask));
629 if (WSAEventSelect (channel->fd, (HANDLE) watch->pollfd.fd,
630 event_mask) == SOCKET_ERROR)
632 channel->event_mask = event_mask;
634 channel->event = watch->pollfd.fd;
636 channel->last_events = 0;
641 g_assert_not_reached ();
644 return ((watch->condition & buffer_condition) == watch->condition);
648 g_io_win32_check (GSource *source)
651 GIOWin32Watch *watch = (GIOWin32Watch *)source;
652 GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
653 GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
654 WSANETWORKEVENTS events;
656 switch (channel->type)
658 case G_IO_WIN32_WINDOWS_MESSAGES:
659 return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE));
661 case G_IO_WIN32_FILE_DESC:
663 g_print ("g_io_win32_check: for thread %#x buffer_condition=%s\n"
664 " watch->pollfd.events={%s} watch->pollfd.revents={%s} channel->revents={%s}\n",
665 channel->thread_id, condition_to_string (buffer_condition),
666 condition_to_string (watch->pollfd.events),
667 condition_to_string (watch->pollfd.revents),
668 condition_to_string (channel->revents));
670 watch->pollfd.revents = (watch->pollfd.events & channel->revents);
672 return ((watch->pollfd.revents | buffer_condition) & watch->condition);
674 case G_IO_WIN32_SOCKET:
675 if (channel->last_events & FD_WRITE)
678 g_print ("g_io_win32_check: sock=%d event=%#x last_events has FD_WRITE\n",
679 channel->fd, watch->pollfd.fd);
683 WSAEnumNetworkEvents (channel->fd, 0, &events);
686 g_print ("g_io_win32_check: WSAEnumNetworkEvents (%d, %#x) revents={%s} condition={%s} events={%s}\n",
687 channel->fd, watch->pollfd.fd,
688 condition_to_string (watch->pollfd.revents),
689 condition_to_string (watch->condition),
690 event_mask_to_string (events.lNetworkEvents));
692 if (watch->pollfd.revents != 0 &&
693 events.lNetworkEvents == 0 &&
694 !(channel->event_mask & FD_WRITE))
696 channel->event_mask = 0;
698 g_print ("g_io_win32_check: WSAEventSelect(%d, %#x, {})\n",
699 channel->fd, watch->pollfd.fd);
700 WSAEventSelect (channel->fd, (HANDLE) watch->pollfd.fd, 0);
702 g_print ("g_io_win32_check: ResetEvent(%#x)\n",
704 ResetEvent ((HANDLE) watch->pollfd.fd);
706 channel->last_events = events.lNetworkEvents;
708 watch->pollfd.revents = 0;
709 if (channel->last_events & (FD_READ | FD_ACCEPT))
710 watch->pollfd.revents |= G_IO_IN;
711 if (channel->last_events & (FD_WRITE | FD_CONNECT))
712 watch->pollfd.revents |= G_IO_OUT;
713 if (watch->pollfd.revents == 0 && (channel->last_events & (FD_CLOSE)))
714 watch->pollfd.revents |= G_IO_HUP;
716 if (!channel->write_would_have_blocked && (channel->event_mask & FD_WRITE))
717 watch->pollfd.revents |= G_IO_OUT; /* This sucks but... */
719 return ((watch->pollfd.revents | buffer_condition) & watch->condition);
722 g_assert_not_reached ();
728 g_io_win32_dispatch (GSource *source,
729 GSourceFunc callback,
732 GIOFunc func = (GIOFunc)callback;
733 GIOWin32Watch *watch = (GIOWin32Watch *)source;
734 GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
735 GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
739 g_warning (G_STRLOC ": GIOWin32Watch dispatched without callback\n"
740 "You must call g_source_connect().");
745 g_print ("g_io_win32_dispatch: pollfd.revents=%s condition=%s result=%s\n",
746 condition_to_string (watch->pollfd.revents),
747 condition_to_string (watch->condition),
748 condition_to_string ((watch->pollfd.revents | buffer_condition) & watch->condition));
750 return (*func) (watch->channel,
751 (watch->pollfd.revents | buffer_condition) & watch->condition,
756 g_io_win32_finalize (GSource *source)
758 GIOWin32Watch *watch = (GIOWin32Watch *)source;
759 GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
761 switch (channel->type)
763 case G_IO_WIN32_WINDOWS_MESSAGES:
766 case G_IO_WIN32_FILE_DESC:
767 LOCK (channel->mutex);
769 g_print ("g_io_win32_finalize: channel with thread %#x\n",
771 UNLOCK (channel->mutex);
774 case G_IO_WIN32_SOCKET:
776 g_print ("g_io_win32_finalize: channel is for sock=%d\n", channel->fd);
778 CloseHandle ((HANDLE) watch->pollfd.fd);
780 channel->event_mask = 0;
785 g_assert_not_reached ();
788 g_io_channel_unref (watch->channel);
791 GSourceFuncs g_io_watch_funcs = {
799 g_io_win32_msg_read (GIOChannel *channel,
805 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
806 MSG msg; /* In case of alignment problems */
808 if (count < sizeof (MSG))
810 g_set_error (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
811 "Incorrect message size"); /* Informative enough error message? */
812 return G_IO_STATUS_ERROR;
815 if (win32_channel->debug)
816 g_print ("g_io_win32_msg_read: for %#x\n",
817 (guint) win32_channel->hwnd);
818 if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
819 return G_IO_STATUS_AGAIN;
821 memmove (buf, &msg, sizeof (MSG));
822 *bytes_read = sizeof (MSG);
824 return G_IO_STATUS_NORMAL;
828 g_io_win32_msg_write (GIOChannel *channel,
831 gsize *bytes_written,
834 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
837 if (count != sizeof (MSG))
839 g_set_error (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
840 "Incorrect message size"); /* Informative enough error message? */
841 return G_IO_STATUS_ERROR;
844 /* In case of alignment problems */
845 memmove (&msg, buf, sizeof (MSG));
846 if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
848 gchar *emsg = g_win32_error_message (GetLastError ());
849 g_set_error (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED, emsg);
851 return G_IO_STATUS_ERROR;
854 *bytes_written = sizeof (MSG);
856 return G_IO_STATUS_NORMAL;
860 g_io_win32_msg_close (GIOChannel *channel,
863 /* Nothing to be done. Or should we set hwnd to some invalid value? */
865 return G_IO_STATUS_NORMAL;
869 g_io_win32_free (GIOChannel *channel)
871 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
873 if (win32_channel->debug)
874 g_print ("g_io_win32_free channel fd=%d\n", win32_channel->fd);
876 if (win32_channel->data_avail_event)
877 CloseHandle (win32_channel->data_avail_event);
878 if (win32_channel->space_avail_event)
879 CloseHandle (win32_channel->space_avail_event);
880 if (win32_channel->type == G_IO_WIN32_SOCKET)
881 WSAEventSelect (win32_channel->fd, NULL, 0);
882 DeleteCriticalSection (&win32_channel->mutex);
884 g_free (win32_channel->buffer);
885 g_free (win32_channel);
889 g_io_win32_msg_create_watch (GIOChannel *channel,
890 GIOCondition condition)
892 GIOWin32Watch *watch;
895 source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
896 watch = (GIOWin32Watch *)source;
898 watch->channel = channel;
899 g_io_channel_ref (channel);
901 watch->condition = condition;
903 watch->pollfd.fd = G_WIN32_MSG_HANDLE;
904 watch->pollfd.events = condition;
906 g_source_add_poll (source, &watch->pollfd);
912 g_io_win32_fd_read (GIOChannel *channel,
918 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
921 if (win32_channel->debug)
922 g_print ("g_io_win32_fd_read: fd=%d count=%d\n",
923 win32_channel->fd, count);
925 if (win32_channel->thread_id)
927 return buffer_read (win32_channel, buf, count, bytes_read, err);
930 result = read (win32_channel->fd, buf, count);
932 if (win32_channel->debug)
933 g_print ("g_io_win32_fd_read: read() => %d\n", result);
943 return G_IO_STATUS_AGAIN;
946 g_set_error (err, G_IO_CHANNEL_ERROR,
947 g_io_channel_error_from_errno (errno),
949 return G_IO_STATUS_ERROR;
953 *bytes_read = result;
955 return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
959 g_io_win32_fd_write (GIOChannel *channel,
962 gsize *bytes_written,
965 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
968 result = write (win32_channel->fd, buf, count);
969 if (win32_channel->debug)
970 g_print ("g_io_win32_fd_write: fd=%d count=%d => %d\n",
971 win32_channel->fd, count, result);
981 return G_IO_STATUS_AGAIN;
984 g_set_error (err, G_IO_CHANNEL_ERROR,
985 g_io_channel_error_from_errno (errno),
987 return G_IO_STATUS_ERROR;
991 *bytes_written = result;
993 return G_IO_STATUS_NORMAL;
997 g_io_win32_fd_seek (GIOChannel *channel,
1002 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1019 whence = -1; /* Keep the compiler quiet */
1020 g_assert_not_reached ();
1024 tmp_offset = offset;
1025 if (tmp_offset != offset)
1027 g_set_error (err, G_IO_CHANNEL_ERROR,
1028 g_io_channel_error_from_errno (EINVAL),
1029 g_strerror (EINVAL));
1030 return G_IO_STATUS_ERROR;
1033 result = lseek (win32_channel->fd, tmp_offset, whence);
1037 g_set_error (err, G_IO_CHANNEL_ERROR,
1038 g_io_channel_error_from_errno (errno),
1039 g_strerror (errno));
1040 return G_IO_STATUS_ERROR;
1043 return G_IO_STATUS_NORMAL;
1047 g_io_win32_fd_close (GIOChannel *channel,
1050 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1052 if (win32_channel->debug)
1053 g_print ("thread %#x: closing fd %d\n",
1054 win32_channel->thread_id,
1056 LOCK (win32_channel->mutex);
1057 if (win32_channel->running)
1059 if (win32_channel->debug)
1060 g_print ("thread %#x: running, marking fd %d for later close\n",
1061 win32_channel->thread_id, win32_channel->fd);
1062 win32_channel->running = FALSE;
1063 win32_channel->needs_close = TRUE;
1064 SetEvent (win32_channel->data_avail_event);
1068 if (win32_channel->debug)
1069 g_print ("closing fd %d\n", win32_channel->fd);
1070 close (win32_channel->fd);
1071 if (win32_channel->debug)
1072 g_print ("closed fd %d, setting to -1\n",
1074 win32_channel->fd = -1;
1076 UNLOCK (win32_channel->mutex);
1078 /* FIXME error detection? */
1080 return G_IO_STATUS_NORMAL;
1084 g_io_win32_fd_create_watch (GIOChannel *channel,
1085 GIOCondition condition)
1087 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1088 GSource *source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
1089 GIOWin32Watch *watch = (GIOWin32Watch *)source;
1091 watch->channel = channel;
1092 g_io_channel_ref (channel);
1094 watch->condition = condition;
1096 if (win32_channel->data_avail_event == NULL)
1097 create_events (win32_channel);
1099 watch->pollfd.fd = (gint) win32_channel->data_avail_event;
1100 watch->pollfd.events = condition;
1102 if (win32_channel->debug)
1103 g_print ("g_io_win32_fd_create_watch: fd=%d condition={%s} handle=%#x\n",
1104 win32_channel->fd, condition_to_string (condition), watch->pollfd.fd);
1106 LOCK (win32_channel->mutex);
1107 if (win32_channel->thread_id == 0)
1108 create_thread (win32_channel, condition, read_thread);
1110 g_source_add_poll (source, &watch->pollfd);
1111 UNLOCK (win32_channel->mutex);
1117 g_io_win32_sock_read (GIOChannel *channel,
1123 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1125 GIOChannelError error;
1128 if (win32_channel->debug)
1129 g_print ("g_io_win32_sock_read: sockfd=%d count=%d\n",
1130 win32_channel->fd, count);
1132 result = recv (win32_channel->fd, buf, count, 0);
1133 if (result == SOCKET_ERROR)
1134 winsock_error = WSAGetLastError ();
1136 if (win32_channel->debug)
1137 g_print ("g_io_win32_sock_read: recv=%d %s\n",
1139 (result == SOCKET_ERROR ? winsock_error_message (winsock_error) : ""));
1141 if (result == SOCKET_ERROR)
1145 switch (winsock_error)
1148 error = G_IO_CHANNEL_ERROR_INVAL;
1150 case WSAEWOULDBLOCK:
1151 return G_IO_STATUS_AGAIN;
1153 error = G_IO_CHANNEL_ERROR_FAILED;
1156 g_set_error (err, G_IO_CHANNEL_ERROR, error,
1157 winsock_error_message (winsock_error));
1158 return G_IO_STATUS_ERROR;
1162 *bytes_read = result;
1164 return G_IO_STATUS_EOF;
1166 return G_IO_STATUS_NORMAL;
1171 g_io_win32_sock_write (GIOChannel *channel,
1174 gsize *bytes_written,
1177 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1179 GIOChannelError error;
1182 if (win32_channel->debug)
1183 g_print ("g_io_win32_sock_write: sockfd=%d count=%d\n",
1184 win32_channel->fd, count);
1186 result = send (win32_channel->fd, buf, count, 0);
1187 if (result == SOCKET_ERROR)
1188 winsock_error = WSAGetLastError ();
1190 if (win32_channel->debug)
1191 g_print ("g_io_win32_sock_write: send=%d %s\n",
1193 (result == SOCKET_ERROR ? winsock_error_message (winsock_error) : ""));
1195 if (result == SOCKET_ERROR)
1199 switch (winsock_error)
1202 error = G_IO_CHANNEL_ERROR_INVAL;
1204 case WSAEWOULDBLOCK:
1205 win32_channel->write_would_have_blocked = TRUE;
1206 win32_channel->last_events = 0;
1207 return G_IO_STATUS_AGAIN;
1209 error = G_IO_CHANNEL_ERROR_FAILED;
1212 g_set_error (err, G_IO_CHANNEL_ERROR, error,
1213 winsock_error_message (winsock_error));
1215 return G_IO_STATUS_ERROR;
1219 *bytes_written = result;
1220 win32_channel->write_would_have_blocked = FALSE;
1222 return G_IO_STATUS_NORMAL;
1227 g_io_win32_sock_close (GIOChannel *channel,
1230 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1232 if (win32_channel->fd != -1)
1234 if (win32_channel->debug)
1235 g_print ("g_io_win32_sock_close: closing socket %d\n",
1238 closesocket (win32_channel->fd);
1239 win32_channel->fd = -1;
1242 /* FIXME error detection? */
1244 return G_IO_STATUS_NORMAL;
1248 g_io_win32_sock_create_watch (GIOChannel *channel,
1249 GIOCondition condition)
1251 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1252 GSource *source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
1253 GIOWin32Watch *watch = (GIOWin32Watch *)source;
1255 watch->channel = channel;
1256 g_io_channel_ref (channel);
1258 watch->condition = condition;
1260 if (win32_channel->event == 0)
1261 win32_channel->event = (int) WSACreateEvent ();
1263 watch->pollfd.fd = win32_channel->event;
1264 watch->pollfd.events = condition;
1266 if (win32_channel->debug)
1267 g_print ("g_io_win32_sock_create_watch: sock=%d handle=%#x condition={%s}\n",
1268 win32_channel->fd, watch->pollfd.fd,
1269 condition_to_string (watch->condition));
1271 g_source_add_poll (source, &watch->pollfd);
1277 g_io_channel_new_file (const gchar *filename,
1281 int fid, flags, pmode;
1282 GIOChannel *channel;
1284 enum { /* Cheesy hack */
1291 g_return_val_if_fail (filename != NULL, NULL);
1292 g_return_val_if_fail (mode != NULL, NULL);
1293 g_return_val_if_fail ((error == NULL) || (*error == NULL), NULL);
1307 g_warning ("Invalid GIOFileMode %s.\n", mode);
1316 if (mode[2] == '\0')
1318 mode_num |= MODE_PLUS;
1323 g_warning ("Invalid GIOFileMode %s.\n", mode);
1334 flags = O_WRONLY | O_TRUNC | O_CREAT;
1338 flags = O_WRONLY | O_APPEND | O_CREAT;
1341 case MODE_R | MODE_PLUS:
1343 pmode = _S_IREAD | _S_IWRITE;
1345 case MODE_W | MODE_PLUS:
1346 flags = O_RDWR | O_TRUNC | O_CREAT;
1347 pmode = _S_IREAD | _S_IWRITE;
1349 case MODE_A | MODE_PLUS:
1350 flags = O_RDWR | O_APPEND | O_CREAT;
1351 pmode = _S_IREAD | _S_IWRITE;
1354 g_assert_not_reached ();
1358 /* always open 'untranslated' */
1359 fid = g_open (filename, flags | _O_BINARY, pmode);
1361 if (g_io_win32_get_debug_flag ())
1363 g_print ("g_io_channel_win32_new_file: open(\"%s\", ", filename);
1364 g_win32_print_access_mode (flags|_O_BINARY);
1365 g_print (",%#o)=%d\n", pmode, fid);
1370 g_set_error (error, G_FILE_ERROR,
1371 g_file_error_from_errno (errno),
1372 g_strerror (errno));
1373 return (GIOChannel *)NULL;
1376 channel = g_io_channel_win32_new_fd (fid);
1378 /* XXX: move this to g_io_channel_win32_new_fd () */
1379 channel->close_on_unref = TRUE;
1380 channel->is_seekable = TRUE;
1382 /* g_io_channel_win32_new_fd sets is_readable and is_writeable to
1383 * correspond to actual readability/writeability. Set to FALSE those
1384 * that mode doesn't allow
1389 channel->is_writeable = FALSE;
1393 channel->is_readable = FALSE;
1395 case MODE_R | MODE_PLUS:
1396 case MODE_W | MODE_PLUS:
1397 case MODE_A | MODE_PLUS:
1400 g_assert_not_reached ();
1409 #undef g_io_channel_new_file
1411 /* Binary compatibility version. Not for newly compiled code. */
1414 g_io_channel_new_file (const gchar *filename,
1418 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, error);
1421 if (utf8_filename == NULL)
1424 retval = g_io_channel_new_file_utf8 (utf8_filename, mode, error);
1426 g_free (utf8_filename);
1434 g_io_win32_set_flags (GIOChannel *channel,
1438 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1440 if (win32_channel->debug)
1442 g_print ("g_io_win32_set_flags: ");
1443 g_win32_print_gioflags (flags);
1447 g_set_error (err, G_IO_CHANNEL_ERROR,
1448 G_IO_CHANNEL_ERROR_FAILED,
1449 "Not implemented on Win32");
1451 return G_IO_STATUS_ERROR;
1455 g_io_win32_fd_get_flags_internal (GIOChannel *channel,
1458 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
1462 if (st->st_mode & _S_IFIFO)
1464 channel->is_readable =
1465 (PeekNamedPipe ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL, NULL) != 0) || GetLastError () == ERROR_BROKEN_PIPE;
1466 channel->is_writeable =
1467 (WriteFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
1468 channel->is_seekable = FALSE;
1470 else if (st->st_mode & _S_IFCHR)
1472 /* XXX Seems there is no way to find out the readability of file
1473 * handles to device files (consoles, mostly) without doing a
1474 * blocking read. So punt, say it's readable.
1476 channel->is_readable = TRUE;
1478 channel->is_writeable =
1479 (WriteFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
1481 /* XXX What about devices that actually *are* seekable? But
1482 * those would probably not be handled using the C runtime
1483 * anyway, but using Windows-specific code.
1485 channel->is_seekable = FALSE;
1489 channel->is_readable =
1490 (ReadFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
1491 channel->is_writeable =
1492 (WriteFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
1493 channel->is_seekable = TRUE;
1496 /* XXX: G_IO_FLAG_APPEND */
1497 /* XXX: G_IO_FLAG_NONBLOCK */
1503 g_io_win32_fd_get_flags (GIOChannel *channel)
1506 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1508 g_return_val_if_fail (win32_channel != NULL, 0);
1509 g_return_val_if_fail (win32_channel->type == G_IO_WIN32_FILE_DESC, 0);
1511 if (0 == fstat (win32_channel->fd, &st))
1512 return g_io_win32_fd_get_flags_internal (channel, &st);
1518 g_io_win32_msg_get_flags (GIOChannel *channel)
1524 g_io_win32_sock_get_flags (GIOChannel *channel)
1526 /* XXX Could do something here. */
1530 static GIOFuncs win32_channel_msg_funcs = {
1531 g_io_win32_msg_read,
1532 g_io_win32_msg_write,
1534 g_io_win32_msg_close,
1535 g_io_win32_msg_create_watch,
1537 g_io_win32_set_flags,
1538 g_io_win32_msg_get_flags,
1541 static GIOFuncs win32_channel_fd_funcs = {
1543 g_io_win32_fd_write,
1545 g_io_win32_fd_close,
1546 g_io_win32_fd_create_watch,
1548 g_io_win32_set_flags,
1549 g_io_win32_fd_get_flags,
1552 static GIOFuncs win32_channel_sock_funcs = {
1553 g_io_win32_sock_read,
1554 g_io_win32_sock_write,
1556 g_io_win32_sock_close,
1557 g_io_win32_sock_create_watch,
1559 g_io_win32_set_flags,
1560 g_io_win32_sock_get_flags,
1564 g_io_channel_win32_new_messages (guint hwnd)
1566 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1567 GIOChannel *channel = (GIOChannel *)win32_channel;
1569 g_io_channel_init (channel);
1570 g_io_channel_win32_init (win32_channel);
1571 if (win32_channel->debug)
1572 g_print ("g_io_channel_win32_new_messages: hwnd=%#x\n", hwnd);
1573 channel->funcs = &win32_channel_msg_funcs;
1574 win32_channel->type = G_IO_WIN32_WINDOWS_MESSAGES;
1575 win32_channel->hwnd = (HWND) hwnd;
1577 /* XXX: check this. */
1578 channel->is_readable = IsWindow (win32_channel->hwnd);
1579 channel->is_writeable = IsWindow (win32_channel->hwnd);
1581 channel->is_seekable = FALSE;
1587 g_io_channel_win32_new_fd_internal (gint fd,
1590 GIOWin32Channel *win32_channel;
1591 GIOChannel *channel;
1593 win32_channel = g_new (GIOWin32Channel, 1);
1594 channel = (GIOChannel *)win32_channel;
1596 g_io_channel_init (channel);
1597 g_io_channel_win32_init (win32_channel);
1598 if (win32_channel->debug)
1599 g_print ("g_io_channel_win32_new_fd: %u\n", fd);
1600 channel->funcs = &win32_channel_fd_funcs;
1601 win32_channel->type = G_IO_WIN32_FILE_DESC;
1602 win32_channel->fd = fd;
1604 g_io_win32_fd_get_flags_internal (channel, st);
1610 g_io_channel_win32_new_fd (gint fd)
1614 if (fstat (fd, &st) == -1)
1616 g_warning (G_STRLOC ": %d isn't a C library file descriptor", fd);
1620 return g_io_channel_win32_new_fd_internal (fd, &st);
1624 g_io_channel_win32_get_fd (GIOChannel *channel)
1626 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1628 return win32_channel->fd;
1632 g_io_channel_win32_new_socket (int socket)
1634 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1635 GIOChannel *channel = (GIOChannel *)win32_channel;
1637 g_io_channel_init (channel);
1638 g_io_channel_win32_init (win32_channel);
1639 if (win32_channel->debug)
1640 g_print ("g_io_channel_win32_new_socket: sockfd=%d\n", socket);
1641 channel->funcs = &win32_channel_sock_funcs;
1642 win32_channel->type = G_IO_WIN32_SOCKET;
1643 win32_channel->fd = socket;
1645 channel->is_readable = TRUE;
1646 channel->is_writeable = TRUE;
1647 channel->is_seekable = FALSE;
1653 g_io_channel_unix_new (gint fd)
1655 gboolean is_fd, is_socket;
1659 is_fd = (fstat (fd, &st) == 0);
1661 optlen = sizeof (optval);
1662 is_socket = (getsockopt (fd, SOL_SOCKET, SO_TYPE, (char *) &optval, &optlen) != SOCKET_ERROR);
1664 if (is_fd && is_socket)
1665 g_warning (G_STRLOC ": %d is both a file descriptor and a socket, file descriptor interpretation assumed.", fd);
1668 return g_io_channel_win32_new_fd_internal (fd, &st);
1671 return g_io_channel_win32_new_socket(fd);
1673 g_warning (G_STRLOC ": %d is neither a file descriptor or a socket", fd);
1679 g_io_channel_unix_get_fd (GIOChannel *channel)
1681 return g_io_channel_win32_get_fd (channel);
1685 g_io_channel_win32_set_debug (GIOChannel *channel,
1688 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1690 win32_channel->debug = flag;
1694 g_io_channel_win32_poll (GPollFD *fds,
1700 g_return_val_if_fail (n_fds >= 0, 0);
1702 result = (*g_main_context_get_poll_func (NULL)) (fds, n_fds, timeout);
1708 g_io_channel_win32_make_pollfd (GIOChannel *channel,
1709 GIOCondition condition,
1712 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1714 switch (win32_channel->type)
1716 case G_IO_WIN32_FILE_DESC:
1717 if (win32_channel->data_avail_event == NULL)
1718 create_events (win32_channel);
1720 fd->fd = (gint) win32_channel->data_avail_event;
1722 if (win32_channel->thread_id == 0 && (condition & G_IO_IN))
1723 create_thread (win32_channel, condition, read_thread);
1726 case G_IO_WIN32_SOCKET:
1727 fd->fd = (int) WSACreateEvent ();
1730 case G_IO_WIN32_WINDOWS_MESSAGES:
1731 fd->fd = G_WIN32_MSG_HANDLE;
1735 g_assert_not_reached ();
1739 fd->events = condition;
1742 /* Binary compatibility */
1744 g_io_channel_win32_new_stream_socket (int socket)
1746 return g_io_channel_win32_new_socket (socket);
1749 #define __G_IO_WIN32_C__
1750 #include "galiasdef.c"