[Spice-devel] [phodav PATCH 4/4] spice-webdavd: Automount shared folder on Windows
Lukas Venhoda
lvenhoda at redhat.com
Thu Aug 27 09:25:53 PDT 2015
Try to connect to shared folder automatically on Windows.
On each loop of run_service(), spawn a thread, that waits for 5 seconds.
If read_thread() returns, it means, that sharing is not yet connected,
and the map_drive thread is cancelled, and joined back to main thread.
If the map_drive thread is NOT cancelled, it enumerates free drive
letters, and maps shared folder to highest possible (from Z: to A:).
If all drive letters are already assigned, stop the service.
---
Changes since RFC:
- Calling WNetAddConnection2() blindly was slow and caause many threads to spawn.
- Now only call it once, when it is sure, that it will connect.
- Now connects to a * drive, instead of always Z:
- Thread is now spawned and joined every time run_service() is called.
---
Makefile.am | 4 +++
spice/spice-webdavd.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 80 insertions(+)
diff --git a/Makefile.am b/Makefile.am
index 485417b..df9a73e 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..3940f1c 100644
--- a/spice/spice-webdavd.c
+++ b/spice/spice-webdavd.c
@@ -737,11 +737,81 @@ open_mux_path (const char *path)
mux_queue = output_queue_new (G_OUTPUT_STREAM (mux_ostream));
}
+#ifdef G_OS_WIN32
+static gchar
+get_free_drive_letter(void)
+{
+ const guint32 max_mask = 1 << 25;
+ guint32 drives;
+ guint32 mask;
+ gint i;
+
+ drives = GetLogicalDrives ();
+
+ for (i = 0; i < 26; i++)
+ {
+ mask = max_mask >> i;
+ if ((drives & mask) == 0)
+ return 'Z' - i;
+ }
+
+ return 0;
+}
+
+static gpointer
+map_drive(gpointer user_data)
+{
+ GCancellable * cancel_map = user_data;
+ gchar drive_letter;
+ gchar local_name[3];
+ gchar remote_name[] = "http://localhost:9843/";
+ NETRESOURCE net_resource;
+ guint32 retval;
+ gint i;
+
+ for (i = 0; i < 5; ++i)
+ {
+ if (g_cancellable_is_cancelled (cancel_map))
+ return NULL;
+ else
+ g_usleep (G_USEC_PER_SEC);
+ }
+
+ if ((drive_letter = get_free_drive_letter ()) == 0)
+ g_error ("all drive letters already assigned.");
+
+ local_name[0] = drive_letter;
+ local_name[1] = ':';
+ local_name[2] = 0;
+
+ net_resource.dwType = RESOURCETYPE_DISK;
+ net_resource.lpLocalName = local_name;
+ net_resource.lpRemoteName = remote_name;
+ net_resource.lpProvider = NULL;
+
+ retval = WNetAddConnection2 (&net_resource, NULL, NULL, CONNECT_TEMPORARY);
+
+ if (retval == NO_ERROR)
+ g_debug ("map_drive ok");
+ else if (retval == ERROR_ALREADY_ASSIGNED)
+ g_debug ("map_drive already asigned");
+ else
+ g_error ("map_drive error %d", retval);
+
+ return NULL;
+}
+#endif
+
static void
run_service (void)
{
g_debug ("Run service");
+#ifdef G_OS_WIN32
+ GCancellable * cancel_map = g_cancellable_new ();
+ GThread * map_drive_thread = g_thread_new ("map-drive-thread", map_drive, cancel_map);
+#endif
+
g_socket_service_start (socket_service);
cancel = g_cancellable_new ();
@@ -775,6 +845,12 @@ run_service (void)
g_main_loop_run (loop);
g_main_loop_unref (loop);
+#ifdef G_OS_WIN32
+ g_cancellable_cancel (cancel_map);
+ g_thread_join(map_drive_thread);
+ g_print ("map-drive-thread joined\n");
+#endif
+
g_cancellable_cancel (cancel);
g_clear_object (&mux_istream);
--
2.4.3
More information about the Spice-devel
mailing list