Import Upstream version 2.72.4

This commit is contained in:
evinadmin 2023-07-04 11:23:22 +02:00
commit 4ef3ff9793
2003 changed files with 1332420 additions and 0 deletions

View file

@ -0,0 +1,104 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
* Copyright (C) 2006-2007 Red Hat, 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: Vlad Grecescu <b100dian@gmail.com>
* Author: Chun-wei Fan <fanc999@yahoo.com.tw>
*
*/
#include "config.h"
#include "gwin32filemonitor.h"
#include "gwin32fsmonitorutils.h"
#include <windows.h>
G_DEFINE_TYPE_WITH_CODE (GWin32FileMonitor, g_win32_file_monitor, G_TYPE_LOCAL_FILE_MONITOR,
g_io_extension_point_implement (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME,
g_define_type_id, "win32filemonitor", 20))
static void
g_win32_file_monitor_start (GLocalFileMonitor *monitor,
const gchar *dirname,
const gchar *basename,
const gchar *filename,
GFileMonitorSource *source)
{
GWin32FileMonitor *win32_monitor = G_WIN32_FILE_MONITOR (monitor);
win32_monitor->priv->fms = source;
if (filename == NULL && basename == NULL)
g_win32_fs_monitor_init (win32_monitor->priv, dirname, NULL, FALSE);
else if (basename != NULL)
g_win32_fs_monitor_init (win32_monitor->priv, dirname, basename, TRUE);
else
g_win32_fs_monitor_init (win32_monitor->priv, NULL, filename, TRUE);
}
static gboolean
g_win32_file_monitor_is_supported (void)
{
return TRUE;
}
static void
g_win32_file_monitor_init (GWin32FileMonitor *monitor)
{
monitor->priv = g_win32_fs_monitor_create (TRUE);
monitor->priv->self = G_FILE_MONITOR (monitor);
}
static void
g_win32_file_monitor_finalize (GObject *object)
{
GWin32FileMonitor *monitor;
monitor = G_WIN32_FILE_MONITOR (object);
g_win32_fs_monitor_finalize (monitor->priv);
G_OBJECT_CLASS (g_win32_file_monitor_parent_class)->finalize (object);
}
static gboolean
g_win32_file_monitor_cancel (GFileMonitor* monitor)
{
GWin32FileMonitor *file_monitor;
file_monitor = G_WIN32_FILE_MONITOR (monitor);
g_win32_fs_monitor_close_handle (file_monitor->priv);
return TRUE;
}
static void
g_win32_file_monitor_class_init (GWin32FileMonitorClass *klass)
{
GObjectClass* gobject_class = G_OBJECT_CLASS (klass);
GFileMonitorClass *file_monitor_class = G_FILE_MONITOR_CLASS (klass);
GLocalFileMonitorClass *local_file_monitor_class = G_LOCAL_FILE_MONITOR_CLASS (klass);
gobject_class->finalize = g_win32_file_monitor_finalize;
file_monitor_class->cancel = g_win32_file_monitor_cancel;
local_file_monitor_class->is_supported = g_win32_file_monitor_is_supported;
local_file_monitor_class->start = g_win32_file_monitor_start;
}

View file

@ -0,0 +1,62 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, 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: Chun-wei Fan <fanc999@yahoo.com.tw>
*
*/
#ifndef __G_WIN32_FILE_MONITOR_H__
#define __G_WIN32_FILE_MONITOR_H__
#include <glib.h>
#include <glib-object.h>
#include <gio/gio.h>
#include <stdlib.h>
#include <string.h>
#include "gio/gfilemonitor.h"
#include "gio/glocalfilemonitor.h"
#include "gio/giomodule.h"
#include "gwin32fsmonitorutils.h"
G_BEGIN_DECLS
#define G_TYPE_WIN32_FILE_MONITOR (g_win32_file_monitor_get_type ())
#define G_WIN32_FILE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_WIN32_FILE_MONITOR, GWin32FileMonitor))
#define G_WIN32_FILE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_WIN32_FILE_MONITOR, GWin32FileMonitorClass))
#define G_IS_WIN32_FILE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_WIN32_FILE_MONITOR))
#define G_IS_WIN32_FILE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_WIN32_FILE_MONITOR))
#define G_WIN32_FILE_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_WIN32_FILE_MONITOR, GWin32FileMonitorClass))
typedef struct _GWin32FileMonitor GWin32FileMonitor;
typedef struct _GWin32FileMonitorClass GWin32FileMonitorClass;
typedef struct _GWin32FileMonitorPrivate GWin32FileMonitorPrivate;
struct _GWin32FileMonitor {
GLocalFileMonitor parent_instance;
GWin32FSMonitorPrivate * priv;
};
struct _GWin32FileMonitorClass {
GLocalFileMonitorClass parent_class;
};
GType g_win32_file_monitor_get_type (void);
void g_win32_file_monitor_register (GIOModule *module);
G_END_DECLS
#endif /* __G_WIN32_FILE_MONITOR_H__ */

View file

@ -0,0 +1,425 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
* Copyright (C) 2015 Chun-wei Fan
*
* 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: Vlad Grecescu <b100dian@gmail.com>
* Author: Chun-wei Fan <fanc999@yahoo.com.tw>
*
*/
#include "config.h"
#include "gwin32fsmonitorutils.h"
#include "gio/gfile.h"
#include <windows.h>
#define MAX_PATH_LONG 32767 /* Support Paths longer than MAX_PATH (260) characters */
static gboolean
g_win32_fs_monitor_handle_event (GWin32FSMonitorPrivate *monitor,
const gchar *filename,
PFILE_NOTIFY_INFORMATION pfni)
{
GFileMonitorEvent fme;
PFILE_NOTIFY_INFORMATION pfni_next;
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {0, };
gchar *renamed_file = NULL;
switch (pfni->Action)
{
case FILE_ACTION_ADDED:
fme = G_FILE_MONITOR_EVENT_CREATED;
break;
case FILE_ACTION_REMOVED:
fme = G_FILE_MONITOR_EVENT_DELETED;
break;
case FILE_ACTION_MODIFIED:
{
gboolean success_attribs = GetFileAttributesExW (monitor->wfullpath_with_long_prefix,
GetFileExInfoStandard,
&attrib_data);
if (monitor->file_attribs != INVALID_FILE_ATTRIBUTES &&
success_attribs &&
attrib_data.dwFileAttributes != monitor->file_attribs)
fme = G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED;
else
fme = G_FILE_MONITOR_EVENT_CHANGED;
monitor->file_attribs = attrib_data.dwFileAttributes;
}
break;
case FILE_ACTION_RENAMED_OLD_NAME:
if (pfni->NextEntryOffset != 0)
{
/* If the file was renamed in the same directory, we would get a
* FILE_ACTION_RENAMED_NEW_NAME action in the next FILE_NOTIFY_INFORMATION
* structure.
*/
glong file_name_len = 0;
pfni_next = (PFILE_NOTIFY_INFORMATION) ((BYTE*)pfni + pfni->NextEntryOffset);
renamed_file = g_utf16_to_utf8 (pfni_next->FileName, pfni_next->FileNameLength / sizeof(WCHAR), NULL, &file_name_len, NULL);
if (pfni_next->Action == FILE_ACTION_RENAMED_NEW_NAME)
fme = G_FILE_MONITOR_EVENT_RENAMED;
else
fme = G_FILE_MONITOR_EVENT_MOVED_OUT;
}
else
fme = G_FILE_MONITOR_EVENT_MOVED_OUT;
break;
case FILE_ACTION_RENAMED_NEW_NAME:
if (monitor->pfni_prev != NULL &&
monitor->pfni_prev->Action == FILE_ACTION_RENAMED_OLD_NAME)
{
/* don't bother sending events, was already sent (rename) */
fme = (GFileMonitorEvent) -1;
}
else
fme = G_FILE_MONITOR_EVENT_MOVED_IN;
break;
default:
/* The possible Windows actions are all above, so shouldn't get here */
g_assert_not_reached ();
break;
}
if (fme != (GFileMonitorEvent) -1)
return g_file_monitor_source_handle_event (monitor->fms,
fme,
filename,
renamed_file,
NULL,
g_get_monotonic_time ());
else
return FALSE;
}
static void CALLBACK
g_win32_fs_monitor_callback (DWORD error,
DWORD nBytes,
LPOVERLAPPED lpOverlapped)
{
gulong offset;
PFILE_NOTIFY_INFORMATION pfile_notify_walker;
GWin32FSMonitorPrivate *monitor = (GWin32FSMonitorPrivate *) lpOverlapped;
DWORD notify_filter = monitor->isfile ?
(FILE_NOTIFY_CHANGE_FILE_NAME |
FILE_NOTIFY_CHANGE_ATTRIBUTES |
FILE_NOTIFY_CHANGE_SIZE) :
(FILE_NOTIFY_CHANGE_FILE_NAME |
FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_ATTRIBUTES |
FILE_NOTIFY_CHANGE_SIZE);
/* If monitor->self is NULL the GWin32FileMonitor object has been destroyed. */
if (monitor->self == NULL ||
g_file_monitor_is_cancelled (monitor->self) ||
monitor->file_notify_buffer == NULL)
{
g_free (monitor->file_notify_buffer);
g_free (monitor);
return;
}
offset = 0;
do
{
pfile_notify_walker = (PFILE_NOTIFY_INFORMATION)((BYTE *)monitor->file_notify_buffer + offset);
if (pfile_notify_walker->Action > 0)
{
glong file_name_len;
gchar *changed_file;
changed_file = g_utf16_to_utf8 (pfile_notify_walker->FileName,
pfile_notify_walker->FileNameLength / sizeof(WCHAR),
NULL, &file_name_len, NULL);
if (monitor->isfile)
{
gint long_filename_length = wcslen (monitor->wfilename_long);
gint short_filename_length = wcslen (monitor->wfilename_short);
enum GWin32FileMonitorFileAlias alias_state;
/* If monitoring a file, check that the changed file
* in the directory matches the file that is to be monitored
* We need to check both the long and short file names for the same file.
*
* We need to send in the name of the monitored file, not its long (or short) variant,
* if they exist.
*/
if (_wcsnicmp (pfile_notify_walker->FileName,
monitor->wfilename_long,
long_filename_length) == 0)
{
if (_wcsnicmp (pfile_notify_walker->FileName,
monitor->wfilename_short,
short_filename_length) == 0)
{
alias_state = G_WIN32_FILE_MONITOR_NO_ALIAS;
}
else
alias_state = G_WIN32_FILE_MONITOR_LONG_FILENAME;
}
else if (_wcsnicmp (pfile_notify_walker->FileName,
monitor->wfilename_short,
short_filename_length) == 0)
{
alias_state = G_WIN32_FILE_MONITOR_SHORT_FILENAME;
}
else
alias_state = G_WIN32_FILE_MONITOR_NO_MATCH_FOUND;
if (alias_state != G_WIN32_FILE_MONITOR_NO_MATCH_FOUND)
{
wchar_t *monitored_file_w;
gchar *monitored_file;
switch (alias_state)
{
case G_WIN32_FILE_MONITOR_NO_ALIAS:
monitored_file = g_strdup (changed_file);
break;
case G_WIN32_FILE_MONITOR_LONG_FILENAME:
case G_WIN32_FILE_MONITOR_SHORT_FILENAME:
monitored_file_w = wcsrchr (monitor->wfullpath_with_long_prefix, L'\\');
monitored_file = g_utf16_to_utf8 (monitored_file_w + 1, -1, NULL, NULL, NULL);
break;
default:
g_assert_not_reached ();
break;
}
g_win32_fs_monitor_handle_event (monitor, monitored_file, pfile_notify_walker);
g_free (monitored_file);
}
}
else
g_win32_fs_monitor_handle_event (monitor, changed_file, pfile_notify_walker);
g_free (changed_file);
}
monitor->pfni_prev = pfile_notify_walker;
offset += pfile_notify_walker->NextEntryOffset;
}
while (pfile_notify_walker->NextEntryOffset);
ReadDirectoryChangesW (monitor->hDirectory,
monitor->file_notify_buffer,
monitor->buffer_allocated_bytes,
FALSE,
notify_filter,
&monitor->buffer_filled_bytes,
&monitor->overlapped,
g_win32_fs_monitor_callback);
}
void
g_win32_fs_monitor_init (GWin32FSMonitorPrivate *monitor,
const gchar *dirname,
const gchar *filename,
gboolean isfile)
{
wchar_t *wdirname_with_long_prefix = NULL;
const gchar LONGPFX[] = "\\\\?\\";
gchar *fullpath_with_long_prefix, *dirname_with_long_prefix;
DWORD notify_filter = isfile ?
(FILE_NOTIFY_CHANGE_FILE_NAME |
FILE_NOTIFY_CHANGE_ATTRIBUTES |
FILE_NOTIFY_CHANGE_SIZE) :
(FILE_NOTIFY_CHANGE_FILE_NAME |
FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_ATTRIBUTES |
FILE_NOTIFY_CHANGE_SIZE);
gboolean success_attribs;
WIN32_FILE_ATTRIBUTE_DATA attrib_data = {0, };
if (dirname != NULL)
{
dirname_with_long_prefix = g_strconcat (LONGPFX, dirname, NULL);
wdirname_with_long_prefix = g_utf8_to_utf16 (dirname_with_long_prefix, -1, NULL, NULL, NULL);
if (isfile)
{
gchar *fullpath;
wchar_t wlongname[MAX_PATH_LONG];
wchar_t wshortname[MAX_PATH_LONG];
wchar_t *wfullpath, *wbasename_long, *wbasename_short;
fullpath = g_build_filename (dirname, filename, NULL);
fullpath_with_long_prefix = g_strconcat (LONGPFX, fullpath, NULL);
wfullpath = g_utf8_to_utf16 (fullpath, -1, NULL, NULL, NULL);
monitor->wfullpath_with_long_prefix =
g_utf8_to_utf16 (fullpath_with_long_prefix, -1, NULL, NULL, NULL);
/* ReadDirectoryChangesW() can return the normal filename or the
* "8.3" format filename, so we need to keep track of both these names
* so that we can check against them later when it returns
*/
if (GetLongPathNameW (monitor->wfullpath_with_long_prefix, wlongname, MAX_PATH_LONG) == 0)
{
wbasename_long = wcsrchr (monitor->wfullpath_with_long_prefix, L'\\');
monitor->wfilename_long = wbasename_long != NULL ?
wcsdup (wbasename_long + 1) :
wcsdup (wfullpath);
}
else
{
wbasename_long = wcsrchr (wlongname, L'\\');
monitor->wfilename_long = wbasename_long != NULL ?
wcsdup (wbasename_long + 1) :
wcsdup (wlongname);
}
if (GetShortPathNameW (monitor->wfullpath_with_long_prefix, wshortname, MAX_PATH_LONG) == 0)
{
wbasename_short = wcsrchr (monitor->wfullpath_with_long_prefix, L'\\');
monitor->wfilename_short = wbasename_short != NULL ?
wcsdup (wbasename_short + 1) :
wcsdup (wfullpath);
}
else
{
wbasename_short = wcsrchr (wshortname, L'\\');
monitor->wfilename_short = wbasename_short != NULL ?
wcsdup (wbasename_short + 1) :
wcsdup (wshortname);
}
g_free (fullpath);
}
else
{
monitor->wfilename_short = NULL;
monitor->wfilename_long = NULL;
monitor->wfullpath_with_long_prefix = g_utf8_to_utf16 (dirname_with_long_prefix, -1, NULL, NULL, NULL);
}
monitor->isfile = isfile;
}
else
{
dirname_with_long_prefix = g_strconcat (LONGPFX, filename, NULL);
monitor->wfullpath_with_long_prefix = g_utf8_to_utf16 (dirname_with_long_prefix, -1, NULL, NULL, NULL);
monitor->wfilename_long = NULL;
monitor->wfilename_short = NULL;
monitor->isfile = FALSE;
}
success_attribs = GetFileAttributesExW (monitor->wfullpath_with_long_prefix,
GetFileExInfoStandard,
&attrib_data);
if (success_attribs)
monitor->file_attribs = attrib_data.dwFileAttributes; /* Store up original attributes */
else
monitor->file_attribs = INVALID_FILE_ATTRIBUTES;
monitor->pfni_prev = NULL;
monitor->hDirectory = CreateFileW (wdirname_with_long_prefix != NULL ? wdirname_with_long_prefix : monitor->wfullpath_with_long_prefix,
FILE_LIST_DIRECTORY,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL);
g_free (wdirname_with_long_prefix);
g_free (dirname_with_long_prefix);
if (monitor->hDirectory != INVALID_HANDLE_VALUE)
{
ReadDirectoryChangesW (monitor->hDirectory,
monitor->file_notify_buffer,
monitor->buffer_allocated_bytes,
FALSE,
notify_filter,
&monitor->buffer_filled_bytes,
&monitor->overlapped,
g_win32_fs_monitor_callback);
}
}
GWin32FSMonitorPrivate *
g_win32_fs_monitor_create (gboolean isfile)
{
GWin32FSMonitorPrivate *monitor = g_new0 (GWin32FSMonitorPrivate, 1);
monitor->buffer_allocated_bytes = 32784;
monitor->file_notify_buffer = g_new0 (FILE_NOTIFY_INFORMATION, monitor->buffer_allocated_bytes);
return monitor;
}
void
g_win32_fs_monitor_finalize (GWin32FSMonitorPrivate *monitor)
{
g_free (monitor->wfullpath_with_long_prefix);
g_free (monitor->wfilename_long);
g_free (monitor->wfilename_short);
if (monitor->hDirectory == INVALID_HANDLE_VALUE)
{
/* If we don't have a directory handle we can free
* monitor->file_notify_buffer and monitor here. The
* callback won't be called obviously any more (and presumably
* never has been called).
*/
g_free (monitor->file_notify_buffer);
monitor->file_notify_buffer = NULL;
g_free (monitor);
}
else
{
/* If we have a directory handle, the OVERLAPPED struct is
* passed once more to the callback as a result of the
* CloseHandle() done in the cancel method, so monitor has to
* be kept around. The GWin32DirectoryMonitor object is
* disappearing, so can't leave a pointer to it in
* monitor->self.
*/
monitor->self = NULL;
}
}
void
g_win32_fs_monitor_close_handle (GWin32FSMonitorPrivate *monitor)
{
/* This triggers a last callback() with nBytes==0. */
/* Actually I am not so sure about that, it seems to trigger a last
* callback correctly, but the way to recognize that it is the final
* one is not to check for nBytes==0, I think that was a
* misunderstanding.
*/
if (monitor->hDirectory != INVALID_HANDLE_VALUE)
CloseHandle (monitor->hDirectory);
}

View file

@ -0,0 +1,76 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
* Copyright (C) 2014 Chun-wei Fan
*
* 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: Vlad Grecescu <b100dian@gmail.com>
* Author: Chun-wei Fan <fanc999@yahoo.com.tw>
*
*/
#ifndef __G_WIN32_FS_MONITOR_UTILS_H__
#define __G_WIN32_FS_MONITOR_UTILS_H__
#include <windows.h>
#include "gio/glocalfilemonitor.h"
#include "gio/gfilemonitor.h"
G_BEGIN_DECLS
typedef struct _GWin32FSMonitorPrivate GWin32FSMonitorPrivate;
struct _GWin32FSMonitorPrivate
{
OVERLAPPED overlapped;
DWORD buffer_allocated_bytes;
PFILE_NOTIFY_INFORMATION file_notify_buffer;
DWORD buffer_filled_bytes;
HANDLE hDirectory;
gboolean isfile;
wchar_t *wfullpath_with_long_prefix;
wchar_t *wfilename_short;
wchar_t *wfilename_long;
DWORD file_attribs;
PFILE_NOTIFY_INFORMATION pfni_prev;
/* Needed in the APC where we only have this private struct */
GFileMonitor *self;
GFileMonitorSource *fms;
};
enum GWin32FileMonitorFileAlias
{
G_WIN32_FILE_MONITOR_NO_ALIAS = 0,
G_WIN32_FILE_MONITOR_LONG_FILENAME,
G_WIN32_FILE_MONITOR_SHORT_FILENAME,
G_WIN32_FILE_MONITOR_NO_MATCH_FOUND
};
GWin32FSMonitorPrivate* g_win32_fs_monitor_create (gboolean isfile);
void g_win32_fs_monitor_init (GWin32FSMonitorPrivate *monitor,
const gchar *dirname,
const gchar *filename,
gboolean isfile);
void g_win32_fs_monitor_finalize (GWin32FSMonitorPrivate *monitor);
void g_win32_fs_monitor_close_handle (GWin32FSMonitorPrivate *monitor);
G_END_DECLS
#endif

788
gio/win32/gwinhttpfile.c Normal file
View file

@ -0,0 +1,788 @@
/* 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 <stdio.h>
#include <string.h>
#include <wchar.h>
#include "gio/gfile.h"
#include "gio/gfileattribute.h"
#include "gio/gfileinfo.h"
#include "gio/gfileinfo-priv.h"
#include "gwinhttpfile.h"
#include "gwinhttpfileinputstream.h"
#include "gwinhttpfileoutputstream.h"
#include "gio/gioerror.h"
#include "glibintl.h"
static void g_winhttp_file_file_iface_init (GFileIface *iface);
#define g_winhttp_file_get_type _g_winhttp_file_get_type
G_DEFINE_TYPE_WITH_CODE (GWinHttpFile, g_winhttp_file, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_FILE,
g_winhttp_file_file_iface_init))
static void
g_winhttp_file_finalize (GObject *object)
{
GWinHttpFile *file;
file = G_WINHTTP_FILE (object);
g_free (file->url.lpszScheme);
g_free (file->url.lpszHostName);
g_free (file->url.lpszUserName);
g_free (file->url.lpszPassword);
g_free (file->url.lpszUrlPath);
g_free (file->url.lpszExtraInfo);
g_object_unref (file->vfs);
G_OBJECT_CLASS (g_winhttp_file_parent_class)->finalize (object);
}
static void
g_winhttp_file_class_init (GWinHttpFileClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = g_winhttp_file_finalize;
}
static void
g_winhttp_file_init (GWinHttpFile *winhttp)
{
}
/*
* _g_winhttp_file_new:
* @vfs: GWinHttpVfs to use
* @uri: URI of the GWinHttpFile to create.
*
* Returns: (nullable): new winhttp #GFile, or %NULL if there was an error constructing it.
*/
GFile *
_g_winhttp_file_new (GWinHttpVfs *vfs,
const char *uri)
{
wchar_t *wuri;
GWinHttpFile *file;
wuri = g_utf8_to_utf16 (uri, -1, NULL, NULL, NULL);
if (wuri == NULL)
return NULL;
file = g_object_new (G_TYPE_WINHTTP_FILE, NULL);
file->vfs = g_object_ref (vfs);
memset (&file->url, 0, sizeof (file->url));
file->url.dwStructSize = sizeof (file->url);
file->url.dwSchemeLength = 1;
file->url.dwHostNameLength = 1;
file->url.dwUserNameLength = 1;
file->url.dwPasswordLength = 1;
file->url.dwUrlPathLength = 1;
file->url.dwExtraInfoLength = 1;
if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpCrackUrl (wuri, 0, 0, &file->url))
{
g_free (wuri);
return NULL;
}
file->url.lpszScheme = g_new (wchar_t, ++file->url.dwSchemeLength);
file->url.lpszHostName = g_new (wchar_t, ++file->url.dwHostNameLength);
file->url.lpszUserName = g_new (wchar_t, ++file->url.dwUserNameLength);
file->url.lpszPassword = g_new (wchar_t, ++file->url.dwPasswordLength);
file->url.lpszUrlPath = g_new (wchar_t, ++file->url.dwUrlPathLength);
file->url.lpszExtraInfo = g_new (wchar_t, ++file->url.dwExtraInfoLength);
if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpCrackUrl (wuri, 0, 0, &file->url))
{
g_free (file->url.lpszScheme);
g_free (file->url.lpszHostName);
g_free (file->url.lpszUserName);
g_free (file->url.lpszPassword);
g_free (file->url.lpszUrlPath);
g_free (file->url.lpszExtraInfo);
g_free (wuri);
return NULL;
}
g_free (wuri);
return G_FILE (file);
}
static gboolean
g_winhttp_file_is_native (GFile *file)
{
return FALSE;
}
static gboolean
g_winhttp_file_has_uri_scheme (GFile *file,
const char *uri_scheme)
{
return (g_ascii_strcasecmp (uri_scheme, "http") == 0 ||
g_ascii_strcasecmp (uri_scheme, "https") == 0);
}
static char *
g_winhttp_file_get_uri_scheme (GFile *file)
{
GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
return g_utf16_to_utf8 (winhttp_file->url.lpszScheme, -1, NULL, NULL, NULL);
}
static char *
g_winhttp_file_get_basename (GFile *file)
{
GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
char *basename;
char *last_slash;
char *retval;
basename = g_utf16_to_utf8 (winhttp_file->url.lpszUrlPath, -1, NULL, NULL, NULL);
last_slash = strrchr (basename, '/');
/* If no slash, or only "/" fallback to full path part of URI */
if (last_slash == NULL || last_slash[1] == '\0')
return basename;
retval = g_strdup (last_slash + 1);
g_free (basename);
return retval;
}
static char *
g_winhttp_file_get_display_name (GFile *file)
{
char *basename;
/* FIXME: This could be improved by using a new g_utf16_make_valid() function
* to recover what we can from the URI, and then suffixing it with
* (invalid encoding) as per g_filename_display_basename(). */
basename = g_winhttp_file_get_basename (file);
if (!basename)
return g_strdup (_(" (invalid encoding)"));
return g_steal_pointer (&basename);
}
static char *
g_winhttp_file_get_path (GFile *file)
{
return NULL;
}
static char *
g_winhttp_file_get_uri (GFile *file)
{
GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
DWORD len;
wchar_t *wuri;
char *retval;
len = 0;
if (!G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpCreateUrl (&winhttp_file->url, ICU_ESCAPE, NULL, &len) &&
GetLastError () != ERROR_INSUFFICIENT_BUFFER)
return NULL;
wuri = g_new (wchar_t, ++len);
if (!G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpCreateUrl (&winhttp_file->url, ICU_ESCAPE, wuri, &len))
{
g_free (wuri);
return NULL;
}
retval = g_utf16_to_utf8 (wuri, -1, NULL, NULL, NULL);
g_free (wuri);
if (g_str_has_prefix (retval, "http://:@"))
{
memmove (retval + 7, retval + 9, strlen (retval) - 9);
retval[strlen (retval) - 2] = '\0';
}
else if (g_str_has_prefix (retval, "https://:@"))
{
memmove (retval + 8, retval + 10, strlen (retval) - 10);
retval[strlen (retval) - 2] = '\0';
}
return retval;
}
static char *
g_winhttp_file_get_parse_name (GFile *file)
{
/* FIXME: More hair surely needed */
return g_winhttp_file_get_uri (file);
}
static GFile *
g_winhttp_file_get_parent (GFile *file)
{
GWinHttpFile *winhttp_file;
char *uri;
char *last_slash;
GFile *parent;
winhttp_file = G_WINHTTP_FILE (file);
uri = g_winhttp_file_get_uri (file);
if (uri == NULL)
return NULL;
last_slash = strrchr (uri, '/');
if (last_slash == NULL || *(last_slash+1) == 0)
{
g_free (uri);
return NULL;
}
while (last_slash > uri && *last_slash == '/')
last_slash--;
last_slash[1] = '\0';
parent = _g_winhttp_file_new (winhttp_file->vfs, uri);
g_free (uri);
return parent;
}
static GFile *
g_winhttp_file_dup (GFile *file)
{
GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
char *uri = g_winhttp_file_get_uri (file);
GFile *retval = _g_winhttp_file_new (winhttp_file->vfs, uri);
g_free (uri);
return retval;
}
static guint
g_winhttp_file_hash (GFile *file)
{
char *uri = g_winhttp_file_get_uri (file);
guint retval = g_str_hash (uri);
g_free (uri);
return retval;
}
static gboolean
g_winhttp_file_equal (GFile *file1,
GFile *file2)
{
char *uri1 = g_winhttp_file_get_uri (file1);
char *uri2 = g_winhttp_file_get_uri (file2);
gboolean retval = g_str_equal (uri1, uri2);
g_free (uri1);
g_free (uri2);
return retval;
}
static const char *
match_prefix (const char *path,
const char *prefix)
{
int prefix_len;
prefix_len = strlen (prefix);
if (strncmp (path, prefix, prefix_len) != 0)
return NULL;
if (prefix_len > 0 && prefix[prefix_len-1] == '/')
prefix_len--;
return path + prefix_len;
}
static gboolean
g_winhttp_file_prefix_matches (GFile *parent,
GFile *descendant)
{
char *parent_uri = g_winhttp_file_get_uri (parent);
char *descendant_uri = g_winhttp_file_get_uri (descendant);
const char *remainder;
gboolean retval;
remainder = match_prefix (descendant_uri, parent_uri);
if (remainder != NULL && *remainder == '/')
retval = TRUE;
else
retval = FALSE;
g_free (parent_uri);
g_free (descendant_uri);
return retval;
}
static char *
g_winhttp_file_get_relative_path (GFile *parent,
GFile *descendant)
{
char *parent_uri = g_winhttp_file_get_uri (parent);
char *descendant_uri = g_winhttp_file_get_uri (descendant);
const char *remainder;
char *retval;
remainder = match_prefix (descendant_uri, parent_uri);
if (remainder != NULL && *remainder == '/')
retval = g_strdup (remainder + 1);
else
retval = NULL;
g_free (parent_uri);
g_free (descendant_uri);
return retval;
}
static GFile *
g_winhttp_file_resolve_relative_path (GFile *file,
const char *relative_path)
{
GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
GWinHttpFile *child;
wchar_t *wnew_path = g_utf8_to_utf16 (relative_path, -1, NULL, NULL, NULL);
if (wnew_path == NULL)
return NULL;
if (*wnew_path != '/')
{
wchar_t *tmp = NULL;
int trailing_slash = winhttp_file->url.lpszUrlPath[winhttp_file->url.dwUrlPathLength-1] == L'/'? 1 : 0;
if (trailing_slash)
{
tmp = g_new (wchar_t, wcslen (winhttp_file->url.lpszUrlPath) + wcslen (wnew_path) + 1);
wcscpy (tmp, winhttp_file->url.lpszUrlPath);
}
else
{
tmp = g_new (wchar_t, wcslen (winhttp_file->url.lpszUrlPath) + 1 + wcslen (wnew_path) + 1);
wcscpy (tmp, winhttp_file->url.lpszUrlPath);
wcscat (tmp, L"/");
}
wcscat (tmp, wnew_path);
g_free (wnew_path);
wnew_path = tmp;
}
child = g_object_new (G_TYPE_WINHTTP_FILE, NULL);
child->vfs = winhttp_file->vfs;
child->url = winhttp_file->url;
child->url.lpszScheme = g_memdup2 (winhttp_file->url.lpszScheme, ((gsize) winhttp_file->url.dwSchemeLength + 1) * 2);
child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, ((gsize) winhttp_file->url.dwHostNameLength + 1) * 2);
child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, ((gsize) winhttp_file->url.dwUserNameLength + 1) * 2);
child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, ((gsize) winhttp_file->url.dwPasswordLength + 1) * 2);
child->url.lpszUrlPath = wnew_path;
child->url.dwUrlPathLength = wcslen (wnew_path);
child->url.lpszExtraInfo = NULL;
child->url.dwExtraInfoLength = 0;
return (GFile *) child;
}
static GFile *
g_winhttp_file_get_child_for_display_name (GFile *file,
const char *display_name,
GError **error)
{
GFile *new_file;
char *basename;
basename = g_locale_from_utf8 (display_name, -1, NULL, NULL, NULL);
if (basename == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_FILENAME,
_("Invalid filename %s"), display_name);
return NULL;
}
new_file = g_file_get_child (file, basename);
g_free (basename);
return new_file;
}
static GFile *
g_winhttp_file_set_display_name (GFile *file,
const char *display_name,
GCancellable *cancellable,
GError **error)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("Operation not supported"));
return NULL;
}
static GFileInfo *
g_winhttp_file_query_info (GFile *file,
const char *attributes,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error)
{
GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
HINTERNET connection, request;
const wchar_t *accept_types[] =
{
L"*/*",
NULL,
};
GFileInfo *info;
GFileAttributeMatcher *matcher;
char *basename;
wchar_t *content_length;
wchar_t *content_type;
SYSTEMTIME last_modified;
DWORD last_modified_len;
connection = G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpConnect
(G_WINHTTP_VFS (winhttp_file->vfs)->session,
winhttp_file->url.lpszHostName,
winhttp_file->url.nPort,
0);
if (connection == NULL)
{
_g_winhttp_set_error (error, GetLastError (), "HTTP connection");
return NULL;
}
request = G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpOpenRequest
(connection,
L"HEAD",
winhttp_file->url.lpszUrlPath,
NULL,
WINHTTP_NO_REFERER,
accept_types,
winhttp_file->url.nScheme == INTERNET_SCHEME_HTTPS ? WINHTTP_FLAG_SECURE : 0);
if (request == NULL)
{
_g_winhttp_set_error (error, GetLastError (), "HEAD request");
return NULL;
}
if (!G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpSendRequest
(request,
NULL, 0,
NULL, 0,
0,
0))
{
_g_winhttp_set_error (error, GetLastError (), "HEAD request");
return NULL;
}
if (!_g_winhttp_response (winhttp_file->vfs, request, error, "HEAD request"))
return NULL;
matcher = g_file_attribute_matcher_new (attributes);
info = g_file_info_new ();
g_file_info_set_attribute_mask (info, matcher);
basename = g_winhttp_file_get_basename (file);
g_file_info_set_name (info, basename);
g_free (basename);
if (_g_file_attribute_matcher_matches_id (matcher,
G_FILE_ATTRIBUTE_ID_STANDARD_DISPLAY_NAME))
{
char *display_name = g_winhttp_file_get_display_name (file);
g_file_info_set_display_name (info, display_name);
g_free (display_name);
}
content_length = NULL;
if (_g_winhttp_query_header (winhttp_file->vfs,
request,
"HEAD request",
WINHTTP_QUERY_CONTENT_LENGTH,
&content_length,
NULL))
{
gint64 cl;
size_t n;
const char *gint64_format = "%"G_GINT64_FORMAT"%n";
wchar_t *gint64_format_w = g_utf8_to_utf16 (gint64_format, -1, NULL, NULL, NULL);
if (swscanf (content_length, gint64_format_w, &cl, &n) == 1 &&
n == wcslen (content_length))
g_file_info_set_size (info, cl);
g_free (content_length);
g_free (gint64_format_w);
}
if (matcher == NULL)
return info;
content_type = NULL;
if (_g_winhttp_query_header (winhttp_file->vfs,
request,
"HEAD request",
WINHTTP_QUERY_CONTENT_TYPE,
&content_type,
NULL))
{
char *ct = g_utf16_to_utf8 (content_type, -1, NULL, NULL, NULL);
if (ct != NULL)
{
char *p = strchr (ct, ';');
if (p != NULL)
{
char *tmp = g_strndup (ct, p - ct);
g_file_info_set_content_type (info, tmp);
g_free (tmp);
}
else
g_file_info_set_content_type (info, ct);
}
g_free (ct);
}
last_modified_len = sizeof (last_modified);
if (G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpQueryHeaders
(request,
WINHTTP_QUERY_LAST_MODIFIED | WINHTTP_QUERY_FLAG_SYSTEMTIME,
NULL,
&last_modified,
&last_modified_len,
NULL) &&
last_modified_len == sizeof (last_modified) &&
/* Don't bother comparing to the exact Y2038 moment */
last_modified.wYear >= 1970 &&
last_modified.wYear < 2038)
{
GDateTime *dt = NULL, *dt2 = NULL;
dt = g_date_time_new_from_unix_utc (last_modified.wMilliseconds / 1000);
dt2 = g_date_time_add_seconds (dt, (last_modified.wMilliseconds % 1000) / 1000);
g_file_info_set_modification_date_time (info, dt2);
g_date_time_unref (dt2);
g_date_time_unref (dt);
}
g_file_attribute_matcher_unref (matcher);
return info;
}
static GFileInputStream *
g_winhttp_file_read (GFile *file,
GCancellable *cancellable,
GError **error)
{
GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
HINTERNET connection, request;
const wchar_t *accept_types[] =
{
L"*/*",
NULL,
};
connection = G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpConnect
(G_WINHTTP_VFS (winhttp_file->vfs)->session,
winhttp_file->url.lpszHostName,
winhttp_file->url.nPort,
0);
if (connection == NULL)
{
_g_winhttp_set_error (error, GetLastError (), "HTTP connection");
return NULL;
}
request = G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpOpenRequest
(connection,
L"GET",
winhttp_file->url.lpszUrlPath,
NULL,
WINHTTP_NO_REFERER,
accept_types,
winhttp_file->url.nScheme == INTERNET_SCHEME_HTTPS ? WINHTTP_FLAG_SECURE : 0);
if (request == NULL)
{
_g_winhttp_set_error (error, GetLastError (), "GET request");
return NULL;
}
return _g_winhttp_file_input_stream_new (winhttp_file, connection, request);
}
static GFileOutputStream *
g_winhttp_file_create (GFile *file,
GFileCreateFlags flags,
GCancellable *cancellable,
GError **error)
{
GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
HINTERNET connection;
connection = G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpConnect
(G_WINHTTP_VFS (winhttp_file->vfs)->session,
winhttp_file->url.lpszHostName,
winhttp_file->url.nPort,
0);
if (connection == NULL)
{
_g_winhttp_set_error (error, GetLastError (), "HTTP connection");
return NULL;
}
return _g_winhttp_file_output_stream_new (winhttp_file, connection);
}
#if 0
static GFileOutputStream *
g_winhttp_file_replace (GFile *file,
const char *etag,
gboolean make_backup,
GFileCreateFlags flags,
GCancellable *cancellable,
GError **error)
{
/* FIXME: Implement */
return NULL;
}
static gboolean
g_winhttp_file_delete (GFile *file,
GCancellable *cancellable,
GError **error)
{
/* FIXME: Implement */
return FALSE;
}
static gboolean
g_winhttp_file_make_directory (GFile *file,
GCancellable *cancellable,
GError **error)
{
/* FIXME: Implement */
return FALSE;
}
static gboolean
g_winhttp_file_copy (GFile *source,
GFile *destination,
GFileCopyFlags flags,
GCancellable *cancellable,
GFileProgressCallback progress_callback,
gpointer progress_callback_data,
GError **error)
{
/* Fall back to default copy?? */
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"Copy not supported");
return FALSE;
}
static gboolean
g_winhttp_file_move (GFile *source,
GFile *destination,
GFileCopyFlags flags,
GCancellable *cancellable,
GFileProgressCallback progress_callback,
gpointer progress_callback_data,
GError **error)
{
/* FIXME: Implement */
return FALSE;
}
#endif
static void
g_winhttp_file_file_iface_init (GFileIface *iface)
{
iface->dup = g_winhttp_file_dup;
iface->hash = g_winhttp_file_hash;
iface->equal = g_winhttp_file_equal;
iface->is_native = g_winhttp_file_is_native;
iface->has_uri_scheme = g_winhttp_file_has_uri_scheme;
iface->get_uri_scheme = g_winhttp_file_get_uri_scheme;
iface->get_basename = g_winhttp_file_get_basename;
iface->get_path = g_winhttp_file_get_path;
iface->get_uri = g_winhttp_file_get_uri;
iface->get_parse_name = g_winhttp_file_get_parse_name;
iface->get_parent = g_winhttp_file_get_parent;
iface->prefix_matches = g_winhttp_file_prefix_matches;
iface->get_relative_path = g_winhttp_file_get_relative_path;
iface->resolve_relative_path = g_winhttp_file_resolve_relative_path;
iface->get_child_for_display_name = g_winhttp_file_get_child_for_display_name;
iface->set_display_name = g_winhttp_file_set_display_name;
iface->query_info = g_winhttp_file_query_info;
iface->read_fn = g_winhttp_file_read;
iface->create = g_winhttp_file_create;
#if 0
iface->replace = g_winhttp_file_replace;
iface->delete_file = g_winhttp_file_delete;
iface->make_directory = g_winhttp_file_make_directory;
iface->copy = g_winhttp_file_copy;
iface->move = g_winhttp_file_move;
#endif
}

62
gio/win32/gwinhttpfile.h Normal file
View file

@ -0,0 +1,62 @@
/* 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>
*/
#ifndef __G_WINHTTP_FILE_H__
#define __G_WINHTTP_FILE_H__
#include <gio/giotypes.h>
#include "gwinhttpvfs.h"
G_BEGIN_DECLS
#define G_TYPE_WINHTTP_FILE (_g_winhttp_file_get_type ())
#define G_WINHTTP_FILE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_WINHTTP_FILE, GWinHttpFile))
#define G_WINHTTP_FILE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_WINHTTP_FILE, GWinHttpFileClass))
#define G_IS_WINHTTP_FILE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_WINHTTP_FILE))
#define G_IS_WINHTTP_FILE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_WINHTTP_FILE))
#define G_WINHTTP_FILE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_WINHTTP_FILE, GWinHttpFileClass))
typedef struct _GWinHttpFile GWinHttpFile;
typedef struct _GWinHttpFileClass GWinHttpFileClass;
struct _GWinHttpFile
{
GObject parent_instance;
GWinHttpVfs *vfs;
URL_COMPONENTS url;
};
struct _GWinHttpFileClass
{
GObjectClass parent_class;
};
GType _g_winhttp_file_get_type (void) G_GNUC_CONST;
GFile * _g_winhttp_file_new (GWinHttpVfs *vfs, const char *uri);
G_END_DECLS
#endif /* __G_WINHTTP_FILE_H__ */

View file

@ -0,0 +1,175 @@
/* 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 <glib.h>
#include "gio/gcancellable.h"
#include "gio/gioerror.h"
#include "gwinhttpfileinputstream.h"
#include "glibintl.h"
struct _GWinHttpFileInputStream
{
GFileInputStream parent_instance;
GWinHttpFile *file;
gboolean request_sent;
HINTERNET connection;
HINTERNET request;
};
struct _GWinHttpFileInputStreamClass
{
GFileInputStreamClass parent_class;
};
#define g_winhttp_file_input_stream_get_type _g_winhttp_file_input_stream_get_type
G_DEFINE_TYPE (GWinHttpFileInputStream, g_winhttp_file_input_stream, G_TYPE_FILE_INPUT_STREAM)
static gssize g_winhttp_file_input_stream_read (GInputStream *stream,
void *buffer,
gsize count,
GCancellable *cancellable,
GError **error);
static gboolean g_winhttp_file_input_stream_close (GInputStream *stream,
GCancellable *cancellable,
GError **error);
static void
g_winhttp_file_input_stream_finalize (GObject *object)
{
GWinHttpFileInputStream *winhttp_stream;
winhttp_stream = G_WINHTTP_FILE_INPUT_STREAM (object);
if (winhttp_stream->request != NULL)
G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (winhttp_stream->request);
if (winhttp_stream->connection != NULL)
G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (winhttp_stream->connection);
g_object_unref (winhttp_stream->file);
winhttp_stream->file = NULL;
G_OBJECT_CLASS (g_winhttp_file_input_stream_parent_class)->finalize (object);
}
static void
g_winhttp_file_input_stream_class_init (GWinHttpFileInputStreamClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
gobject_class->finalize = g_winhttp_file_input_stream_finalize;
stream_class->read_fn = g_winhttp_file_input_stream_read;
stream_class->close_fn = g_winhttp_file_input_stream_close;
}
static void
g_winhttp_file_input_stream_init (GWinHttpFileInputStream *info)
{
}
/*
* g_winhttp_file_input_stream_new:
* @file: the GWinHttpFile being read
* @connection: handle to the HTTP connection, as from WinHttpConnect()
* @request: handle to the HTTP request, as from WinHttpOpenRequest
*
* Returns: #GFileInputStream for the given request
*/
GFileInputStream *
_g_winhttp_file_input_stream_new (GWinHttpFile *file,
HINTERNET connection,
HINTERNET request)
{
GWinHttpFileInputStream *stream;
stream = g_object_new (G_TYPE_WINHTTP_FILE_INPUT_STREAM, NULL);
stream->file = g_object_ref (file);
stream->request_sent = FALSE;
stream->connection = connection;
stream->request = request;
return G_FILE_INPUT_STREAM (stream);
}
static gssize
g_winhttp_file_input_stream_read (GInputStream *stream,
void *buffer,
gsize count,
GCancellable *cancellable,
GError **error)
{
GWinHttpFileInputStream *winhttp_stream = G_WINHTTP_FILE_INPUT_STREAM (stream);
DWORD bytes_read;
if (!winhttp_stream->request_sent)
{
if (!G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpSendRequest
(winhttp_stream->request,
NULL, 0,
NULL, 0,
0,
0))
{
_g_winhttp_set_error (error, GetLastError (), "GET request");
return -1;
}
if (!_g_winhttp_response (winhttp_stream->file->vfs,
winhttp_stream->request,
error,
"GET request"))
return -1;
winhttp_stream->request_sent = TRUE;
}
if (!G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpReadData
(winhttp_stream->request, buffer, count, &bytes_read))
{
_g_winhttp_set_error (error, GetLastError (), "GET request");
return -1;
}
return bytes_read;
}
static gboolean
g_winhttp_file_input_stream_close (GInputStream *stream,
GCancellable *cancellable,
GError **error)
{
GWinHttpFileInputStream *winhttp_stream = G_WINHTTP_FILE_INPUT_STREAM (stream);
if (winhttp_stream->connection != NULL)
G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (winhttp_stream->connection);
winhttp_stream->connection = NULL;
return TRUE;
}

View file

@ -0,0 +1,50 @@
/* 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>
*/
#ifndef __G_WINHTTP_FILE_INPUT_STREAM_H__
#define __G_WINHTTP_FILE_INPUT_STREAM_H__
#include <gio/gfileinputstream.h>
#include "gwinhttpfile.h"
G_BEGIN_DECLS
#define G_TYPE_WINHTTP_FILE_INPUT_STREAM (_g_winhttp_file_input_stream_get_type ())
#define G_WINHTTP_FILE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_WINHTTP_FILE_INPUT_STREAM, GWinHttpFileInputStream))
#define G_WINHTTP_FILE_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_WINHTTP_FILE_INPUT_STREAM, GWinHttpFileInputStreamClass))
#define G_IS_WINHTTP_FILE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_WINHTTP_FILE_INPUT_STREAM))
#define G_IS_WINHTTP_FILE_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_WINHTTP_FILE_INPUT_STREAM))
#define G_WINHTTP_FILE_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_WINHTTP_FILE_INPUT_STREAM, GWinHttpFileInputStreamClass))
typedef struct _GWinHttpFileInputStream GWinHttpFileInputStream;
typedef struct _GWinHttpFileInputStreamClass GWinHttpFileInputStreamClass;
GType _g_winhttp_file_input_stream_get_type (void) G_GNUC_CONST;
GFileInputStream *_g_winhttp_file_input_stream_new (GWinHttpFile *file,
HINTERNET connection,
HINTERNET request);
G_END_DECLS
#endif /* __G_WINHTTP_FILE_INPUT_STREAM_H__ */

View file

@ -0,0 +1,183 @@
/* 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 <glib.h>
#include "gio/gcancellable.h"
#include "gio/gioerror.h"
#include "gwinhttpfileoutputstream.h"
#include "glibintl.h"
struct _GWinHttpFileOutputStream
{
GFileOutputStream parent_instance;
GWinHttpFile *file;
HINTERNET connection;
goffset offset;
};
struct _GWinHttpFileOutputStreamClass
{
GFileOutputStreamClass parent_class;
};
#define g_winhttp_file_output_stream_get_type _g_winhttp_file_output_stream_get_type
G_DEFINE_TYPE (GWinHttpFileOutputStream, g_winhttp_file_output_stream, G_TYPE_FILE_OUTPUT_STREAM)
static gssize g_winhttp_file_output_stream_write (GOutputStream *stream,
const void *buffer,
gsize count,
GCancellable *cancellable,
GError **error);
static void
g_winhttp_file_output_stream_finalize (GObject *object)
{
GWinHttpFileOutputStream *winhttp_stream;
winhttp_stream = G_WINHTTP_FILE_OUTPUT_STREAM (object);
if (winhttp_stream->connection != NULL)
G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (winhttp_stream->connection);
G_OBJECT_CLASS (g_winhttp_file_output_stream_parent_class)->finalize (object);
}
static void
g_winhttp_file_output_stream_class_init (GWinHttpFileOutputStreamClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (klass);
gobject_class->finalize = g_winhttp_file_output_stream_finalize;
stream_class->write_fn = g_winhttp_file_output_stream_write;
}
static void
g_winhttp_file_output_stream_init (GWinHttpFileOutputStream *info)
{
}
/*
* g_winhttp_file_output_stream_new:
* @file: the GWinHttpFile being read
* @connection: handle to the HTTP connection, as from WinHttpConnect()
* @request: handle to the HTTP request, as from WinHttpOpenRequest
*
* Returns: #GFileOutputStream for the given request
*/
GFileOutputStream *
_g_winhttp_file_output_stream_new (GWinHttpFile *file,
HINTERNET connection)
{
GWinHttpFileOutputStream *stream;
stream = g_object_new (G_TYPE_WINHTTP_FILE_OUTPUT_STREAM, NULL);
stream->file = file;
stream->connection = connection;
stream->offset = 0;
return G_FILE_OUTPUT_STREAM (stream);
}
static gssize
g_winhttp_file_output_stream_write (GOutputStream *stream,
const void *buffer,
gsize count,
GCancellable *cancellable,
GError **error)
{
GWinHttpFileOutputStream *winhttp_stream = G_WINHTTP_FILE_OUTPUT_STREAM (stream);
HINTERNET request;
char *headers;
wchar_t *wheaders;
DWORD bytes_written;
request = G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpOpenRequest
(winhttp_stream->connection,
L"PUT",
winhttp_stream->file->url.lpszUrlPath,
NULL,
WINHTTP_NO_REFERER,
NULL,
winhttp_stream->file->url.nScheme == INTERNET_SCHEME_HTTPS ? WINHTTP_FLAG_SECURE : 0);
if (request == NULL)
{
_g_winhttp_set_error (error, GetLastError (), "PUT request");
return -1;
}
headers = g_strdup_printf ("Content-Range: bytes %" G_GINT64_FORMAT "-%" G_GINT64_FORMAT "/*\r\n",
winhttp_stream->offset, winhttp_stream->offset + count);
wheaders = g_utf8_to_utf16 (headers, -1, NULL, NULL, NULL);
g_free (headers);
if (!G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpSendRequest
(request,
wheaders, -1,
NULL, 0,
count,
0))
{
_g_winhttp_set_error (error, GetLastError (), "PUT request");
G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (request);
g_free (wheaders);
return -1;
}
g_free (wheaders);
if (!G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpWriteData
(request, buffer, count, &bytes_written))
{
_g_winhttp_set_error (error, GetLastError (), "PUT request");
G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (request);
return -1;
}
winhttp_stream->offset += bytes_written;
if (!_g_winhttp_response (winhttp_stream->file->vfs,
request,
error,
"PUT request"))
{
G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (request);
return -1;
}
G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (request);
return bytes_written;
}

View file

@ -0,0 +1,49 @@
/* 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>
*/
#ifndef __G_WINHTTP_FILE_OUTPUT_STREAM_H__
#define __G_WINHTTP_FILE_OUTPUT_STREAM_H__
#include <gio/gfileoutputstream.h>
#include "gwinhttpfile.h"
G_BEGIN_DECLS
#define G_TYPE_WINHTTP_FILE_OUTPUT_STREAM (_g_winhttp_file_output_stream_get_type ())
#define G_WINHTTP_FILE_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_WINHTTP_FILE_OUTPUT_STREAM, GWinHttpFileOutputStream))
#define G_WINHTTP_FILE_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_WINHTTP_FILE_OUTPUT_STREAM, GWinHttpFileOutputStreamClass))
#define G_IS_WINHTTP_FILE_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_WINHTTP_FILE_OUTPUT_STREAM))
#define G_IS_WINHTTP_FILE_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_WINHTTP_FILE_OUTPUT_STREAM))
#define G_WINHTTP_FILE_OUTPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_WINHTTP_FILE_OUTPUT_STREAM, GWinHttpFileOutputStreamClass))
typedef struct _GWinHttpFileOutputStream GWinHttpFileOutputStream;
typedef struct _GWinHttpFileOutputStreamClass GWinHttpFileOutputStreamClass;
GType _g_winhttp_file_output_stream_get_type (void) G_GNUC_CONST;
GFileOutputStream *_g_winhttp_file_output_stream_new (GWinHttpFile *file,
HINTERNET connection);
G_END_DECLS
#endif /* __G_WINHTTP_FILE_OUTPUT_STREAM_H__ */

479
gio/win32/gwinhttpvfs.c Normal file
View file

@ -0,0 +1,479 @@
/* 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;
}

106
gio/win32/gwinhttpvfs.h Normal file
View file

@ -0,0 +1,106 @@
/* 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>
*/
#ifndef __G_WINHTTP_VFS_H__
#define __G_WINHTTP_VFS_H__
#include <gio/giotypes.h>
#include <gio/gvfs.h>
#include <windows.h>
#include "winhttp.h"
G_BEGIN_DECLS
#define G_TYPE_WINHTTP_VFS (_g_winhttp_vfs_get_type ())
#define G_WINHTTP_VFS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_WINHTTP_VFS, GWinHttpVfs))
#define G_WINHTTP_VFS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_WINHTTP_VFS, GWinHttpVfsClass))
#define G_IS_WINHTTP_VFS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_WINHTTP_VFS))
#define G_IS_WINHTTP_VFS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_WINHTTP_VFS))
#define G_WINHTTP_VFS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_WINHTTP_VFS, GWinHttpVfsClass))
typedef struct _GWinHttpVfs GWinHttpVfs;
typedef struct _GWinHttpDllFuncs GWinHttpDllFuncs;
typedef struct _GWinHttpVfsClass GWinHttpVfsClass;
struct _GWinHttpVfs
{
GVfs parent;
GVfs *wrapped_vfs;
HINTERNET session;
};
struct _GWinHttpDllFuncs
{
BOOL (WINAPI *pWinHttpCloseHandle) (HINTERNET);
BOOL (WINAPI *pWinHttpCrackUrl) (LPCWSTR,DWORD,DWORD,LPURL_COMPONENTS);
HINTERNET (WINAPI *pWinHttpConnect) (HINTERNET,LPCWSTR,INTERNET_PORT,DWORD);
BOOL (WINAPI *pWinHttpCreateUrl) (LPURL_COMPONENTS,DWORD,LPWSTR,LPDWORD);
HINTERNET (WINAPI *pWinHttpOpen) (LPCWSTR,DWORD,LPCWSTR,LPCWSTR,DWORD);
HINTERNET (WINAPI *pWinHttpOpenRequest) (HINTERNET,LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR*,DWORD);
BOOL (WINAPI *pWinHttpQueryDataAvailable) (HINTERNET,LPDWORD);
BOOL (WINAPI *pWinHttpQueryHeaders) (HINTERNET,DWORD,LPCWSTR,LPVOID,LPDWORD,LPDWORD);
BOOL (WINAPI *pWinHttpReadData) (HINTERNET,LPVOID,DWORD,LPDWORD);
BOOL (WINAPI *pWinHttpReceiveResponse) (HINTERNET,LPVOID);
BOOL (WINAPI *pWinHttpSendRequest) (HINTERNET,LPCWSTR,DWORD,LPVOID,DWORD,DWORD,DWORD_PTR);
BOOL (WINAPI *pWinHttpWriteData) (HINTERNET,LPCVOID,DWORD,LPDWORD);
};
struct _GWinHttpVfsClass
{
GVfsClass parent_class;
/* As there is no import library for winhttp.dll in mingw, and
* winhttp.dll isn't present on Windows 2000 anyway, we must look up
* the functions we need dynamically. Store the pointers here.
*/
GWinHttpDllFuncs *funcs;
};
GType _g_winhttp_vfs_get_type (void) G_GNUC_CONST;
GVfs *_g_winhttp_vfs_new (void);
char *_g_winhttp_error_message (DWORD error_code);
void _g_winhttp_set_error (GError **error,
DWORD error_code,
const char *what);
gboolean _g_winhttp_response (GWinHttpVfs *vfs,
HINTERNET request,
GError **error,
const char *what);
gboolean _g_winhttp_query_header (GWinHttpVfs *vfs,
HINTERNET request,
const char *request_description,
DWORD which_header,
wchar_t **header,
GError **error);
G_END_DECLS
#endif /* __G_WINHTTP_VFS_H__ */

15
gio/win32/meson.build Normal file
View file

@ -0,0 +1,15 @@
giowin32_sources = [
'gwin32fsmonitorutils.c',
'gwin32filemonitor.c',
'gwinhttpvfs.c',
'gwinhttpfile.c',
'gwinhttpfileinputstream.c',
'gwinhttpfileoutputstream.c',
]
giowin32_lib = static_library('giowin32',
sources : [giowin32_sources],
include_directories : [configinc, glibinc, gioinc, gmoduleinc],
dependencies : [libintl, gioenumtypes_dep],
pic : true,
c_args : gio_c_args)

247
gio/win32/winhttp.h Normal file
View file

@ -0,0 +1,247 @@
/*
* Copyright (C) 2007 Francois Gouget
*
* 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/>.
*/
#ifndef __WINE_WINHTTP_H
#define __WINE_WINHTTP_H
#define WINHTTPAPI
#define BOOLAPI WINHTTPAPI BOOL WINAPI
typedef LPVOID HINTERNET;
typedef HINTERNET *LPHINTERNET;
#define INTERNET_DEFAULT_PORT 0
#define INTERNET_DEFAULT_HTTP_PORT 80
#define INTERNET_DEFAULT_HTTPS_PORT 443
typedef WORD INTERNET_PORT;
typedef INTERNET_PORT *LPINTERNET_PORT;
#define INTERNET_SCHEME_HTTP 1
#define INTERNET_SCHEME_HTTPS 2
typedef int INTERNET_SCHEME, *LPINTERNET_SCHEME;
/* flags for WinHttpOpen */
#define WINHTTP_FLAG_ASYNC 0x10000000
/* flags for WinHttpOpenRequest */
#define WINHTTP_FLAG_ESCAPE_PERCENT 0x00000004
#define WINHTTP_FLAG_NULL_CODEPAGE 0x00000008
#define WINHTTP_FLAG_ESCAPE_DISABLE 0x00000040
#define WINHTTP_FLAG_ESCAPE_DISABLE_QUERY 0x00000080
#define WINHTTP_FLAG_BYPASS_PROXY_CACHE 0x00000100
#define WINHTTP_FLAG_REFRESH WINHTTP_FLAG_BYPASS_PROXY_CACHE
#define WINHTTP_FLAG_SECURE 0x00800000
#define WINHTTP_ACCESS_TYPE_DEFAULT_PROXY 0
#define WINHTTP_ACCESS_TYPE_NO_PROXY 1
#define WINHTTP_ACCESS_TYPE_NAMED_PROXY 3
#define WINHTTP_NO_PROXY_NAME NULL
#define WINHTTP_NO_PROXY_BYPASS NULL
#define WINHTTP_NO_REFERER NULL
#define WINHTTP_DEFAULT_ACCEPT_TYPES NULL
#define WINHTTP_ERROR_BASE 12000
/* The original WINE winhttp.h didn't contain symbolic names for the
* error codes. However, the values of most of them are publicly
* documented at
* http://msdn.microsoft.com/en-us/library/aa383770(VS.85).aspx so
* we can add them here.
*/
#define ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR 12178
#define ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT 12166
#define ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN 12103
#define ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND 12102
#define ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN 12100
#define ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND 12101
#define ERROR_WINHTTP_CANNOT_CONNECT 12029
#define ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW 12183
#define ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED 12044
#define ERROR_WINHTTP_CONNECTION_ERROR 12030
#define ERROR_WINHTTP_HEADER_ALREADY_EXISTS 12155
#define ERROR_WINHTTP_HEADER_COUNT_EXCEEDED 12181
#define ERROR_WINHTTP_HEADER_NOT_FOUND 12150
#define ERROR_WINHTTP_HEADER_SIZE_OVERFLOW 12182
#define ERROR_WINHTTP_INCORRECT_HANDLE_STATE 12019
#define ERROR_WINHTTP_INCORRECT_HANDLE_TYPE 12018
#define ERROR_WINHTTP_INTERNAL_ERROR 12004
#define ERROR_WINHTTP_INVALID_OPTION 12009
#define ERROR_WINHTTP_INVALID_QUERY_REQUEST 12154
#define ERROR_WINHTTP_INVALID_SERVER_RESPONSE 12152
#define ERROR_WINHTTP_INVALID_URL 12005
#define ERROR_WINHTTP_LOGIN_FAILURE 12015
#define ERROR_WINHTTP_NAME_NOT_RESOLVED 12007
#define ERROR_WINHTTP_NOT_INITIALIZED 12172
#define ERROR_WINHTTP_OPERATION_CANCELLED 12017
#define ERROR_WINHTTP_OPTION_NOT_SETTABLE 12011
#define ERROR_WINHTTP_OUT_OF_HANDLES 12001
#define ERROR_WINHTTP_REDIRECT_FAILED 12156
#define ERROR_WINHTTP_RESEND_REQUEST 12032
#define ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW 12184
#define ERROR_WINHTTP_SECURE_CERT_CN_INVALID 12038
#define ERROR_WINHTTP_SECURE_CERT_DATE_INVALID 12037
#define ERROR_WINHTTP_SECURE_CERT_REV_FAILED 12057
#define ERROR_WINHTTP_SECURE_CERT_REVOKED 12170
#define ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE 12179
#define ERROR_WINHTTP_SECURE_CHANNEL_ERROR 12157
#define ERROR_WINHTTP_SECURE_FAILURE 12175
#define ERROR_WINHTTP_SECURE_INVALID_CA 12045
#define ERROR_WINHTTP_SECURE_INVALID_CERT 12169
#define ERROR_WINHTTP_SHUTDOWN 12012
#define ERROR_WINHTTP_TIMEOUT 12002
#define ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT 12167
#define ERROR_WINHTTP_UNRECOGNIZED_SCHEME 12006
/* End of added error codes */
#define ERROR_WINHTTP_AUTODETECTION_FAILED (WINHTTP_ERROR_BASE + 180)
typedef struct
{
DWORD dwStructSize;
LPWSTR lpszScheme;
DWORD dwSchemeLength;
INTERNET_SCHEME nScheme;
LPWSTR lpszHostName;
DWORD dwHostNameLength;
INTERNET_PORT nPort;
LPWSTR lpszUserName;
DWORD dwUserNameLength;
LPWSTR lpszPassword;
DWORD dwPasswordLength;
LPWSTR lpszUrlPath;
DWORD dwUrlPathLength;
LPWSTR lpszExtraInfo;
DWORD dwExtraInfoLength;
} URL_COMPONENTS, *LPURL_COMPONENTS;
typedef URL_COMPONENTS URL_COMPONENTSW;
typedef LPURL_COMPONENTS LPURL_COMPONENTSW;
typedef struct
{
DWORD_PTR dwResult;
DWORD dwError;
} WINHTTP_ASYNC_RESULT, *LPWINHTTP_ASYNC_RESULT;
typedef struct
{
FILETIME ftExpiry;
FILETIME ftStart;
LPWSTR lpszSubjectInfo;
LPWSTR lpszIssuerInfo;
LPWSTR lpszProtocolName;
LPWSTR lpszSignatureAlgName;
LPWSTR lpszEncryptionAlgName;
DWORD dwKeySize;
} WINHTTP_CERTIFICATE_INFO;
typedef struct
{
DWORD dwAccessType;
LPCWSTR lpszProxy;
LPCWSTR lpszProxyBypass;
} WINHTTP_PROXY_INFO, *LPWINHTTP_PROXY_INFO;
typedef WINHTTP_PROXY_INFO WINHTTP_PROXY_INFOW;
typedef LPWINHTTP_PROXY_INFO LPWINHTTP_PROXY_INFOW;
typedef struct
{
BOOL fAutoDetect;
LPWSTR lpszAutoConfigUrl;
LPWSTR lpszProxy;
LPWSTR lpszProxyBypass;
} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
typedef VOID (CALLBACK *WINHTTP_STATUS_CALLBACK)(HINTERNET,DWORD_PTR,DWORD,LPVOID,DWORD);
typedef struct
{
DWORD dwFlags;
DWORD dwAutoDetectFlags;
LPCWSTR lpszAutoConfigUrl;
LPVOID lpvReserved;
DWORD dwReserved;
BOOL fAutoLogonIfChallenged;
} WINHTTP_AUTOPROXY_OPTIONS;
typedef struct
{
DWORD dwMajorVersion;
DWORD dwMinorVersion;
} HTTP_VERSION_INFO, *LPHTTP_VERSION_INFO;
#ifdef __cplusplus
extern "C" {
#endif
BOOL WINAPI WinHttpAddRequestHeaders(HINTERNET,LPCWSTR,DWORD,DWORD);
BOOL WINAPI WinHttpDetectAutoProxyConfigUrl(DWORD,LPWSTR*);
BOOL WINAPI WinHttpCheckPlatform(void);
BOOL WINAPI WinHttpCloseHandle(HINTERNET);
HINTERNET WINAPI WinHttpConnect(HINTERNET,LPCWSTR,INTERNET_PORT,DWORD);
BOOL WINAPI WinHttpCrackUrl(LPCWSTR,DWORD,DWORD,LPURL_COMPONENTS);
BOOL WINAPI WinHttpCreateUrl(LPURL_COMPONENTS,DWORD,LPWSTR,LPDWORD);
BOOL WINAPI WinHttpGetDefaultProxyConfiguration(WINHTTP_PROXY_INFO*);
BOOL WINAPI WinHttpGetIEProxyConfigForCurrentUser(WINHTTP_CURRENT_USER_IE_PROXY_CONFIG* config);
BOOL WINAPI WinHttpGetProxyForUrl(HINTERNET,LPCWSTR,WINHTTP_AUTOPROXY_OPTIONS*,WINHTTP_PROXY_INFO*);
HINTERNET WINAPI WinHttpOpen(LPCWSTR,DWORD,LPCWSTR,LPCWSTR,DWORD);
/* The sixth parameter to WinHttpOpenRequest was wrong in the original
* WINE header. It should be LPCWSTR*, not LPCWSTR, as it points to an
* array of wide strings.
*/
HINTERNET WINAPI WinHttpOpenRequest(HINTERNET,LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR*,DWORD);
BOOL WINAPI WinHttpQueryAuthParams(HINTERNET,DWORD,LPVOID*);
BOOL WINAPI WinHttpQueryAuthSchemes(HINTERNET,LPDWORD,LPDWORD,LPDWORD);
BOOL WINAPI WinHttpQueryDataAvailable(HINTERNET,LPDWORD);
BOOL WINAPI WinHttpQueryHeaders(HINTERNET,DWORD,LPCWSTR,LPVOID,LPDWORD,LPDWORD);
BOOL WINAPI WinHttpReadData(HINTERNET,LPVOID,DWORD,LPDWORD);
BOOL WINAPI WinHttpReceiveResponse(HINTERNET,LPVOID);
BOOL WINAPI WinHttpSendRequest(HINTERNET,LPCWSTR,DWORD,LPVOID,DWORD,DWORD,DWORD_PTR);
BOOL WINAPI WinHttpSetDefaultProxyConfiguration(WINHTTP_PROXY_INFO*);
BOOL WINAPI WinHttpSetCredentials(HINTERNET,DWORD,DWORD,LPCWSTR,LPCWSTR,LPVOID);
BOOL WINAPI WinHttpSetOption(HINTERNET,DWORD,LPVOID,DWORD);
WINHTTP_STATUS_CALLBACK WINAPI WinHttpSetStatusCallback(HINTERNET,WINHTTP_STATUS_CALLBACK,DWORD,DWORD_PTR);
BOOL WINAPI WinHttpSetTimeouts(HINTERNET,int,int,int,int);
BOOL WINAPI WinHttpTimeFromSystemTime(CONST SYSTEMTIME *,LPWSTR);
BOOL WINAPI WinHttpTimeToSystemTime(LPCWSTR,SYSTEMTIME*);
BOOL WINAPI WinHttpWriteData(HINTERNET,LPCVOID,DWORD,LPDWORD);
/* Additional definitions, from the public domain <wininet.h> in mingw */
#define ICU_ESCAPE 0x80000000
#define ICU_DECODE 0x10000000
/* A few constants I couldn't find publicly documented, so I looked up
* their value from the Windows SDK <winhttp.h>. Presumably this falls
* under fair use.
*/
#define WINHTTP_QUERY_CONTENT_LENGTH 5
#define WINHTTP_QUERY_CONTENT_TYPE 1
#define WINHTTP_QUERY_LAST_MODIFIED 11
#define WINHTTP_QUERY_STATUS_CODE 19
#define WINHTTP_QUERY_STATUS_TEXT 20
#define WINHTTP_QUERY_FLAG_SYSTEMTIME 0x40000000
#ifdef __cplusplus
}
#endif
#endif /* __WINE_WINHTTP_H */