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