Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34385077
olflange.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
40 KB
Subscribers
None
olflange.cpp
View Options
/* olflange.cpp - Flange between Outlook and the MapiGPGME class
* Copyright (C) 2001 G Data Software AG, http://www.gdata.de
* Copyright (C) 2004, 2005 g10 Code GmbH
*
* This file is part of OutlGPG.
*
* OutlGPG 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 of the License, or (at your option) any later version.
*
* OutlGPG 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include
<config.h>
#endif
#include
<windows.h>
#ifndef INITGUID
#define INITGUID
#endif
#include
<initguid.h>
#include
"mymapi.h"
#include
"mymapitags.h"
#include
"myexchext.h"
#include
"display.h"
#include
"intern.h"
#include
"gpgmsg.hh"
#include
"msgcache.h"
#include
"engine.h"
#include
"olflange-ids.h"
#include
"olflange-def.h"
#include
"olflange.h"
#define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \
__FILE__, __func__, __LINE__); \
} while (0)
bool
g_bInitDll
=
FALSE
;
/* Registers this module as an Exchange extension. This basically updates
some Registry entries. */
STDAPI
DllRegisterServer
(
void
)
{
HKEY
hkey
;
CHAR
szKeyBuf
[
1024
];
CHAR
szEntry
[
512
];
TCHAR
szModuleFileName
[
MAX_PATH
];
DWORD
dwTemp
=
0
;
long
ec
;
/* Get server location. */
if
(
!
GetModuleFileName
(
glob_hinst
,
szModuleFileName
,
MAX_PATH
))
return
E_FAIL
;
lstrcpy
(
szKeyBuf
,
"Software
\\
Microsoft
\\
Exchange
\\
Client
\\
Extensions"
);
lstrcpy
(
szEntry
,
"4.0;"
);
lstrcat
(
szEntry
,
szModuleFileName
);
lstrcat
(
szEntry
,
";1"
);
/* Entry point ordinal. */
/* Context information string:
pos context
1 EECONTEXT_SESSION
2 EECONTEXT_VIEWER
3 EECONTEXT_REMOTEVIEWER
4 EECONTEXT_SEARCHVIEWER
5 EECONTEXT_ADDRBOOK
6 EECONTEXT_SENDNOTEMESSAGE
7 EECONTEXT_READNOTEMESSAGE
8 EECONTEXT_SENDPOSTMESSAGE
9 EECONTEXT_READPOSTMESSAGE
10 EECONTEXT_READREPORTMESSAGE
11 EECONTEXT_SENDRESENDMESSAGE
12 EECONTEXT_PROPERTYSHEETS
13 EECONTEXT_ADVANCEDCRITERIA
14 EECONTEXT_TASK
*/
lstrcat
(
szEntry
,
";11000111111100"
);
ec
=
RegCreateKeyEx
(
HKEY_LOCAL_MACHINE
,
szKeyBuf
,
0
,
NULL
,
REG_OPTION_NON_VOLATILE
,
KEY_ALL_ACCESS
,
NULL
,
&
hkey
,
NULL
);
if
(
ec
!=
ERROR_SUCCESS
)
{
log_debug
(
"DllRegisterServer failed
\n
"
);
return
E_ACCESSDENIED
;
}
dwTemp
=
lstrlen
(
szEntry
)
+
1
;
RegSetValueEx
(
hkey
,
"OutlGPG"
,
0
,
REG_SZ
,
(
BYTE
*
)
szEntry
,
dwTemp
);
/* To avoid conflicts with the old G-DATA plugin and older vesions
of this Plugin, we remove the key used by these versions. */
RegDeleteValue
(
hkey
,
"GPG Exchange"
);
/* Set outlook update flag. */
strcpy
(
szEntry
,
"4.0;Outxxx.dll;7;000000000000000;0000000000;OutXXX"
);
dwTemp
=
lstrlen
(
szEntry
)
+
1
;
RegSetValueEx
(
hkey
,
"Outlook Setup Extension"
,
0
,
REG_SZ
,
(
BYTE
*
)
szEntry
,
dwTemp
);
RegCloseKey
(
hkey
);
hkey
=
NULL
;
lstrcpy
(
szKeyBuf
,
"Software
\\
GNU
\\
OutlGPG"
);
RegCreateKeyEx
(
HKEY_CURRENT_USER
,
szKeyBuf
,
0
,
NULL
,
REG_OPTION_NON_VOLATILE
,
KEY_ALL_ACCESS
,
NULL
,
&
hkey
,
NULL
);
if
(
hkey
!=
NULL
)
RegCloseKey
(
hkey
);
log_debug
(
"DllRegisterServer succeeded
\n
"
);
return
S_OK
;
}
/* Unregisters this module as an Exchange extension. */
STDAPI
DllUnregisterServer
(
void
)
{
HKEY
hkey
;
CHAR
szKeyBuf
[
1024
];
lstrcpy
(
szKeyBuf
,
"Software
\\
Microsoft
\\
Exchange
\\
Client
\\
Extensions"
);
/* create and open key and subkey */
long
lResult
=
RegCreateKeyEx
(
HKEY_LOCAL_MACHINE
,
szKeyBuf
,
0
,
NULL
,
REG_OPTION_NON_VOLATILE
,
KEY_ALL_ACCESS
,
NULL
,
&
hkey
,
NULL
);
if
(
lResult
!=
ERROR_SUCCESS
)
{
log_debug
(
"DllUnregisterServer: access denied.
\n
"
);
return
E_ACCESSDENIED
;
}
RegDeleteValue
(
hkey
,
"OutlGPG"
);
/* set outlook update flag */
CHAR
szEntry
[
512
];
strcpy
(
szEntry
,
"4.0;Outxxx.dll;7;000000000000000;0000000000;OutXXX"
);
DWORD
dwTemp
=
lstrlen
(
szEntry
)
+
1
;
RegSetValueEx
(
hkey
,
"Outlook Setup Extension"
,
0
,
REG_SZ
,
(
BYTE
*
)
szEntry
,
dwTemp
);
RegCloseKey
(
hkey
);
return
S_OK
;
}
/* DISPLAY a MAPI property. */
static
void
show_mapi_property
(
LPMESSAGE
message
,
ULONG
prop
,
const
char
*
propname
)
{
HRESULT
hr
;
LPSPropValue
lpspvFEID
=
NULL
;
cache_item_t
item
;
size_t
keylen
;
void
*
key
;
if
(
!
message
)
return
;
/* No message: Nop. */
hr
=
HrGetOneProp
((
LPMAPIPROP
)
message
,
prop
,
&
lpspvFEID
);
if
(
FAILED
(
hr
))
{
log_debug
(
"%s: HrGetOneProp(%s) failed: hr=%#lx
\n
"
,
__func__
,
propname
,
hr
);
return
;
}
if
(
PROP_TYPE
(
lpspvFEID
->
ulPropTag
)
!=
PT_BINARY
)
{
log_debug
(
"%s: HrGetOneProp(%s) returned unexpected property type
\n
"
,
__func__
,
propname
);
MAPIFreeBuffer
(
lpspvFEID
);
return
;
}
keylen
=
lpspvFEID
->
Value
.
bin
.
cb
;
key
=
lpspvFEID
->
Value
.
bin
.
lpb
;
log_hexdump
(
key
,
keylen
,
"%s: %20s="
,
__func__
,
propname
);
MAPIFreeBuffer
(
lpspvFEID
);
}
/* Locate a property using the current callback LPEECB and traverse
down to the last element in the dot delimited NAME. Returns the
Dispatch object and if R_DISPID is not NULL, the dispatch-id of the
last part. Returns NULL on error. The traversal implictly starts
at the object returned by the outlook application callback. */
static
LPDISPATCH
find_outlook_property
(
LPEXCHEXTCALLBACK
lpeecb
,
const
char
*
name
,
DISPID
*
r_dispid
)
{
HRESULT
hr
;
LPOUTLOOKEXTCALLBACK
pCb
;
LPUNKNOWN
pObj
;
LPDISPATCH
pDisp
;
DISPID
dispid
;
wchar_t
*
wname
;
const
char
*
s
;
log_debug
(
"%s:%s: looking for `%s'
\n
"
,
__FILE__
,
__func__
,
name
);
pCb
=
NULL
;
pObj
=
NULL
;
lpeecb
->
QueryInterface
(
IID_IOutlookExtCallback
,
(
LPVOID
*
)
&
pCb
);
if
(
pCb
)
pCb
->
GetObject
(
&
pObj
);
for
(;
pObj
&&
(
s
=
strchr
(
name
,
'.'
))
&&
s
!=
name
;
name
=
s
+
1
)
{
DISPPARAMS
dispparamsNoArgs
=
{
NULL
,
NULL
,
0
,
0
};
VARIANT
vtResult
;
/* 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
);
if
(
!
wname
)
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);
vtResult
.
pdispVal
=
NULL
;
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",
// __FILE__, __func__, (int)(s-name), name, pObj, hr);
pDisp
->
Release
();
pDisp
=
NULL
;
/* Fixme: Do we need to release pObj? */
}
if
(
!
pObj
||
!*
name
)
return
NULL
;
pObj
->
QueryInterface
(
IID_IDispatch
,
(
LPVOID
*
)
&
pDisp
);
if
(
!
pDisp
)
return
NULL
;
wname
=
utf8_to_wchar
(
name
);
if
(
!
wname
)
{
pDisp
->
Release
();
return
NULL
;
}
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);
if
(
r_dispid
)
*
r_dispid
=
dispid
;
log_debug
(
"%s:%s: got IDispatch=%p dispid=%d
\n
"
,
__FILE__
,
__func__
,
pDisp
,
dispid
);
return
pDisp
;
}
/* Return Outlook's Application object. */
/* FIXME: We should be able to fold most of the code into
find_outlook_property. */
static
LPUNKNOWN
get_outlook_application_object
(
LPEXCHEXTCALLBACK
lpeecb
)
{
LPOUTLOOKEXTCALLBACK
pCb
=
NULL
;
LPDISPATCH
pDisp
=
NULL
;
LPUNKNOWN
pUnk
=
NULL
;
lpeecb
->
QueryInterface
(
IID_IOutlookExtCallback
,
(
LPVOID
*
)
&
pCb
);
if
(
pCb
)
pCb
->
GetObject
(
&
pUnk
);
if
(
pUnk
)
{
pUnk
->
QueryInterface
(
IID_IDispatch
,
(
LPVOID
*
)
&
pDisp
);
pUnk
->
Release
();
pUnk
=
NULL
;
}
if
(
pDisp
)
{
WCHAR
*
name
=
L
"Class"
;
DISPPARAMS
dispparamsNoArgs
=
{
NULL
,
NULL
,
0
,
0
};
DISPID
dispid
;
VARIANT
vtResult
;
pDisp
->
GetIDsOfNames
(
IID_NULL
,
&
name
,
1
,
LOCALE_SYSTEM_DEFAULT
,
&
dispid
);
vtResult
.
pdispVal
=
NULL
;
pDisp
->
Invoke
(
dispid
,
IID_NULL
,
LOCALE_SYSTEM_DEFAULT
,
DISPATCH_PROPERTYGET
,
&
dispparamsNoArgs
,
&
vtResult
,
NULL
,
NULL
);
log_debug
(
"%s:%s: Outlookcallback returned object of class=%d
\n
"
,
__FILE__
,
__func__
,
vtResult
.
intVal
);
}
if
(
pDisp
)
{
WCHAR
*
name
=
L
"Application"
;
DISPPARAMS
dispparamsNoArgs
=
{
NULL
,
NULL
,
0
,
0
};
DISPID
dispid
;
VARIANT
vtResult
;
pDisp
->
GetIDsOfNames
(
IID_NULL
,
&
name
,
1
,
LOCALE_SYSTEM_DEFAULT
,
&
dispid
);
//log_debug (" dispid(Application)=%d\n", dispid);
vtResult
.
pdispVal
=
NULL
;
pDisp
->
Invoke
(
dispid
,
IID_NULL
,
LOCALE_SYSTEM_DEFAULT
,
DISPATCH_METHOD
,
&
dispparamsNoArgs
,
&
vtResult
,
NULL
,
NULL
);
pUnk
=
vtResult
.
pdispVal
;
//log_debug ("%s:%s: Outlook.Application=%p\n",
// __FILE__, __func__, pUnk);
pDisp
->
Release
();
pDisp
=
NULL
;
}
return
pUnk
;
}
/* The entry point which Exchange calls. This is called for each
context entry. Creates a new CGPGExchExt object every time so each
context will get its own CGPGExchExt interface. */
EXTERN_C
LPEXCHEXT
__stdcall
ExchEntryPoint
(
void
)
{
log_debug
(
"%s:%s: creating new CGPGExchExt object
\n
"
,
__FILE__
,
__func__
);
return
new
CGPGExchExt
;
}
/* Constructor of CGPGExchExt
Initializes members and creates the interface objects for the new
context. Does the DLL initialization if it has not been done
before. */
CGPGExchExt
::
CGPGExchExt
(
void
)
{
m_lRef
=
1
;
m_lContext
=
0
;
m_hWndExchange
=
0
;
m_gpgEncrypt
=
FALSE
;
m_gpgSign
=
FALSE
;
m_pExchExtMessageEvents
=
new
CGPGExchExtMessageEvents
(
this
);
m_pExchExtCommands
=
new
CGPGExchExtCommands
(
this
);
m_pExchExtPropertySheets
=
new
CGPGExchExtPropertySheets
(
this
);
if
(
!
m_pExchExtMessageEvents
||
!
m_pExchExtCommands
||
!
m_pExchExtPropertySheets
)
out_of_core
();
if
(
!
g_bInitDll
)
{
read_options
();
op_init
();
g_bInitDll
=
TRUE
;
log_debug
(
"%s:%s: first time initialization done
\n
"
,
__FILE__
,
__func__
);
}
}
/* Uninitializes the DLL in the session context. */
CGPGExchExt
::~
CGPGExchExt
(
void
)
{
log_debug
(
"%s:%s: cleaning up CGPGExchExt object
\n
"
,
__FILE__
,
__func__
);
if
(
m_lContext
==
EECONTEXT_SESSION
)
{
if
(
g_bInitDll
)
{
op_deinit
();
write_options
();
g_bInitDll
=
FALSE
;
log_debug
(
"%s:%s: DLL shutdown down
\n
"
,
__FILE__
,
__func__
);
}
}
}
/* Called by Exchange to retrieve an object pointer for a named
interface. This is a standard COM method. REFIID is the ID of the
interface and PPVOBJ will get the address of the object pointer if
this class defines the requested interface. Return value: S_OK if
the interface is supported, otherwise E_NOINTERFACE. */
STDMETHODIMP
CGPGExchExt
::
QueryInterface
(
REFIID
riid
,
LPVOID
*
ppvObj
)
{
HRESULT
hr
=
S_OK
;
*
ppvObj
=
NULL
;
if
((
riid
==
IID_IUnknown
)
||
(
riid
==
IID_IExchExt
))
{
*
ppvObj
=
(
LPUNKNOWN
)
this
;
}
else
if
(
riid
==
IID_IExchExtMessageEvents
)
{
*
ppvObj
=
(
LPUNKNOWN
)
m_pExchExtMessageEvents
;
m_pExchExtMessageEvents
->
SetContext
(
m_lContext
);
}
else
if
(
riid
==
IID_IExchExtCommands
)
{
*
ppvObj
=
(
LPUNKNOWN
)
m_pExchExtCommands
;
m_pExchExtCommands
->
SetContext
(
m_lContext
);
}
else
if
(
riid
==
IID_IExchExtPropertySheets
)
{
if
(
m_lContext
!=
EECONTEXT_PROPERTYSHEETS
)
return
E_NOINTERFACE
;
*
ppvObj
=
(
LPUNKNOWN
)
m_pExchExtPropertySheets
;
}
else
hr
=
E_NOINTERFACE
;
/* On success we need to bump up the reference counter for the
requested object. */
if
(
*
ppvObj
)
((
LPUNKNOWN
)
*
ppvObj
)
->
AddRef
();
/*log_debug("QueryInterface %d\n", __LINE__);*/
return
hr
;
}
/* Called once for each new context. Checks the Exchange extension
version number and the context. Returns: S_OK if the extension
should used in the requested context, otherwise S_FALSE. PEECB is
a pointer to Exchange extension callback function. LCONTEXT is the
context code at time of being called. LFLAGS carries flags to
indicate whether the extension should be installed modal.
*/
STDMETHODIMP
CGPGExchExt
::
Install
(
LPEXCHEXTCALLBACK
pEECB
,
ULONG
lContext
,
ULONG
lFlags
)
{
ULONG
lBuildVersion
;
/* Save the context in an instance variable. */
m_lContext
=
lContext
;
log_debug
(
"%s:%s: context=0x%lx (%s) flags=0x%lx
\n
"
,
__FILE__
,
__func__
,
lContext
,
(
lContext
==
EECONTEXT_SESSION
?
"Session"
:
lContext
==
EECONTEXT_VIEWER
?
"Viewer"
:
lContext
==
EECONTEXT_REMOTEVIEWER
?
"RemoteViewer"
:
lContext
==
EECONTEXT_SEARCHVIEWER
?
"SearchViewer"
:
lContext
==
EECONTEXT_ADDRBOOK
?
"AddrBook"
:
lContext
==
EECONTEXT_SENDNOTEMESSAGE
?
"SendNoteMessage"
:
lContext
==
EECONTEXT_READNOTEMESSAGE
?
"ReadNoteMessage"
:
lContext
==
EECONTEXT_SENDPOSTMESSAGE
?
"SendPostMessage"
:
lContext
==
EECONTEXT_READPOSTMESSAGE
?
"ReadPostMessage"
:
lContext
==
EECONTEXT_READREPORTMESSAGE
?
"ReadReportMessage"
:
lContext
==
EECONTEXT_SENDRESENDMESSAGE
?
"SendResendMessage"
:
lContext
==
EECONTEXT_PROPERTYSHEETS
?
"PropertySheets"
:
lContext
==
EECONTEXT_ADVANCEDCRITERIA
?
"AdvancedCriteria"
:
lContext
==
EECONTEXT_TASK
?
"Task"
:
""
),
lFlags
);
/* Check version. */
pEECB
->
GetVersion
(
&
lBuildVersion
,
EECBGV_GETBUILDVERSION
);
if
(
EECBGV_BUILDVERSION_MAJOR
!=
(
lBuildVersion
&
EECBGV_BUILDVERSION_MAJOR_MASK
))
{
log_debug
(
"%s:%s: invalid version 0x%lx
\n
"
,
__FILE__
,
__func__
,
lBuildVersion
);
return
S_FALSE
;
}
/* Check context. */
if
(
lContext
==
EECONTEXT_PROPERTYSHEETS
||
lContext
==
EECONTEXT_SENDNOTEMESSAGE
||
lContext
==
EECONTEXT_SENDPOSTMESSAGE
||
lContext
==
EECONTEXT_SENDRESENDMESSAGE
||
lContext
==
EECONTEXT_READNOTEMESSAGE
||
lContext
==
EECONTEXT_READPOSTMESSAGE
||
lContext
==
EECONTEXT_READREPORTMESSAGE
||
lContext
==
EECONTEXT_VIEWER
)
{
// LPUNKNOWN pApplication = get_outlook_application_object (pEECB);
// log_debug ("%s:%s: pApplication=%p\n",
// __FILE__, __func__, pApplication);
return
S_OK
;
}
log_debug
(
"%s:%s: can't handle this context
\n
"
,
__FILE__
,
__func__
);
return
S_FALSE
;
}
CGPGExchExtMessageEvents
::
CGPGExchExtMessageEvents
(
CGPGExchExt
*
pParentInterface
)
{
m_pExchExt
=
pParentInterface
;
m_lRef
=
0
;
m_bOnSubmitActive
=
FALSE
;
};
STDMETHODIMP
CGPGExchExtMessageEvents
::
QueryInterface
(
REFIID
riid
,
LPVOID
FAR
*
ppvObj
)
{
*
ppvObj
=
NULL
;
if
(
riid
==
IID_IExchExtMessageEvents
)
{
*
ppvObj
=
(
LPVOID
)
this
;
AddRef
();
return
S_OK
;
}
if
(
riid
==
IID_IUnknown
)
{
*
ppvObj
=
(
LPVOID
)
m_pExchExt
;
m_pExchExt
->
AddRef
();
return
S_OK
;
}
return
E_NOINTERFACE
;
}
/* Called from Exchange on reading a message. Returns: S_FALSE to
signal Exchange to continue calling extensions. PEECB is a pointer
to the IExchExtCallback interface. */
STDMETHODIMP
CGPGExchExtMessageEvents
::
OnRead
(
LPEXCHEXTCALLBACK
pEECB
)
{
LPMDB
pMDB
=
NULL
;
LPMESSAGE
pMessage
=
NULL
;
log_debug
(
"%s:%s: received
\n
"
,
__FILE__
,
__func__
);
pEECB
->
GetObject
(
&
pMDB
,
(
LPMAPIPROP
*
)
&
pMessage
);
show_mapi_property
(
pMessage
,
PR_SEARCH_KEY
,
"SEARCH_KEY"
);
msgcache_set_active
(
pMessage
);
if
(
pMessage
)
UlRelease
(
pMessage
);
if
(
pMDB
)
UlRelease
(
pMDB
);
return
S_FALSE
;
}
/* Called by Exchange after a message has been read. Returns: S_FALSE
to signal Exchange to continue calling extensions. PEECB is a
pointer to the IExchExtCallback interface. LFLAGS are some flags. */
STDMETHODIMP
CGPGExchExtMessageEvents
::
OnReadComplete
(
LPEXCHEXTCALLBACK
pEECB
,
ULONG
lFlags
)
{
log_debug
(
"%s:%s: received
\n
"
,
__FILE__
,
__func__
);
return
S_FALSE
;
}
/* Called by Exchange when a message will be written. Returns: S_FALSE
to signal Exchange to continue calling extensions. PEECB is a
pointer to the IExchExtCallback interface. */
STDMETHODIMP
CGPGExchExtMessageEvents
::
OnWrite
(
LPEXCHEXTCALLBACK
pEECB
)
{
log_debug
(
"%s:%s: received
\n
"
,
__FILE__
,
__func__
);
return
S_FALSE
;
}
/* Called by Exchange when the data has been written to the message.
Encrypts and signs the message if the options are set. PEECB is a
pointer to the IExchExtCallback interface. Returns: S_FALSE to
signal Exchange to continue calling extensions. E_FAIL to signals
Exchange an error; the message will not be sent */
STDMETHODIMP
CGPGExchExtMessageEvents
::
OnWriteComplete
(
LPEXCHEXTCALLBACK
pEECB
,
ULONG
lFlags
)
{
log_debug
(
"%s:%s: received
\n
"
,
__FILE__
,
__func__
);
HRESULT
hrReturn
=
S_FALSE
;
LPMESSAGE
msg
=
NULL
;
LPMDB
pMDB
=
NULL
;
HWND
hWnd
=
NULL
;
int
rc
;
if
(
FAILED
(
pEECB
->
GetWindow
(
&
hWnd
)))
hWnd
=
NULL
;
if
(
!
m_bOnSubmitActive
)
/* the user is just saving the message */
return
S_FALSE
;
if
(
m_bWriteFailed
)
/* operation failed already */
return
S_FALSE
;
HRESULT
hr
=
pEECB
->
GetObject
(
&
pMDB
,
(
LPMAPIPROP
*
)
&
msg
);
if
(
SUCCEEDED
(
hr
))
{
GpgMsg
*
m
=
CreateGpgMsg
(
msg
);
if
(
m_pExchExt
->
m_gpgEncrypt
&&
m_pExchExt
->
m_gpgSign
)
rc
=
m
->
signEncrypt
(
hWnd
);
if
(
m_pExchExt
->
m_gpgEncrypt
&&
!
m_pExchExt
->
m_gpgSign
)
rc
=
m
->
encrypt
(
hWnd
);
if
(
!
m_pExchExt
->
m_gpgEncrypt
&&
m_pExchExt
->
m_gpgSign
)
rc
=
m
->
sign
(
hWnd
);
else
rc
=
0
;
delete
m
;
if
(
rc
)
{
hrReturn
=
E_FAIL
;
m_bWriteFailed
=
TRUE
;
}
}
if
(
msg
)
UlRelease
(
msg
);
if
(
pMDB
)
UlRelease
(
pMDB
);
return
hrReturn
;
}
/* Called by Exchange when the user selects the "check names" command.
PEECB is a pointer to the IExchExtCallback interface. Returns
S_FALSE to signal Exchange to continue calling extensions. */
STDMETHODIMP
CGPGExchExtMessageEvents
::
OnCheckNames
(
LPEXCHEXTCALLBACK
pEECB
)
{
log_debug
(
"%s:%s: received
\n
"
,
__FILE__
,
__func__
);
return
S_FALSE
;
}
/* Called by Exchange when "check names" command is complete.
PEECB is a pointer to the IExchExtCallback interface. Returns
S_FALSE to signal Exchange to continue calling extensions. */
STDMETHODIMP
CGPGExchExtMessageEvents
::
OnCheckNamesComplete
(
LPEXCHEXTCALLBACK
pEECB
,
ULONG
lFlags
)
{
log_debug
(
"%s:%s: received
\n
"
,
__FILE__
,
__func__
);
return
S_FALSE
;
}
/* Called by Exchange before the message data will be written and
submitted to MAPI. PEECB is a pointer to the IExchExtCallback
interface. Returns S_FALSE to signal Exchange to continue calling
extensions. */
STDMETHODIMP
CGPGExchExtMessageEvents
::
OnSubmit
(
LPEXCHEXTCALLBACK
pEECB
)
{
log_debug
(
"%s:%s: received
\n
"
,
__FILE__
,
__func__
);
m_bOnSubmitActive
=
TRUE
;
m_bWriteFailed
=
FALSE
;
return
S_FALSE
;
}
/* Called by Echange after the message has been submitted to MAPI.
PEECB is a pointer to the IExchExtCallback interface. */
STDMETHODIMP_
(
VOID
)
CGPGExchExtMessageEvents
::
OnSubmitComplete
(
LPEXCHEXTCALLBACK
pEECB
,
ULONG
lFlags
)
{
log_debug
(
"%s:%s: received
\n
"
,
__FILE__
,
__func__
);
m_bOnSubmitActive
=
FALSE
;
}
CGPGExchExtCommands
::
CGPGExchExtCommands
(
CGPGExchExt
*
pParentInterface
)
{
m_pExchExt
=
pParentInterface
;
m_lRef
=
0
;
m_lContext
=
0
;
m_nCmdEncrypt
=
0
;
m_nCmdSign
=
0
;
m_nToolbarButtonID1
=
0
;
m_nToolbarButtonID2
=
0
;
m_nToolbarBitmap1
=
0
;
m_nToolbarBitmap2
=
0
;
m_hWnd
=
NULL
;
};
STDMETHODIMP
CGPGExchExtCommands
::
QueryInterface
(
REFIID
riid
,
LPVOID
FAR
*
ppvObj
)
{
*
ppvObj
=
NULL
;
if
((
riid
==
IID_IExchExtCommands
)
||
(
riid
==
IID_IUnknown
))
{
*
ppvObj
=
(
LPVOID
)
this
;
AddRef
();
return
S_OK
;
}
return
E_NOINTERFACE
;
}
// We can't read the Body object because it would fire up the
// security pop-up. Writing is okay.
// vtResult.pdispVal = NULL;
// pDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
// DISPATCH_PROPERTYGET, &dispparamsNoArgs,
// &vtResult, NULL, NULL);
// log_debug ("%s:%s: Body=%p (%s)\n", __FILE__, __func__,
// vtResult.pbVal,
// (tmp = wchar_to_utf8 ((wchar_t*)vtResult.pbVal)));
// XXX IExchExtSessionEvents::OnDelivery: could be used to automatically decrypt new mails
// when they arrive
/* Called by Echange to install commands and toolbar buttons. Returns
S_FALSE to signal Exchange to continue calling extensions. */
STDMETHODIMP
CGPGExchExtCommands
::
InstallCommands
(
LPEXCHEXTCALLBACK
pEECB
,
// The Exchange Callback Interface.
HWND
hWnd
,
// The window handle to the main window
// of context.
HMENU
hMenu
,
// The menu handle to main menu of context.
UINT
FAR
*
pnCommandIDBase
,
// The base conmmand id.
LPTBENTRY
pTBEArray
,
// The array of toolbar button entries.
UINT
nTBECnt
,
// The count of button entries in array.
ULONG
lFlags
)
// reserved
{
HRESULT
hr
;
HMENU
hMenuTools
;
m_hWnd
=
hWnd
;
LPDISPATCH
pDisp
;
DISPID
dispid
;
DISPID
dispid_put
=
DISPID_PROPERTYPUT
;
DISPPARAMS
dispparams
;
VARIANT
aVariant
;
int
force_encrypt
=
0
;
log_debug
(
"%s:%s: context=0x%lx (%s) flags=0x%lx
\n
"
,
__FILE__
,
__func__
,
m_lContext
,
(
m_lContext
==
EECONTEXT_SESSION
?
"Session"
:
m_lContext
==
EECONTEXT_VIEWER
?
"Viewer"
:
m_lContext
==
EECONTEXT_REMOTEVIEWER
?
"RemoteViewer"
:
m_lContext
==
EECONTEXT_SEARCHVIEWER
?
"SearchViewer"
:
m_lContext
==
EECONTEXT_ADDRBOOK
?
"AddrBook"
:
m_lContext
==
EECONTEXT_SENDNOTEMESSAGE
?
"SendNoteMessage"
:
m_lContext
==
EECONTEXT_READNOTEMESSAGE
?
"ReadNoteMessage"
:
m_lContext
==
EECONTEXT_SENDPOSTMESSAGE
?
"SendPostMessage"
:
m_lContext
==
EECONTEXT_READPOSTMESSAGE
?
"ReadPostMessage"
:
m_lContext
==
EECONTEXT_READREPORTMESSAGE
?
"ReadReportMessage"
:
m_lContext
==
EECONTEXT_SENDRESENDMESSAGE
?
"SendResendMessage"
:
m_lContext
==
EECONTEXT_PROPERTYSHEETS
?
"PropertySheets"
:
m_lContext
==
EECONTEXT_ADVANCEDCRITERIA
?
"AdvancedCriteria"
:
m_lContext
==
EECONTEXT_TASK
?
"Task"
:
""
),
lFlags
);
if
(
m_lContext
==
EECONTEXT_READNOTEMESSAGE
||
m_lContext
==
EECONTEXT_SENDNOTEMESSAGE
)
{
LPMDB
pMDB
=
NULL
;
LPMESSAGE
pMessage
=
NULL
;
pEECB
->
GetObject
(
&
pMDB
,
(
LPMAPIPROP
*
)
&
pMessage
);
show_mapi_property
(
pMessage
,
PR_ENTRYID
,
"ENTRYID"
);
show_mapi_property
(
pMessage
,
PR_SEARCH_KEY
,
"SEARCH_KEY"
);
if
(
pMessage
)
UlRelease
(
pMessage
);
if
(
pMDB
)
UlRelease
(
pMDB
);
}
/* Outlook 2003 sometimes displays the plaintext sometimes the
orginal undecrypted text when doing a Reply. This seems to
depend on the sieze of the message; my guess it that only short
messages are locally saved in the process and larger ones are
fetyched again from the backend - or the other way around.
Anyway, we can't rely on that and thus me make sure to update the
Body object right here with our own copy of the plaintext. To
match the text we use the Storage ID Property of MAPI.
Unfortunately there seems to be no way of resetting the Saved
property after updating the body, thus even without entering a
single byte the user will be asked when cancelling a reply
whether he really wants to do that.
Note, that we can't optimize the code here by first reading the
body becuase this would pop up the securiy window, telling tghe
user that someone is trying to read these data.
*/
if
(
m_lContext
==
EECONTEXT_SENDNOTEMESSAGE
)
{
LPMDB
pMDB
=
NULL
;
LPMESSAGE
pMessage
=
NULL
;
const
char
*
body
;
void
*
refhandle
=
NULL
;
/* Note that for read and send the object returned by the
outlook extension callback is of class 43 (MailItem) so we
only need to ask for Body then. */
hr
=
pEECB
->
GetObject
(
&
pMDB
,
(
LPMAPIPROP
*
)
&
pMessage
);
if
(
FAILED
(
hr
))
log_debug
(
"%s:%s: getObject failed: hr=%#x
\n
"
,
hr
);
else
if
(
(
body
=
msgcache_get
(
pMessage
,
&
refhandle
))
&&
(
pDisp
=
find_outlook_property
(
pEECB
,
"Body"
,
&
dispid
)))
{
dispparams
.
cNamedArgs
=
1
;
dispparams
.
rgdispidNamedArgs
=
&
dispid_put
;
dispparams
.
cArgs
=
1
;
dispparams
.
rgvarg
=
&
aVariant
;
dispparams
.
rgvarg
[
0
].
vt
=
VT_LPWSTR
;
dispparams
.
rgvarg
[
0
].
bstrVal
=
utf8_to_wchar
(
body
);
hr
=
pDisp
->
Invoke
(
dispid
,
IID_NULL
,
LOCALE_SYSTEM_DEFAULT
,
DISPATCH_PROPERTYPUT
,
&
dispparams
,
NULL
,
NULL
,
NULL
);
xfree
(
dispparams
.
rgvarg
[
0
].
bstrVal
);
log_debug
(
"%s:%s: PROPERTYPUT(body) result -> %d
\n
"
,
__FILE__
,
__func__
,
hr
);
pDisp
->
Release
();
pDisp
=
NULL
;
/* Because we found the plaintext in the cache we can assume
that the orginal message has been encrypted and thus we
now set a flag to make sure that by default the reply
gets encrypted too. */
force_encrypt
=
1
;
}
msgcache_unref
(
refhandle
);
if
(
pMessage
)
UlRelease
(
pMessage
);
if
(
pMDB
)
UlRelease
(
pMDB
);
}
/* XXX: factor out common code */
if
(
m_lContext
==
EECONTEXT_READNOTEMESSAGE
)
{
int
nTBIndex
;
HWND
hwndToolbar
=
NULL
;
CHAR
szBuffer
[
128
];
pEECB
->
GetMenuPos
(
EECMDID_ToolsCustomizeToolbar
,
&
hMenuTools
,
NULL
,
NULL
,
0
);
AppendMenu
(
hMenuTools
,
MF_SEPARATOR
,
0
,
NULL
);
LoadString
(
glob_hinst
,
IDS_DECRYPT_MENU_ITEM
,
szBuffer
,
128
);
AppendMenu
(
hMenuTools
,
MF_BYPOSITION
|
MF_STRING
,
*
pnCommandIDBase
,
szBuffer
);
m_nCmdEncrypt
=
*
pnCommandIDBase
;
(
*
pnCommandIDBase
)
++
;
for
(
nTBIndex
=
nTBECnt
-1
;
nTBIndex
>
-1
;
--
nTBIndex
)
{
if
(
EETBID_STANDARD
==
pTBEArray
[
nTBIndex
].
tbid
)
{
hwndToolbar
=
pTBEArray
[
nTBIndex
].
hwnd
;
m_nToolbarButtonID1
=
pTBEArray
[
nTBIndex
].
itbbBase
;
pTBEArray
[
nTBIndex
].
itbbBase
++
;
break
;
}
}
if
(
hwndToolbar
)
{
TBADDBITMAP
tbab
;
tbab
.
hInst
=
glob_hinst
;
tbab
.
nID
=
IDB_DECRYPT
;
m_nToolbarBitmap1
=
SendMessage
(
hwndToolbar
,
TB_ADDBITMAP
,
1
,
(
LPARAM
)
&
tbab
);
m_nToolbarButtonID2
=
pTBEArray
[
nTBIndex
].
itbbBase
;
pTBEArray
[
nTBIndex
].
itbbBase
++
;
}
}
if
(
m_lContext
==
EECONTEXT_SENDNOTEMESSAGE
)
{
CHAR
szBuffer
[
128
];
int
nTBIndex
;
HWND
hwndToolbar
=
NULL
;
pEECB
->
GetMenuPos
(
EECMDID_ToolsCustomizeToolbar
,
&
hMenuTools
,
NULL
,
NULL
,
0
);
AppendMenu
(
hMenuTools
,
MF_SEPARATOR
,
0
,
NULL
);
LoadString
(
glob_hinst
,
IDS_ENCRYPT_MENU_ITEM
,
szBuffer
,
128
);
AppendMenu
(
hMenuTools
,
MF_BYPOSITION
|
MF_STRING
,
*
pnCommandIDBase
,
szBuffer
);
m_nCmdEncrypt
=
*
pnCommandIDBase
;
(
*
pnCommandIDBase
)
++
;
LoadString
(
glob_hinst
,
IDS_SIGN_MENU_ITEM
,
szBuffer
,
128
);
AppendMenu
(
hMenuTools
,
MF_BYPOSITION
|
MF_STRING
,
*
pnCommandIDBase
,
szBuffer
);
m_nCmdSign
=
*
pnCommandIDBase
;
(
*
pnCommandIDBase
)
++
;
for
(
nTBIndex
=
nTBECnt
-1
;
nTBIndex
>
-1
;
--
nTBIndex
)
{
if
(
EETBID_STANDARD
==
pTBEArray
[
nTBIndex
].
tbid
)
{
hwndToolbar
=
pTBEArray
[
nTBIndex
].
hwnd
;
m_nToolbarButtonID1
=
pTBEArray
[
nTBIndex
].
itbbBase
;
pTBEArray
[
nTBIndex
].
itbbBase
++
;
break
;
}
}
if
(
hwndToolbar
)
{
TBADDBITMAP
tbab
;
tbab
.
hInst
=
glob_hinst
;
tbab
.
nID
=
IDB_ENCRYPT
;
m_nToolbarBitmap1
=
SendMessage
(
hwndToolbar
,
TB_ADDBITMAP
,
1
,
(
LPARAM
)
&
tbab
);
m_nToolbarButtonID2
=
pTBEArray
[
nTBIndex
].
itbbBase
;
pTBEArray
[
nTBIndex
].
itbbBase
++
;
tbab
.
nID
=
IDB_SIGN
;
m_nToolbarBitmap2
=
SendMessage
(
hwndToolbar
,
TB_ADDBITMAP
,
1
,
(
LPARAM
)
&
tbab
);
}
m_pExchExt
->
m_gpgEncrypt
=
opt
.
encrypt_default
;
m_pExchExt
->
m_gpgSign
=
opt
.
sign_default
;
if
(
force_encrypt
)
m_pExchExt
->
m_gpgEncrypt
=
true
;
}
if
(
m_lContext
==
EECONTEXT_VIEWER
)
{
CHAR
szBuffer
[
128
];
int
nTBIndex
;
HWND
hwndToolbar
=
NULL
;
pEECB
->
GetMenuPos
(
EECMDID_ToolsCustomizeToolbar
,
&
hMenuTools
,
NULL
,
NULL
,
0
);
AppendMenu
(
hMenuTools
,
MF_SEPARATOR
,
0
,
NULL
);
LoadString
(
glob_hinst
,
IDS_KEY_MANAGER
,
szBuffer
,
128
);
AppendMenu
(
hMenuTools
,
MF_BYPOSITION
|
MF_STRING
,
*
pnCommandIDBase
,
szBuffer
);
m_nCmdEncrypt
=
*
pnCommandIDBase
;
(
*
pnCommandIDBase
)
++
;
for
(
nTBIndex
=
nTBECnt
-1
;
nTBIndex
>
-1
;
--
nTBIndex
)
{
if
(
EETBID_STANDARD
==
pTBEArray
[
nTBIndex
].
tbid
)
{
hwndToolbar
=
pTBEArray
[
nTBIndex
].
hwnd
;
m_nToolbarButtonID1
=
pTBEArray
[
nTBIndex
].
itbbBase
;
pTBEArray
[
nTBIndex
].
itbbBase
++
;
break
;
}
}
if
(
hwndToolbar
)
{
TBADDBITMAP
tbab
;
tbab
.
hInst
=
glob_hinst
;
tbab
.
nID
=
IDB_KEY_MANAGER
;
m_nToolbarBitmap1
=
SendMessage
(
hwndToolbar
,
TB_ADDBITMAP
,
1
,
(
LPARAM
)
&
tbab
);
}
}
return
S_FALSE
;
}
/* Called by Exchange when a user selects a command. Return value:
S_OK if command is handled, otherwise S_FALSE. */
STDMETHODIMP
CGPGExchExtCommands
::
DoCommand
(
LPEXCHEXTCALLBACK
pEECB
,
// The Exchange Callback Interface.
UINT
nCommandID
)
// The command id.
{
HRESULT
hr
;
if
((
nCommandID
!=
m_nCmdEncrypt
)
&&
(
nCommandID
!=
m_nCmdSign
))
return
S_FALSE
;
if
(
m_lContext
==
EECONTEXT_READNOTEMESSAGE
)
{
HWND
hWnd
=
NULL
;
LPMESSAGE
pMessage
=
NULL
;
LPMDB
pMDB
=
NULL
;
if
(
FAILED
(
pEECB
->
GetWindow
(
&
hWnd
)))
hWnd
=
NULL
;
hr
=
pEECB
->
GetObject
(
&
pMDB
,
(
LPMAPIPROP
*
)
&
pMessage
);
if
(
SUCCEEDED
(
hr
))
{
show_mapi_property
(
pMessage
,
PR_SEARCH_KEY
,
"SEARCH_KEY"
);
if
(
nCommandID
==
m_nCmdEncrypt
)
{
GpgMsg
*
m
=
CreateGpgMsg
(
pMessage
);
m
->
decrypt
(
hWnd
);
delete
m
;
}
}
if
(
pMessage
)
UlRelease
(
pMessage
);
if
(
pMDB
)
UlRelease
(
pMDB
);
}
else
if
(
m_lContext
==
EECONTEXT_SENDNOTEMESSAGE
)
{
if
(
nCommandID
==
m_nCmdEncrypt
)
m_pExchExt
->
m_gpgEncrypt
=
!
m_pExchExt
->
m_gpgEncrypt
;
if
(
nCommandID
==
m_nCmdSign
)
m_pExchExt
->
m_gpgSign
=
!
m_pExchExt
->
m_gpgSign
;
}
else
if
(
m_lContext
==
EECONTEXT_VIEWER
)
{
if
(
start_key_manager
())
MessageBox
(
NULL
,
"Could not start Key-Manager"
,
"OutlGPG"
,
MB_ICONERROR
|
MB_OK
);
}
return
S_OK
;
}
STDMETHODIMP_
(
VOID
)
CGPGExchExtCommands
::
InitMenu
(
LPEXCHEXTCALLBACK
pEECB
)
{
}
/* Called by Exhange when the user requests help for a menu item.
Return value: S_OK when it is a menu item of this plugin and the
help was shown; otherwise S_FALSE. */
STDMETHODIMP
CGPGExchExtCommands
::
Help
(
LPEXCHEXTCALLBACK
pEECB
,
// The pointer to Exchange Callback Interface.
UINT
nCommandID
)
// The command id.
{
if
(
m_lContext
==
EECONTEXT_READNOTEMESSAGE
)
{
if
(
nCommandID
==
m_nCmdEncrypt
)
{
CHAR
szBuffer
[
512
];
CHAR
szAppName
[
128
];
LoadString
(
glob_hinst
,
IDS_DECRYPT_HELP
,
szBuffer
,
511
);
LoadString
(
glob_hinst
,
IDS_APP_NAME
,
szAppName
,
127
);
MessageBox
(
m_hWnd
,
szBuffer
,
szAppName
,
MB_OK
);
return
S_OK
;
}
}
if
(
m_lContext
==
EECONTEXT_SENDNOTEMESSAGE
)
{
if
(
nCommandID
==
m_nCmdEncrypt
)
{
CHAR
szBuffer
[
512
];
CHAR
szAppName
[
128
];
LoadString
(
glob_hinst
,
IDS_ENCRYPT_HELP
,
szBuffer
,
511
);
LoadString
(
glob_hinst
,
IDS_APP_NAME
,
szAppName
,
127
);
MessageBox
(
m_hWnd
,
szBuffer
,
szAppName
,
MB_OK
);
return
S_OK
;
}
if
(
nCommandID
==
m_nCmdSign
)
{
CHAR
szBuffer
[
512
];
CHAR
szAppName
[
128
];
LoadString
(
glob_hinst
,
IDS_SIGN_HELP
,
szBuffer
,
511
);
LoadString
(
glob_hinst
,
IDS_APP_NAME
,
szAppName
,
127
);
MessageBox
(
m_hWnd
,
szBuffer
,
szAppName
,
MB_OK
);
return
S_OK
;
}
}
if
(
m_lContext
==
EECONTEXT_VIEWER
)
{
if
(
nCommandID
==
m_nCmdEncrypt
)
{
CHAR
szBuffer
[
512
];
CHAR
szAppName
[
128
];
LoadString
(
glob_hinst
,
IDS_KEY_MANAGER_HELP
,
szBuffer
,
511
);
LoadString
(
glob_hinst
,
IDS_APP_NAME
,
szAppName
,
127
);
MessageBox
(
m_hWnd
,
szBuffer
,
szAppName
,
MB_OK
);
return
S_OK
;
}
}
return
S_FALSE
;
}
/* Called by Exhange to get the status bar text or the tooltip of a
menu item. Returns S_OK when it is a menu item of this plugin and
the text was set; otherwise S_FALSE. */
STDMETHODIMP
CGPGExchExtCommands
::
QueryHelpText
(
UINT
nCommandID
,
// The command id corresponding to the
// menu item activated.
ULONG
lFlags
,
// Identifies either EECQHT_STATUS
// or EECQHT_TOOLTIP.
LPTSTR
pszText
,
// A pointer to buffer to be populated
// with text to display.
UINT
nCharCnt
)
// The count of characters available in psz buffer.
{
if
(
m_lContext
==
EECONTEXT_READNOTEMESSAGE
)
{
if
(
nCommandID
==
m_nCmdEncrypt
)
{
if
(
lFlags
==
EECQHT_STATUS
)
LoadString
(
glob_hinst
,
IDS_DECRYPT_STATUSBAR
,
pszText
,
nCharCnt
);
if
(
lFlags
==
EECQHT_TOOLTIP
)
LoadString
(
glob_hinst
,
IDS_DECRYPT_TOOLTIP
,
pszText
,
nCharCnt
);
return
S_OK
;
}
}
if
(
m_lContext
==
EECONTEXT_SENDNOTEMESSAGE
)
{
if
(
nCommandID
==
m_nCmdEncrypt
)
{
if
(
lFlags
==
EECQHT_STATUS
)
LoadString
(
glob_hinst
,
IDS_ENCRYPT_STATUSBAR
,
pszText
,
nCharCnt
);
if
(
lFlags
==
EECQHT_TOOLTIP
)
LoadString
(
glob_hinst
,
IDS_ENCRYPT_TOOLTIP
,
pszText
,
nCharCnt
);
return
S_OK
;
}
if
(
nCommandID
==
m_nCmdSign
)
{
if
(
lFlags
==
EECQHT_STATUS
)
LoadString
(
glob_hinst
,
IDS_SIGN_STATUSBAR
,
pszText
,
nCharCnt
);
if
(
lFlags
==
EECQHT_TOOLTIP
)
LoadString
(
glob_hinst
,
IDS_SIGN_TOOLTIP
,
pszText
,
nCharCnt
);
return
S_OK
;
}
}
if
(
m_lContext
==
EECONTEXT_VIEWER
)
{
if
(
nCommandID
==
m_nCmdEncrypt
)
{
if
(
lFlags
==
EECQHT_STATUS
)
LoadString
(
glob_hinst
,
IDS_KEY_MANAGER_STATUSBAR
,
pszText
,
nCharCnt
);
if
(
lFlags
==
EECQHT_TOOLTIP
)
LoadString
(
glob_hinst
,
IDS_KEY_MANAGER_TOOLTIP
,
pszText
,
nCharCnt
);
return
S_OK
;
}
}
return
S_FALSE
;
}
/* Called by Exchange to get toolbar button infos. Returns S_OK when
it is a button of this plugin and the requested info was delivered;
otherwise S_FALSE. */
STDMETHODIMP
CGPGExchExtCommands
::
QueryButtonInfo
(
ULONG
lToolbarID
,
// The toolbar identifier.
UINT
nToolbarButtonID
,
// The toolbar button index.
LPTBBUTTON
pTBB
,
// A pointer to toolbar button structure
// (see TBBUTTON structure).
LPTSTR
lpszDescription
,
// A pointer to string describing button.
UINT
nCharCnt
,
// The maximum size of lpsz buffer.
ULONG
lFlags
)
// EXCHEXT_UNICODE may be specified
{
if
(
m_lContext
==
EECONTEXT_READNOTEMESSAGE
)
{
if
(
nToolbarButtonID
==
m_nToolbarButtonID1
)
{
pTBB
->
iBitmap
=
m_nToolbarBitmap1
;
pTBB
->
idCommand
=
m_nCmdEncrypt
;
pTBB
->
fsState
=
TBSTATE_ENABLED
;
pTBB
->
fsStyle
=
TBSTYLE_BUTTON
;
pTBB
->
dwData
=
0
;
pTBB
->
iString
=
-1
;
LoadString
(
glob_hinst
,
IDS_DECRYPT_TOOLTIP
,
lpszDescription
,
nCharCnt
);
return
S_OK
;
}
}
if
(
m_lContext
==
EECONTEXT_SENDNOTEMESSAGE
)
{
if
(
nToolbarButtonID
==
m_nToolbarButtonID1
)
{
pTBB
->
iBitmap
=
m_nToolbarBitmap1
;
pTBB
->
idCommand
=
m_nCmdEncrypt
;
pTBB
->
fsState
=
TBSTATE_ENABLED
;
if
(
m_pExchExt
->
m_gpgEncrypt
)
pTBB
->
fsState
|=
TBSTATE_CHECKED
;
pTBB
->
fsStyle
=
TBSTYLE_BUTTON
|
TBSTYLE_CHECK
;
pTBB
->
dwData
=
0
;
pTBB
->
iString
=
-1
;
LoadString
(
glob_hinst
,
IDS_ENCRYPT_TOOLTIP
,
lpszDescription
,
nCharCnt
);
return
S_OK
;
}
if
(
nToolbarButtonID
==
m_nToolbarButtonID2
)
{
pTBB
->
iBitmap
=
m_nToolbarBitmap2
;
pTBB
->
idCommand
=
m_nCmdSign
;
pTBB
->
fsState
=
TBSTATE_ENABLED
;
if
(
m_pExchExt
->
m_gpgSign
)
pTBB
->
fsState
|=
TBSTATE_CHECKED
;
pTBB
->
fsStyle
=
TBSTYLE_BUTTON
|
TBSTYLE_CHECK
;
pTBB
->
dwData
=
0
;
pTBB
->
iString
=
-1
;
LoadString
(
glob_hinst
,
IDS_SIGN_TOOLTIP
,
lpszDescription
,
nCharCnt
);
return
S_OK
;
}
}
if
(
m_lContext
==
EECONTEXT_VIEWER
)
{
if
(
nToolbarButtonID
==
m_nToolbarButtonID1
)
{
pTBB
->
iBitmap
=
m_nToolbarBitmap1
;
pTBB
->
idCommand
=
m_nCmdEncrypt
;
pTBB
->
fsState
=
TBSTATE_ENABLED
;
pTBB
->
fsStyle
=
TBSTYLE_BUTTON
;
pTBB
->
dwData
=
0
;
pTBB
->
iString
=
-1
;
LoadString
(
glob_hinst
,
IDS_KEY_MANAGER_TOOLTIP
,
lpszDescription
,
nCharCnt
);
return
S_OK
;
}
}
return
S_FALSE
;
}
STDMETHODIMP
CGPGExchExtCommands
::
ResetToolbar
(
ULONG
lToolbarID
,
ULONG
lFlags
)
{
return
S_OK
;
}
CGPGExchExtPropertySheets
::
CGPGExchExtPropertySheets
(
CGPGExchExt
*
pParentInterface
)
{
m_pExchExt
=
pParentInterface
;
m_lRef
=
0
;
}
STDMETHODIMP
CGPGExchExtPropertySheets
::
QueryInterface
(
REFIID
riid
,
LPVOID
FAR
*
ppvObj
)
{
*
ppvObj
=
NULL
;
if
(
riid
==
IID_IExchExtPropertySheets
)
{
*
ppvObj
=
(
LPVOID
)
this
;
AddRef
();
return
S_OK
;
}
if
(
riid
==
IID_IUnknown
)
{
*
ppvObj
=
(
LPVOID
)
m_pExchExt
;
m_pExchExt
->
AddRef
();
return
S_OK
;
}
return
E_NOINTERFACE
;
}
/* Called by Echange to get the maximum number of property pages which
are to be added. LFLAGS is a bitmask indicating what type of
property sheet is being displayed. Return value: The maximum number
of custom pages for the property sheet. */
STDMETHODIMP_
(
ULONG
)
CGPGExchExtPropertySheets
::
GetMaxPageCount
(
ULONG
lFlags
)
{
if
(
lFlags
==
EEPS_TOOLSOPTIONS
)
return
1
;
return
0
;
}
/* Called by Exchange to request information about the property page.
Return value: S_OK to signal Echange to use the pPSP
information. */
STDMETHODIMP
CGPGExchExtPropertySheets
::
GetPages
(
LPEXCHEXTCALLBACK
pEECB
,
// A pointer to Exchange callback interface.
ULONG
lFlags
,
// A bitmask indicating what type of
// property sheet is being displayed.
LPPROPSHEETPAGE
pPSP
,
// The output parm pointing to pointer
// to list of property sheets.
ULONG
FAR
*
plPSP
)
// The output parm pointing to buffer
// containing the number of property
// sheets actually used.
{
int
resid
=
0
;
switch
(
GetUserDefaultLangID
())
{
case
0x0407
:
resid
=
IDD_GPG_OPTIONS_DE
;
break
;
default
:
resid
=
IDD_GPG_OPTIONS
;
break
;
}
pPSP
[
0
].
dwSize
=
sizeof
(
PROPSHEETPAGE
);
pPSP
[
0
].
dwFlags
=
PSP_DEFAULT
|
PSP_HASHELP
;
pPSP
[
0
].
hInstance
=
glob_hinst
;
pPSP
[
0
].
pszTemplate
=
MAKEINTRESOURCE
(
resid
);
pPSP
[
0
].
hIcon
=
NULL
;
pPSP
[
0
].
pszTitle
=
NULL
;
pPSP
[
0
].
pfnDlgProc
=
(
DLGPROC
)
GPGOptionsDlgProc
;
pPSP
[
0
].
lParam
=
0
;
pPSP
[
0
].
pfnCallback
=
NULL
;
pPSP
[
0
].
pcRefParent
=
NULL
;
*
plPSP
=
1
;
return
S_OK
;
}
STDMETHODIMP_
(
VOID
)
CGPGExchExtPropertySheets
::
FreePages
(
LPPROPSHEETPAGE
pPSP
,
ULONG
lFlags
,
ULONG
lPSP
)
{
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Sun, Jan 4, 5:45 AM (1 d, 4 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
0a/09/1e1c8c29fe4657dd38bbccac6011
Attached To
rO GpgOL
Event Timeline
Log In to Comment