(root)/
glib-2.79.0/
gio/
win32/
gwinhttpfileinputstream.c
       1  /* GIO - GLib Input, Output and Streaming Library
       2   *
       3   * Copyright (C) 2006-2007 Red Hat, Inc.
       4   * Copyright (C) 2008 Novell, Inc.
       5   *
       6   * This library is free software; you can redistribute it and/or
       7   * modify it under the terms of the GNU Lesser General Public
       8   * License as published by the Free Software Foundation; either
       9   * version 2.1 of the License, or (at your option) any later version.
      10   *
      11   * This library is distributed in the hope that it will be useful,
      12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14   * Lesser General Public License for more details.
      15   *
      16   * You should have received a copy of the GNU Lesser General
      17   * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      18   *
      19   * Author: Alexander Larsson <alexl@redhat.com>
      20   * Author: Tor Lillqvist <tml@novell.com>
      21   */
      22  
      23  #include "config.h"
      24  
      25  #include <glib.h>
      26  
      27  #include "gio/gcancellable.h"
      28  #include "gio/gioerror.h"
      29  #include "gwinhttpfileinputstream.h"
      30  #include "glibintl.h"
      31  
      32  struct _GWinHttpFileInputStream
      33  {
      34    GFileInputStream parent_instance;
      35  
      36    GWinHttpFile *file;
      37    gboolean request_sent;
      38    HINTERNET connection;
      39    HINTERNET request;
      40  };
      41  
      42  struct _GWinHttpFileInputStreamClass
      43  {
      44    GFileInputStreamClass parent_class;
      45  };
      46  
      47  #define g_winhttp_file_input_stream_get_type _g_winhttp_file_input_stream_get_type
      48  G_DEFINE_TYPE (GWinHttpFileInputStream, g_winhttp_file_input_stream, G_TYPE_FILE_INPUT_STREAM)
      49  
      50  static gssize g_winhttp_file_input_stream_read (GInputStream    *stream,
      51                                                  void            *buffer,
      52                                                  gsize            count,
      53                                                  GCancellable    *cancellable,
      54                                                  GError         **error);
      55  
      56  static gboolean g_winhttp_file_input_stream_close (GInputStream  *stream,
      57  						   GCancellable  *cancellable,
      58  						   GError       **error);
      59  
      60  static void
      61  g_winhttp_file_input_stream_finalize (GObject *object)
      62  {
      63    GWinHttpFileInputStream *winhttp_stream;
      64  
      65    winhttp_stream = G_WINHTTP_FILE_INPUT_STREAM (object);
      66  
      67    if (winhttp_stream->request != NULL)
      68      G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (winhttp_stream->request);
      69    if (winhttp_stream->connection != NULL)
      70      G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (winhttp_stream->connection);
      71  
      72    g_object_unref (winhttp_stream->file);
      73    winhttp_stream->file = NULL;
      74  
      75    G_OBJECT_CLASS (g_winhttp_file_input_stream_parent_class)->finalize (object);
      76  }
      77  
      78  static void
      79  g_winhttp_file_input_stream_class_init (GWinHttpFileInputStreamClass *klass)
      80  {
      81    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
      82    GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
      83  
      84    gobject_class->finalize = g_winhttp_file_input_stream_finalize;
      85  
      86    stream_class->read_fn = g_winhttp_file_input_stream_read;
      87    stream_class->close_fn = g_winhttp_file_input_stream_close;
      88  }
      89  
      90  static void
      91  g_winhttp_file_input_stream_init (GWinHttpFileInputStream *info)
      92  {
      93  }
      94  
      95  /*
      96   * g_winhttp_file_input_stream_new:
      97   * @file: the GWinHttpFile being read
      98   * @connection: handle to the HTTP connection, as from WinHttpConnect()
      99   * @request: handle to the HTTP request, as from WinHttpOpenRequest
     100   *
     101   * Returns: #GFileInputStream for the given request
     102   */
     103  GFileInputStream *
     104  _g_winhttp_file_input_stream_new (GWinHttpFile *file,
     105                                    HINTERNET     connection,
     106                                    HINTERNET     request)
     107  {
     108    GWinHttpFileInputStream *stream;
     109  
     110    stream = g_object_new (G_TYPE_WINHTTP_FILE_INPUT_STREAM, NULL);
     111  
     112    stream->file = g_object_ref (file);
     113    stream->request_sent = FALSE;
     114    stream->connection = connection;
     115    stream->request = request;
     116  
     117    return G_FILE_INPUT_STREAM (stream);
     118  }
     119  
     120  static gssize
     121  g_winhttp_file_input_stream_read (GInputStream  *stream,
     122                                    void          *buffer,
     123                                    gsize          count,
     124                                    GCancellable  *cancellable,
     125                                    GError       **error)
     126  {
     127    GWinHttpFileInputStream *winhttp_stream = G_WINHTTP_FILE_INPUT_STREAM (stream);
     128    DWORD bytes_read;
     129  
     130    if (!winhttp_stream->request_sent)
     131      {
     132        if (!G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpSendRequest
     133            (winhttp_stream->request,
     134             NULL, 0,
     135             NULL, 0,
     136             0,
     137             0))
     138          {
     139            _g_winhttp_set_error (error, GetLastError (), "GET request");
     140  
     141            return -1;
     142          }
     143  
     144        if (!_g_winhttp_response (winhttp_stream->file->vfs,
     145                                  winhttp_stream->request,
     146                                  error,
     147                                  "GET request"))
     148          return -1;
     149  
     150        winhttp_stream->request_sent = TRUE;
     151      }
     152  
     153    if (!G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpReadData
     154        (winhttp_stream->request, buffer, count, &bytes_read))
     155      {
     156        _g_winhttp_set_error (error, GetLastError (), "GET request");
     157  
     158        return -1;
     159      }
     160  
     161    return bytes_read;
     162  }
     163  
     164  static gboolean 
     165  g_winhttp_file_input_stream_close (GInputStream         *stream,
     166  				   GCancellable         *cancellable,
     167  				   GError              **error)
     168  {
     169    GWinHttpFileInputStream *winhttp_stream = G_WINHTTP_FILE_INPUT_STREAM (stream);
     170  
     171    if (winhttp_stream->connection != NULL)
     172      G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (winhttp_stream->connection);
     173    winhttp_stream->connection = NULL;
     174    return TRUE;
     175  }