Fix crash on async send in OL 2013
authorAndre Heinecke <aheinecke@intevation.de>
Fri, 10 Aug 2018 09:38:01 +0000 (11:38 +0200)
committerAndre Heinecke <aheinecke@intevation.de>
Fri, 10 Aug 2018 09:38:01 +0000 (11:38 +0200)
* src/mail.cpp, src/mail.h (Mail::

src/mail.cpp
src/mail.h
src/mailitem-events.cpp
src/windowmessages.cpp

index 4ee4314..0e8a9d2 100644 (file)
@@ -73,6 +73,7 @@ static Mail *s_last_mail;
 
 Mail::Mail (LPDISPATCH mailitem) :
     m_mailitem(mailitem),
+    m_currentItemRef(nullptr),
     m_processed(false),
     m_needs_wipe(false),
     m_needs_save(false),
@@ -201,6 +202,8 @@ Mail::~Mail()
                  SRCNAME, __func__);
   m_parser = nullptr;
   m_crypter = nullptr;
+
+  releaseCurrentItem();
   gpgrt_lock_unlock (&dtor_lock);
   log_oom_extra ("%s:%s: returning",
                  SRCNAME, __func__);
@@ -3454,3 +3457,33 @@ Mail::installFolderEventHandler_o()
   /* Folder already registered */
   gpgol_release (folder);
 }
+
+void
+Mail::refCurrentItem()
+{
+  if (m_currentItemRef)
+    {
+      gpgol_release (m_currentItemRef);
+    }
+  /* This prevents a crash in Outlook 2013 when sending a mail as it
+   * would unload too early.
+   *
+   * As it didn't crash when the mail was opened in Outlook Spy this
+   * mimics that the mail is inspected somewhere else. */
+  m_currentItemRef = get_oom_object (m_mailitem, "GetInspector.CurrentItem");
+}
+
+void
+Mail::releaseCurrentItem()
+{
+  if (!m_currentItemRef)
+    {
+      return;
+    }
+  log_oom_extra ("%s:%s: releasing CurrentItem ref %p",
+                 SRCNAME, __func__, m_currentItemRef);
+  LPDISPATCH m_tmp = m_currentItemRef;
+  m_currentItemRef = nullptr;
+  /* This can cause our destruction */
+  gpgol_release (m_tmp);
+}
index cc4a78b..ee7fcac 100644 (file)
@@ -591,12 +591,18 @@ public:
   bool isAboutToBeMoved () { return m_is_about_to_be_moved; }
   void setIsAboutToBeMoved (bool value) { m_is_about_to_be_moved = value; }
 
+  /* Releases the current item ref obtained in update oom data */
+  void releaseCurrentItem ();
+  /* Gets an additional reference for GetInspector.CurrentItem */
+  void refCurrentItem ();
+
 private:
   void updateCategories_o ();
   void updateSigstate ();
 
   LPDISPATCH m_mailitem;
   LPDISPATCH m_event_sink;
+  LPDISPATCH m_currentItemRef;
   bool m_processed,    /* The message has been porcessed by us.  */
        m_needs_wipe,   /* We have added plaintext to the mesage. */
        m_needs_save,   /* A property was changed but not by us. */
index f93b239..26cbbdd 100644 (file)
@@ -371,6 +371,16 @@ EVENT_SINK_INVOKE(MailItemEvents)
               log_debug ("%s:%s: Send event for crypto mail %p saving and starting.",
                          SRCNAME, __func__, m_mail);
 
+              if (!m_mail->isAsyncCryptDisabled())
+                {
+                  /* Obtain a reference of the current item. This prevents
+                   * an early unload which would crash Outlook 2013
+                   *
+                   * As it didn't crash when the mail was opened in Outlook Spy this
+                   * mimics that the mail is inspected somewhere else. */
+                  m_mail->refCurrentItem ();
+                }
+
               // First contact with a mail to encrypt update
               // state and oom data.
               m_mail->updateOOMData_o ();
index bf252a0..afb8197 100644 (file)
@@ -162,6 +162,7 @@ gpgol_window_proc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
               invoke_oom_method (mail->item (), "Send", NULL);
               log_debug ("%s:%s:  Send for %p completed.",
                          SRCNAME, __func__, mail);
+              mail->releaseCurrentItem();
               break;
             }
           case (BRING_TO_FRONT):