[phodav] spice-webdavd-windows: Automount shared folder
- From: Victor Toso de Carvalho <victortoso src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [phodav] spice-webdavd-windows: Automount shared folder
- Date: Fri, 24 Jun 2016 15:44:18 +0000 (UTC)
commit 13151735cb97bc4e95deb72597c1024d139504e3
Author: Lukas Venhoda <lvenhoda redhat com>
Date: Wed May 25 15:51:42 2016 +0200
spice-webdavd-windows: Automount shared folder
Try to connect to shared folder automatically on Windows.
On each loop of run_service(), run a GTask, that waits for half a
second. If read_thread() returns, it means, that sharing is not yet
connected, and the map_drive task is cancelled.
If the map_drive task is NOT cancelled, it enumerates free drive
letters, and maps Spice Folder to highest possible (from Z: to A:).
If all drive letters are already assigned, show a critical error, but
don't stop the service. The folder can still be accessed trough other
means.
Acked-by: Victor Toso <victortoso redhat com>
Makefile.am | 4 ++
spice/spice-webdavd.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 144 insertions(+), 0 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 6127f93..d8e2d53 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -87,6 +87,10 @@ spice_webdavd_LDADD = \
$(PIE_LDFLAGS) \
$(NULL)
+if OS_WIN32
+spice_webdavd_LDADD += -lnetapi32 -lmpr
+endif
+
deps.txt:
$(AM_V_GEN)rpm -qa | grep $(host_os) | sort | unix2dos > $@
diff --git a/spice/spice-webdavd.c b/spice/spice-webdavd.c
index f9c5cf1..9783459 100644
--- a/spice/spice-webdavd.c
+++ b/spice/spice-webdavd.c
@@ -737,11 +737,146 @@ open_mux_path (const char *path)
mux_queue = output_queue_new (G_OUTPUT_STREAM (mux_ostream));
}
+#ifdef G_OS_WIN32
+#define MAX_SHARED_FOLDER_NAME_SIZE 64
+#define MAX_DRIVE_LETTER_SIZE 3
+typedef enum _MapDriveEnum
+{
+ MAP_DRIVE_OK,
+ MAP_DRIVE_TRY_AGAIN,
+ MAP_DRIVE_ERROR
+} MapDriveEnum;
+
+typedef struct _MapDriveData
+{
+ GCancellable *cancel_map;
+} MapDriveData;
+
+static gchar
+get_free_drive_letter(void)
+{
+ const guint32 max_mask = 1 << 25;
+ guint32 drives;
+ gint i;
+
+ drives = GetLogicalDrives ();
+ if (drives == 0)
+ {
+ g_warning ("%s", g_win32_error_message (GetLastError ()));
+ return 0;
+ }
+
+ for (i = 0; i < 26; i++)
+ {
+ guint32 mask = max_mask >> i;
+ if ((drives & mask) == 0)
+ return 'z' - i;
+ }
+
+ return 0;
+}
+
+/* User is required to call netresource_free, when no longer needed. */
+static void
+netresource_init(NETRESOURCE *net_resource, const gchar drive_letter)
+{
+ net_resource->dwType = RESOURCETYPE_DISK;
+ net_resource->lpLocalName = g_strdup_printf("%c:", drive_letter);
+ net_resource->lpRemoteName = g_strdup_printf("http://localhost:%d/", port);
+ net_resource->lpProvider = NULL;
+}
+
+static void
+netresource_free(NETRESOURCE *net_resource)
+{
+ g_free(net_resource->lpLocalName);
+ g_free(net_resource->lpRemoteName);
+}
+
+static MapDriveEnum
+map_drive(const gchar drive_letter)
+{
+ NETRESOURCE net_resource;
+ guint32 errn;
+
+ netresource_init(&net_resource, drive_letter);
+ errn = WNetAddConnection2 (&net_resource, NULL, NULL, CONNECT_TEMPORARY);
+ netresource_free(&net_resource);
+
+ if (errn == NO_ERROR)
+ {
+ g_debug ("Shared folder mapped to %c succesfully", drive_letter);
+ return MAP_DRIVE_OK;
+ }
+ else if (errn == ERROR_ALREADY_ASSIGNED)
+ {
+ g_debug ("Drive letter %c is already assigned", drive_letter);
+ return MAP_DRIVE_TRY_AGAIN;
+ }
+
+ g_warning ("map_drive error %d", errn);
+ return MAP_DRIVE_ERROR;
+}
+
+static void
+map_drive_cb(GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ const guint32 delay = 500; //half a second
+ MapDriveData *map_drive_data = task_data;
+ gchar drive_letter;
+ GPollFD cancel_pollfd;
+ guint32 ret = 0;
+
+ if (!g_cancellable_make_pollfd (map_drive_data->cancel_map, &cancel_pollfd))
+ {
+ g_critical ("GPollFD failed to create.");
+ return;
+ }
+
+ ret = g_poll (&cancel_pollfd, 1, delay);
+ g_cancellable_release_fd (map_drive_data->cancel_map);
+
+ if (ret != 0)
+ {
+ return;
+ }
+
+ while (TRUE)
+ {
+ drive_letter = get_free_drive_letter ();
+ if (drive_letter == 0)
+ {
+ g_warning ("all drive letters already assigned.");
+ break;
+ }
+
+ if (map_drive (drive_letter) != MAP_DRIVE_TRY_AGAIN)
+ {
+ break;
+ }
+ //TODO: After mapping, rename network drive from \\localhost PORT\DavWWWRoot
+ // to something like SPICE Shared Folder
+ }
+}
+#endif
+
static void
run_service (void)
{
g_debug ("Run service");
+#ifdef G_OS_WIN32
+ MapDriveData map_drive_data;
+ map_drive_data.cancel_map = g_cancellable_new ();
+ GTask *map_drive_task = g_task_new (NULL, NULL, NULL, NULL);
+ g_task_set_task_data (map_drive_task, &map_drive_data, NULL);
+ g_task_run_in_thread (map_drive_task, map_drive_cb);
+ g_object_unref (map_drive_task);
+#endif
+
g_socket_service_start (socket_service);
cancel = g_cancellable_new ();
@@ -775,6 +910,11 @@ run_service (void)
g_main_loop_run (loop);
g_main_loop_unref (loop);
+#ifdef G_OS_WIN32
+ g_cancellable_cancel (map_drive_data.cancel_map);
+ g_object_unref (map_drive_data.cancel_map);
+#endif
+
g_cancellable_cancel (cancel);
g_clear_object (&mux_istream);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]