Import Upstream version 2.72.4
This commit is contained in:
commit
4ef3ff9793
2003 changed files with 1332420 additions and 0 deletions
104
gio/win32/gwin32filemonitor.c
Normal file
104
gio/win32/gwin32filemonitor.c
Normal 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;
|
||||
}
|
||||
62
gio/win32/gwin32filemonitor.h
Normal file
62
gio/win32/gwin32filemonitor.h
Normal 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__ */
|
||||
425
gio/win32/gwin32fsmonitorutils.c
Normal file
425
gio/win32/gwin32fsmonitorutils.c
Normal 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);
|
||||
}
|
||||
76
gio/win32/gwin32fsmonitorutils.h
Normal file
76
gio/win32/gwin32fsmonitorutils.h
Normal 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
788
gio/win32/gwinhttpfile.c
Normal 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
62
gio/win32/gwinhttpfile.h
Normal 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__ */
|
||||
175
gio/win32/gwinhttpfileinputstream.c
Normal file
175
gio/win32/gwinhttpfileinputstream.c
Normal 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;
|
||||
}
|
||||
50
gio/win32/gwinhttpfileinputstream.h
Normal file
50
gio/win32/gwinhttpfileinputstream.h
Normal 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__ */
|
||||
183
gio/win32/gwinhttpfileoutputstream.c
Normal file
183
gio/win32/gwinhttpfileoutputstream.c
Normal 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;
|
||||
}
|
||||
49
gio/win32/gwinhttpfileoutputstream.h
Normal file
49
gio/win32/gwinhttpfileoutputstream.h
Normal 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
479
gio/win32/gwinhttpvfs.c
Normal 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
106
gio/win32/gwinhttpvfs.h
Normal 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
15
gio/win32/meson.build
Normal 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
247
gio/win32/winhttp.h
Normal 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 */
|
||||
Loading…
Add table
Add a link
Reference in a new issue