From: Lukas Venhoda <lvenh...@redhat.com>

When stopping the service, automatically disconnect shared folder on
windows. Not dismounting could lead to multiple shared folders.
---
Fixup:
 - Added GMutex init and clear
 - Inititalize service_data
 - Only unmap when drive_letter != 0

Changes since v6:
 - Changed gchar* to ServiceData*
 - Added mutex for ServiceData multithread handeling
 - Moved ServiceData from windows service only to all OS
    - ServiceData is currently empty on Linux
    - Can be used in the future
 - Added correct unmapping for --no-service

Changes since v5:
 - fixed indentation
 - fixed * indentaion
 - removed return from void functions
 - changed ServiceData * to gpointer, so that it compiles on linux

Changes since v4:
 - Dont lookup drive letter when unmapping
    - Uses a service_data structure and map_drive_data structure to store
      the drive_letter for later use while unmapping
 - Better debug messages

Changes since v3:
 - Better handeling of string names
 - Syntax cleanup
 - Remove global variable drive_letter
    - Now scans for mapped drive and unmaps it

Changes since v2:
 - None

Changes since v1:
 - New patch
---
 spice/spice-webdavd.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 77 insertions(+), 4 deletions(-)

diff --git a/spice/spice-webdavd.c b/spice/spice-webdavd.c
index 216d895..077a1b3 100644
--- a/spice/spice-webdavd.c
+++ b/spice/spice-webdavd.c
@@ -57,6 +57,14 @@ typedef struct _OutputQueueElem
   gpointer      user_data;
 } OutputQueueElem;

+typedef struct _ServiceData
+{
+#ifdef G_OS_WIN32
+  gchar drive_letter;
+  GMutex mutex;
+#endif
+} ServiceData;
+
 static GCancellable *cancel;

 static OutputQueue*
@@ -749,6 +757,7 @@ typedef enum _MapDriveEnum

 typedef struct _MapDriveData
 {
+  ServiceData *service_data;
   GCancellable *cancel_map;
 } MapDriveData;

@@ -855,6 +864,31 @@ map_drive(const gchar drive_letter)
 }

 static void
+unmap_drive(const gchar drive_letter)
+{
+  gchar local_name[MAX_DRIVE_LETTER_SIZE];
+  guint32 errn;
+
+  g_snprintf(local_name, MAX_DRIVE_LETTER_SIZE, "%c:", drive_letter);
+  errn = WNetCancelConnection2(local_name, CONNECT_UPDATE_PROFILE, TRUE);
+
+  if (errn == NO_ERROR)
+    {
+      g_debug ("Shared folder unmapped succesfully");
+    }
+  else if (errn == ERROR_NOT_CONNECTED)
+    {
+      g_debug ("Drive %c is not connected", drive_letter);
+    }
+  else
+    {
+      g_warning ("map_drive error %d", errn);
+    }
+
+  return;
+}
+
+static void
 map_drive_cb(GTask *task,
              gpointer source_object,
              gpointer task_data,
@@ -896,11 +930,16 @@ map_drive_cb(GTask *task,
       //TODO: After mapping, rename network drive from 
\\localhost@PORT\DavWWWRoot
       //      to something like SPICE Shared Folder
     }
+
+  g_mutex_lock(&map_drive_data->service_data->mutex);
+  map_drive_data->service_data->drive_letter = drive_letter;
+  g_mutex_unlock(&map_drive_data->service_data->mutex);
 }
+
 #endif

 static void
-run_service (void)
+run_service (ServiceData *service_data)
 {
   g_debug ("Run service");

@@ -909,6 +948,11 @@ run_service (void)
   map_drive_data.cancel_map = g_cancellable_new ();
   gchar drive_letter = get_spice_folder_letter ();

+  g_mutex_lock(&service_data->mutex);
+  service_data->drive_letter = drive_letter;
+  map_drive_data.service_data = service_data;
+  g_mutex_unlock(&service_data->mutex);
+
   if (drive_letter == 0)
     {
       GTask *map_drive_task = g_task_new (NULL, NULL, NULL, NULL);
@@ -990,10 +1034,19 @@ service_ctrl_handler (DWORD ctrl, DWORD type, LPVOID 
data, LPVOID ctx)
 {
   DWORD ret = NO_ERROR;

+  ServiceData *service_data = ctx;
+
   switch (ctrl)
     {
     case SERVICE_CONTROL_STOP:
     case SERVICE_CONTROL_SHUTDOWN:
+        if (service_data->drive_letter != 0)
+          {
+            g_mutex_lock(&service_data->mutex);
+            unmap_drive (service_data->drive_letter);
+            g_mutex_unlock(&service_data->mutex);
+            g_mutex_clear(&service_data->mutex);
+          }
         quit (SIGTERM);
         service_status.dwCurrentState = SERVICE_STOP_PENDING;
         SetServiceStatus (service_status_handle, &service_status);
@@ -1009,8 +1062,13 @@ service_ctrl_handler (DWORD ctrl, DWORD type, LPVOID 
data, LPVOID ctx)
 VOID WINAPI
 service_main (DWORD argc, TCHAR *argv[])
 {
+  ServiceData service_data;
+
+  service_data.drive_letter = 0;
+  g_mutex_init(&service_data.mutex);
+
   service_status_handle =
-    RegisterServiceCtrlHandlerEx ("spice-webdavd", service_ctrl_handler, NULL);
+    RegisterServiceCtrlHandlerEx ("spice-webdavd", service_ctrl_handler, 
&service_data);

   g_return_if_fail (service_status_handle != 0);

@@ -1024,7 +1082,7 @@ service_main (DWORD argc, TCHAR *argv[])
   SetServiceStatus (service_status_handle, &service_status);

   while (!quit_service) {
-      run_service ();
+      run_service (&service_data);
       g_usleep (G_USEC_PER_SEC);
   }

@@ -1048,6 +1106,7 @@ static GOptionEntry entries[] = {
 int
 main (int argc, char *argv[])
 {
+  ServiceData service_data;
   GOptionContext *opts;
   GError *error = NULL;

@@ -1095,6 +1154,10 @@ main (int argc, char *argv[])
                     "incoming", G_CALLBACK (incoming_callback),
                     NULL);

+
+  service_data.drive_letter = 0;
+  g_mutex_init(&service_data.mutex);
+
 #ifdef G_OS_WIN32
   SERVICE_TABLE_ENTRY service_table[] =
     {
@@ -1110,10 +1173,20 @@ main (int argc, char *argv[])
     } else
 #endif
   while (!quit_service) {
-    run_service ();
+    run_service (&service_data);
     g_usleep (G_USEC_PER_SEC);
   }

+#ifdef G_OS_WIN32
+  if (service_data.drive_letter != 0)
+    {
+      g_mutex_lock(&service_data.mutex);
+      unmap_drive (service_data.drive_letter);
+      g_mutex_unlock(&service_data.mutex);
+      g_mutex_clear(&service_data.mutex);
+    }
+#endif
+
   g_clear_object (&socket_service);

   return 0;
--
2.5.5

_______________________________________________
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Reply via email to