Renamed to olgpgmain and olgpgcore. Added fucntion to retrieve the
[gpgol.git] / olflange / GPGExch.cpp
1 /* GPGExch.cpp - exchange extension classes\r
2  *      Copyright (C) 2001 G Data Software AG, http://www.gdata.de\r
3  *      Copyright (C) 2004, 2005 g10 Code GmbH\r
4  * \r
5  * This file is part of the G DATA Outlook Plugin for GnuPG.\r
6  * \r
7  * This plugin is free software; you can redistribute it and/or\r
8  * modify it under the terms of the GNU Lesser General Public\r
9  * License as published by the Free Software Foundation; either\r
10  * version 2 of the License, or (at your option) any later version.\r
11  * \r
12  * This plugin is distributed in the hope that it will be useful,\r
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
15  * GNU Lesser General Public License for more details.\r
16  * \r
17  * You should have received a copy of the GNU Lesser General\r
18  * Public License along with this plugin; if not, write to the \r
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, \r
20  * Boston, MA 02111-1307, USA.\r
21  */\r
22 \r
23 #include "stdafx.h"\r
24 \r
25 #ifndef INITGUID\r
26 #define INITGUID\r
27 #endif\r
28 #include <INITGUID.H>\r
29 #include <MAPIGUID.H>\r
30 #include <EXCHEXT.H>\r
31 \r
32 #include "GPGExchange.h"\r
33 #include "GPGExch.h"\r
34 #include "../src/MapiGPGME.h"\r
35 \r
36 BOOL g_bInitDll = FALSE;\r
37 MapiGPGME *m_gpg = NULL;\r
38 \r
39 static void \r
40 ExchLogInfo (const char * fmt, ...)\r
41 {\r
42     if (m_gpg) {\r
43         va_list a;\r
44   \r
45         va_start (a, fmt);\r
46         m_gpg->logDebug (fmt, a);\r
47         va_end (a);\r
48     }\r
49 }\r
50 \r
51 /* The one and only CGPGExchApp object */\r
52 BEGIN_MESSAGE_MAP(CGPGExchApp, CWinApp)\r
53 END_MESSAGE_MAP()\r
54 \r
55 CGPGExchApp::CGPGExchApp (void)\r
56 {\r
57     ExchLogInfo("GPGExch\n");\r
58 }\r
59 \r
60 CGPGExchApp theApp;\r
61 \r
62 \r
63 \r
64 /* ExchEntryPoint -\r
65  The entry point which Exchange calls.\r
66  This is called for each context entry. Creates a new CAvkExchExt object\r
67  every time so each context will get its own CAvkExchExt interface.\r
68  \r
69  Return value: Pointer to Exchange Extension Object */\r
70 LPEXCHEXT CALLBACK \r
71 ExchEntryPoint (void)\r
72 {\r
73     ExchLogInfo ("extension entry point...\n");\r
74     return new CGPGExchExt;\r
75 }\r
76 \r
77 \r
78 /* DllRegisterServer\r
79  Registers this object as exchange extension. Sets the contextes which are \r
80  implemented by this object. */\r
81 STDAPI \r
82 DllRegisterServer (void)\r
83 {    \r
84     HKEY hKey;\r
85     CHAR szKeyBuf[1024];\r
86     CHAR szEntry[512];\r
87     TCHAR szModuleFileName[MAX_PATH];\r
88 \r
89     /* get server location */\r
90     DWORD dwResult = ::GetModuleFileName(theApp.m_hInstance, szModuleFileName, MAX_PATH);\r
91     if (dwResult == 0)  \r
92         return E_FAIL;\r
93 \r
94     lstrcpy (szKeyBuf, "Software\\Microsoft\\Exchange\\Client\\Extensions");\r
95     lstrcpy (szEntry, "4.0;");\r
96     lstrcat (szEntry, szModuleFileName);\r
97     lstrcat (szEntry, ";1;11000111111100");  /* context information */\r
98     long lResult = RegCreateKeyEx (HKEY_LOCAL_MACHINE, szKeyBuf, 0, NULL, \r
99                                    REG_OPTION_NON_VOLATILE,\r
100                                    KEY_ALL_ACCESS, NULL, &hKey, NULL);\r
101     if (lResult != ERROR_SUCCESS) {\r
102         ExchLogInfo ("DllRegisterServer failed\n");\r
103         return E_ACCESSDENIED;\r
104     }\r
105     DWORD dwTemp = 0;\r
106     dwTemp = lstrlen (szEntry) + 1;\r
107     RegSetValueEx (hKey, "OutlGPG", 0, REG_SZ, (BYTE*) szEntry, dwTemp);\r
108 \r
109     /* set outlook update flag */\r
110     strcpy(szEntry, "4.0;Outxxx.dll;7;000000000000000;0000000000;OutXXX");\r
111     dwTemp = lstrlen (szEntry) + 1;\r
112     RegSetValueEx (hKey, "Outlook Setup Extension", 0, REG_SZ, (BYTE*) szEntry, dwTemp);\r
113     RegCloseKey (hKey);\r
114     \r
115     ExchLogInfo ("DllRegisterServer succeeded\n");\r
116     return S_OK;\r
117 }\r
118 \r
119 \r
120 /* DllUnregisterServer - Unregisters this object in the exchange extension list. */\r
121 STDAPI \r
122 DllUnregisterServer (void)\r
123 {\r
124     HKEY hKey;\r
125     CHAR szKeyBuf[1024];\r
126 \r
127     lstrcpy(szKeyBuf, "Software\\Microsoft\\Exchange\\Client\\Extensions");\r
128     /* create and open key and subkey */\r
129     long lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, szKeyBuf, 0, NULL, \r
130                                     REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, \r
131                                     NULL, &hKey, NULL);\r
132     if (lResult != ERROR_SUCCESS) {\r
133         ExchLogInfo ("DllUnregisterServer: access denied.\n");\r
134         return E_ACCESSDENIED;\r
135     }\r
136     RegDeleteValue (hKey, "OutlGPG");\r
137     /* set outlook update flag */\r
138     CHAR szEntry[512];\r
139     strcpy (szEntry, "4.0;Outxxx.dll;7;000000000000000;0000000000;OutXXX");\r
140     DWORD dwTemp = lstrlen (szEntry) + 1;\r
141     RegSetValueEx (hKey, "Outlook Setup Extension", 0, REG_SZ, (BYTE*) szEntry, dwTemp);\r
142     RegCloseKey (hKey);\r
143 \r
144     return S_OK;\r
145 }\r
146 \r
147 \r
148 /* constructor of CGPGExchExt\r
149  Initializes members and creates the interface objects for the new context.\r
150  Does the dll initialization if it was not done before. */\r
151 CGPGExchExt::CGPGExchExt (void)\r
152\r
153     m_lRef = 1;\r
154     m_lContext = 0;\r
155     m_hWndExchange = 0;\r
156     m_gpgEncrypt = FALSE;\r
157     m_gpgSign = FALSE;\r
158     m_pExchExtMessageEvents = new CGPGExchExtMessageEvents (this);\r
159     m_pExchExtCommands = new CGPGExchExtCommands (this);\r
160     m_pExchExtPropertySheets = new CGPGExchExtPropertySheets (this);\r
161     if (!g_bInitDll) {\r
162         if (m_gpg == NULL) {\r
163             m_gpg = CreateMapiGPGME (NULL);\r
164             m_gpg->readOptions ();\r
165         }\r
166         g_bInitDll = TRUE;\r
167         ExchLogInfo("CGPGExchExt load\n");\r
168     }\r
169     else\r
170         ExchLogInfo("CGPGExchExt exists\n");\r
171 }\r
172 \r
173 \r
174 /* constructor of CGPGExchExt - Uninitializes the dll in the dession context. */\r
175 CGPGExchExt::~CGPGExchExt (void) \r
176 {\r
177     if (m_lContext == EECONTEXT_SESSION) {\r
178         if (g_bInitDll) {\r
179             if (m_gpg != NULL) {\r
180                 m_gpg->writeOptions ();\r
181                 delete m_gpg;\r
182                 m_gpg = NULL;\r
183             }\r
184             g_bInitDll = FALSE;\r
185         }       \r
186     }\r
187 }\r
188 \r
189 \r
190 /* CGPGExchExt::QueryInterface\r
191  Called by Exchage to request for interfaces.\r
192 \r
193  Return value: S_OK if the interface is supported, otherwise E_NOINTERFACE: */\r
194 STDMETHODIMP \r
195 CGPGExchExt::QueryInterface(\r
196         REFIID riid,      // The interface ID.\r
197         LPVOID * ppvObj)  // The address of interface object pointer.\r
198 {\r
199     HRESULT hr = S_OK;\r
200 \r
201     *ppvObj = NULL;\r
202 \r
203     if ((riid == IID_IUnknown) || (riid == IID_IExchExt)) {\r
204         *ppvObj = (LPUNKNOWN) this;\r
205     }\r
206     else if (riid == IID_IExchExtMessageEvents) {\r
207         *ppvObj = (LPUNKNOWN) m_pExchExtMessageEvents;\r
208     }\r
209     else if (riid == IID_IExchExtCommands) {\r
210         *ppvObj = (LPUNKNOWN)m_pExchExtCommands;\r
211         m_pExchExtCommands->SetContext(m_lContext);\r
212     }\r
213     else if (riid == IID_IExchExtPropertySheets) {\r
214         if (m_lContext != EECONTEXT_PROPERTYSHEETS)\r
215             return E_NOINTERFACE;\r
216         *ppvObj = (LPUNKNOWN) m_pExchExtPropertySheets;\r
217     }\r
218     else\r
219         hr = E_NOINTERFACE;\r
220 \r
221     if (*ppvObj != NULL)\r
222         ((LPUNKNOWN)*ppvObj)->AddRef();\r
223 \r
224     /*ExchLogInfo("QueryInterface %d\n", __LINE__);*/\r
225     return hr;\r
226 }\r
227 \r
228 \r
229 /* CGPGExchExt::Install\r
230  Called once for each new context. Checks the exchange extension version \r
231  number and the context.\r
232  \r
233  Return value: S_OK if the extension should used in the requested context, \r
234                otherwise S_FALSE. */\r
235 STDMETHODIMP CGPGExchExt::Install(\r
236         LPEXCHEXTCALLBACK pEECB, // The pointer to Exchange Extension callback function.\r
237         ULONG lContext,          // The context code at time of being called.\r
238         ULONG lFlags)            // The flag to say if install is for modal or not.\r
239 {\r
240     ULONG lBuildVersion;\r
241 \r
242     m_lContext = lContext;\r
243 \r
244     /*ExchLogInfo("Install %d\n", __LINE__);*/\r
245     // check the version \r
246     pEECB->GetVersion (&lBuildVersion, EECBGV_GETBUILDVERSION);\r
247     if (EECBGV_BUILDVERSION_MAJOR != (lBuildVersion & EECBGV_BUILDVERSION_MAJOR_MASK))\r
248         return S_FALSE;\r
249 \r
250     // and the context\r
251     if ((lContext == EECONTEXT_PROPERTYSHEETS) ||\r
252         (lContext == EECONTEXT_SENDNOTEMESSAGE) ||\r
253         (lContext == EECONTEXT_SENDPOSTMESSAGE) ||\r
254         (lContext == EECONTEXT_SENDRESENDMESSAGE) ||\r
255         (lContext == EECONTEXT_READNOTEMESSAGE) ||\r
256         (lContext == EECONTEXT_READPOSTMESSAGE) ||\r
257         (lContext == EECONTEXT_READREPORTMESSAGE) ||\r
258         (lContext == EECONTEXT_VIEWER))\r
259         return S_OK;\r
260     return S_FALSE;\r
261 }\r
262 \r
263 \r
264 CGPGExchExtMessageEvents::CGPGExchExtMessageEvents (CGPGExchExt *pParentInterface)\r
265\r
266     m_pExchExt = pParentInterface;\r
267     m_lRef = 0; \r
268     m_bOnSubmitCalled = FALSE;\r
269 };\r
270 \r
271 \r
272 STDMETHODIMP \r
273 CGPGExchExtMessageEvents::QueryInterface (REFIID riid, LPVOID FAR *ppvObj)\r
274 {   \r
275     *ppvObj = NULL;\r
276     if (riid == IID_IExchExtMessageEvents) {\r
277         *ppvObj = (LPVOID)this;\r
278         AddRef();\r
279         return S_OK;\r
280     }\r
281     if (riid == IID_IUnknown) {\r
282         *ppvObj = (LPVOID)m_pExchExt;  \r
283         m_pExchExt->AddRef();\r
284         return S_OK;\r
285     }\r
286     return E_NOINTERFACE;\r
287 }\r
288 \r
289 \r
290 /* CGPGExchExtMessageEvents::OnRead - Called from Exchange on reading a message.\r
291  Return value: S_FALSE to signal Exchange to continue calling extensions. */\r
292 STDMETHODIMP CGPGExchExtMessageEvents::OnRead(\r
293         LPEXCHEXTCALLBACK pEECB) // A pointer to IExchExtCallback interface.\r
294 {\r
295     ExchLogInfo ("OnRead\n");\r
296     return S_FALSE;\r
297 }\r
298 \r
299 \r
300 /* CGPGExchExtMessageEvents::OnReadComplete\r
301  Called by Exchange after a message has been read.\r
302 \r
303  Return value: S_FALSE to signal Exchange to continue calling extensions. */\r
304 STDMETHODIMP CGPGExchExtMessageEvents::OnReadComplete(\r
305         LPEXCHEXTCALLBACK pEECB, // A pointer to IExchExtCallback interface.\r
306         ULONG lFlags)\r
307 {\r
308     ExchLogInfo ("OnReadComplete\n");\r
309     return S_FALSE;\r
310 }\r
311 \r
312 \r
313 /* CGPGExchExtMessageEvents::OnWrite - Called by Exchange when a message will be written.\r
314  @rdesc S_FALSE to signal Exchange to continue calling extensions. */\r
315 STDMETHODIMP CGPGExchExtMessageEvents::OnWrite(\r
316         LPEXCHEXTCALLBACK pEECB) // A pointer to IExchExtCallback interface.\r
317 {\r
318     ExchLogInfo ("OnWrite\n");\r
319     return S_FALSE;\r
320 }\r
321 \r
322 \r
323 /* CGPGExchExtMessageEvents::OnWriteComplete\r
324  Called by Exchange when the data has been written to the message.\r
325  Encrypts and signs the message if the options are set.\r
326  @pEECB - A pointer to IExchExtCallback interface.\r
327 \r
328  Return value: S_FALSE: signals Exchange to continue calling extensions\r
329                E_FAIL:  signals Exchange an error; the message will not be sent */\r
330 STDMETHODIMP CGPGExchExtMessageEvents::OnWriteComplete (\r
331                   LPEXCHEXTCALLBACK pEECB, ULONG lFlags)\r
332 {\r
333     HRESULT hrReturn = S_FALSE;\r
334     LPMESSAGE pMessage = NULL;\r
335     LPMDB pMDB = NULL;\r
336     HWND hWnd = NULL;\r
337 \r
338     if (FAILED(pEECB->GetWindow (&hWnd)))\r
339         hWnd = NULL;\r
340 \r
341     if (!m_bOnSubmitCalled) /* the user is just saving the message */\r
342         return S_FALSE;\r
343 \r
344     if (m_bWriteFailed)     /* operation failed already */\r
345         return S_FALSE;\r
346 \r
347     HRESULT hr = pEECB->GetObject (&pMDB, (LPMAPIPROP *)&pMessage);\r
348     if (SUCCEEDED (hr)) {\r
349         if (m_pExchExt->m_gpgEncrypt || m_pExchExt->m_gpgSign) {\r
350             m_gpg->setMessage (pMessage);\r
351             if (m_gpg->doCmd (m_pExchExt->m_gpgEncrypt,\r
352                               m_pExchExt->m_gpgSign)) {\r
353                 hrReturn = E_FAIL;\r
354                 m_bWriteFailed = TRUE;  \r
355             }\r
356         }\r
357     }\r
358     if (pMessage != NULL)\r
359         UlRelease(pMessage);\r
360     if (pMDB != NULL)\r
361         UlRelease(pMDB);\r
362 \r
363     return hrReturn;\r
364 }\r
365 \r
366 /* CGPGExchExtMessageEvents::OnCheckNames\r
367 \r
368  Called by Exchange when the user selects the "check names" command.\r
369 \r
370  @pEECB - A pointer to IExchExtCallback interface.\r
371 \r
372  Return value: S_FALSE to signal Exchange to continue calling extensions.\r
373 */\r
374 STDMETHODIMP CGPGExchExtMessageEvents::OnCheckNames(LPEXCHEXTCALLBACK pEECB)\r
375 {\r
376     return S_FALSE;\r
377 }\r
378 \r
379 \r
380 /* CGPGExchExtMessageEvents::OnCheckNamesComplete\r
381 \r
382  Called by Exchange when "check names" command is complete.\r
383 \r
384   @pEECB - A pointer to IExchExtCallback interface.\r
385 \r
386  Return value: S_FALSE to signal Exchange to continue calling extensions.\r
387 */\r
388 STDMETHODIMP CGPGExchExtMessageEvents::OnCheckNamesComplete(\r
389                         LPEXCHEXTCALLBACK pEECB, ULONG lFlags)\r
390 {\r
391     return S_FALSE;\r
392 }\r
393 \r
394 \r
395 /* CGPGExchExtMessageEvents::OnSubmit\r
396 \r
397  Called by Exchange before the message data will be written and submitted.\r
398  to MAPI.\r
399 \r
400  @pEECB - A pointer to IExchExtCallback interface.\r
401 \r
402  Return value: S_FALSE to signal Exchange to continue calling extensions.\r
403 */\r
404 STDMETHODIMP CGPGExchExtMessageEvents::OnSubmit(\r
405                             LPEXCHEXTCALLBACK pEECB)\r
406 {\r
407     m_bOnSubmitCalled = TRUE;\r
408     m_bWriteFailed = FALSE;\r
409     return S_FALSE;\r
410 }\r
411 \r
412 \r
413 /* CGPGExchExtMessageEvents::OnSubmitComplete\r
414 \r
415   @pEECB - A pointer to IExchExtCallback interface.\r
416 \r
417  Called by Echange after the message has been submitted to MAPI.\r
418 */\r
419 STDMETHODIMP_ (VOID) CGPGExchExtMessageEvents::OnSubmitComplete (\r
420                             LPEXCHEXTCALLBACK pEECB, ULONG lFlags)\r
421 {\r
422     m_bOnSubmitCalled = FALSE; \r
423 }\r
424 \r
425 \r
426 CGPGExchExtCommands::CGPGExchExtCommands (CGPGExchExt* pParentInterface)\r
427\r
428     m_pExchExt = pParentInterface; \r
429     m_lRef = 0; \r
430     m_lContext = 0; \r
431     m_nCmdEncrypt = 0;  \r
432     m_nCmdSign = 0; \r
433     m_nToolbarButtonID1 = 0; \r
434     m_nToolbarButtonID2 = 0; \r
435     m_nToolbarBitmap1 = 0;\r
436     m_nToolbarBitmap2 = 0; \r
437     m_hWnd = NULL; \r
438 };\r
439 \r
440 \r
441 \r
442 STDMETHODIMP \r
443 CGPGExchExtCommands::QueryInterface (REFIID riid, LPVOID FAR * ppvObj)\r
444 {\r
445     *ppvObj = NULL;\r
446     if ((riid == IID_IExchExtCommands) || (riid == IID_IUnknown)) {\r
447         *ppvObj = (LPVOID)this;\r
448         AddRef ();\r
449         return S_OK;\r
450     }\r
451     return E_NOINTERFACE;\r
452 }\r
453 \r
454 \r
455 // XXX IExchExtSessionEvents::OnDelivery: could be used to automatically decrypt new mails\r
456 // when they arrive\r
457 \r
458 /* CGPGExchExtCommands::InstallCommands\r
459 \r
460  Called by Echange to install commands and toolbar buttons.\r
461 \r
462  Return value: S_FALSE to signal Exchange to continue calling extensions.\r
463 */\r
464 STDMETHODIMP CGPGExchExtCommands::InstallCommands(\r
465         LPEXCHEXTCALLBACK pEECB, // The Exchange Callback Interface.\r
466         HWND hWnd,               // The window handle to main window of context.\r
467         HMENU hMenu,             // The menu handle to main menu of context.\r
468         UINT FAR * pnCommandIDBase,  // The base conmmand id.\r
469         LPTBENTRY pTBEArray,     // The array of toolbar button entries.\r
470         UINT nTBECnt,            // The count of button entries in array.\r
471         ULONG lFlags)            // reserved\r
472 {\r
473     HMENU hMenuTools;\r
474     m_hWnd = hWnd;\r
475 \r
476     /* XXX: factor out common code */\r
477     if (m_lContext == EECONTEXT_READNOTEMESSAGE) {\r
478         int nTBIndex;\r
479         HWND hwndToolbar = NULL;\r
480         CHAR szBuffer[128];\r
481 \r
482         pEECB->GetMenuPos (EECMDID_ToolsCustomizeToolbar, &hMenuTools, NULL, NULL, 0);\r
483         AppendMenu (hMenuTools, MF_SEPARATOR, 0, NULL);\r
484         \r
485         LoadString (theApp.m_hInstance, IDS_DECRYPT_MENU_ITEM, szBuffer, 128);\r
486         AppendMenu (hMenuTools, MF_BYPOSITION | MF_STRING, *pnCommandIDBase, szBuffer);\r
487 \r
488         m_nCmdEncrypt = *pnCommandIDBase;\r
489         (*pnCommandIDBase)++;\r
490         \r
491         for (nTBIndex = nTBECnt-1; nTBIndex > -1; --nTBIndex) { \r
492             if (EETBID_STANDARD == pTBEArray[nTBIndex].tbid) {\r
493                 hwndToolbar = pTBEArray[nTBIndex].hwnd;         \r
494                 m_nToolbarButtonID1 = pTBEArray[nTBIndex].itbbBase;\r
495                 pTBEArray[nTBIndex].itbbBase++;\r
496                 break;          \r
497             }   \r
498         }\r
499 \r
500         if (hwndToolbar) {\r
501             TBADDBITMAP tbab;\r
502             tbab.hInst = theApp.m_hInstance;\r
503             tbab.nID = IDB_DECRYPT;\r
504             m_nToolbarBitmap1 = SendMessage(hwndToolbar, TB_ADDBITMAP, 1, (LPARAM)&tbab);\r
505             m_nToolbarButtonID2 = pTBEArray[nTBIndex].itbbBase;\r
506             pTBEArray[nTBIndex].itbbBase++;\r
507         }\r
508     }\r
509 \r
510     if (m_lContext == EECONTEXT_SENDNOTEMESSAGE) {\r
511         CHAR szBuffer[128];\r
512         int nTBIndex;\r
513         HWND hwndToolbar = NULL;\r
514 \r
515         pEECB->GetMenuPos(EECMDID_ToolsCustomizeToolbar, &hMenuTools, NULL, NULL, 0);\r
516         AppendMenu(hMenuTools, MF_SEPARATOR, 0, NULL);\r
517         \r
518         LoadString(theApp.m_hInstance, IDS_ENCRYPT_MENU_ITEM, szBuffer, 128);\r
519         AppendMenu(hMenuTools, MF_BYPOSITION | MF_STRING, *pnCommandIDBase, szBuffer);\r
520 \r
521         m_nCmdEncrypt = *pnCommandIDBase;\r
522         (*pnCommandIDBase)++;\r
523 \r
524         LoadString(theApp.m_hInstance, IDS_SIGN_MENU_ITEM, szBuffer, 128);\r
525         AppendMenu(hMenuTools, MF_BYPOSITION | MF_STRING, *pnCommandIDBase, szBuffer);\r
526 \r
527         m_nCmdSign = *pnCommandIDBase;\r
528         (*pnCommandIDBase)++;\r
529 \r
530         for (nTBIndex = nTBECnt-1; nTBIndex > -1; --nTBIndex)\r
531         {\r
532             if (EETBID_STANDARD == pTBEArray[nTBIndex].tbid)\r
533             {\r
534                 hwndToolbar = pTBEArray[nTBIndex].hwnd;\r
535                 m_nToolbarButtonID1 = pTBEArray[nTBIndex].itbbBase;\r
536                 pTBEArray[nTBIndex].itbbBase++;\r
537                 break;  \r
538             }\r
539         }\r
540 \r
541         if (hwndToolbar) {\r
542             TBADDBITMAP tbab;\r
543             tbab.hInst = theApp.m_hInstance;\r
544             tbab.nID = IDB_ENCRYPT;\r
545             m_nToolbarBitmap1 = SendMessage(hwndToolbar, TB_ADDBITMAP, 1, (LPARAM)&tbab);\r
546             m_nToolbarButtonID2 = pTBEArray[nTBIndex].itbbBase;\r
547             pTBEArray[nTBIndex].itbbBase++;\r
548             tbab.nID = IDB_SIGN;\r
549             m_nToolbarBitmap2 = SendMessage(hwndToolbar, TB_ADDBITMAP, 1, (LPARAM)&tbab);\r
550         }\r
551         m_pExchExt->m_gpgEncrypt = m_gpg->getEncryptDefault ();\r
552         m_pExchExt->m_gpgSign = m_gpg->getSignDefault ();\r
553     }\r
554 \r
555     if (m_lContext == EECONTEXT_VIEWER) {\r
556         CHAR szBuffer[128];\r
557         int nTBIndex;\r
558         HWND hwndToolbar = NULL;\r
559 \r
560         pEECB->GetMenuPos (EECMDID_ToolsCustomizeToolbar, &hMenuTools, NULL, NULL, 0);\r
561         AppendMenu (hMenuTools, MF_SEPARATOR, 0, NULL);\r
562         \r
563         LoadString (theApp.m_hInstance, IDS_KEY_MANAGER, szBuffer, 128);\r
564         AppendMenu (hMenuTools, MF_BYPOSITION | MF_STRING, *pnCommandIDBase, szBuffer);\r
565 \r
566         m_nCmdEncrypt = *pnCommandIDBase;\r
567         (*pnCommandIDBase)++;   \r
568 \r
569         for (nTBIndex = nTBECnt-1; nTBIndex > -1; --nTBIndex) {\r
570             if (EETBID_STANDARD == pTBEArray[nTBIndex].tbid) {\r
571                 hwndToolbar = pTBEArray[nTBIndex].hwnd;\r
572                 m_nToolbarButtonID1 = pTBEArray[nTBIndex].itbbBase;\r
573                 pTBEArray[nTBIndex].itbbBase++;\r
574                 break;  \r
575             }\r
576         }\r
577         if (hwndToolbar) {\r
578             TBADDBITMAP tbab;\r
579             tbab.hInst = theApp.m_hInstance;\r
580             tbab.nID = IDB_KEY_MANAGER;\r
581             m_nToolbarBitmap1 = SendMessage(hwndToolbar, TB_ADDBITMAP, 1, (LPARAM)&tbab);\r
582         }       \r
583     }\r
584     return S_FALSE;\r
585 }\r
586 \r
587 \r
588 /* CGPGExchExtCommands::DoCommand - Called by Exchange when a user selects a command. \r
589 \r
590  Return value: S_OK if command is handled, otherwise S_FALSE.\r
591 */\r
592 STDMETHODIMP CGPGExchExtCommands::DoCommand(\r
593         LPEXCHEXTCALLBACK pEECB, // The Exchange Callback Interface.\r
594         UINT nCommandID)         // The command id.\r
595 {\r
596 \r
597     if ((nCommandID != m_nCmdEncrypt) && \r
598         (nCommandID != m_nCmdSign))\r
599         return S_FALSE; \r
600 \r
601     if (m_lContext == EECONTEXT_READNOTEMESSAGE) {\r
602         LPMESSAGE pMessage = NULL;\r
603         LPMDB pMDB = NULL;\r
604         HWND hWnd = NULL;\r
605 \r
606         if (FAILED (pEECB->GetWindow (&hWnd)))\r
607             hWnd = NULL;\r
608         HRESULT hr = pEECB->GetObject (&pMDB, (LPMAPIPROP *)&pMessage);\r
609         if (SUCCEEDED (hr)) {\r
610             if (nCommandID == m_nCmdEncrypt) {\r
611                 m_gpg->setWindow (hWnd);\r
612                 m_gpg->setMessage (pMessage);\r
613                 m_gpg->decrypt ();\r
614             }\r
615         }\r
616         if (pMessage != NULL)\r
617             UlRelease(pMessage);\r
618         if (pMDB != NULL)\r
619             UlRelease(pMDB);\r
620     }\r
621     if (m_lContext == EECONTEXT_SENDNOTEMESSAGE) {\r
622         HWND hWnd = NULL;\r
623         if (FAILED(pEECB->GetWindow (&hWnd)))\r
624             hWnd = NULL;\r
625         if (nCommandID == m_nCmdEncrypt)\r
626             m_pExchExt->m_gpgEncrypt = !m_pExchExt->m_gpgEncrypt;\r
627         if (nCommandID == m_nCmdSign)\r
628             m_pExchExt->m_gpgSign = !m_pExchExt->m_gpgSign;\r
629     }\r
630     if (m_lContext == EECONTEXT_VIEWER) {\r
631         if (m_gpg->startKeyManager ())\r
632             MessageBox (NULL, "Could not start Key-Manager", "GPGExch", MB_ICONERROR|MB_OK);\r
633     }\r
634     return S_OK; \r
635 }\r
636 \r
637 STDMETHODIMP_(VOID) CGPGExchExtCommands::InitMenu(\r
638         LPEXCHEXTCALLBACK pEECB) // The pointer to Exchange Callback Interface.\r
639 {\r
640 }\r
641 \r
642 /* CGPGExchExtCommands::Help\r
643 \r
644  Called by Exhange when the user requests help for a menu item.\r
645 \r
646  Return value: S_OK when it is a menu item of this plugin and the help was shown;\r
647                otherwise S_FALSE\r
648 */\r
649 STDMETHODIMP CGPGExchExtCommands::Help (\r
650         LPEXCHEXTCALLBACK pEECB, // The pointer to Exchange Callback Interface.\r
651         UINT nCommandID)         // The command id.\r
652 {\r
653     if (m_lContext == EECONTEXT_READNOTEMESSAGE) {\r
654         if (nCommandID == m_nCmdEncrypt) {\r
655             CHAR szBuffer[512];\r
656             CHAR szAppName[128];\r
657 \r
658             LoadString (theApp.m_hInstance, IDS_DECRYPT_HELP, szBuffer, 511);\r
659             LoadString (theApp.m_hInstance, IDS_APP_NAME, szAppName, 127);\r
660             MessageBox (m_hWnd, szBuffer, szAppName, MB_OK);\r
661             return S_OK;\r
662         }\r
663     }\r
664     if (m_lContext == EECONTEXT_SENDNOTEMESSAGE) {\r
665         if (nCommandID == m_nCmdEncrypt) {\r
666             CHAR szBuffer[512];\r
667             CHAR szAppName[128];\r
668             LoadString(theApp.m_hInstance, IDS_ENCRYPT_HELP, szBuffer, 511);\r
669             LoadString(theApp.m_hInstance, IDS_APP_NAME, szAppName, 127);\r
670             MessageBox(m_hWnd, szBuffer, szAppName, MB_OK);     \r
671             return S_OK;\r
672         } \r
673         if (nCommandID == m_nCmdSign) {\r
674             CHAR szBuffer[512]; \r
675             CHAR szAppName[128];        \r
676             LoadString(theApp.m_hInstance, IDS_SIGN_HELP, szBuffer, 511);       \r
677             LoadString(theApp.m_hInstance, IDS_APP_NAME, szAppName, 127);       \r
678             MessageBox(m_hWnd, szBuffer, szAppName, MB_OK);     \r
679             return S_OK;\r
680         } \r
681     }\r
682 \r
683     if (m_lContext == EECONTEXT_VIEWER) {\r
684         if (nCommandID == m_nCmdEncrypt) {\r
685                 CHAR szBuffer[512];\r
686                 CHAR szAppName[128];\r
687                 LoadString(theApp.m_hInstance, IDS_KEY_MANAGER_HELP, szBuffer, 511);\r
688                 LoadString(theApp.m_hInstance, IDS_APP_NAME, szAppName, 127);\r
689                 MessageBox(m_hWnd, szBuffer, szAppName, MB_OK);\r
690                 return S_OK;\r
691         } \r
692     }\r
693 \r
694     return S_FALSE;\r
695 }\r
696 \r
697 /* CGPGExchExtCommands::QueryHelpText\r
698 \r
699  Called by Exhange to get the status bar text or the tooltip of a menu item.\r
700 \r
701  @rdesc S_OK when it is a menu item of this plugin and the text was set;\r
702         otherwise S_FALSE.\r
703 */\r
704 STDMETHODIMP CGPGExchExtCommands::QueryHelpText(\r
705         UINT nCommandID,  // The command id corresponding to menu item activated.\r
706         ULONG lFlags,     // Identifies either EECQHT_STATUS or EECQHT_TOOLTIP.\r
707     LPTSTR pszText,   // A pointer to buffer to be populated with text to display.\r
708         UINT nCharCnt)    // The count of characters available in psz buffer.\r
709 {\r
710         \r
711     if (m_lContext == EECONTEXT_READNOTEMESSAGE) {\r
712         if (nCommandID == m_nCmdEncrypt) {\r
713             if (lFlags == EECQHT_STATUS)\r
714                 LoadString (theApp.m_hInstance, IDS_DECRYPT_STATUSBAR, pszText, nCharCnt);\r
715             if (lFlags == EECQHT_TOOLTIP)\r
716                 LoadString (theApp.m_hInstance, IDS_DECRYPT_TOOLTIP, pszText, nCharCnt);\r
717             return S_OK;\r
718         }\r
719     }\r
720     if (m_lContext == EECONTEXT_SENDNOTEMESSAGE) {\r
721         if (nCommandID == m_nCmdEncrypt) {\r
722             if (lFlags == EECQHT_STATUS)\r
723                 LoadString (theApp.m_hInstance, IDS_ENCRYPT_STATUSBAR, pszText, nCharCnt);\r
724             if (lFlags == EECQHT_TOOLTIP)\r
725                 LoadString (theApp.m_hInstance, IDS_ENCRYPT_TOOLTIP, pszText, nCharCnt);\r
726             return S_OK;\r
727         }\r
728         if (nCommandID == m_nCmdSign) {\r
729             if (lFlags == EECQHT_STATUS)\r
730                 LoadString (theApp.m_hInstance, IDS_SIGN_STATUSBAR, pszText, nCharCnt);\r
731             if (lFlags == EECQHT_TOOLTIP)\r
732                 LoadString (theApp.m_hInstance, IDS_SIGN_TOOLTIP, pszText, nCharCnt);\r
733             return S_OK;\r
734         }\r
735     }\r
736     if (m_lContext == EECONTEXT_VIEWER) {\r
737         if (nCommandID == m_nCmdEncrypt) {\r
738             if (lFlags == EECQHT_STATUS)\r
739                 LoadString (theApp.m_hInstance, IDS_KEY_MANAGER_STATUSBAR, pszText, nCharCnt);\r
740             if (lFlags == EECQHT_TOOLTIP)\r
741                 LoadString (theApp.m_hInstance, IDS_KEY_MANAGER_TOOLTIP, pszText, nCharCnt);\r
742             return S_OK;\r
743         }       \r
744     }\r
745     return S_FALSE;\r
746 }\r
747 \r
748 /////////////////////////////////////////////////////////////////////////////\r
749 // CGPGExchExtCommands::QueryButtonInfo \r
750 //\r
751 // Called by Exchange to get toolbar button infos,\r
752 //\r
753 // @rdesc S_OK when it is a button of this plugin and the requested info was delivered;\r
754 //        otherwise S_FALSE\r
755 //\r
756 STDMETHODIMP CGPGExchExtCommands::QueryButtonInfo (\r
757         ULONG lToolbarID,       // The toolbar identifier.\r
758         UINT nToolbarButtonID,  // The toolbar button index.\r
759     LPTBBUTTON pTBB,        // A pointer to toolbar button structure (see TBBUTTON structure).\r
760         LPTSTR lpszDescription, // A pointer to string describing button.\r
761         UINT nCharCnt,          // The maximum size of lpsz buffer.\r
762     ULONG lFlags)           // EXCHEXT_UNICODE may be specified\r
763 {\r
764         if (m_lContext == EECONTEXT_READNOTEMESSAGE)\r
765         {\r
766                 if (nToolbarButtonID == m_nToolbarButtonID1)\r
767                 {\r
768                         pTBB->iBitmap = m_nToolbarBitmap1;             \r
769                         pTBB->idCommand = m_nCmdEncrypt;\r
770                         pTBB->fsState = TBSTATE_ENABLED;\r
771                         pTBB->fsStyle = TBSTYLE_BUTTON;\r
772                         pTBB->dwData = 0;\r
773                         pTBB->iString = -1;\r
774                         LoadString(theApp.m_hInstance, IDS_DECRYPT_TOOLTIP, lpszDescription, nCharCnt);\r
775                         return S_OK;\r
776                 }\r
777         }\r
778         if (m_lContext == EECONTEXT_SENDNOTEMESSAGE)\r
779         {\r
780                 if (nToolbarButtonID == m_nToolbarButtonID1)\r
781                 {\r
782                         pTBB->iBitmap = m_nToolbarBitmap1;             \r
783                         pTBB->idCommand = m_nCmdEncrypt;\r
784                         pTBB->fsState = TBSTATE_ENABLED;\r
785                         if (m_pExchExt->m_gpgEncrypt)\r
786                                 pTBB->fsState |= TBSTATE_CHECKED;\r
787                         pTBB->fsStyle = TBSTYLE_BUTTON | TBSTYLE_CHECK;\r
788                         pTBB->dwData = 0;\r
789                         pTBB->iString = -1;\r
790                         LoadString(theApp.m_hInstance, IDS_ENCRYPT_TOOLTIP, lpszDescription, nCharCnt);\r
791                         return S_OK;\r
792                 }\r
793                 if (nToolbarButtonID == m_nToolbarButtonID2)\r
794                 {\r
795                         pTBB->iBitmap = m_nToolbarBitmap2;             \r
796                         pTBB->idCommand = m_nCmdSign;\r
797                         pTBB->fsState = TBSTATE_ENABLED;\r
798                         if (m_pExchExt->m_gpgSign)\r
799                                 pTBB->fsState |= TBSTATE_CHECKED;\r
800                         pTBB->fsStyle = TBSTYLE_BUTTON | TBSTYLE_CHECK;\r
801                         pTBB->dwData = 0;\r
802                         pTBB->iString = -1;\r
803                         LoadString(theApp.m_hInstance, IDS_SIGN_TOOLTIP, lpszDescription, nCharCnt);\r
804                         return S_OK;\r
805                 }\r
806         }\r
807         if (m_lContext == EECONTEXT_VIEWER)\r
808         {\r
809                 if (nToolbarButtonID == m_nToolbarButtonID1)\r
810                 {\r
811                         pTBB->iBitmap = m_nToolbarBitmap1;             \r
812                         pTBB->idCommand = m_nCmdEncrypt;\r
813                         pTBB->fsState = TBSTATE_ENABLED;\r
814                         pTBB->fsStyle = TBSTYLE_BUTTON;\r
815                         pTBB->dwData = 0;\r
816                         pTBB->iString = -1;\r
817                         LoadString(theApp.m_hInstance, IDS_KEY_MANAGER_TOOLTIP, lpszDescription, nCharCnt);\r
818                         return S_OK;\r
819                 }\r
820         }\r
821 \r
822         return S_FALSE;\r
823 }\r
824 \r
825 \r
826 STDMETHODIMP \r
827 CGPGExchExtCommands::ResetToolbar (ULONG lToolbarID, ULONG lFlags)\r
828 {       \r
829     return S_OK;\r
830 }\r
831 \r
832 \r
833 CGPGExchExtPropertySheets::CGPGExchExtPropertySheets(CGPGExchExt* pParentInterface)\r
834\r
835     m_pExchExt = pParentInterface;\r
836     m_lRef = 0; \r
837 }\r
838 \r
839 \r
840 STDMETHODIMP \r
841 CGPGExchExtPropertySheets::QueryInterface(REFIID riid, LPVOID FAR * ppvObj)\r
842 {   \r
843     *ppvObj = NULL;\r
844     if (riid == IID_IExchExtPropertySheets) {\r
845         *ppvObj = (LPVOID)this;\r
846         AddRef();\r
847         return S_OK;\r
848     }\r
849     if (riid == IID_IUnknown) {\r
850         *ppvObj = (LPVOID)m_pExchExt;\r
851         m_pExchExt->AddRef();\r
852         return S_OK;\r
853     }\r
854 \r
855     return E_NOINTERFACE;\r
856 }\r
857 \r
858 \r
859 /* CGPGExchExtPropertySheets::GetMaxPageCount\r
860 \r
861  Called by Echange to get the maximum number of property pages which are\r
862  to be added.\r
863 \r
864  Return value: The maximum number of custom pages for the property sheet.\r
865 */\r
866 STDMETHODIMP_ (ULONG) \r
867 CGPGExchExtPropertySheets::GetMaxPageCount(\r
868         ULONG lFlags) // A bitmask indicating what type of property sheet is being displayed.\r
869 {\r
870     if (lFlags == EEPS_TOOLSOPTIONS)\r
871         return 1;       \r
872     return 0;\r
873 }\r
874 \r
875 \r
876 BOOL CALLBACK GPGOptionsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);\r
877 \r
878 \r
879 /* CGPGExchExtPropertySheets::GetPages\r
880 \r
881  Called by Exchange to request information about the property page.\r
882 \r
883  Return value: S_OK to signal Echange to use the pPSP information.\r
884 */\r
885 STDMETHODIMP \r
886 CGPGExchExtPropertySheets::GetPages(\r
887         LPEXCHEXTCALLBACK pEECB, // A pointer to Exchange callback interface.\r
888         ULONG lFlags,            // A  bitmask indicating what type of property sheet is being displayed.\r
889         LPPROPSHEETPAGE pPSP,    // The output parm pointing to pointer to list of property sheets.\r
890         ULONG FAR * plPSP)       // The output parm pointing to buffer contaiing number of property sheets actually used.\r
891 {\r
892     int resid = 0;\r
893 \r
894     switch (GetUserDefaultLangID ()) {\r
895     case 0x0407:    resid = IDD_GPG_OPTIONS_DE;break;\r
896     default:        resid = IDD_GPG_OPTIONS; break;\r
897     }\r
898 \r
899     pPSP[0].dwSize = sizeof (PROPSHEETPAGE);\r
900     pPSP[0].dwFlags = PSP_DEFAULT | PSP_HASHELP;\r
901     pPSP[0].hInstance = theApp.m_hInstance;\r
902     pPSP[0].pszTemplate = MAKEINTRESOURCE (resid);\r
903     pPSP[0].hIcon = NULL;     \r
904     pPSP[0].pszTitle = NULL;  \r
905     pPSP[0].pfnDlgProc = (DLGPROC) GPGOptionsDlgProc;\r
906     pPSP[0].lParam = 0;     \r
907     pPSP[0].pfnCallback = NULL;\r
908     pPSP[0].pcRefParent = NULL; \r
909 \r
910     *plPSP = 1;\r
911 \r
912     return S_OK;\r
913 }\r
914 \r
915 STDMETHODIMP_ (VOID) \r
916 CGPGExchExtPropertySheets::FreePages (LPPROPSHEETPAGE pPSP, ULONG lFlags, ULONG lPSP)\r
917 {\r
918 }\r