Fix crash due to the gpgme backend.
authorWerner Koch <wk@gnupg.org>
Wed, 26 Mar 2008 16:14:14 +0000 (16:14 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 26 Mar 2008 16:14:14 +0000 (16:14 +0000)
Fallback to GPA if Kleopatra is not installed.

src/ChangeLog
src/engine-assuan.c
src/engine-gpgme.c

index afaae63..2de1cf5 100644 (file)
@@ -1,3 +1,11 @@
+2008-03-26  Werner Koch  <wk@g10code.com>
+
+       * engine-gpgme.c (cleanup): Implement.
+       (op_gpgme_init): Save thread handle.
+       (waiter_thread): Check shutdown flags.
+
+       * engine-assuan.c (get_uiserver_name): Fallback to GPA.
+
 2008-03-19  Werner Koch  <wk@g10code.com>
 
        * mapihelp.cpp (mapi_change_message_class): Look into
index 17b05fc..6e9a36b 100644 (file)
@@ -324,6 +324,7 @@ get_uiserver_name (void)
 {
   char *name = NULL;
   char *dir, *uiserver, *p;
+  int extra_arglen = 0;
 
   dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", GNUPG_REGKEY,
                                   "Install Directory");
@@ -332,15 +333,43 @@ get_uiserver_name (void)
       uiserver = read_w32_registry_string (NULL, GNUPG_REGKEY, 
                                            "UI Server");
       if (!uiserver)
-        uiserver = xstrdup ("kleopatra.exe --daemon");
+        {
+          uiserver = xstrdup ("kleopatra.exe");
+          extra_arglen = 9; /* Space required for " --daemon".  */
+        }
 
-      name = xmalloc (strlen (dir) + strlen (uiserver) + 2);
+      name = xmalloc (strlen (dir) + strlen (uiserver) + extra_arglen + 2);
       strcpy (stpcpy (stpcpy (name, dir), "\\"), uiserver);
       for (p = name; *p; p++)
         if (*p == '/')
           *p = '\\';
       xfree (uiserver);
+      if (extra_arglen && access (name, F_OK))
+        {
+          /* Kleopatra iis not nstalled: Try GPA instead but if it is
+             also not available still return the Kleopatra
+             filename.  */
+          const char gpaserver[] = "gpa.exe";
+          char *name2;
+          
+          name2 = xmalloc (strlen (dir) + strlen (gpaserver) + extra_arglen+2);
+          strcpy (stpcpy (stpcpy (name2, dir), "\\"), gpaserver);
+          for (p = name2; *p; p++)
+            if (*p == '/')
+              *p = '\\';
+          if (access (name2, F_OK ))
+            xfree (name2);
+          else
+            {
+              xfree (name);
+              name = name2;
+            }
+        }
       xfree (dir);
+
+      /* Append the arg for Kleopatra.  */
+      if (name && extra_arglen)
+        strcat (name, " --daemon");
     }
   
   return name;
index 11614a9..5b0e6ee 100644 (file)
@@ -1,5 +1,5 @@
 /* engine-gpgme.c - Crypto engine with GPGME
- *     Copyright (C) 2005, 2006, 2007 g10 Code GmbH
+ *     Copyright (C) 2005, 2006, 2007, 2008 g10 Code GmbH
  *
  * This file is part of GpgOL.
  *
@@ -59,10 +59,11 @@ struct closure_data_s
 
 static int basic_init_done = 0;
 static int init_done = 0;
-
+static int shutdown_gpgme = 0;
 
 static DWORD WINAPI waiter_thread (void *dummy);
 static CRITICAL_SECTION waiter_thread_lock;
+static HANDLE waiter_thread_handle = INVALID_HANDLE_VALUE;
 static void update_passphrase_cache (int err, 
                                      struct passphrase_cb_s *pass_cb_value);
 /* static void add_verify_attestation (gpgme_data_t at,  */
@@ -75,7 +76,17 @@ static void update_passphrase_cache (int err,
 static void
 cleanup (void)
 {
-  /* Fixme: We should stop the thread.  */
+  if (init_done && waiter_thread_handle != INVALID_HANDLE_VALUE )
+    {
+      DWORD ec;
+
+      EnterCriticalSection (&waiter_thread_lock);
+      shutdown_gpgme = 1;
+      LeaveCriticalSection (&waiter_thread_lock);
+      while ( GetExitCodeThread (waiter_thread_handle, &ec) )
+        Sleep (100);
+      waiter_thread_handle = INVALID_HANDLE_VALUE;
+    }
 }
 
 
@@ -139,12 +150,13 @@ op_gpgme_init (void)
     HANDLE th;
     DWORD tid;
 
+    waiter_thread_handle = INVALID_HANDLE_VALUE;
     InitializeCriticalSection (&waiter_thread_lock);
     th = CreateThread (NULL, 128*1024, waiter_thread, NULL, 0, &tid);
     if (th == INVALID_HANDLE_VALUE)
       log_error ("failed to start the gpgme waiter thread\n");
     else
-      CloseHandle (th);
+      waiter_thread_handle = th;
   }
 
   init_done = 1;
@@ -163,7 +175,7 @@ waiter_thread (void *dummy)
 
   (void)dummy;
 
-  for (;;)
+  while (!shutdown_gpgme)
     {
       /*  Note: We don't use hang because this will end up in a tight
           loop and does not do a voluntary context switch.  Thus we do
@@ -189,6 +201,8 @@ waiter_thread (void *dummy)
       else
         Sleep (50);
     }
+  ExitThread (0);
+  return 0;
 }