giowin32.c 53.7 KB
Newer Older
1 2 3 4 5
/* GLIB - Library of useful routines for C programming
 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * giowin32.c: IO Channels for Win32.
 * 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 12 13 14 15
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * 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 21 22 23 24
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

25
/*
26
 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
27 28
 * file for a list of people on the GLib Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
29
 * GLib at ftp://ftp.gtk.org/pub/gtk/.
30 31
 */

Owen Taylor's avatar
Owen Taylor committed
32 33
#include "config.h"

34
#include "glib.h"
35 36

#include <stdlib.h>
37
#include <winsock2.h>
38
#include <windows.h>
39
#include <conio.h>
40 41
#include <fcntl.h>
#include <io.h>
42
#include <process.h>
43
#include <errno.h>
44
#include <sys/stat.h>
45

46
#include "gstdio.h"
47 48
#include "glibintl.h"

49 50
#include "galias.h"

51 52 53
typedef struct _GIOWin32Channel GIOWin32Channel;
typedef struct _GIOWin32Watch GIOWin32Watch;

54
#define BUFFER_SIZE 4096
55 56

typedef enum {
57 58
  G_IO_WIN32_WINDOWS_MESSAGES,	/* Windows messages */
  G_IO_WIN32_FILE_DESC,		/* Unix-like file descriptors from
59
				 * _open() or _pipe(), except for console IO.
60 61
				 * Have to create separate thread to read.
				 */
62
  G_IO_WIN32_CONSOLE,		/* Console IO (usually stdin, stdout, stderr) */
63
  G_IO_WIN32_SOCKET		/* Sockets. No separate thread */
64 65 66 67 68 69 70 71 72
} GIOWin32ChannelType;

struct _GIOWin32Channel {
  GIOChannel channel;
  gint fd;			/* Either a Unix-like file handle as provided
				 * by the Microsoft C runtime, or a SOCKET
				 * as provided by WinSock.
				 */
  GIOWin32ChannelType type;
73
  
74 75
  gboolean debug;

76
  /* This is used by G_IO_WIN32_WINDOWS_MESSAGES channels */
77
  HWND hwnd;			/* handle of window, or NULL */
78
  
79 80 81
  /* Following fields are used by fd channels. */
  CRITICAL_SECTION mutex;

82 83 84 85
  int direction;		/* 0 means we read from it,
				 * 1 means we write to it.
				 */

86 87 88 89 90 91 92 93 94 95 96 97 98
  gboolean running;		/* Is reader thread running. FALSE if
				 * EOF has been reached.
				 */
  gboolean needs_close;		/* If the channel has been closed while
				 * the reader thread was still running.
				 */
  guint thread_id;		/* If non-NULL has a reader thread, or has
				 * had.*/
  HANDLE data_avail_event;

  gushort revents;

  /* Following fields used by fd channels for input */
99 100 101 102 103 104 105 106 107 108 109 110 111 112
  
  /* Data is kept in a circular buffer. To be able to distinguish between
   * empty and full buffer, we cannot fill it completely, but have to
   * leave a one character gap.
   *
   * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
   *
   * Empty:    wrp == rdp
   * Full:     (wrp + 1) % BUFFER_SIZE == rdp
   * Partial:  otherwise
   */
  guchar *buffer;		/* (Circular) buffer */
  gint wrp, rdp;		/* Buffer indices for writing and reading */
  HANDLE space_avail_event;
113 114

  /* Following fields used by socket channels */
115 116 117 118
  int event_mask;
  int last_events;
  int event;
  gboolean write_would_have_blocked;
119 120
};

121 122 123
#define LOCK(mutex) EnterCriticalSection (&mutex)
#define UNLOCK(mutex) LeaveCriticalSection (&mutex)

124
struct _GIOWin32Watch {
125
  GSource       source;
126 127 128 129 130
  GPollFD       pollfd;
  GIOChannel   *channel;
  GIOCondition  condition;
};

131
static void
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
g_win32_print_access_mode (int flags)
{
  g_print ("%s%s%s%s%s%s%s%s%s%s",
	   ((flags & 0x3) == _O_RDWR ? "O_RDWR" :
	    ((flags & 0x3) == _O_RDONLY ? "O_RDONLY" :
	     ((flags & 0x3) == _O_WRONLY ? "O_WRONLY" : "0"))),
	   (flags & _O_APPEND ? "|O_APPEND" : ""),
	   (flags & _O_RANDOM ? "|O_RANDOM" : ""),
	   (flags & _O_SEQUENTIAL ? "|O_SEQUENTIAL" : ""),
	   (flags & _O_TEMPORARY ? "|O_TEMPORARY" : ""),
	   (flags & _O_CREAT ? "|O_CREAT" : ""),
	   (flags & _O_TRUNC ? "|O_TRUNC" : ""),
	   (flags & _O_EXCL ? "|O_EXCL" : ""),
	   (flags & _O_TEXT ? "|O_TEXT" : ""),
	   (flags & _O_BINARY ? "|O_BINARY" : ""));
}

static void
g_win32_print_gioflags (GIOFlags flags)
{
  char *bar = "";

  if (flags & G_IO_FLAG_APPEND)
    bar = "|", g_print ("APPEND");
  if (flags & G_IO_FLAG_NONBLOCK)
    g_print ("%sNONBLOCK", bar), bar = "|";
  if (flags & G_IO_FLAG_IS_READABLE)
    g_print ("%sREADABLE", bar), bar = "|";
  if (flags & G_IO_FLAG_IS_WRITEABLE)
    g_print ("%sWRITEABLE", bar), bar = "|";
  if (flags & G_IO_FLAG_IS_SEEKABLE)
    g_print ("%sSEEKABLE", bar), bar = "|";
}

166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
static const char *
event_mask_to_string (int mask)
{
  char buf[100];
  int checked_bits = 0;
  char *bufp = buf;

  if (mask == 0)
    return "";

#define BIT(n) checked_bits |= FD_##n; if (mask & FD_##n) bufp += sprintf (bufp, "%s" #n, (bufp>buf ? "|" : ""))

  BIT (READ);
  BIT (WRITE);
  BIT (OOB);
  BIT (ACCEPT);
  BIT (CONNECT);
  BIT (CLOSE);
  BIT (QOS);
  BIT (GROUP_QOS);
  BIT (ROUTING_INTERFACE_CHANGE);
  BIT (ADDRESS_LIST_CHANGE);
  
#undef BIT

  if ((mask & ~checked_bits) != 0)
	  bufp += sprintf (bufp, "|%#x", mask & ~checked_bits);
  
  return g_quark_to_string (g_quark_from_string (buf));
}

static const char *
condition_to_string (GIOCondition condition)
{
  char buf[100];
  int checked_bits = 0;
  char *bufp = buf;

  if (condition == 0)
    return "";

#define BIT(n) checked_bits |= G_IO_##n; if (condition & G_IO_##n) bufp += sprintf (bufp, "%s" #n, (bufp>buf ? "|" : ""))

  BIT (IN);
  BIT (OUT);
  BIT (PRI);
  BIT (ERR);
  BIT (HUP);
  BIT (NVAL);
  
#undef BIT

  if ((condition & ~checked_bits) != 0)
	  bufp += sprintf (bufp, "|%#x", condition & ~checked_bits);
  
  return g_quark_to_string (g_quark_from_string (buf));
}

224 225
static gboolean
g_io_win32_get_debug_flag (void)
226
{
227 228 229
  return (getenv ("G_IO_WIN32_DEBUG") != NULL);
}

230 231 232 233
static void
g_io_channel_win32_init (GIOWin32Channel *channel)
{
  channel->debug = g_io_win32_get_debug_flag ();
234 235
  channel->buffer = NULL;
  channel->running = FALSE;
236
  channel->needs_close = FALSE;
237
  channel->thread_id = 0;
238
  channel->data_avail_event = NULL;
239
  channel->revents = 0;
240
  channel->space_avail_event = NULL;
241 242 243 244
  channel->event_mask = 0;
  channel->last_events = 0;
  channel->event = 0;
  channel->write_would_have_blocked = FALSE;
245
  InitializeCriticalSection (&channel->mutex);
246 247
}

248 249 250 251 252
static void
create_events (GIOWin32Channel *channel)
{
  SECURITY_ATTRIBUTES sec_attrs;
  
253
  sec_attrs.nLength = sizeof (SECURITY_ATTRIBUTES);
254 255
  sec_attrs.lpSecurityDescriptor = NULL;
  sec_attrs.bInheritHandle = FALSE;
256

257 258 259 260
  /* The data available event is manual reset, the space available event
   * is automatic reset.
   */
  if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
261
      || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
262
    {
263 264 265
      gchar *emsg = g_win32_error_message (GetLastError ());
      g_error ("Error creating event: %s", emsg);
      g_free (emsg);
266 267
    }
}
268

269
static unsigned __stdcall
270
read_thread (void *parameter)
271 272 273 274
{
  GIOWin32Channel *channel = parameter;
  guchar *buffer;
  guint nbytes;
275

276
  g_io_channel_ref ((GIOChannel *)channel);
277

278
  if (channel->debug)
279
    g_print ("read_thread %#x: start fd=%d, data_avail=%#x space_avail=%#x\n",
280 281 282 283
	     channel->thread_id,
	     channel->fd,
	     (guint) channel->data_avail_event,
	     (guint) channel->space_avail_event);
284 285

  channel->direction = 0;
286 287 288
  channel->buffer = g_malloc (BUFFER_SIZE);
  channel->rdp = channel->wrp = 0;
  channel->running = TRUE;
289

290 291
  SetEvent (channel->space_avail_event);
  
292
  LOCK (channel->mutex);
293 294
  while (channel->running)
    {
295
      if (channel->debug)
296
	g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
297
		 channel->thread_id, channel->rdp, channel->wrp);
298 299 300
      if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
	{
	  /* Buffer is full */
301
	  if (channel->debug)
302
	    g_print ("read_thread %#x: resetting space_avail\n",
303
		     channel->thread_id);
304
	  ResetEvent (channel->space_avail_event);
305
	  if (channel->debug)
306 307
	    g_print ("read_thread %#x: waiting for space\n",
		     channel->thread_id);
308 309 310
	  UNLOCK (channel->mutex);
	  WaitForSingleObject (channel->space_avail_event, INFINITE);
	  LOCK (channel->mutex);
311
	  if (channel->debug)
312
	    g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
313
		     channel->thread_id, channel->rdp, channel->wrp);
314 315 316 317 318 319 320 321 322
	}
      
      buffer = channel->buffer + channel->wrp;
      
      /* Always leave at least one byte unused gap to be able to
       * distinguish between the full and empty condition...
       */
      nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
		    BUFFER_SIZE - channel->wrp);
323

324
      if (channel->debug)
325
	g_print ("read_thread %#x: calling read() for %d bytes\n",
326 327
		 channel->thread_id, nbytes);

328
      UNLOCK (channel->mutex);
329

330
      nbytes = read (channel->fd, buffer, nbytes);
331 332
      
      LOCK (channel->mutex);
333

334 335 336 337 338 339
      channel->revents = G_IO_IN;
      if (nbytes == 0)
	channel->revents |= G_IO_HUP;
      else if (nbytes < 0)
	channel->revents |= G_IO_ERR;

340
      if (channel->debug)
341
	g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
342
		 channel->thread_id, nbytes, channel->rdp, channel->wrp);
343 344 345 346

      if (nbytes <= 0)
	break;

347
      channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
348
      if (channel->debug)
349
	g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
350
		 channel->thread_id, channel->rdp, channel->wrp);
351 352 353 354
      SetEvent (channel->data_avail_event);
    }
  
  channel->running = FALSE;
355 356 357
  if (channel->needs_close)
    {
      if (channel->debug)
358
	g_print ("read_thread %#x: channel fd %d needs closing\n",
359
		 channel->thread_id, channel->fd);
360
      close (channel->fd);
361 362 363
      channel->fd = -1;
    }

364 365 366
  if (channel->debug)
    g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
	     channel->thread_id, channel->rdp, channel->wrp);
367 368 369
  SetEvent (channel->data_avail_event);
  UNLOCK (channel->mutex);
  
370
  g_io_channel_unref ((GIOChannel *)channel);
371
  
372 373 374
  /* No need to call _endthreadex(), the actual thread starter routine
   * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
   * _endthreadex() for us.
375
   */
376

377 378
  return 0;
}
379

380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
static unsigned __stdcall
write_thread (void *parameter)
{
  GIOWin32Channel *channel = parameter;
  guchar *buffer;
  guint nbytes;

  g_io_channel_ref ((GIOChannel *)channel);

  if (channel->debug)
    g_print ("write_thread %#x: start fd=%d, data_avail=%#x space_avail=%#x\n",
	     channel->thread_id,
	     channel->fd,
	     (guint) channel->data_avail_event,
	     (guint) channel->space_avail_event);
  
  channel->direction = 1;
  channel->buffer = g_malloc (BUFFER_SIZE);
  channel->rdp = channel->wrp = 0;
  channel->running = TRUE;

  SetEvent (channel->space_avail_event);

  /* We use the same event objects as for a reader thread, but with
   * reversed meaning. So, space_avail is used if data is available
   * for writing, and data_avail is used if space is available in the
   * write buffer.
   */

  LOCK (channel->mutex);
  while (channel->running || channel->rdp != channel->wrp)
    {
      if (channel->debug)
	g_print ("write_thread %#x: rdp=%d, wrp=%d\n",
		 channel->thread_id, channel->rdp, channel->wrp);
      if (channel->wrp == channel->rdp)
	{
	  /* Buffer is empty. */
	  if (channel->debug)
	    g_print ("write_thread %#x: resetting space_avail\n",
		     channel->thread_id);
	  ResetEvent (channel->space_avail_event);
	  if (channel->debug)
	    g_print ("write_thread %#x: waiting for data\n",
		     channel->thread_id);
	  channel->revents = G_IO_OUT;
	  SetEvent (channel->data_avail_event);
	  UNLOCK (channel->mutex);
	  WaitForSingleObject (channel->space_avail_event, INFINITE);

	  LOCK (channel->mutex);
	  if (channel->rdp == channel->wrp)
	    break;

	  if (channel->debug)
	    g_print ("write_thread %#x: rdp=%d, wrp=%d\n",
		     channel->thread_id, channel->rdp, channel->wrp);
	}
      
      buffer = channel->buffer + channel->rdp;
      if (channel->rdp < channel->wrp)
	nbytes = channel->wrp - channel->rdp;
      else
	nbytes = BUFFER_SIZE - channel->rdp;

      if (channel->debug)
	g_print ("write_thread %#x: calling write() for %d bytes\n",
		 channel->thread_id, nbytes);

      UNLOCK (channel->mutex);
      nbytes = write (channel->fd, buffer, nbytes);
      LOCK (channel->mutex);

      if (channel->debug)
	g_print ("write_thread %#x: write(%i) returned %d, rdp=%d, wrp=%d\n",
		 channel->thread_id, channel->fd, nbytes, channel->rdp, channel->wrp);

      channel->revents = 0;
      if (nbytes > 0)
	channel->revents |= G_IO_OUT;
      else if (nbytes <= 0)
	channel->revents |= G_IO_ERR;

      channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;

      if (nbytes <= 0)
	break;

      if (channel->debug)
	g_print ("write_thread: setting data_avail for thread %#x\n",
		 channel->thread_id);
      SetEvent (channel->data_avail_event);
    }
  
  channel->running = FALSE;
  if (channel->needs_close)
    {
      if (channel->debug)
	g_print ("write_thread %#x: channel fd %d needs closing\n",
		 channel->thread_id, channel->fd);
      close (channel->fd);
      channel->fd = -1;
    }

  UNLOCK (channel->mutex);
  
  g_io_channel_unref ((GIOChannel *)channel);
  
  return 0;
}

491
static void
492 493 494
create_thread (GIOWin32Channel     *channel,
	       GIOCondition         condition,
	       unsigned (__stdcall *thread) (void *parameter))
495
{
496 497 498 499 500
  HANDLE thread_handle;

  thread_handle = (HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
					   &channel->thread_id);
  if (thread_handle == 0)
501
    g_warning (G_STRLOC ": Error creating reader thread: %s",
Owen Taylor's avatar
Owen Taylor committed
502
	       g_strerror (errno));
503 504 505 506
  else if (!CloseHandle (thread_handle))
    g_warning (G_STRLOC ": Error closing thread handle: %s\n",
	       g_win32_error_message (GetLastError ()));

507 508
  WaitForSingleObject (channel->space_avail_event, INFINITE);
}
509

510
static GIOStatus
511 512
buffer_read (GIOWin32Channel *channel,
	     guchar          *dest,
513 514 515
	     gsize            count,
	     gsize           *bytes_read,
	     GError         **err)
516
{
517 518 519 520
  guint nbytes;
  guint left = count;
  
  LOCK (channel->mutex);
521 522 523
  if (channel->debug)
    g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
	     channel->thread_id, count, channel->rdp, channel->wrp);
524
  
525
  if (channel->wrp == channel->rdp)
526 527
    {
      UNLOCK (channel->mutex);
528 529 530
      if (channel->debug)
	g_print ("waiting for data from thread %#x\n", channel->thread_id);
      WaitForSingleObject (channel->data_avail_event, INFINITE);
531 532
      if (channel->debug)
	g_print ("done waiting for data from thread %#x\n", channel->thread_id);
533
      LOCK (channel->mutex);
534
      if (channel->wrp == channel->rdp && !channel->running)
535
	{
536 537
	  if (channel->debug)
	    g_print ("wrp==rdp, !running\n");
538
	  UNLOCK (channel->mutex);
539
          *bytes_read = 0;
540
	  return G_IO_STATUS_EOF;
541
	}
542
    }
543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558
  
  if (channel->rdp < channel->wrp)
    nbytes = channel->wrp - channel->rdp;
  else
    nbytes = BUFFER_SIZE - channel->rdp;
  UNLOCK (channel->mutex);
  nbytes = MIN (left, nbytes);
  if (channel->debug)
    g_print ("moving %d bytes from thread %#x\n",
	     nbytes, channel->thread_id);
  memcpy (dest, channel->buffer + channel->rdp, nbytes);
  dest += nbytes;
  left -= nbytes;
  LOCK (channel->mutex);
  channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
  if (channel->debug)
559
    g_print ("setting space_avail for thread %#x\n", channel->thread_id);
560 561 562 563
  SetEvent (channel->space_avail_event);
  if (channel->debug)
    g_print ("for thread %#x: rdp=%d, wrp=%d\n",
	     channel->thread_id, channel->rdp, channel->wrp);
564
  if (channel->running && channel->wrp == channel->rdp)
565 566
    {
      if (channel->debug)
567
	g_print ("resetting data_avail of thread %#x\n",
568 569 570
		 channel->thread_id);
      ResetEvent (channel->data_avail_event);
    };
571 572
  UNLOCK (channel->mutex);
  
573 574 575
  /* We have no way to indicate any errors form the actual
   * read() or recv() call in the reader thread. Should we have?
   */
576 577
  *bytes_read = count - left;
  return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
578
}
579

580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651

static GIOStatus
buffer_write (GIOWin32Channel *channel,
	      const guchar    *dest,
	      gsize            count,
	      gsize           *bytes_written,
	      GError         **err)
{
  guint nbytes;
  guint left = count;
  
  LOCK (channel->mutex);
  if (channel->debug)
    g_print ("buffer_write: writing to thread %#x %d bytes, rdp=%d, wrp=%d\n",
	     channel->thread_id, count, channel->rdp, channel->wrp);
  
  if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
    {
      /* Buffer is full */
      if (channel->debug)
	g_print ("buffer_write: tid %#x: resetting data_avail\n",
		 channel->thread_id);
      ResetEvent (channel->data_avail_event);
      if (channel->debug)
	g_print ("buffer_write: tid %#x: waiting for space\n",
		 channel->thread_id);
      UNLOCK (channel->mutex);
      WaitForSingleObject (channel->data_avail_event, INFINITE);
      LOCK (channel->mutex);
      if (channel->debug)
	g_print ("buffer_write: tid %#x: rdp=%d, wrp=%d\n",
		 channel->thread_id, channel->rdp, channel->wrp);
    }
   
  nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
		BUFFER_SIZE - channel->wrp);

  UNLOCK (channel->mutex);
  nbytes = MIN (left, nbytes);
  if (channel->debug)
    g_print ("buffer_write: tid %#x: writing %d bytes\n",
	     channel->thread_id, nbytes);
  memcpy (channel->buffer + channel->wrp, dest, nbytes);
  dest += nbytes;
  left -= nbytes;
  LOCK (channel->mutex);

  channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
  if (channel->debug)
    g_print ("buffer_write: tid %#x: rdp=%d, wrp=%d, setting space_avail\n",
	     channel->thread_id, channel->rdp, channel->wrp);
  SetEvent (channel->space_avail_event);

  if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
    {
      /* Buffer is full */
      if (channel->debug)
	g_print ("buffer_write: tid %#x: resetting data_avail\n",
		 channel->thread_id);
      ResetEvent (channel->data_avail_event);
    }

  UNLOCK (channel->mutex);
  
  /* We have no way to indicate any errors form the actual
   * write() call in the writer thread. Should we have?
   */
  *bytes_written = count - left;
  return (*bytes_written > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
}


652
static gboolean
653 654
g_io_win32_prepare (GSource *source,
		    gint    *timeout)
655
{
656
  GIOWin32Watch *watch = (GIOWin32Watch *)source;
657
  GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
658
  GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
659
  int event_mask;
660
  
661
  *timeout = -1;
662
  
663 664 665
  if (channel->debug)
    g_print ("g_io_win32_prepare: source=%p channel=%p", source, channel);

666
  switch (channel->type)
667
    {
668
    case G_IO_WIN32_WINDOWS_MESSAGES:
669 670 671 672
      if (channel->debug)
	g_print (" MSG");
      break;

673
    case G_IO_WIN32_CONSOLE:
674 675
      if (channel->debug)
	g_print (" CON");
676 677 678 679
      break;

    case G_IO_WIN32_FILE_DESC:
      if (channel->debug)
680 681
	g_print (" FD thread=%#x buffer_condition:{%s}"
		 "\n  watch->pollfd.events:{%s} watch->pollfd.revents:{%s} channel->revents:{%s}",
682 683 684 685 686
		 channel->thread_id, condition_to_string (buffer_condition),
		 condition_to_string (watch->pollfd.events),
		 condition_to_string (watch->pollfd.revents),
		 condition_to_string (channel->revents));
      
687
      LOCK (channel->mutex);
688
      if (channel->running)
689
	{
690 691 692
	  if (channel->direction == 0 && channel->wrp == channel->rdp)
	    {
	      if (channel->debug)
693
		g_print ("\n  setting revents=0");
694 695
	      channel->revents = 0;
	    }
696
	}
697 698 699 700 701 702
      else
	{
	  if (channel->direction == 1
	      && (channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
	    {
	      if (channel->debug)
703
		g_print ("\n setting revents=0");
704 705 706
	      channel->revents = 0;
	    }
	}	  
707
      UNLOCK (channel->mutex);
708
      break;
709

710
    case G_IO_WIN32_SOCKET:
711 712
      if (channel->debug)
	g_print (" SOCK");
713 714 715 716 717
      event_mask = 0;
      if (watch->condition & G_IO_IN)
	event_mask |= (FD_READ | FD_ACCEPT);
      if (watch->condition & G_IO_OUT)
	event_mask |= (FD_WRITE | FD_CONNECT);
718
      event_mask |= FD_CLOSE;
719 720 721 722

      if (channel->event_mask != event_mask /* || channel->event != watch->pollfd.fd*/)
	{
	  if (channel->debug)
723
	    g_print ("\n  WSAEventSelect(%d,%#x,{%s})",
724 725 726 727 728 729 730 731 732
		     channel->fd, watch->pollfd.fd,
		     event_mask_to_string (event_mask));
	  if (WSAEventSelect (channel->fd, (HANDLE) watch->pollfd.fd,
			      event_mask) == SOCKET_ERROR)
	    ;			/* What? */
	  channel->event_mask = event_mask;
#if 0
	  channel->event = watch->pollfd.fd;
#endif
733 734
	  if (channel->debug)
	    g_print ("\n  setting last_events=0");
735
	  channel->last_events = 0;
736 737 738 739 740 741 742

	  if ((event_mask & FD_WRITE) && !channel->write_would_have_blocked)
	    {
	      if (channel->debug)
		g_print (" WSASetEvent(%#x)", watch->pollfd.fd);
	      WSASetEvent ((WSAEVENT) watch->pollfd.fd);
	    }
743 744 745 746 747 748 749
	}
      break;

    default:
      g_assert_not_reached ();
      abort ();
    }
750 751 752
  if (channel->debug)
    g_print ("\n");

753
  return ((watch->condition & buffer_condition) == watch->condition);
754 755
}

756
static gboolean
757
g_io_win32_check (GSource *source)
758
{
759
  MSG msg;
760
  GIOWin32Watch *watch = (GIOWin32Watch *)source;
761
  GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
762
  GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
763
  WSANETWORKEVENTS events;
764

765 766 767
  if (channel->debug)
    g_print ("g_io_win32_check: source=%p channel=%p", source, channel);

768
  switch (channel->type)
769
    {
770
    case G_IO_WIN32_WINDOWS_MESSAGES:
771 772
      if (channel->debug)
	g_print (" MSG\n");
773
      return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE));
774 775

    case G_IO_WIN32_FILE_DESC:
776
      if (channel->debug)
777
	g_print (" FD thread=%#x buffer_condition=%s\n"
778 779 780 781 782 783 784 785 786 787
		 "  watch->pollfd.events={%s} watch->pollfd.revents={%s} channel->revents={%s}\n",
		 channel->thread_id, condition_to_string (buffer_condition),
		 condition_to_string (watch->pollfd.events),
		 condition_to_string (watch->pollfd.revents),
		 condition_to_string (channel->revents));
      
      watch->pollfd.revents = (watch->pollfd.events & channel->revents);

      return ((watch->pollfd.revents | buffer_condition) & watch->condition);

788
    case G_IO_WIN32_CONSOLE:
789 790
      if (channel->debug)
	g_print (" CON\n");
791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812
      if (watch->channel->is_writeable)
	return TRUE;
      else if (watch->channel->is_readable)
        {
	  INPUT_RECORD buffer;
	  DWORD n;
	  if (PeekConsoleInput ((HANDLE) watch->pollfd.fd, &buffer, 1, &n) &&
	      n == 1)
	    {
	      /* _kbhit() does quite complex processing to find out
	       * whether at least one of the key events pending corresponds
	       * to a "real" character that can be read.
	       */
	      if (_kbhit ())
		return TRUE;
	      
	      /* Discard all other kinds of events */
	      ReadConsoleInput ((HANDLE) watch->pollfd.fd, &buffer, 1, &n);
	    }
        }
      return FALSE;

813
    case G_IO_WIN32_SOCKET:
814 815
      if (channel->debug)
	g_print (" SOCK");
816 817 818
      if (channel->last_events & FD_WRITE)
	{
	  if (channel->debug)
819
	    g_print (" sock=%d event=%#x last_events has FD_WRITE",
820 821 822 823 824 825 826
		     channel->fd, watch->pollfd.fd);
	}
      else
	{
	  WSAEnumNetworkEvents (channel->fd, 0, &events);

	  if (channel->debug)
827 828
	    g_print ("\n  revents={%s} condition={%s}"
		     "\n  WSAEnumNetworkEvents(%d,0) sets events={%s}",
829 830
		     condition_to_string (watch->pollfd.revents),
		     condition_to_string (watch->condition),
831
		     channel->fd, 
832 833 834 835 836 837 838 839
		     event_mask_to_string (events.lNetworkEvents));
	  
	  if (watch->pollfd.revents != 0 &&
	      events.lNetworkEvents == 0 &&
	      !(channel->event_mask & FD_WRITE))
	    {
	      channel->event_mask = 0;
	      if (channel->debug)
840
		g_print ("\n  WSAEventSelect(%d,%#x,{})",
841 842 843
			 channel->fd, watch->pollfd.fd);
	      WSAEventSelect (channel->fd, (HANDLE) watch->pollfd.fd, 0);
	      if (channel->debug)
844
		g_print ("  ResetEvent(%#x)",
845 846 847 848 849 850 851 852
			 watch->pollfd.fd);
	      ResetEvent ((HANDLE) watch->pollfd.fd);
	    }
	  channel->last_events = events.lNetworkEvents;
	}
      watch->pollfd.revents = 0;
      if (channel->last_events & (FD_READ | FD_ACCEPT))
	watch->pollfd.revents |= G_IO_IN;
853
      if (channel->last_events & FD_WRITE)
854
	watch->pollfd.revents |= G_IO_OUT;
855 856 857 858 859 860 861 862 863 864 865 866 867 868 869
      else
	{
	  /* We have called WSAEnumNetworkEvents() above but it didn't
	   * set FD_WRITE.
	   */
	  if (events.lNetworkEvents & FD_CONNECT)
	    {
	      if (events.iErrorCode[FD_CONNECT_BIT] == 0)
		watch->pollfd.revents |= G_IO_OUT;
	      else
		watch->pollfd.revents |= (G_IO_HUP | G_IO_ERR);
	    }
	  if (watch->pollfd.revents == 0 && (channel->last_events & (FD_CLOSE)))
	    watch->pollfd.revents |= G_IO_HUP;
	}
870

871 872 873 874 875 876 877 878
      /* Regardless of WSAEnumNetworkEvents() result, if watching for
       * writability, unless last write would have blocked set
       * G_IO_OUT. But never set both G_IO_OUT and G_IO_HUP.
       */
      if (!(watch->pollfd.revents & G_IO_HUP) &&
	  !channel->write_would_have_blocked &&
	  (channel->event_mask & FD_WRITE))
	watch->pollfd.revents |= G_IO_OUT;
879

880 881 882 883 884
      if (channel->debug)
	g_print ("\n  revents={%s} retval={%s}\n",
		 condition_to_string (watch->pollfd.revents),
		 condition_to_string ((watch->pollfd.revents | buffer_condition) & watch->condition));

885 886 887 888 889 890
      return ((watch->pollfd.revents | buffer_condition) & watch->condition);

    default:
      g_assert_not_reached ();
      abort ();
    }
891 892 893
}

static gboolean
894 895 896
g_io_win32_dispatch (GSource     *source,
		     GSourceFunc  callback,
		     gpointer     user_data)
897
{
898
  GIOFunc func = (GIOFunc)callback;
899
  GIOWin32Watch *watch = (GIOWin32Watch *)source;
900
  GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
901
  GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
902
  
903 904
  if (!func)
    {
905
      g_warning (G_STRLOC ": GIOWin32Watch dispatched without callback\n"
906 907 908 909
		 "You must call g_source_connect().");
      return FALSE;
    }
  
910 911 912 913 914 915
  if (channel->debug)
    g_print ("g_io_win32_dispatch: pollfd.revents=%s condition=%s result=%s\n",
	     condition_to_string (watch->pollfd.revents),
	     condition_to_string (watch->condition),
	     condition_to_string ((watch->pollfd.revents | buffer_condition) & watch->condition));

916
  return (*func) (watch->channel,
917
		  (watch->pollfd.revents | buffer_condition) & watch->condition,
918
		  user_data);
919 920 921
}

static void
922
g_io_win32_finalize (GSource *source)
923
{
924
  GIOWin32Watch *watch = (GIOWin32Watch *)source;
925
  GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
926
  
927 928 929
  if (channel->debug)
    g_print ("g_io_win32_finalize: source=%p channel=%p", source, channel);

930 931 932
  switch (channel->type)
    {
    case G_IO_WIN32_WINDOWS_MESSAGES:
933 934 935 936
      if (channel->debug)
	g_print (" MSG");
      break;

937
    case G_IO_WIN32_CONSOLE:
938 939
      if (channel->debug)
	g_print (" CON");
940
      break;
941

942 943
    case G_IO_WIN32_FILE_DESC:
      if (channel->debug)
944
	g_print (" FD thread=%#x", channel->thread_id);
945 946 947 948
      break;

    case G_IO_WIN32_SOCKET:
      if (channel->debug)
949
	g_print (" SOCK sock=%d", channel->fd);
950 951 952 953 954 955 956 957 958 959 960
#if 0
      CloseHandle ((HANDLE) watch->pollfd.fd);
      channel->event = 0;
      channel->event_mask = 0;
#endif
      break;

    default:
      g_assert_not_reached ();
      abort ();
    }
961 962
  if (channel->debug)
    g_print ("\n");
963
  g_io_channel_unref (watch->channel);
964 965
}

966
GSourceFuncs g_io_watch_funcs = {
967 968 969
  g_io_win32_prepare,
  g_io_win32_check,
  g_io_win32_dispatch,
970
  g_io_win32_finalize
971
};
972

973
static GIOStatus
974 975
g_io_win32_msg_read (GIOChannel *channel,
		     gchar      *buf,
976 977 978
		     gsize       count,
		     gsize      *bytes_read,
		     GError    **err)
979
{
980
  GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
981 982
  MSG msg;               /* In case of alignment problems */
  
983
  if (count < sizeof (MSG))
984
    {
985 986
      g_set_error_literal (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
                           "Incorrect message size"); /* Informative enough error message? */
987 988
      return G_IO_STATUS_ERROR;
    }
989
  
990
  if (win32_channel->debug)
991 992
    g_print ("g_io_win32_msg_read: channel=%p hwnd=%#x\n",
	     channel, (guint) win32_channel->hwnd);
993
  if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
994
    return G_IO_STATUS_AGAIN;
995

996 997
  memmove (buf, &msg, sizeof (MSG));
  *bytes_read = sizeof (MSG);
998

999
  return G_IO_STATUS_NORMAL;
1000
}
1001

1002 1003 1004 1005 1006 1007
static GIOStatus
g_io_win32_msg_write (GIOChannel  *channel,
		      const gchar *buf,
		      gsize        count,
		      gsize       *bytes_written,
		      GError     **err)
1008
{
1009
  GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1010
  MSG msg;
1011
  
1012
  if (count != sizeof (MSG))
1013
    {
1014 1015
      g_set_error_literal (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_INVAL,
                           "Incorrect message size"); /* Informative enough error message? */
1016 1017
      return G_IO_STATUS_ERROR;
    }
1018
  
1019 1020 1021
  /* In case of alignment problems */
  memmove (&msg, buf, sizeof (MSG));
  if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
1022
    {
1023
      gchar *emsg = g_win32_error_message (GetLastError ());
1024
      g_set_error_literal (err, G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED, emsg);
1025
      g_free (emsg);
1026 1027 1028
      return G_IO_STATUS_ERROR;
    }

1029
  *bytes_written = sizeof (MSG);
1030 1031

  return G_IO_STATUS_NORMAL;
1032 1033
}

1034 1035 1036
static GIOStatus
g_io_win32_msg_close (GIOChannel *channel,
		      GError    **err)
1037 1038
{
  /* Nothing to be done. Or should we set hwnd to some invalid value? */
1039 1040

  return G_IO_STATUS_NORMAL;
1041 1042
}

1043
static void
1044 1045
g_io_win32_free (GIOChannel *channel)
{
1046
  GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1047
  
1048
  if (win32_channel->debug)
1049
    g_print ("g_io_win32_free channel=%p fd=%d\n", channel, win32_channel->fd);
1050

1051 1052 1053 1054
  if (win32_channel->data_avail_event)
    CloseHandle (win32_channel->data_avail_event);
  if (win32_channel->space_avail_event)
    CloseHandle (win32_channel->space_avail_event);
1055 1056
  if (win32_channel->type == G_IO_WIN32_SOCKET)
    WSAEventSelect (win32_channel->fd, NULL, 0);
1057
  DeleteCriticalSection (&win32_channel->mutex);
1058

1059
  g_free (win32_channel->buffer);
1060 1061 1062
  g_free (win32_channel);
}

1063
static GSource *
1064 1065
g_io_win32_msg_create_watch (GIOChannel   *channel,
			     GIOCondition  condition)
1066
{
1067 1068 1069
  GIOWin32Watch *watch;
  GSource *source;

1070
  source = g_source_new (&g_io_watch_funcs, sizeof (GIOWin32Watch));
1071
  watch = (GIOWin32Watch *)source;
1072 1073 1074
  
  watch->channel = channel;
  g_io_channel_ref (channel);
1075
  
1076
  watch->condition = condition;
1077
  
1078 1079
  watch->pollfd.fd = G_WIN32_MSG_HANDLE;
  watch->pollfd.events = condition;
1080
  
1081
  g_source_add_poll (source, &watch->pollfd);
1082
  
1083
  return source;
1084 1085
}

1086
static GIOStatus
1087 1088 1089 1090 1091
g_io_win32_fd_and_console_read (GIOChannel *channel,
				gchar      *buf,
				gsize       count,
				gsize      *bytes_read,
				GError    **err)
1092
{
1093
  GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1094
  gint result;
1095
  
1096
  if (win32_channel->debug)
1097
    g_print ("g_io_win32_fd_read: fd=%d count=%d\n",
1098 1099
	     win32_channel->fd, count);
  
1100 1101
  if (win32_channel->thread_id)
    {
1102
      return buffer_read (win32_channel, buf, count, bytes_read, err);
1103
    }
1104 1105

  result = read (win32_channel->fd, buf, count);
1106

1107
  if (win32_channel->debug)
1108
    g_print ("g_io_win32_fd_read: read() => %d\n", result);
1109

1110 1111 1112
  if (result < 0)
    {
      *bytes_read = 0;
1113

1114
      switch (errno)
1115 1116
        {
#ifdef EAGAIN
1117 1118
	case EAGAIN:
	  return G_IO_STATUS_AGAIN;
1119
#endif
1120
	default:
1121 1122 1123
	  g_set_error_literal (err, G_IO_CHANNEL_ERROR,
                               g_io_channel_error_from_errno (errno),
                               g_strerror (errno));
1124
	  return G_IO_STATUS_ERROR;
1125
        }
1126
    }
1127 1128 1129 1130

  *bytes_read = result;

  return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
1131
}
1132

1133
static GIOStatus
1134 1135 1136 1137 1138
g_io_win32_fd_and_console_write (GIOChannel  *channel,
				 const gchar *buf,
				 gsize        count,
				 gsize       *bytes_written,
				 GError     **err)
1139
{
1140
  GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
1141
  gint result;
1142 1143 1144 1145 1146

  if (win32_channel->thread_id)
    {
      return buffer_write (win32_channel, buf, count, bytes_written, err);
    }
1147
  
1148
  result = write (win32_channel->fd, buf, count);
1149
  if (win32_channel->debug)
1150
    g_print ("g_io_win32_fd_write: fd=%d count=%d => %d\n",
1151
	     win32_channel->fd, count, result);
1152

1153 1154 1155
  if (result < 0)
    {
      *bytes_written = 0;
1156