| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  | /* GIO - GLib Input, Output and Streaming Library
 | 
					
						
							| 
									
										
										
										
											2008-08-13 19:39:49 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  |  * 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 | 
					
						
							| 
									
										
										
										
											2017-01-05 14:32:59 +01:00
										 |  |  |  * version 2.1 of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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 | 
					
						
							| 
									
										
										
										
											2014-01-23 12:58:29 +01:00
										 |  |  |  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Author: Alexander Larsson <alexl@redhat.com> | 
					
						
							|  |  |  |  * Author: Tor Lillqvist <tml@novell.com> | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "config.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-13 19:39:49 +00:00
										 |  |  | #include <wchar.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-10 16:01:39 +03:00
										 |  |  | #include "gio/gioerror.h"
 | 
					
						
							|  |  |  | #include "gio/giomodule.h"
 | 
					
						
							|  |  |  | #include "gio/gvfs.h"
 | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "gwinhttpfile.h"
 | 
					
						
							|  |  |  | #include "gwinhttpvfs.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-12 17:52:39 +00:00
										 |  |  | static gboolean lookup_done = FALSE; | 
					
						
							|  |  |  | static gboolean funcs_found = FALSE; | 
					
						
							|  |  |  | static GWinHttpDllFuncs funcs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | lookup_funcs (void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-02 21:56:02 +03:00
										 |  |  |   HMODULE winhttp = NULL; | 
					
						
							| 
									
										
										
										
											2018-08-15 22:25:08 +02:00
										 |  |  |   WCHAR winhttp_dll[MAX_PATH + 100]; | 
					
						
							| 
									
										
										
										
											2010-09-02 21:56:02 +03:00
										 |  |  |   int n; | 
					
						
							| 
									
										
										
										
											2008-11-12 17:52:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (lookup_done) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-15 22:25:08 +02:00
										 |  |  |   n = GetSystemDirectoryW (winhttp_dll, MAX_PATH); | 
					
						
							| 
									
										
										
										
											2010-09-02 21:56:02 +03:00
										 |  |  |   if (n > 0 && n < MAX_PATH) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-08-15 22:25:08 +02:00
										 |  |  |         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); | 
					
						
							| 
									
										
										
										
											2010-09-02 21:56:02 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-12 17:52:39 +00:00
										 |  |  |   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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  | #define g_winhttp_vfs_get_type _g_winhttp_vfs_get_type
 | 
					
						
							|  |  |  | G_DEFINE_TYPE_WITH_CODE (GWinHttpVfs, g_winhttp_vfs, G_TYPE_VFS, | 
					
						
							| 
									
										
										
										
											2008-11-12 17:52:39 +00:00
										 |  |  | 			 { | 
					
						
							|  |  |  | 			   lookup_funcs (); | 
					
						
							|  |  |  | 			   if (funcs_found) | 
					
						
							|  |  |  | 			     g_io_extension_point_implement (G_VFS_EXTENSION_POINT_NAME, | 
					
						
							|  |  |  | 							     g_define_type_id, | 
					
						
							|  |  |  | 							     "winhttp", | 
					
						
							|  |  |  | 							     10); | 
					
						
							|  |  |  | 			 }) | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static const gchar *winhttp_uri_schemes[] = { "http", "https" }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | g_winhttp_vfs_finalize (GObject *object) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GWinHttpVfs *vfs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   vfs = G_WINHTTP_VFS (object); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-12 17:52:39 +00:00
										 |  |  |   (G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpCloseHandle) (vfs->session); | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  |   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; | 
					
						
							| 
									
										
										
										
											2019-10-06 20:05:44 +02:00
										 |  |  |   const gchar *prgname = g_get_prgname (); | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   vfs->wrapped_vfs = g_vfs_get_local (); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-06 20:05:44 +02:00
										 |  |  |   if (prgname) | 
					
						
							|  |  |  |     wagent = g_utf8_to_utf16 (prgname, -1, NULL, NULL, NULL); | 
					
						
							|  |  |  |   else | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  |     wagent = g_utf8_to_utf16 ("GWinHttpVfs", -1, NULL, NULL, NULL); | 
					
						
							| 
									
										
										
										
											2008-08-13 19:39:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-12 17:52:39 +00:00
										 |  |  |   vfs->session = (G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpOpen) | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  |     (wagent, | 
					
						
							|  |  |  |      WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, | 
					
						
							|  |  |  |      WINHTTP_NO_PROXY_NAME, | 
					
						
							|  |  |  |      WINHTTP_NO_PROXY_BYPASS, | 
					
						
							|  |  |  |      0); | 
					
						
							| 
									
										
										
										
											2012-08-16 22:17:46 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   g_free (wagent); | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-18 14:08:41 +02:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  |  * 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); | 
					
						
							| 
									
										
										
										
											2021-05-14 13:54:06 +02:00
										 |  |  |   gsize i; | 
					
						
							| 
									
										
										
										
											2019-07-02 12:10:21 +01:00
										 |  |  |   GFile *ret = NULL; | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* If it matches one of "our" schemes, handle it */ | 
					
						
							|  |  |  |   for (i = 0; i < G_N_ELEMENTS (winhttp_uri_schemes); i++) | 
					
						
							| 
									
										
										
										
											2019-07-02 12:10:21 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |       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); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* For other URIs fallback to the wrapped GVfs */ | 
					
						
							| 
									
										
										
										
											2019-07-02 12:10:21 +01:00
										 |  |  |   if (ret == NULL) | 
					
						
							|  |  |  |     ret = g_vfs_get_file_for_uri (winhttp_vfs->wrapped_vfs, uri); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_assert (ret != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return g_steal_pointer (&ret); | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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); | 
					
						
							| 
									
										
										
										
											2021-05-14 13:54:06 +02:00
										 |  |  |   gsize i, n; | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  |   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; | 
					
						
							| 
									
										
										
										
											2008-08-13 19:39:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  |   return retval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static GFile * | 
					
						
							|  |  |  | g_winhttp_vfs_parse_name (GVfs       *vfs, | 
					
						
							|  |  |  |                           const char *parse_name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GWinHttpVfs *winhttp_vfs = G_WINHTTP_VFS (vfs); | 
					
						
							| 
									
										
										
										
											2008-08-13 19:39:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  |   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; | 
					
						
							| 
									
										
										
										
											2008-08-13 19:39:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  |   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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-12 17:52:39 +00:00
										 |  |  |   lookup_funcs (); | 
					
						
							|  |  |  |   if (funcs_found) | 
					
						
							|  |  |  |     class->funcs = &funcs; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     class->funcs = NULL; | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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: | 
					
						
							| 
									
										
										
										
											2008-08-13 19:39:49 +00:00
										 |  |  |           return g_strdup_printf ("WinHttp error %ld", error_code); | 
					
						
							| 
									
										
										
										
											2008-08-12 23:09:04 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return g_win32_error_message (error_code); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-08-13 19:39:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-12 17:52:39 +00:00
										 |  |  |   if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpReceiveResponse (request, NULL)) | 
					
						
							| 
									
										
										
										
											2008-08-13 19:39:49 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       _g_winhttp_set_error (error, GetLastError (), what); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   status_code_len = 0; | 
					
						
							| 
									
										
										
										
											2008-11-12 17:52:39 +00:00
										 |  |  |   if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpQueryHeaders | 
					
						
							| 
									
										
										
										
											2008-08-13 19:39:49 +00:00
										 |  |  |       (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); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-12 17:52:39 +00:00
										 |  |  |   if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpQueryHeaders | 
					
						
							| 
									
										
										
										
											2008-08-13 19:39:49 +00:00
										 |  |  |       (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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-12 17:52:39 +00:00
										 |  |  |       if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpQueryHeaders | 
					
						
							| 
									
										
										
										
											2008-08-13 19:39:49 +00:00
										 |  |  |           (request, | 
					
						
							|  |  |  |            WINHTTP_QUERY_STATUS_TEXT, | 
					
						
							|  |  |  |            NULL, | 
					
						
							|  |  |  |            NULL, | 
					
						
							|  |  |  |            &status_text_len, | 
					
						
							|  |  |  |            NULL) && | 
					
						
							|  |  |  |           GetLastError () == ERROR_INSUFFICIENT_BUFFER) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           status_text = g_malloc (status_text_len); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-12 17:52:39 +00:00
										 |  |  |           if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpQueryHeaders | 
					
						
							| 
									
										
										
										
											2008-08-13 19:39:49 +00:00
										 |  |  |               (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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-12 17:52:39 +00:00
										 |  |  |   if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpQueryHeaders | 
					
						
							| 
									
										
										
										
											2008-08-13 19:39:49 +00:00
										 |  |  |       (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); | 
					
						
							| 
									
										
										
										
											2008-11-12 17:52:39 +00:00
										 |  |  |   if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpQueryHeaders | 
					
						
							| 
									
										
										
										
											2008-08-13 19:39:49 +00:00
										 |  |  |       (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; | 
					
						
							|  |  |  | } |