A bunch of changes to support better looking icons.
authorWerner Koch <wk@gnupg.org>
Wed, 28 Oct 2009 19:26:06 +0000 (19:26 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 28 Oct 2009 19:26:06 +0000 (19:26 +0000)
CLeaned up some code and introduced a lot of code to support the OOM.

43 files changed:
ChangeLog
NEWS
configure.ac
po/de.po
po/sv.po
src/ChangeLog
src/Makefile.am
src/cmdbarcontrols.cpp [new file with mode: 0644]
src/cmdbarcontrols.h [new file with mode: 0644]
src/common.c
src/common.h
src/decrypt-mask.bmp [new file with mode: 0644]
src/decrypt-verify-mask.bmp [new file with mode: 0644]
src/decrypt-verify.bmp [new file with mode: 0644]
src/decrypt.bmp
src/dialogs.h
src/dialogs.rc
src/explorers.cpp [new file with mode: 0644]
src/explorers.h [new file with mode: 0644]
src/ext-commands.cpp
src/ext-commands.h
src/inspectors.cpp [new file with mode: 0644]
src/inspectors.h [new file with mode: 0644]
src/item-events.h
src/key-manager-mask.bmp [new file with mode: 0644]
src/key-manager.bmp [new file with mode: 0644]
src/main.c
src/message-events.cpp
src/message.cpp
src/mimemaker.c
src/myexchext.h
src/ol-ext-callback.cpp
src/ol-ext-callback.h
src/olflange-dlgs.cpp
src/olflange.cpp
src/oomhelp.cpp [new file with mode: 0644]
src/oomhelp.h [new file with mode: 0644]
src/sign-mask.bmp [new file with mode: 0644]
src/sign.bmp
src/user-events.cpp
src/util.h
src/verify-mask.bmp [new file with mode: 0644]
src/verify.bmp [new file with mode: 0644]

index 37b9b14..1e04456 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2009-10-08  Werner Koch  <wk@g10code.com>
+
+       * configure.ac (CFLAGS): Add -fno-strict-aliasing.
+
 2009-09-28  Werner Koch  <wk@g10code.com>
 
        Release 1.0.1.
diff --git a/NEWS b/NEWS
index 8736b48..4cfd55b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,15 @@
+Noteworthy changes for version 1.1.0
+===================================================
+
+ * Replaced some ECF code by direct OOM code.  This was required to
+   support better icons; i.e. icons not limited to a 16 color palette.
+
+ * New icons.
+
+ * Removed protocol selection.  The UI-server is now expected to select
+   the protocol (i.e. the auto selection modus is now the only one).
+
+
 Noteworthy changes for version 1.0.1 (2009-09-28)
 ===================================================
 
index afee9e6..1345edc 100644 (file)
@@ -16,8 +16,8 @@ min_automake_version="1.9.4"
 # Remember to change the version number immediately *after* a release.
 # Set my_issvn to "yes" for non-released code.  Remember to run an
 # "svn up" and "autogen.sh" right before creating a distribution.
-m4_define([my_version], [1.0.1])
-m4_define([my_issvn], [no])
+m4_define([my_version], [1.1.0])
+m4_define([my_issvn], [yes])
 
 m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \
             || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q;}')]))
@@ -190,8 +190,8 @@ if test "$have_w32_system" = yes; then
 fi
 
 if test "$GCC" = yes; then
-    CFLAGS="$CFLAGS -Wall -mms-bitfields"
-    CXXFLAGS="$CXXFLAGS -Wall -mms-bitfields"
+    CFLAGS="$CFLAGS -Wall -mms-bitfields -fno-strict-aliasing"
+    CXXFLAGS="$CXXFLAGS -Wall -mms-bitfields -fno-strict-aliasing"
     if test "$USE_MAINTAINER_MODE" = "yes"; then
         CFLAGS="$CFLAGS -Wcast-align -Wshadow -Wstrict-prototypes"
         CFLAGS="$CFLAGS -Wno-format-y2k -Wformat-security"
index ef7dff3..08f738c 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: GpgOL 1.0.0\n"
 "Report-Msgid-Bugs-To: bug-gpgol@g10code.com\n"
-"POT-Creation-Date: 2009-08-28 19:09+0200\n"
+"POT-Creation-Date: 2009-10-26 17:53+0100\n"
 "PO-Revision-Date: 2009-06-18 19:18+0200\n"
 "Last-Translator: Werner Koch <wk@gnupg.org>\n"
 "Language-Team: de\n"
@@ -56,9 +56,8 @@ msgstr ""
 "Die GnuPG Benutzeroberfläche \"Kleopatra\" konnte nicht gefunden oder "
 "rechtzeitig gestartet werden.  Sie sollten es noch einmal versuchen."
 
-#: src/engine.c:395 src/engine.c:405 src/ext-commands.cpp:807
-#: src/ext-commands.cpp:828 src/ext-commands.cpp:833 src/main.c:687
-#: src/main.c:693 src/message.cpp:321
+#: src/engine.c:395 src/engine.c:405 src/ext-commands.cpp:821
+#: src/ext-commands.cpp:826 src/main.c:688 src/main.c:694 src/message.cpp:321
 msgid "GpgOL"
 msgstr "GpgOL"
 
@@ -216,11 +215,11 @@ msgstr "*** Anfang Notation (Signatur von: "
 msgid "*** End Notation ***\n"
 msgstr "*** Ende Notation ***\n"
 
-#: src/ext-commands.cpp:547
+#: src/ext-commands.cpp:550
 msgid "GpgOL Decrypt/Verify"
 msgstr "GpgOL Enschlüsseln/Prüfen"
 
-#: src/ext-commands.cpp:561
+#: src/ext-commands.cpp:564
 msgid ""
 "This is a signed and encrypted message.\n"
 "Click for more information. "
@@ -228,7 +227,7 @@ msgstr ""
 "Dies ist eine signierte und verschlüsselte Nachricht.\n"
 "Klicken Sie hier um weitere Informationen zu erhalten. "
 
-#: src/ext-commands.cpp:564
+#: src/ext-commands.cpp:567
 msgid ""
 "This is an encrypted message.\n"
 "Click for more information. "
@@ -236,7 +235,7 @@ msgstr ""
 "Dies ist eine verschlüsselte Nachricht.\n"
 "Klicken Sie hier um weitere Informationen zu erhalten. "
 
-#: src/ext-commands.cpp:566
+#: src/ext-commands.cpp:569
 msgid ""
 "This is a signed message.\n"
 "Click for more information. "
@@ -244,62 +243,19 @@ msgstr ""
 "Dies ist eine signierte Nachricht.\n"
 "Klicken Sie hier um weitere Informationen zu erhalten. "
 
-#: src/ext-commands.cpp:576
-msgid ">GnuPG protocol"
-msgstr ">GnuPG Protokoll"
-
-#: src/ext-commands.cpp:577
-msgid "auto"
-msgstr "automatisch"
-
-#: src/ext-commands.cpp:578
-msgid "PGP/MIME"
-msgstr "PGP/MIME"
-
-#: src/ext-commands.cpp:579
-msgid "S/MIME"
-msgstr "S/MIME"
-
-#: src/ext-commands.cpp:581
+#: src/ext-commands.cpp:584
 msgid "&encrypt message with GnuPG"
 msgstr "Nachricht verschlüsseln"
 
-#: src/ext-commands.cpp:582
+#: src/ext-commands.cpp:585
 msgid "&sign message with GnuPG"
 msgstr "Nachricht signieren"
 
-#: src/ext-commands.cpp:634
-msgid "GnuPG Certificate &Manager"
-msgstr "GnuPG Zertifikats&verwaltung"
-
-#: src/ext-commands.cpp:635
+#: src/ext-commands.cpp:637
 msgid "Remove GpgOL flags from this folder"
 msgstr "GpgOL Eigenschaften aus diesem Ordner entfernen"
 
-#: src/ext-commands.cpp:639
-msgid "Open the certificate manager"
-msgstr "Die Zertifikatsverwaltung öffnen"
-
-#: src/ext-commands.cpp:778
-msgid ""
-"Support for S/MIME has not been enabled.\n"
-"\n"
-"To enable S/MIME support, open the option dialog and check \"Enable the S/"
-"MIME support\".  The option dialog can be found in the main menu at: Extras-"
-">Options->GpgOL.\n"
-msgstr ""
-"Unterstützung für S/MIME ist nicht eingeschaltet.\n"
-"\n"
-"Um die S/MIME Unterstützung einzuschalten, öffnen Sie bitte das Fenster mit "
-"den Einstellungen um dort die Option \"S/MIME Unterstützung einschalten\" zu "
-"aktivieren.  Sie finden die Einstellungen im Hauptmenu unter:  Extras-"
-">Optionen->GpgOL.\n"
-
-#: src/ext-commands.cpp:806
-msgid "Could not start certificate manager"
-msgstr "Die Zertifikatsverwaltung konnte nicht aufgerufen werden"
-
-#: src/ext-commands.cpp:818
+#: src/ext-commands.cpp:811
 msgid ""
 "You are about to start the process of reversing messages created by GpgOL to "
 "prepare deinstalling of GpgOL. Running this command will put GpgOL into a "
@@ -322,64 +278,32 @@ msgstr ""
 "weiterhin installiertem GpgOL - Nachrichten wieder wie gewohnt von GpgOL "
 "angezeigt werden."
 
-#: src/ext-commands.cpp:832
+#: src/ext-commands.cpp:825
 msgid "Do you want to revert this folder?"
 msgstr "Möchten Sie diesen Ordner von GpgOL befreien?"
 
-#: src/ext-commands.cpp:960
-msgid "Select this option to automatically select the protocol."
-msgstr "Wählen Sie diese Option zum das Protokoll automatisch auszuwählen."
-
-#: src/ext-commands.cpp:967
-msgid "Select this option to select the PGP/MIME protocol."
-msgstr "Wählen Sie diese Option zum das PGP/MIME Protokoll auszuwählen."
-
-#: src/ext-commands.cpp:974
-msgid "Select this option to select the S/MIME protocol."
-msgstr "Wählen Sie diese Option zum das S/MIME Protokoll auszuwählen."
-
-#: src/ext-commands.cpp:981
+#: src/ext-commands.cpp:976
 msgid "Select this option to encrypt the message."
 msgstr "Wählen Sie diese Option zum Verschlüsseln der Nachricht."
 
-#: src/ext-commands.cpp:988
+#: src/ext-commands.cpp:983
 msgid "Select this option to sign the message."
 msgstr "Wählen Sie diese Option zum Signieren der Nachricht."
 
-#: src/ext-commands.cpp:995
-msgid "Select this option to open the certificate manager"
-msgstr "Wählen Sie diese Option zum die Zertifikatsverwaltung zu öffenen."
-
-#: src/ext-commands.cpp:1025
-msgid "Automatically select the protocol for sign/encrypt"
-msgstr "Wählen Sie diese Option um das Protokoll automatisch auszuwählen."
-
-#: src/ext-commands.cpp:1035
-msgid "Use PGP/MIME for sign/encrypt"
-msgstr "PGP/MIME zum signieren/verschlüsseln verwenden."
-
-#: src/ext-commands.cpp:1045
-msgid "Use S/MIME for sign/encrypt"
-msgstr "S/MIME zum signieren/verschlüsseln verwenden."
-
-#: src/ext-commands.cpp:1055
+#: src/ext-commands.cpp:1043
 msgid "Encrypt message with GnuPG"
 msgstr "Nachricht verschlüsseln"
 
-#: src/ext-commands.cpp:1065
+#: src/ext-commands.cpp:1053
 msgid "Sign message with GnuPG"
 msgstr "Nachricht signieren"
 
-#: src/ext-commands.cpp:1075
-msgid "Open the GpgOL certificate manager"
-msgstr "Zertifikatsverwaltung von GpgOL öffnen"
-
-#: src/main.c:686
+#: src/main.c:687
 #, c-format
 msgid "Note: Using compatibility flags: %s"
 msgstr "Notiz: Diese Kompatibilitätsflags werden verwendet: %s"
 
-#: src/main.c:692
+#: src/main.c:693
 #, c-format
 msgid ""
 "Note: Writing debug logs to\n"
@@ -414,7 +338,7 @@ msgstr ""
 "[Aufgrund eines Verarbeitungsfehlers in GpgOL ist der Inhalt dieser "
 "Nachricht nicht sichtbar.]"
 
-#: src/message-events.cpp:320
+#: src/message-events.cpp:254
 msgid ""
 "Sorry, we can only encrypt plain text messages and\n"
 "no RTF messages. Please make sure that only the text\n"
@@ -531,50 +455,24 @@ msgstr "Neue Nachrichten per Voreinstellung verschlüsseln"
 msgid "&Sign new messages by default"
 msgstr "Neue Nachrichten per Voreinstellung signieren"
 
-#: src/olflange-dlgs.cpp:50
-msgid "Use PGP/MIME by default"
-msgstr "PGP/MIME per Voreinstellung verwenden"
-
 #: src/olflange-dlgs.cpp:51
-msgid "Use S/MIME by default"
-msgstr "S/MIME per Voreinstellung verwenden"
-
-#: src/olflange-dlgs.cpp:53
 msgid "Message receiving"
 msgstr "Lesen von Nachrichten"
 
-#: src/olflange-dlgs.cpp:55
+#: src/olflange-dlgs.cpp:53
 msgid "Show HTML view if possible"
 msgstr "HTML Darstellung anzeigen wenn möglich"
 
-#: src/olflange-dlgs.cpp:56
+#: src/olflange-dlgs.cpp:54
 msgid "Present encrypted message as attachment"
 msgstr "Verschlüsselte Nachricht als Anlage anzeigen"
 
-#: src/olflange-dlgs.cpp:59
+#: src/olflange-dlgs.cpp:57
 msgid "Crypto Engine"
 msgstr "Zertifikatsserver ..."
 
-#: src/olflange-dlgs.cpp:216
-msgid ""
-"You have enabled GpgOL's support for the S/MIME protocol.\n"
-"\n"
-"New S/MIME messages are thus only viewable with GpgOL and not anymore with "
-"Outlook's internal S/MIME support.  Those message will even be unreadable by "
-"Outlook after GpgOL has been deinstalled.  A tool to mitigate this problem "
-"will be provided when GpgOL arrives at production quality status."
-msgstr ""
-"Sie haben die S/MIME Unterstützung von GpgOL eingeschaltet.\n"
-"\n"
-"Neue S/MIME Nachrichten werden jetzt nur noch mittels GpgOL sichtbar sein "
-"und nicht mehr über Outlooks interne S/MIME Unterstützung.  Diese "
-"Nachrichten werden auch dann nicht mehr mit Outlook lesbar sein, wenn GpgOL "
-"deinstalliert wurde.  Mit dem Erscheinen der endgültigen Version von GpgOL "
-"wird aber ein Werkzeug bereitgestellt werden, welches dieses Problem lösen "
-"kann."
-
 #. TRANSLATORS: See the source for the full english text.
-#: src/olflange-dlgs.cpp:273
+#: src/olflange-dlgs.cpp:257
 msgid "-#GpgOLFullHelpText#-"
 msgstr ""
 "GpgOL ist ein Plugin für Microsoft Outlook, welches es ermöglicht\n"
@@ -600,12 +498,12 @@ msgstr ""
 "Public License erhalten haben.  Falls nicht, finden Sie diese\n"
 "unter der Webadresse <http://www.gnu.org/licenses/>."
 
-#: src/olflange-dlgs.cpp:279
+#: src/olflange-dlgs.cpp:263
 #, c-format
 msgid "This is GpgOL version %s"
 msgstr "Dies ist GpgOL Version %s"
 
-#: src/olflange.cpp:442
+#: src/olflange.cpp:447
 msgid ""
 "Welcome to GpgOL 1.0\n"
 "\n"
@@ -644,7 +542,7 @@ msgstr ""
 "Konto nicht.  Wird GpgOL zusammen mit anderen Outlook Plugins benutzt, kann "
 "es möglicherweise nicht richtig arbeiten.\n"
 
-#: src/olflange.cpp:470
+#: src/olflange.cpp:475
 msgid ""
 "You have installed a new version of GpgOL.\n"
 "\n"
@@ -658,7 +556,7 @@ msgstr ""
 "die Einstellungen für Sie noch stimmen.  Sie finden die Einstellungen im "
 "Hauptmenu unter:  Extras->Optionen->GpgOL.\n"
 
-#: src/olflange.cpp:658
+#: src/olflange.cpp:663
 msgid ""
 "This version of Outlook is too old!\n"
 "\n"
@@ -817,6 +715,89 @@ msgstr "PGP/MIME Prüfungsresultat"
 msgid "S/MIME Verification Result"
 msgstr "S/MIME Prüfungsresultat"
 
+#~ msgid "GnuPG Certificate &Manager"
+#~ msgstr "GnuPG Zertifikats&verwaltung"
+
+#~ msgid "Open the certificate manager"
+#~ msgstr "Die Zertifikatsverwaltung öffnen"
+
+#~ msgid "Select this option to open the certificate manager"
+#~ msgstr "Wählen Sie diese Option zum die Zertifikatsverwaltung zu öffenen."
+
+#~ msgid "Open the GpgOL certificate manager"
+#~ msgstr "Zertifikatsverwaltung von GpgOL öffnen"
+
+#~ msgid ">GnuPG protocol"
+#~ msgstr ">GnuPG Protokoll"
+
+#~ msgid "auto"
+#~ msgstr "automatisch"
+
+#~ msgid "PGP/MIME"
+#~ msgstr "PGP/MIME"
+
+#~ msgid "S/MIME"
+#~ msgstr "S/MIME"
+
+#~ msgid ""
+#~ "Support for S/MIME has not been enabled.\n"
+#~ "\n"
+#~ "To enable S/MIME support, open the option dialog and check \"Enable the S/"
+#~ "MIME support\".  The option dialog can be found in the main menu at: "
+#~ "Extras->Options->GpgOL.\n"
+#~ msgstr ""
+#~ "Unterstützung für S/MIME ist nicht eingeschaltet.\n"
+#~ "\n"
+#~ "Um die S/MIME Unterstützung einzuschalten, öffnen Sie bitte das Fenster "
+#~ "mit den Einstellungen um dort die Option \"S/MIME Unterstützung "
+#~ "einschalten\" zu aktivieren.  Sie finden die Einstellungen im Hauptmenu "
+#~ "unter:  Extras->Optionen->GpgOL.\n"
+
+#~ msgid "Could not start certificate manager"
+#~ msgstr "Die Zertifikatsverwaltung konnte nicht aufgerufen werden"
+
+#~ msgid "Select this option to automatically select the protocol."
+#~ msgstr "Wählen Sie diese Option zum das Protokoll automatisch auszuwählen."
+
+#~ msgid "Select this option to select the PGP/MIME protocol."
+#~ msgstr "Wählen Sie diese Option zum das PGP/MIME Protokoll auszuwählen."
+
+#~ msgid "Select this option to select the S/MIME protocol."
+#~ msgstr "Wählen Sie diese Option zum das S/MIME Protokoll auszuwählen."
+
+#~ msgid "Automatically select the protocol for sign/encrypt"
+#~ msgstr "Wählen Sie diese Option um das Protokoll automatisch auszuwählen."
+
+#~ msgid "Use PGP/MIME for sign/encrypt"
+#~ msgstr "PGP/MIME zum signieren/verschlüsseln verwenden."
+
+#~ msgid "Use S/MIME for sign/encrypt"
+#~ msgstr "S/MIME zum signieren/verschlüsseln verwenden."
+
+#~ msgid "Use PGP/MIME by default"
+#~ msgstr "PGP/MIME per Voreinstellung verwenden"
+
+#~ msgid "Use S/MIME by default"
+#~ msgstr "S/MIME per Voreinstellung verwenden"
+
+#~ msgid ""
+#~ "You have enabled GpgOL's support for the S/MIME protocol.\n"
+#~ "\n"
+#~ "New S/MIME messages are thus only viewable with GpgOL and not anymore "
+#~ "with Outlook's internal S/MIME support.  Those message will even be "
+#~ "unreadable by Outlook after GpgOL has been deinstalled.  A tool to "
+#~ "mitigate this problem will be provided when GpgOL arrives at production "
+#~ "quality status."
+#~ msgstr ""
+#~ "Sie haben die S/MIME Unterstützung von GpgOL eingeschaltet.\n"
+#~ "\n"
+#~ "Neue S/MIME Nachrichten werden jetzt nur noch mittels GpgOL sichtbar sein "
+#~ "und nicht mehr über Outlooks interne S/MIME Unterstützung.  Diese "
+#~ "Nachrichten werden auch dann nicht mehr mit Outlook lesbar sein, wenn "
+#~ "GpgOL deinstalliert wurde.  Mit dem Erscheinen der endgültigen Version "
+#~ "von GpgOL wird aber ein Werkzeug bereitgestellt werden, welches dieses "
+#~ "Problem lösen kann."
+
 #~ msgid "Also decrypt in preview window"
 #~ msgstr "Auch im Vorschaufenster entschlüsseln"
 
index e599d46..0e739fa 100644 (file)
--- a/po/sv.po
+++ b/po/sv.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: GPGol\n"
 "Report-Msgid-Bugs-To: bug-gpgol@g10code.com\n"
-"POT-Creation-Date: 2009-08-28 19:09+0200\n"
+"POT-Creation-Date: 2009-10-26 17:53+0100\n"
 "PO-Revision-Date: 2006-12-12 23:52+0100\n"
 "Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
 "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
@@ -54,9 +54,8 @@ msgid ""
 "You may want to try again."
 msgstr ""
 
-#: src/engine.c:395 src/engine.c:405 src/ext-commands.cpp:807
-#: src/ext-commands.cpp:828 src/ext-commands.cpp:833 src/main.c:687
-#: src/main.c:693 src/message.cpp:321
+#: src/engine.c:395 src/engine.c:405 src/ext-commands.cpp:821
+#: src/ext-commands.cpp:826 src/main.c:688 src/main.c:694 src/message.cpp:321
 msgid "GpgOL"
 msgstr ""
 
@@ -206,83 +205,43 @@ msgstr "*** Notation start (signatur av: "
 msgid "*** End Notation ***\n"
 msgstr "*** Notation slut ***\n"
 
-#: src/ext-commands.cpp:547
+#: src/ext-commands.cpp:550
 msgid "GpgOL Decrypt/Verify"
 msgstr ""
 
-#: src/ext-commands.cpp:561
+#: src/ext-commands.cpp:564
 msgid ""
 "This is a signed and encrypted message.\n"
 "Click for more information. "
 msgstr ""
 
-#: src/ext-commands.cpp:564
+#: src/ext-commands.cpp:567
 msgid ""
 "This is an encrypted message.\n"
 "Click for more information. "
 msgstr ""
 
-#: src/ext-commands.cpp:566
+#: src/ext-commands.cpp:569
 msgid ""
 "This is a signed message.\n"
 "Click for more information. "
 msgstr ""
 
-#: src/ext-commands.cpp:576
-msgid ">GnuPG protocol"
-msgstr ""
-
-#: src/ext-commands.cpp:577
-msgid "auto"
-msgstr ""
-
-#: src/ext-commands.cpp:578
-#, fuzzy
-msgid "PGP/MIME"
-msgstr "[PGP/MIME-meddelande]"
-
-#: src/ext-commands.cpp:579
-msgid "S/MIME"
-msgstr ""
-
-#: src/ext-commands.cpp:581
+#: src/ext-commands.cpp:584
 #, fuzzy
 msgid "&encrypt message with GnuPG"
 msgstr "Signera meddelandet med GPG"
 
-#: src/ext-commands.cpp:582
+#: src/ext-commands.cpp:585
 #, fuzzy
 msgid "&sign message with GnuPG"
 msgstr "Signera meddelandet med GPG"
 
-#: src/ext-commands.cpp:634
-#, fuzzy
-msgid "GnuPG Certificate &Manager"
-msgstr "GPG-nyckel&hanterare"
-
-#: src/ext-commands.cpp:635
+#: src/ext-commands.cpp:637
 msgid "Remove GpgOL flags from this folder"
 msgstr ""
 
-#: src/ext-commands.cpp:639
-msgid "Open the certificate manager"
-msgstr ""
-
-#: src/ext-commands.cpp:778
-msgid ""
-"Support for S/MIME has not been enabled.\n"
-"\n"
-"To enable S/MIME support, open the option dialog and check \"Enable the S/"
-"MIME support\".  The option dialog can be found in the main menu at: Extras-"
-">Options->GpgOL.\n"
-msgstr ""
-
-#: src/ext-commands.cpp:806
-#, fuzzy
-msgid "Could not start certificate manager"
-msgstr "Kunde inte starta nyckelhanteraren"
-
-#: src/ext-commands.cpp:818
+#: src/ext-commands.cpp:811
 msgid ""
 "You are about to start the process of reversing messages created by GpgOL to "
 "prepare deinstalling of GpgOL. Running this command will put GpgOL into a "
@@ -295,71 +254,34 @@ msgid ""
 "will again process messages."
 msgstr ""
 
-#: src/ext-commands.cpp:832
+#: src/ext-commands.cpp:825
 msgid "Do you want to revert this folder?"
 msgstr ""
 
-#: src/ext-commands.cpp:960
-#, fuzzy
-msgid "Select this option to automatically select the protocol."
-msgstr "Välj det här alternativet för att kryptera meddelandet."
-
-#: src/ext-commands.cpp:967
-#, fuzzy
-msgid "Select this option to select the PGP/MIME protocol."
-msgstr "Välj det här alternativet för att kryptera meddelandet."
-
-#: src/ext-commands.cpp:974
-#, fuzzy
-msgid "Select this option to select the S/MIME protocol."
-msgstr "Välj det här alternativet för att kryptera meddelandet."
-
-#: src/ext-commands.cpp:981
+#: src/ext-commands.cpp:976
 msgid "Select this option to encrypt the message."
 msgstr "Välj det här alternativet för att kryptera meddelandet."
 
-#: src/ext-commands.cpp:988
+#: src/ext-commands.cpp:983
 msgid "Select this option to sign the message."
 msgstr "Välj det här alternativet för att signera meddelandet."
 
-#: src/ext-commands.cpp:995
-#, fuzzy
-msgid "Select this option to open the certificate manager"
-msgstr "Välj det här alternativet för att kryptera meddelandet."
-
-#: src/ext-commands.cpp:1025
-#, fuzzy
-msgid "Automatically select the protocol for sign/encrypt"
-msgstr "Välj det här alternativet för att kryptera meddelandet."
-
-#: src/ext-commands.cpp:1035
-msgid "Use PGP/MIME for sign/encrypt"
-msgstr ""
-
-#: src/ext-commands.cpp:1045
-msgid "Use S/MIME for sign/encrypt"
-msgstr ""
-
-#: src/ext-commands.cpp:1055
+#: src/ext-commands.cpp:1043
 #, fuzzy
 msgid "Encrypt message with GnuPG"
 msgstr "Signera meddelandet med GPG"
 
-#: src/ext-commands.cpp:1065
+#: src/ext-commands.cpp:1053
 #, fuzzy
 msgid "Sign message with GnuPG"
 msgstr "Signera meddelandet med GPG"
 
-#: src/ext-commands.cpp:1075
-msgid "Open the GpgOL certificate manager"
-msgstr ""
-
-#: src/main.c:686
+#: src/main.c:687
 #, c-format
 msgid "Note: Using compatibility flags: %s"
 msgstr ""
 
-#: src/main.c:692
+#: src/main.c:693
 #, c-format
 msgid ""
 "Note: Writing debug logs to\n"
@@ -385,7 +307,7 @@ msgid ""
 msgstr ""
 
 # A bit unclear in the original text
-#: src/message-events.cpp:320
+#: src/message-events.cpp:254
 msgid ""
 "Sorry, we can only encrypt plain text messages and\n"
 "no RTF messages. Please make sure that only the text\n"
@@ -490,51 +412,33 @@ msgstr "Kryptera meddelandet med GPG"
 msgid "&Sign new messages by default"
 msgstr ""
 
-#: src/olflange-dlgs.cpp:50
-msgid "Use PGP/MIME by default"
-msgstr ""
-
 #: src/olflange-dlgs.cpp:51
-msgid "Use S/MIME by default"
-msgstr ""
-
-#: src/olflange-dlgs.cpp:53
 msgid "Message receiving"
 msgstr ""
 
-#: src/olflange-dlgs.cpp:55
+#: src/olflange-dlgs.cpp:53
 msgid "Show HTML view if possible"
 msgstr ""
 
-#: src/olflange-dlgs.cpp:56
+#: src/olflange-dlgs.cpp:54
 msgid "Present encrypted message as attachment"
 msgstr ""
 
-#: src/olflange-dlgs.cpp:59
+#: src/olflange-dlgs.cpp:57
 msgid "Crypto Engine"
 msgstr ""
 
-#: src/olflange-dlgs.cpp:216
-msgid ""
-"You have enabled GpgOL's support for the S/MIME protocol.\n"
-"\n"
-"New S/MIME messages are thus only viewable with GpgOL and not anymore with "
-"Outlook's internal S/MIME support.  Those message will even be unreadable by "
-"Outlook after GpgOL has been deinstalled.  A tool to mitigate this problem "
-"will be provided when GpgOL arrives at production quality status."
-msgstr ""
-
 #. TRANSLATORS: See the source for the full english text.
-#: src/olflange-dlgs.cpp:273
+#: src/olflange-dlgs.cpp:257
 msgid "-#GpgOLFullHelpText#-"
 msgstr ""
 
-#: src/olflange-dlgs.cpp:279
+#: src/olflange-dlgs.cpp:263
 #, c-format
 msgid "This is GpgOL version %s"
 msgstr ""
 
-#: src/olflange.cpp:442
+#: src/olflange.cpp:447
 msgid ""
 "Welcome to GpgOL 1.0\n"
 "\n"
@@ -555,7 +459,7 @@ msgid ""
 "along with other Outlook plugins may in some cases not work.\n"
 msgstr ""
 
-#: src/olflange.cpp:470
+#: src/olflange.cpp:475
 msgid ""
 "You have installed a new version of GpgOL.\n"
 "\n"
@@ -564,7 +468,7 @@ msgid ""
 ">Options->GpgOL.\n"
 msgstr ""
 
-#: src/olflange.cpp:658
+#: src/olflange.cpp:663
 msgid ""
 "This version of Outlook is too old!\n"
 "\n"
@@ -731,6 +635,38 @@ msgstr "Resultat från validering"
 msgid "S/MIME Verification Result"
 msgstr "Resultat från validering"
 
+#, fuzzy
+#~ msgid "GnuPG Certificate &Manager"
+#~ msgstr "GPG-nyckel&hanterare"
+
+#, fuzzy
+#~ msgid "Select this option to open the certificate manager"
+#~ msgstr "Välj det här alternativet för att kryptera meddelandet."
+
+#, fuzzy
+#~ msgid "PGP/MIME"
+#~ msgstr "[PGP/MIME-meddelande]"
+
+#, fuzzy
+#~ msgid "Could not start certificate manager"
+#~ msgstr "Kunde inte starta nyckelhanteraren"
+
+#, fuzzy
+#~ msgid "Select this option to automatically select the protocol."
+#~ msgstr "Välj det här alternativet för att kryptera meddelandet."
+
+#, fuzzy
+#~ msgid "Select this option to select the PGP/MIME protocol."
+#~ msgstr "Välj det här alternativet för att kryptera meddelandet."
+
+#, fuzzy
+#~ msgid "Select this option to select the S/MIME protocol."
+#~ msgstr "Välj det här alternativet för att kryptera meddelandet."
+
+#, fuzzy
+#~ msgid "Automatically select the protocol for sign/encrypt"
+#~ msgstr "Välj det här alternativet för att kryptera meddelandet."
+
 #~ msgid "&Decrypt and verify message"
 #~ msgstr "&Dekryptera och validera meddelandet"
 
index a197afd..67c8d78 100644 (file)
@@ -1,3 +1,47 @@
+2009-10-28  Werner Koch  <wk@g10code.com>
+
+       * ext-commands.cpp: Remove m_nCmdCryptoState and all related code;
+       now handled in inspectors.cpp.  Remove m_nCmdKeyManager and all
+       related code; now handled in cmdbarcontrols.cpp.
+
+       * oomhelp.cpp, oomhelp.h, eventsink.h: New.
+       * myexchext.h: Move generic COM+ stuff to oomhelp.h.
+       * explorers.cpp, explorers.h: New.
+       * inspectors.cpp, inspectors.h: New.
+       * cmdbarcontrols.cpp cmdbarcontrols.h: New.
+       * olflange.cpp (install_sinks): New.
+       (Install): Call install_sinks.
+       * main.c (DllMain): Call initialize_inspectors.
+
+       * common.c (fatal_error): New.
+
+2009-10-20  Werner Koch  <wk@g10code.com>
+
+       * myexchext.h (IID_IConnectionPoint)
+       (IID_IConnectionPointContainer): Define.  There are missing in
+       current wine  From ReactOS.
+
+2009-10-19  Werner Koch  <wk@g10code.com>
+
+       * message-events.cpp (show_event_object): Move to ..
+       * ol-ext-callback.cpp (show_event_object): .. here.
+       (show_preview_pane): Revert dispparms order to make it work.
+
+       * common.c (mem2str): New.
+
+2009-10-07  Werner Koch  <wk@g10code.com>
+
+       * ext-commands.cpp (InstallCommands): Comment out the protocol
+       selection.
+       (DoCommand, Help, QueryHelpText, QueryButtonInfo): Ditto.
+       (update_protocol_menu): Comment out.
+       * main.c (write_options): Do not write the default protocol.
+       (read_options): Always set it to auto.
+       * dialogs.rc: Remove openpgp-by-default and smime-by-default check
+       boxes.
+       * olflange-dlgs.cpp (set_labels): Likewise.
+       (GPGOptionsDlgProc): Likewise.
+
 2009-09-25  Werner Koch  <wk@g10code.com>
 
        * main.c (read_options): Enable Smime by default.
index 8f809f7..3e36f68 100644 (file)
@@ -16,9 +16,14 @@ unused_sources = item-events.cpp
 bin_PROGRAMS = gpgol 
 #treeview
 EXTRA_DIST = versioninfo.rc.in mapi32.def $(unused_sources) Outlook.gpl \
-            logo.bmp decrypt.bmp encrypt.bmp sign.bmp key_mana.bmp \
+            logo.bmp encrypt.bmp  \
              proto-auto.bmp proto-pgpmime.bmp proto-smime.bmp \
-             cryptostate.bmp
+             cryptostate.bmp \
+             key-manager.bmp key-manager-mask.bmp \
+             decrypt.bmp decrypt-mask.bmp \
+            verify.bmp  verify-mask.bmp \
+             decrypt-verify.bmp decrypt-verify-mask.bmp \
+            sign.bmp sign-mask.bmp
 
 EXEEXT = .dll
 
@@ -63,6 +68,10 @@ gpgol_SOURCES = \
        property-sheets.cpp property-sheets.h \
        item-events.h         \
        ol-ext-callback.cpp ol-ext-callback.h \
+       oomhelp.cpp oomhelp.h eventsink.h \
+       explorers.cpp explorers.h \
+       inspectors.cpp inspectors.h \
+       cmdbarcontrols.cpp cmdbarcontrols.h \
        w32-gettext.c w32-gettext.h 
 
 
diff --git a/src/cmdbarcontrols.cpp b/src/cmdbarcontrols.cpp
new file mode 100644 (file)
index 0000000..d710791
--- /dev/null
@@ -0,0 +1,132 @@
+/* cmdbarcontrols.cpp - Code to handle the CommandBarControls
+ *     Copyright (C) 2009 g10 Code 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/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <windows.h>
+#include <olectl.h>
+
+#include "common.h"
+#include "oomhelp.h"
+#include "cmdbarcontrols.h"
+#include "inspectors.h"
+#include "engine.h"
+
+#include "eventsink.h"
+
+
+/* Subclass of CommandBarButtonEvents so that we can hook into the
+   Click event.  */
+BEGIN_EVENT_SINK(GpgolCommandBarButtonEvents, IOOMCommandBarButtonEvents)
+  STDMETHOD (Click) (THIS_ LPDISPATCH, PBOOL);
+EVENT_SINK_DEFAULT_DTOR(GpgolCommandBarButtonEvents)
+EVENT_SINK_INVOKE(GpgolCommandBarButtonEvents)
+{
+  HRESULT hr;
+  (void)lcid; (void)riid; (void)result; (void)exepinfo; (void)argerr;
+
+  if (dispid == 1 && (flags & DISPATCH_METHOD))
+    {
+      if (!parms) 
+        hr = DISP_E_PARAMNOTOPTIONAL;
+      else if (parms->cArgs != 2)
+        hr = DISP_E_BADPARAMCOUNT;
+      else if (parms->rgvarg[0].vt != (VT_BOOL|VT_BYREF)
+               || parms->rgvarg[1].vt != VT_DISPATCH)
+        hr = DISP_E_BADVARTYPE;
+      else
+        {
+          BOOL cancel_default = !!*parms->rgvarg[0].pboolVal;
+          hr = Click (parms->rgvarg[1].pdispVal, (PBOOL)&cancel_default);
+          *parms->rgvarg[0].pboolVal = (cancel_default 
+                                        ? VARIANT_TRUE:VARIANT_FALSE);
+        }
+    }
+  else
+    hr = DISP_E_MEMBERNOTFOUND;
+  return hr;
+}
+END_EVENT_SINK(GpgolCommandBarButtonEvents, IID_IOOMCommandBarButtonEvents)
+
+
+
+
+static int
+tagcmp (const char *a, const char *b)
+{
+  return strncmp (a, b, strlen (b));
+}
+
+
+/* This is the event sink for a button click.  */
+STDMETHODIMP
+GpgolCommandBarButtonEvents::Click (LPDISPATCH button, PBOOL cancel_default)
+{
+  char *tag;
+
+  (void)cancel_default;
+  log_debug ("%s:%s: Called", SRCNAME, __func__);
+
+  {
+    char *tmp = get_object_name (button);
+    log_debug ("%s:%s: button is %p (%s)", 
+               SRCNAME, __func__, button, tmp? tmp:"(null)");
+    xfree (tmp);
+  }
+
+  tag = get_oom_string (button, "Tag");
+  log_debug ("%s:%s: button's tag is (%s)", 
+             SRCNAME, __func__, tag? tag:"(null)");
+  if (!tag)
+    ;
+  else if (!tagcmp (tag, "GpgOL_Start_Key_Manager"))
+    {
+      /* FIXME: We don't have the current window handle.  */
+      if (engine_start_keymanager (NULL))
+         MessageBox (NULL, _("Could not start certificate manager"),
+                     _("GpgOL"), MB_ICONERROR|MB_OK);
+    }
+  else if (!tagcmp (tag, "GpgOL_Inspector_Crypto_Info"))
+    {
+      /* FIXME: We should invoke the decrypt/verify again. */
+      update_inspector_crypto_info (button);
+#if 0 /* This is the code we used to use.  */
+      log_debug ("%s:%s: command CryptoState called\n", SRCNAME, __func__);
+      hr = eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
+      if (SUCCEEDED (hr))
+        {
+          if (message_incoming_handler (message, hwnd, true))
+            message_display_handler (eecb, hwnd);
+       }
+      else
+        log_debug_w32 (hr, "%s:%s: command CryptoState failed", 
+                       SRCNAME, __func__);
+      ul_release (message, __func__, __LINE__);
+      ul_release (mdb, __func__, __LINE__);
+#endif
+
+    }
+
+  xfree (tag);
+  return S_OK;
+}
+
+
diff --git a/src/cmdbarcontrols.h b/src/cmdbarcontrols.h
new file mode 100644 (file)
index 0000000..7c8e1ed
--- /dev/null
@@ -0,0 +1,63 @@
+/* cmdbarcontrols.h - Defs to handle the CommandBarControls
+ *     Copyright (C) 2009 g10 Code 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 CMDBARCONTROLS_H
+#define CMDBARCONTROLS_H
+
+#include <commctrl.h>
+#include "oomhelp.h"
+
+DEFINE_OLEGUID(IID_IOOMCommandBarButtonEvents,  0x000c0351, 0, 0);
+
+typedef struct IOOMCommandBarButtonEvents IOOMCommandBarButtonEvents;
+typedef IOOMCommandBarButtonEvents *LPOOMCOMMANDBARBUTTONEVENTS;
+
+struct IOOMCommandBarButton;
+typedef IOOMCommandBarButton *LPOOMCOMMANDBARBUTTON;
+
+
+EXTERN_C const IID IID_IOOMCommandBarButtonEvents;
+#undef INTERFACE
+#define INTERFACE  IOOMCommandBarButtonEvents
+DECLARE_INTERFACE_(IOOMCommandBarButtonEvents, IDispatch)
+{
+  /*** IUnknown methods ***/
+  STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * lppvObj) PURE;
+  STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+  STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+  /*** IDispatch methods ***/
+  STDMETHOD(GetTypeInfoCount)(THIS_ UINT*) PURE;
+  STDMETHOD(GetTypeInfo)(THIS_ UINT, LCID, LPTYPEINFO*) PURE;
+  STDMETHOD(GetIDsOfNames)(THIS_ REFIID, LPOLESTR*, UINT, LCID, DISPID*) PURE;
+  STDMETHOD(Invoke)(THIS_ DISPID, REFIID, LCID, WORD,
+                    DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*) PURE;
+
+  /*** IOOMCommandBarButtonEvents methods ***/
+  /* dispid=1 */
+  STDMETHOD(Click)(THIS_ LPDISPATCH, PBOOL) PURE;
+};
+
+
+
+LPDISPATCH install_GpgolCommandBarButtonEvents_sink (LPDISPATCH button);
+
+
+
+#endif /*CMDBARCONTROLS_H*/
index 32fe466..43239c7 100644 (file)
@@ -223,10 +223,25 @@ get_save_filename (HWND root, const char *srcname)
 
 
 void
+fatal_error (const char *format, ...)
+{
+  va_list arg_ptr;
+  char buf[512];
+
+  va_start (arg_ptr, format);
+  vsnprintf (buf, sizeof buf -1, format, arg_ptr);
+  buf[sizeof buf - 1] = 0;
+  va_end (arg_ptr);
+  MessageBox (NULL, buf, "Fatal Error", MB_OK);
+  abort ();
+}
+
+
+void
 out_of_core (void)
 {
-    MessageBox (NULL, "Out of core!", "Fatal Error", MB_OK);
-    abort ();
+  MessageBox (NULL, "Out of core!", "Fatal Error", MB_OK);
+  abort ();
 }
 
 void*
@@ -391,6 +406,38 @@ latin1_to_utf8 (const char *string)
 }
 
 
+/* This function is similar to strncpy().  However it won't copy more
+   than N - 1 characters and makes sure that a Nul is appended. With N
+   given as 0, nothing will happen.  With DEST given as NULL, memory
+   will be allocated using xmalloc (i.e. if it runs out of core the
+   function terminates).  Returns DEST or a pointer to the allocated
+   memory.  */
+char *
+mem2str (char *dest, const void *src, size_t n)
+{
+  char *d;
+  const char *s;
+  
+  if (n)
+    {
+      if (!dest)
+        dest = xmalloc (n);
+      d = dest;
+      s = src ;
+      for (n--; n && *s; n--)
+        *d++ = *s++;
+      *d = 0;
+    }
+  else if (!dest)
+    {
+      dest = xmalloc (1);
+      *dest = 0;
+    }
+  
+  return dest;
+}
+
+
 /* Strip off trailing white spaces from STRING.  Returns STRING. */
 char *
 trim_trailing_spaces (char *string)
index df5eeb7..0fb11ed 100644 (file)
@@ -242,6 +242,10 @@ int verify_dialog_box (gpgme_protocol_t protocol,
                        const char *filename);
 
 
+/*-- inspectors.cpp --*/
+int initialize_inspectors (void);
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/decrypt-mask.bmp b/src/decrypt-mask.bmp
new file mode 100644 (file)
index 0000000..71ab4a7
Binary files /dev/null and b/src/decrypt-mask.bmp differ
diff --git a/src/decrypt-verify-mask.bmp b/src/decrypt-verify-mask.bmp
new file mode 100644 (file)
index 0000000..c13623c
Binary files /dev/null and b/src/decrypt-verify-mask.bmp differ
diff --git a/src/decrypt-verify.bmp b/src/decrypt-verify.bmp
new file mode 100644 (file)
index 0000000..b2680ea
Binary files /dev/null and b/src/decrypt-verify.bmp differ
index 841b834..f2251f1 100644 (file)
Binary files a/src/decrypt.bmp and b/src/decrypt.bmp differ
index 04c67fb..bc218d4 100644 (file)
@@ -7,18 +7,27 @@
 #define DIALOGS_H
 
 
-/* Ids used for bitmaps.  */
-#define IDB_DECRYPT                     3001  /* Not used.  */
-#define IDB_ENCRYPT                     3002
-#define IDB_SIGN                        3003
-#define IDB_ADD_KEYS                    3004
-#define IDB_KEY_MANAGER                 3005
-#define IDB_BANNER                      3006  /* The g10 Code logo.  */
-#define IDB_BANNER_HI                   3007  /* Not used.  */
-#define IDB_CRYPTO_STATE                3008  
-#define IDB_PROTO_AUTO                  3009
-#define IDB_PROTO_PGPMIME               3010
-#define IDB_PROTO_SMIME                 3011
+/* Ids used for bitmaps. 
+   Note: FOO_MASK must have a value of FOO + 1. */
+#define IDB_ENCRYPT                     3004
+#define IDB_SIGN                        3006
+#define IDB_SIGN_MASK                   3007
+#define IDB_ADD_KEYS                    3008
+#define IDB_KEY_MANAGER                 3010
+#define IDB_KEY_MANAGER_MASK            3011
+#define IDB_BANNER                      3012  /* The g10 Code logo.  */
+#define IDB_BANNER_HI                   3014  /* Not used.  */
+#define IDB_CRYPTO_STATE                3016  
+#define IDB_PROTO_AUTO                  3018  /* Not used.  */
+#define IDB_PROTO_PGPMIME               3020  /* Not used.  */
+#define IDB_PROTO_SMIME                 3022  /* Not used.  */
+#define IDB_PROTO_SMIME_MASK            3023  /* Not used.  */
+#define IDB_DECRYPT                     3024
+#define IDB_DECRYPT_MASK                3025
+#define IDB_VERIFY                      3026
+#define IDB_VERIFY_MASK                 3027
+#define IDB_DECRYPT_VERIFY              3028
+#define IDB_DECRYPT_VERIFY_MASK         3029
 
 
 /* Ids used for the main config dialog.  */
index e917d02..b283337 100644 (file)
 
 /*IDB_DECRYPT             BITMAP  DISCARDABLE     "decrypt.bmp"*/
 IDB_ENCRYPT             BITMAP  DISCARDABLE     "encrypt.bmp"
-IDB_SIGN                BITMAP  DISCARDABLE     "sign.bmp"
-IDB_KEY_MANAGER         BITMAP  DISCARDABLE     "key_mana.bmp"
 IDB_BANNER              BITMAP  DISCARDABLE     "logo.bmp"
 IDB_CRYPTO_STATE        BITMAP  DISCARDABLE     "cryptostate.bmp"
 IDB_PROTO_AUTO          BITMAP  DISCARDABLE     "proto-auto.bmp"
 IDB_PROTO_PGPMIME       BITMAP  DISCARDABLE     "proto-pgpmime.bmp"
 IDB_PROTO_SMIME         BITMAP  DISCARDABLE     "proto-smime.bmp"
+IDB_PROTO_SMIME_MASK    BITMAP  DISCARDABLE     "proto-smime-mask.bmp"
+
+IDB_KEY_MANAGER         BITMAP  DISCARDABLE     "key-manager.bmp"
+IDB_KEY_MANAGER_MASK    BITMAP  DISCARDABLE     "key-manager-mask.bmp"
+IDB_DECRYPT             BITMAP  DISCARDABLE     "decrypt.bmp"
+IDB_DECRYPT_MASK        BITMAP  DISCARDABLE     "decrypt-mask.bmp"
+IDB_VERIFY              BITMAP  DISCARDABLE     "verify.bmp"
+IDB_VERIFY_MASK         BITMAP  DISCARDABLE     "verify-mask.bmp"
+IDB_DECRYPT_VERIFY      BITMAP  DISCARDABLE     "decrypt-verify.bmp"
+IDB_DECRYPT_VERIFY_MASK BITMAP  DISCARDABLE     "decrypt-verify-mask.bmp"
+IDB_SIGN                BITMAP  DISCARDABLE     "sign.bmp"
+IDB_SIGN_MASK           BITMAP  DISCARDABLE     "sign-mask.bmp"
+
 
 
 IDD_GPG_OPTIONS  DIALOG DISCARDABLE  0, 0, 266, 274
@@ -52,7 +63,7 @@ BEGIN
 
     /* Send options box.  */
     GROUPBOX        "send-options", IDC_G_SEND,
-                    9, 40, 250, 58
+                    9, 40, 250, 38
 
     CONTROL         "encrypt-by-default", IDC_ENCRYPT_DEFAULT,
                     "Button", BS_AUTOCHECKBOX | WS_TABSTOP,
@@ -62,17 +73,9 @@ BEGIN
                     "Button", BS_AUTOCHECKBOX | WS_TABSTOP,
                     24, 61, 215, 10
 
-    CONTROL         "openpgp-by-default", IDC_OPENPGP_DEFAULT,
-                    "Button", BS_AUTOCHECKBOX | WS_TABSTOP,
-                    24, 72, 215, 10
-
-    CONTROL         "smime-by-default", IDC_SMIME_DEFAULT,
-                    "Button", BS_AUTOCHECKBOX | WS_TABSTOP,
-                    24, 83, 215, 10
-
     /* Receive options box.  */
     GROUPBOX        "recv-options", IDC_G_RECV,
-                    9, 104, 250, 36
+                    9, 82, 250, 36
 
   /* We have no reliable way to detect the preview window, thus we
      don't show this option.  */
@@ -82,11 +85,11 @@ BEGIN
 
     CONTROL         "prefer-html", IDC_PREFER_HTML,
                     "Button", BS_AUTOCHECKBOX | WS_TABSTOP,
-                    24, 114, 215, 10
+                    24,  94, 215, 10
  
     CONTROL         "body-as-attachment", IDC_BODY_AS_ATTACHMENT,
                     "Button", BS_AUTOCHECKBOX | WS_TABSTOP,
-                    24, 125, 215, 10
+                    24, 103, 215, 10
  
     /* Stuff at the lower left corner.  */
     LTEXT           "GpgOL by g10 Code GmbH", IDC_G10CODE_STRING, 
diff --git a/src/explorers.cpp b/src/explorers.cpp
new file mode 100644 (file)
index 0000000..5e686e4
--- /dev/null
@@ -0,0 +1,164 @@
+/* explorers.cpp - Code to handle the OOM Explorers
+ *     Copyright (C) 2009 g10 Code 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/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <windows.h>
+#include <olectl.h>
+
+#include "common.h"
+#include "oomhelp.h"
+#include "explorers.h"
+#include "dialogs.h"  /* IDB_xxx */
+#include "cmdbarcontrols.h"
+
+#include "eventsink.h"
+
+BEGIN_EVENT_SINK(GpgolExplorersEvents, IOOMExplorersEvents)
+  STDMETHOD (NewExplorer) (THIS_ LPOOMEXPLORER);
+EVENT_SINK_DEFAULT_DTOR(GpgolExplorersEvents)
+EVENT_SINK_INVOKE(GpgolExplorersEvents)
+{
+  HRESULT hr;
+  (void)lcid; (void)riid; (void)result; (void)exepinfo; (void)argerr;
+
+  if (dispid == 0xf001 && (flags & DISPATCH_METHOD))
+    {
+      if (!parms) 
+        hr = DISP_E_PARAMNOTOPTIONAL;
+      else if (parms->cArgs != 1)
+        hr = DISP_E_BADPARAMCOUNT;
+      else if (parms->rgvarg[0].vt != VT_DISPATCH)
+        hr = DISP_E_BADVARTYPE;
+      else
+        hr = NewExplorer ((LPOOMEXPLORER)parms->rgvarg[0].pdispVal);
+    }
+  else
+    hr = DISP_E_MEMBERNOTFOUND;
+  return hr;
+}
+END_EVENT_SINK(GpgolExplorersEvents, IID_IOOMExplorersEvents)
+
+
+\f
+
+/* The method called by outlook for each new explorer.  Note that
+   Outlook sometimes reuses Inspectro objects thus this event is not
+   an indication for a newly opened Explorer.  */
+STDMETHODIMP
+GpgolExplorersEvents::NewExplorer (LPOOMEXPLORER explorer)
+{
+  log_debug ("%s:%s: Called", SRCNAME, __func__);
+
+  add_explorer_controls (explorer);
+  return S_OK;
+}
+
+
+/* Add buttons to the explorer.  */
+void
+add_explorer_controls (LPOOMEXPLORER explorer)
+{
+  LPDISPATCH pObj, pDisp, pTmp;
+
+  log_debug ("%s:%s: Enter", SRCNAME, __func__);
+
+  /* In theory we should take a lock here to avoid a race between the
+     test for a new control and the creation.  However, we are not
+     called from a second thread.  */
+
+  /* Check that our controls do not already exist.  */
+  pObj = get_oom_object (explorer, "CommandBars");
+  if (!pObj)
+    {
+      log_debug ("%s:%s: CommandBars not found", SRCNAME, __func__);
+      return;
+    }
+  pDisp = get_oom_control_bytag (pObj, "GpgOL_Start_Key_Manager");
+  pObj->Release ();
+  pObj = NULL;
+  if (pDisp)
+    {
+      pDisp->Release ();
+      log_debug ("%s:%s: Leave (Controls are already added)",
+                 SRCNAME, __func__);
+      return;
+    }
+
+  /* Fixme: To avoid an extra lookup we should use the CommandBars
+     object to start the search for the controls.  I tried this but
+     Outlooked crashed.  Quite likely my error but I was not able to
+     find the problem.  */
+
+  /* Create the Start-Key-Manager menu entry.  */
+  pDisp = get_oom_object (explorer,
+                          "CommandBars.FindControl(,30007).get_Controls");
+  if (!pDisp)
+    log_debug ("%s:%s: Menu Popup Extras not found\n", SRCNAME, __func__);
+  else
+    {
+      pTmp = add_oom_button (pDisp);
+      pDisp->Release ();
+      pDisp = pTmp;
+      if (pDisp)
+        {
+          put_oom_string (pDisp, "Tag", "GpgOL_Start_Key_Manager");
+          put_oom_int (pDisp, "Style", msoButtonIconAndCaption );
+          put_oom_string (pDisp, "Caption", _("GnuPG Certificate &Manager"));
+          put_oom_string (pDisp, "TooltipText",
+                          _("Open the certificate manager"));
+          put_oom_icon (pDisp, IDB_KEY_MANAGER, 16);
+          
+          install_GpgolCommandBarButtonEvents_sink (pDisp);
+          pDisp->Release ();
+        }
+    }
+
+  /* Create the Start-Key-Manager toolbar icon.  Not ethat we need to
+     use a different tag name here.  If we won't do that event sink
+     would be called twice.  */
+  pDisp = get_oom_object (explorer,
+                          "CommandBars.Item(Standard).get_Controls");
+  if (!pDisp)
+    log_debug ("%s:%s: CommandBar \"Standard\" not found\n",
+               SRCNAME, __func__);
+  else
+    {
+      pTmp = add_oom_button (pDisp);
+      pDisp->Release ();
+      pDisp = pTmp;
+      if (pDisp)
+        {
+          put_oom_string (pDisp, "Tag", "GpgOL_Start_Key_Manager@t");
+          put_oom_int (pDisp, "Style", msoButtonIcon );
+          put_oom_string (pDisp, "TooltipText",
+                          _("Open the certificate manager"));
+          put_oom_icon (pDisp, IDB_KEY_MANAGER, 16);
+          
+          install_GpgolCommandBarButtonEvents_sink (pDisp);
+          /* Fixme:  store the event sink object somewhere.  */
+          pDisp->Release ();
+        }
+    }
+  
+  log_debug ("%s:%s: Leave", SRCNAME, __func__);
+}
+
diff --git a/src/explorers.h b/src/explorers.h
new file mode 100644 (file)
index 0000000..7554d15
--- /dev/null
@@ -0,0 +1,91 @@
+/* explorers.h - Defs to handle the OOM Explorers
+ *     Copyright (C) 2009 g10 Code 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 EXPLORERS_H
+#define EXPLORERS_H
+
+#include "myexchext.h"
+
+DEFINE_OLEGUID(IID_IOOMExplorer,              0x00063003, 0, 0);
+DEFINE_OLEGUID(IID_IOOMExplorers,             0x0006300A, 0, 0);
+DEFINE_OLEGUID(IID_IOOMExplorersEvents,       0x00063078, 0, 0);
+
+
+typedef struct IOOMExplorer IOOMExplorer;
+typedef IOOMExplorer *LPOOMEXPLORER;
+
+typedef struct IOOMExplorersEvents IOOMExplorersEvents;
+typedef IOOMExplorersEvents *LPOOMEXPLORERSEVENTS;
+
+
+EXTERN_C const IID IID_IOOMExplorer;
+#undef INTERFACE
+#define INTERFACE  IOOMExplorer
+DECLARE_INTERFACE_(IOOMExplorer, IDispatch)
+{
+  /*** IUnknown methods ***/
+  STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * lppvObj) PURE;
+  STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+  STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+  /*** IDispatch methods ***/
+  STDMETHOD(GetTypeInfoCount)(THIS_ UINT*) PURE;
+  STDMETHOD(GetTypeInfo)(THIS_ UINT, LCID, LPTYPEINFO*) PURE;
+  STDMETHOD(GetIDsOfNames)(THIS_ REFIID, LPOLESTR*, UINT, LCID, DISPID*) PURE;
+  STDMETHOD(Invoke)(THIS_ DISPID, REFIID, LCID, WORD,
+                    DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*) PURE;
+
+  /*** IOOM_Explorer methods ***/
+  /* Activate, Close, .... */
+};
+
+
+EXTERN_C const IID IID_IOOMExplorersEvents;
+#undef INTERFACE
+#define INTERFACE  IOOMExplorersEvents
+DECLARE_INTERFACE_(IOOMExplorersEvents, IDispatch)
+{
+  /*** IUnknown methods ***/
+  STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * lppvObj) PURE;
+  STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+  STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+  /*** IDispatch methods ***/
+  STDMETHOD(GetTypeInfoCount)(THIS_ UINT*) PURE;
+  STDMETHOD(GetTypeInfo)(THIS_ UINT, LCID, LPTYPEINFO*) PURE;
+  STDMETHOD(GetIDsOfNames)(THIS_ REFIID, LPOLESTR*, UINT, LCID, DISPID*) PURE;
+  STDMETHOD(Invoke)(THIS_ DISPID, REFIID, LCID, WORD,
+                    DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*) PURE;
+
+  /*** IOOMExplorersEvents methods ***/
+  /* dispid=0xf001 */
+  STDMETHOD(NewExplorer)(THIS_ LPOOMEXPLORER) PURE;
+};
+
+
+/* Install an explorers collection event sink in OBJ.  Returns the
+   event sink object which must be released by the caller if it is not
+   anymore required.  */
+LPDISPATCH install_GpgolExplorersEvents_sink (LPDISPATCH obj);
+
+void add_explorer_controls (LPOOMEXPLORER explorer);
+
+
+
+#endif /*EXPLORERS_H*/
index 09b4ad3..befdf60 100644 (file)
@@ -40,6 +40,7 @@
 #include "engine.h"
 #include "ext-commands.h"
 #include "revert.h"
+#include "explorers.h"
 
 #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \
                                      SRCNAME, __func__, __LINE__); \
@@ -103,9 +104,7 @@ GpgolExtCommands::GpgolExtCommands (GpgolExt* pParentInterface)
   m_nCmdProtoSmime = 0;
   m_nCmdEncrypt = 0;  
   m_nCmdSign = 0; 
-  m_nCmdKeyManager = 0;
   m_nCmdRevertFolder = 0;
-  m_nCmdCryptoState = 0;
   m_nCmdDebug0 = 0;
   m_nCmdDebug1 = 0;
   m_nCmdDebug2 = 0;
@@ -213,88 +212,6 @@ check_menu (LPEXCHEXTCALLBACK eecb, UINT menu_id, int checked)
 }
 
 
-static void
-check_toolbar (LPEXCHEXTCALLBACK eecb, struct toolbar_info_s *toolbar_info,
-               UINT cmd_id, int checked)
-{
-  HWND hwnd;
-  toolbar_info_t tb_info;
-  TBBUTTONINFOA tbb;
-
-  eecb->GetToolbar (EETBID_STANDARD, &hwnd);
-  if (debug_commands)
-    log_debug ("check_toolbar: eecb=%p cmd_id=%u checked=%d -> hwnd=%p\n", 
-               eecb, cmd_id, checked, hwnd);
-
-  for (tb_info = toolbar_info; tb_info; tb_info = tb_info->next )
-    if (tb_info->cmd_id == cmd_id)
-      break;
-  if (!tb_info)
-    {
-      log_error ("check_toolbar: no such toolbar button");
-      return;
-    }
-  if (!tb_info->did_qbi)
-    {
-      if(debug_commands)
-        log_debug ("check_toolbar: button(cmd_id=%d) not yet initialized",
-                   cmd_id);
-      return;
-    }
-
-  tbb.cbSize = sizeof (tbb);
-  tbb.dwMask = TBIF_COMMAND | TBIF_STATE | TBIF_STYLE;
-  if (!SendMessage (hwnd, TB_GETBUTTONINFO, cmd_id, (LPARAM)&tbb))
-    log_error_w32 (-1, "TB_GETBUTTONINFO failed");
-  else
-    {
-      tbb.cbSize = sizeof (tbb);
-      tbb.dwMask = TBIF_STATE;
-      if (checked)
-        tbb.fsState |= TBSTATE_CHECKED;
-      else
-        tbb.fsState &= ~TBSTATE_CHECKED;
-      if (!SendMessage (hwnd, TB_SETBUTTONINFO, cmd_id, (LPARAM)&tbb))
-        log_error_w32 (-1, "TB_SETBUTTONINFO failed");
-    }
-}
-
-
-static void
-check_menu_toolbar (LPEXCHEXTCALLBACK eecb,
-                    struct toolbar_info_s *toolbar_info,
-                    UINT cmd_id, int checked)
-{
-  check_menu (eecb, cmd_id, checked);
-  check_toolbar (eecb, toolbar_info, cmd_id, checked);
-}
-
-
-void
-GpgolExtCommands::update_protocol_menu (LPEXCHEXTCALLBACK eecb)
-{
-  if (debug_commands)
-    log_debug ("update_protocol_menu called\n");
-  switch (m_pExchExt->m_protoSelection)
-    {
-    case PROTOCOL_OPENPGP:
-      check_menu_toolbar (eecb, m_toolbar_info, m_nCmdProtoAuto, FALSE);
-      check_menu_toolbar (eecb, m_toolbar_info, m_nCmdProtoPgpmime, TRUE);
-      check_menu_toolbar (eecb, m_toolbar_info, m_nCmdProtoSmime, FALSE);
-      break;
-    case PROTOCOL_SMIME:
-      check_menu_toolbar (eecb, m_toolbar_info, m_nCmdProtoAuto, FALSE);
-      check_menu_toolbar (eecb, m_toolbar_info, m_nCmdProtoPgpmime, FALSE);
-      check_menu_toolbar (eecb, m_toolbar_info, m_nCmdProtoSmime, TRUE);
-      break;
-    default:
-      check_menu_toolbar (eecb, m_toolbar_info, m_nCmdProtoAuto, TRUE);
-      check_menu_toolbar (eecb, m_toolbar_info, m_nCmdProtoPgpmime, FALSE);
-      check_menu_toolbar (eecb, m_toolbar_info, m_nCmdProtoSmime, FALSE);
-      break;
-    }
-}
-
 
 void
 GpgolExtCommands::add_toolbar (LPTBENTRY tbearr, UINT n_tbearr, ...)
@@ -365,7 +282,6 @@ GpgolExtCommands::add_toolbar (LPTBENTRY tbearr, UINT n_tbearr, ...)
 
 
 
-
 /* Called by Exchange to install commands and toolbar buttons.  Returns
    S_FALSE to signal Exchange to continue calling extensions. */
 STDMETHODIMP 
@@ -396,6 +312,7 @@ GpgolExtCommands::InstallCommands (
     log_debug ("%s:%s: context=%s flags=0x%lx\n", SRCNAME, __func__, 
                ext_context_name (m_lContext), lFlags);
 
+  show_event_object (eecb, __func__);
 
   /* Outlook 2003 sometimes displays the plaintext and sometimes the
      original undecrypted text when doing a reply.  This seems to
@@ -509,44 +426,8 @@ GpgolExtCommands::InstallCommands (
   /* Now install menu and toolbar items.  */
   if (m_lContext == EECONTEXT_READNOTEMESSAGE)
     {
-      int is_encrypted = 0;
-      int not_a_gpgol_message = 0;
-      
-      LPMDB mdb = NULL;
-      LPMESSAGE message = NULL;
-
-      hr = eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
-      if (FAILED(hr))
-        log_debug ("%s:%s: getObject failed: hr=%#lx\n", SRCNAME, __func__, hr);
-      else
-        {
-          switch (mapi_get_message_type (message))
-            {
-            case MSGTYPE_GPGOL_MULTIPART_ENCRYPTED:
-            case MSGTYPE_GPGOL_OPAQUE_ENCRYPTED:
-            case MSGTYPE_GPGOL_PGP_MESSAGE:
-              is_encrypted = 1;
-              if ( mapi_test_sig_status (message) )
-                is_encrypted++;
-              break;
-            case MSGTYPE_GPGOL:
-            case MSGTYPE_SMIME:
-            case MSGTYPE_UNKNOWN:
-              not_a_gpgol_message = 1;
-              break;
-            default:
-              break;
-            }
-        }
-      ul_release (message, __func__, __LINE__);
-      ul_release (mdb, __func__, __LINE__);
-      
       add_menu (eecb, pnCommandIDBase,
         "@", NULL,
-        (opt.disable_gpgol || not_a_gpgol_message)?
-                "" : _("GpgOL Decrypt/Verify"), &m_nCmdCryptoState,
-        opt.enable_debug? "GpgOL Debug-0 (display crypto info)":"", 
-                &m_nCmdDebug0,
         (opt.enable_debug && !opt.disable_gpgol)?
                 "GpgOL Debug-1 (open_inspector)":"", &m_nCmdDebug1,
         (opt.enable_debug && !opt.disable_gpgol)? 
@@ -555,58 +436,21 @@ GpgolExtCommands::InstallCommands (
                 &m_nCmdDebug3,
         NULL);
 
-      if (!opt.disable_gpgol && !not_a_gpgol_message)
-        add_toolbar (pTBEArray, nTBECnt, 
-                     is_encrypted == 2 
-                     ? _("This is a signed and encrypted message.\n"
-                         "Click for more information. ")
-                     : is_encrypted
-                     ? _("This is an encrypted message.\n"
-                         "Click for more information. ")
-                     : _("This is a signed message.\n"
-                       "Click for more information. "),
-                     IDB_CRYPTO_STATE, m_nCmdCryptoState,
-                     NULL, 0, 0);
-
     }
   else if (m_lContext == EECONTEXT_SENDNOTEMESSAGE && !opt.disable_gpgol) 
     {
       add_menu (eecb, pnCommandIDBase,
         "@", NULL,
-        _(">GnuPG protocol"), NULL,
-        _("auto"),   &m_nCmdProtoAuto,        
-        _("PGP/MIME"),&m_nCmdProtoPgpmime,        
-        _("S/MIME"), &m_nCmdProtoSmime,        
-          "<", NULL,
         _("&encrypt message with GnuPG"), &m_nCmdEncrypt,
         _("&sign message with GnuPG"), &m_nCmdSign,
         NULL );
 
-      /* We display the protocol icons only for Outlook 2007 becuase
-         there seems to be no way to add a plain menu item. */
-      if (get_ol_main_version () > 11)
-        add_toolbar (pTBEArray, nTBECnt,
-                     "Encrypt", IDB_ENCRYPT, m_nCmdEncrypt,
-                     "Sign",    IDB_SIGN,    m_nCmdSign,
-                     "Autoselect", IDB_PROTO_AUTO, m_nCmdProtoAuto,
-                     "Use PGP/MIME", IDB_PROTO_PGPMIME, m_nCmdProtoPgpmime,
-                     "Use/MIME", IDB_PROTO_SMIME, m_nCmdProtoSmime,
-                     NULL, 0, 0);
-      else
         add_toolbar (pTBEArray, nTBECnt,
                      "Encrypt", IDB_ENCRYPT, m_nCmdEncrypt,
                      "Sign",    IDB_SIGN,    m_nCmdSign,
                      NULL, 0, 0);
       
-      if (draft_info && strlen (draft_info) >= 3 && draft_info[2] == 'A')
-        m_pExchExt->m_protoSelection = PROTOCOL_UNKNOWN;
-      else if (draft_info && strlen (draft_info) >= 3 && draft_info[2] == 'P')
-        m_pExchExt->m_protoSelection = PROTOCOL_OPENPGP;
-      else if (draft_info && strlen (draft_info) >= 3 && draft_info[2] == 'X')
-        m_pExchExt->m_protoSelection = PROTOCOL_SMIME;
-      else
-        m_pExchExt->m_protoSelection = opt.default_protocol;
-      update_protocol_menu (eecb);
+      m_pExchExt->m_protoSelection = opt.default_protocol;
 
       if (draft_info && draft_info[0] == 'E')
         m_pExchExt->m_gpgEncrypt = true;
@@ -631,13 +475,9 @@ GpgolExtCommands::InstallCommands (
     {
       add_menu (eecb, pnCommandIDBase, 
         "@", NULL,
-        _("GnuPG Certificate &Manager"), &m_nCmdKeyManager,
         _("Remove GpgOL flags from this folder"), &m_nCmdRevertFolder,
         NULL);
 
-      add_toolbar (pTBEArray, nTBECnt, 
-        _("Open the certificate manager"), IDB_KEY_MANAGER, m_nCmdKeyManager,
-        NULL, 0, 0);
     }
 
   xfree (draft_info);
@@ -664,6 +504,8 @@ GpgolExtCommands::DoCommand (LPEXCHEXTCALLBACK eecb, UINT nCommandID)
                SRCNAME, __func__, nCommandID, nCommandID, 
                ext_context_name (m_lContext), hwnd);
 
+  show_event_object (eecb, __func__);
+
   if (nCommandID == SC_CLOSE && m_lContext == EECONTEXT_READNOTEMESSAGE)
     {
       /* This is the system close command. Replace it with our own to
@@ -733,57 +575,6 @@ GpgolExtCommands::DoCommand (LPEXCHEXTCALLBACK eecb, UINT nCommandID)
         log_debug ("%s:%s: command Forward called\n", SRCNAME, __func__);
       return S_FALSE; /* Pass it on.  */
     }
-  else if (nCommandID == m_nCmdCryptoState
-           && m_lContext == EECONTEXT_READNOTEMESSAGE)
-    {
-      log_debug ("%s:%s: command CryptoState called\n", SRCNAME, __func__);
-      hr = eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
-      if (SUCCEEDED (hr))
-        {
-          if (message_incoming_handler (message, hwnd, true))
-            message_display_handler (eecb, hwnd);
-       }
-      else
-        log_debug_w32 (hr, "%s:%s: command CryptoState failed", 
-                       SRCNAME, __func__);
-      ul_release (message, __func__, __LINE__);
-      ul_release (mdb, __func__, __LINE__);
-    }
-  else if (nCommandID == m_nCmdProtoAuto
-           && m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
-    {
-      log_debug ("%s:%s: command ProtoAuto called\n", SRCNAME, __func__);
-      m_pExchExt->m_protoSelection = PROTOCOL_UNKNOWN;
-      update_protocol_menu (eecb);
-    }
-  else if (nCommandID == m_nCmdProtoPgpmime
-           && m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
-    {
-      log_debug ("%s:%s: command ProtoPgpmime called\n", SRCNAME, __func__);
-      m_pExchExt->m_protoSelection = PROTOCOL_OPENPGP;
-      update_protocol_menu (eecb);
-    }
-  else if (nCommandID == m_nCmdProtoSmime
-           && m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
-    {
-      log_debug ("%s:%s: command ProtoSmime called\n", SRCNAME, __func__);
-      if (opt.enable_smime)
-        {
-          m_pExchExt->m_protoSelection = PROTOCOL_SMIME;
-          update_protocol_menu (eecb);
-        }
-      else
-        {
-          MessageBox (hwnd,
-                      _("Support for S/MIME has not been enabled.\n"
-                        "\n"
-                        "To enable S/MIME support, open the option dialog"
-                        " and check \"Enable the S/MIME support\".  The"
-                        " option dialog can be found in the main menu at:"
-                       " Extras->Options->GpgOL.\n"),
-                      "GpgOL", MB_ICONHAND|MB_OK);
-        }
-    }
   else if (nCommandID == m_nCmdEncrypt
            && m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
     {
@@ -798,14 +589,6 @@ GpgolExtCommands::DoCommand (LPEXCHEXTCALLBACK eecb, UINT nCommandID)
       m_pExchExt->m_gpgSign = !m_pExchExt->m_gpgSign;
       check_menu (eecb, m_nCmdSign, m_pExchExt->m_gpgSign);
     }
-  else if (nCommandID == m_nCmdKeyManager
-           && m_lContext == EECONTEXT_VIEWER)
-    {
-      log_debug ("%s:%s: command KeyManager called\n", SRCNAME, __func__);
-      if (engine_start_keymanager (hwnd))
-        MessageBox (NULL, _("Could not start certificate manager"),
-                    _("GpgOL"), MB_ICONERROR|MB_OK);
-    }
   else if (nCommandID == m_nCmdRevertFolder
            && m_lContext == EECONTEXT_VIEWER)
     {
@@ -953,28 +736,9 @@ GpgolExtCommands::Help (LPEXCHEXTCALLBACK eecb, UINT nCommandID)
 {
   (void)eecb;
 
-  if (nCommandID == m_nCmdProtoAuto
-           && m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
-    {
-      MessageBox (m_hWnd,
-                 _("Select this option to automatically select the protocol."),
-                  "GpgOL", MB_OK);     
-    } 
-  else if (nCommandID == m_nCmdProtoPgpmime
-           && m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
-    {
-      MessageBox (m_hWnd,
-                  _("Select this option to select the PGP/MIME protocol."),
-                  "GpgOL", MB_OK);     
-    } 
-  else if (nCommandID == m_nCmdProtoSmime
-           && m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
-    {
-      MessageBox (m_hWnd,
-                  _("Select this option to select the S/MIME protocol."),
-                  "GpgOL", MB_OK);     
-    } 
-  else if (nCommandID == m_nCmdEncrypt 
+  show_event_object (eecb, __func__);
+
+  if (nCommandID == m_nCmdEncrypt 
            && m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
     {
       MessageBox (m_hWnd,
@@ -988,13 +752,6 @@ GpgolExtCommands::Help (LPEXCHEXTCALLBACK eecb, UINT nCommandID)
                   _("Select this option to sign the message."),
                   "GpgOL", MB_OK);     
     }
-  else if (nCommandID == m_nCmdKeyManager
-           && m_lContext == EECONTEXT_VIEWER) 
-    {
-      MessageBox (m_hWnd,
-                  _("Select this option to open the certificate manager"),
-                  "GpgOL", MB_OK);
-    }
   else
     return S_FALSE;
 
@@ -1014,38 +771,8 @@ STDMETHODIMP
 GpgolExtCommands::QueryHelpText(UINT nCommandID, ULONG lFlags,
                                 LPTSTR pszText,  UINT nCharCnt)    
 {
-       
-  if (nCommandID == m_nCmdProtoAuto
-           && m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
-    {
-      if (lFlags == EECQHT_STATUS)
-        lstrcpyn (pszText, ".", nCharCnt);
-      if (lFlags == EECQHT_TOOLTIP)
-        lstrcpyn (pszText,
-                  _("Automatically select the protocol for sign/encrypt"),
-                  nCharCnt);
-    }
-  else if (nCommandID == m_nCmdProtoPgpmime
-           && m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
-    {
-      if (lFlags == EECQHT_STATUS)
-        lstrcpyn (pszText, ".", nCharCnt);
-      if (lFlags == EECQHT_TOOLTIP)
-        lstrcpyn (pszText,
-                  _("Use PGP/MIME for sign/encrypt"),
-                  nCharCnt);
-    }
-  else if (nCommandID == m_nCmdProtoSmime
-           && m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
-    {
-      if (lFlags == EECQHT_STATUS)
-        lstrcpyn (pszText, ".", nCharCnt);
-      if (lFlags == EECQHT_TOOLTIP)
-        lstrcpyn (pszText,
-                  _("Use S/MIME for sign/encrypt"),
-                  nCharCnt);
-    }
-  else if (nCommandID == m_nCmdEncrypt
+
+  if (nCommandID == m_nCmdEncrypt
            && m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
     {
       if (lFlags == EECQHT_STATUS)
@@ -1065,16 +792,6 @@ GpgolExtCommands::QueryHelpText(UINT nCommandID, ULONG lFlags,
                   _("Sign message with GnuPG"),
                   nCharCnt);
     }
-  else if (nCommandID == m_nCmdKeyManager
-           && m_lContext == EECONTEXT_VIEWER) 
-    {
-      if (lFlags == EECQHT_STATUS)
-        lstrcpyn (pszText, ".", nCharCnt);
-      if (lFlags == EECQHT_TOOLTIP)
-        lstrcpyn (pszText,
-                  _("Open the GpgOL certificate manager"),
-                  nCharCnt);
-    }
   else 
     return S_FALSE;
 
@@ -1144,25 +861,6 @@ GpgolExtCommands::QueryButtonInfo (ULONG toolbarid, UINT buttonid,
       if (m_pExchExt->m_gpgSign)
         pTBB->fsState |= TBSTATE_CHECKED;
     }
-  else if (tb_info->cmd_id == m_nCmdProtoAuto)
-    {
-      pTBB->fsStyle |= TBSTYLE_CHECK;
-      if (m_pExchExt->m_protoSelection != PROTOCOL_OPENPGP
-          && m_pExchExt->m_protoSelection != PROTOCOL_SMIME)
-        pTBB->fsState |= TBSTATE_CHECKED;
-    }
-  else if (tb_info->cmd_id == m_nCmdProtoPgpmime)
-    {
-      pTBB->fsStyle |= TBSTYLE_CHECK;
-      if (m_pExchExt->m_protoSelection == PROTOCOL_OPENPGP)
-        pTBB->fsState |= TBSTATE_CHECKED;
-    }
-  else if (tb_info->cmd_id == m_nCmdProtoSmime)
-    {
-      pTBB->fsStyle |= TBSTYLE_CHECK;
-      if (m_pExchExt->m_protoSelection == PROTOCOL_SMIME)
-        pTBB->fsState |= TBSTATE_CHECKED;
-    }
 
   return S_OK;
 }
index 8ba7e34..bce887f 100644 (file)
@@ -45,9 +45,7 @@ private:
   UINT  m_nCmdProtoSmime;
   UINT  m_nCmdEncrypt;
   UINT  m_nCmdSign;
-  UINT  m_nCmdKeyManager;
   UINT  m_nCmdRevertFolder;
-  UINT  m_nCmdCryptoState;
   UINT  m_nCmdDebug0;
   UINT  m_nCmdDebug1;
   UINT  m_nCmdDebug2;
diff --git a/src/inspectors.cpp b/src/inspectors.cpp
new file mode 100644 (file)
index 0000000..4309c19
--- /dev/null
@@ -0,0 +1,496 @@
+/* inspectors.cpp - Code to handle OOM Inspectors
+ *     Copyright (C) 2009 g10 Code 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/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <windows.h>
+#include <olectl.h>
+
+#include "common.h"
+#include "oomhelp.h"
+#include "myexchext.h"
+#include "inspectors.h"
+#include "dialogs.h"  /* IDB_xxx */
+#include "cmdbarcontrols.h"
+
+#include "eventsink.h"
+
+\f
+/* Event sink for an Inspectors collection object.  */
+BEGIN_EVENT_SINK(GpgolInspectorsEvents, IOOMInspectorsEvents)
+  STDMETHOD (NewInspector) (THIS_ LPOOMINSPECTOR);
+EVENT_SINK_DEFAULT_DTOR(GpgolInspectorsEvents)
+EVENT_SINK_INVOKE(GpgolInspectorsEvents)
+{
+  HRESULT hr;
+  (void)lcid; (void)riid; (void)result; (void)exepinfo; (void)argerr;
+  
+  if (dispid == 0xf001 && (flags & DISPATCH_METHOD))
+    {
+      if (!parms) 
+        hr = DISP_E_PARAMNOTOPTIONAL;
+      else if (parms->cArgs != 1)
+        hr = DISP_E_BADPARAMCOUNT;
+      else if (parms->rgvarg[0].vt != VT_DISPATCH)
+        hr = DISP_E_BADVARTYPE;
+      else
+        hr = NewInspector ((LPOOMINSPECTOR)parms->rgvarg[0].pdispVal);
+    }
+  else
+    hr = DISP_E_MEMBERNOTFOUND;
+  return hr;
+}
+END_EVENT_SINK(GpgolInspectorsEvents, IID_IOOMInspectorsEvents)
+
+
+\f
+/* Event sink for an Inspector object.  */
+BEGIN_EVENT_SINK(GpgolInspectorEvents, IOOMInspectorEvents)
+  STDMETHOD_ (void, Activate) (THIS_);
+  STDMETHOD_ (void, Close) (THIS_);
+  STDMETHOD_ (void, Deactivate) (THIS_);
+EVENT_SINK_DEFAULT_DTOR(GpgolInspectorEvents)
+EVENT_SINK_INVOKE(GpgolInspectorEvents)
+{
+  HRESULT hr = S_OK;
+  (void)lcid; (void)riid; (void)result; (void)exepinfo; (void)argerr;
+  
+  if ((dispid == 0xf001 || dispid == 0xf006 || dispid == 0xf008)
+      && (flags & DISPATCH_METHOD))
+    {
+      if (!parms) 
+        hr = DISP_E_PARAMNOTOPTIONAL;
+      else if (parms->cArgs != 0)
+        hr = DISP_E_BADPARAMCOUNT;
+      else if (dispid == 0xf001)
+        Activate ();
+      else if (dispid == 0xf006)
+        Deactivate ();
+      else if (dispid == 0xf008)
+        Close ();
+    }
+  else
+    hr = DISP_E_MEMBERNOTFOUND;
+  return hr;
+}
+END_EVENT_SINK(GpgolInspectorEvents, IID_IOOMInspectorEvents)
+
+
+\f
+/* To avoid messing around with the OOM (adding extra objects as user
+   properties and such), we keep our own information structure about
+   inspectors. */
+struct inspector_info_s
+{
+  /* We are pretty lame and keep all inspectors in a linked list.  */
+  struct inspector_info_s *next;
+
+  /* The inspector object.  */
+  LPOOMINSPECTOR inspector;
+
+  /* The event sink object.  This is used by the event methods to
+     locate the inspector object.  */
+  LPOOMINSPECTOREVENTS eventsink;
+
+  /* The event sink object for the crypto info button.  */
+  LPDISPATCH crypto_info_sink;
+
+};
+typedef struct inspector_info_s *inspector_info_t;
+
+/* The list of all inspectors and a lock for it.  */
+static inspector_info_t all_inspectors;
+static HANDLE all_inspectors_lock;
+
+/* Initialize this module.  Returns 0 on success.  Called once by dllinit.  */
+int
+initialize_inspectors (void)
+{
+  SECURITY_ATTRIBUTES sa;
+  
+  memset (&sa, 0, sizeof sa);
+  sa.bInheritHandle = FALSE;
+  sa.lpSecurityDescriptor = NULL;
+  sa.nLength = sizeof sa;
+  all_inspectors_lock = CreateMutex (&sa, FALSE, NULL);
+  return !all_inspectors_lock;
+}
+
+
+/* Acquire the all_inspectors_lock.  No error is returned because we
+   can't do anything anyway.  */
+static void
+lock_all_inspectors (void)
+{
+  int ec = WaitForSingleObject (all_inspectors_lock, INFINITE);
+  if (ec != WAIT_OBJECT_0)
+    {
+      log_error ("%s:%s: waiting on mutex failed: ec=%#x\n", 
+                 SRCNAME, __func__, ec);
+      fatal_error ("%s:%s: waiting on mutex failed: ec=%#x\n", 
+                   SRCNAME, __func__, ec);
+    }
+}
+
+
+/* Release the all_inspectors_lock.  No error is returned because this
+   is a fatal error anyway and there is no way to clean up.  */
+static void
+unlock_all_inspectors (void)
+{
+  if (!ReleaseMutex (all_inspectors_lock))
+    {
+      log_error_w32 (-1, "%s:%s: ReleaseMutex failed", SRCNAME, __func__);
+      fatal_error ("%s:%s: ReleaseMutex failed", SRCNAME, __func__);
+    }
+}
+
+
+/* Register the inspector object INSPECTOR along with its event SINK.  */
+static void
+register_inspector (LPOOMINSPECTOR inspector, LPOOMINSPECTOREVENTS sink)
+{
+  inspector_info_t item;
+
+  item = (inspector_info_t)xcalloc (1, sizeof *item);
+  lock_all_inspectors ();
+  inspector->AddRef ();
+  item->inspector = inspector;
+
+  sink->AddRef ();
+  item->eventsink = sink;
+
+  item->next = all_inspectors;
+  all_inspectors = item;
+
+  unlock_all_inspectors ();
+}
+
+
+/* Deregister the inspector with the event SINK.  */
+static void
+deregister_inspector (LPOOMINSPECTOREVENTS sink)
+{
+  inspector_info_t r, rprev;
+
+  if (!sink)
+    return;
+
+  lock_all_inspectors ();
+  for (r = all_inspectors, rprev = NULL; r; rprev = r, r = r->next)
+    if (r->eventsink == sink)
+      {
+        if (!rprev)
+          all_inspectors = r->next;
+        else
+          rprev->next = r->next;
+        r->next = NULL;
+        break; 
+      }
+  unlock_all_inspectors ();
+  if (!r)
+    {
+      log_error ("%s:%s: inspector not registered", SRCNAME, __func__);
+      return;
+    }
+  r->eventsink->Release ();
+  r->eventsink = NULL;
+  if (r->inspector)
+    r->inspector->Release ();
+  if (r->crypto_info_sink)
+    r->crypto_info_sink->Release ();
+  xfree (r);
+}
+
+
+/* Return the inspector info for INSPECTOR.  On success the
+   ALL_INSPECTORS list is locked and thus the caller should call
+   unlock_all_inspectors as soon as possible.  On error NULL is
+   returned and the caller must *not* call unlock_all_inspectors.  */
+static inspector_info_t
+get_inspector_info (LPOOMINSPECTOR inspector)
+{
+  inspector_info_t r;
+
+  if (!inspector)
+    return NULL;
+
+  lock_all_inspectors ();
+  for (r = all_inspectors; r; r = r->next)
+    if (r->inspector == inspector)
+      return r;
+  unlock_all_inspectors ();
+  return NULL;
+}
+
+
+
+/* The method called by outlook for each new inspector.  Note that
+   Outlook sometimes reuses Inspectro objects thus this event is not
+   an indication for a newly opened Inspector.  */
+STDMETHODIMP
+GpgolInspectorsEvents::NewInspector (LPOOMINSPECTOR inspector)
+{
+  LPDISPATCH obj;
+  log_debug ("%s:%s: Called", SRCNAME, __func__);
+
+  /* It has been said that INSPECTOR here a "weak" reference. This may
+     mean that the object has not been fully initialized.  So better
+     take some care here and also take an additional reference.  */
+  inspector->AddRef ();
+  obj = install_GpgolInspectorEvents_sink ((LPDISPATCH)inspector);
+  if (obj)
+    {
+      register_inspector (inspector, (LPOOMINSPECTOREVENTS)obj);
+      obj->Release ();
+      add_inspector_controls (inspector);
+    }
+  inspector->Release ();
+  return S_OK;
+}
+
+
+/* The method is called by an inspector before closing.  */
+STDMETHODIMP_(void)
+GpgolInspectorEvents::Close (void)
+{
+  log_debug ("%s:%s: Called", SRCNAME, __func__);
+  /* Deregister the inspector and free outself.  */
+  deregister_inspector (this);
+  this->Release ();
+}
+
+
+/* The method called by an inspector on activation.  */
+STDMETHODIMP_(void)
+GpgolInspectorEvents::Activate (void)
+{
+  LPDISPATCH obj, button;
+
+  log_debug ("%s:%s: Called", SRCNAME, __func__);
+
+  /* Note: It is easier to use the registered inspector object than to
+     find the inspector object in the ALL_INSPECTORS list.  The
+     ALL_INSPECTORS list primarly useful to keep track of additional
+     information, not directly related to the event sink. */
+  if (!m_object)
+    {
+      log_error ("%s:%s: Object not set", SRCNAME, __func__);
+      return;
+    }
+
+  /* Update the crypt info.  */
+  obj = get_oom_object (m_object, "CommandBars");
+  if (!obj)
+    log_error ("%s:%s: CommandBars not found", SRCNAME, __func__);
+  else
+    {
+      button = get_oom_control_bytag (obj, "GpgOL_Inspector_Crypto_Info");
+      obj->Release ();
+      if (button)
+        {
+          update_inspector_crypto_info (button);
+          button->Release ();
+        }
+    }
+}
+
+
+/* The method called by an inspector on dectivation.  */
+STDMETHODIMP_(void)
+GpgolInspectorEvents::Deactivate (void)
+{
+  log_debug ("%s:%s: Called", SRCNAME, __func__);
+
+}
+
+
+
+
+
+void
+add_inspector_controls (LPOOMINSPECTOR inspector)
+{
+  LPDISPATCH pObj, pDisp, pTmp;
+  inspector_info_t inspinfo;
+
+  log_debug ("%s:%s: Enter", SRCNAME, __func__);
+
+  /* In theory we should take a lock here to avoid a race between the
+     test for a new control and the creation.  However, we are not
+     called from a second thread.  FIXME: We might want to use
+     inspector_info insteasd to check this.  However this requires us
+     to keep a lock per inspector. */
+
+  /* Check that our controls do not already exist.  */
+  pObj = get_oom_object (inspector, "CommandBars");
+  if (!pObj)
+    {
+      log_debug ("%s:%s: CommandBars not found", SRCNAME, __func__);
+      return;
+    }
+  pDisp = get_oom_control_bytag (pObj, "GpgOL_Inspector_Crypto_Info");
+  pObj->Release ();
+  pObj = NULL;
+  if (pDisp)
+    {
+      pDisp->Release ();
+      log_debug ("%s:%s: Leave (Controls are already added)",
+                 SRCNAME, __func__);
+      return;
+    }
+
+  /* Create our controls.  */
+  pDisp = get_oom_object (inspector,
+                          "CommandBars.Item(Standard).get_Controls");
+  if (!pDisp)
+    log_debug ("%s:%s: CommandBar \"Standard\" not found\n",
+               SRCNAME, __func__);
+  else
+    {
+      pTmp = add_oom_button (pDisp);
+      pDisp->Release ();
+      pDisp = pTmp;
+      if (pDisp)
+        {
+          put_oom_string (pDisp, "Tag", "GpgOL_Inspector_Crypto_Info");
+          put_oom_int (pDisp, "Style", msoButtonIcon );
+          put_oom_string (pDisp, "TooltipText",
+                          _("Indicates the crypto status of the message"));
+          put_oom_icon (pDisp, IDB_SIGN, 16);
+          
+          pObj = install_GpgolCommandBarButtonEvents_sink (pDisp);
+          pDisp->Release ();
+          inspinfo = get_inspector_info (inspector);
+          if (inspinfo)
+            {
+              inspinfo->crypto_info_sink = pObj;
+              unlock_all_inspectors ();
+            }
+          else
+            {
+              log_error ("%s:%s: inspector not registered", SRCNAME, __func__);
+              pObj->Release (); /* Get rid of the sink.  */
+            }
+        }
+    }
+
+  /* FIXME: Menuswe need to add: */
+        // (opt.disable_gpgol || not_a_gpgol_message)?
+        //         "" : _("GpgOL Decrypt/Verify"), &m_nCmdCryptoState,
+        // opt.enable_debug? "GpgOL Debug-0 (display crypto info)":"", 
+        //         &m_nCmdDebug0,
+
+
+    
+  log_debug ("%s:%s: Leave", SRCNAME, __func__);
+}
+
+
+/* Update the crypto info icon.  */
+void
+update_inspector_crypto_info (LPDISPATCH button)
+{
+  LPDISPATCH obj;
+  char *msgcls = NULL;;
+  const char *s;
+  int in_composer = 0;
+  int is_encrypted = 0;
+  int is_signed = 0;
+  const char *tooltip;
+  int iconrc;
+
+  /* FIXME: We should store the information retrieved by old
+     versions via mapi_get_message_type and mapi_test_sig_status
+     in UserProperties and use them instead of a direct lookup of
+     the messageClass.  */
+  obj = get_oom_object (button, "get_Parent.get_Parent.get_CurrentItem");
+  if (obj)
+    {
+      msgcls = get_oom_string (obj, "MessageClass");
+      /* If "Sent" is false we are in composer mode  */
+      in_composer = !get_oom_bool (obj, "Sent");
+      obj->Release ();
+    }
+  if (msgcls)
+    {
+      log_debug ("%s:%s: message class is `%s'", SRCNAME, __func__, msgcls);
+      if (!strncmp (msgcls, "IPM.Note.GpgOL", 14) 
+          && (!msgcls[14] || msgcls[14] == '.'))
+        {
+          s = msgcls + 14;
+          if (!*s)
+            ;
+          else if (!strcmp (s, ".MultipartSigned"))
+            is_signed = 1;
+          else if (!strcmp (s, ".MultipartEncrypted"))
+            is_encrypted = 1;
+          else if (!strcmp (s, ".OpaqueSigned"))
+            is_signed = 1;
+          else if (!strcmp (s, ".OpaqueEncrypted"))
+            is_encrypted = 1;
+          else if (!strcmp (s, ".ClearSigned"))
+            is_signed = 1;
+          else if (!strcmp (s, ".PGPMessage"))
+            is_encrypted = 1;
+        }
+      
+      /*FIXME: check something like mail_test_sig_status to see
+        whether it is an encrypted and signed message.  */
+      
+      if (in_composer)
+        {
+          tooltip = "";
+          iconrc = -1;
+        }
+      else if (is_signed && is_encrypted)
+        {
+          tooltip =  _("This is a signed and encrypted message.\n"
+                       "Click for more information. ");
+          iconrc = IDB_DECRYPT_VERIFY;
+        }
+      else if (is_signed)
+        {
+          tooltip =  _("This is a signed message.\n"
+                       "Click for more information. ");
+          iconrc = IDB_VERIFY;
+        }
+      else if (is_encrypted)
+        {
+          tooltip =  _("This is an encrypted message.\n"
+                       "Click for more information. ");
+          iconrc = IDB_DECRYPT;
+        }
+      else
+        {
+          tooltip = "";
+          iconrc = -1;
+        }
+      
+      put_oom_string (button, "TooltipText", tooltip);
+      if (iconrc != -1)
+        put_oom_icon (button, iconrc, 16);
+      put_oom_bool (button, "Visible", (iconrc != -1));
+      
+      xfree (msgcls);
+    }
+}
+
diff --git a/src/inspectors.h b/src/inspectors.h
new file mode 100644 (file)
index 0000000..3436a7d
--- /dev/null
@@ -0,0 +1,132 @@
+/* inspectors.h - Defs to handle the OOM Inspectors
+ *     Copyright (C) 2009 g10 Code 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 INSPECTORS_H
+#define INSPECTORS_H
+
+#include "myexchext.h"
+
+
+DEFINE_OLEGUID(IID_IOOMInspector,             0x00063005, 0, 0);
+DEFINE_OLEGUID(IID_IOOMInspectorEvents,       0x0006302A, 0, 0);
+DEFINE_OLEGUID(IID_IOOMInspectors,            0x00063008, 0, 0);
+DEFINE_OLEGUID(IID_IOOMInspectorsEvents,      0x00063079, 0, 0);
+
+typedef struct IOOMInspector IOOMInspector;
+typedef IOOMInspector *LPOOMINSPECTOR;
+
+typedef struct IOOMInspectorEvents IOOMInspectorEvents;
+typedef IOOMInspectorEvents *LPOOMINSPECTOREVENTS;
+
+typedef struct IOOMInspectorsEvents IOOMInspectorsEvents;
+typedef IOOMInspectorsEvents *LPOOMINSPECTORSEVENTS;
+
+EXTERN_C const IID IID_IOOMInspector;
+#undef INTERFACE
+#define INTERFACE  IOOMInspector
+DECLARE_INTERFACE_(IOOMInspector, IDispatch)
+{
+  /*** IUnknown methods ***/
+  STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * lppvObj) PURE;
+  STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+  STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+  /*** IDispatch methods ***/
+  STDMETHOD(GetTypeInfoCount)(THIS_ UINT*) PURE;
+  STDMETHOD(GetTypeInfo)(THIS_ UINT, LCID, LPTYPEINFO*) PURE;
+  STDMETHOD(GetIDsOfNames)(THIS_ REFIID, LPOLESTR*, UINT, LCID, DISPID*) PURE;
+  STDMETHOD(Invoke)(THIS_ DISPID, REFIID, LCID, WORD,
+                    DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*) PURE;
+
+  /*** IOOM_Inspector methods ***/
+  /* Fixme: Don't know.  */
+};
+
+
+EXTERN_C const IID IID_IOOMInspectorEvents;
+#undef INTERFACE
+#define INTERFACE  IOOMInspectorEvents
+DECLARE_INTERFACE_(IOOMInspectorEvents, IDispatch)
+{
+  /*** IUnknown methods ***/
+  STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * lppvObj) PURE;
+  STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+  STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+  /*** IDispatch methods ***/
+  STDMETHOD(GetTypeInfoCount)(THIS_ UINT*) PURE;
+  STDMETHOD(GetTypeInfo)(THIS_ UINT, LCID, LPTYPEINFO*) PURE;
+  STDMETHOD(GetIDsOfNames)(THIS_ REFIID, LPOLESTR*, UINT, LCID, DISPID*) PURE;
+  STDMETHOD(Invoke)(THIS_ DISPID, REFIID, LCID, WORD,
+                    DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*) PURE;
+
+  /*** IOOM_Inspector methods ***/
+  /* dispid=0xf001 */
+  STDMETHOD_(void, Activate)(THIS_);
+  /* dispid=0xfa11 */
+  STDMETHODIMP(BeforeMaximize)(THIS_ PBOOL);
+  /* dispid=0xfa12 */
+  STDMETHODIMP(BeforeMinimize)(THIS_ PBOOL);
+  /* dispid=0xfa13 */
+  STDMETHODIMP(BeforeMove)(THIS_ PBOOL);
+  /* dispid=0xfa14 */
+  STDMETHODIMP(BeforeSize)(THIS_ PBOOL);
+  /* dispid=0xf008 */
+  STDMETHOD_(void, Close)(THIS_);
+  /* dispid=0xf006 */
+  STDMETHOD_(void, Deactivate)(THIS_);
+};
+
+
+EXTERN_C const IID IID_IOOMInspectorsEvents;
+#undef INTERFACE
+#define INTERFACE  IOOMInspectorsEvents
+DECLARE_INTERFACE_(IOOMInspectorsEvents, IDispatch)
+{
+  /*** IUnknown methods ***/
+  STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * lppvObj) PURE;
+  STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
+  STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+  /*** IDispatch methods ***/
+  STDMETHOD(GetTypeInfoCount)(THIS_ UINT*) PURE;
+  STDMETHOD(GetTypeInfo)(THIS_ UINT, LCID, LPTYPEINFO*) PURE;
+  STDMETHOD(GetIDsOfNames)(THIS_ REFIID, LPOLESTR*, UINT, LCID, DISPID*) PURE;
+  STDMETHOD(Invoke)(THIS_ DISPID, REFIID, LCID, WORD,
+                    DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*) PURE;
+
+  /*** IOOMInspectorsEvents methods ***/
+  /* dispid=0xf001 */
+  STDMETHOD(NewInspector)(THIS_ LPOOMINSPECTOR) PURE;
+};
+
+
+LPDISPATCH install_GpgolInspectorsEvents_sink (LPDISPATCH object);
+
+LPDISPATCH install_GpgolInspectorEvents_sink (LPDISPATCH object);
+
+
+void add_inspector_controls (LPOOMINSPECTOR inspector);
+
+void update_inspector_crypto_info (LPDISPATCH button);
+
+
+
+
+#endif /*INSPECTORS_H*/
index f3cfce3..7d1fcaf 100644 (file)
@@ -61,4 +61,4 @@ class GpgolItemEvents : public IOutlookExtItemEvents
   STDMETHODIMP OnCloseComplete (LPEXCHEXTCALLBACK peecb, ULONG flags);
 };
 
-#endif /*ATTACHED_FILE_EVENTS_H*/
+#endif /*ITEM_EVENTS_H*/
diff --git a/src/key-manager-mask.bmp b/src/key-manager-mask.bmp
new file mode 100644 (file)
index 0000000..a5a5e30
Binary files /dev/null and b/src/key-manager-mask.bmp differ
diff --git a/src/key-manager.bmp b/src/key-manager.bmp
new file mode 100644 (file)
index 0000000..6ee81ca
Binary files /dev/null and b/src/key-manager.bmp differ
index f30f2bd..8960f39 100644 (file)
@@ -31,7 +31,6 @@
 #include "msgcache.h"
 #include "mymapi.h"
 
-
 /* The malloced name of the logfile and the logging stream.  If
    LOGFILE is NULL, no logging is done. */
 static char *logfile;
@@ -176,6 +175,8 @@ DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved)
         return FALSE;
       if (initialize_msgcache ())
         return FALSE;
+      if (initialize_inspectors ())
+        return FALSE;
       init_options ();
     }
   else if (reason == DLL_PROCESS_DETACH)
@@ -587,15 +588,16 @@ read_options (void)
   opt.enable_smime = (!val || atoi (val));
   xfree (val); val = NULL;
   
-  load_extension_value ("defaultProtocol", &val);
-  switch ((!val || *val == '0')? 0 : atol (val))
-    {
-    case 1: opt.default_protocol = PROTOCOL_OPENPGP; break;
-    case 2: opt.default_protocol = PROTOCOL_SMIME; break;
-    case 0:
-    default: opt.default_protocol = PROTOCOL_UNKNOWN /*(auto*)*/; break;
-    }
-  xfree (val); val = NULL;
+/*   load_extension_value ("defaultProtocol", &val); */
+/*   switch ((!val || *val == '0')? 0 : atol (val)) */
+/*     { */
+/*     case 1: opt.default_protocol = PROTOCOL_OPENPGP; break; */
+/*     case 2: opt.default_protocol = PROTOCOL_SMIME; break; */
+/*     case 0: */
+/*     default: opt.default_protocol = PROTOCOL_UNKNOWN /\*(auto*)*\/; break; */
+/*     } */
+/*   xfree (val); val = NULL; */
+  opt.default_protocol = PROTOCOL_UNKNOWN; /* (auto)*/
 
   load_extension_value ("encryptDefault", &val);
   opt.encrypt_default = val == NULL || *val != '1'? 0 : 1;
@@ -710,7 +712,7 @@ write_options (void)
     char *s_val;
   } table[] = {
     {"enableSmime",              0, opt.enable_smime},
-    {"defaultProtocol",          3, opt.default_protocol},
+/*     {"defaultProtocol",          3, opt.default_protocol}, */
     {"encryptDefault",           0, opt.encrypt_default},
     {"signDefault",              0, opt.sign_default},
     {"previewDecrypt",           0, opt.preview_decrypt},
@@ -752,19 +754,19 @@ write_options (void)
                      table[i].name, string);
           rc = store_extension_value (table[i].name, string);
           break;
-        case 3:
-          buf[0] = '0';
-          buf[1] = 0;
-          switch (opt.default_protocol)
-            {
-            case PROTOCOL_UNKNOWN: buf[0] = '0'; /* auto */ break;
-            case PROTOCOL_OPENPGP: buf[0] = '1'; break;
-            case PROTOCOL_SMIME:   buf[0] = '2'; break;
-            }
-          log_debug ("storing option `%s' value=`%s'\n",
-                     table[i].name, buf);
-          rc = store_extension_value (table[i].name, buf);
-          break;  
+/*         case 3: */
+/*           buf[0] = '0'; */
+/*           buf[1] = 0; */
+/*           switch (opt.default_protocol) */
+/*             { */
+/*             case PROTOCOL_UNKNOWN: buf[0] = '0'; /\* auto *\/ break; */
+/*             case PROTOCOL_OPENPGP: buf[0] = '1'; break; */
+/*             case PROTOCOL_SMIME:   buf[0] = '2'; break; */
+/*             } */
+/*           log_debug ("storing option `%s' value=`%s'\n", */
+/*                      table[i].name, buf); */
+/*           rc = store_extension_value (table[i].name, buf); */
+/*           break;   */
 
         default:
           rc = -1;
index 5d6db2c..ded7527 100644 (file)
@@ -38,6 +38,7 @@
 #include "message.h"
 #include "message-events.h"
 
+#include "explorers.h"
 
 #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \
                                      SRCNAME, __func__, __LINE__); \
@@ -98,76 +99,6 @@ GpgolMessageEvents::QueryInterface (REFIID riid, LPVOID FAR *ppvObj)
 }
 
 
-#if 0
-#warning  test code
-static void
-show_event_object (LPEXCHEXTCALLBACK eecb)
-{
-  HRESULT hr;
-  LPOUTLOOKEXTCALLBACK outlook_cb;
-  LPUNKNOWN obj;
-  LPDISPATCH disp;
-  LPTYPEINFO tinfo;
-  BSTR bstrname;
-  char *name;
-
-  outlook_cb = NULL;
-  eecb->QueryInterface(IID_IOutlookExtCallback, (void **)&outlook_cb);
-  if (!outlook_cb)
-    {
-      log_debug ("%s%s: no outlook callback found\n", SRCNAME, __func__);
-      return;
-    }
-               
-  obj = NULL;
-  outlook_cb->GetObject (&obj);
-  if (!obj)
-    {
-      log_debug ("%s%s: no object found for event\n", SRCNAME, __func__);
-      outlook_cb->Release ();
-      return;
-    }
-
-  disp = NULL;
-  obj->QueryInterface (IID_IDispatch, (void **)&disp);
-  obj->Release ();
-  obj = NULL;
-  if (!disp)
-    {
-      log_debug ("%s%s: no dispatcher found for event\n", SRCNAME, __func__);
-      outlook_cb->Release ();
-      return;
-    }
-
-  tinfo = NULL;
-  disp->GetTypeInfo (0, 0, &tinfo);
-  if (!tinfo)
-    {
-      log_debug ("%s%s: no dispatcher found for event\n", SRCNAME, __func__);
-      disp->Release ();
-      outlook_cb->Release ();
-      return;
-    }
-
-  name = NULL;
-  hr = tinfo->GetDocumentation (MEMBERID_NIL, &bstrname, 0, 0, 0);
-  if (hr)
-    log_debug ("%s%s: GetDocumentation failed: hr=%#lx\n", 
-               SRCNAME, __func__, hr);
-
-  name = wchar_to_utf8 (bstrname);
-  SysFreeString (bstrname);
-  log_debug ("%s:%s: event fired by item type `%s'\n",
-             SRCNAME, __func__, name);
-  xfree (name);
-
-  disp->Release ();
-  outlook_cb->Release ();
-}
-#endif /* Test code */
-
-
-
 /* Called from Exchange on reading a message.  Returns: S_FALSE to
    signal Exchange to continue calling extensions.  EECB is a pointer
    to the IExchExtCallback interface. */
@@ -187,7 +118,8 @@ GpgolMessageEvents::OnRead (LPEXCHEXTCALLBACK eecb)
   log_debug ("%s:%s: received (hwnd=%p) %s\n", 
              SRCNAME, __func__, hwnd, m_gotinspector? "got_inspector":"");
 
-//   show_event_object (eecb);
+  show_event_object (eecb, __func__);
+  //add_oom_command_button (eecb);
 
   /* Fixme: If preview decryption is not enabled and we have an
      encrypted message, we might want to show a greyed out preview
@@ -218,7 +150,7 @@ GpgolMessageEvents::OnRead (LPEXCHEXTCALLBACK eecb)
         default:
           ;
         }
-      
+
       ul_release (message, __func__, __LINE__);
       ul_release (mdb, __func__, __LINE__);
     }
@@ -236,6 +168,8 @@ GpgolMessageEvents::OnReadComplete (LPEXCHEXTCALLBACK eecb, ULONG flags)
   log_debug ("%s:%s: received; flags=%#lx m_processed=%d \n",
              SRCNAME, __func__, flags, m_processed);
 
+  show_event_object (eecb, __func__);
+
   /* If the message has been processed by us (i.e. in OnRead), we now
      use our own display code.  */
   if (!flags && m_processed && !opt.disable_gpgol)
index db099d1..2fbf446 100644 (file)
@@ -80,7 +80,7 @@ message_incoming_handler (LPMESSAGE message, HWND hwnd, bool force)
          latter decrypt command or when viewed a second time all has
          been set.  Note that we should have similar code for some
          message classes in GpgolUserEvents:OnSelectionChange; but
-         tehre are a couple of problems.  */
+         there are a couple of problems.  */
       if (pass == 1 && !force && !mapi_has_sig_status (message)
           && !opt.disable_gpgol)
         {
index c370bda..b988ccf 100644 (file)
@@ -1060,7 +1060,7 @@ finalize_message (LPMESSAGE message, mapi_attach_item_t *att_table,
     return -1;
 
   /* We also need to set the message class into our custom
-     property. This override is at leas required for encrypted
+     property. This override is at least required for encrypted
      messages.  */
   if (mapi_set_gpgol_msg_class (message,
                                 (encrypt? 
index 74f1143..6c4f7d2 100644 (file)
@@ -9,6 +9,7 @@
  * 2005-09-18  Add IExchExtAttachedFileEvents.
  * 2007-07-18  Add IExchExtUserEvents and IExchExtSessionEvents.
  * 2007-07-20  Add IOutlookExtItemEvents.
+ * 2009-10-21  Move generic COM_ stuff to oomhelp.h
  */
 
 #ifndef EXCHEXT_H
@@ -22,10 +23,9 @@ extern "C" {
 #endif
 
 #include <commctrl.h>
-#include <unknwn.h>
+#include "oomhelp.h"
 #include "mymapi.h"
 
-
 /* Constants used by Install. */
 #define EECONTEXT_SESSION               0x00000001
 #define EECONTEXT_VIEWER                0x00000002
@@ -91,11 +91,6 @@ extern "C" {
 
 
 /* GUIDs */
-DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
-
-DEFINE_OLEGUID(IID_IUnknown,                  0x00000000, 0, 0);
-DEFINE_OLEGUID(IID_IDispatch,                 0x00020400, 0, 0);
-
 DEFINE_OLEGUID(IID_IExchExtCallback,          0x00020d10, 0, 0);
 DEFINE_OLEGUID(IID_IExchExt,                  0x00020d11, 0, 0);
 DEFINE_OLEGUID(IID_IExchExtCommands,          0x00020d12, 0, 0);
@@ -110,6 +105,9 @@ DEFINE_OLEGUID(IID_IExchExtModelessCallback,  0x00020d1a, 0, 0);
 DEFINE_OLEGUID(IID_IOutlookExtCallback,       0x0006720d, 0, 0);
 DEFINE_OLEGUID(IID_IOutlookExtItemEvents,     0x0006723A, 0, 0);
 
+DEFINE_OLEGUID(IID_IOOMMailItem,              0x00063034, 0, 0);
+DEFINE_OLEGUID(IID_IOOMItemEvents,            0x0006302B, 0, 0);
+
 
 /* Type definitions. */
 
@@ -161,7 +159,6 @@ typedef IOutlookExtCallback *LPOUTLOOKEXTCALLBACK;
 typedef struct IOutlookExtItemEvents IOutlookExtItemEvents;
 typedef IOutlookExtItemEvents *LPOUTLOOKEXTITEMEVENTS;
 
-
 /* The next classes are not yet defined. but if so they should go here. */
 typedef struct IExchExtModeless IExchExtModeless; 
 typedef IExchExtModeless *LPEXCHEXTMODELESS;
index a34cc38..fa5d310 100644 (file)
@@ -56,9 +56,6 @@ ul_release (LPVOID punk, const char *func, int lnr)
 
 
 
-
-
-
 /* Locate a property using the provided callback LPEECB and traverse
    down to the last element of the dot delimited NAME.  Returns the
    Dispatch object and if R_DISPID is not NULL, the dispatch-id of the
@@ -76,7 +73,7 @@ find_outlook_property (LPEXCHEXTCALLBACK lpeecb,
   wchar_t *wname;
   const char *s;
 
-  // log_debug ("%s:%s: looking for `%s'\n", SRCNAME, __func__, name);
+  log_debug ("%s:%s: looking for `%s'\n", SRCNAME, __func__, name);
 
   pCb = NULL;
   pObj = NULL;
@@ -85,36 +82,90 @@ find_outlook_property (LPEXCHEXTCALLBACK lpeecb,
     pCb->GetObject (&pObj);
   for (; pObj && (s = strchr (name, '.')) && s != name; name = s + 1)
     {
-      DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
       VARIANT vtResult;
+      char namepart[100];
+      size_t n;
+      char *p, *pend;
+      BSTR parmstr = NULL;
 
       /* Our loop expects that all objects except for the last one are
          of class IDispatch.  This is pretty reasonable. */
       pObj->QueryInterface (IID_IDispatch, (LPVOID*)&pDisp);
       if (!pDisp)
         return NULL;
-      
-      wname = utf8_to_wchar2 (name, s-name);
+
+      n = s - name;
+      if (n >= sizeof namepart)
+        n = sizeof namepart - 1;
+      strncpy (namepart, name, n);
+      namepart[n] = 0;
+
+      /* Parse a parameter (like "Print" in "Item(Print)").  */
+      p = strchr (namepart, '(');
+      if (p)
+        {
+          *p++ = 0;
+          pend = strchr (p, ')');
+          if (pend)
+            *pend = 0;
+          wname = utf8_to_wchar (p);
+          if (wname)
+            {
+              log_debug ("   parm(%s)=(%s)\n", namepart, p);
+              parmstr = SysAllocString (wname);
+              xfree (wname);
+            }
+        }
+
+      wname = utf8_to_wchar (namepart);
       if (!wname)
-        return NULL;
+        {
+          if (parmstr)
+            SysFreeString (parmstr);
+          return NULL;
+        }
 
       hr = pDisp->GetIDsOfNames(IID_NULL, &wname, 1,
                                 LOCALE_SYSTEM_DEFAULT, &dispid);
       xfree (wname);
-      //log_debug ("   dispid(%.*s)=%d  (hr=0x%x)\n",
-      //           (int)(s-name), name, dispid, hr);
+      log_debug ("   dispid(%s)=%d  (hr=0x%x)\n",
+                 namepart, (int)dispid, (unsigned int)hr);
+
       vtResult.pdispVal = NULL;
-      hr = pDisp->Invoke (dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
-                          DISPATCH_METHOD, &dispparamsNoArgs,
-                          &vtResult, NULL, NULL);
+      if (parmstr)
+        {
+          DISPPARAMS dispparams;
+          VARIANT aVariant[4];
+
+          dispparams.rgvarg = aVariant;
+          dispparams.rgvarg[0].vt = VT_BSTR;
+          dispparams.rgvarg[0].bstrVal = parmstr;
+          dispparams.cArgs = 1;
+          dispparams.cNamedArgs = 0;
+          hr = pDisp->Invoke (dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
+                              DISPATCH_METHOD|DISPATCH_PROPERTYGET,
+                              &dispparams, &vtResult, NULL, NULL);
+          SysFreeString (parmstr);
+        }
+      else
+        {
+          DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
+
+          hr = pDisp->Invoke (dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
+                              DISPATCH_METHOD, &dispparamsNoArgs,
+                              &vtResult, NULL, NULL);
+        }
+
       pObj = vtResult.pdispVal;
       /* FIXME: Check that the class of the returned object is as
          expected.  To do this we better let GetIdsOfNames also return
          the ID of "Class". */
-      //log_debug ("%s:%s: %.*s=%p  (hr=0x%x)\n",
-      //           SRCNAME, __func__, (int)(s-name), name, pObj, hr);
+      log_debug ("   %s=%p vt=%d (hr=0x%x)\n",
+                 namepart, pObj, vtResult.vt, (unsigned int)hr);
       pDisp->Release ();
       pDisp = NULL;
+      if (vtResult.vt != VT_DISPATCH)
+        return NULL;
       /* Fixme: Do we need to release pObj? */
     }
   if (!pObj || !*name)
@@ -133,12 +184,12 @@ find_outlook_property (LPEXCHEXTCALLBACK lpeecb,
   hr = pDisp->GetIDsOfNames (IID_NULL, &wname, 1,
                              LOCALE_SYSTEM_DEFAULT, &dispid);
   xfree (wname);
-  //log_debug ("   dispid(%s)=%d  (hr=0x%x)\n", name, dispid, hr);
+  log_debug ("   dispid(%s)=%d  (hr=0x%x)\n", name, (int)dispid, (int)hr);
   if (r_dispid)
     *r_dispid = dispid;
 
-  //log_debug ("%s:%s:    got IDispatch=%p dispid=%u\n",
-  //        SRCNAME, __func__, pDisp, (unsigned int)dispid);
+  log_debug ("%s:%s:    got IDispatch=%p dispid=%u\n",
+            SRCNAME, __func__, pDisp, (unsigned int)dispid);
   return pDisp;
 }
 
@@ -155,7 +206,6 @@ put_outlook_property (void *pEECB, const char *key, const char *value)
   DISPID dispid_put = DISPID_PROPERTYPUT;
   DISPPARAMS dispparams;
   VARIANT aVariant;
-
   if (!pEECB)
     return -1;
 
@@ -368,10 +418,10 @@ show_preview_pane (LPEXCHEXTCALLBACK eecb, int visible)
     }
 
   dispparams.rgvarg = aVariant;
-  dispparams.rgvarg[0].vt = VT_INT;
-  dispparams.rgvarg[0].intVal = 3; /* olPreview */
-  dispparams.rgvarg[1].vt = VT_BOOL;
-  dispparams.rgvarg[1].boolVal = !!visible;
+  dispparams.rgvarg[0].vt = VT_BOOL;
+  dispparams.rgvarg[0].boolVal = !!visible;
+  dispparams.rgvarg[1].vt = VT_INT;
+  dispparams.rgvarg[1].intVal = 3; /* olPreview */
   dispparams.cArgs = 2;
   dispparams.cNamedArgs = 0;
   hr = pDisp->Invoke (dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
@@ -384,3 +434,186 @@ show_preview_pane (LPEXCHEXTCALLBACK eecb, int visible)
                SRCNAME, __func__, visible, hr);
 }
 
+
+
+void
+show_event_object (LPEXCHEXTCALLBACK eecb, const char *description)
+{
+#if 1
+  (void)eecb;
+  (void)description;
+#else
+  HRESULT hr;
+  LPOUTLOOKEXTCALLBACK outlook_cb;
+  LPUNKNOWN obj;
+  LPDISPATCH disp;
+  LPTYPEINFO tinfo;
+  BSTR bstrname;
+  char *name;
+
+  log_debug ("%s:%s: looking for origin of event: %s\n", 
+             SRCNAME, __func__, description);
+
+  outlook_cb = NULL;
+  eecb->QueryInterface(IID_IOutlookExtCallback, (void **)&outlook_cb);
+  if (!outlook_cb)
+    {
+      log_debug ("%s%s: no outlook callback found\n", SRCNAME, __func__);
+      return;
+    }
+               
+  obj = NULL;
+  outlook_cb->GetObject (&obj);
+  if (!obj)
+    {
+      log_debug ("%s%s: no object found for event\n", SRCNAME, __func__);
+      outlook_cb->Release ();
+      return;
+    }
+
+  disp = NULL;
+  obj->QueryInterface (IID_IDispatch, (void **)&disp);
+  obj->Release ();
+  obj = NULL;
+  if (!disp)
+    {
+      log_debug ("%s%s: no dispatcher found for event\n", SRCNAME, __func__);
+      outlook_cb->Release ();
+      return;
+    }
+
+  tinfo = NULL;
+  disp->GetTypeInfo (0, 0, &tinfo);
+  if (!tinfo)
+    {
+      log_debug ("%s%s: no typeinfo found for dispatcher\n", 
+                 SRCNAME, __func__);
+      disp->Release ();
+      outlook_cb->Release ();
+      return;
+    }
+
+  bstrname = NULL;
+  hr = tinfo->GetDocumentation (MEMBERID_NIL, &bstrname, 0, 0, 0);
+  if (hr || !bstrname)
+    log_debug ("%s%s: GetDocumentation failed: hr=%#lx\n", 
+               SRCNAME, __func__, hr);
+
+  if (bstrname)
+    {
+      name = wchar_to_utf8 (bstrname);
+      SysFreeString (bstrname);
+      log_debug ("%s:%s: event fired by item type `%s'\n",
+                 SRCNAME, __func__, name);
+      xfree (name);
+    }
+
+  disp->Release ();
+  outlook_cb->Release ();
+#endif
+}
+
+\f
+/* 
+   Test code
+ */
+void
+add_oom_command_button (LPEXCHEXTCALLBACK eecb)
+{
+  HRESULT hr;      
+  LPUNKNOWN pObj;
+  LPDISPATCH pDisp;
+  DISPID dispid;
+  DISPPARAMS dispparams;
+  VARIANT aVariant[5];
+  VARIANT rVariant;
+  const char name[] = 
+    "Application.ActiveExplorer.CommandBars.Item(Standard).FindControl";
+
+  log_debug ("%s:%s: ENTER", SRCNAME, __func__);
+  pDisp = find_outlook_property (eecb, name, &dispid);
+  if (!pDisp)
+    {
+      log_debug ("%s:%s: %s NOT found\n",
+                 SRCNAME, __func__, name);
+      return;
+    }
+
+  dispparams.rgvarg = aVariant;
+  dispparams.rgvarg[0].vt = VT_ERROR;
+  dispparams.rgvarg[0].scode = DISP_E_PARAMNOTFOUND; 
+  dispparams.rgvarg[1].vt = VT_ERROR;
+  dispparams.rgvarg[1].scode = DISP_E_PARAMNOTFOUND; 
+  dispparams.rgvarg[2].vt = VT_INT;
+  dispparams.rgvarg[2].intVal = 4; /* Print button.  */
+  dispparams.rgvarg[3].vt = VT_ERROR;
+  dispparams.rgvarg[3].scode = DISP_E_PARAMNOTFOUND; 
+  dispparams.cArgs = 4;
+  dispparams.cNamedArgs = 0;
+  rVariant.bstrVal = NULL;
+  hr = pDisp->Invoke (dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
+                      DISPATCH_METHOD, &dispparams,
+                      &rVariant, NULL, NULL);
+  pDisp->Release();
+  pDisp = NULL;
+  if (hr != S_OK)
+    {
+      log_debug ("%s:%s: invoking %s failed: %#lx",
+                 SRCNAME, __func__, name, hr);
+      return ;
+    }
+
+  log_debug ("%s:%s: invoking %s succeeded; vt is %d",
+             SRCNAME, __func__, name, rVariant.vt);
+  if (rVariant.vt == VT_DISPATCH)
+    {
+      log_debug ("%s:%s:   rVariant.pdispVal=%p", 
+                 SRCNAME, __func__, rVariant.pdispVal);
+      pObj = rVariant.pdispVal;
+      pObj->QueryInterface (IID_IDispatch, (LPVOID*)&pDisp);
+      log_debug ("%s:%s:   queryinterface=%p", 
+                 SRCNAME, __func__, pDisp);
+      if (pDisp)
+        {
+          DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
+          VARIANT rVariant2;
+          char *result;
+          wchar_t *wname;
+
+          wname = utf8_to_wchar ("Caption");
+          if (!wname)
+            return;
+
+          hr = pDisp->GetIDsOfNames(IID_NULL, &wname, 1,
+                                    LOCALE_SYSTEM_DEFAULT, &dispid);
+          xfree (wname);
+          log_debug ("   dispid(%s)=%d  (hr=0x%x)\n",
+                        "Caption", (int)dispid, (unsigned int)hr);
+          
+          rVariant2.bstrVal = NULL;
+          hr = pDisp->Invoke (dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
+                              DISPATCH_PROPERTYGET, &dispparamsNoArgs,
+                              &rVariant2, NULL, NULL);
+          if (hr != S_OK)
+            log_debug ("%s:%s: retrieving dispid failed: %#lx",
+                       SRCNAME, __func__, hr);
+          else if (rVariant2.vt != VT_BSTR)
+            log_debug ("%s:%s: id is not a string but vt %d",
+                           SRCNAME, __func__, rVariant2.vt);
+          else if (rVariant2.bstrVal)
+            {
+              result = wchar_to_utf8 (rVariant2.bstrVal);
+              log_debug ("%s:%s: `id is `%s'", SRCNAME, __func__,  result);
+              SysFreeString (rVariant2.bstrVal);
+              xfree (result);
+            }
+        }
+    }
+  else
+    log_debug ("%s:%s: ERROR: unexpected vt", SRCNAME, __func__);
+    
+  if (rVariant.vt == VT_BSTR && rVariant.bstrVal)
+    SysFreeString (rVariant.bstrVal);
+}
+
+
index b7b6e00..7964df7 100644 (file)
@@ -31,5 +31,9 @@ char *get_outlook_property (void *pEECB, const char *key);
 int is_preview_pane_visible (LPEXCHEXTCALLBACK eecb);
 void show_preview_pane (LPEXCHEXTCALLBACK eecb, int visible);
 
+void show_event_object (LPEXCHEXTCALLBACK eecb, const char *description);
+
+void add_oom_command_button (LPEXCHEXTCALLBACK eecb);
+
 
 #endif /*OL_EXT_CALLBACK_H*/
index a131837..c60c6a2 100644 (file)
@@ -47,8 +47,6 @@ set_labels (HWND dlg)
     { IDC_G_SEND,           N_("Message sending")},
     { IDC_ENCRYPT_DEFAULT,  N_("&Encrypt new messages by default")},
     { IDC_SIGN_DEFAULT,     N_("&Sign new messages by default")},
-    { IDC_OPENPGP_DEFAULT,  N_("Use PGP/MIME by default")},
-    { IDC_SMIME_DEFAULT,    N_("Use S/MIME by default")},
 
     { IDC_G_RECV,           N_("Message receiving")},
 //     { IDC_PREVIEW_DECRYPT,  N_("Also decrypt in preview window")},
@@ -75,15 +73,15 @@ GPGOptionsDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
   BOOL bMsgResult = FALSE;    
   static LPNMHDR pnmhdr;
-  static BOOL openpgp_state = FALSE;
-  static BOOL smime_state = FALSE;
+//   static BOOL openpgp_state = FALSE;
+//   static BOOL smime_state = FALSE;
   
   switch (uMsg) 
     {
     case WM_INITDIALOG:
       {
-        openpgp_state = (opt.default_protocol == PROTOCOL_OPENPGP);
-        smime_state = (opt.default_protocol == PROTOCOL_SMIME);
+//         openpgp_state = (opt.default_protocol == PROTOCOL_OPENPGP);
+//         smime_state = (opt.default_protocol == PROTOCOL_SMIME);
         
         EnableWindow (GetDlgItem (hDlg, IDC_SMIME_DEFAULT), 
                       !!opt.enable_smime);
@@ -130,8 +128,8 @@ GPGOptionsDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
            case IDC_ENABLE_SMIME:
            case IDC_ENCRYPT_DEFAULT:
            case IDC_SIGN_DEFAULT:
-           case IDC_OPENPGP_DEFAULT:
-           case IDC_SMIME_DEFAULT:
+//         case IDC_OPENPGP_DEFAULT:
+//         case IDC_SMIME_DEFAULT:
 //         case IDC_PREVIEW_DECRYPT:
              SendMessage (GetParent (hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
              break;
@@ -144,26 +142,26 @@ GPGOptionsDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
          EnableWindow (GetDlgItem (hDlg, IDC_SMIME_DEFAULT), 
                         opt.enable_smime);
        }
-      if (HIWORD (wParam) == BN_CLICKED &&
-         LOWORD (wParam) == IDC_OPENPGP_DEFAULT) 
-       {
-         openpgp_state = !openpgp_state;
-          if (openpgp_state)
-            {
-              smime_state = 0;
-              SendDlgItemMessage (hDlg, IDC_SMIME_DEFAULT, BM_SETCHECK,0,0L);
-            }
-       }
-      if (HIWORD (wParam) == BN_CLICKED &&
-         LOWORD (wParam) == IDC_SMIME_DEFAULT) 
-       {
-         smime_state = !smime_state;
-          if (smime_state)
-            {
-              openpgp_state = 0;
-              SendDlgItemMessage (hDlg, IDC_OPENPGP_DEFAULT, BM_SETCHECK,0,0L);
-            }
-       }
+//       if (HIWORD (wParam) == BN_CLICKED &&
+//       LOWORD (wParam) == IDC_OPENPGP_DEFAULT) 
+//     {
+//       openpgp_state = !openpgp_state;
+//           if (openpgp_state)
+//             {
+//               smime_state = 0;
+//               SendDlgItemMessage (hDlg, IDC_SMIME_DEFAULT, BM_SETCHECK,0,0L);
+//             }
+//     }
+//       if (HIWORD (wParam) == BN_CLICKED &&
+//       LOWORD (wParam) == IDC_SMIME_DEFAULT) 
+//     {
+//       smime_state = !smime_state;
+//           if (smime_state)
+//             {
+//               openpgp_state = 0;
+//               SendDlgItemMessage (hDlg, IDC_OPENPGP_DEFAULT, BM_SETCHECK,0,0L);
+//             }
+//     }
       if (opt.enable_debug && LOWORD (wParam) == IDC_GPG_OPTIONS)
        config_dialog_box (hDlg);
       else if (LOWORD (wParam) == IDC_GPG_CONF)
@@ -186,10 +184,10 @@ GPGOptionsDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
                               !!opt.encrypt_default, 0L);
           SendDlgItemMessage (hDlg, IDC_SIGN_DEFAULT, BM_SETCHECK, 
                               !!opt.sign_default, 0L);
-          SendDlgItemMessage (hDlg, IDC_OPENPGP_DEFAULT, BM_SETCHECK, 
-                                openpgp_state, 0L);
-          SendDlgItemMessage (hDlg, IDC_SMIME_DEFAULT, BM_SETCHECK, 
-                              smime_state, 0L);
+//           SendDlgItemMessage (hDlg, IDC_OPENPGP_DEFAULT, BM_SETCHECK, 
+//                                 openpgp_state, 0L);
+//           SendDlgItemMessage (hDlg, IDC_SMIME_DEFAULT, BM_SETCHECK, 
+//                               smime_state, 0L);
           
 //           SendDlgItemMessage (hDlg, IDC_PREVIEW_DECRYPT, BM_SETCHECK,
 //                               !!opt.preview_decrypt, 0L);
@@ -209,25 +207,11 @@ GPGOptionsDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
           opt.sign_default = !!SendDlgItemMessage 
             (hDlg, IDC_SIGN_DEFAULT, BM_GETCHECK, 0, 0L);
           
-#if 0  /* The mentioned tool is now available.  */
-          if (opt.enable_smime)
-            {
-              MessageBox (hDlg, 
-              _("You have enabled GpgOL's support for the S/MIME protocol.\n\n"
-                "New S/MIME messages are thus only viewable with GpgOL and "
-                "not anymore with Outlook's internal S/MIME support.  Those "
-                "message will even be unreadable by Outlook after GpgOL has "
-                "been deinstalled.  A tool to mitigate this problem will be "
-                "provided when GpgOL arrives at production quality status."),
-                            "GpgOL", MB_ICONINFORMATION|MB_OK);
-            }
-#endif /*0*/
-
-          if (openpgp_state)
-            opt.default_protocol = PROTOCOL_OPENPGP;
-          else if (smime_state && opt.enable_smime)
-            opt.default_protocol = PROTOCOL_SMIME;
-          else
+//           if (openpgp_state)
+//             opt.default_protocol = PROTOCOL_OPENPGP;
+//           else if (smime_state && opt.enable_smime)
+//             opt.default_protocol = PROTOCOL_SMIME;
+//           else
             opt.default_protocol = PROTOCOL_UNKNOWN;
             
 //           opt.preview_decrypt = !!SendDlgItemMessage
index 09df8c3..c35eba5 100644 (file)
@@ -49,6 +49,9 @@
 #include "attached-file-events.h"
 #include "item-events.h"
 #include "ol-ext-callback.h"
+#include "explorers.h"
+#include "inspectors.h"
+#include "cmdbarcontrols.h"
 
 /* The GUID for this plugin.  */
 #define CLSIDSTR_GPGOL   "{42d30988-1a3a-11da-c687-000d6080e735}"
@@ -68,6 +71,8 @@ DEFINE_GUID(CLSID_GPGOL, 0x42d30988, 0x1a3a, 0x11da,
 static bool g_initdll = FALSE;
 
 static void install_forms (void);
+static void install_sinks (LPEXCHEXTCALLBACK eecb);
+
 
 static char *olversion;
 
@@ -664,6 +669,13 @@ GpgolExt::Install(LPEXCHEXTCALLBACK pEECB, ULONG lContext, ULONG lFlags)
                       "GpgOL", MB_ICONSTOP|MB_OK);
         }
     }
+
+  /* If the version from the OOM is available we can assume that the
+     OOM is ready for use and thus we can install the event sinks. */
+  if (olversion)
+    {
+      install_sinks (pEECB);
+    }
   
 
   /* Check context. */
@@ -690,7 +702,7 @@ install_forms (void)
 {
   HRESULT hr;
   LPMAPIFORMCONTAINER formcontainer = NULL;
-  static char *forms[] = 
+  static char const *forms[] = 
     {
       "gpgol",
       "gpgol-ms",
@@ -760,3 +772,65 @@ install_forms (void)
 }
 
 
+\f
+static void
+install_sinks (LPEXCHEXTCALLBACK eecb)
+{
+  static int done;
+  LPOUTLOOKEXTCALLBACK pCb;
+  LPUNKNOWN rootobj;
+
+  /* We call this function just once.  */
+  if (done)
+    return;
+  done++;
+
+  log_debug ("%s:%s: Enter", SRCNAME, __func__);
+
+  pCb = NULL;
+  rootobj = NULL;
+  eecb->QueryInterface (IID_IOutlookExtCallback, (LPVOID*)&pCb);
+  if (pCb)
+    pCb->GetObject (&rootobj);
+  if (rootobj)
+    {
+      LPDISPATCH disp;
+
+      disp = get_oom_object ((LPDISPATCH)rootobj, "Application.Explorers");
+      if (!disp)
+        log_error ("%s:%s: Explorers NOT found\n", SRCNAME, __func__);
+      else
+        {
+          install_GpgolExplorersEvents_sink (disp);
+          /* Fixme: Register the event sink object somewhere.  */
+          disp->Release ();
+        }
+      
+      /* It seems that when installing this sink the first explorer
+         has already been created and thus we don't see a NewInspector
+         event.  Thus we create the controls direct.  */
+      disp = get_oom_object ((LPDISPATCH)rootobj,
+                             "Application.ActiveExplorer");
+      if (!disp)
+        log_error ("%s:%s: ActiveExplorer NOT found\n", SRCNAME, __func__);
+      else
+        {
+          add_explorer_controls ((LPOOMEXPLORER)disp);
+          disp->Release ();
+        }
+
+      disp = get_oom_object ((LPDISPATCH)rootobj, "Application.Inspectors");
+      if (!disp)
+        log_error ("%s:%s: Inspectors NOT found\n", SRCNAME, __func__);
+      else
+        {
+          install_GpgolInspectorsEvents_sink (disp);
+          /* Fixme: Register the event sink object somewhere.  */
+          disp->Release ();
+        }
+      
+      rootobj->Release ();
+    }
+  
+  log_debug ("%s:%s: Leave", SRCNAME, __func__);
+}
diff --git a/src/oomhelp.cpp b/src/oomhelp.cpp
new file mode 100644 (file)
index 0000000..d8eaaa1
--- /dev/null
@@ -0,0 +1,646 @@
+/* oomhelp.cpp - Helper functions for the Outlook Object Model
+ *     Copyright (C) 2009 g10 Code 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/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <windows.h>
+#include <olectl.h>
+
+#include "myexchext.h"
+#include "common.h"
+
+#include "oomhelp.h"
+
+
+/* Return a malloced string with the utf-8 encoded name of the object
+   or NULL if not available.  */
+char *
+get_object_name (LPUNKNOWN obj)
+{
+  HRESULT hr;
+  LPDISPATCH disp = NULL;
+  LPTYPEINFO tinfo = NULL;
+  BSTR bstrname;
+  char *name = NULL;
+
+  if (!obj)
+    goto leave;
+
+  obj->QueryInterface (IID_IDispatch, (void **)&disp);
+  if (!disp)
+    goto leave;
+
+  disp->GetTypeInfo (0, 0, &tinfo);
+  if (!tinfo)
+    {
+      log_debug ("%s:%s: no typeinfo found for object\n", 
+                 SRCNAME, __func__);
+      goto leave;
+    }
+
+  bstrname = NULL;
+  hr = tinfo->GetDocumentation (MEMBERID_NIL, &bstrname, 0, 0, 0);
+  if (hr || !bstrname)
+    log_debug ("%s:%s: GetDocumentation failed: hr=%#lx\n", 
+               SRCNAME, __func__, hr);
+  if (bstrname)
+    {
+      name = wchar_to_utf8 (bstrname);
+      SysFreeString (bstrname);
+    }
+
+ leave:
+  if (tinfo)
+    tinfo->Release ();
+  if (disp)
+    disp->Release ();
+
+  return name;
+}
+
+
+/* Lookup the dispid of object PDISP for member NAME.  Returns
+   DISPID_UNKNOWN on error.  */
+DISPID
+lookup_oom_dispid (LPDISPATCH pDisp, const char *name)
+{
+  HRESULT hr;
+  DISPID dispid;
+  wchar_t *wname;
+
+  if (!pDisp || !name)
+    return DISPID_UNKNOWN; /* Error: Invalid arg.  */
+
+  wname = utf8_to_wchar (name);
+  if (!wname)
+    return DISPID_UNKNOWN;/* Error:  Out of memory.  */
+
+  hr = pDisp->GetIDsOfNames (IID_NULL, &wname, 1, 
+                             LOCALE_SYSTEM_DEFAULT, &dispid);
+  xfree (wname);
+  if (hr != S_OK || dispid == DISPID_UNKNOWN)
+    log_debug ("%s:%s: error looking up dispid(%s)=%d: hr=0x%x\n",
+               SRCNAME, __func__, name, (int)dispid, (unsigned int)hr);
+  if (hr != S_OK)
+    dispid = DISPID_UNKNOWN;
+
+  return dispid;
+}
+
+
+/* Return the OOM object's IDispatch interface described by FULLNAME.
+   Returns NULL if not found.  PSTART is the object where the search
+   starts.  FULLNAME is a dot delimited sequence of object names.  If
+   an object name has a "(foo)" suffix this passes it as a parameter
+   to the invoke function (i.e. using (DISPATCH|PROPERTYGET)).  Object
+   names including the optional suffix are truncated at 127 byte.  */
+LPDISPATCH
+get_oom_object (LPDISPATCH pStart, const char *fullname)
+{
+  HRESULT hr;
+  LPDISPATCH pObj = pStart;
+  LPDISPATCH pDisp = NULL;
+
+  log_debug ("%s:%s: looking for %p->`%s'\n",
+             SRCNAME, __func__, pStart, fullname);
+
+  while (pObj)
+    {
+      DISPPARAMS dispparams;
+      VARIANT aVariant[4];
+      VARIANT vtResult;
+      wchar_t *wname;
+      char name[128];
+      int n_parms = 0;
+      BSTR parmstr = NULL;
+      INT  parmint = 0;
+      DISPID dispid;
+      char *p, *pend;
+      int dispmethod;
+
+      if (pDisp)
+        {
+          pDisp->Release ();
+          pDisp = NULL;
+        }
+      pObj->QueryInterface (IID_IDispatch, (LPVOID*)&pDisp);
+      if (pObj != pStart)
+        pObj->Release ();
+      pObj = NULL;
+      if (!pDisp)
+        return NULL;  /* The object has no IDispatch interface.  */
+      if (!*fullname)
+        return pDisp; /* Ready.  */
+
+      /* Break out the next name part.  */
+      {
+        const char *dot;
+        size_t n;
+        
+        dot = strchr (fullname, '.');
+        if (dot == fullname)
+          {
+            pDisp->Release ();
+            return NULL;  /* Empty name part: error.  */
+          }
+        else if (dot)
+          n = dot - fullname;
+        else
+          n = strlen (fullname);
+        
+        if (n >= sizeof name)
+          n = sizeof name - 1;
+        strncpy (name, fullname, n);
+        name[n] = 0;
+        
+        if (dot)
+          fullname = dot + 1;
+        else
+          fullname += strlen (fullname);
+      }
+      
+      if (!strncmp (name, "get_", 4) && name[4])
+        {
+          dispmethod = DISPATCH_PROPERTYGET;
+          memmove (name, name+4, strlen (name+4)+1);
+        }
+      else if ((p = strchr (name, '(')))
+        {
+          *p++ = 0;
+          pend = strchr (p, ')');
+          if (pend)
+            *pend = 0;
+
+          if (*p == ',' && p[1] != ',')
+            {
+              /* We assume this is "foo(,30007)".  I.e. the frst arg
+                 is not given and the second one is an integer.  */
+              parmint = (int)strtol (p+1, NULL, 10);
+              n_parms = 4;
+            }
+          else
+            {
+              wname = utf8_to_wchar (p);
+              if (wname)
+                {
+                  parmstr = SysAllocString (wname);
+                  xfree (wname);
+                }
+              if (!parmstr)
+                {
+                  pDisp->Release ();
+                  return NULL; /* Error:  Out of memory.  */
+                }
+              n_parms = 1;
+            }
+          dispmethod = DISPATCH_METHOD|DISPATCH_PROPERTYGET;
+        }
+      else
+        dispmethod = DISPATCH_METHOD;
+
+      /* Lookup the dispid.  */
+      dispid = lookup_oom_dispid (pDisp, name);
+      if (dispid == DISPID_UNKNOWN)
+        {
+          if (parmstr)
+            SysFreeString (parmstr);
+          pDisp->Release ();
+          return NULL;  /* Name not found.  */
+        }
+
+      /* Invoke the method.  */
+      dispparams.rgvarg = aVariant;
+      dispparams.cArgs = 0;
+      if (n_parms)
+        {
+          if (n_parms == 4)
+            {
+              dispparams.rgvarg[0].vt = VT_ERROR; 
+              dispparams.rgvarg[0].scode = DISP_E_PARAMNOTFOUND; 
+              dispparams.rgvarg[1].vt = VT_ERROR; 
+              dispparams.rgvarg[1].scode = DISP_E_PARAMNOTFOUND; 
+              dispparams.rgvarg[2].vt = VT_INT; 
+              dispparams.rgvarg[2].intVal = parmint; 
+              dispparams.rgvarg[3].vt = VT_ERROR; 
+              dispparams.rgvarg[3].scode = DISP_E_PARAMNOTFOUND; 
+              dispparams.cArgs = n_parms;
+            }
+          else if (n_parms == 1 && parmstr)
+            {
+              dispparams.rgvarg[0].vt = VT_BSTR;
+              dispparams.rgvarg[0].bstrVal = parmstr;
+              dispparams.cArgs++;
+            }
+        }
+      dispparams.cNamedArgs = 0;
+      VariantInit (&vtResult);
+      hr = pDisp->Invoke (dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
+                          dispmethod, &dispparams,
+                          &vtResult, NULL, NULL);
+      if (parmstr)
+        SysFreeString (parmstr);
+      log_debug ("%s:%s:   %s=%p vt=%d (hr=0x%x)\n",
+                 SRCNAME, __func__,
+                 name, vtResult.pdispVal, vtResult.vt, (unsigned int)hr);
+      if (hr != S_OK || vtResult.vt != VT_DISPATCH)
+        {
+          VariantClear (&vtResult);
+          if (parmstr)
+            SysFreeString (parmstr);
+          pDisp->Release ();
+          return NULL;  /* Invoke failed.  */
+        }
+
+      pObj = vtResult.pdispVal;
+    }
+
+  return NULL;
+}
+
+
+/* Helper for put_oom_icon.  */
+static int
+put_picture_or_mask (LPDISPATCH pDisp, int resource, int size, int is_mask)
+{
+  HRESULT hr;
+  PICTDESC pdesc;
+  LPDISPATCH pPict;
+  DISPID dispid_put = DISPID_PROPERTYPUT;
+  UINT fuload;
+  DISPID dispid;
+  DISPPARAMS dispparams;
+  VARIANT aVariant[2];
+
+  /* When loading the mask we need to set the monochrome flag.  We
+     better create a DIB section to avoid possible rendering
+     problems.  */
+  fuload = LR_CREATEDIBSECTION | LR_SHARED;
+  if (is_mask)
+    fuload |= LR_MONOCHROME;
+  
+  memset (&pdesc, 0, sizeof pdesc);
+  pdesc.cbSizeofstruct = sizeof pdesc;
+  pdesc.picType = PICTYPE_BITMAP;
+  pdesc.bmp.hbitmap = (HBITMAP) LoadImage (glob_hinst,
+                                           MAKEINTRESOURCE (resource),
+                                           IMAGE_BITMAP, size, size, fuload);
+  if (!pdesc.bmp.hbitmap)
+    {
+      log_error_w32 (-1, "%s:%s: LoadImage(%d) failed\n", 
+                     SRCNAME, __func__, resource);
+      return -1;
+    }
+
+  /* Wrap the image into an OLE object.  */
+  hr = OleCreatePictureIndirect (&pdesc, IID_IPictureDisp, 
+                                 TRUE, (void **) &pPict);
+  if (hr != S_OK || !pPict)
+    {
+      log_error ("%s:%s: OleCreatePictureIndirect failed: hr=%#lx\n",
+                 SRCNAME, __func__, hr);
+      return -1;
+    }
+        
+  /* Store to the Picture or Mask property of the CommandBarButton.  */
+  dispid = lookup_oom_dispid (pDisp, is_mask? "Mask":"Picture");
+
+  dispparams.rgvarg = aVariant;
+  dispparams.rgvarg[0].vt = VT_DISPATCH;
+  dispparams.rgvarg[0].pdispVal = pPict;
+  dispparams.cArgs = 1;
+  dispparams.rgdispidNamedArgs = &dispid_put;
+  dispparams.cNamedArgs = 1;
+  hr = pDisp->Invoke (dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
+                      DISPATCH_PROPERTYPUT, &dispparams,
+                      NULL, NULL, NULL);
+  if (hr != S_OK)
+    {
+      log_debug ("%s:%s: Putting icon failed: %#lx", SRCNAME, __func__, hr);
+      return -1;
+    }
+  return 0;
+}
+
+
+/* Update the icon of PDISP using the bitmap with RESOURCE ID and a
+   mask of (RESOURCE_ID+1).  SIZE specifies the size of the bitmap.
+   Return 0 on success.  */
+int
+put_oom_icon (LPDISPATCH pDisp, int resource_id, int size)
+{
+  int rc;
+  
+  rc = put_picture_or_mask (pDisp, resource_id, size, 0);
+  if (!rc)
+    rc = put_picture_or_mask (pDisp, resource_id+1, size, 1);
+  
+  return rc;
+}
+
+
+/* Set the boolean property NAME to VALUE.  */
+int
+put_oom_bool (LPDISPATCH pDisp, const char *name, int value)
+{
+  HRESULT hr;
+  DISPID dispid_put = DISPID_PROPERTYPUT;
+  DISPID dispid;
+  DISPPARAMS dispparams;
+  VARIANT aVariant[1];
+
+  dispid = lookup_oom_dispid (pDisp, name);
+  if (dispid == DISPID_UNKNOWN)
+    return -1;
+
+  dispparams.rgvarg = aVariant;
+  dispparams.rgvarg[0].vt = VT_BOOL;
+  dispparams.rgvarg[0].boolVal = value? VARIANT_TRUE:VARIANT_FALSE;
+  dispparams.cArgs = 1;
+  dispparams.rgdispidNamedArgs = &dispid_put;
+  dispparams.cNamedArgs = 1;
+  hr = pDisp->Invoke (dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
+                      DISPATCH_PROPERTYPUT, &dispparams,
+                      NULL, NULL, NULL);
+  if (hr != S_OK)
+    {
+      log_debug ("%s:%s: Putting '%s' failed: %#lx", 
+                 SRCNAME, __func__, name, hr);
+      return -1;
+    }
+  return 0;
+}
+
+
+/* Set the property NAME to VALUE.  */
+int
+put_oom_int (LPDISPATCH pDisp, const char *name, int value)
+{
+  HRESULT hr;
+  DISPID dispid_put = DISPID_PROPERTYPUT;
+  DISPID dispid;
+  DISPPARAMS dispparams;
+  VARIANT aVariant[1];
+
+  dispid = lookup_oom_dispid (pDisp, name);
+  if (dispid == DISPID_UNKNOWN)
+    return -1;
+
+  dispparams.rgvarg = aVariant;
+  dispparams.rgvarg[0].vt = VT_INT;
+  dispparams.rgvarg[0].intVal = value;
+  dispparams.cArgs = 1;
+  dispparams.rgdispidNamedArgs = &dispid_put;
+  dispparams.cNamedArgs = 1;
+  hr = pDisp->Invoke (dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
+                      DISPATCH_PROPERTYPUT, &dispparams,
+                      NULL, NULL, NULL);
+  if (hr != S_OK)
+    {
+      log_debug ("%s:%s: Putting '%s' failed: %#lx", 
+                 SRCNAME, __func__, name, hr);
+      return -1;
+    }
+  return 0;
+}
+
+
+/* Set the property NAME to STRING.  */
+int
+put_oom_string (LPDISPATCH pDisp, const char *name, const char *string)
+{
+  HRESULT hr;
+  DISPID dispid_put = DISPID_PROPERTYPUT;
+  DISPID dispid;
+  DISPPARAMS dispparams;
+  VARIANT aVariant[1];
+  BSTR bstring;
+
+  dispid = lookup_oom_dispid (pDisp, name);
+  if (dispid == DISPID_UNKNOWN)
+    return -1;
+
+  {
+    wchar_t *tmp = utf8_to_wchar (string);
+    bstring = tmp? SysAllocString (tmp):NULL;
+    xfree (tmp);
+    if (!bstring)
+      {
+        log_error_w32 (-1, "%s:%s: SysAllocString failed", SRCNAME, __func__);
+        return -1;
+      }
+  }
+
+  dispparams.rgvarg = aVariant;
+  dispparams.rgvarg[0].vt = VT_BSTR;
+  dispparams.rgvarg[0].bstrVal = bstring;
+  dispparams.cArgs = 1;
+  dispparams.rgdispidNamedArgs = &dispid_put;
+  dispparams.cNamedArgs = 1;
+  hr = pDisp->Invoke (dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
+                      DISPATCH_PROPERTYPUT, &dispparams,
+                      NULL, NULL, NULL);
+  SysFreeString (bstring);
+  if (hr != S_OK)
+    {
+      log_debug ("%s:%s: Putting '%s' failed: %#lx", 
+                 SRCNAME, __func__, name, hr);
+      return -1;
+    }
+  return 0;
+}
+
+
+/* Get the boolean property NAME of the object PDISP.  Returns False if
+   not found or if it is not a boolean property.  */
+int
+get_oom_bool (LPDISPATCH pDisp, const char *name)
+{
+  HRESULT hr;      
+  int result = 0;
+  DISPID dispid;
+  
+  dispid = lookup_oom_dispid (pDisp, name);
+  if (dispid != DISPID_UNKNOWN)
+    {
+      DISPPARAMS dispparams = {NULL, NULL, 0, 0};
+      VARIANT rVariant;
+
+      VariantInit (&rVariant);
+      hr = pDisp->Invoke (dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
+                          DISPATCH_PROPERTYGET, &dispparams,
+                          &rVariant, NULL, NULL);
+      if (hr != S_OK)
+        log_debug ("%s:%s: Property '%s' not found: %#lx",
+                   SRCNAME, __func__, name, hr);
+      else if (rVariant.vt != VT_BOOL)
+        log_debug ("%s:%s: Property `%s' is not a boolean (vt=%d)",
+                   SRCNAME, __func__, name, rVariant.vt);
+      else
+        result = !!rVariant.boolVal;
+      VariantClear (&rVariant);
+    }
+
+  return result;
+}
+
+
+/* Get the string property NAME of the object PDISP.  Returns NULL if
+   not found or if it is not a string property.  */
+char *
+get_oom_string (LPDISPATCH pDisp, const char *name)
+{
+  HRESULT hr;      
+  char *result = NULL;
+  DISPID dispid;
+  
+  dispid = lookup_oom_dispid (pDisp, name);
+  if (dispid != DISPID_UNKNOWN)
+    {
+      DISPPARAMS dispparams = {NULL, NULL, 0, 0};
+      VARIANT rVariant;
+
+      VariantInit (&rVariant);
+      hr = pDisp->Invoke (dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
+                          DISPATCH_PROPERTYGET, &dispparams,
+                          &rVariant, NULL, NULL);
+      if (hr != S_OK)
+        log_debug ("%s:%s: Property '%s' not found: %#lx",
+                   SRCNAME, __func__, name, hr);
+      else if (rVariant.vt != VT_BSTR)
+        log_debug ("%s:%s: Property `%s' is not a string (vt=%d)",
+                   SRCNAME, __func__, name, rVariant.vt);
+      else if (rVariant.bstrVal)
+        result = wchar_to_utf8 (rVariant.bstrVal);
+      VariantClear (&rVariant);
+    }
+
+  return result;
+}
+
+
+/* Return the control object described by the tag property with value
+   TAG. The object POBJ must support the FindControl method.  Returns
+   NULL if not found.  */
+LPDISPATCH
+get_oom_control_bytag (LPDISPATCH pDisp, const char *tag)
+{
+  HRESULT hr;      
+  DISPID dispid;
+  DISPPARAMS dispparams;
+  VARIANT aVariant[4];
+  VARIANT rVariant;
+  BSTR bstring;
+
+  dispid = lookup_oom_dispid (pDisp, "FindControl");
+  if (dispid == DISPID_UNKNOWN)
+    {
+      log_debug ("%s:%s: Object %p has no FindControl method",
+                 SRCNAME, __func__, pDisp);
+      return NULL;
+    }
+
+  {
+    wchar_t *tmp = utf8_to_wchar (tag);
+    bstring = tmp? SysAllocString (tmp):NULL;
+    xfree (tmp);
+    if (!bstring)
+      {
+        log_error_w32 (-1, "%s:%s: SysAllocString failed", SRCNAME, __func__);
+        return NULL;
+      }
+  }
+  dispparams.rgvarg = aVariant;
+  dispparams.rgvarg[0].vt = VT_ERROR; /* Visible */
+  dispparams.rgvarg[0].scode = DISP_E_PARAMNOTFOUND; 
+  dispparams.rgvarg[1].vt = VT_BSTR;  /* Tag */
+  dispparams.rgvarg[1].bstrVal = bstring;
+  dispparams.rgvarg[2].vt = VT_ERROR; /* Id */
+  dispparams.rgvarg[2].scode = DISP_E_PARAMNOTFOUND;
+  dispparams.rgvarg[3].vt = VT_ERROR;/* Type */
+  dispparams.rgvarg[3].scode = DISP_E_PARAMNOTFOUND; 
+  dispparams.cArgs = 4;
+  dispparams.cNamedArgs = 0;
+  VariantInit (&rVariant);
+  hr = pDisp->Invoke (dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
+                      DISPATCH_METHOD, &dispparams,
+                      &rVariant, NULL, NULL);
+  SysFreeString (bstring);
+  pDisp->Release();
+  pDisp = NULL;
+  if (hr == S_OK && rVariant.vt == VT_DISPATCH && rVariant.pdispVal)
+    {
+      rVariant.pdispVal->QueryInterface (IID_IDispatch, (LPVOID*)&pDisp);
+      rVariant.pdispVal->Release ();
+      if (!pDisp)
+        log_debug ("%s:%s: Object with tag `%s' has no dispatch intf.",
+                   SRCNAME, __func__, tag);
+    }
+  else
+    {
+      log_debug ("%s:%s: No object with tag `%s' found: vt=%d hr=%#lx",
+                 SRCNAME, __func__, tag, rVariant.vt, hr);
+      VariantClear (&rVariant);
+    }
+
+  return pDisp;
+}
+
+
+/* Add a new button to an object which supports the add method.
+   Returns the new object or NULL on error.  */
+LPDISPATCH
+add_oom_button (LPDISPATCH pObj)
+{
+  HRESULT hr;      
+  DISPID dispid;
+  DISPPARAMS dispparams;
+  VARIANT aVariant[5];
+  VARIANT rVariant;
+
+  dispid = lookup_oom_dispid (pObj, "Add");
+
+  dispparams.rgvarg = aVariant;
+  dispparams.rgvarg[0].vt = VT_BOOL;  /* Temporary */
+  dispparams.rgvarg[0].boolVal = VARIANT_TRUE;
+  dispparams.rgvarg[1].vt = VT_ERROR;  /* Before */
+  dispparams.rgvarg[1].scode = DISP_E_PARAMNOTFOUND; 
+  dispparams.rgvarg[2].vt = VT_ERROR;  /* Parameter */
+  dispparams.rgvarg[2].scode = DISP_E_PARAMNOTFOUND; 
+  dispparams.rgvarg[3].vt = VT_ERROR;  /* Id */
+  dispparams.rgvarg[3].scode = DISP_E_PARAMNOTFOUND; 
+  dispparams.rgvarg[4].vt = VT_INT;    /* Type */
+  dispparams.rgvarg[4].intVal = MSOCONTROLBUTTON;
+  dispparams.cArgs = 5;
+  dispparams.cNamedArgs = 0;
+  VariantInit (&rVariant);
+  hr = pObj->Invoke (dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
+                     DISPATCH_METHOD, &dispparams,
+                     &rVariant, NULL, NULL);
+  if (hr != S_OK || rVariant.vt != VT_DISPATCH || !rVariant.pdispVal)
+    {
+      log_debug ("%s:%s: Adding Control failed: %#lx - vt=%d",
+                 SRCNAME, __func__, hr, rVariant.vt);
+      VariantClear (&rVariant);
+      return NULL;
+    }
+  return rVariant.pdispVal;
+}
+
diff --git a/src/oomhelp.h b/src/oomhelp.h
new file mode 100644 (file)
index 0000000..7dec2a2
--- /dev/null
@@ -0,0 +1,107 @@
+/* oomhelp.h - Defs for helper functions for the Outlook Object Model
+ *     Copyright (C) 2009 g10 Code 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 OOMHELP_H
+#define OOMHELP_H
+
+#include <unknwn.h>
+
+
+#define MSOCONTROLBUTTON    1
+#define MSOCONTROLEDIT      2
+#define MSOCONTROLDROPDOWN  3
+#define MSOCONTROLCOMBOBOX  4
+#define MSOCONTROLPOPUP    10
+
+enum 
+  {
+    msoButtonAutomatic = 0,
+    msoButtonIcon = 1,
+    msoButtonCaption = 2,
+    msoButtonIconAndCaption = 3,
+    msoButtonIconAndWrapCaption = 7,
+    msoButtonIconAndCaptionBelow = 11,
+    msoButtonWrapCaption = 14,
+    msoButtonIconAndWrapCaptionBelow = 15 
+  };
+
+
+
+DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+DEFINE_GUID(IID_IConnectionPoint, 
+            0xb196b286, 0xbab4, 0x101a,
+            0xb6, 0x9c, 0x00, 0xaa, 0x00, 0x34, 0x1d, 0x07);
+DEFINE_GUID(IID_IConnectionPointContainer, 
+            0xb196b284, 0xbab4, 0x101a,
+            0xb6, 0x9c, 0x00, 0xaa, 0x00, 0x34, 0x1d, 0x07);
+DEFINE_GUID(IID_IPictureDisp,
+            0x7bf80981, 0xbf32, 0x101a,
+            0x8b, 0xbb, 0x00, 0xaa, 0x00, 0x30, 0x0c, 0xab);
+
+DEFINE_OLEGUID(IID_IUnknown,                  0x00000000, 0, 0);
+DEFINE_OLEGUID(IID_IDispatch,                 0x00020400, 0, 0);
+
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+}
+#endif
+#endif
+
+/* Return the malloced name of an COM+ object.  */
+char *get_object_name (LPUNKNOWN obj);
+
+/* Helper to lookup a dispid.  */
+DISPID lookup_oom_dispid (LPDISPATCH pDisp, const char *name);
+
+/* Return the OOM object's IDispatch interface described by FULLNAME.  */
+LPDISPATCH get_oom_object (LPDISPATCH pStart, const char *fullname);
+
+/* Set the Icon of a CommandBarControl.  */
+int put_oom_icon (LPDISPATCH pDisp, int rsource_id, int size);
+
+/* Set the boolean property NAME to VALUE.  */
+int put_oom_bool (LPDISPATCH pDisp, const char *name, int value);
+
+/* Set the property NAME to VALUE.  */
+int put_oom_int (LPDISPATCH pDisp, const char *name, int value);
+
+/* Set the property NAME to STRING.  */
+int put_oom_string (LPDISPATCH pDisp, const char *name, const char *string);
+
+/* Get the boolean property NAME of the object PDISP.  */
+int get_oom_bool (LPDISPATCH pDisp, const char *name);
+
+/* Get the string property NAME of the object PDISP.  */
+char *get_oom_string (LPDISPATCH pDisp, const char *name);
+
+/* Return the control object with tag property value TAG.  */
+LPDISPATCH get_oom_control_bytag (LPDISPATCH pObj, const char *tag);
+
+/* Add a new button to an object which supports the add method.
+   Returns the new object or NULL on error.  */
+LPDISPATCH add_oom_button (LPDISPATCH pObj);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*OOMHELP_H*/
diff --git a/src/sign-mask.bmp b/src/sign-mask.bmp
new file mode 100644 (file)
index 0000000..294865f
Binary files /dev/null and b/src/sign-mask.bmp differ
index ad78a7f..005fb6f 100644 (file)
Binary files a/src/sign.bmp and b/src/sign.bmp differ
index fb0e3de..cff402b 100644 (file)
@@ -104,20 +104,20 @@ GpgolUserEvents::OnSelectionChange (LPEXCHEXTCALLBACK eecb)
   if (debug_commands)
     log_debug ("%s:%s: received\n", SRCNAME, __func__);
 
-//   switch (is_preview_pane_visible (eecb))
-//     {
-//     case 0:
-//       log_debug ("%s:%s: preview pane is not visible\n", SRCNAME, __func__);
-//       break;
+  // switch (is_preview_pane_visible (eecb))
+  //   {
+  //   case 0:
+  //     log_debug ("%s:%s: preview pane is not visible\n", SRCNAME, __func__);
+  //     break;
       
-//     case 1:
-//       log_debug ("%s:%s: preview pane is visible\n", SRCNAME, __func__);
-//       break;
-
-//     default:
-//       log_debug ("%s:%s: no status for preview pane\n", SRCNAME, __func__);
-//       break;
-//     }
+  //   case 1:
+  //     log_debug ("%s:%s: preview pane is visible\n", SRCNAME, __func__);
+  //     break;
+
+  //   default:
+  //     log_debug ("%s:%s: no status for preview pane\n", SRCNAME, __func__);
+  //     break;
+  //   }
   
 
   hr = eecb->GetSelectionCount (&count);
index cb38ff1..3fc1497 100644 (file)
@@ -58,10 +58,14 @@ extern "C" {
 
 #include "xmalloc.h"
 
+void fatal_error (const char *format, ...);
+
 char *wchar_to_utf8_2 (const wchar_t *string, size_t len);
 wchar_t *utf8_to_wchar2 (const char *string, size_t len);
 char *latin1_to_utf8 (const char *string);
 
+char *mem2str (char *dest, const void *src, size_t n);
+
 char *trim_spaces (char *string);
 char *trim_trailing_spaces (char *string);
 char *read_w32_registry_string (const char *root, const char *dir,
diff --git a/src/verify-mask.bmp b/src/verify-mask.bmp
new file mode 100644 (file)
index 0000000..9ec605a
Binary files /dev/null and b/src/verify-mask.bmp differ
diff --git a/src/verify.bmp b/src/verify.bmp
new file mode 100644 (file)
index 0000000..f592e55
Binary files /dev/null and b/src/verify.bmp differ