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 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel