5eaa5c4c45238a0b8ad63ddd9bdf41c79246fca8
[gpgol.git] / src / item-events.cpp
1 /* item-events.cpp - GpgolItemEvents implementation
2  *      Copyright (C) 2007 g10 Code GmbH
3  * 
4  * This file is part of GpgOL.
5  * 
6  * GpgOL is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  * 
11  * GpgOL is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  * 
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #error not used becuase it requires an ECF
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <windows.h>
26
27 #include "mymapi.h"
28 #include "mymapitags.h"
29 #include "myexchext.h"
30 #include "common.h"
31 #include "olflange-def.h"
32 #include "olflange.h"
33 #include "message.h"
34 #include "mapihelp.h"
35 #include "display.h"
36 #include "item-events.h"
37
38 #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \
39                                      SRCNAME, __func__, __LINE__); \
40                         } while (0)
41
42
43 /* Wrapper around UlRelease with error checking. */
44 /* FIXME: Duplicated code.  */
45 static void 
46 ul_release (LPVOID punk)
47 {
48   ULONG res;
49   
50   if (!punk)
51     return;
52   res = UlRelease (punk);
53 //   log_debug ("%s UlRelease(%p) had %lu references\n", __func__, punk, res);
54 }
55
56
57
58
59 /* Our constructor.  */
60 GpgolItemEvents::GpgolItemEvents (GpgolExt *pParentInterface)
61
62   m_pExchExt = pParentInterface;
63   m_ref = 0;
64   m_processed = false;
65   m_wasencrypted = false;
66 }
67
68
69 /* The QueryInterfac.  */
70 STDMETHODIMP 
71 GpgolItemEvents::QueryInterface (REFIID riid, LPVOID FAR *ppvObj)
72 {
73   *ppvObj = NULL;
74   if (riid == IID_IOutlookExtItemEvents)
75     {
76       *ppvObj = (LPVOID)this;
77       AddRef ();
78       return S_OK;
79     }
80   if (riid == IID_IUnknown)
81     {
82       *ppvObj = (LPVOID)m_pExchExt;
83       m_pExchExt->AddRef ();
84       return S_OK;
85     }
86   return E_NOINTERFACE;
87 }
88  
89
90 /* This method is called if an item is about to being displayed.
91    Possible return values are: 
92
93       S_FALSE - Let Outlook continue the operation.
94
95       E_ABORT - Abort the open operation and the item is not being
96                 displayed.
97 */
98 STDMETHODIMP 
99 GpgolItemEvents::OnOpen (LPEXCHEXTCALLBACK eecb)
100 {
101   LPMDB mdb = NULL;
102   LPMESSAGE message = NULL;
103   
104   log_debug ("%s:%s: received\n", SRCNAME, __func__);
105
106   m_wasencrypted = false;
107   eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
108   if (message_incoming_handler (message, m_pExchExt->getMsgtype (eecb)))
109     m_processed = TRUE;
110   ul_release (message);
111   ul_release (mdb);
112
113   return S_FALSE;
114 }
115
116
117 /* Like all the other Complete methods this one is called after OnOpen
118    has been called for all registered extensions.  FLAGS may have these
119    values:
120
121     0 - The open action has not been canceled.
122
123     EEME_FAILED or EEME_COMPLETE_FAILED - both indicate that the
124         open action has been canceled.  
125
126     Note that this method may be called more than once for each OnOpen
127     and may even occur without an OnOpen (i.e. while setting up a new
128     extension).
129
130     The same return values as for OnOpen may be used..
131 */ 
132 STDMETHODIMP 
133 GpgolItemEvents::OnOpenComplete (LPEXCHEXTCALLBACK eecb, ULONG flags)
134 {
135   log_debug ("%s:%s: received, flags=%#lx", SRCNAME, __func__, flags);
136
137   /* If the message has been processed by us (i.e. in OnOpen), we now
138      use our own display code.  */
139   if (!flags && m_processed)
140     {
141       HWND hwnd = NULL;
142
143       if (FAILED (eecb->GetWindow (&hwnd)))
144         hwnd = NULL;
145       if (message_display_handler (eecb, hwnd))
146         m_wasencrypted = true;
147     }
148   
149   return S_FALSE;
150 }
151
152
153 /* This method is called if an item's window received a close request.
154    Possible return values are: 
155
156       S_FALSE - Let Outlook continue the operation.
157
158       E_ABORT - Abort the close operation and don't dismiss the window.
159 */
160 STDMETHODIMP 
161 GpgolItemEvents::OnClose (LPEXCHEXTCALLBACK eecb, ULONG save_options)
162 {
163   log_debug ("%s:%s: received, options=%#lx", SRCNAME, __func__, save_options);
164
165   return S_FALSE;
166 }
167
168
169 /* This is the corresponding Complete method for OnClose.  See
170    OnOpenComplete for a description.  */
171 STDMETHODIMP 
172 GpgolItemEvents::OnCloseComplete (LPEXCHEXTCALLBACK eecb, ULONG flags)
173 {
174   log_debug ("%s:%s: received, flags=%#lx", SRCNAME, __func__, flags);
175
176   if (m_wasencrypted)
177     {
178       /* Delete any body parts so that encrypted stuff won't show up
179          in the clear. */
180       HRESULT hr;
181       LPMESSAGE message = NULL;
182       LPMDB mdb = NULL;
183       
184       log_debug ("%s:%s: deleting body properties", SRCNAME, __func__);
185       hr = eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
186       if (SUCCEEDED (hr))
187         {
188           SPropTagArray proparray;
189           int anyokay = 0;
190           
191           proparray.cValues = 1;
192           proparray.aulPropTag[0] = PR_BODY;
193           hr = message->DeleteProps (&proparray, NULL);
194           if (hr)
195             log_debug_w32 (hr, "%s:%s: deleting PR_BODY failed",
196                            SRCNAME, __func__);
197           else
198             anyokay++;
199      
200           proparray.cValues = 1;
201           proparray.aulPropTag[0] = PR_BODY_HTML;
202           message->DeleteProps (&proparray, NULL);
203           if (hr)
204             log_debug_w32 (hr, "%s:%s: deleting PR_BODY_HTML failed", 
205                            SRCNAME, __func__);
206           else
207             anyokay++;
208
209           if (anyokay)
210             {
211               hr = message->SaveChanges (KEEP_OPEN_READWRITE);
212               if (hr)
213                 log_error_w32 (hr, "%s:%s: SaveChanges failed",
214                                SRCNAME, __func__); 
215             }
216
217           m_wasencrypted = false;
218           
219         }  
220       else
221         log_debug_w32 (hr, "%s:%s: error getting message", 
222                        SRCNAME, __func__);
223      
224       ul_release (message);
225       ul_release (mdb);
226     }
227
228   return S_FALSE;
229 }