[git] GpgOL - branch, mime-addin, updated. gpgol-1.2.0-32-g3674e18

by Andre Heinecke cvs at cvs.gnupg.org
Thu Sep 24 18:50:28 CEST 2015


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GnuPG extension for MS Outlook".

The branch, mime-addin has been updated
       via  3674e1868412eb48576267a01cab522ffd327f4c (commit)
       via  094b038883f8e03645ca88f21780205f026c7aa0 (commit)
       via  d2e45d9a24787e04e17bde0ce9c8aba0d3104bfa (commit)
       via  1e170dea1f8c918f7cc0e48a264785086c2e41ea (commit)
      from  312f71f0904b8642674ffd2b1af5d39f82a5f03d (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 3674e1868412eb48576267a01cab522ffd327f4c
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Thu Sep 24 18:37:51 2015 +0200

    Do not send an item with encryption errors
    
    * mailitem-events.cpp (MailItemEvents::Invoke): Handle crypto errors.
      (request_send): New. Sleep for 50ms and then request a send.
      (sign_encrypt_item): Renamed from handle_after_write. Remove
      not working context window lookup. Return errors.
      (handle_before_read): Remove context window lookup.
    
    --
    The first send event is not canceled. We then encrypt / sign
    the message in the AfterWrite event and then use Windowmessages
    to request a Send again in the main thread. We need to yield
    to the main thread for a bit so that it can do some stuff that
    allows us to trigger Send again. Otherwise we will get an error
    that calling Send is not allowed in this context.

diff --git a/src/mailitem-events.cpp b/src/mailitem-events.cpp
index f73391c..bf364f1 100644
--- a/src/mailitem-events.cpp
+++ b/src/mailitem-events.cpp
@@ -26,6 +26,8 @@
 #include "ocidl.h"
 #include "attachment.h"
 #include "mapihelp.h"
+#include "gpgoladdin.h"
+#include "windowmessages.h"
 
 /* TODO Add a proper / l10n encrypted thing message. */
 static const char * ENCRYPTED_MESSAGE_BODY = \
@@ -71,11 +73,11 @@ private:
        m_want_html,    /* Encryption of HTML is desired. */
        m_processed,    /* The message has been porcessed by us.  */
        m_needs_wipe,   /* We have added plaintext to the mesage. */
-       m_was_encrypted; /* The original message was encrypted.  */
+       m_was_encrypted, /* The original message was encrypted.  */
+       m_crypt_successful; /* We successfuly performed crypto on the item. */
 
   HRESULT handle_before_read();
   HRESULT handle_read();
-  HRESULT handle_after_write();
 };
 
 MailItemEvents::MailItemEvents() :
@@ -85,7 +87,8 @@ MailItemEvents::MailItemEvents() :
     m_ref(1),
     m_send_seen(false),
     m_want_html(false),
-    m_processed(false)
+    m_processed(false),
+    m_crypt_successful(false)
 {
 }
 
@@ -151,7 +154,7 @@ MailItemEvents::handle_before_read()
     }
   log_oom_extra ("%s:%s: GetBaseMessage OK.",
                  SRCNAME, __func__);
-  err = message_incoming_handler (message, get_oom_context_window (m_object),
+  err = message_incoming_handler (message, NULL,
                                   false);
   m_processed = (err == 1) || (err == 2);
   m_was_encrypted = err == 2;
@@ -163,33 +166,51 @@ MailItemEvents::handle_before_read()
 }
 
 
-HRESULT
-MailItemEvents::handle_after_write()
+static int
+sign_encrypt_item (LPDISPATCH mailitem)
 {
-  int err;
-  LPMESSAGE message = get_oom_base_message (m_object);
+  int err = -1;
+  LPMESSAGE message = get_oom_base_message (mailitem);
   if (!message)
     {
       log_error ("%s:%s: Failed to get base message.",
                  SRCNAME, __func__);
-      return S_OK;
+      return err;
     }
   log_debug ("%s:%s: Sign / Encrypting message",
              SRCNAME, __func__);
   /* TODO check for message flags to determine */
   err = message_sign_encrypt (message, PROTOCOL_UNKNOWN,
-                              get_oom_context_window (m_object));
+                              NULL);
   log_debug ("%s:%s: Sign / Encryption status: %i",
              SRCNAME, __func__, err);
   message->Release ();
-  if (err)
+  return err;
+}
+
+
+DWORD WINAPI
+request_send (LPVOID arg)
+{
+  int not_sent = 1;
+  int tries = 0;
+  do
+    {
+      /* Outlook needs to handle the message some more to unblock
+         calls to Send. Lets give it 50ms before we send it again. */
+      Sleep (50);
+      log_debug ("%s:%s: requesting send for: %p",
+                 SRCNAME, __func__, arg);
+      not_sent = do_in_ui_thread (REQUEST_SEND_MAIL, arg);
+      tries++;
+    } while (not_sent && tries < 50);
+  if (tries == 50)
     {
-      // TODO: I think we can still cancel the send
-      // on the MAPI level in case of errors
-      // but we have to get at the messagestore to
-      // do that.
+      // Hum should not happen but I rather avoid
+      // an endless loop in that case.
+      // TODO show error message.
     }
-  return S_OK;
+  return 0;
 }
 
 /* The main Invoke function. The return value of this
@@ -220,16 +241,41 @@ EVENT_SINK_INVOKE(MailItemEvents)
         }
       case Send:
         {
-          m_send_seen = true;
-          return S_OK;
-        }
-      case AfterWrite:
-        {
-          if (m_send_seen)
+          /* This is the only event where we can cancel the send of an
+             mailitem. But it is too early for us to encrypt as the MAPI
+             structures are not yet filled (and we don't seem to have a way
+             to trigger this and it is likely to be impossible)
+
+             So the first send event is canceled but we save that we have
+             seen it in m_send_seen. We then trigger a Save of that item.
+             The Save causes the Item to be written and we have a chance
+             to Encrypt it in the AfterWrite event.
+
+             If this encryption is successful and we see a send again
+             we let it pass as then the encrypted data is sent.
+
+             The value of m_send_seen is set to false in this case as
+             we consumed the original send that we canceled. */
+          if (parms->cArgs != 1 || parms->rgvarg[0].vt != (VT_BOOL | VT_BYREF))
+           {
+             log_debug ("%s:%s: Uncancellable send event.",
+                        SRCNAME, __func__);
+             break;
+           }
+          if (m_crypt_successful)
             {
-              m_send_seen = false;
-              return handle_after_write();
+               log_debug ("%s:%s: Message %p sucessfully encrypted. May go.",
+                          SRCNAME, __func__, m_object);
+               m_send_seen = false;
+               break;
             }
+          m_send_seen = true;
+          log_debug ("%s:%s: Message %p cancelling send to let us do crypto.",
+                     SRCNAME, __func__, m_object);
+          *(parms->rgvarg[0].pboolVal) = VARIANT_TRUE;
+          invoke_oom_method (m_object, "Save", NULL);
+
+          return S_OK;
         }
       case Write:
         {
@@ -264,6 +310,26 @@ EVENT_SINK_INVOKE(MailItemEvents)
                 }
               m_needs_wipe = false;
             }
+          break;
+        }
+      case AfterWrite:
+        {
+          if (m_send_seen)
+            {
+              m_send_seen = false;
+              m_crypt_successful = !sign_encrypt_item (m_object);
+              if (m_crypt_successful)
+                {
+                  /* We can't trigger a Send event in the current state.
+                     Appearently Outlook locks some methods in some events.
+                     So we Create a new thread that will sleep a bit before
+                     it requests to send the item again. */
+                  CreateThread (NULL, 0, request_send, (LPVOID) m_object, 0,
+                                NULL);
+                }
+              return S_OK;
+            }
+          break;
         }
       default:
         log_oom_extra ("%s:%s: Message:%p Unhandled Event: %lx \n",

commit 094b038883f8e03645ca88f21780205f026c7aa0
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Thu Sep 24 18:33:12 2015 +0200

    Add window message helper code.
    
    * Makefile.am: Add sources.
    * gpgoladdin.cpp (OnStartupComplete): Initialize responder.
    * windowmessages.cpp, windowmessages.h: New.
    
    --
    See windowmessages.h for a detailed description.

diff --git a/src/Makefile.am b/src/Makefile.am
index 71246a3..93312cd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -90,7 +90,8 @@ gpgol_SOURCES = \
 	filetype.c filetype.h \
 	eventsinks.h application-events.cpp \
 	mailitem-events.cpp \
-	attachment.h attachment.cpp
+	attachment.h attachment.cpp \
+	windowmessages.h windowmessages.cpp
 
 
 #treeview_SOURCES = treeview.c
diff --git a/src/gpgoladdin.cpp b/src/gpgoladdin.cpp
index 7323674..72b2f60 100644
--- a/src/gpgoladdin.cpp
+++ b/src/gpgoladdin.cpp
@@ -46,6 +46,7 @@
 #include "gpgol-ids.h"
 #include "ribbon-callbacks.h"
 #include "eventsinks.h"
+#include "windowmessages.h"
 
 #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \
                                      SRCNAME, __func__, __LINE__); \
@@ -276,6 +277,12 @@ GpgolAddin::OnStartupComplete (SAFEARRAY** custom)
   (void)custom;
   TRACEPOINT();
 
+  if (!create_responder_window())
+    {
+      log_error ("%s:%s: Failed to create the responder window;",
+                 SRCNAME, __func__);
+    }
+
   if (m_application)
     {
       m_applicationEventSink = install_ApplicationEvents_sink(m_application);
diff --git a/src/windowmessages.cpp b/src/windowmessages.cpp
new file mode 100644
index 0000000..ce1afa5
--- /dev/null
+++ b/src/windowmessages.cpp
@@ -0,0 +1,110 @@
+#include "windowmessages.h"
+
+#include "util.h"
+#include "oomhelp.h"
+
+#include <stdio.h>
+
+#define RESPONDER_CLASS_NAME "GpgOLResponder"
+
+/* Singleton window */
+static HWND g_responder_window = NULL;
+
+static int
+request_send_mail (LPDISPATCH mailitem)
+{
+  if (invoke_oom_method (mailitem, "Send", NULL))
+    {
+      log_debug ("%s:%s: Failed to resend message.",
+                 SRCNAME, __func__);
+      return -1;
+    }
+  log_debug ("%s:%s: Message %p sent.",
+             SRCNAME, __func__, mailitem);
+  return 0;
+}
+
+LONG_PTR WINAPI
+gpgol_window_proc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  if (message == WM_USER + 1)
+    {
+      wm_ctx_t *ctx = (wm_ctx_t *) lParam;
+      log_debug ("%s:%s: Recieved user msg: %i",
+                 SRCNAME, __func__, ctx->wmsg_type);
+      switch (ctx->wmsg_type)
+        {
+          case (REQUEST_SEND_MAIL):
+            {
+              ctx->err = request_send_mail ((LPDISPATCH) ctx->data);
+              break;
+            }
+          default:
+            log_debug ("Unknown msg");
+        }
+        return 0;
+    }
+
+  return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+HWND
+create_responder_window ()
+{
+  size_t cls_name_len = strlen(RESPONDER_CLASS_NAME) + 1;
+  char cls_name[cls_name_len];
+  if (g_responder_window)
+    {
+      return g_responder_window;
+    }
+  /* Create Window wants a mutable string as the first parameter */
+  snprintf (cls_name, cls_name_len, "%s", RESPONDER_CLASS_NAME);
+
+  WNDCLASS windowClass;
+  windowClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
+  windowClass.lpfnWndProc = gpgol_window_proc;
+  windowClass.cbClsExtra = 0;
+  windowClass.cbWndExtra = 0;
+  windowClass.hInstance = (HINSTANCE) GetModuleHandle(NULL);
+  windowClass.hIcon = 0;
+  windowClass.hCursor = 0;
+  windowClass.hbrBackground = 0;
+  windowClass.lpszMenuName  = 0;
+  windowClass.lpszClassName = cls_name;
+  RegisterClass(&windowClass);
+  g_responder_window = CreateWindow (cls_name, RESPONDER_CLASS_NAME, 0, 0, 0,
+                                     0, 0, 0, (HMENU) 0,
+                                     (HINSTANCE) GetModuleHandle(NULL), 0);
+  return g_responder_window;
+}
+
+int
+send_msg_to_ui_thread (wm_ctx_t *ctx)
+{
+  size_t cls_name_len = strlen(RESPONDER_CLASS_NAME) + 1;
+  char cls_name[cls_name_len];
+  snprintf (cls_name, cls_name_len, "%s", RESPONDER_CLASS_NAME);
+
+  HWND responder = FindWindow (cls_name, RESPONDER_CLASS_NAME);
+  if (!responder)
+  {
+    log_error ("%s:%s: Failed to find responder window.",
+               SRCNAME, __func__);
+    return -1;
+  }
+  SendMessage (responder, WM_USER + 1, 0, (LPARAM) ctx);
+  return 0;
+}
+
+int
+do_in_ui_thread (gpgol_wmsg_type type, void *data)
+{
+  wm_ctx_t ctx = {0};
+  ctx.wmsg_type = type;
+  ctx.data = data;
+  if (send_msg_to_ui_thread (&ctx))
+    {
+      return -1;
+    }
+  return ctx.err;
+}
diff --git a/src/windowmessages.h b/src/windowmessages.h
new file mode 100644
index 0000000..c9355d5
--- /dev/null
+++ b/src/windowmessages.h
@@ -0,0 +1,66 @@
+/* windowmessages.h - Helper functions for Window message exchange.
+ *    Copyright (C) 2015 Intevation GmbH
+ *
+ * This file is part of GpgOL.
+ *
+ * GpgOL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GpgOL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef WINDOWMESSAGES_H
+#define WINDOWMESSAGES_H
+
+#include <windows.h>
+
+/** Window Message handling for GpgOL.
+  In Outlook only one thread has access to the Outlook Object model
+  and this is the UI Thread. We can work in other threads but
+  to do something with outlooks data we neet to be in the UI Thread.
+  So we create a hidden Window in this thread and use the fact
+  that SendMessage handles Window messages in the thread where the
+  Window was created.
+  This way we can go back to interactct with the Outlook from another
+  thread without working with COM Multithreading / Marshaling.
+
+  The Responder Window should be initalized on startup.
+  */
+
+
+typedef enum _gpgol_wmsg_type
+{
+  UNKNOWN = 0,
+  REQUEST_SEND_MAIL = 1 /* Request to send a mail.
+                           Data should be LPMAILITEM */
+} gpgol_wmsg_type;
+
+typedef struct
+{
+  void *data; /* Pointer to arbitrary data depending on msg type */
+  gpgol_wmsg_type wmsg_type; /* Type of the msg. */
+  int err; /* Set to true on error */
+} wm_ctx_t;
+
+/** Create and register the responder window.
+  The responder window should be */
+HWND
+create_responder_window ();
+
+/** Send a message to the UI thread through the responder Window.
+  Returns 0 on success. */
+int
+send_msg_to_ui_thread (wm_ctx_t *ctx);
+
+/** Uses send_msg_to_ui_thread to execute the request
+  in the ui thread.  Returns the result. */
+int
+do_in_ui_thread (gpgol_wmsg_type type, void *data);
+#endif // WINDOWMESSAGES_H

commit d2e45d9a24787e04e17bde0ce9c8aba0d3104bfa
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Thu Sep 24 18:20:39 2015 +0200

    Show exceptions in invoke_oom_method.
    
    * src/oomhelp.cpp (dump_excepinfo): Clean up dump style.
      (invoke_oom_method): Add exception handling for better debugging.

diff --git a/src/oomhelp.cpp b/src/oomhelp.cpp
index d3f284d..a920b51 100644
--- a/src/oomhelp.cpp
+++ b/src/oomhelp.cpp
@@ -109,7 +109,7 @@ lookup_oom_dispid (LPDISPATCH pDisp, const char *name)
 void
 dump_excepinfo (EXCEPINFO err)
 {
-  log_debug ("%s:%s: Dumping exception: \n"
+  log_debug ("%s:%s: Exception: \n"
              "              wCode: 0x%x\n"
              "              wReserved: 0x%x\n"
              "              source: %S\n"
@@ -117,8 +117,7 @@ dump_excepinfo (EXCEPINFO err)
              "              help: %S\n"
              "              helpCtx: 0x%x\n"
              "              deferredFill: 0x%x\n"
-             "              scode: 0x%x\n"
-             "%s:%s: Dump done." ,
+             "              scode: 0x%x\n",
              SRCNAME, __func__, (unsigned int) err.wCode,
              (unsigned int) err.wReserved,
              err.bstrSource, err.bstrDescription, err.bstrHelpFile,
@@ -1078,15 +1077,17 @@ invoke_oom_method (LPDISPATCH pDisp, const char *name, VARIANT *rVariant)
   dispid = lookup_oom_dispid (pDisp, name);
   if (dispid != DISPID_UNKNOWN)
     {
+      EXCEPINFO execpinfo;
       DISPPARAMS dispparams = {NULL, NULL, 0, 0};
 
       hr = pDisp->Invoke (dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
                           DISPATCH_METHOD, &dispparams,
-                          rVariant, NULL, NULL);
+                          rVariant, &execpinfo, NULL);
       if (hr != S_OK)
         {
           log_debug ("%s:%s: Method '%s' invokation failed: %#lx",
                      SRCNAME, __func__, name, hr);
+          dump_excepinfo (execpinfo);
           return false;
         }
     }

commit 1e170dea1f8c918f7cc0e48a264785086c2e41ea
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Mon Sep 21 16:35:27 2015 +0200

    Add short text to processed messages.
    
    * src/mailitem-events.cpp (MailItemEvents::Invoke): Add info text
    instead of setting the message body to an empty string.
    
    --
    This could be improved using HTML to look something like KMail's
    "This message is encrypted" Box. Telling you to activate GpgOL.

diff --git a/src/mailitem-events.cpp b/src/mailitem-events.cpp
index 34ac116..f73391c 100644
--- a/src/mailitem-events.cpp
+++ b/src/mailitem-events.cpp
@@ -27,6 +27,10 @@
 #include "attachment.h"
 #include "mapihelp.h"
 
+/* TODO Add a proper / l10n encrypted thing message. */
+static const char * ENCRYPTED_MESSAGE_BODY = \
+"This message is encrypted. Please install or activate GpgOL"\
+" to decrypt this message.";
 
 typedef enum
   {
@@ -245,8 +249,9 @@ EVENT_SINK_INVOKE(MailItemEvents)
             {
               log_debug ("%s:%s: Message %p removing plaintext from Message.",
                          SRCNAME, __func__, m_object);
-              if (put_oom_string (m_object, "HTMLBody", "") ||
-                  put_oom_string (m_object, "Body", "") ||
+              if (put_oom_string (m_object, "HTMLBody",
+                                  ENCRYPTED_MESSAGE_BODY) ||
+                  put_oom_string (m_object, "Body", ENCRYPTED_MESSAGE_BODY) ||
                   protect_attachments (m_object))
                 {
                   /* An error cleaning the mail should not happen normally.

-----------------------------------------------------------------------

Summary of changes:
 src/Makefile.am         |   3 +-
 src/gpgoladdin.cpp      |   7 +++
 src/mailitem-events.cpp | 123 ++++++++++++++++++++++++++++++++++++++----------
 src/oomhelp.cpp         |   9 ++--
 src/windowmessages.cpp  | 110 +++++++++++++++++++++++++++++++++++++++++++
 src/windowmessages.h    |  66 ++++++++++++++++++++++++++
 6 files changed, 287 insertions(+), 31 deletions(-)
 create mode 100644 src/windowmessages.cpp
 create mode 100644 src/windowmessages.h


hooks/post-receive
-- 
GnuPG extension for MS Outlook
http://git.gnupg.org




More information about the Gnupg-commits mailing list