Blame gio/win32/gwinhttpvfs.c

Packit ae235b
/* GIO - GLib Input, Output and Streaming Library
Packit ae235b
 *
Packit ae235b
 * Copyright (C) 2006-2007 Red Hat, Inc.
Packit ae235b
 * Copyright (C) 2008 Novell, Inc.
Packit ae235b
 *
Packit ae235b
 * This library is free software; you can redistribute it and/or
Packit ae235b
 * modify it under the terms of the GNU Lesser General Public
Packit ae235b
 * License as published by the Free Software Foundation; either
Packit ae235b
 * version 2.1 of the License, or (at your option) any later version.
Packit ae235b
 *
Packit ae235b
 * This library is distributed in the hope that it will be useful,
Packit ae235b
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit ae235b
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit ae235b
 * Lesser General Public License for more details.
Packit ae235b
 *
Packit ae235b
 * You should have received a copy of the GNU Lesser General
Packit ae235b
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit ae235b
 *
Packit ae235b
 * Author: Alexander Larsson <alexl@redhat.com>
Packit ae235b
 * Author: Tor Lillqvist <tml@novell.com>
Packit ae235b
 */
Packit ae235b
Packit ae235b
#include "config.h"
Packit ae235b
Packit ae235b
#include <wchar.h>
Packit ae235b
Packit ae235b
#include "gio/gioerror.h"
Packit ae235b
#include "gio/giomodule.h"
Packit ae235b
#include "gio/gvfs.h"
Packit ae235b
Packit ae235b
#include "gwinhttpfile.h"
Packit ae235b
#include "gwinhttpvfs.h"
Packit ae235b
Packit ae235b
static gboolean lookup_done = FALSE;
Packit ae235b
static gboolean funcs_found = FALSE;
Packit ae235b
static GWinHttpDllFuncs funcs;
Packit ae235b
Packit ae235b
static void
Packit ae235b
lookup_funcs (void)
Packit ae235b
{
Packit ae235b
  HMODULE winhttp = NULL;
Packit ae235b
  char winhttp_dll[MAX_PATH + 100];
Packit ae235b
  int n;
Packit ae235b
Packit ae235b
  if (lookup_done)
Packit ae235b
    return;
Packit ae235b
Packit ae235b
  n = GetSystemDirectory (winhttp_dll, MAX_PATH);
Packit ae235b
  if (n > 0 && n < MAX_PATH)
Packit ae235b
    {
Packit ae235b
        if (winhttp_dll[n-1] != '\\' &&
Packit ae235b
            winhttp_dll[n-1] != '/')
Packit ae235b
            strcat (winhttp_dll, "\\");
Packit ae235b
        strcat (winhttp_dll, "winhttp.dll");
Packit ae235b
        winhttp = LoadLibrary (winhttp_dll);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  if (winhttp != NULL)
Packit ae235b
    {
Packit ae235b
      funcs.pWinHttpCloseHandle = (BOOL (WINAPI *) (HINTERNET)) GetProcAddress (winhttp, "WinHttpCloseHandle");
Packit ae235b
      funcs.pWinHttpCrackUrl = (BOOL (WINAPI *) (LPCWSTR,DWORD,DWORD,LPURL_COMPONENTS)) GetProcAddress (winhttp, "WinHttpCrackUrl");
Packit ae235b
      funcs.pWinHttpConnect = (HINTERNET (WINAPI *) (HINTERNET,LPCWSTR,INTERNET_PORT,DWORD)) GetProcAddress (winhttp, "WinHttpConnect");
Packit ae235b
      funcs.pWinHttpCreateUrl = (BOOL (WINAPI *) (LPURL_COMPONENTS,DWORD,LPWSTR,LPDWORD)) GetProcAddress (winhttp, "WinHttpCreateUrl");
Packit ae235b
      funcs.pWinHttpOpen = (HINTERNET (WINAPI *) (LPCWSTR,DWORD,LPCWSTR,LPCWSTR,DWORD)) GetProcAddress (winhttp, "WinHttpOpen");
Packit ae235b
      funcs.pWinHttpOpenRequest = (HINTERNET (WINAPI *) (HINTERNET,LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR*,DWORD)) GetProcAddress (winhttp, "WinHttpOpenRequest");
Packit ae235b
      funcs.pWinHttpQueryDataAvailable = (BOOL (WINAPI *) (HINTERNET,LPDWORD)) GetProcAddress (winhttp, "WinHttpQueryDataAvailable");
Packit ae235b
      funcs.pWinHttpQueryHeaders = (BOOL (WINAPI *) (HINTERNET,DWORD,LPCWSTR,LPVOID,LPDWORD,LPDWORD)) GetProcAddress (winhttp, "WinHttpQueryHeaders");
Packit ae235b
      funcs.pWinHttpReadData = (BOOL (WINAPI *) (HINTERNET,LPVOID,DWORD,LPDWORD)) GetProcAddress (winhttp, "WinHttpReadData");
Packit ae235b
      funcs.pWinHttpReceiveResponse = (BOOL (WINAPI *) (HINTERNET,LPVOID)) GetProcAddress (winhttp, "WinHttpReceiveResponse");
Packit ae235b
      funcs.pWinHttpSendRequest = (BOOL (WINAPI *) (HINTERNET,LPCWSTR,DWORD,LPVOID,DWORD,DWORD,DWORD_PTR)) GetProcAddress (winhttp, "WinHttpSendRequest");
Packit ae235b
      funcs.pWinHttpWriteData = (BOOL (WINAPI *) (HINTERNET,LPCVOID,DWORD,LPDWORD)) GetProcAddress (winhttp, "WinHttpWriteData");
Packit ae235b
Packit ae235b
      if (funcs.pWinHttpCloseHandle &&
Packit ae235b
	  funcs.pWinHttpCrackUrl &&
Packit ae235b
	  funcs.pWinHttpConnect &&
Packit ae235b
	  funcs.pWinHttpCreateUrl &&
Packit ae235b
	  funcs.pWinHttpOpen &&
Packit ae235b
	  funcs.pWinHttpOpenRequest &&
Packit ae235b
	  funcs.pWinHttpQueryDataAvailable &&
Packit ae235b
	  funcs.pWinHttpQueryHeaders &&
Packit ae235b
	  funcs.pWinHttpReadData &&
Packit ae235b
	  funcs.pWinHttpReceiveResponse &&
Packit ae235b
	  funcs.pWinHttpSendRequest &&
Packit ae235b
	  funcs.pWinHttpWriteData)
Packit ae235b
	funcs_found = TRUE;
Packit ae235b
    }
Packit ae235b
  lookup_done = TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
#define g_winhttp_vfs_get_type _g_winhttp_vfs_get_type
Packit ae235b
G_DEFINE_TYPE_WITH_CODE (GWinHttpVfs, g_winhttp_vfs, G_TYPE_VFS,
Packit ae235b
			 {
Packit ae235b
			   lookup_funcs ();
Packit ae235b
			   if (funcs_found)
Packit ae235b
			     g_io_extension_point_implement (G_VFS_EXTENSION_POINT_NAME,
Packit ae235b
							     g_define_type_id,
Packit ae235b
							     "winhttp",
Packit ae235b
							     10);
Packit ae235b
			 })
Packit ae235b
Packit ae235b
static const gchar *winhttp_uri_schemes[] = { "http", "https" };
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_winhttp_vfs_finalize (GObject *object)
Packit ae235b
{
Packit ae235b
  GWinHttpVfs *vfs;
Packit ae235b
Packit ae235b
  vfs = G_WINHTTP_VFS (object);
Packit ae235b
Packit ae235b
  (G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpCloseHandle) (vfs->session);
Packit ae235b
  vfs->session = NULL;
Packit ae235b
Packit ae235b
  if (vfs->wrapped_vfs)
Packit ae235b
    g_object_unref (vfs->wrapped_vfs);
Packit ae235b
  vfs->wrapped_vfs = NULL;
Packit ae235b
Packit ae235b
  G_OBJECT_CLASS (g_winhttp_vfs_parent_class)->finalize (object);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_winhttp_vfs_init (GWinHttpVfs *vfs)
Packit ae235b
{
Packit ae235b
  wchar_t *wagent;
Packit ae235b
Packit ae235b
  vfs->wrapped_vfs = g_vfs_get_local ();
Packit ae235b
Packit ae235b
  wagent = g_utf8_to_utf16 (g_get_prgname (), -1, NULL, NULL, NULL);
Packit ae235b
Packit ae235b
  if (!wagent)
Packit ae235b
    wagent = g_utf8_to_utf16 ("GWinHttpVfs", -1, NULL, NULL, NULL);
Packit ae235b
Packit ae235b
  vfs->session = (G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpOpen)
Packit ae235b
    (wagent,
Packit ae235b
     WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
Packit ae235b
     WINHTTP_NO_PROXY_NAME,
Packit ae235b
     WINHTTP_NO_PROXY_BYPASS,
Packit ae235b
     0);
Packit ae235b
Packit ae235b
  g_free (wagent);
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_winhttp_vfs_new:
Packit ae235b
 *
Packit ae235b
 * Returns a new #GVfs handle for a WinHttp vfs.
Packit ae235b
 *
Packit ae235b
 * Returns: a new #GVfs handle.
Packit ae235b
 **/
Packit ae235b
GVfs *
Packit ae235b
_g_winhttp_vfs_new (void)
Packit ae235b
{
Packit ae235b
  return g_object_new (G_TYPE_WINHTTP_VFS, NULL);
Packit ae235b
}
Packit ae235b
Packit ae235b
static GFile *
Packit ae235b
g_winhttp_vfs_get_file_for_path (GVfs       *vfs,
Packit ae235b
                                 const char *path)
Packit ae235b
{
Packit ae235b
  return g_vfs_get_file_for_path (G_WINHTTP_VFS (vfs)->wrapped_vfs, path);
Packit ae235b
}
Packit ae235b
Packit ae235b
static GFile *
Packit ae235b
g_winhttp_vfs_get_file_for_uri (GVfs       *vfs,
Packit ae235b
                                const char *uri)
Packit ae235b
{
Packit ae235b
  GWinHttpVfs *winhttp_vfs = G_WINHTTP_VFS (vfs);
Packit ae235b
  int i;
Packit ae235b
Packit ae235b
  /* If it matches one of "our" schemes, handle it */
Packit ae235b
  for (i = 0; i < G_N_ELEMENTS (winhttp_uri_schemes); i++)
Packit ae235b
    if (g_ascii_strncasecmp (uri, winhttp_uri_schemes[i], strlen (winhttp_uri_schemes[i])) == 0 &&
Packit ae235b
        uri[strlen (winhttp_uri_schemes[i])] == ':')
Packit ae235b
      return _g_winhttp_file_new (winhttp_vfs, uri);
Packit ae235b
Packit ae235b
  /* For other URIs fallback to the wrapped GVfs */
Packit ae235b
  return g_vfs_parse_name (winhttp_vfs->wrapped_vfs, uri);
Packit ae235b
}
Packit ae235b
Packit ae235b
static const gchar * const *
Packit ae235b
g_winhttp_vfs_get_supported_uri_schemes (GVfs *vfs)
Packit ae235b
{
Packit ae235b
  GWinHttpVfs *winhttp_vfs = G_WINHTTP_VFS (vfs);
Packit ae235b
  const gchar * const *wrapped_vfs_uri_schemes = g_vfs_get_supported_uri_schemes (winhttp_vfs->wrapped_vfs);
Packit ae235b
  int i, n;
Packit ae235b
  const gchar **retval;
Packit ae235b
Packit ae235b
  n = 0;
Packit ae235b
  while (wrapped_vfs_uri_schemes[n] != NULL)
Packit ae235b
    n++;
Packit ae235b
Packit ae235b
  retval = g_new (const gchar *, n + G_N_ELEMENTS (winhttp_uri_schemes) + 1);
Packit ae235b
  n = 0;
Packit ae235b
  while (wrapped_vfs_uri_schemes[n] != NULL)
Packit ae235b
    {
Packit ae235b
      retval[n] = wrapped_vfs_uri_schemes[n];
Packit ae235b
      n++;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  for (i = 0; i < G_N_ELEMENTS (winhttp_uri_schemes); i++)
Packit ae235b
    {
Packit ae235b
      retval[n] = winhttp_uri_schemes[i];
Packit ae235b
      n++;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  retval[n] = NULL;
Packit ae235b
Packit ae235b
  return retval;
Packit ae235b
}
Packit ae235b
Packit ae235b
static GFile *
Packit ae235b
g_winhttp_vfs_parse_name (GVfs       *vfs,
Packit ae235b
                          const char *parse_name)
Packit ae235b
{
Packit ae235b
  GWinHttpVfs *winhttp_vfs = G_WINHTTP_VFS (vfs);
Packit ae235b
Packit ae235b
  g_return_val_if_fail (G_IS_VFS (vfs), NULL);
Packit ae235b
  g_return_val_if_fail (parse_name != NULL, NULL);
Packit ae235b
Packit ae235b
  /* For plain file paths fallback to the wrapped GVfs */
Packit ae235b
  if (g_path_is_absolute (parse_name))
Packit ae235b
    return g_vfs_parse_name (winhttp_vfs->wrapped_vfs, parse_name);
Packit ae235b
Packit ae235b
  /* Otherwise assume it is an URI, so pass on to
Packit ae235b
   * g_winhttp_vfs_get_file_for_uri().
Packit ae235b
   */
Packit ae235b
  return g_winhttp_vfs_get_file_for_uri (vfs, parse_name);
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
g_winhttp_vfs_is_active (GVfs *vfs)
Packit ae235b
{
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
g_winhttp_vfs_class_init (GWinHttpVfsClass *class)
Packit ae235b
{
Packit ae235b
  GObjectClass *object_class;
Packit ae235b
  GVfsClass *vfs_class;
Packit ae235b
Packit ae235b
  object_class = (GObjectClass *) class;
Packit ae235b
Packit ae235b
  object_class->finalize = g_winhttp_vfs_finalize;
Packit ae235b
Packit ae235b
  vfs_class = G_VFS_CLASS (class);
Packit ae235b
Packit ae235b
  vfs_class->is_active = g_winhttp_vfs_is_active;
Packit ae235b
  vfs_class->get_file_for_path = g_winhttp_vfs_get_file_for_path;
Packit ae235b
  vfs_class->get_file_for_uri = g_winhttp_vfs_get_file_for_uri;
Packit ae235b
  vfs_class->get_supported_uri_schemes = g_winhttp_vfs_get_supported_uri_schemes;
Packit ae235b
  vfs_class->parse_name = g_winhttp_vfs_parse_name;
Packit ae235b
Packit ae235b
  lookup_funcs ();
Packit ae235b
  if (funcs_found)
Packit ae235b
    class->funcs = &funcs;
Packit ae235b
  else
Packit ae235b
    class->funcs = NULL;
Packit ae235b
}
Packit ae235b
Packit ae235b
char *
Packit ae235b
_g_winhttp_error_message (DWORD error_code)
Packit ae235b
{
Packit ae235b
  /* The FormatMessage() API that g_win32_error_message() uses doesn't
Packit ae235b
   * seem to know about WinHttp errors, unfortunately.
Packit ae235b
   */
Packit ae235b
  if (error_code >= WINHTTP_ERROR_BASE && error_code < WINHTTP_ERROR_BASE + 200)
Packit ae235b
    {
Packit ae235b
      switch (error_code)
Packit ae235b
        {
Packit ae235b
          /* FIXME: Use meaningful error messages */
Packit ae235b
#define CASE(x) case ERROR_WINHTTP_##x: return g_strdup ("WinHttp error: " #x);
Packit ae235b
          CASE (AUTO_PROXY_SERVICE_ERROR);
Packit ae235b
          CASE (AUTODETECTION_FAILED);
Packit ae235b
          CASE (BAD_AUTO_PROXY_SCRIPT);
Packit ae235b
          CASE (CANNOT_CALL_AFTER_OPEN);
Packit ae235b
          CASE (CANNOT_CALL_AFTER_SEND);
Packit ae235b
          CASE (CANNOT_CALL_BEFORE_OPEN);
Packit ae235b
          CASE (CANNOT_CALL_BEFORE_SEND);
Packit ae235b
          CASE (CANNOT_CONNECT);
Packit ae235b
          CASE (CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW);
Packit ae235b
          CASE (CLIENT_AUTH_CERT_NEEDED);
Packit ae235b
          CASE (CONNECTION_ERROR);
Packit ae235b
          CASE (HEADER_ALREADY_EXISTS);
Packit ae235b
          CASE (HEADER_COUNT_EXCEEDED);
Packit ae235b
          CASE (HEADER_NOT_FOUND);
Packit ae235b
          CASE (HEADER_SIZE_OVERFLOW);
Packit ae235b
          CASE (INCORRECT_HANDLE_STATE);
Packit ae235b
          CASE (INCORRECT_HANDLE_TYPE);
Packit ae235b
          CASE (INTERNAL_ERROR);
Packit ae235b
          CASE (INVALID_OPTION);
Packit ae235b
          CASE (INVALID_QUERY_REQUEST);
Packit ae235b
          CASE (INVALID_SERVER_RESPONSE);
Packit ae235b
          CASE (INVALID_URL);
Packit ae235b
          CASE (LOGIN_FAILURE);
Packit ae235b
          CASE (NAME_NOT_RESOLVED);
Packit ae235b
          CASE (NOT_INITIALIZED);
Packit ae235b
          CASE (OPERATION_CANCELLED);
Packit ae235b
          CASE (OPTION_NOT_SETTABLE);
Packit ae235b
          CASE (OUT_OF_HANDLES);
Packit ae235b
          CASE (REDIRECT_FAILED);
Packit ae235b
          CASE (RESEND_REQUEST);
Packit ae235b
          CASE (RESPONSE_DRAIN_OVERFLOW);
Packit ae235b
          CASE (SECURE_CERT_CN_INVALID);
Packit ae235b
          CASE (SECURE_CERT_DATE_INVALID);
Packit ae235b
          CASE (SECURE_CERT_REV_FAILED);
Packit ae235b
          CASE (SECURE_CERT_REVOKED);
Packit ae235b
          CASE (SECURE_CERT_WRONG_USAGE);
Packit ae235b
          CASE (SECURE_CHANNEL_ERROR);
Packit ae235b
          CASE (SECURE_FAILURE);
Packit ae235b
          CASE (SECURE_INVALID_CA);
Packit ae235b
          CASE (SECURE_INVALID_CERT);
Packit ae235b
          CASE (SHUTDOWN);
Packit ae235b
          CASE (TIMEOUT);
Packit ae235b
          CASE (UNABLE_TO_DOWNLOAD_SCRIPT);
Packit ae235b
          CASE (UNRECOGNIZED_SCHEME);
Packit ae235b
          #undef CASE
Packit ae235b
        default:
Packit ae235b
          return g_strdup_printf ("WinHttp error %ld", error_code);
Packit ae235b
        }
Packit ae235b
    }
Packit ae235b
  else
Packit ae235b
    return g_win32_error_message (error_code);
Packit ae235b
}
Packit ae235b
Packit ae235b
void
Packit ae235b
_g_winhttp_set_error (GError     **error,
Packit ae235b
                      DWORD        error_code,
Packit ae235b
                      const char  *what)
Packit ae235b
{
Packit ae235b
  char *emsg = _g_winhttp_error_message (error_code);
Packit ae235b
Packit ae235b
  g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
Packit ae235b
               "%s failed: %s", what, emsg);
Packit ae235b
  g_free (emsg);
Packit ae235b
}
Packit ae235b
Packit ae235b
gboolean
Packit ae235b
_g_winhttp_response (GWinHttpVfs *vfs,
Packit ae235b
                     HINTERNET    request,
Packit ae235b
                     GError     **error,
Packit ae235b
                     const char  *what)
Packit ae235b
{
Packit ae235b
  wchar_t *status_code;
Packit ae235b
  DWORD status_code_len;
Packit ae235b
Packit ae235b
  if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpReceiveResponse (request, NULL))
Packit ae235b
    {
Packit ae235b
      _g_winhttp_set_error (error, GetLastError (), what);
Packit ae235b
Packit ae235b
      return FALSE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  status_code_len = 0;
Packit ae235b
  if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpQueryHeaders
Packit ae235b
      (request,
Packit ae235b
       WINHTTP_QUERY_STATUS_CODE,
Packit ae235b
       NULL,
Packit ae235b
       NULL,
Packit ae235b
       &status_code_len,
Packit ae235b
       NULL) &&
Packit ae235b
      GetLastError () != ERROR_INSUFFICIENT_BUFFER)
Packit ae235b
    {
Packit ae235b
      _g_winhttp_set_error (error, GetLastError (), what);
Packit ae235b
Packit ae235b
      return FALSE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  status_code = g_malloc (status_code_len);
Packit ae235b
Packit ae235b
  if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpQueryHeaders
Packit ae235b
      (request,
Packit ae235b
       WINHTTP_QUERY_STATUS_CODE,
Packit ae235b
       NULL,
Packit ae235b
       status_code,
Packit ae235b
       &status_code_len,
Packit ae235b
       NULL))
Packit ae235b
    {
Packit ae235b
      _g_winhttp_set_error (error, GetLastError (), what);
Packit ae235b
      g_free (status_code);
Packit ae235b
Packit ae235b
      return FALSE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  if (status_code[0] != L'2')
Packit ae235b
    {
Packit ae235b
      wchar_t *status_text = NULL;
Packit ae235b
      DWORD status_text_len;
Packit ae235b
Packit ae235b
      if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpQueryHeaders
Packit ae235b
          (request,
Packit ae235b
           WINHTTP_QUERY_STATUS_TEXT,
Packit ae235b
           NULL,
Packit ae235b
           NULL,
Packit ae235b
           &status_text_len,
Packit ae235b
           NULL) &&
Packit ae235b
          GetLastError () == ERROR_INSUFFICIENT_BUFFER)
Packit ae235b
        {
Packit ae235b
          status_text = g_malloc (status_text_len);
Packit ae235b
Packit ae235b
          if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpQueryHeaders
Packit ae235b
              (request,
Packit ae235b
               WINHTTP_QUERY_STATUS_TEXT,
Packit ae235b
               NULL,
Packit ae235b
               status_text,
Packit ae235b
               &status_text_len,
Packit ae235b
               NULL))
Packit ae235b
            {
Packit ae235b
              g_free (status_text);
Packit ae235b
              status_text = NULL;
Packit ae235b
            }
Packit ae235b
        }
Packit ae235b
Packit ae235b
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
Packit ae235b
                   "%s failed: %S %S",
Packit ae235b
                   what, status_code, status_text ? status_text : L"");
Packit ae235b
      g_free (status_code);
Packit ae235b
      g_free (status_text);
Packit ae235b
Packit ae235b
      return FALSE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  g_free (status_code);
Packit ae235b
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
gboolean
Packit ae235b
_g_winhttp_query_header (GWinHttpVfs *vfs,
Packit ae235b
                         HINTERNET    request,
Packit ae235b
                         const char  *request_description,
Packit ae235b
                         DWORD        which_header,
Packit ae235b
                         wchar_t    **header,
Packit ae235b
                         GError     **error)
Packit ae235b
{
Packit ae235b
  DWORD header_len = 0;
Packit ae235b
Packit ae235b
  if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpQueryHeaders
Packit ae235b
      (request,
Packit ae235b
       which_header,
Packit ae235b
       NULL,
Packit ae235b
       NULL,
Packit ae235b
       &header_len,
Packit ae235b
       NULL) &&
Packit ae235b
      GetLastError () != ERROR_INSUFFICIENT_BUFFER)
Packit ae235b
    {
Packit ae235b
      _g_winhttp_set_error (error, GetLastError (), request_description);
Packit ae235b
Packit ae235b
      return FALSE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  *header = g_malloc (header_len);
Packit ae235b
  if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpQueryHeaders
Packit ae235b
      (request,
Packit ae235b
       which_header,
Packit ae235b
       NULL,
Packit ae235b
       *header,
Packit ae235b
       &header_len,
Packit ae235b
       NULL))
Packit ae235b
    {
Packit ae235b
      _g_winhttp_set_error (error, GetLastError (), request_description);
Packit ae235b
      g_free (*header);
Packit ae235b
      *header = NULL;
Packit ae235b
Packit ae235b
      return FALSE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return TRUE;
Packit ae235b
}