Fix a possible crash when reactivating gpgol
authorAndre Heinecke <aheinecke@intevation.de>
Fri, 7 Sep 2018 07:56:35 +0000 (09:56 +0200)
committerAndre Heinecke <aheinecke@intevation.de>
Wed, 12 Sep 2018 07:01:00 +0000 (09:01 +0200)
* src/gpgoladdin.cpp (GpgolAddin::invalidateRibbons)
(GpgolAddin::addRibbon): New.
(g_ribbon_uis): Removed.

--
This keeps the ribbon ui in a member variable so that they
are cleared out when the GpgolAddin class is remvoved on
unload.

Fixes a potential crash when a user would activate gpgol
after deactivating it in the same outlook session and
stale ribbon ui pointers would be accessed.

(cherry picked from commit 50c514d6bd6026076f5f467b7d8523dff2ce97aa)

src/gpgoladdin.cpp
src/gpgoladdin.h

index e331b86..03baf95 100644 (file)
@@ -63,8 +63,6 @@ ULONG addinLocks = 0;
 
 bool can_unload = false;
 
-static std::list<LPDISPATCH> g_ribbon_uis;
-
 static GpgolAddin * addin_instance = NULL;
 
 /* This is the main entry point for the addin
@@ -791,7 +789,7 @@ GpgolRibbonExtender::Invoke (DISPID dispid, REFIID riid, LCID lcid,
 
       case ID_ON_LOAD:
           {
-            g_ribbon_uis.push_back (parms->rgvarg[0].pdispVal);
+            GpgolAddin::get_instance ()->addRibbon (parms->rgvarg[0].pdispVal);
             return S_OK;
           }
       case ID_CMD_OPEN_OPTIONS:
@@ -1102,16 +1100,10 @@ GpgolRibbonExtender::GetCustomUI (BSTR RibbonID, BSTR * RibbonXml)
    Updated. Sadly we don't know which ribbon_ui needs updates
    so we have to invalidate everything.
 */
-void gpgoladdin_invalidate_ui ()
+void
+gpgoladdin_invalidate_ui ()
 {
-  std::list<LPDISPATCH>::iterator it;
-
-  for (it = g_ribbon_uis.begin(); it != g_ribbon_uis.end(); ++it)
-    {
-      log_debug ("%s:%s: Invalidating ribbon: %p",
-                 SRCNAME, __func__, *it);
-      invoke_oom_method (*it, "Invalidate", NULL);
-    }
+  GpgolAddin::get_instance ()->invalidateRibbons();
 }
 
 GpgolAddin *
@@ -1130,6 +1122,27 @@ GpgolAddin::get_instance ()
 }
 
 void
+GpgolAddin::invalidateRibbons()
+{
+  /* This can only be done in the main thread so no
+     need for locking or copying here. */
+  for (const auto it: m_ribbon_uis)
+    {
+      log_debug ("%s:%s: Invalidating ribbon: %p",
+                 SRCNAME, __func__, it);
+      invoke_oom_method (it, "Invalidate", NULL);
+    }
+  log_debug ("%s:%s: Invalidation done.",
+             SRCNAME, __func__);
+}
+
+void
+GpgolAddin::addRibbon (LPDISPATCH disp)
+{
+  m_ribbon_uis.push_back (disp);
+}
+
+void
 GpgolAddin::shutdown ()
 {
   if (m_shutdown)
index 1641942..3627a01 100644 (file)
@@ -217,6 +217,12 @@ public:
   std::shared_ptr<DispCache> get_dispcache () { return m_dispcache; }
   bool isShutdown() { return m_shutdown; };
 
+  /* Register a ribbon ui component */
+  void addRibbon (LPDISPATCH ribbon);
+
+  /* Invalidate the ribbons. */
+  void invalidateRibbons ();
+
 private:
   ULONG m_lRef;
   GpgolRibbonExtender* m_ribbonExtender;
@@ -231,6 +237,7 @@ private:
   HHOOK m_hook;
   std::vector<LPDISPATCH> m_explorerEventSinks;
   std::shared_ptr<DispCache> m_dispcache;
+  std::vector<LPDISPATCH> m_ribbon_uis;
 };
 
 class GpgolAddinFactory: public IClassFactory