• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
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
8  *
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.1 of the License, or (at your option) any later version.
13  *
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.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 /*
24  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
25  * file for a list of people on the GLib Team.  See the ChangeLog
26  * files for a list of changes.  These files are distributed with
27  * GLib at ftp://ftp.gtk.org/pub/gtk/.
28  */
29 
30 /*
31  * Bugs that are related to the code in this file:
32  *
33  * Bug 137968 - Sometimes a GIOFunc on Win32 is called with zero condition
34  * http://bugzilla.gnome.org/show_bug.cgi?id=137968
35  *
36  * Bug 324234 - Using g_io_add_watch_full() to wait for connect() to return on a non-blocking socket returns prematurely
37  * http://bugzilla.gnome.org/show_bug.cgi?id=324234
38  *
39  * Bug 331214 - g_io_channel async socket io stalls
40  * http://bugzilla.gnome.org/show_bug.cgi?id=331214
41  *
42  * Bug 338943 - Multiple watches on the same socket
43  * http://bugzilla.gnome.org/show_bug.cgi?id=338943
44  *
45  * Bug 357674 - 2 serious bugs in giowin32.c making glib iochannels useless
46  * http://bugzilla.gnome.org/show_bug.cgi?id=357674
47  *
48  * Bug 425156 - GIOChannel deadlocks on a win32 socket
49  * http://bugzilla.gnome.org/show_bug.cgi?id=425156
50  *
51  * Bug 468910 - giofunc condition=0
52  * http://bugzilla.gnome.org/show_bug.cgi?id=468910
53  *
54  * Bug 500246 - Bug fixes for giowin32
55  * http://bugzilla.gnome.org/show_bug.cgi?id=500246
56  *
57  * Bug 548278 - Async GETs connections are always terminated unexpectedly on windows
58  * http://bugzilla.gnome.org/show_bug.cgi?id=548278
59  *
60  * Bug 548536 - giowin32 problem when adding and removing watches
61  * http://bugzilla.gnome.org/show_bug.cgi?id=548536
62  *
63  * When fixing bugs related to the code in this file, either the above
64  * bugs or others, make sure that the test programs attached to the
65  * above bugs continue to work.
66  */
67 
68 #include "config.h"
69 
70 #include "glib.h"
71 
72 #include <stdlib.h>
73 #include <winsock2.h>
74 #include <windows.h>
75 #include <conio.h>
76 #include <fcntl.h>
77 #include <io.h>
78 #include <process.h>
79 #include <errno.h>
80 #include <sys/stat.h>
81 
82 #include "gstdio.h"
83 #include "glibintl.h"
84 
85 
86 typedef struct _GIOWin32Channel GIOWin32Channel;
87 typedef struct _GIOWin32Watch GIOWin32Watch;
88 
89 #define BUFFER_SIZE 4096
90 
91 typedef enum {
92   G_IO_WIN32_WINDOWS_MESSAGES,	/* Windows messages */
93 
94   G_IO_WIN32_FILE_DESC,		/* Unix-like file descriptors from
95 				 * _open() or _pipe(), except for
96 				 * console IO. Separate thread to read
97 				 * or write.
98 				 */
99 
100   G_IO_WIN32_CONSOLE,		/* Console IO (usually stdin, stdout, stderr) */
101 
102   G_IO_WIN32_SOCKET		/* Sockets. No separate thread. */
103 } GIOWin32ChannelType;
104 
105 struct _GIOWin32Channel {
106   GIOChannel channel;
107   gint fd;			/* Either a Unix-like file handle as provided
108 				 * by the Microsoft C runtime, or a SOCKET
109 				 * as provided by WinSock.
110 				 */
111   GIOWin32ChannelType type;
112 
113   gboolean debug;
114 
115   /* Field used by G_IO_WIN32_WINDOWS_MESSAGES channels */
116   HWND hwnd;			/* Handle of window, or NULL */
117 
118   /* Fields used by G_IO_WIN32_FILE_DESC channels. */
119   CRITICAL_SECTION mutex;
120 
121   int direction;		/* 0 means we read from it,
122 				 * 1 means we write to it.
123 				 */
124 
125   gboolean running;		/* Is reader or writer thread
126 				 * running. FALSE if EOF has been
127 				 * reached by the reader thread.
128 				 */
129 
130   gboolean needs_close;		/* If the channel has been closed while
131 				 * the reader thread was still running.
132 				 */
133 
134   guint thread_id;		/* If non-NULL the channel has or has
135 				 * had a reader or writer thread.
136 				 */
137   HANDLE data_avail_event;
138 
139   gushort revents;
140 
141   /* Data is kept in a circular buffer. To be able to distinguish between
142    * empty and full buffers, we cannot fill it completely, but have to
143    * leave a one character gap.
144    *
145    * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
146    *
147    * Empty:    wrp == rdp
148    * Full:     (wrp + 1) % BUFFER_SIZE == rdp
149    * Partial:  otherwise
150    */
151   guchar *buffer;		/* (Circular) buffer */
152   gint wrp, rdp;		/* Buffer indices for writing and reading */
153   HANDLE space_avail_event;
154 
155   /* Fields used by G_IO_WIN32_SOCKET channels */
156   int event_mask;
157   int last_events;
158   HANDLE event;
159   gboolean write_would_have_blocked;
160   gboolean ever_writable;
161 };
162 
163 struct _GIOWin32Watch {
164   GSource       source;
165   GPollFD       pollfd;
166   GIOChannel   *channel;
167   GIOCondition  condition;
168 };
169 
170 static void
g_win32_print_access_mode(int flags)171 g_win32_print_access_mode (int flags)
172 {
173   g_print ("%s%s%s%s%s%s%s%s%s%s",
174 	   ((flags & 0x3) == _O_RDWR ? "O_RDWR" :
175 	    ((flags & 0x3) == _O_RDONLY ? "O_RDONLY" :
176 	     ((flags & 0x3) == _O_WRONLY ? "O_WRONLY" : "0"))),
177 	   (flags & _O_APPEND ? "|O_APPEND" : ""),
178 	   (flags & _O_RANDOM ? "|O_RANDOM" : ""),
179 	   (flags & _O_SEQUENTIAL ? "|O_SEQUENTIAL" : ""),
180 	   (flags & _O_TEMPORARY ? "|O_TEMPORARY" : ""),
181 	   (flags & _O_CREAT ? "|O_CREAT" : ""),
182 	   (flags & _O_TRUNC ? "|O_TRUNC" : ""),
183 	   (flags & _O_EXCL ? "|O_EXCL" : ""),
184 	   (flags & _O_TEXT ? "|O_TEXT" : ""),
185 	   (flags & _O_BINARY ? "|O_BINARY" : ""));
186 }
187 
188 static void
g_win32_print_gioflags(GIOFlags flags)189 g_win32_print_gioflags (GIOFlags flags)
190 {
191   char *bar = "";
192 
193   if (flags & G_IO_FLAG_APPEND)
194     bar = "|", g_print ("APPEND");
195   if (flags & G_IO_FLAG_NONBLOCK)
196     g_print ("%sNONBLOCK", bar), bar = "|";
197   if (flags & G_IO_FLAG_IS_READABLE)
198     g_print ("%sREADABLE", bar), bar = "|";
199   if (flags & G_IO_FLAG_IS_WRITABLE)
200     g_print ("%sWRITABLE", bar), bar = "|";
201   if (flags & G_IO_FLAG_IS_SEEKABLE)
202     g_print ("%sSEEKABLE", bar), bar = "|";
203 }
204 
205 static const char *
event_mask_to_string(int mask)206 event_mask_to_string (int mask)
207 {
208   char buf[100];
209   int checked_bits = 0;
210   char *bufp = buf;
211 
212   if (mask == 0)
213     return "";
214 
215 #define BIT(n) checked_bits |= FD_##n; if (mask & FD_##n) bufp += sprintf (bufp, "%s" #n, (bufp>buf ? "|" : ""))
216 
217   BIT (READ);
218   BIT (WRITE);
219   BIT (OOB);
220   BIT (ACCEPT);
221   BIT (CONNECT);
222   BIT (CLOSE);
223   BIT (QOS);
224   BIT (GROUP_QOS);
225   BIT (ROUTING_INTERFACE_CHANGE);
226   BIT (ADDRESS_LIST_CHANGE);
227 
228 #undef BIT
229 
230   if ((mask & ~checked_bits) != 0)
231 	  bufp += sprintf (bufp, "|%#x", mask & ~checked_bits);
232 
233   return g_quark_to_string (g_quark_from_string (buf));
234 }
235 
236 static const char *
condition_to_string(GIOCondition condition)237 condition_to_string (GIOCondition condition)
238 {
239   char buf[100];
240   int checked_bits = 0;
241   char *bufp = buf;
242 
243   if (condition == 0)
244     return "";
245 
246 #define BIT(n) checked_bits |= G_IO_##n; if (condition & G_IO_##n) bufp += sprintf (bufp, "%s" #n, (bufp>buf ? "|" : ""))
247 
248   BIT (IN);
249   BIT (OUT);
250   BIT (PRI);
251   BIT (ERR);
252   BIT (HUP);
253   BIT (NVAL);
254 
255 #undef BIT
256 
257   if ((condition & ~checked_bits) != 0)
258 	  bufp += sprintf (bufp, "|%#x", condition & ~checked_bits);
259 
260   return g_quark_to_string (g_quark_from_string (buf));
261 }
262 
263 static gboolean
g_io_win32_get_debug_flag(void)264 g_io_win32_get_debug_flag (void)
265 {
266   return (g_getenv ("G_IO_WIN32_DEBUG") != NULL);
267 }
268 
269 static void
g_io_channel_win32_init(GIOWin32Channel * channel)270 g_io_channel_win32_init (GIOWin32Channel *channel)
271 {
272   channel->debug = g_io_win32_get_debug_flag ();
273 
274   InitializeCriticalSection (&channel->mutex);
275   channel->running = FALSE;
276   channel->needs_close = FALSE;
277   channel->thread_id = 0;
278   channel->data_avail_event = NULL;
279   channel->revents = 0;
280   channel->buffer = NULL;
281   channel->space_avail_event = NULL;
282 
283   channel->event_mask = 0;
284   channel->last_events = 0;
285   channel->event = NULL;
286   channel->write_would_have_blocked = FALSE;
287   channel->ever_writable = FALSE;
288 }
289 
290 static void
create_events(GIOWin32Channel * channel)291 create_events (GIOWin32Channel *channel)
292 {
293   SECURITY_ATTRIBUTES sec_attrs;
294 
295   sec_attrs.nLength = sizeof (SECURITY_ATTRIBUTES);
296   sec_attrs.lpSecurityDescriptor = NULL;
297   sec_attrs.bInheritHandle = FALSE;
298 
299   /* The data available event is manual reset, the space available event
300    * is automatic reset.
301    */
302   if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
303       || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
304     {
305       gchar *emsg = g_win32_error_message (GetLastError ());
306 
307       g_error ("Error creating event: %s", emsg);
308       g_free (emsg);
309     }
310 }
311 
312 static unsigned __stdcall
read_thread(void * parameter)313 read_thread (void *parameter)
314 {
315   GIOWin32Channel *channel = parameter;
316   guchar *buffer;
317   gint nbytes;
318 
319   g_io_channel_ref ((GIOChannel *)channel);
320 
321   if (channel->debug)
322     g_print ("read_thread %#x: start fd=%d, data_avail=%p space_avail=%p\n",
323 	     channel->thread_id,
324 	     channel->fd,
325 	     channel->data_avail_event,
326 	     channel->space_avail_event);
327 
328   channel->direction = 0;
329   channel->buffer = g_malloc (BUFFER_SIZE);
330   channel->rdp = channel->wrp = 0;
331   channel->running = TRUE;
332 
333   SetEvent (channel->space_avail_event);
334 
335   EnterCriticalSection (&channel->mutex);
336   while (channel->running)
337     {
338       if (channel->debug)
339 	g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
340 		 channel->thread_id, channel->rdp, channel->wrp);
341       if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
342 	{
343 	  /* Buffer is full */
344 	  if (channel->debug)
345 	    g_print ("read_thread %#x: resetting space_avail\n",
346 		     channel->thread_id);
347 	  ResetEvent (channel->space_avail_event);
348 	  if (channel->debug)
349 	    g_print ("read_thread %#x: waiting for space\n",
350 		     channel->thread_id);
351 	  LeaveCriticalSection (&channel->mutex);
352 	  WaitForSingleObject (channel->space_avail_event, INFINITE);
353 	  EnterCriticalSection (&channel->mutex);
354 	  if (channel->debug)
355 	    g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
356 		     channel->thread_id, channel->rdp, channel->wrp);
357 	}
358 
359       buffer = channel->buffer + channel->wrp;
360 
361       /* Always leave at least one byte unused gap to be able to
362        * distinguish between the full and empty condition...
363        */
364       nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
365 		    BUFFER_SIZE - channel->wrp);
366 
367       if (channel->debug)
368 	g_print ("read_thread %#x: calling read() for %d bytes\n",
369 		 channel->thread_id, nbytes);
370 
371       LeaveCriticalSection (&channel->mutex);
372 
373       nbytes = read (channel->fd, buffer, nbytes);
374 
375       EnterCriticalSection (&channel->mutex);
376 
377       channel->revents = G_IO_IN;
378       if (nbytes == 0)
379 	channel->revents |= G_IO_HUP;
380       else if (nbytes < 0)
381 	channel->revents |= G_IO_ERR;
382 
383       if (channel->debug)
384 	g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
385 		 channel->thread_id, nbytes, channel->rdp, channel->wrp);
386 
387       if (nbytes <= 0)
388 	break;
389 
390       channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
391       if (channel->debug)
392 	g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
393 		 channel->thread_id, channel->rdp, channel->wrp);
394       SetEvent (channel->data_avail_event);
395     }
396 
397   channel->running = FALSE;
398   if (channel->needs_close)
399     {
400       if (channel->debug)
401 	g_print ("read_thread %#x: channel fd %d needs closing\n",
402 		 channel->thread_id, channel->fd);
403       close (channel->fd);
404       channel->fd = -1;
405     }
406 
407   if (channel->debug)
408     g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
409 	     channel->thread_id, channel->rdp, channel->wrp);
410   SetEvent (channel->data_avail_event);
411   LeaveCriticalSection (&channel->mutex);
412 
413   g_io_channel_unref ((GIOChannel *)channel);
414 
415   /* No need to call _endthreadex(), the actual thread starter routine
416    * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
417    * _endthreadex() for us.
418    */
419 
420   return 0;
421 }
422 
423 static unsigned __stdcall
write_thread(void * parameter)424 write_thread (void *parameter)
425 {
426   GIOWin32Channel *channel = parameter;
427   guchar *buffer;
428   gint nbytes;
429 
430   g_io_channel_ref ((GIOChannel *)channel);
431 
432   if (channel->debug)
433     g_print ("write_thread %#x: start fd=%d, data_avail=%p space_avail=%p\n",
434 	     channel->thread_id,
435 	     channel->fd,
436 	     channel->data_avail_event,
437 	     channel->space_avail_event);
438 
439   channel->direction = 1;
440   channel->buffer = g_malloc (BUFFER_SIZE);
441   channel->rdp = channel->wrp = 0;
442   channel->running = TRUE;
443 
444   SetEvent (channel->space_avail_event);
445 
446   /* We use the same event objects as for a reader thread, but with
447    * reversed meaning. So, space_avail is used if data is available
448    * for writing, and data_avail is used if space is available in the
449    * write buffer.
450    */
451 
452   EnterCriticalSection (&channel->mutex);
453   while (channel->running || channel->rdp != channel->wrp)
454     {
455       if (channel->debug)
456 	g_print ("write_thread %#x: rdp=%d, wrp=%d\n",
457 		 channel->thread_id, channel->rdp, channel->wrp);
458       if (channel->wrp == channel->rdp)
459 	{
460 	  /* Buffer is empty. */
461 	  if (channel->debug)
462 	    g_print ("write_thread %#x: resetting space_avail\n",
463 		     channel->thread_id);
464 	  ResetEvent (channel->space_avail_event);
465 	  if (channel->debug)
466 	    g_print ("write_thread %#x: waiting for data\n",
467 		     channel->thread_id);
468 	  channel->revents = G_IO_OUT;
469 	  SetEvent (channel->data_avail_event);
470 	  LeaveCriticalSection (&channel->mutex);
471 	  WaitForSingleObject (channel->space_avail_event, INFINITE);
472 
473 	  EnterCriticalSection (&channel->mutex);
474 	  if (channel->rdp == channel->wrp)
475 	    break;
476 
477 	  if (channel->debug)
478 	    g_print ("write_thread %#x: rdp=%d, wrp=%d\n",
479 		     channel->thread_id, channel->rdp, channel->wrp);
480 	}
481 
482       buffer = channel->buffer + channel->rdp;
483       if (channel->rdp < channel->wrp)
484 	nbytes = channel->wrp - channel->rdp;
485       else
486 	nbytes = BUFFER_SIZE - channel->rdp;
487 
488       if (channel->debug)
489 	g_print ("write_thread %#x: calling write() for %d bytes\n",
490 		 channel->thread_id, nbytes);
491 
492       LeaveCriticalSection (&channel->mutex);
493       nbytes = write (channel->fd, buffer, nbytes);
494       EnterCriticalSection (&channel->mutex);
495 
496       if (channel->debug)
497 	g_print ("write_thread %#x: write(%i) returned %d, rdp=%d, wrp=%d\n",
498 		 channel->thread_id, channel->fd, nbytes, channel->rdp, channel->wrp);
499 
500       channel->revents = 0;
501       if (nbytes > 0)
502 	channel->revents |= G_IO_OUT;
503       else if (nbytes <= 0)
504 	channel->revents |= G_IO_ERR;
505 
506       channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
507 
508       if (nbytes <= 0)
509 	break;
510 
511       if (channel->debug)
512 	g_print ("write_thread: setting data_avail for thread %#x\n",
513 		 channel->thread_id);
514       SetEvent (channel->data_avail_event);
515     }
516 
517   channel->running = FALSE;
518   if (channel->needs_close)
519     {
520       if (channel->debug)
521 	g_print ("write_thread %#x: channel fd %d needs closing\n",
522 		 channel->thread_id, channel->fd);
523       close (channel->fd);
524       channel->fd = -1;
525     }
526 
527   LeaveCriticalSection (&channel->mutex);
528 
529   g_io_channel_unref ((GIOChannel *)channel);
530 
531   return 0;
532 }
533 
534 static void
create_thread(GIOWin32Channel * channel,GIOCondition condition,unsigned (__stdcall * thread)(void * parameter))535 create_thread (GIOWin32Channel     *channel,
536 	       GIOCondition         condition,
537 	       unsigned (__stdcall *thread) (void *parameter))
538 {
539   HANDLE thread_handle;
540   int errsv;
541 
542   thread_handle = (HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
543 					   &channel->thread_id);
544   errsv = errno;
545   if (thread_handle == 0)
546     g_warning ("Error creating thread: %s.",
547 	       g_strerror (errsv));
548   else if (!CloseHandle (thread_handle))
549     {
550       gchar *emsg = g_win32_error_message (GetLastError ());
551 
552       g_warning ("Error closing thread handle: %s.", emsg);
553       g_free (emsg);
554     }
555 
556   WaitForSingleObject (channel->space_avail_event, INFINITE);
557 }
558 
559 static GIOStatus
buffer_read(GIOWin32Channel * channel,gchar * dest,gsize count,gsize * bytes_read,GError ** err)560 buffer_read (GIOWin32Channel *channel,
561 	     gchar           *dest,
562 	     gsize            count,
563 	     gsize           *bytes_read,
564 	     GError         **err)
565 {
566   guint nbytes;
567   guint left = count;
568 
569   EnterCriticalSection (&channel->mutex);
570   if (channel->debug)
571     g_print ("reading from thread %#x %" G_GSIZE_FORMAT " bytes, rdp=%d, wrp=%d\n",
572 	     channel->thread_id, count, channel->rdp, channel->wrp);
573 
574   if (channel->wrp == channel->rdp)
575     {
576       LeaveCriticalSection (&channel->mutex);
577       if (channel->debug)
578 	g_print ("waiting for data from thread %#x\n", channel->thread_id);
579       WaitForSingleObject (channel->data_avail_event, INFINITE);
580       if (channel->debug)
581 	g_print ("done waiting for data from thread %#x\n", channel->thread_id);
582       EnterCriticalSection (&channel->mutex);
583       if (channel->wrp == channel->rdp && !channel->running)
584 	{
585 	  if (channel->debug)
586 	    g_print ("wrp==rdp, !running\n");
587 	  LeaveCriticalSection (&channel->mutex);
588           *bytes_read = 0;
589 	  return G_IO_STATUS_EOF;
590 	}
591     }
592 
593   if (channel->rdp < channel->wrp)
594     nbytes = channel->wrp - channel->rdp;
595   else
596     nbytes = BUFFER_SIZE - channel->rdp;
597   LeaveCriticalSection (&channel->mutex);
598   nbytes = MIN (left, nbytes);
599   if (channel->debug)
600     g_print ("moving %d bytes from thread %#x\n",
601 	     nbytes, channel->thread_id);
602   memcpy (dest, channel->buffer + channel->rdp, nbytes);
603   dest += nbytes;
604   left -= nbytes;
605   EnterCriticalSection (&channel->mutex);
606   channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
607   if (channel->debug)
608     g_print ("setting space_avail for thread %#x\n", channel->thread_id);
609   SetEvent (channel->space_avail_event);
610   if (channel->debug)
611     g_print ("for thread %#x: rdp=%d, wrp=%d\n",
612 	     channel->thread_id, channel->rdp, channel->wrp);
613   if (channel->running && channel->wrp == channel->rdp)
614     {
615       if (channel->debug)
616 	g_print ("resetting data_avail of thread %#x\n",
617 		 channel->thread_id);
618       ResetEvent (channel->data_avail_event);
619     };
620   LeaveCriticalSection (&channel->mutex);
621 
622   /* We have no way to indicate any errors form the actual
623    * read() or recv() call in the reader thread. Should we have?
624    */
625   *bytes_read = count - left;
626   return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
627 }
628 
629 
630 static GIOStatus
buffer_write(GIOWin32Channel * channel,const gchar * dest,gsize count,gsize * bytes_written,GError ** err)631 buffer_write (GIOWin32Channel *channel,
632 	      const gchar     *dest,
633 	      gsize            count,
634 	      gsize           *bytes_written,
635 	      GError         **err)
636 {
637   guint nbytes;
638   guint left = count;
639 
640   EnterCriticalSection (&channel->mutex);
641   if (channel->debug)
642     g_print ("buffer_write: writing to thread %#x %" G_GSIZE_FORMAT " bytes, rdp=%d, wrp=%d\n",
643 	     channel->thread_id, count, channel->rdp, channel->wrp);
644 
645   if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
646     {
647       /* Buffer is full */
648       if (channel->debug)
649 	g_print ("buffer_write: tid %#x: resetting data_avail\n",
650 		 channel->thread_id);
651       ResetEvent (channel->data_avail_event);
652       if (channel->debug)
653 	g_print ("buffer_write: tid %#x: waiting for space\n",
654 		 channel->thread_id);
655       LeaveCriticalSection (&channel->mutex);
656       WaitForSingleObject (channel->data_avail_event, INFINITE);
657       EnterCriticalSection (&channel->mutex);
658       if (channel->debug)
659 	g_print ("buffer_write: tid %#x: rdp=%d, wrp=%d\n",
660 		 channel->thread_id, channel->rdp, channel->wrp);
661     }
662 
663   nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
664 		BUFFER_SIZE - channel->wrp);
665 
666   LeaveCriticalSection (&channel->mutex);
667   nbytes = MIN (left, nbytes);
668   if (channel->debug)
669     g_print ("buffer_write: tid %#x: writing %d bytes\n",
670 	     channel->thread_id, nbytes);
671   memcpy (channel->buffer + channel->wrp, dest, nbytes);
672   dest += nbytes;
673   left -= nbytes;
674   EnterCriticalSection (&channel->mutex);
675 
676   channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
677   if (channel->debug)
678     g_print ("buffer_write: tid %#x: rdp=%d, wrp=%d, setting space_avail\n",
679 	     channel->thread_id, channel->rdp, channel->wrp);
680   SetEvent (channel->space_avail_event);
681 
682   if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
683     {
684       /* Buffer is full */
685       if (channel->debug)
686 	g_print ("buffer_write: tid %#x: resetting data_avail\n",
687 		 channel->thread_id);
688       ResetEvent (channel->data_avail_event);
689     }
690 
691   LeaveCriticalSection (&channel->mutex);
692 
693   /* We have no way to indicate any errors form the actual
694    * write() call in the writer thread. Should we have?
695    */
696   *bytes_written = count - left;
697   return (*bytes_written > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
698 }
699 
700 
701 static gboolean
g_io_win32_prepare(GSource * source,gint * timeout)702 g_io_win32_prepare (GSource *source,
703 		    gint    *timeout)
704 {
705   GIOWin32Watch *watch = (GIOWin32Watch *)source;
706   GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
707   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
708   int event_mask;
709 
710   *timeout = -1;
711 
712   if (channel->debug)
713     g_print ("g_io_win32_prepare: source=%p channel=%p", source, channel);
714 
715   switch (channel->type)
716     {
717     case G_IO_WIN32_WINDOWS_MESSAGES:
718       if (channel->debug)
719 	g_print (" MSG");
720       break;
721 
722     case G_IO_WIN32_CONSOLE:
723       if (channel->debug)
724 	g_print (" CON");
725       break;
726 
727     case G_IO_WIN32_FILE_DESC:
728       if (channel->debug)
729 	g_print (" FD thread=%#x buffer_condition:{%s}"
730 		 "\n  watch->pollfd.events:{%s} watch->pollfd.revents:{%s} channel->revents:{%s}",
731 		 channel->thread_id, condition_to_string (buffer_condition),
732 		 condition_to_string (watch->pollfd.events),
733 		 condition_to_string (watch->pollfd.revents),
734 		 condition_to_string (channel->revents));
735 
736       EnterCriticalSection (&channel->mutex);
737       if (channel->running)
738 	{
739 	  if (channel->direction == 0 && channel->wrp == channel->rdp)
740 	    {
741 	      if (channel->debug)
742 		g_print ("\n  setting revents=0");
743 	      channel->revents = 0;
744 	    }
745 	}
746       else
747 	{
748 	  if (channel->direction == 1
749 	      && (channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
750 	    {
751 	      if (channel->debug)
752 		g_print ("\n setting revents=0");
753 	      channel->revents = 0;
754 	    }
755 	}
756       LeaveCriticalSection (&channel->mutex);
757       break;
758 
759     case G_IO_WIN32_SOCKET:
760       if (channel->debug)
761 	g_print (" SOCK");
762       event_mask = 0;
763       if (watch->condition & G_IO_IN)
764 	event_mask |= (FD_READ | FD_ACCEPT);
765       if (watch->condition & G_IO_OUT)
766 	event_mask |= (FD_WRITE | FD_CONNECT);
767       event_mask |= FD_CLOSE;
768 
769       if (channel->event_mask != event_mask)
770 	{
771 	  if (channel->debug)
772 	    g_print ("\n  WSAEventSelect(%d,%p,{%s})",
773 		     channel->fd, (HANDLE) watch->pollfd.fd,
774 		     event_mask_to_string (event_mask));
775 	  if (WSAEventSelect (channel->fd, (HANDLE) watch->pollfd.fd,
776 			      event_mask) == SOCKET_ERROR)
777 	    if (channel->debug)
778 	      {
779 		gchar *emsg = g_win32_error_message (WSAGetLastError ());
780 
781 		g_print (" failed: %s", emsg);
782 		g_free (emsg);
783 	      }
784 	  channel->event_mask = event_mask;
785 
786 	  if (channel->debug)
787 	    g_print ("\n  setting last_events=0");
788 	  channel->last_events = 0;
789 
790 	  if ((event_mask & FD_WRITE) &&
791 	      channel->ever_writable &&
792 	      !channel->write_would_have_blocked)
793 	    {
794 	      if (channel->debug)
795 		g_print (" WSASetEvent(%p)", (WSAEVENT) watch->pollfd.fd);
796 	      WSASetEvent ((WSAEVENT) watch->pollfd.fd);
797 	    }
798 	}
799       break;
800 
801     default:
802       g_assert_not_reached ();
803       g_abort ();
804     }
805   if (channel->debug)
806     g_print ("\n");
807 
808   return ((watch->condition & buffer_condition) == watch->condition);
809 }
810 
811 static gboolean
g_io_win32_check(GSource * source)812 g_io_win32_check (GSource *source)
813 {
814   MSG msg;
815   GIOWin32Watch *watch = (GIOWin32Watch *)source;
816   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
817   GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
818   WSANETWORKEVENTS events;
819 
820   if (channel->debug)
821     g_print ("g_io_win32_check: source=%p channel=%p", source, channel);
822 
823   switch (channel->type)
824     {
825     case G_IO_WIN32_WINDOWS_MESSAGES:
826       if (channel->debug)
827 	g_print (" MSG\n");
828       return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE));
829 
830     case G_IO_WIN32_FILE_DESC:
831       if (channel->debug)
832 	g_print (" FD thread=%#x buffer_condition=%s\n"
833 		 "  watch->pollfd.events={%s} watch->pollfd.revents={%s} channel->revents={%s}\n",
834 		 channel->thread_id, condition_to_string (buffer_condition),
835 		 condition_to_string (watch->pollfd.events),
836 		 condition_to_string (watch->pollfd.revents),
837 		 condition_to_string (channel->revents));
838 
839       watch->pollfd.revents = (watch->pollfd.events & channel->revents);
840 
841       return ((watch->pollfd.revents | buffer_condition) & watch->condition);
842 
843     case G_IO_WIN32_CONSOLE:
844       if (channel->debug)
845 	g_print (" CON\n");
846       if (watch->channel->is_writeable)
847 	return TRUE;
848       else if (watch->channel->is_readable)
849         {
850 	  INPUT_RECORD buffer;
851 	  DWORD n;
852 	  if (PeekConsoleInput ((HANDLE) watch->pollfd.fd, &buffer, 1, &n) &&
853 	      n == 1)
854 	    {
855 	      /* _kbhit() does quite complex processing to find out
856 	       * whether at least one of the key events pending corresponds
857 	       * to a "real" character that can be read.
858 	       */
859 	      if (_kbhit ())
860 		return TRUE;
861 
862 	      /* Discard all other kinds of events */
863 	      ReadConsoleInput ((HANDLE) watch->pollfd.fd, &buffer, 1, &n);
864 	    }
865         }
866       return FALSE;
867 
868     case G_IO_WIN32_SOCKET:
869       if (channel->debug)
870 	g_print (" SOCK");
871       if (channel->last_events & FD_WRITE)
872 	{
873 	  if (channel->debug)
874 	    g_print (" sock=%d event=%p last_events has FD_WRITE",
875 		     channel->fd, (HANDLE) watch->pollfd.fd);
876 	}
877       else
878 	{
879 	  WSAEnumNetworkEvents (channel->fd, 0, &events);
880 
881 	  if (channel->debug)
882 	    g_print ("\n  revents={%s} condition={%s}"
883 		     "\n  WSAEnumNetworkEvents(%d,0) sets events={%s}",
884 		     condition_to_string (watch->pollfd.revents),
885 		     condition_to_string (watch->condition),
886 		     channel->fd,
887 		     event_mask_to_string (events.lNetworkEvents));
888 
889 	  if (watch->pollfd.revents != 0 &&
890 	      events.lNetworkEvents == 0 &&
891 	      !(channel->event_mask & FD_WRITE))
892 	    {
893 	      channel->event_mask = 0;
894 	      if (channel->debug)
895 		g_print ("\n  WSAEventSelect(%d,%p,{})",
896 			 channel->fd, (HANDLE) watch->pollfd.fd);
897 	      WSAEventSelect (channel->fd, (HANDLE) watch->pollfd.fd, 0);
898 	      if (channel->debug)
899 		g_print ("  ResetEvent(%p)",
900 			 (HANDLE) watch->pollfd.fd);
901 	      ResetEvent ((HANDLE) watch->pollfd.fd);
902 	    }
903 	  else if (events.lNetworkEvents & FD_WRITE)
904 	    channel->ever_writable = TRUE;
905 	  channel->last_events = events.lNetworkEvents;
906 	}
907 
908       watch->pollfd.revents = 0;
909       if (channel->last_events & (FD_READ | FD_ACCEPT))
910 	watch->pollfd.revents |= G_IO_IN;
911 
912       if (channel->last_events & FD_WRITE)
913 	watch->pollfd.revents |= G_IO_OUT;
914       else
915 	{
916 	  /* We have called WSAEnumNetworkEvents() above but it didn't
917 	   * set FD_WRITE.
918 	   */
919 	  if (events.lNetworkEvents & FD_CONNECT)
920 	    {
921 	      if (events.iErrorCode[FD_CONNECT_BIT] == 0)
922 		watch->pollfd.revents |= G_IO_OUT;
923 	      else
924 		watch->pollfd.revents |= (G_IO_HUP | G_IO_ERR);
925 	    }
926 	  if (watch->pollfd.revents == 0 && (channel->last_events & (FD_CLOSE)))
927 	    watch->pollfd.revents |= G_IO_HUP;
928 	}
929 
930       /* Regardless of WSAEnumNetworkEvents() result, if watching for
931        * writability, and if we have ever got a FD_WRITE event, and
932        * unless last write would have blocked, set G_IO_OUT. But never
933        * set both G_IO_OUT and G_IO_HUP.
934        */
935       if (!(watch->pollfd.revents & G_IO_HUP) &&
936 	  channel->ever_writable &&
937 	  !channel->write_would_have_blocked &&
938 	  (channel->event_mask & FD_WRITE))
939 	watch->pollfd.revents |= G_IO_OUT;
940 
941       if (channel->debug)
942 	g_print ("\n  revents={%s} retval={%s}\n",
943 		 condition_to_string (watch->pollfd.revents),
944 		 condition_to_string ((watch->pollfd.revents | buffer_condition) & watch->condition));
945 
946       return ((watch->pollfd.revents | buffer_condition) & watch->condition);
947 
948     default:
949       g_assert_not_reached ();
950       g_abort ();
951     }
952 }
953 
954 static gboolean
g_io_win32_dispatch(GSource * source,GSourceFunc callback,gpointer user_data)955 g_io_win32_dispatch (GSource     *source,
956 		     GSourceFunc  callback,
957 		     gpointer     user_data)
958 {
959   GIOFunc func = (GIOFunc)callback;
960   GIOWin32Watch *watch = (GIOWin32Watch *)source;
961   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
962   GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
963 
964   if (!func)
965     {
966       g_warning ("IO Watch dispatched without callback. "
967 		 "You must call g_source_connect().");
968       return FALSE;
969     }
970 
971   if (channel->debug)
972     g_print ("g_io_win32_dispatch: pollfd.revents=%s condition=%s result=%s\n",
973 	     condition_to_string (watch->pollfd.revents),
974 	     condition_to_string (watch->condition),
975 	     condition_to_string ((watch->pollfd.revents | buffer_condition) & watch->condition));
976 
977   return (*func) (watch->channel,
978 		  (watch->pollfd.revents | buffer_condition) & watch->condition,
979 		  user_data);
980 }
981 
982 static void
g_io_win32_finalize(GSource * source)983 g_io_win32_finalize (GSource *source)
984 {
985   GIOWin32Watch *watch = (GIOWin32Watch *)source;
986   GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
987 
988   if (channel->debug)
989     g_print ("g_io_win32_finalize: source=%p channel=%p", source, channel);
990 
991   switch (channel->type)
992     {
993     case G_IO_WIN32_WINDOWS_MESSAGES:
994       if (channel->debug)
995 	g_print (" MSG");
996       break;
997 
998     case G_IO_WIN32_CONSOLE:
999       if (channel->debug)
1000 	g_print (" CON");
1001       break;
1002 
1003     case G_IO_WIN32_FILE_DESC:
1004       if (channel->debug)
1005 	g_print (" FD thread=%#x", channel->thread_id);
1006       break;
1007 
1008     case G_IO_WIN32_SOCKET:
1009       if (channel->debug)
1010 	g_print (" SOCK sock=%d", channel->fd);
1011       break;
1012 
1013     default:
1014       g_assert_not_reached ();
1015       g_abort ();
1016     }
1017   if (channel->debug)
1018     g_print ("\n");
1019   g_io_channel_unref (watch->channel);
1020 }
1021 
1022 GSourceFuncs g_io_watch_funcs = {
1023   g_io_win32_prepare,
1024   g_io_win32_check,
1025   g_io_win32_dispatch,
1026   g_io_win32_finalize
1027 };
1028 
1029 static GIOStatus
g_io_win32_msg_read(GIOChannel * channel,gchar * buf,gsize count,gsize * bytes_read,GError ** err)1030 g_io_win32_msg_read (GIOChannel *channel,
1031 		     gchar      *buf,
1032 		     gsize       count,
1033 		     gsize      *bytes_read,
1034 		     GError    **err)
1035 {
1036   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1037   MSG msg;               /* In case of alignment problems */
1038 
1039   *bytes_read = 0;
1040 
1041   if (count < sizeof (MSG))
1042     {
1043       g_set_error_literal (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
1044                            "Incorrect message size"); /* Informative enough error message? */
1045       return G_IO_STATUS_ERROR;
1046     }
1047 
1048   if (win32_channel->debug)
1049     g_print ("g_io_win32_msg_read: channel=%p hwnd=%p\n",
1050 	     channel, win32_channel->hwnd);
1051   if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
1052     return G_IO_STATUS_AGAIN;
1053 
1054   memmove (buf, &msg, sizeof (MSG));
1055   *bytes_read = sizeof (MSG);
1056 
1057   return G_IO_STATUS_NORMAL;
1058 }
1059 
1060 static GIOStatus
g_io_win32_msg_write(GIOChannel * channel,const gchar * buf,gsize count,gsize * bytes_written,GError ** err)1061 g_io_win32_msg_write (GIOChannel  *channel,
1062 		      const gchar *buf,
1063 		      gsize        count,
1064 		      gsize       *bytes_written,
1065 		      GError     **err)
1066 {
1067   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1068   MSG msg;
1069 
1070   *bytes_written = 0;
1071 
1072   if (count != sizeof (MSG))
1073     {
1074       g_set_error_literal (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
1075                            "Incorrect message size"); /* Informative enough error message? */
1076       return G_IO_STATUS_ERROR;
1077     }
1078 
1079   /* In case of alignment problems */
1080   memmove (&msg, buf, sizeof (MSG));
1081   if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
1082     {
1083       gchar *emsg = g_win32_error_message (GetLastError ());
1084 
1085       g_set_error_literal (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED, emsg);
1086       g_free (emsg);
1087 
1088       return G_IO_STATUS_ERROR;
1089     }
1090 
1091   *bytes_written = sizeof (MSG);
1092 
1093   return G_IO_STATUS_NORMAL;
1094 }
1095 
1096 static GIOStatus
g_io_win32_msg_close(GIOChannel * channel,GError ** err)1097 g_io_win32_msg_close (GIOChannel *channel,
1098 		      GError    **err)
1099 {
1100   /* Nothing to be done. Or should we set hwnd to some invalid value? */
1101 
1102   return G_IO_STATUS_NORMAL;
1103 }
1104 
1105 static void
g_io_win32_free(GIOChannel * channel)1106 g_io_win32_free (GIOChannel *channel)
1107 {
1108   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1109 
1110   if (win32_channel->debug)
1111     g_print ("g_io_win32_free channel=%p fd=%d\n", channel, win32_channel->fd);
1112 
1113   DeleteCriticalSection (&win32_channel->mutex);
1114 
1115   if (win32_channel->data_avail_event)
1116     if (!CloseHandle (win32_channel->data_avail_event))
1117       if (win32_channel->debug)
1118 	{
1119 	  gchar *emsg = g_win32_error_message (GetLastError ());
1120 
1121 	  g_print ("  CloseHandle(%p) failed: %s\n",
1122 		   win32_channel->data_avail_event, emsg);
1123 	  g_free (emsg);
1124 	}
1125 
1126   g_free (win32_channel->buffer);
1127 
1128   if (win32_channel->space_avail_event)
1129     if (!CloseHandle (win32_channel->space_avail_event))
1130       if (win32_channel->debug)
1131 	{
1132 	  gchar *emsg = g_win32_error_message (GetLastError ());
1133 
1134 	  g_print ("  CloseHandle(%p) failed: %s\n",
1135 		   win32_channel->space_avail_event, emsg);
1136 	  g_free (emsg);
1137 	}
1138 
1139   if (win32_channel->type == G_IO_WIN32_SOCKET &&
1140       win32_channel->fd != -1)
1141     if (WSAEventSelect (win32_channel->fd, NULL, 0) == SOCKET_ERROR)
1142       if (win32_channel->debug)
1143 	{
1144 	  gchar *emsg = g_win32_error_message (WSAGetLastError ());
1145 
1146 	  g_print ("  WSAEventSelect(%d,NULL,{}) failed: %s\n",
1147 		   win32_channel->fd, emsg);
1148 	  g_free (emsg);
1149 	}
1150 
1151   if (win32_channel->event)
1152     if (!WSACloseEvent (win32_channel->event))
1153       if (win32_channel->debug)
1154 	{
1155 	  gchar *emsg = g_win32_error_message (WSAGetLastError ());
1156 
1157 	  g_print ("  WSACloseEvent(%p) failed: %s\n",
1158 		   win32_channel->event, emsg);
1159 	  g_free (emsg);
1160 	}
1161 
1162   g_free (win32_channel);
1163 }
1164 
1165 static GSource *
g_io_win32_msg_create_watch(GIOChannel * channel,GIOCondition condition)1166 g_io_win32_msg_create_watch (GIOChannel   *channel,
1167 			     GIOCondition  condition)
1168 {
1169   GIOWin32Watch *watch;
1170   GSource *source;
1171 
1172   source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
1173   g_source_set_name (source, "GIOChannel (Win32)");
1174   watch = (GIOWin32Watch *)source;
1175 
1176   watch->channel = channel;
1177   g_io_channel_ref (channel);
1178 
1179   watch->condition = condition;
1180 
1181   watch->pollfd.fd = (gintptr) G_WIN32_MSG_HANDLE;
1182   watch->pollfd.events = condition;
1183 
1184   g_source_add_poll (source, &watch->pollfd);
1185 
1186   return source;
1187 }
1188 
1189 static GIOStatus
g_io_win32_fd_and_console_read(GIOChannel * channel,gchar * buf,gsize count,gsize * bytes_read,GError ** err)1190 g_io_win32_fd_and_console_read (GIOChannel *channel,
1191 				gchar      *buf,
1192 				gsize       count,
1193 				gsize      *bytes_read,
1194 				GError    **err)
1195 {
1196   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1197   gint result;
1198   int errsv;
1199 
1200   if (win32_channel->debug)
1201     g_print ("g_io_win32_fd_read: fd=%d count=%" G_GSIZE_FORMAT "\n",
1202 	     win32_channel->fd, count);
1203 
1204   if (win32_channel->thread_id)
1205     {
1206       return buffer_read (win32_channel, buf, count, bytes_read, err);
1207     }
1208 
1209   result = read (win32_channel->fd, buf, count);
1210   errsv = errno;
1211 
1212   if (win32_channel->debug)
1213     g_print ("g_io_win32_fd_read: read() => %d\n", result);
1214 
1215   if (result < 0)
1216     {
1217       *bytes_read = 0;
1218 
1219       switch (errsv)
1220         {
1221 #ifdef EAGAIN
1222 	case EAGAIN:
1223 	  return G_IO_STATUS_AGAIN;
1224 #endif
1225 	default:
1226 	  g_set_error_literal (err, G_IO_CHANNEL_ERROR,
1227                                g_io_channel_error_from_errno (errsv),
1228                                g_strerror (errsv));
1229 	  return G_IO_STATUS_ERROR;
1230         }
1231     }
1232 
1233   *bytes_read = result;
1234 
1235   return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
1236 }
1237 
1238 static GIOStatus
g_io_win32_fd_and_console_write(GIOChannel * channel,const gchar * buf,gsize count,gsize * bytes_written,GError ** err)1239 g_io_win32_fd_and_console_write (GIOChannel  *channel,
1240 				 const gchar *buf,
1241 				 gsize        count,
1242 				 gsize       *bytes_written,
1243 				 GError     **err)
1244 {
1245   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1246   gint result;
1247   int errsv;
1248 
1249   if (win32_channel->thread_id)
1250     {
1251       return buffer_write (win32_channel, buf, count, bytes_written, err);
1252     }
1253 
1254   result = write (win32_channel->fd, buf, count);
1255   errsv = errno;
1256 
1257   if (win32_channel->debug)
1258     g_print ("g_io_win32_fd_write: fd=%d count=%" G_GSIZE_FORMAT " => %d\n",
1259 	     win32_channel->fd, count, result);
1260 
1261   if (result < 0)
1262     {
1263       *bytes_written = 0;
1264 
1265       switch (errsv)
1266         {
1267 #ifdef EAGAIN
1268 	case EAGAIN:
1269 	  return G_IO_STATUS_AGAIN;
1270 #endif
1271 	default:
1272 	  g_set_error_literal (err, G_IO_CHANNEL_ERROR,
1273                                g_io_channel_error_from_errno (errsv),
1274                                g_strerror (errsv));
1275 	  return G_IO_STATUS_ERROR;
1276         }
1277     }
1278 
1279   *bytes_written = result;
1280 
1281   return G_IO_STATUS_NORMAL;
1282 }
1283 
1284 static GIOStatus
g_io_win32_fd_seek(GIOChannel * channel,gint64 offset,GSeekType type,GError ** err)1285 g_io_win32_fd_seek (GIOChannel *channel,
1286 		    gint64      offset,
1287 		    GSeekType   type,
1288 		    GError    **err)
1289 {
1290   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1291   int whence, errsv;
1292   off_t tmp_offset;
1293   off_t result;
1294 
1295   switch (type)
1296     {
1297     case G_SEEK_SET:
1298       whence = SEEK_SET;
1299       break;
1300     case G_SEEK_CUR:
1301       whence = SEEK_CUR;
1302       break;
1303     case G_SEEK_END:
1304       whence = SEEK_END;
1305       break;
1306     default:
1307       whence = -1; /* Keep the compiler quiet */
1308       g_assert_not_reached ();
1309       g_abort ();
1310     }
1311 
1312   tmp_offset = offset;
1313   if (tmp_offset != offset)
1314     {
1315       g_set_error_literal (err, G_IO_CHANNEL_ERROR,
1316                            g_io_channel_error_from_errno (EINVAL),
1317                            g_strerror (EINVAL));
1318       return G_IO_STATUS_ERROR;
1319     }
1320 
1321   result = lseek (win32_channel->fd, tmp_offset, whence);
1322   errsv = errno;
1323 
1324   if (result < 0)
1325     {
1326       g_set_error_literal (err, G_IO_CHANNEL_ERROR,
1327                            g_io_channel_error_from_errno (errsv),
1328                            g_strerror (errsv));
1329       return G_IO_STATUS_ERROR;
1330     }
1331 
1332   return G_IO_STATUS_NORMAL;
1333 }
1334 
1335 static GIOStatus
g_io_win32_fd_close(GIOChannel * channel,GError ** err)1336 g_io_win32_fd_close (GIOChannel *channel,
1337 	             GError    **err)
1338 {
1339   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1340 
1341   if (win32_channel->debug)
1342     g_print ("g_io_win32_fd_close: thread=%#x: fd=%d\n",
1343 	     win32_channel->thread_id,
1344 	     win32_channel->fd);
1345   EnterCriticalSection (&win32_channel->mutex);
1346   if (win32_channel->running)
1347     {
1348       if (win32_channel->debug)
1349 	g_print ("thread %#x: running, marking fd %d for later close\n",
1350 		 win32_channel->thread_id, win32_channel->fd);
1351       win32_channel->running = FALSE;
1352       win32_channel->needs_close = TRUE;
1353       if (win32_channel->direction == 0)
1354 	SetEvent (win32_channel->data_avail_event);
1355       else
1356 	SetEvent (win32_channel->space_avail_event);
1357     }
1358   else
1359     {
1360       if (win32_channel->debug)
1361 	g_print ("closing fd %d\n", win32_channel->fd);
1362       close (win32_channel->fd);
1363       if (win32_channel->debug)
1364 	g_print ("closed fd %d, setting to -1\n",
1365 		 win32_channel->fd);
1366       win32_channel->fd = -1;
1367     }
1368   LeaveCriticalSection (&win32_channel->mutex);
1369 
1370   /* FIXME error detection? */
1371 
1372   return G_IO_STATUS_NORMAL;
1373 }
1374 
1375 static GSource *
g_io_win32_fd_create_watch(GIOChannel * channel,GIOCondition condition)1376 g_io_win32_fd_create_watch (GIOChannel    *channel,
1377 			    GIOCondition   condition)
1378 {
1379   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1380   GSource *source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
1381   GIOWin32Watch *watch = (GIOWin32Watch *)source;
1382 
1383   watch->channel = channel;
1384   g_io_channel_ref (channel);
1385 
1386   watch->condition = condition;
1387 
1388   if (win32_channel->data_avail_event == NULL)
1389     create_events (win32_channel);
1390 
1391   watch->pollfd.fd = (gintptr) win32_channel->data_avail_event;
1392   watch->pollfd.events = condition;
1393 
1394   if (win32_channel->debug)
1395     g_print ("g_io_win32_fd_create_watch: channel=%p fd=%d condition={%s} event=%p\n",
1396 	     channel, win32_channel->fd,
1397 	     condition_to_string (condition), (HANDLE) watch->pollfd.fd);
1398 
1399   EnterCriticalSection (&win32_channel->mutex);
1400   if (win32_channel->thread_id == 0)
1401     {
1402       if (condition & G_IO_IN)
1403 	create_thread (win32_channel, condition, read_thread);
1404       else if (condition & G_IO_OUT)
1405 	create_thread (win32_channel, condition, write_thread);
1406     }
1407 
1408   g_source_add_poll (source, &watch->pollfd);
1409   LeaveCriticalSection (&win32_channel->mutex);
1410 
1411   return source;
1412 }
1413 
1414 static GIOStatus
g_io_win32_console_close(GIOChannel * channel,GError ** err)1415 g_io_win32_console_close (GIOChannel *channel,
1416 		          GError    **err)
1417 {
1418   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1419 
1420   if (close (win32_channel->fd) < 0)
1421     {
1422       int errsv = errno;
1423       g_set_error_literal (err, G_IO_CHANNEL_ERROR,
1424                            g_io_channel_error_from_errno (errsv),
1425                            g_strerror (errsv));
1426       return G_IO_STATUS_ERROR;
1427     }
1428 
1429   return G_IO_STATUS_NORMAL;
1430 }
1431 
1432 static GSource *
g_io_win32_console_create_watch(GIOChannel * channel,GIOCondition condition)1433 g_io_win32_console_create_watch (GIOChannel    *channel,
1434 				 GIOCondition   condition)
1435 {
1436   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1437   GSource *source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
1438   GIOWin32Watch *watch = (GIOWin32Watch *)source;
1439 
1440   watch->channel = channel;
1441   g_io_channel_ref (channel);
1442 
1443   watch->condition = condition;
1444 
1445   watch->pollfd.fd = _get_osfhandle (win32_channel->fd);
1446   watch->pollfd.events = condition;
1447 
1448   g_source_add_poll (source, &watch->pollfd);
1449 
1450   return source;
1451 }
1452 
1453 static GIOStatus
g_io_win32_sock_read(GIOChannel * channel,gchar * buf,gsize count,gsize * bytes_read,GError ** err)1454 g_io_win32_sock_read (GIOChannel *channel,
1455 		      gchar      *buf,
1456 		      gsize       count,
1457 		      gsize      *bytes_read,
1458 		      GError    **err)
1459 {
1460   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1461   gint result;
1462   GIOChannelError error;
1463   int winsock_error;
1464 
1465   if (win32_channel->debug)
1466     g_print ("g_io_win32_sock_read: channel=%p sock=%d count=%" G_GSIZE_FORMAT,
1467 	     channel, win32_channel->fd, count);
1468 
1469   result = recv (win32_channel->fd, buf, count, 0);
1470   if (result == SOCKET_ERROR)
1471     winsock_error = WSAGetLastError ();
1472 
1473   if (win32_channel->debug)
1474     g_print (" recv=%d", result);
1475 
1476   if (result == SOCKET_ERROR)
1477     {
1478       gchar *emsg = g_win32_error_message (winsock_error);
1479 
1480       if (win32_channel->debug)
1481 	g_print (" %s\n", emsg);
1482 
1483       *bytes_read = 0;
1484 
1485       switch (winsock_error)
1486 	{
1487 	case WSAEINVAL:
1488           error = G_IO_CHANNEL_ERROR_INVAL;
1489           break;
1490 	case WSAEWOULDBLOCK:
1491 	  g_free (emsg);
1492           return G_IO_STATUS_AGAIN;
1493 	default:
1494 	  error = G_IO_CHANNEL_ERROR_FAILED;
1495           break;
1496 	}
1497       g_set_error_literal (err, G_IO_CHANNEL_ERROR, error, emsg);
1498       g_free (emsg);
1499 
1500       return G_IO_STATUS_ERROR;
1501     }
1502   else
1503     {
1504       if (win32_channel->debug)
1505 	g_print ("\n");
1506       *bytes_read = result;
1507       if (result == 0)
1508 	return G_IO_STATUS_EOF;
1509       else
1510 	return G_IO_STATUS_NORMAL;
1511     }
1512 }
1513 
1514 static GIOStatus
g_io_win32_sock_write(GIOChannel * channel,const gchar * buf,gsize count,gsize * bytes_written,GError ** err)1515 g_io_win32_sock_write (GIOChannel  *channel,
1516 		       const gchar *buf,
1517 		       gsize        count,
1518 		       gsize       *bytes_written,
1519 		       GError     **err)
1520 {
1521   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1522   gint result;
1523   GIOChannelError error;
1524   int winsock_error;
1525 
1526   if (win32_channel->debug)
1527     g_print ("g_io_win32_sock_write: channel=%p sock=%d count=%" G_GSIZE_FORMAT,
1528 	     channel, win32_channel->fd, count);
1529 
1530   result = send (win32_channel->fd, buf, count, 0);
1531   if (result == SOCKET_ERROR)
1532     winsock_error = WSAGetLastError ();
1533 
1534   if (win32_channel->debug)
1535     g_print (" send=%d", result);
1536 
1537   if (result == SOCKET_ERROR)
1538     {
1539       gchar *emsg = g_win32_error_message (winsock_error);
1540 
1541       if (win32_channel->debug)
1542 	g_print (" %s\n", emsg);
1543 
1544       *bytes_written = 0;
1545 
1546       switch (winsock_error)
1547 	{
1548 	case WSAEINVAL:
1549 	  error = G_IO_CHANNEL_ERROR_INVAL;
1550           break;
1551 	case WSAEWOULDBLOCK:
1552 	  win32_channel->write_would_have_blocked = TRUE;
1553 	  win32_channel->last_events = 0;
1554 	  g_free (emsg);
1555           return G_IO_STATUS_AGAIN;
1556 	default:
1557 	  error = G_IO_CHANNEL_ERROR_FAILED;
1558           break;
1559 	}
1560       g_set_error_literal (err, G_IO_CHANNEL_ERROR, error, emsg);
1561       g_free (emsg);
1562 
1563       return G_IO_STATUS_ERROR;
1564     }
1565   else
1566     {
1567       if (win32_channel->debug)
1568 	g_print ("\n");
1569       *bytes_written = result;
1570       win32_channel->write_would_have_blocked = FALSE;
1571 
1572       return G_IO_STATUS_NORMAL;
1573     }
1574 }
1575 
1576 static GIOStatus
g_io_win32_sock_close(GIOChannel * channel,GError ** err)1577 g_io_win32_sock_close (GIOChannel *channel,
1578 		       GError    **err)
1579 {
1580   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1581 
1582   if (win32_channel->fd != -1)
1583     {
1584       if (win32_channel->debug)
1585 	g_print ("g_io_win32_sock_close: channel=%p sock=%d\n",
1586 		 channel, win32_channel->fd);
1587 
1588       closesocket (win32_channel->fd);
1589       win32_channel->fd = -1;
1590     }
1591 
1592   /* FIXME error detection? */
1593 
1594   return G_IO_STATUS_NORMAL;
1595 }
1596 
1597 static GSource *
g_io_win32_sock_create_watch(GIOChannel * channel,GIOCondition condition)1598 g_io_win32_sock_create_watch (GIOChannel    *channel,
1599 			      GIOCondition   condition)
1600 {
1601   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1602   GSource *source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
1603   GIOWin32Watch *watch = (GIOWin32Watch *)source;
1604 
1605   watch->channel = channel;
1606   g_io_channel_ref (channel);
1607 
1608   watch->condition = condition;
1609 
1610   if (win32_channel->event == 0)
1611     win32_channel->event = WSACreateEvent ();
1612 
1613   watch->pollfd.fd = (gintptr) win32_channel->event;
1614   watch->pollfd.events = condition;
1615 
1616   if (win32_channel->debug)
1617     g_print ("g_io_win32_sock_create_watch: channel=%p sock=%d event=%p condition={%s}\n",
1618 	     channel, win32_channel->fd, (HANDLE) watch->pollfd.fd,
1619 	     condition_to_string (watch->condition));
1620 
1621   g_source_add_poll (source, &watch->pollfd);
1622 
1623   return source;
1624 }
1625 
1626 GIOChannel *
g_io_channel_new_file(const gchar * filename,const gchar * mode,GError ** error)1627 g_io_channel_new_file (const gchar  *filename,
1628                        const gchar  *mode,
1629                        GError      **error)
1630 {
1631   int fid, flags, pmode;
1632   GIOChannel *channel;
1633 
1634   enum { /* Cheesy hack */
1635     MODE_R = 1 << 0,
1636     MODE_W = 1 << 1,
1637     MODE_A = 1 << 2,
1638     MODE_PLUS = 1 << 3,
1639   };
1640   int mode_num, errsv;
1641 
1642   g_return_val_if_fail (filename != NULL, NULL);
1643   g_return_val_if_fail (mode != NULL, NULL);
1644   g_return_val_if_fail ((error == NULL) || (*error == NULL), NULL);
1645 
1646   switch (mode[0])
1647     {
1648       case 'r':
1649         mode_num = MODE_R;
1650         break;
1651       case 'w':
1652         mode_num = MODE_W;
1653         break;
1654       case 'a':
1655         mode_num = MODE_A;
1656         break;
1657       default:
1658         g_warning ("Invalid GIOFileMode %s.", mode);
1659         return NULL;
1660     }
1661 
1662   switch (mode[1])
1663     {
1664       case '\0':
1665         break;
1666       case '+':
1667         if (mode[2] == '\0')
1668           {
1669             mode_num |= MODE_PLUS;
1670             break;
1671           }
1672         /* Fall through */
1673       default:
1674         g_warning ("Invalid GIOFileMode %s.", mode);
1675         return NULL;
1676     }
1677 
1678   switch (mode_num)
1679     {
1680       case MODE_R:
1681         flags = O_RDONLY;
1682         pmode = _S_IREAD;
1683         break;
1684       case MODE_W:
1685         flags = O_WRONLY | O_TRUNC | O_CREAT;
1686         pmode = _S_IWRITE;
1687         break;
1688       case MODE_A:
1689         flags = O_WRONLY | O_APPEND | O_CREAT;
1690         pmode = _S_IWRITE;
1691         break;
1692       case MODE_R | MODE_PLUS:
1693         flags = O_RDWR;
1694         pmode = _S_IREAD | _S_IWRITE;
1695         break;
1696       case MODE_W | MODE_PLUS:
1697         flags = O_RDWR | O_TRUNC | O_CREAT;
1698         pmode = _S_IREAD | _S_IWRITE;
1699         break;
1700       case MODE_A | MODE_PLUS:
1701         flags = O_RDWR | O_APPEND | O_CREAT;
1702         pmode = _S_IREAD | _S_IWRITE;
1703         break;
1704       default:
1705         g_assert_not_reached ();
1706         g_abort ();
1707     }
1708 
1709   /* always open 'untranslated' */
1710   fid = g_open (filename, flags | _O_BINARY, pmode);
1711   errsv = errno;
1712 
1713   if (g_io_win32_get_debug_flag ())
1714     {
1715       g_print ("g_io_channel_win32_new_file: open(\"%s\",", filename);
1716       g_win32_print_access_mode (flags|_O_BINARY);
1717       g_print (",%#o)=%d\n", pmode, fid);
1718     }
1719 
1720   if (fid < 0)
1721     {
1722       g_set_error_literal (error, G_FILE_ERROR,
1723                            g_file_error_from_errno (errsv),
1724                            g_strerror (errsv));
1725       return (GIOChannel *)NULL;
1726     }
1727 
1728   channel = g_io_channel_win32_new_fd (fid);
1729 
1730   /* XXX: move this to g_io_channel_win32_new_fd () */
1731   channel->close_on_unref = TRUE;
1732   channel->is_seekable = TRUE;
1733 
1734   /* g_io_channel_win32_new_fd sets is_readable and is_writeable to
1735    * correspond to actual readability/writeability. Set to FALSE those
1736    * that mode doesn't allow
1737    */
1738   switch (mode_num)
1739     {
1740       case MODE_R:
1741         channel->is_writeable = FALSE;
1742         break;
1743       case MODE_W:
1744       case MODE_A:
1745         channel->is_readable = FALSE;
1746         break;
1747       case MODE_R | MODE_PLUS:
1748       case MODE_W | MODE_PLUS:
1749       case MODE_A | MODE_PLUS:
1750         break;
1751       default:
1752         g_assert_not_reached ();
1753         g_abort ();
1754     }
1755 
1756   return channel;
1757 }
1758 
1759 static GIOStatus
g_io_win32_unimpl_set_flags(GIOChannel * channel,GIOFlags flags,GError ** err)1760 g_io_win32_unimpl_set_flags (GIOChannel *channel,
1761 			     GIOFlags    flags,
1762 			     GError    **err)
1763 {
1764   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1765 
1766   if (win32_channel->debug)
1767     {
1768       g_print ("g_io_win32_unimpl_set_flags: ");
1769       g_win32_print_gioflags (flags);
1770       g_print ("\n");
1771     }
1772 
1773   g_set_error_literal (err, G_IO_CHANNEL_ERROR,
1774                        G_IO_CHANNEL_ERROR_FAILED,
1775                        "Not implemented on Win32");
1776 
1777   return G_IO_STATUS_ERROR;
1778 }
1779 
1780 static GIOFlags
g_io_win32_fd_get_flags_internal(GIOChannel * channel,struct _stati64 * st)1781 g_io_win32_fd_get_flags_internal (GIOChannel      *channel,
1782 				  struct _stati64 *st)
1783 {
1784   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
1785   gchar c;
1786   DWORD count;
1787 
1788   if (st->st_mode & _S_IFIFO)
1789     {
1790       channel->is_readable =
1791 	(PeekNamedPipe ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL, NULL) != 0) || GetLastError () == ERROR_BROKEN_PIPE;
1792       channel->is_writeable =
1793 	(WriteFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
1794       channel->is_seekable  = FALSE;
1795     }
1796   else
1797     {
1798       channel->is_readable =
1799 	(ReadFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
1800       channel->is_writeable =
1801 	(WriteFile ((HANDLE) _get_osfhandle (win32_channel->fd), &c, 0, &count, NULL) != 0);
1802       channel->is_seekable = TRUE;
1803     }
1804 
1805   /* XXX: G_IO_FLAG_APPEND */
1806   /* XXX: G_IO_FLAG_NONBLOCK */
1807 
1808   return 0;
1809 }
1810 
1811 static GIOFlags
g_io_win32_fd_get_flags(GIOChannel * channel)1812 g_io_win32_fd_get_flags (GIOChannel *channel)
1813 {
1814   struct _stati64 st;
1815   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1816 
1817   g_return_val_if_fail (win32_channel != NULL, 0);
1818   g_return_val_if_fail (win32_channel->type == G_IO_WIN32_FILE_DESC, 0);
1819 
1820   if (0 == _fstati64 (win32_channel->fd, &st))
1821     return g_io_win32_fd_get_flags_internal (channel, &st);
1822   else
1823     return 0;
1824 }
1825 
1826 static GIOFlags
g_io_win32_console_get_flags_internal(GIOChannel * channel)1827 g_io_win32_console_get_flags_internal (GIOChannel  *channel)
1828 {
1829   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
1830   HANDLE handle = (HANDLE) _get_osfhandle (win32_channel->fd);
1831   gchar c;
1832   DWORD count;
1833   INPUT_RECORD record;
1834 
1835   channel->is_readable = PeekConsoleInput (handle, &record, 1, &count);
1836   channel->is_writeable = WriteFile (handle, &c, 0, &count, NULL);
1837   channel->is_seekable = FALSE;
1838 
1839   return 0;
1840 }
1841 
1842 static GIOFlags
g_io_win32_console_get_flags(GIOChannel * channel)1843 g_io_win32_console_get_flags (GIOChannel *channel)
1844 {
1845   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1846 
1847   g_return_val_if_fail (win32_channel != NULL, 0);
1848   g_return_val_if_fail (win32_channel->type == G_IO_WIN32_CONSOLE, 0);
1849 
1850   return g_io_win32_console_get_flags_internal (channel);
1851 }
1852 
1853 static GIOFlags
g_io_win32_msg_get_flags(GIOChannel * channel)1854 g_io_win32_msg_get_flags (GIOChannel *channel)
1855 {
1856   return 0;
1857 }
1858 
1859 static GIOStatus
g_io_win32_sock_set_flags(GIOChannel * channel,GIOFlags flags,GError ** err)1860 g_io_win32_sock_set_flags (GIOChannel *channel,
1861 			   GIOFlags    flags,
1862 			   GError    **err)
1863 {
1864   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1865   u_long arg;
1866 
1867   if (win32_channel->debug)
1868     {
1869       g_print ("g_io_win32_sock_set_flags: ");
1870       g_win32_print_gioflags (flags);
1871       g_print ("\n");
1872     }
1873 
1874   if (flags & G_IO_FLAG_NONBLOCK)
1875     {
1876       arg = 1;
1877       if (ioctlsocket (win32_channel->fd, FIONBIO, &arg) == SOCKET_ERROR)
1878 	{
1879 	  gchar *emsg = g_win32_error_message (WSAGetLastError ());
1880 
1881 	  g_set_error_literal (err, G_IO_CHANNEL_ERROR,
1882 			       G_IO_CHANNEL_ERROR_FAILED,
1883 			       emsg);
1884 	  g_free (emsg);
1885 
1886 	  return G_IO_STATUS_ERROR;
1887 	}
1888     }
1889   else
1890     {
1891       arg = 0;
1892       if (ioctlsocket (win32_channel->fd, FIONBIO, &arg) == SOCKET_ERROR)
1893 	{
1894 	  gchar *emsg = g_win32_error_message (WSAGetLastError ());
1895 
1896 	  g_set_error_literal (err, G_IO_CHANNEL_ERROR,
1897 			       G_IO_CHANNEL_ERROR_FAILED,
1898 			       emsg);
1899 	  g_free (emsg);
1900 
1901 	  return G_IO_STATUS_ERROR;
1902 	}
1903     }
1904 
1905   return G_IO_STATUS_NORMAL;
1906 }
1907 
1908 static GIOFlags
g_io_win32_sock_get_flags(GIOChannel * channel)1909 g_io_win32_sock_get_flags (GIOChannel *channel)
1910 {
1911   /* Could we do something here? */
1912   return 0;
1913 }
1914 
1915 static GIOFuncs win32_channel_msg_funcs = {
1916   g_io_win32_msg_read,
1917   g_io_win32_msg_write,
1918   NULL,
1919   g_io_win32_msg_close,
1920   g_io_win32_msg_create_watch,
1921   g_io_win32_free,
1922   g_io_win32_unimpl_set_flags,
1923   g_io_win32_msg_get_flags,
1924 };
1925 
1926 static GIOFuncs win32_channel_fd_funcs = {
1927   g_io_win32_fd_and_console_read,
1928   g_io_win32_fd_and_console_write,
1929   g_io_win32_fd_seek,
1930   g_io_win32_fd_close,
1931   g_io_win32_fd_create_watch,
1932   g_io_win32_free,
1933   g_io_win32_unimpl_set_flags,
1934   g_io_win32_fd_get_flags,
1935 };
1936 
1937 static GIOFuncs win32_channel_console_funcs = {
1938   g_io_win32_fd_and_console_read,
1939   g_io_win32_fd_and_console_write,
1940   NULL,
1941   g_io_win32_console_close,
1942   g_io_win32_console_create_watch,
1943   g_io_win32_free,
1944   g_io_win32_unimpl_set_flags,
1945   g_io_win32_console_get_flags,
1946 };
1947 
1948 static GIOFuncs win32_channel_sock_funcs = {
1949   g_io_win32_sock_read,
1950   g_io_win32_sock_write,
1951   NULL,
1952   g_io_win32_sock_close,
1953   g_io_win32_sock_create_watch,
1954   g_io_win32_free,
1955   g_io_win32_sock_set_flags,
1956   g_io_win32_sock_get_flags,
1957 };
1958 
1959 /**
1960  * g_io_channel_win32_new_messages:
1961  * @hwnd: a window handle.
1962  *
1963  * Creates a new #GIOChannel given a window handle on Windows.
1964  *
1965  * This function creates a #GIOChannel that can be used to poll for
1966  * Windows messages for the window in question.
1967  *
1968  * Returns: a new #GIOChannel.
1969  **/
1970 GIOChannel *
1971 #if GLIB_SIZEOF_VOID_P == 8
g_io_channel_win32_new_messages(gsize hwnd)1972 g_io_channel_win32_new_messages (gsize hwnd)
1973 #else
1974 g_io_channel_win32_new_messages (guint hwnd)
1975 #endif
1976 {
1977   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
1978   GIOChannel *channel = (GIOChannel *)win32_channel;
1979 
1980   g_io_channel_init (channel);
1981   g_io_channel_win32_init (win32_channel);
1982   if (win32_channel->debug)
1983     g_print ("g_io_channel_win32_new_messages: channel=%p hwnd=%p\n",
1984 	     channel, (HWND) hwnd);
1985   channel->funcs = &win32_channel_msg_funcs;
1986   win32_channel->type = G_IO_WIN32_WINDOWS_MESSAGES;
1987   win32_channel->hwnd = (HWND) hwnd;
1988 
1989   /* XXX: check this. */
1990   channel->is_readable = IsWindow (win32_channel->hwnd);
1991   channel->is_writeable = IsWindow (win32_channel->hwnd);
1992 
1993   channel->is_seekable = FALSE;
1994 
1995   return channel;
1996 }
1997 
1998 static GIOChannel *
g_io_channel_win32_new_fd_internal(gint fd,struct _stati64 * st)1999 g_io_channel_win32_new_fd_internal (gint             fd,
2000 				    struct _stati64 *st)
2001 {
2002   GIOWin32Channel *win32_channel;
2003   GIOChannel *channel;
2004 
2005   win32_channel = g_new (GIOWin32Channel, 1);
2006   channel = (GIOChannel *)win32_channel;
2007 
2008   g_io_channel_init (channel);
2009   g_io_channel_win32_init (win32_channel);
2010 
2011   win32_channel->fd = fd;
2012 
2013   if (win32_channel->debug)
2014     g_print ("g_io_channel_win32_new_fd: channel=%p fd=%u\n",
2015 	     channel, fd);
2016 
2017   if (st->st_mode & _S_IFCHR) /* console */
2018     {
2019       channel->funcs = &win32_channel_console_funcs;
2020       win32_channel->type = G_IO_WIN32_CONSOLE;
2021       g_io_win32_console_get_flags_internal (channel);
2022     }
2023   else
2024     {
2025       channel->funcs = &win32_channel_fd_funcs;
2026       win32_channel->type = G_IO_WIN32_FILE_DESC;
2027       g_io_win32_fd_get_flags_internal (channel, st);
2028     }
2029 
2030   return channel;
2031 }
2032 
2033 /**
2034  * g_io_channel_win32_new_fd:
2035  * @fd: a C library file descriptor.
2036  *
2037  * Creates a new #GIOChannel given a file descriptor on Windows. This
2038  * works for file descriptors from the C runtime.
2039  *
2040  * This function works for file descriptors as returned by the open(),
2041  * creat(), pipe() and fileno() calls in the Microsoft C runtime. In
2042  * order to meaningfully use this function your code should use the
2043  * same C runtime as GLib uses, which is msvcrt.dll. Note that in
2044  * current Microsoft compilers it is near impossible to convince it to
2045  * build code that would use msvcrt.dll. The last Microsoft compiler
2046  * version that supported using msvcrt.dll as the C runtime was version 6.
2047  * The GNU compiler and toolchain for Windows, also known as Mingw,
2048  * fully supports msvcrt.dll.
2049  *
2050  * If you have created a #GIOChannel for a file descriptor and started
2051  * watching (polling) it, you shouldn't call read() on the file
2052  * descriptor. This is because adding polling for a file descriptor is
2053  * implemented in GLib on Windows by starting a thread that sits
2054  * blocked in a read() from the file descriptor most of the time. All
2055  * reads from the file descriptor should be done by this internal GLib
2056  * thread. Your code should call only g_io_channel_read().
2057  *
2058  * This function is available only in GLib on Windows.
2059  *
2060  * Returns: a new #GIOChannel.
2061  **/
2062 GIOChannel *
g_io_channel_win32_new_fd(gint fd)2063 g_io_channel_win32_new_fd (gint fd)
2064 {
2065   struct _stati64 st;
2066 
2067   if (_fstati64 (fd, &st) == -1)
2068     {
2069       g_warning ("g_io_channel_win32_new_fd: %d isn't an open file descriptor in the C library GLib uses.", fd);
2070       return NULL;
2071     }
2072 
2073   return g_io_channel_win32_new_fd_internal (fd, &st);
2074 }
2075 
2076 gint
g_io_channel_win32_get_fd(GIOChannel * channel)2077 g_io_channel_win32_get_fd (GIOChannel *channel)
2078 {
2079   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
2080 
2081   return win32_channel->fd;
2082 }
2083 
2084 /**
2085  * g_io_channel_win32_new_socket:
2086  * @socket: a Winsock socket
2087  *
2088  * Creates a new #GIOChannel given a socket on Windows.
2089  *
2090  * This function works for sockets created by Winsock. It's available
2091  * only in GLib on Windows.
2092  *
2093  * Polling a #GSource created to watch a channel for a socket puts the
2094  * socket in non-blocking mode. This is a side-effect of the
2095  * implementation and unavoidable.
2096  *
2097  * Returns: a new #GIOChannel
2098  **/
2099 GIOChannel *
g_io_channel_win32_new_socket(int socket)2100 g_io_channel_win32_new_socket (int socket)
2101 {
2102   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
2103   GIOChannel *channel = (GIOChannel *)win32_channel;
2104 
2105   g_io_channel_init (channel);
2106   g_io_channel_win32_init (win32_channel);
2107   if (win32_channel->debug)
2108     g_print ("g_io_channel_win32_new_socket: channel=%p sock=%d\n",
2109 	     channel, socket);
2110   channel->funcs = &win32_channel_sock_funcs;
2111   win32_channel->type = G_IO_WIN32_SOCKET;
2112   win32_channel->fd = socket;
2113 
2114   channel->is_readable = TRUE;
2115   channel->is_writeable = TRUE;
2116   channel->is_seekable = FALSE;
2117 
2118   return channel;
2119 }
2120 
2121 GIOChannel *
g_io_channel_unix_new(gint fd)2122 g_io_channel_unix_new (gint fd)
2123 {
2124   gboolean is_fd, is_socket;
2125   struct _stati64 st;
2126   int optval, optlen;
2127 
2128   is_fd = (_fstati64 (fd, &st) == 0);
2129 
2130   optlen = sizeof (optval);
2131   is_socket = (getsockopt (fd, SOL_SOCKET, SO_TYPE, (char *) &optval, &optlen) != SOCKET_ERROR);
2132 
2133   if (is_fd && is_socket)
2134     g_warning ("g_io_channel_unix_new: %d is both a file descriptor and a socket. File descriptor interpretation assumed. To avoid ambiguity, call either g_io_channel_win32_new_fd() or g_io_channel_win32_new_socket() instead.", fd);
2135 
2136   if (is_fd)
2137     return g_io_channel_win32_new_fd_internal (fd, &st);
2138 
2139   if (is_socket)
2140     return g_io_channel_win32_new_socket(fd);
2141 
2142   g_warning ("g_io_channel_unix_new: %d is neither a file descriptor or a socket.", fd);
2143 
2144   return NULL;
2145 }
2146 
2147 gint
g_io_channel_unix_get_fd(GIOChannel * channel)2148 g_io_channel_unix_get_fd (GIOChannel *channel)
2149 {
2150   return g_io_channel_win32_get_fd (channel);
2151 }
2152 
2153 void
g_io_channel_win32_set_debug(GIOChannel * channel,gboolean flag)2154 g_io_channel_win32_set_debug (GIOChannel *channel,
2155 			      gboolean    flag)
2156 {
2157   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
2158 
2159   win32_channel->debug = flag;
2160 }
2161 
2162 gint
g_io_channel_win32_poll(GPollFD * fds,gint n_fds,gint timeout)2163 g_io_channel_win32_poll (GPollFD *fds,
2164 			 gint     n_fds,
2165 			 gint     timeout)
2166 {
2167   g_return_val_if_fail (n_fds >= 0, 0);
2168 
2169   return g_poll (fds, n_fds, timeout);
2170 }
2171 
2172 void
g_io_channel_win32_make_pollfd(GIOChannel * channel,GIOCondition condition,GPollFD * fd)2173 g_io_channel_win32_make_pollfd (GIOChannel   *channel,
2174 				GIOCondition  condition,
2175 				GPollFD      *fd)
2176 {
2177   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
2178 
2179   switch (win32_channel->type)
2180     {
2181     case G_IO_WIN32_FILE_DESC:
2182       if (win32_channel->data_avail_event == NULL)
2183 	create_events (win32_channel);
2184 
2185       fd->fd = (gintptr) win32_channel->data_avail_event;
2186 
2187       if (win32_channel->thread_id == 0)
2188 	{
2189 	  /* Is it meaningful for a file descriptor to be polled for
2190 	   * both IN and OUT? For what kind of file descriptor would
2191 	   * that be? Doesn't seem to make sense, in practise the file
2192 	   * descriptors handled here are always read or write ends of
2193 	   * pipes surely, and thus unidirectional.
2194 	   */
2195 	  if (condition & G_IO_IN)
2196 	    create_thread (win32_channel, condition, read_thread);
2197 	  else if (condition & G_IO_OUT)
2198 	    create_thread (win32_channel, condition, write_thread);
2199 	}
2200       break;
2201 
2202     case G_IO_WIN32_CONSOLE:
2203       fd->fd = _get_osfhandle (win32_channel->fd);
2204       break;
2205 
2206     case G_IO_WIN32_SOCKET:
2207       fd->fd = (gintptr) WSACreateEvent ();
2208       break;
2209 
2210     case G_IO_WIN32_WINDOWS_MESSAGES:
2211       fd->fd = G_WIN32_MSG_HANDLE;
2212       break;
2213 
2214     default:
2215       g_assert_not_reached ();
2216       g_abort ();
2217     }
2218 
2219   fd->events = condition;
2220 }
2221 
2222 #ifndef _WIN64
2223 
2224 /* Binary compatibility */
2225 GIOChannel *
g_io_channel_win32_new_stream_socket(int socket)2226 g_io_channel_win32_new_stream_socket (int socket)
2227 {
2228   return g_io_channel_win32_new_socket (socket);
2229 }
2230 
2231 #endif
2232 
2233 #ifdef G_OS_WIN32
2234 
2235 /* Binary compatibility versions. Not for newly compiled code. */
2236 
2237 _GLIB_EXTERN GIOChannel *g_io_channel_new_file_utf8 (const gchar  *filename,
2238                                                      const gchar  *mode,
2239                                                      GError      **error);
2240 
2241 GIOChannel *
g_io_channel_new_file_utf8(const gchar * filename,const gchar * mode,GError ** error)2242 g_io_channel_new_file_utf8 (const gchar  *filename,
2243                             const gchar  *mode,
2244                             GError      **error)
2245 {
2246   return g_io_channel_new_file (filename, mode, error);
2247 }
2248 
2249 #endif
2250