If a character can't be converted, don't replace it with a NUL byte, but
[glib.git] / glib / giowin32.c
blob53549687c47daa280a975c4d088cb1586231c9e9
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 #include "config.h"
34 #include "glib.h"
36 #include <stdlib.h>
37 #include <winsock2.h>
38 #include <windows.h>
39 #include <fcntl.h>
40 #include <io.h>
41 #include <process.h>
42 #include <errno.h>
43 #include <sys/stat.h>
45 #include "gstdio.h"
46 #include "glibintl.h"
48 #include "galias.h"
50 typedef struct _GIOWin32Channel GIOWin32Channel;
51 typedef struct _GIOWin32Watch GIOWin32Watch;
53 #define BUFFER_SIZE 4096
55 typedef enum {
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 {
65 GIOChannel channel;
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;
72 gboolean debug;
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 int direction; /* 0 means we read from it,
81 * 1 means we write to it.
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
91 * had.*/
92 HANDLE data_avail_event;
94 gushort revents;
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).
104 * Empty: wrp == rdp
105 * Full: (wrp + 1) % BUFFER_SIZE == rdp
106 * Partial: otherwise
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 */
113 int event_mask;
114 int last_events;
115 int event;
116 gboolean write_would_have_blocked;
119 #define LOCK(mutex) EnterCriticalSection (&mutex)
120 #define UNLOCK(mutex) LeaveCriticalSection (&mutex)
122 struct _GIOWin32Watch {
123 GSource source;
124 GPollFD pollfd;
125 GIOChannel *channel;
126 GIOCondition condition;
129 static void
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" : ""));
147 static void
148 g_win32_print_gioflags (GIOFlags flags)
150 char *bar = "";
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 = "|";
164 static const char *
165 event_mask_to_string (int mask)
167 char buf[100];
168 int checked_bits = 0;
169 char *bufp = buf;
171 if (mask == 0)
172 return "";
174 #define BIT(n) checked_bits |= FD_##n; if (mask & FD_##n) bufp += sprintf (bufp, "%s" #n, (bufp>buf ? "|" : ""))
176 BIT (READ);
177 BIT (WRITE);
178 BIT (OOB);
179 BIT (ACCEPT);
180 BIT (CONNECT);
181 BIT (CLOSE);
182 BIT (QOS);
183 BIT (GROUP_QOS);
184 BIT (ROUTING_INTERFACE_CHANGE);
185 BIT (ADDRESS_LIST_CHANGE);
187 #undef BIT
189 if ((mask & ~checked_bits) != 0)
190 bufp += sprintf (bufp, "|%#x", mask & ~checked_bits);
192 return g_quark_to_string (g_quark_from_string (buf));
195 static const char *
196 condition_to_string (GIOCondition condition)
198 char buf[100];
199 int checked_bits = 0;
200 char *bufp = buf;
202 if (condition == 0)
203 return "";
205 #define BIT(n) checked_bits |= G_IO_##n; if (condition & G_IO_##n) bufp += sprintf (bufp, "%s" #n, (bufp>buf ? "|" : ""))
207 BIT (IN);
208 BIT (OUT);
209 BIT (PRI);
210 BIT (ERR);
211 BIT (HUP);
212 BIT (NVAL);
214 #undef BIT
216 if ((condition & ~checked_bits) != 0)
217 bufp += sprintf (bufp, "|%#x", condition & ~checked_bits);
219 return g_quark_to_string (g_quark_from_string (buf));
222 static gboolean
223 g_io_win32_get_debug_flag (void)
225 return (getenv ("G_IO_WIN32_DEBUG") != NULL);
228 static char *
229 winsock_error_message (int number)
231 static char unk[100];
233 switch (number) {
234 case WSAEINTR:
235 return "Interrupted function call";
236 case WSAEACCES:
237 return "Permission denied";
238 case WSAEFAULT:
239 return "Bad address";
240 case WSAEINVAL:
241 return "Invalid argument";
242 case WSAEMFILE:
243 return "Too many open sockets";
244 case WSAEWOULDBLOCK:
245 return "Resource temporarily unavailable";
246 case WSAEINPROGRESS:
247 return "Operation now in progress";
248 case WSAEALREADY:
249 return "Operation already in progress";
250 case WSAENOTSOCK:
251 return "Socket operation on nonsocket";
252 case WSAEDESTADDRREQ:
253 return "Destination address required";
254 case WSAEMSGSIZE:
255 return "Message too long";
256 case WSAEPROTOTYPE:
257 return "Protocol wrong type for socket";
258 case WSAENOPROTOOPT:
259 return "Bad protocol option";
260 case WSAEPROTONOSUPPORT:
261 return "Protocol not supported";
262 case WSAESOCKTNOSUPPORT:
263 return "Socket type not supported";
264 case WSAEOPNOTSUPP:
265 return "Operation not supported on transport endpoint";
266 case WSAEPFNOSUPPORT:
267 return "Protocol family not supported";
268 case WSAEAFNOSUPPORT:
269 return "Address family not supported by protocol family";
270 case WSAEADDRINUSE:
271 return "Address already in use";
272 case WSAEADDRNOTAVAIL:
273 return "Address not available";
274 case WSAENETDOWN:
275 return "Network interface is not configured";
276 case WSAENETUNREACH:
277 return "Network is unreachable";
278 case WSAENETRESET:
279 return "Network dropped connection on reset";
280 case WSAECONNABORTED:
281 return "Software caused connection abort";
282 case WSAECONNRESET:
283 return "Connection reset by peer";
284 case WSAENOBUFS:
285 return "No buffer space available";
286 case WSAEISCONN:
287 return "Socket is already connected";
288 case WSAENOTCONN:
289 return "Socket is not connected";
290 case WSAESHUTDOWN:
291 return "Can't send after socket shutdown";
292 case WSAETIMEDOUT:
293 return "Connection timed out";
294 case WSAECONNREFUSED:
295 return "Connection refused";
296 case WSAEHOSTDOWN:
297 return "Host is down";
298 case WSAEHOSTUNREACH:
299 return "Host is unreachable";
300 case WSAEPROCLIM:
301 return "Too many processes";
302 case WSASYSNOTREADY:
303 return "Network subsystem is unavailable";
304 case WSAVERNOTSUPPORTED:
305 return "Winsock.dll version out of range";
306 case WSANOTINITIALISED:
307 return "Successful WSAStartup not yet performed";
308 case WSAEDISCON:
309 return "Graceful shutdown in progress";
310 case WSATYPE_NOT_FOUND:
311 return "Class type not found";
312 case WSAHOST_NOT_FOUND:
313 return "Host not found";
314 case WSATRY_AGAIN:
315 return "Nonauthoritative host not found";
316 case WSANO_RECOVERY:
317 return "This is a nonrecoverable error";
318 case WSANO_DATA:
319 return "Valid name, no data record of requested type";
320 case WSA_INVALID_HANDLE:
321 return "Specified event object handle is invalid";
322 case WSA_INVALID_PARAMETER:
323 return "One or more parameters are invalid";
324 case WSA_IO_INCOMPLETE:
325 return "Overlapped I/O event object not in signaled state";
326 case WSA_NOT_ENOUGH_MEMORY:
327 return "Insufficient memory available";
328 case WSA_OPERATION_ABORTED:
329 return "Overlapped operation aborted";
330 case WSAEINVALIDPROCTABLE:
331 return "Invalid procedure table from service provider";
332 case WSAEINVALIDPROVIDER:
333 return "Invalid service provider version number";
334 case WSAEPROVIDERFAILEDINIT:
335 return "Unable to initialize a service provider";
336 case WSASYSCALLFAILURE:
337 return "System call failure";
338 default:
339 sprintf (unk, "Unknown WinSock error %d", number);
340 return unk;
344 static void
345 g_io_channel_win32_init (GIOWin32Channel *channel)
347 channel->debug = g_io_win32_get_debug_flag ();
348 channel->buffer = NULL;
349 channel->running = FALSE;
350 channel->needs_close = FALSE;
351 channel->thread_id = 0;
352 channel->data_avail_event = NULL;
353 channel->revents = 0;
354 channel->space_avail_event = NULL;
355 channel->event_mask = 0;
356 channel->last_events = 0;
357 channel->event = 0;
358 channel->write_would_have_blocked = FALSE;
359 InitializeCriticalSection (&channel->mutex);
362 static void
363 create_events (GIOWin32Channel *channel)
365 SECURITY_ATTRIBUTES sec_attrs;
367 sec_attrs.nLength = sizeof (SECURITY_ATTRIBUTES);
368 sec_attrs.lpSecurityDescriptor = NULL;
369 sec_attrs.bInheritHandle = FALSE;
371 /* The data available event is manual reset, the space available event
372 * is automatic reset.
374 if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
375 || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
377 gchar *emsg = g_win32_error_message (GetLastError ());
378 g_error ("Error creating event: %s", emsg);
379 g_free (emsg);
383 static unsigned __stdcall
384 read_thread (void *parameter)
386 GIOWin32Channel *channel = parameter;
387 guchar *buffer;
388 guint nbytes;
390 g_io_channel_ref ((GIOChannel *)channel);
392 if (channel->debug)
393 g_print ("read_thread %#x: start fd=%d, data_avail=%#x space_avail=%#x\n",
394 channel->thread_id,
395 channel->fd,
396 (guint) channel->data_avail_event,
397 (guint) channel->space_avail_event);
399 channel->direction = 0;
400 channel->buffer = g_malloc (BUFFER_SIZE);
401 channel->rdp = channel->wrp = 0;
402 channel->running = TRUE;
404 SetEvent (channel->space_avail_event);
406 LOCK (channel->mutex);
407 while (channel->running)
409 if (channel->debug)
410 g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
411 channel->thread_id, channel->rdp, channel->wrp);
412 if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
414 /* Buffer is full */
415 if (channel->debug)
416 g_print ("read_thread %#x: resetting space_avail\n",
417 channel->thread_id);
418 ResetEvent (channel->space_avail_event);
419 if (channel->debug)
420 g_print ("read_thread %#x: waiting for space\n",
421 channel->thread_id);
422 UNLOCK (channel->mutex);
423 WaitForSingleObject (channel->space_avail_event, INFINITE);
424 LOCK (channel->mutex);
425 if (channel->debug)
426 g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
427 channel->thread_id, channel->rdp, channel->wrp);
430 buffer = channel->buffer + channel->wrp;
432 /* Always leave at least one byte unused gap to be able to
433 * distinguish between the full and empty condition...
435 nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
436 BUFFER_SIZE - channel->wrp);
438 if (channel->debug)
439 g_print ("read_thread %#x: calling read() for %d bytes\n",
440 channel->thread_id, nbytes);
442 UNLOCK (channel->mutex);
444 nbytes = read (channel->fd, buffer, nbytes);
446 LOCK (channel->mutex);
448 channel->revents = G_IO_IN;
449 if (nbytes == 0)
450 channel->revents |= G_IO_HUP;
451 else if (nbytes < 0)
452 channel->revents |= G_IO_ERR;
454 if (channel->debug)
455 g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
456 channel->thread_id, nbytes, channel->rdp, channel->wrp);
458 if (nbytes <= 0)
459 break;
461 channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
462 if (channel->debug)
463 g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
464 channel->thread_id, channel->rdp, channel->wrp);
465 SetEvent (channel->data_avail_event);
468 channel->running = FALSE;
469 if (channel->needs_close)
471 if (channel->debug)
472 g_print ("read_thread %#x: channel fd %d needs closing\n",
473 channel->thread_id, channel->fd);
474 close (channel->fd);
475 channel->fd = -1;
478 if (channel->debug)
479 g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
480 channel->thread_id, channel->rdp, channel->wrp);
481 SetEvent (channel->data_avail_event);
482 UNLOCK (channel->mutex);
484 g_io_channel_unref ((GIOChannel *)channel);
486 /* No need to call _endthreadex(), the actual thread starter routine
487 * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
488 * _endthreadex() for us.
491 return 0;
494 static unsigned __stdcall
495 write_thread (void *parameter)
497 GIOWin32Channel *channel = parameter;
498 guchar *buffer;
499 guint nbytes;
501 g_io_channel_ref ((GIOChannel *)channel);
503 if (channel->debug)
504 g_print ("write_thread %#x: start fd=%d, data_avail=%#x space_avail=%#x\n",
505 channel->thread_id,
506 channel->fd,
507 (guint) channel->data_avail_event,
508 (guint) channel->space_avail_event);
510 channel->direction = 1;
511 channel->buffer = g_malloc (BUFFER_SIZE);
512 channel->rdp = channel->wrp = 0;
513 channel->running = TRUE;
515 SetEvent (channel->space_avail_event);
517 /* We use the same event objects as for a reader thread, but with
518 * reversed meaning. So, space_avail is used if data is available
519 * for writing, and data_avail is used if space is available in the
520 * write buffer.
523 LOCK (channel->mutex);
524 while (channel->running || channel->rdp != channel->wrp)
526 if (channel->debug)
527 g_print ("write_thread %#x: rdp=%d, wrp=%d\n",
528 channel->thread_id, channel->rdp, channel->wrp);
529 if (channel->wrp == channel->rdp)
531 /* Buffer is empty. */
532 if (channel->debug)
533 g_print ("write_thread %#x: resetting space_avail\n",
534 channel->thread_id);
535 ResetEvent (channel->space_avail_event);
536 if (channel->debug)
537 g_print ("write_thread %#x: waiting for data\n",
538 channel->thread_id);
539 channel->revents = G_IO_OUT;
540 SetEvent (channel->data_avail_event);
541 UNLOCK (channel->mutex);
542 WaitForSingleObject (channel->space_avail_event, INFINITE);
544 LOCK (channel->mutex);
545 if (channel->rdp == channel->wrp)
546 break;
548 if (channel->debug)
549 g_print ("write_thread %#x: rdp=%d, wrp=%d\n",
550 channel->thread_id, channel->rdp, channel->wrp);
553 buffer = channel->buffer + channel->rdp;
554 if (channel->rdp < channel->wrp)
555 nbytes = channel->wrp - channel->rdp;
556 else
557 nbytes = BUFFER_SIZE - channel->rdp;
559 if (channel->debug)
560 g_print ("write_thread %#x: calling write() for %d bytes\n",
561 channel->thread_id, nbytes);
563 UNLOCK (channel->mutex);
564 nbytes = write (channel->fd, buffer, nbytes);
565 LOCK (channel->mutex);
567 if (channel->debug)
568 g_print ("write_thread %#x: write(%i) returned %d, rdp=%d, wrp=%d\n",
569 channel->thread_id, channel->fd, nbytes, channel->rdp, channel->wrp);
571 channel->revents = 0;
572 if (nbytes > 0)
573 channel->revents |= G_IO_OUT;
574 else if (nbytes <= 0)
575 channel->revents |= G_IO_ERR;
577 channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
579 if (nbytes <= 0)
580 break;
582 if (channel->debug)
583 g_print ("write_thread: setting data_avail for thread %#x\n",
584 channel->thread_id);
585 SetEvent (channel->data_avail_event);
588 channel->running = FALSE;
589 if (channel->needs_close)
591 if (channel->debug)
592 g_print ("write_thread %#x: channel fd %d needs closing\n",
593 channel->thread_id, channel->fd);
594 close (channel->fd);
595 channel->fd = -1;
598 UNLOCK (channel->mutex);
600 g_io_channel_unref ((GIOChannel *)channel);
602 return 0;
605 static void
606 create_thread (GIOWin32Channel *channel,
607 GIOCondition condition,
608 unsigned (__stdcall *thread) (void *parameter))
610 HANDLE thread_handle;
612 thread_handle = (HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
613 &channel->thread_id);
614 if (thread_handle == 0)
615 g_warning (G_STRLOC ": Error creating reader thread: %s",
616 g_strerror (errno));
617 else if (!CloseHandle (thread_handle))
618 g_warning (G_STRLOC ": Error closing thread handle: %s\n",
619 g_win32_error_message (GetLastError ()));
621 WaitForSingleObject (channel->space_avail_event, INFINITE);
624 static GIOStatus
625 buffer_read (GIOWin32Channel *channel,
626 guchar *dest,
627 gsize count,
628 gsize *bytes_read,
629 GError **err)
631 guint nbytes;
632 guint left = count;
634 LOCK (channel->mutex);
635 if (channel->debug)
636 g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
637 channel->thread_id, count, channel->rdp, channel->wrp);
639 if (channel->wrp == channel->rdp)
641 UNLOCK (channel->mutex);
642 if (channel->debug)
643 g_print ("waiting for data from thread %#x\n", channel->thread_id);
644 WaitForSingleObject (channel->data_avail_event, INFINITE);
645 if (channel->debug)
646 g_print ("done waiting for data from thread %#x\n", channel->thread_id);
647 LOCK (channel->mutex);
648 if (channel->wrp == channel->rdp && !channel->running)
650 if (channel->debug)
651 g_print ("wrp==rdp, !running\n");
652 UNLOCK (channel->mutex);
653 *bytes_read = 0;
654 return G_IO_STATUS_EOF;
658 if (channel->rdp < channel->wrp)
659 nbytes = channel->wrp - channel->rdp;
660 else
661 nbytes = BUFFER_SIZE - channel->rdp;
662 UNLOCK (channel->mutex);
663 nbytes = MIN (left, nbytes);
664 if (channel->debug)
665 g_print ("moving %d bytes from thread %#x\n",
666 nbytes, channel->thread_id);
667 memcpy (dest, channel->buffer + channel->rdp, nbytes);
668 dest += nbytes;
669 left -= nbytes;
670 LOCK (channel->mutex);
671 channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
672 if (channel->debug)
673 g_print ("setting space_avail for thread %#x\n", channel->thread_id);
674 SetEvent (channel->space_avail_event);
675 if (channel->debug)
676 g_print ("for thread %#x: rdp=%d, wrp=%d\n",
677 channel->thread_id, channel->rdp, channel->wrp);
678 if (channel->running && channel->wrp == channel->rdp)
680 if (channel->debug)
681 g_print ("resetting data_avail of thread %#x\n",
682 channel->thread_id);
683 ResetEvent (channel->data_avail_event);
685 UNLOCK (channel->mutex);
687 /* We have no way to indicate any errors form the actual
688 * read() or recv() call in the reader thread. Should we have?
690 *bytes_read = count - left;
691 return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
695 static GIOStatus
696 buffer_write (GIOWin32Channel *channel,
697 const guchar *dest,
698 gsize count,
699 gsize *bytes_written,
700 GError **err)
702 guint nbytes;
703 guint left = count;
705 LOCK (channel->mutex);
706 if (channel->debug)
707 g_print ("buffer_write: writing to thread %#x %d bytes, rdp=%d, wrp=%d\n",
708 channel->thread_id, count, channel->rdp, channel->wrp);
710 if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
712 /* Buffer is full */
713 if (channel->debug)
714 g_print ("buffer_write: tid %#x: resetting data_avail\n",
715 channel->thread_id);
716 ResetEvent (channel->data_avail_event);
717 if (channel->debug)
718 g_print ("buffer_write: tid %#x: waiting for space\n",
719 channel->thread_id);
720 UNLOCK (channel->mutex);
721 WaitForSingleObject (channel->data_avail_event, INFINITE);
722 LOCK (channel->mutex);
723 if (channel->debug)
724 g_print ("buffer_write: tid %#x: rdp=%d, wrp=%d\n",
725 channel->thread_id, channel->rdp, channel->wrp);
728 nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
729 BUFFER_SIZE - channel->wrp);
731 UNLOCK (channel->mutex);
732 nbytes = MIN (left, nbytes);
733 if (channel->debug)
734 g_print ("buffer_write: tid %#x: writing %d bytes\n",
735 channel->thread_id, nbytes);
736 memcpy (channel->buffer + channel->wrp, dest, nbytes);
737 dest += nbytes;
738 left -= nbytes;
739 LOCK (channel->mutex);
741 channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
742 if (channel->debug)
743 g_print ("buffer_write: tid %#x: rdp=%d, wrp=%d, setting space_avail\n",
744 channel->thread_id, channel->rdp, channel->wrp);
745 SetEvent (channel->space_avail_event);
747 if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
749 /* Buffer is full */
750 if (channel->debug)
751 g_print ("buffer_write: tid %#x: resetting data_avail\n",
752 channel->thread_id);
753 ResetEvent (channel->data_avail_event);
756 UNLOCK (channel->mutex);
758 /* We have no way to indicate any errors form the actual
759 * write() call in the writer thread. Should we have?
761 *bytes_written = count - left;
762 return (*bytes_written > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
766 static gboolean
767 g_io_win32_prepare (GSource *source,
768 gint *timeout)
770 GIOWin32Watch *watch = (GIOWin32Watch *)source;
771 GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
772 GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
773 int event_mask;
775 *timeout = -1;
777 switch (channel->type)
779 case G_IO_WIN32_WINDOWS_MESSAGES:
780 break;
782 case G_IO_WIN32_FILE_DESC:
783 if (channel->debug)
784 g_print ("g_io_win32_prepare: for thread %#x buffer_condition:{%s}\n"
785 " watch->pollfd.events:{%s} watch->pollfd.revents:{%s} channel->revents:{%s}\n",
786 channel->thread_id, condition_to_string (buffer_condition),
787 condition_to_string (watch->pollfd.events),
788 condition_to_string (watch->pollfd.revents),
789 condition_to_string (channel->revents));
791 LOCK (channel->mutex);
792 if (channel->running)
794 if (channel->direction == 0 && channel->wrp == channel->rdp)
796 if (channel->debug)
797 g_print ("g_io_win32_prepare: for thread %#x, setting channel->revents = 0\n",
798 channel->thread_id);
799 channel->revents = 0;
802 else
804 if (channel->direction == 1
805 && (channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
807 if (channel->debug)
808 g_print ("g_io_win32_prepare: for thread %#x, setting channel->revents = %i\n",
809 channel->thread_id, 0);
810 channel->revents = 0;
813 UNLOCK (channel->mutex);
814 break;
816 case G_IO_WIN32_SOCKET:
817 event_mask = 0;
818 if (watch->condition & G_IO_IN)
819 event_mask |= (FD_READ | FD_ACCEPT);
820 if (watch->condition & G_IO_OUT)
821 event_mask |= (FD_WRITE | FD_CONNECT);
822 if (watch->condition & G_IO_HUP)
823 event_mask |= FD_CLOSE;
825 if (channel->event_mask != event_mask /* || channel->event != watch->pollfd.fd*/)
827 if (channel->debug)
828 g_print ("g_io_win32_prepare: WSAEventSelect(%d, %#x, {%s}\n",
829 channel->fd, watch->pollfd.fd,
830 event_mask_to_string (event_mask));
831 if (WSAEventSelect (channel->fd, (HANDLE) watch->pollfd.fd,
832 event_mask) == SOCKET_ERROR)
833 ; /* What? */
834 channel->event_mask = event_mask;
835 #if 0
836 channel->event = watch->pollfd.fd;
837 #endif
838 channel->last_events = 0;
840 break;
842 default:
843 g_assert_not_reached ();
844 abort ();
846 return ((watch->condition & buffer_condition) == watch->condition);
849 static gboolean
850 g_io_win32_check (GSource *source)
852 MSG msg;
853 GIOWin32Watch *watch = (GIOWin32Watch *)source;
854 GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
855 GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
856 WSANETWORKEVENTS events;
858 switch (channel->type)
860 case G_IO_WIN32_WINDOWS_MESSAGES:
861 return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE));
863 case G_IO_WIN32_FILE_DESC:
864 if (channel->debug)
865 g_print ("g_io_win32_check: for thread %#x buffer_condition=%s\n"
866 " watch->pollfd.events={%s} watch->pollfd.revents={%s} channel->revents={%s}\n",
867 channel->thread_id, condition_to_string (buffer_condition),
868 condition_to_string (watch->pollfd.events),
869 condition_to_string (watch->pollfd.revents),
870 condition_to_string (channel->revents));
872 watch->pollfd.revents = (watch->pollfd.events & channel->revents);
874 return ((watch->pollfd.revents | buffer_condition) & watch->condition);
876 case G_IO_WIN32_SOCKET:
877 if (channel->last_events & FD_WRITE)
879 if (channel->debug)
880 g_print ("g_io_win32_check: sock=%d event=%#x last_events has FD_WRITE\n",
881 channel->fd, watch->pollfd.fd);
883 else
885 WSAEnumNetworkEvents (channel->fd, 0, &events);
887 if (channel->debug)
888 g_print ("g_io_win32_check: WSAEnumNetworkEvents (%d, %#x) revents={%s} condition={%s} events={%s}\n",
889 channel->fd, watch->pollfd.fd,
890 condition_to_string (watch->pollfd.revents),
891 condition_to_string (watch->condition),
892 event_mask_to_string (events.lNetworkEvents));
894 if (watch->pollfd.revents != 0 &&
895 events.lNetworkEvents == 0 &&
896 !(channel->event_mask & FD_WRITE))
898 channel->event_mask = 0;
899 if (channel->debug)
900 g_print ("g_io_win32_check: WSAEventSelect(%d, %#x, {})\n",
901 channel->fd, watch->pollfd.fd);
902 WSAEventSelect (channel->fd, (HANDLE) watch->pollfd.fd, 0);
903 if (channel->debug)
904 g_print ("g_io_win32_check: ResetEvent(%#x)\n",
905 watch->pollfd.fd);
906 ResetEvent ((HANDLE) watch->pollfd.fd);
908 channel->last_events = events.lNetworkEvents;
910 watch->pollfd.revents = 0;
911 if (channel->last_events & (FD_READ | FD_ACCEPT))
912 watch->pollfd.revents |= G_IO_IN;
913 if (channel->last_events & (FD_WRITE | FD_CONNECT))
914 watch->pollfd.revents |= G_IO_OUT;
915 if (watch->pollfd.revents == 0 && (channel->last_events & (FD_CLOSE)))
916 watch->pollfd.revents |= G_IO_HUP;
918 if (!channel->write_would_have_blocked && (channel->event_mask & FD_WRITE))
919 watch->pollfd.revents |= G_IO_OUT; /* This sucks but... */
921 return ((watch->pollfd.revents | buffer_condition) & watch->condition);
923 default:
924 g_assert_not_reached ();
925 abort ();
929 static gboolean
930 g_io_win32_dispatch (GSource *source,
931 GSourceFunc callback,
932 gpointer user_data)
934 GIOFunc func = (GIOFunc)callback;
935 GIOWin32Watch *watch = (GIOWin32Watch *)source;
936 GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
937 GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
939 if (!func)
941 g_warning (G_STRLOC ": GIOWin32Watch dispatched without callback\n"
942 "You must call g_source_connect().");
943 return FALSE;
946 if (channel->debug)
947 g_print ("g_io_win32_dispatch: pollfd.revents=%s condition=%s result=%s\n",
948 condition_to_string (watch->pollfd.revents),
949 condition_to_string (watch->condition),
950 condition_to_string ((watch->pollfd.revents | buffer_condition) & watch->condition));
952 return (*func) (watch->channel,
953 (watch->pollfd.revents | buffer_condition) & watch->condition,
954 user_data);
957 static void
958 g_io_win32_finalize (GSource *source)
960 GIOWin32Watch *watch = (GIOWin32Watch *)source;
961 GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
963 switch (channel->type)
965 case G_IO_WIN32_WINDOWS_MESSAGES:
966 break;
968 case G_IO_WIN32_FILE_DESC:
969 LOCK (channel->mutex);
970 if (channel->debug)
971 g_print ("g_io_win32_finalize: channel with thread %#x\n",
972 channel->thread_id);
973 UNLOCK (channel->mutex);
974 break;
976 case G_IO_WIN32_SOCKET:
977 if (channel->debug)
978 g_print ("g_io_win32_finalize: channel is for sock=%d\n", channel->fd);
979 #if 0
980 CloseHandle ((HANDLE) watch->pollfd.fd);
981 channel->event = 0;
982 channel->event_mask = 0;
983 #endif
984 break;
986 default:
987 g_assert_not_reached ();
988 abort ();
990 g_io_channel_unref (watch->channel);
993 GSourceFuncs g_io_watch_funcs = {
994 g_io_win32_prepare,
995 g_io_win32_check,
996 g_io_win32_dispatch,
997 g_io_win32_finalize
1000 static GIOStatus
1001 g_io_win32_msg_read (GIOChannel *channel,
1002 gchar *buf,
1003 gsize count,
1004 gsize *bytes_read,
1005 GError **err)
1007 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1008 MSG msg; /* In case of alignment problems */
1010 if (count < sizeof (MSG))
1012 g_set_error (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
1013 "Incorrect message size"); /* Informative enough error message? */
1014 return G_IO_STATUS_ERROR;
1017 if (win32_channel->debug)
1018 g_print ("g_io_win32_msg_read: for %#x\n",
1019 (guint) win32_channel->hwnd);
1020 if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
1021 return G_IO_STATUS_AGAIN;
1023 memmove (buf, &msg, sizeof (MSG));
1024 *bytes_read = sizeof (MSG);
1026 return G_IO_STATUS_NORMAL;
1029 static GIOStatus
1030 g_io_win32_msg_write (GIOChannel *channel,
1031 const gchar *buf,
1032 gsize count,
1033 gsize *bytes_written,
1034 GError **err)
1036 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1037 MSG msg;
1039 if (count != sizeof (MSG))
1041 g_set_error (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
1042 "Incorrect message size"); /* Informative enough error message? */
1043 return G_IO_STATUS_ERROR;
1046 /* In case of alignment problems */
1047 memmove (&msg, buf, sizeof (MSG));
1048 if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
1050 gchar *emsg = g_win32_error_message (GetLastError ());
1051 g_set_error (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED, emsg);
1052 g_free (emsg);
1053 return G_IO_STATUS_ERROR;
1056 *bytes_written = sizeof (MSG);
1058 return G_IO_STATUS_NORMAL;
1061 static GIOStatus
1062 g_io_win32_msg_close (GIOChannel *channel,
1063 GError **err)
1065 /* Nothing to be done. Or should we set hwnd to some invalid value? */
1067 return G_IO_STATUS_NORMAL;
1070 static void
1071 g_io_win32_free (GIOChannel *channel)
1073 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1075 if (win32_channel->debug)
1076 g_print ("g_io_win32_free channel fd=%d\n", win32_channel->fd);
1078 if (win32_channel->data_avail_event)
1079 CloseHandle (win32_channel->data_avail_event);
1080 if (win32_channel->space_avail_event)
1081 CloseHandle (win32_channel->space_avail_event);
1082 if (win32_channel->type == G_IO_WIN32_SOCKET)
1083 WSAEventSelect (win32_channel->fd, NULL, 0);
1084 DeleteCriticalSection (&win32_channel->mutex);
1086 g_free (win32_channel->buffer);
1087 g_free (win32_channel);
1090 static GSource *
1091 g_io_win32_msg_create_watch (GIOChannel *channel,
1092 GIOCondition condition)
1094 GIOWin32Watch *watch;
1095 GSource *source;
1097 source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
1098 watch = (GIOWin32Watch *)source;
1100 watch->channel = channel;
1101 g_io_channel_ref (channel);
1103 watch->condition = condition;
1105 watch->pollfd.fd = G_WIN32_MSG_HANDLE;
1106 watch->pollfd.events = condition;
1108 g_source_add_poll (source, &watch->pollfd);
1110 return source;
1113 static GIOStatus
1114 g_io_win32_fd_read (GIOChannel *channel,
1115 gchar *buf,
1116 gsize count,
1117 gsize *bytes_read,
1118 GError **err)
1120 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1121 gint result;
1123 if (win32_channel->debug)
1124 g_print ("g_io_win32_fd_read: fd=%d count=%d\n",
1125 win32_channel->fd, count);
1127 if (win32_channel->thread_id)
1129 return buffer_read (win32_channel, buf, count, bytes_read, err);
1132 result = read (win32_channel->fd, buf, count);
1134 if (win32_channel->debug)
1135 g_print ("g_io_win32_fd_read: read() => %d\n", result);
1137 if (result < 0)
1139 *bytes_read = 0;
1141 switch (errno)
1143 #ifdef EAGAIN
1144 case EAGAIN:
1145 return G_IO_STATUS_AGAIN;
1146 #endif
1147 default:
1148 g_set_error (err, G_IO_CHANNEL_ERROR,
1149 g_io_channel_error_from_errno (errno),
1150 g_strerror (errno));
1151 return G_IO_STATUS_ERROR;
1155 *bytes_read = result;
1157 return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
1160 static GIOStatus
1161 g_io_win32_fd_write (GIOChannel *channel,
1162 const gchar *buf,
1163 gsize count,
1164 gsize *bytes_written,
1165 GError **err)
1167 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1168 gint result;
1170 if (win32_channel->thread_id)
1172 return buffer_write (win32_channel, buf, count, bytes_written, err);
1175 result = write (win32_channel->fd, buf, count);
1176 if (win32_channel->debug)
1177 g_print ("g_io_win32_fd_write: fd=%d count=%d => %d\n",
1178 win32_channel->fd, count, result);
1180 if (result < 0)
1182 *bytes_written = 0;
1184 switch (errno)
1186 #ifdef EAGAIN
1187 case EAGAIN:
1188 return G_IO_STATUS_AGAIN;
1189 #endif
1190 default:
1191 g_set_error (err, G_IO_CHANNEL_ERROR,
1192 g_io_channel_error_from_errno (errno),
1193 g_strerror (errno));
1194 return G_IO_STATUS_ERROR;
1198 *bytes_written = result;
1200 return G_IO_STATUS_NORMAL;
1203 static GIOStatus
1204 g_io_win32_fd_seek (GIOChannel *channel,
1205 gint64 offset,
1206 GSeekType type,
1207 GError **err)
1209 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1210 int whence;
1211 off_t tmp_offset;
1212 off_t result;
1214 switch (type)
1216 case G_SEEK_SET:
1217 whence = SEEK_SET;
1218 break;
1219 case G_SEEK_CUR:
1220 whence = SEEK_CUR;
1221 break;
1222 case G_SEEK_END:
1223 whence = SEEK_END;
1224 break;
1225 default:
1226 whence = -1; /* Keep the compiler quiet */
1227 g_assert_not_reached ();
1228 abort ();
1231 tmp_offset = offset;
1232 if (tmp_offset != offset)
1234 g_set_error (err, G_IO_CHANNEL_ERROR,
1235 g_io_channel_error_from_errno (EINVAL),
1236 g_strerror (EINVAL));
1237 return G_IO_STATUS_ERROR;
1240 result = lseek (win32_channel->fd, tmp_offset, whence);
1242 if (result < 0)
1244 g_set_error (err, G_IO_CHANNEL_ERROR,
1245 g_io_channel_error_from_errno (errno),
1246 g_strerror (errno));
1247 return G_IO_STATUS_ERROR;
1250 return G_IO_STATUS_NORMAL;
1253 static GIOStatus
1254 g_io_win32_fd_close (GIOChannel *channel,
1255 GError **err)
1257 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1259 if (win32_channel->debug)
1260 g_print ("thread %#x: closing fd %d\n",
1261 win32_channel->thread_id,
1262 win32_channel->fd);
1263 LOCK (win32_channel->mutex);
1264 if (win32_channel->running)
1266 if (win32_channel->debug)
1267 g_print ("thread %#x: running, marking fd %d for later close\n",
1268 win32_channel->thread_id, win32_channel->fd);
1269 win32_channel->running = FALSE;
1270 win32_channel->needs_close = TRUE;
1271 if (win32_channel->direction == 0)
1272 SetEvent (win32_channel->data_avail_event);
1273 else
1274 SetEvent (win32_channel->space_avail_event);
1276 else
1278 if (win32_channel->debug)
1279 g_print ("closing fd %d\n", win32_channel->fd);
1280 close (win32_channel->fd);
1281 if (win32_channel->debug)
1282 g_print ("closed fd %d, setting to -1\n",
1283 win32_channel->fd);
1284 win32_channel->fd = -1;
1286 UNLOCK (win32_channel->mutex);
1288 /* FIXME error detection? */
1290 return G_IO_STATUS_NORMAL;
1293 static GSource *
1294 g_io_win32_fd_create_watch (GIOChannel *channel,
1295 GIOCondition condition)
1297 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1298 GSource *source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
1299 GIOWin32Watch *watch = (GIOWin32Watch *)source;
1301 watch->channel = channel;
1302 g_io_channel_ref (channel);
1304 watch->condition = condition;
1306 if (win32_channel->data_avail_event == NULL)
1307 create_events (win32_channel);
1309 watch->pollfd.fd = (gint) win32_channel->data_avail_event;
1310 watch->pollfd.events = condition;
1312 if (win32_channel->debug)
1313 g_print ("g_io_win32_fd_create_watch: fd=%d condition={%s} handle=%#x\n",
1314 win32_channel->fd, condition_to_string (condition), watch->pollfd.fd);
1316 LOCK (win32_channel->mutex);
1317 if (win32_channel->thread_id == 0)
1319 if (condition & G_IO_IN)
1320 create_thread (win32_channel, condition, read_thread);
1321 else if (condition & G_IO_OUT)
1322 create_thread (win32_channel, condition, write_thread);
1325 g_source_add_poll (source, &watch->pollfd);
1326 UNLOCK (win32_channel->mutex);
1328 return source;
1331 static GIOStatus
1332 g_io_win32_sock_read (GIOChannel *channel,
1333 gchar *buf,
1334 gsize count,
1335 gsize *bytes_read,
1336 GError **err)
1338 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1339 gint result;
1340 GIOChannelError error;
1341 int winsock_error;
1343 if (win32_channel->debug)
1344 g_print ("g_io_win32_sock_read: sockfd=%d count=%d\n",
1345 win32_channel->fd, count);
1347 result = recv (win32_channel->fd, buf, count, 0);
1348 if (result == SOCKET_ERROR)
1349 winsock_error = WSAGetLastError ();
1351 if (win32_channel->debug)
1352 g_print ("g_io_win32_sock_read: recv=%d %s\n",
1353 result,
1354 (result == SOCKET_ERROR ? winsock_error_message (winsock_error) : ""));
1356 if (result == SOCKET_ERROR)
1358 *bytes_read = 0;
1360 switch (winsock_error)
1362 case WSAEINVAL:
1363 error = G_IO_CHANNEL_ERROR_INVAL;
1364 break;
1365 case WSAEWOULDBLOCK:
1366 return G_IO_STATUS_AGAIN;
1367 default:
1368 error = G_IO_CHANNEL_ERROR_FAILED;
1369 break;
1371 g_set_error (err, G_IO_CHANNEL_ERROR, error,
1372 winsock_error_message (winsock_error));
1373 return G_IO_STATUS_ERROR;
1375 else
1377 *bytes_read = result;
1378 if (result == 0)
1379 return G_IO_STATUS_EOF;
1380 else
1381 return G_IO_STATUS_NORMAL;
1385 static GIOStatus
1386 g_io_win32_sock_write (GIOChannel *channel,
1387 const gchar *buf,
1388 gsize count,
1389 gsize *bytes_written,
1390 GError **err)
1392 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1393 gint result;
1394 GIOChannelError error;
1395 int winsock_error;
1397 if (win32_channel->debug)
1398 g_print ("g_io_win32_sock_write: sockfd=%d count=%d\n",
1399 win32_channel->fd, count);
1401 result = send (win32_channel->fd, buf, count, 0);
1402 if (result == SOCKET_ERROR)
1403 winsock_error = WSAGetLastError ();
1405 if (win32_channel->debug)
1406 g_print ("g_io_win32_sock_write: send=%d %s\n",
1407 result,
1408 (result == SOCKET_ERROR ? winsock_error_message (winsock_error) : ""));
1410 if (result == SOCKET_ERROR)
1412 *bytes_written = 0;
1414 switch (winsock_error)
1416 case WSAEINVAL:
1417 error = G_IO_CHANNEL_ERROR_INVAL;
1418 break;
1419 case WSAEWOULDBLOCK:
1420 win32_channel->write_would_have_blocked = TRUE;
1421 win32_channel->last_events = 0;
1422 return G_IO_STATUS_AGAIN;
1423 default:
1424 error = G_IO_CHANNEL_ERROR_FAILED;
1425 break;
1427 g_set_error (err, G_IO_CHANNEL_ERROR, error,
1428 winsock_error_message (winsock_error));
1430 return G_IO_STATUS_ERROR;
1432 else
1434 *bytes_written = result;
1435 win32_channel->write_would_have_blocked = FALSE;
1437 return G_IO_STATUS_NORMAL;
1441 static GIOStatus
1442 g_io_win32_sock_close (GIOChannel *channel,
1443 GError **err)
1445 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1447 if (win32_channel->fd != -1)
1449 if (win32_channel->debug)
1450 g_print ("g_io_win32_sock_close: closing socket %d\n",
1451 win32_channel->fd);
1453 closesocket (win32_channel->fd);
1454 win32_channel->fd = -1;
1457 /* FIXME error detection? */
1459 return G_IO_STATUS_NORMAL;
1462 static GSource *
1463 g_io_win32_sock_create_watch (GIOChannel *channel,
1464 GIOCondition condition)
1466 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1467 GSource *source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
1468 GIOWin32Watch *watch = (GIOWin32Watch *)source;
1470 watch->channel = channel;
1471 g_io_channel_ref (channel);
1473 watch->condition = condition;
1475 if (win32_channel->event == 0)
1476 win32_channel->event = (int) WSACreateEvent ();
1478 watch->pollfd.fd = win32_channel->event;
1479 watch->pollfd.events = condition;
1481 if (win32_channel->debug)
1482 g_print ("g_io_win32_sock_create_watch: sock=%d handle=%#x condition={%s}\n",
1483 win32_channel->fd, watch->pollfd.fd,
1484 condition_to_string (watch->condition));
1486 g_source_add_poll (source, &watch->pollfd);
1488 return source;
1491 GIOChannel *
1492 g_io_channel_new_file (const gchar *filename,
1493 const gchar *mode,
1494 GError **error)
1496 int fid, flags, pmode;
1497 GIOChannel *channel;
1499 enum { /* Cheesy hack */
1500 MODE_R = 1 << 0,
1501 MODE_W = 1 << 1,
1502 MODE_A = 1 << 2,
1503 MODE_PLUS = 1 << 3,
1504 } mode_num;
1506 g_return_val_if_fail (filename != NULL, NULL);
1507 g_return_val_if_fail (mode != NULL, NULL);
1508 g_return_val_if_fail ((error == NULL) || (*error == NULL), NULL);
1510 switch (mode[0])
1512 case 'r':
1513 mode_num = MODE_R;
1514 break;
1515 case 'w':
1516 mode_num = MODE_W;
1517 break;
1518 case 'a':
1519 mode_num = MODE_A;
1520 break;
1521 default:
1522 g_warning ("Invalid GIOFileMode %s.\n", mode);
1523 return NULL;
1526 switch (mode[1])
1528 case '\0':
1529 break;
1530 case '+':
1531 if (mode[2] == '\0')
1533 mode_num |= MODE_PLUS;
1534 break;
1536 /* Fall through */
1537 default:
1538 g_warning ("Invalid GIOFileMode %s.\n", mode);
1539 return NULL;
1542 switch (mode_num)
1544 case MODE_R:
1545 flags = O_RDONLY;
1546 pmode = _S_IREAD;
1547 break;
1548 case MODE_W:
1549 flags = O_WRONLY | O_TRUNC | O_CREAT;
1550 pmode = _S_IWRITE;
1551 break;
1552 case MODE_A:
1553 flags = O_WRONLY | O_APPEND | O_CREAT;
1554 pmode = _S_IWRITE;
1555 break;
1556 case MODE_R | MODE_PLUS:
1557 flags = O_RDWR;
1558 pmode = _S_IREAD | _S_IWRITE;
1559 break;
1560 case MODE_W | MODE_PLUS:
1561 flags = O_RDWR | O_TRUNC | O_CREAT;
1562 pmode = _S_IREAD | _S_IWRITE;
1563 break;
1564 case MODE_A | MODE_PLUS:
1565 flags = O_RDWR | O_APPEND | O_CREAT;
1566 pmode = _S_IREAD | _S_IWRITE;
1567 break;
1568 default:
1569 g_assert_not_reached ();
1570 abort ();
1573 /* always open 'untranslated' */
1574 fid = g_open (filename, flags | _O_BINARY, pmode);
1576 if (g_io_win32_get_debug_flag ())
1578 g_print ("g_io_channel_win32_new_file: open(\"%s\", ", filename);
1579 g_win32_print_access_mode (flags|_O_BINARY);
1580 g_print (",%#o)=%d\n", pmode, fid);
1583 if (fid < 0)
1585 g_set_error (error, G_FILE_ERROR,
1586 g_file_error_from_errno (errno),
1587 g_strerror (errno));
1588 return (GIOChannel *)NULL;
1591 channel = g_io_channel_win32_new_fd (fid);
1593 /* XXX: move this to g_io_channel_win32_new_fd () */
1594 channel->close_on_unref = TRUE;
1595 channel->is_seekable = TRUE;
1597 /* g_io_channel_win32_new_fd sets is_readable and is_writeable to
1598 * correspond to actual readability/writeability. Set to FALSE those
1599 * that mode doesn't allow
1601 switch (mode_num)
1603 case MODE_R:
1604 channel->is_writeable = FALSE;
1605 break;
1606 case MODE_W:
1607 case MODE_A:
1608 channel->is_readable = FALSE;
1609 break;
1610 case MODE_R | MODE_PLUS:
1611 case MODE_W | MODE_PLUS:
1612 case MODE_A | MODE_PLUS:
1613 break;
1614 default:
1615 g_assert_not_reached ();
1616 abort ();
1619 return channel;
1622 #ifdef G_OS_WIN32
1624 #undef g_io_channel_new_file
1626 /* Binary compatibility version. Not for newly compiled code. */
1628 GIOChannel *
1629 g_io_channel_new_file (const gchar *filename,
1630 const gchar *mode,
1631 GError **error)
1633 gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, error);
1634 GIOChannel *retval;
1636 if (utf8_filename == NULL)
1637 return NULL;
1639 retval = g_io_channel_new_file_utf8 (utf8_filename, mode, error);
1641 g_free (utf8_filename);
1643 return retval;
1646 #endif
1648 static GIOStatus
1649 g_io_win32_unimpl_set_flags (GIOChannel *channel,
1650 GIOFlags flags,
1651 GError **err)
1653 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1655 if (win32_channel->debug)
1657 g_print ("g_io_win32_unimpl_set_flags: ");
1658 g_win32_print_gioflags (flags);
1659 g_print ("\n");
1662 g_set_error (err, G_IO_CHANNEL_ERROR,
1663 G_IO_CHANNEL_ERROR_FAILED,
1664 "Not implemented on Win32");
1666 return G_IO_STATUS_ERROR;
1669 static GIOFlags
1670 g_io_win32_fd_get_flags_internal (GIOChannel *channel,
1671 struct stat *st)
1673 GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
1674 gchar c;
1675 DWORD count;
1677 if (st->st_mode & _S_IFIFO)
1679 channel->is_readable =
1680 (PeekNamedPipe ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL, NULL) != 0) || GetLastError () == ERROR_BROKEN_PIPE;
1681 channel->is_writeable =
1682 (WriteFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
1683 channel->is_seekable = FALSE;
1685 else if (st->st_mode & _S_IFCHR)
1687 /* XXX Seems there is no way to find out the readability of file
1688 * handles to device files (consoles, mostly) without doing a
1689 * blocking read. So punt, say it's readable.
1691 channel->is_readable = TRUE;
1693 channel->is_writeable =
1694 (WriteFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
1696 /* XXX What about devices that actually *are* seekable? But
1697 * those would probably not be handled using the C runtime
1698 * anyway, but using Windows-specific code.
1700 channel->is_seekable = FALSE;
1702 else
1704 channel->is_readable =
1705 (ReadFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
1706 channel->is_writeable =
1707 (WriteFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
1708 channel->is_seekable = TRUE;
1711 /* XXX: G_IO_FLAG_APPEND */
1712 /* XXX: G_IO_FLAG_NONBLOCK */
1714 return 0;
1717 static GIOFlags
1718 g_io_win32_fd_get_flags (GIOChannel *channel)
1720 struct stat st;
1721 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1723 g_return_val_if_fail (win32_channel != NULL, 0);
1724 g_return_val_if_fail (win32_channel->type == G_IO_WIN32_FILE_DESC, 0);
1726 if (0 == fstat (win32_channel->fd, &st))
1727 return g_io_win32_fd_get_flags_internal (channel, &st);
1728 else
1729 return 0;
1732 static GIOFlags
1733 g_io_win32_msg_get_flags (GIOChannel *channel)
1735 return 0;
1738 static GIOStatus
1739 g_io_win32_sock_set_flags (GIOChannel *channel,
1740 GIOFlags flags,
1741 GError **err)
1743 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1744 u_long arg;
1746 if (win32_channel->debug)
1748 g_print ("g_io_win32_sock_set_flags: ");
1749 g_win32_print_gioflags (flags);
1750 g_print ("\n");
1753 if (flags & G_IO_FLAG_NONBLOCK)
1755 arg = 1;
1756 if (ioctlsocket (win32_channel->fd, FIONBIO, &arg) == SOCKET_ERROR)
1758 g_set_error (err, G_IO_CHANNEL_ERROR,
1759 G_IO_CHANNEL_ERROR_FAILED,
1760 winsock_error_message (WSAGetLastError ()));
1761 return G_IO_STATUS_ERROR;
1764 else
1766 arg = 0;
1767 if (ioctlsocket (win32_channel->fd, FIONBIO, &arg) == SOCKET_ERROR)
1769 g_set_error (err, G_IO_CHANNEL_ERROR,
1770 G_IO_CHANNEL_ERROR_FAILED,
1771 winsock_error_message (WSAGetLastError ()));
1772 return G_IO_STATUS_ERROR;
1776 return G_IO_STATUS_NORMAL;
1779 static GIOFlags
1780 g_io_win32_sock_get_flags (GIOChannel *channel)
1782 /* Could we do something here? */
1783 return 0;
1786 static GIOFuncs win32_channel_msg_funcs = {
1787 g_io_win32_msg_read,
1788 g_io_win32_msg_write,
1789 NULL,
1790 g_io_win32_msg_close,
1791 g_io_win32_msg_create_watch,
1792 g_io_win32_free,
1793 g_io_win32_unimpl_set_flags,
1794 g_io_win32_msg_get_flags,
1797 static GIOFuncs win32_channel_fd_funcs = {
1798 g_io_win32_fd_read,
1799 g_io_win32_fd_write,
1800 g_io_win32_fd_seek,
1801 g_io_win32_fd_close,
1802 g_io_win32_fd_create_watch,
1803 g_io_win32_free,
1804 g_io_win32_unimpl_set_flags,
1805 g_io_win32_fd_get_flags,
1808 static GIOFuncs win32_channel_sock_funcs = {
1809 g_io_win32_sock_read,
1810 g_io_win32_sock_write,
1811 NULL,
1812 g_io_win32_sock_close,
1813 g_io_win32_sock_create_watch,
1814 g_io_win32_free,
1815 g_io_win32_sock_set_flags,
1816 g_io_win32_sock_get_flags,
1819 GIOChannel *
1820 g_io_channel_win32_new_messages (guint hwnd)
1822 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1823 GIOChannel *channel = (GIOChannel *)win32_channel;
1825 g_io_channel_init (channel);
1826 g_io_channel_win32_init (win32_channel);
1827 if (win32_channel->debug)
1828 g_print ("g_io_channel_win32_new_messages: hwnd=%#x\n", hwnd);
1829 channel->funcs = &win32_channel_msg_funcs;
1830 win32_channel->type = G_IO_WIN32_WINDOWS_MESSAGES;
1831 win32_channel->hwnd = (HWND) hwnd;
1833 /* XXX: check this. */
1834 channel->is_readable = IsWindow (win32_channel->hwnd);
1835 channel->is_writeable = IsWindow (win32_channel->hwnd);
1837 channel->is_seekable = FALSE;
1839 return channel;
1842 static GIOChannel *
1843 g_io_channel_win32_new_fd_internal (gint fd,
1844 struct stat *st)
1846 GIOWin32Channel *win32_channel;
1847 GIOChannel *channel;
1849 win32_channel = g_new (GIOWin32Channel, 1);
1850 channel = (GIOChannel *)win32_channel;
1852 g_io_channel_init (channel);
1853 g_io_channel_win32_init (win32_channel);
1854 if (win32_channel->debug)
1855 g_print ("g_io_channel_win32_new_fd: %u\n", fd);
1856 channel->funcs = &win32_channel_fd_funcs;
1857 win32_channel->type = G_IO_WIN32_FILE_DESC;
1858 win32_channel->fd = fd;
1860 g_io_win32_fd_get_flags_internal (channel, st);
1862 return channel;
1865 GIOChannel *
1866 g_io_channel_win32_new_fd (gint fd)
1868 struct stat st;
1870 if (fstat (fd, &st) == -1)
1872 g_warning (G_STRLOC ": %d isn't a C library file descriptor", fd);
1873 return NULL;
1876 return g_io_channel_win32_new_fd_internal (fd, &st);
1879 gint
1880 g_io_channel_win32_get_fd (GIOChannel *channel)
1882 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1884 return win32_channel->fd;
1887 GIOChannel *
1888 g_io_channel_win32_new_socket (int socket)
1890 GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1891 GIOChannel *channel = (GIOChannel *)win32_channel;
1893 g_io_channel_init (channel);
1894 g_io_channel_win32_init (win32_channel);
1895 if (win32_channel->debug)
1896 g_print ("g_io_channel_win32_new_socket: sockfd=%d\n", socket);
1897 channel->funcs = &win32_channel_sock_funcs;
1898 win32_channel->type = G_IO_WIN32_SOCKET;
1899 win32_channel->fd = socket;
1901 channel->is_readable = TRUE;
1902 channel->is_writeable = TRUE;
1903 channel->is_seekable = FALSE;
1905 return channel;
1908 GIOChannel *
1909 g_io_channel_unix_new (gint fd)
1911 gboolean is_fd, is_socket;
1912 struct stat st;
1913 int optval, optlen;
1915 is_fd = (fstat (fd, &st) == 0);
1917 optlen = sizeof (optval);
1918 is_socket = (getsockopt (fd, SOL_SOCKET, SO_TYPE, (char *) &optval, &optlen) != SOCKET_ERROR);
1920 if (is_fd && is_socket)
1921 g_warning (G_STRLOC ": %d is both a file descriptor and a socket, file descriptor interpretation assumed.", fd);
1923 if (is_fd)
1924 return g_io_channel_win32_new_fd_internal (fd, &st);
1926 if (is_socket)
1927 return g_io_channel_win32_new_socket(fd);
1929 g_warning (G_STRLOC ": %d is neither a file descriptor or a socket", fd);
1931 return NULL;
1934 gint
1935 g_io_channel_unix_get_fd (GIOChannel *channel)
1937 return g_io_channel_win32_get_fd (channel);
1940 void
1941 g_io_channel_win32_set_debug (GIOChannel *channel,
1942 gboolean flag)
1944 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1946 win32_channel->debug = flag;
1949 gint
1950 g_io_channel_win32_poll (GPollFD *fds,
1951 gint n_fds,
1952 gint timeout)
1954 int result;
1956 g_return_val_if_fail (n_fds >= 0, 0);
1958 result = (*g_main_context_get_poll_func (NULL)) (fds, n_fds, timeout);
1960 return result;
1963 void
1964 g_io_channel_win32_make_pollfd (GIOChannel *channel,
1965 GIOCondition condition,
1966 GPollFD *fd)
1968 GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1970 switch (win32_channel->type)
1972 case G_IO_WIN32_FILE_DESC:
1973 if (win32_channel->data_avail_event == NULL)
1974 create_events (win32_channel);
1976 fd->fd = (gint) win32_channel->data_avail_event;
1978 if (win32_channel->thread_id == 0 && (condition & G_IO_IN))
1980 if (condition & G_IO_IN)
1981 create_thread (win32_channel, condition, read_thread);
1982 else if (condition & G_IO_OUT)
1983 create_thread (win32_channel, condition, write_thread);
1985 break;
1987 case G_IO_WIN32_SOCKET:
1988 fd->fd = (int) WSACreateEvent ();
1989 break;
1991 case G_IO_WIN32_WINDOWS_MESSAGES:
1992 fd->fd = G_WIN32_MSG_HANDLE;
1993 break;
1995 default:
1996 g_assert_not_reached ();
1997 abort ();
2000 fd->events = condition;
2003 /* Binary compatibility */
2004 GIOChannel *
2005 g_io_channel_win32_new_stream_socket (int socket)
2007 return g_io_channel_win32_new_socket (socket);
2010 #define __G_IO_WIN32_C__
2011 #include "galiasdef.c"