Bug 621213 – GDBusProxy and well-known names
[platform/upstream/glib.git] / gio / gwin32inputstream.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright (C) 2006-2010 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Alexander Larsson <alexl@redhat.com>
21  * Author: Tor Lillqvist <tml@iki.fi>
22  */
23
24 #include "config.h"
25
26 #include <windows.h>
27
28 #include <io.h>
29
30 #include <glib.h>
31 #include "gioerror.h"
32 #include "gsimpleasyncresult.h"
33 #include "gwin32inputstream.h"
34 #include "gcancellable.h"
35 #include "gasynchelper.h"
36 #include "glibintl.h"
37
38 #include "gioalias.h"
39
40 /**
41  * SECTION:gwin32inputstream
42  * @short_description: Streaming input operations for Windows file handles
43  * @include: gio/gwin32inputstream.h
44  * @see_also: #GInputStream
45  *
46  * #GWin32InputStream implements #GInputStream for reading from a
47  * Windows file handle.
48  *
49  * Note that <filename>&lt;gio/gwin32inputstream.h&gt;</filename> belongs
50  * to the Windows-specific GIO interfaces, thus you have to use the
51  * <filename>gio-windows-2.0.pc</filename> pkg-config file when using it.
52  */
53
54 enum {
55   PROP_0,
56   PROP_HANDLE,
57   PROP_CLOSE_HANDLE
58 };
59
60 G_DEFINE_TYPE (GWin32InputStream, g_win32_input_stream, G_TYPE_INPUT_STREAM);
61
62 struct _GWin32InputStreamPrivate {
63   HANDLE handle;
64   gboolean close_handle;
65 };
66
67 static void     g_win32_input_stream_set_property (GObject              *object,
68                                                    guint                 prop_id,
69                                                    const GValue         *value,
70                                                    GParamSpec           *pspec);
71 static void     g_win32_input_stream_get_property (GObject              *object,
72                                                    guint                 prop_id,
73                                                    GValue               *value,
74                                                    GParamSpec           *pspec);
75 static gssize   g_win32_input_stream_read         (GInputStream         *stream,
76                                                    void                 *buffer,
77                                                    gsize                 count,
78                                                    GCancellable         *cancellable,
79                                                    GError              **error);
80 static gboolean g_win32_input_stream_close        (GInputStream         *stream,
81                                                    GCancellable         *cancellable,
82                                                    GError              **error);
83
84 static void
85 g_win32_input_stream_finalize (GObject *object)
86 {
87   G_OBJECT_CLASS (g_win32_input_stream_parent_class)->finalize (object);
88 }
89
90 static void
91 g_win32_input_stream_class_init (GWin32InputStreamClass *klass)
92 {
93   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
94   GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
95
96   g_type_class_add_private (klass, sizeof (GWin32InputStreamPrivate));
97
98   gobject_class->get_property = g_win32_input_stream_get_property;
99   gobject_class->set_property = g_win32_input_stream_set_property;
100   gobject_class->finalize = g_win32_input_stream_finalize;
101
102   stream_class->read_fn = g_win32_input_stream_read;
103   stream_class->close_fn = g_win32_input_stream_close;
104
105   /**
106    * GWin32InputStream:handle:
107    *
108    * The handle that the stream reads from.
109    *
110    * Since: 2.26
111    */
112   g_object_class_install_property (gobject_class,
113                                    PROP_HANDLE,
114                                    g_param_spec_pointer ("handle",
115                                                          P_("File handle"),
116                                                          P_("The file handle to read from"),
117                                                          G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
118
119   /**
120    * GWin32InputStream:close-handle:
121    *
122    * Whether to close the file handle when the stream is closed.
123    *
124    * Since: 2.26
125    */
126   g_object_class_install_property (gobject_class,
127                                    PROP_CLOSE_HANDLE,
128                                    g_param_spec_boolean ("close-handle",
129                                                          P_("Close file handle"),
130                                                          P_("Whether to close the file handle when the stream is closed"),
131                                                          TRUE,
132                                                          G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
133 }
134
135 static void
136 g_win32_input_stream_set_property (GObject         *object,
137                                    guint            prop_id,
138                                    const GValue    *value,
139                                    GParamSpec      *pspec)
140 {
141   GWin32InputStream *win32_stream;
142
143   win32_stream = G_WIN32_INPUT_STREAM (object);
144
145   switch (prop_id)
146     {
147     case PROP_HANDLE:
148       win32_stream->priv->handle = g_value_get_pointer (value);
149       break;
150     case PROP_CLOSE_HANDLE:
151       win32_stream->priv->close_handle = g_value_get_boolean (value);
152       break;
153     default:
154       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
155       break;
156     }
157 }
158
159 static void
160 g_win32_input_stream_get_property (GObject    *object,
161                                    guint       prop_id,
162                                    GValue     *value,
163                                    GParamSpec *pspec)
164 {
165   GWin32InputStream *win32_stream;
166
167   win32_stream = G_WIN32_INPUT_STREAM (object);
168
169   switch (prop_id)
170     {
171     case PROP_HANDLE:
172       g_value_set_pointer (value, win32_stream->priv->handle);
173       break;
174     case PROP_CLOSE_HANDLE:
175       g_value_set_boolean (value, win32_stream->priv->close_handle);
176       break;
177     default:
178       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
179     }
180 }
181
182 static void
183 g_win32_input_stream_init (GWin32InputStream *win32_stream)
184 {
185   win32_stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (win32_stream,
186                                                     G_TYPE_WIN32_INPUT_STREAM,
187                                                     GWin32InputStreamPrivate);
188
189   win32_stream->priv->handle = NULL;
190   win32_stream->priv->close_handle = TRUE;
191 }
192
193 /**
194  * g_win32_input_stream_new:
195  * @handle: a Win32 file handle
196  * @close_fd: %TRUE to close the handle when done
197  *
198  * Creates a new #GWin32InputStream for the given @fd.
199  *
200  * If @close_handle is %TRUE, the handle will be closed
201  * when the stream is closed.
202  *
203  * Note that "handle" here means a Win32 HANDLE, not a "file descriptor"
204  * as used in the Windows C libraries.
205  *
206  * Returns: a new #GWin32InputStream
207  **/
208 GInputStream *
209 g_win32_input_stream_new (void     *handle,
210                           gboolean close_handle)
211 {
212   GWin32InputStream *stream;
213
214   g_return_val_if_fail (handle != NULL, NULL);
215
216   stream = g_object_new (G_TYPE_WIN32_INPUT_STREAM,
217                          "handle", handle,
218                          "close-handle", close_handle,
219                          NULL);
220
221   return G_INPUT_STREAM (stream);
222 }
223
224 /**
225  * g_win32_input_stream_set_close_handle:
226  * @stream: a #GWin32InputStream
227  * @close_handle: %TRUE to close the handle when done
228  *
229  * Sets whether the handle of @stream shall be closed
230  * when the stream is closed.
231  *
232  * Since: 2.26
233  */
234 void
235 g_win32_input_stream_set_close_handle (GWin32InputStream *stream,
236                                        gboolean          close_handle)
237 {
238   g_return_if_fail (G_IS_WIN32_INPUT_STREAM (stream));
239
240   close_handle = close_handle != FALSE;
241   if (stream->priv->close_handle != close_handle)
242     {
243       stream->priv->close_handle = close_handle;
244       g_object_notify (G_OBJECT (stream), "close-handle");
245     }
246 }
247
248 /**
249  * g_win32_input_stream_get_close_handle:
250  * @stream: a #GWin32InputStream
251  *
252  * Returns whether the handle of @stream will be
253  * closed when the stream is closed.
254  *
255  * Return value: %TRUE if the handle is closed when done
256  *
257  * Since: 2.26
258  */
259 gboolean
260 g_win32_input_stream_get_close_handle (GWin32InputStream *stream)
261 {
262   g_return_val_if_fail (G_IS_WIN32_INPUT_STREAM (stream), FALSE);
263
264   return stream->priv->close_handle;
265 }
266
267 /**
268  * g_win32_input_stream_get_handle:
269  * @stream: a #GWin32InputStream
270  *
271  * Return the Windows file handle that the stream reads from.
272  *
273  * Return value: The file handle of @stream
274  *
275  * Since: 2.26
276  */
277 void *
278 g_win32_input_stream_get_handle (GWin32InputStream *stream)
279 {
280   g_return_val_if_fail (G_IS_WIN32_INPUT_STREAM (stream), NULL);
281
282   return stream->priv->handle;
283 }
284
285 static gssize
286 g_win32_input_stream_read (GInputStream  *stream,
287                            void          *buffer,
288                            gsize          count,
289                            GCancellable  *cancellable,
290                            GError       **error)
291 {
292   GWin32InputStream *win32_stream;
293   BOOL res;
294   DWORD nbytes, nread;
295
296   win32_stream = G_WIN32_INPUT_STREAM (stream);
297
298   if (g_cancellable_set_error_if_cancelled (cancellable, error))
299     return -1;
300
301   if (count > G_MAXINT)
302     nbytes = G_MAXINT;
303   else
304     nbytes = count;
305
306   res = ReadFile (win32_stream->priv->handle, buffer, nbytes, &nread, NULL);
307   if (!res)
308     {
309       int errsv = GetLastError ();
310       gchar *emsg;
311
312       if (errsv == ERROR_HANDLE_EOF ||
313           errsv == ERROR_BROKEN_PIPE)
314         return 0;
315
316       emsg = g_win32_error_message (errsv);
317       g_set_error (error, G_IO_ERROR,
318                    g_io_error_from_win32_error (errsv),
319                    _("Error reading from handle: %s"),
320                    emsg);
321       g_free (emsg);
322       return -1;
323     }
324
325   return nread;
326 }
327
328 static gboolean
329 g_win32_input_stream_close (GInputStream  *stream,
330                            GCancellable  *cancellable,
331                            GError       **error)
332 {
333   GWin32InputStream *win32_stream;
334   BOOL res;
335
336   win32_stream = G_WIN32_INPUT_STREAM (stream);
337
338   if (!win32_stream->priv->close_handle)
339     return TRUE;
340
341   res = CloseHandle (win32_stream->priv->handle);
342   if (!res)
343     {
344       int errsv = GetLastError ();
345       gchar *emsg = g_win32_error_message (errsv);
346
347       g_set_error (error, G_IO_ERROR,
348                    g_io_error_from_win32_error (errsv),
349                    _("Error closing handle: %s"),
350                    emsg);
351       g_free (emsg);
352       return FALSE;
353     }
354
355   return TRUE;
356 }
357
358 #define __G_WIN32_INPUT_STREAM_C__
359 #include "gioaliasdef.c"