Main Page | Class List | Directories | File List | Class Members | File Members

giowin32.c

Go to the documentation of this file.
00001 /* GLIB - Library of useful routines for C programming
00002  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
00003  *
00004  * giowin32.c: IO Channels for Win32.
00005  * Copyright 1998 Owen Taylor and Tor Lillqvist
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Library General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Library General Public
00018  * License along with this library; if not, write to the
00019  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00020  * Boston, MA 02111-1307, USA.
00021  */
00022 
00023 /*
00024  * Modified by the GLib Team and others 1997-1999.  See the AUTHORS
00025  * file for a list of people on the GLib Team.  See the ChangeLog
00026  * files for a list of changes.  These files are distributed with
00027  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
00028  */
00029 
00030 
00031 #include "config.h"
00032 #include "glib.h"
00033 #include <windows.h>
00034 #include <winsock.h>            /* Not everybody has winsock2 */
00035 #include <fcntl.h>
00036 #include <io.h>
00037 #include <errno.h>
00038 #include <sys/types.h>
00039 
00040 #include <stdio.h>
00041 
00042 typedef struct _GIOWin32Channel GIOWin32Channel;
00043 typedef struct _GIOWin32Watch GIOWin32Watch;
00044 
00045 guint g_pipe_readable_msg;
00046 
00047 typedef enum {
00048   G_IO_WINDOWS_MESSAGES,        /* Windows messages */
00049   G_IO_FILE_DESC,               /* Unix-like file descriptors from _open*/
00050   G_IO_PIPE,                    /* pipe, with windows messages for signalling */
00051   G_IO_STREAM_SOCKET            /* Stream sockets */
00052 } GIOWin32ChannelType;
00053 
00054 struct _GIOWin32Channel {
00055   GIOChannel channel;
00056   gint fd;                      /* Either a Unix-like file handle as provided
00057                                  * by the Microsoft C runtime, or a SOCKET
00058                                  * as provided by WinSock.
00059                                  */
00060   GIOWin32ChannelType type;
00061 
00062   /* This is used by G_IO_WINDOWS_MESSAGES channels */
00063   HWND hwnd;                    /* handle of window, or NULL */
00064 
00065   /* This is used by G_IO_PIPE channels */
00066   guint peer;                   /* thread id of reader */
00067   guint peer_fd;                /* fd in the reader */
00068   guint offset;                 /* counter of accumulated bytes */
00069   guint need_wakeups;           /* in output channels whether the
00070                                  * reader needs wakeups
00071                                  */
00072 };
00073 
00074 struct _GIOWin32Watch {
00075   GPollFD       pollfd;
00076   GIOChannel   *channel;
00077   GIOCondition  condition;
00078   GIOFunc       callback;
00079 };
00080 
00081 static gboolean g_io_win32_msg_prepare  (gpointer  source_data, 
00082                                          GTimeVal *current_time,
00083                                          gint     *timeout);
00084 static gboolean g_io_win32_msg_check    (gpointer  source_data,
00085                                          GTimeVal *current_time);
00086 static gboolean g_io_win32_msg_dispatch (gpointer  source_data,
00087                                          GTimeVal *current_time,
00088                                          gpointer  user_data);
00089 
00090 static gboolean g_io_win32_fd_prepare  (gpointer  source_data, 
00091                                         GTimeVal *current_time,
00092                                         gint     *timeout);
00093 static gboolean g_io_win32_fd_check    (gpointer  source_data,
00094                                         GTimeVal *current_time);
00095 static gboolean g_io_win32_fd_dispatch (gpointer  source_data,
00096                                         GTimeVal *current_time,
00097                                         gpointer  user_data);
00098 
00099 static gboolean g_io_win32_pipe_prepare  (gpointer  source_data, 
00100                                           GTimeVal *current_time,
00101                                           gint     *timeout);
00102 static gboolean g_io_win32_pipe_check    (gpointer  source_data,
00103                                           GTimeVal *current_time);
00104 static gboolean g_io_win32_pipe_dispatch (gpointer  source_data,
00105                                           GTimeVal *current_time,
00106                                           gpointer  user_data);
00107 static void g_io_win32_pipe_destroy      (gpointer source_data);
00108 
00109 static gboolean g_io_win32_sock_prepare  (gpointer  source_data, 
00110                                           GTimeVal *current_time,
00111                                           gint     *timeout);
00112 static gboolean g_io_win32_sock_check    (gpointer  source_data,
00113                                           GTimeVal *current_time);
00114 static gboolean g_io_win32_sock_dispatch (gpointer  source_data,
00115                                           GTimeVal *current_time,
00116                                           gpointer  user_data);
00117 
00118 static void g_io_win32_destroy (gpointer source_data);
00119 
00120 static GIOError g_io_win32_msg_read (GIOChannel *channel, 
00121                                      gchar      *buf, 
00122                                      guint       count,
00123                                      guint      *bytes_written);
00124 
00125 static GIOError g_io_win32_msg_write(GIOChannel *channel, 
00126                                      gchar      *buf, 
00127                                      guint       count,
00128                                      guint      *bytes_written);
00129 static GIOError g_io_win32_msg_seek (GIOChannel *channel,
00130                                      gint        offset, 
00131                                      GSeekType   type);
00132 static void g_io_win32_msg_close    (GIOChannel *channel);
00133 static guint g_io_win32_msg_add_watch (GIOChannel      *channel,
00134                                        gint             priority,
00135                                        GIOCondition     condition,
00136                                        GIOFunc          func,
00137                                        gpointer         user_data,
00138                                        GDestroyNotify   notify);
00139 
00140 static GIOError g_io_win32_fd_read (GIOChannel *channel, 
00141                                     gchar      *buf, 
00142                                     guint       count,
00143                                     guint      *bytes_written);
00144 static GIOError g_io_win32_fd_write(GIOChannel *channel, 
00145                                     gchar      *buf, 
00146                                     guint       count,
00147                                     guint      *bytes_written);
00148 static GIOError g_io_win32_fd_seek (GIOChannel *channel,
00149                                     gint        offset, 
00150                                     GSeekType   type);
00151 static void g_io_win32_fd_close (GIOChannel *channel);
00152 
00153 static void g_io_win32_free (GIOChannel *channel);
00154 
00155 static guint g_io_win32_fd_add_watch (GIOChannel      *channel,
00156                                       gint             priority,
00157                                       GIOCondition     condition,
00158                                       GIOFunc          func,
00159                                       gpointer         user_data,
00160                                       GDestroyNotify   notify);
00161 
00162 static GIOError g_io_win32_no_seek (GIOChannel *channel,
00163                                     gint        offset, 
00164                                     GSeekType   type);
00165 
00166 static GIOError g_io_win32_pipe_read (GIOChannel *channel, 
00167                                       gchar      *buf, 
00168                                       guint       count,
00169                                       guint      *bytes_written);
00170 static GIOError g_io_win32_pipe_write (GIOChannel *channel, 
00171                                        gchar      *buf, 
00172                                        guint       count,
00173                                        guint      *bytes_written);
00174 static void g_io_win32_pipe_close    (GIOChannel *channel);
00175 static guint g_io_win32_pipe_add_watch (GIOChannel      *channel,
00176                                         gint             priority,
00177                                         GIOCondition     condition,
00178                                         GIOFunc          func,
00179                                         gpointer         user_data,
00180                                         GDestroyNotify   notify);
00181 static void g_io_win32_pipe_free (GIOChannel *channel);
00182 
00183 static GIOError g_io_win32_sock_read (GIOChannel *channel, 
00184                                       gchar      *buf, 
00185                                       guint       count,
00186                                       guint      *bytes_written);
00187 static GIOError g_io_win32_sock_write(GIOChannel *channel, 
00188                                       gchar      *buf, 
00189                                       guint       count,
00190                                       guint      *bytes_written);
00191 static void g_io_win32_sock_close    (GIOChannel *channel);
00192 static guint g_io_win32_sock_add_watch (GIOChannel      *channel,
00193                                         gint             priority,
00194                                         GIOCondition     condition,
00195                                         GIOFunc          func,
00196                                         gpointer         user_data,
00197                                         GDestroyNotify   notify);
00198 
00199 GSourceFuncs win32_watch_msg_funcs = {
00200   g_io_win32_msg_prepare,
00201   g_io_win32_msg_check,
00202   g_io_win32_msg_dispatch,
00203   g_io_win32_destroy
00204 };
00205 
00206 GSourceFuncs win32_watch_fd_funcs = {
00207   g_io_win32_fd_prepare,
00208   g_io_win32_fd_check,
00209   g_io_win32_fd_dispatch,
00210   g_io_win32_destroy
00211 };
00212 
00213 GSourceFuncs win32_watch_pipe_funcs = {
00214   g_io_win32_pipe_prepare,
00215   g_io_win32_pipe_check,
00216   g_io_win32_pipe_dispatch,
00217   g_io_win32_pipe_destroy
00218 };
00219 
00220 GSourceFuncs win32_watch_sock_funcs = {
00221   g_io_win32_sock_prepare,
00222   g_io_win32_sock_check,
00223   g_io_win32_sock_dispatch,
00224   g_io_win32_destroy
00225 };
00226 
00227 GIOFuncs win32_channel_msg_funcs = {
00228   g_io_win32_msg_read,
00229   g_io_win32_msg_write,
00230   g_io_win32_no_seek,
00231   g_io_win32_msg_close,
00232   g_io_win32_msg_add_watch,
00233   g_io_win32_free
00234 };
00235 
00236 GIOFuncs win32_channel_fd_funcs = {
00237   g_io_win32_fd_read,
00238   g_io_win32_fd_write,
00239   g_io_win32_fd_seek,
00240   g_io_win32_fd_close,
00241   g_io_win32_fd_add_watch,
00242   g_io_win32_free
00243 };
00244 
00245 GIOFuncs win32_channel_pipe_funcs = {
00246   g_io_win32_pipe_read,
00247   g_io_win32_pipe_write,
00248   g_io_win32_no_seek,
00249   g_io_win32_pipe_close,
00250   g_io_win32_pipe_add_watch,
00251   g_io_win32_pipe_free
00252 };
00253 
00254 GIOFuncs win32_channel_sock_funcs = {
00255   g_io_win32_sock_read,
00256   g_io_win32_sock_write,
00257   g_io_win32_no_seek,
00258   g_io_win32_sock_close,
00259   g_io_win32_sock_add_watch,
00260   g_io_win32_free
00261 };
00262 
00263 #define N_WATCHED_PIPES 4
00264 
00265 static struct {
00266   gint fd;
00267   GIOWin32Watch *watch;
00268   GIOWin32Channel *channel;
00269   gpointer user_data;
00270 } watched_pipes[N_WATCHED_PIPES];
00271 
00272 static gint n_watched_pipes = 0;
00273 
00274 static gboolean
00275 g_io_win32_msg_prepare  (gpointer source_data, 
00276                          GTimeVal *current_time,
00277                          gint    *timeout)
00278 {
00279   GIOWin32Watch *data = source_data;
00280   GIOWin32Channel *win32_channel = (GIOWin32Channel *) data->channel;
00281   MSG msg;
00282 
00283   *timeout = -1;
00284 
00285   return PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_NOREMOVE) == TRUE;
00286 }
00287 
00288 static gboolean 
00289 g_io_win32_msg_check    (gpointer source_data,
00290                          GTimeVal *current_time)
00291 {
00292   GIOWin32Watch *data = source_data;
00293   GIOWin32Channel *win32_channel = (GIOWin32Channel *) data->channel;
00294   MSG msg;
00295 
00296   return PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_NOREMOVE) == TRUE;
00297 }
00298 
00299 static gboolean
00300 g_io_win32_msg_dispatch (gpointer source_data, 
00301                          GTimeVal *current_time,
00302                          gpointer user_data)
00303 
00304 {
00305   GIOWin32Watch *data = source_data;
00306 
00307   return (*data->callback)(data->channel,
00308                            data->pollfd.revents & data->condition,
00309                            user_data);
00310 }
00311 
00312 static void
00313 g_io_win32_destroy (gpointer source_data)
00314 {
00315   GIOWin32Watch *data = source_data;
00316 
00317   g_main_remove_poll (&data->pollfd);
00318   g_io_channel_unref (data->channel);
00319   g_free (data);
00320 }
00321 
00322 static gboolean
00323 g_io_win32_fd_prepare  (gpointer source_data, 
00324                         GTimeVal *current_time,
00325                         gint    *timeout)
00326 {
00327   *timeout = -1;
00328 
00329   return FALSE;
00330 }
00331 
00332 static gboolean 
00333 g_io_win32_fd_check    (gpointer source_data,
00334                         GTimeVal *current_time)
00335 {
00336   GIOWin32Watch *data = source_data;
00337 
00338   return (data->pollfd.revents & data->condition);
00339 }
00340 
00341 static gboolean
00342 g_io_win32_fd_dispatch (gpointer source_data, 
00343                         GTimeVal *current_time,
00344                         gpointer user_data)
00345 
00346 {
00347   GIOWin32Watch *data = source_data;
00348 
00349   return (*data->callback)(data->channel,
00350                            data->pollfd.revents & data->condition,
00351                            user_data);
00352 }
00353 
00354 static GIOError
00355 g_io_win32_msg_read (GIOChannel *channel, 
00356                      gchar     *buf, 
00357                      guint      count,
00358                      guint     *bytes_read)
00359 {
00360   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00361   MSG msg;                      /* In case of alignment problems */
00362 
00363   if (count < sizeof (MSG))
00364     return G_IO_ERROR_INVAL;
00365   
00366   if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
00367     return G_IO_ERROR_AGAIN;
00368 
00369   memmove (buf, &msg, sizeof (MSG));
00370   *bytes_read = sizeof (MSG);
00371   return G_IO_ERROR_NONE;
00372 }
00373                        
00374 static GIOError 
00375 g_io_win32_msg_write(GIOChannel *channel, 
00376                      gchar     *buf, 
00377                      guint      count,
00378                      guint     *bytes_written)
00379 {
00380   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00381   MSG msg;
00382   gint result;
00383 
00384   if (count != sizeof (MSG))
00385     return G_IO_ERROR_INVAL;
00386 
00387   /* In case of alignment problems */
00388   memmove (&msg, buf, sizeof (MSG));
00389   if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
00390     return G_IO_ERROR_UNKNOWN;
00391 
00392   *bytes_written = sizeof (MSG);
00393   return G_IO_ERROR_NONE; 
00394 }
00395 
00396 static GIOError 
00397 g_io_win32_no_seek (GIOChannel *channel,
00398                     gint      offset, 
00399                     GSeekType type)
00400 {
00401   g_warning ("g_io_win32_no_seek: unseekable IO channel type");
00402   return G_IO_ERROR_UNKNOWN;
00403 }
00404 
00405 
00406 static void 
00407 g_io_win32_msg_close (GIOChannel *channel)
00408 {
00409   /* Nothing to be done. Or should we set hwnd to some invalid value? */
00410 }
00411 
00412 static void 
00413 g_io_win32_free (GIOChannel *channel)
00414 {
00415   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00416 
00417   g_free (win32_channel);
00418 }
00419 
00420 static guint 
00421 g_io_win32_msg_add_watch (GIOChannel    *channel,
00422                           gint           priority,
00423                           GIOCondition   condition,
00424                           GIOFunc        func,
00425                           gpointer       user_data,
00426                           GDestroyNotify notify)
00427 {
00428   GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
00429   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00430   
00431   watch->channel = channel;
00432   g_io_channel_ref (channel);
00433 
00434   watch->callback = func;
00435   watch->condition = condition;
00436 
00437   watch->pollfd.fd = G_WIN32_MSG_HANDLE;
00438   watch->pollfd.events = condition;
00439 
00440   g_main_add_poll (&watch->pollfd, priority);
00441 
00442   return g_source_add (priority, TRUE, &win32_watch_msg_funcs,
00443                        watch, user_data, notify);
00444 }
00445 
00446 static gboolean
00447 g_io_win32_pipe_prepare  (gpointer source_data, 
00448                           GTimeVal *current_time,
00449                           gint    *timeout)
00450 {
00451   *timeout = -1;
00452 
00453   return FALSE;
00454 }
00455 
00456 static gboolean 
00457 g_io_win32_pipe_check    (gpointer source_data,
00458                           GTimeVal *current_time)
00459 {
00460   GIOWin32Watch *data = source_data;
00461   return FALSE;
00462 }
00463 
00464 static gboolean
00465 g_io_win32_pipe_dispatch (gpointer source_data, 
00466                           GTimeVal *current_time,
00467                           gpointer user_data)
00468 
00469 {
00470   GIOWin32Watch *data = source_data;
00471 
00472   return (*data->callback)(data->channel,
00473                            data->pollfd.revents & data->condition,
00474                            user_data);
00475 }
00476 
00477 static void
00478 g_io_win32_pipe_destroy (gpointer source_data)
00479 {
00480   GIOWin32Watch *data = source_data;
00481 
00482   g_io_channel_unref (data->channel);
00483   g_free (data);
00484 }
00485 
00486 static gboolean
00487 g_io_win32_sock_prepare  (gpointer source_data, 
00488                         GTimeVal *current_time,
00489                         gint    *timeout)
00490 {
00491   *timeout = -1;
00492 
00493   return FALSE;
00494 }
00495 
00496 static gboolean 
00497 g_io_win32_sock_check    (gpointer source_data,
00498                         GTimeVal *current_time)
00499 {
00500   GIOWin32Watch *data = source_data;
00501 
00502   return (data->pollfd.revents & data->condition);
00503 }
00504 
00505 static gboolean
00506 g_io_win32_sock_dispatch (gpointer source_data, 
00507                         GTimeVal *current_time,
00508                         gpointer user_data)
00509 
00510 {
00511   GIOWin32Watch *data = source_data;
00512 
00513   return (*data->callback)(data->channel,
00514                            data->pollfd.revents & data->condition,
00515                            user_data);
00516 }
00517 
00518 static GIOError
00519 g_io_win32_fd_read (GIOChannel *channel, 
00520                     gchar     *buf, 
00521                     guint      count,
00522                     guint     *bytes_read)
00523 {
00524   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00525   gint result;
00526 
00527   result = read (win32_channel->fd, buf, count);
00528   if (result < 0)
00529     {
00530       *bytes_read = 0;
00531       switch (errno)
00532         {
00533         case EINVAL:
00534           return G_IO_ERROR_INVAL;
00535         case EAGAIN:
00536           return G_IO_ERROR_AGAIN;
00537         default:
00538           return G_IO_ERROR_UNKNOWN;
00539         }
00540     }
00541   else
00542     {
00543       *bytes_read = result;
00544       return G_IO_ERROR_NONE;
00545     }
00546 }
00547                        
00548 static GIOError 
00549 g_io_win32_fd_write(GIOChannel *channel, 
00550                     gchar     *buf, 
00551                     guint      count,
00552                     guint     *bytes_written)
00553 {
00554   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00555   gint result;
00556 
00557   result = write (win32_channel->fd, buf, count);
00558       
00559   if (result < 0)
00560     {
00561       *bytes_written = 0;
00562       switch (errno)
00563         {
00564         case EINVAL:
00565           return G_IO_ERROR_INVAL;
00566         case EAGAIN:
00567           return G_IO_ERROR_AGAIN;
00568         default:
00569           return G_IO_ERROR_UNKNOWN;
00570         }
00571     }
00572   else
00573     {
00574       *bytes_written = result;
00575       return G_IO_ERROR_NONE;
00576     }
00577 }
00578 
00579 static GIOError 
00580 g_io_win32_fd_seek (GIOChannel *channel,
00581                     gint      offset, 
00582                     GSeekType type)
00583 {
00584   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00585   int whence;
00586   off_t result;
00587 
00588   switch (type)
00589     {
00590     case G_SEEK_SET:
00591       whence = SEEK_SET;
00592       break;
00593     case G_SEEK_CUR:
00594       whence = SEEK_CUR;
00595       break;
00596     case G_SEEK_END:
00597       whence = SEEK_END;
00598       break;
00599     default:
00600       g_warning ("g_io_win32_fd_seek: unknown seek type");
00601       return G_IO_ERROR_UNKNOWN;
00602     }
00603   
00604   result = lseek (win32_channel->fd, offset, whence);
00605   
00606   if (result < 0)
00607     {
00608       switch (errno)
00609         {
00610         case EINVAL:
00611           return G_IO_ERROR_INVAL;
00612         default:
00613           return G_IO_ERROR_UNKNOWN;
00614         }
00615     }
00616   else
00617     return G_IO_ERROR_NONE;
00618 }
00619 
00620 static void 
00621 g_io_win32_fd_close (GIOChannel *channel)
00622 {
00623   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00624 
00625   close (win32_channel->fd);
00626   return;
00627 }
00628 
00629 static guint 
00630 g_io_win32_fd_add_watch (GIOChannel    *channel,
00631                          gint           priority,
00632                          GIOCondition   condition,
00633                          GIOFunc        func,
00634                          gpointer       user_data,
00635                          GDestroyNotify notify)
00636 {
00637   GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
00638   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00639   
00640   watch->channel = channel;
00641   g_io_channel_ref (channel);
00642 
00643   watch->callback = func;
00644   watch->condition = condition;
00645 
00646   /* This probably does not work, except for CONIN$. */
00647   watch->pollfd.fd = _get_osfhandle (win32_channel->fd);
00648   watch->pollfd.events = condition;
00649 
00650   g_main_add_poll (&watch->pollfd, priority);
00651 
00652   return g_source_add (priority, TRUE, &win32_watch_fd_funcs,
00653                        watch, user_data, notify);
00654 }
00655 
00656 static GIOError
00657 g_io_win32_pipe_read (GIOChannel *channel, 
00658                       gchar     *buf, 
00659                       guint      count,
00660                       guint     *bytes_read)
00661 {
00662   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00663   HANDLE handle;
00664   DWORD avail;
00665   gint result;
00666 
00667   handle = (HANDLE) _get_osfhandle (win32_channel->fd);
00668   if (!PeekNamedPipe (handle, NULL, 0, NULL, &avail, NULL))
00669     {
00670       return G_IO_ERROR_UNKNOWN;
00671     }
00672 
00673   count = MIN (count, avail);
00674 
00675   count = MAX (count, 1);       /* Must read at least one byte, or
00676                                  * caller will think it's EOF.
00677                                  */
00678   /* g_print ("g_io_win32_pipe_read: %d %d\n", win32_channel->fd, count); */
00679   if (count == 0)
00680     result = 0;
00681   else
00682     result = read (win32_channel->fd, buf, count);
00683   if (result < 0)
00684     {
00685       *bytes_read = 0;
00686       switch (errno)
00687         {
00688         case EINVAL:
00689           return G_IO_ERROR_INVAL;
00690         case EAGAIN:
00691           return G_IO_ERROR_AGAIN;
00692         default:
00693           return G_IO_ERROR_UNKNOWN;
00694         }
00695     }
00696   else
00697     {
00698       *bytes_read = result;
00699       win32_channel->offset += result;
00700       /* g_print ("=%d (%d)\n", result, win32_channel->offset); */
00701       return G_IO_ERROR_NONE;
00702     }
00703 }
00704                        
00705 static GIOError 
00706 g_io_win32_pipe_write(GIOChannel *channel, 
00707                       gchar     *buf, 
00708                       guint      count,
00709                       guint     *bytes_written)
00710 {
00711   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00712   LONG prevcnt;
00713   gint result;
00714 
00715   /* g_print ("g_io_win32_pipe_write: %d %d\n", win32_channel->fd, count); */
00716   result = write (win32_channel->fd, buf, count);
00717   if (result < 0)
00718     {
00719       *bytes_written = 0;
00720       switch (errno)
00721         {
00722         case EINVAL:
00723           return G_IO_ERROR_INVAL;
00724         case EAGAIN:
00725           return G_IO_ERROR_AGAIN;
00726         default:
00727           return G_IO_ERROR_UNKNOWN;
00728         }
00729     }
00730   else
00731     {
00732       if (g_pipe_readable_msg == 0)
00733         g_pipe_readable_msg = RegisterWindowMessage ("g-pipe-readable");
00734 
00735       win32_channel->offset += result;
00736       /* g_print ("=%d (%d)\n", result, win32_channel->offset); */
00737       if (win32_channel->need_wakeups)
00738         {
00739           PostThreadMessage (win32_channel->peer,
00740                              g_pipe_readable_msg,
00741                              win32_channel->peer_fd,
00742                              win32_channel->offset);
00743         }
00744       *bytes_written = result;
00745       return G_IO_ERROR_NONE;
00746     }
00747 }
00748 
00749 static void 
00750 g_io_win32_pipe_close (GIOChannel *channel)
00751 {
00752   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00753 
00754   /* g_print ("g_io_win32_pipe_close: %#x %d\n", channel, win32_channel->fd); */
00755 
00756   close (win32_channel->fd);
00757   return;
00758 }
00759 
00760 static guint 
00761 g_io_win32_pipe_add_watch (GIOChannel    *channel,
00762                            gint           priority,
00763                            GIOCondition   condition,
00764                            GIOFunc        func,
00765                            gpointer       user_data,
00766                            GDestroyNotify notify)
00767 {
00768   GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
00769   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00770   gint i;
00771   
00772   /* g_print ("g_io_win32_pipe_add_watch: %d\n", win32_channel->fd); */
00773 
00774   watch->channel = channel;
00775   g_io_channel_ref (channel);
00776 
00777   watch->callback = func;
00778   watch->condition = condition;
00779 
00780   watch->pollfd.fd = win32_channel->fd;
00781   watch->pollfd.events = condition;
00782 
00783   for (i = 0; i < n_watched_pipes; i++)
00784     if (watched_pipes[i].fd == -1)
00785       break;
00786   if (i == N_WATCHED_PIPES)
00787     g_error ("Too many watched pipes");
00788   else
00789     {
00790       watched_pipes[i].fd = win32_channel->fd;
00791       watched_pipes[i].watch = watch;
00792       watched_pipes[i].channel = win32_channel;
00793       watched_pipes[i].user_data = user_data;
00794       n_watched_pipes = MAX (i + 1, n_watched_pipes);
00795     }
00796   return g_source_add (priority, FALSE, &win32_watch_pipe_funcs, watch, user_data, notify);
00797 }
00798 
00799 static void
00800 g_io_win32_pipe_free (GIOChannel *channel)
00801 {
00802   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00803   gint i;
00804 
00805   /* g_print ("g_io_win32_pipe_free: %#x %#x\n", channel, channel->channel_data); */
00806 
00807   for (i = 0; i < n_watched_pipes; i++)
00808     if (watched_pipes[i].fd == win32_channel->fd)
00809       {
00810         watched_pipes[i].fd = -1;
00811         break;
00812       }
00813   g_io_win32_free (channel);
00814 }
00815 
00816 static GIOError 
00817 g_io_win32_sock_read (GIOChannel *channel, 
00818                       gchar      *buf, 
00819                       guint       count,
00820                       guint      *bytes_read)
00821 {
00822   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00823   gint result;
00824 
00825   result = recv (win32_channel->fd, buf, count, 0);
00826   if (result == SOCKET_ERROR)
00827     {
00828       *bytes_read = 0;
00829       switch (WSAGetLastError ())
00830         {
00831         case WSAEINVAL:
00832           return G_IO_ERROR_INVAL;
00833         case WSAEWOULDBLOCK:
00834         case WSAEINTR:
00835           return G_IO_ERROR_AGAIN;
00836         default:
00837           return G_IO_ERROR_UNKNOWN;
00838         }
00839     }
00840   else
00841     {
00842       *bytes_read = result;
00843       return G_IO_ERROR_NONE;
00844     }
00845 }
00846                        
00847 static GIOError 
00848 g_io_win32_sock_write(GIOChannel *channel, 
00849                       gchar      *buf, 
00850                       guint       count,
00851                       guint      *bytes_written)
00852 {
00853   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00854   gint result;
00855 
00856   result = send (win32_channel->fd, buf, count, 0);
00857       
00858   if (result == SOCKET_ERROR)
00859     {
00860       *bytes_written = 0;
00861       switch (WSAGetLastError ())
00862         {
00863         case WSAEINVAL:
00864           return G_IO_ERROR_INVAL;
00865         case WSAEWOULDBLOCK:
00866         case WSAEINTR:
00867           return G_IO_ERROR_AGAIN;
00868         default:
00869           return G_IO_ERROR_UNKNOWN;
00870         }
00871     }
00872   else
00873     {
00874       *bytes_written = result;
00875       return G_IO_ERROR_NONE;
00876     }
00877 }
00878 
00879 static void 
00880 g_io_win32_sock_close (GIOChannel *channel)
00881 {
00882   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00883 
00884   closesocket (win32_channel->fd);
00885   return;
00886 }
00887 
00888 static guint 
00889 g_io_win32_sock_add_watch (GIOChannel    *channel,
00890                            gint           priority,
00891                            GIOCondition   condition,
00892                            GIOFunc        func,
00893                            gpointer       user_data,
00894                            GDestroyNotify notify)
00895 {
00896   GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
00897   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00898   
00899   watch->channel = channel;
00900   g_io_channel_ref (channel);
00901 
00902   watch->callback = func;
00903   watch->condition = condition;
00904 
00905   watch->pollfd.fd = win32_channel->fd;
00906   watch->pollfd.events = condition;
00907 
00908   g_main_add_poll (&watch->pollfd, priority);
00909 
00910   return g_source_add (priority, TRUE, &win32_watch_sock_funcs, watch, user_data, notify);
00911 }
00912 
00913 GIOChannel *
00914 g_io_channel_win32_new_messages (guint hwnd)
00915 {
00916   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
00917   GIOChannel *channel = (GIOChannel *) win32_channel;
00918 
00919   g_io_channel_init (channel);
00920   channel->funcs = &win32_channel_msg_funcs;
00921   win32_channel->fd = -1;
00922   win32_channel->type = G_IO_WINDOWS_MESSAGES;
00923   win32_channel->hwnd = (HWND) hwnd;
00924 
00925   return channel;
00926 }
00927 
00928 GIOChannel *
00929 g_io_channel_unix_new (gint fd)
00930 {
00931   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
00932   GIOChannel *channel = (GIOChannel *) win32_channel;
00933 
00934   g_io_channel_init (channel);
00935   channel->funcs = &win32_channel_fd_funcs;
00936   win32_channel->fd = fd;
00937   win32_channel->type = G_IO_FILE_DESC;
00938 
00939   return channel;
00940 }
00941 
00942 gint
00943 g_io_channel_unix_get_fd (GIOChannel *channel)
00944 {
00945   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
00946 
00947   return win32_channel->fd;
00948 }
00949 
00950 GIOChannel *
00951 g_io_channel_win32_new_pipe_with_wakeups (int   fd,
00952                                           guint peer,
00953                                           int   peer_fd)
00954 {
00955   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
00956   GIOChannel *channel = (GIOChannel *) win32_channel;
00957 
00958   /* g_print ("g_io_channel_win32_new_pipe_with_wakeups %d %#x %d\n", fd, peer, peer_fd); */
00959 
00960   g_io_channel_init (channel);
00961   channel->funcs = &win32_channel_pipe_funcs;
00962   win32_channel->fd = fd;
00963   win32_channel->type = G_IO_PIPE;
00964   win32_channel->peer = peer;
00965   win32_channel->peer_fd = peer_fd;
00966   win32_channel->offset = 0;
00967   win32_channel->need_wakeups = TRUE;
00968 
00969   return channel;
00970 }
00971 
00972 GIOChannel *
00973 g_io_channel_win32_new_pipe (int fd)
00974 {
00975   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
00976   GIOChannel *channel = (GIOChannel *) win32_channel;
00977 
00978   g_io_channel_init (channel);
00979   channel->funcs = &win32_channel_pipe_funcs;
00980   win32_channel->fd = fd;
00981   win32_channel->type = G_IO_PIPE;
00982   win32_channel->offset = 0;
00983   win32_channel->need_wakeups = FALSE;
00984 
00985   return channel;
00986 }
00987 
00988 GIOChannel *
00989 g_io_channel_win32_new_stream_socket (int socket)
00990 {
00991   GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
00992   GIOChannel *channel = (GIOChannel *) win32_channel;
00993 
00994   g_io_channel_init (channel);
00995   channel->funcs = &win32_channel_sock_funcs;
00996   win32_channel->fd = socket;
00997   win32_channel->type = G_IO_STREAM_SOCKET;
00998 
00999   return channel;
01000 }
01001 
01002 gint
01003 g_io_channel_win32_get_fd (GIOChannel *channel)
01004 {
01005   return g_io_channel_unix_get_fd (channel);
01006 }
01007 
01008 void
01009 g_io_channel_win32_pipe_request_wakeups (GIOChannel *channel,
01010                                          guint       peer,
01011                                          int         peer_fd)
01012 {
01013   GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
01014 
01015   win32_channel->peer = peer;
01016   win32_channel->peer_fd = peer_fd;
01017   win32_channel->need_wakeups = TRUE;
01018 }
01019 
01020 void
01021 g_io_channel_win32_pipe_readable (gint  fd,
01022                                   guint offset)
01023 {
01024   gint i;
01025 
01026   for (i = 0; i < n_watched_pipes; i++)
01027     if (watched_pipes[i].fd == fd)
01028       {
01029         if (watched_pipes[i].channel->offset < offset)
01030           (*watched_pipes[i].watch->callback) (watched_pipes[i].watch->channel,
01031                                                G_IO_IN,
01032                                                watched_pipes[i].user_data);
01033         break;
01034       }
01035 }

© sourcejam.com 2005-2008