Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F18825796
message-events.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
11 KB
Subscribers
None
message-events.cpp
View Options
/* message-events.cpp - Subclass impl of IExchExtMessageEvents
* Copyright (C) 2004, 2005, 2007, 2008 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
"mymapi.h"
#include
"mymapitags.h"
#include
"myexchext.h"
#include
"display.h"
#include
"common.h"
#include
"msgcache.h"
#include
"mapihelp.h"
#include
"olflange-def.h"
#include
"olflange.h"
#include
"mimeparser.h"
#include
"mimemaker.h"
#include
"message.h"
#include
"message-events.h"
#include
"explorers.h"
#include
"inspectors.h"
/* Wrapper around UlRelease with error checking. */
static
void
ul_release
(
LPVOID
punk
,
const
char
*
func
,
int
lnr
)
{
ULONG
res
;
if
(
!
punk
)
return
;
res
=
UlRelease
(
punk
);
if
(
opt
.
enable_debug
&
DBG_MEMORY
)
log_debug
(
"%s:%s:%d: UlRelease(%p) had %lu references
\n
"
,
SRCNAME
,
func
,
lnr
,
punk
,
res
);
}
/* Our constructor. */
GpgolMessageEvents
::
GpgolMessageEvents
(
GpgolExt
*
pParentInterface
)
{
m_pExchExt
=
pParentInterface
;
m_lRef
=
0
;
m_bOnSubmitActive
=
false
;
m_want_html
=
false
;
m_processed
=
false
;
m_wasencrypted
=
false
;
m_gotinspector
=
false
;
}
/* The QueryInterfac. */
STDMETHODIMP
GpgolMessageEvents
::
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
;
}
static
int
get_crypto_flags
(
HWND
hwnd
,
bool
*
r_sign
,
bool
*
r_encrypt
)
{
LPDISPATCH
inspector
;
int
rc
;
inspector
=
get_inspector_from_hwnd
(
hwnd
);
if
(
!
inspector
)
{
log_error
(
"%s:%s: inspector not found"
,
SRCNAME
,
__func__
);
rc
=
-1
;
}
else
{
rc
=
get_inspector_composer_flags
(
inspector
,
r_sign
,
r_encrypt
);
gpgol_release
(
inspector
);
}
return
rc
;
}
/* 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. */
STDMETHODIMP
GpgolMessageEvents
::
OnRead
(
LPEXCHEXTCALLBACK
eecb
)
{
HWND
hwnd
=
NULL
;
LPMDB
mdb
=
NULL
;
LPMESSAGE
message
=
NULL
;
m_wasencrypted
=
false
;
if
(
FAILED
(
eecb
->
GetWindow
(
&
hwnd
)))
hwnd
=
NULL
;
m_gotinspector
=
!!
is_inspector_display
(
hwnd
);
log_debug
(
"%s:%s: received (hwnd=%p) %s
\n
"
,
SRCNAME
,
__func__
,
hwnd
,
m_gotinspector
?
"got_inspector"
:
""
);
/* Fixme: If preview decryption is not enabled and we have an
encrypted message, we might want to show a greyed out preview
window. There are two ways to clear the preview window:
- Change the message class to something unknown to Outlook, like
IPM.GpgOL. This shows a grey and empty preview window.
- Set flag 0x2000 in the 0x8510 property (SideEffects). This
shows a grey window with a notice that the message can't be
shown due to active content. */
/* The is_inspector_display function is not reliable enough.
Missing another solution we set it to true for now with the
result that the preview decryption can't be disabled. */
m_gotinspector
=
1
;
if
(
(
m_gotinspector
||
opt
.
preview_decrypt
)
&&
!
opt
.
disable_gpgol
)
{
eecb
->
GetObject
(
&
mdb
,
(
LPMAPIPROP
*
)
&
message
);
switch
(
message_incoming_handler
(
message
,
hwnd
,
false
))
{
case
1
:
m_processed
=
true
;
break
;
case
2
:
m_processed
=
true
;
m_wasencrypted
=
true
;
break
;
default
:
;
}
ul_release
(
message
,
__func__
,
__LINE__
);
ul_release
(
mdb
,
__func__
,
__LINE__
);
}
return
S_FALSE
;
}
/* Called by Exchange after a message has been read. Returns: S_FALSE
to signal Exchange to continue calling extensions. EECB is a
pointer to the IExchExtCallback interface. FLAGS are some flags. */
STDMETHODIMP
GpgolMessageEvents
::
OnReadComplete
(
LPEXCHEXTCALLBACK
eecb
,
ULONG
flags
)
{
log_debug
(
"%s:%s: received; flags=%#lx m_processed=%d
\n
"
,
SRCNAME
,
__func__
,
flags
,
m_processed
);
/* 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
)
{
HRESULT
hr
;
LPMDB
mdb
=
NULL
;
LPMESSAGE
message
=
NULL
;
HWND
hwnd
=
NULL
;
if
(
FAILED
(
eecb
->
GetWindow
(
&
hwnd
)))
hwnd
=
NULL
;
hr
=
eecb
->
GetObject
(
&
mdb
,
(
LPMAPIPROP
*
)
&
message
);
if
(
hr
!=
S_OK
||
!
message
)
log_error
(
"%s:%s: error getting message: hr=%#lx"
,
SRCNAME
,
__func__
,
hr
);
else
{
LPDISPATCH
inspector
;
LPDISPATCH
obj
;
inspector
=
get_inspector_from_hwnd
(
hwnd
);
if
(
!
inspector
)
{
/* No inspector available. We now force the creation of
a new inspector by using the GetInspector method for
the current MailItem. In theory we could do this
always but we better try the *from_hwnd method first
as this will not create a new inspector in OL2007 if
one already exists. Not a real problem for OnRead
but we had this problem in OnWrite. */
obj
=
get_eecb_object
(
eecb
);
if
(
obj
)
{
inspector
=
get_oom_object
(
obj
,
"GetInspector"
);
if
(
opt
.
enable_debug
&
DBG_OOM
)
log_debug
(
"%s:%s: %p->GetInspector returned %p"
,
SRCNAME
,
__func__
,
obj
,
inspector
);
gpgol_release
(
obj
);
}
}
message_display_handler
(
message
,
inspector
,
hwnd
);
if
(
inspector
)
gpgol_release
(
inspector
);
}
if
(
message
)
gpgol_release
(
message
);
if
(
mdb
)
gpgol_release
(
mdb
);
}
return
S_FALSE
;
}
/* Called by Exchange when a message will be written. Returns: S_FALSE
to signal Exchange to continue calling extensions. EECB is a
pointer to the IExchExtCallback interface. */
STDMETHODIMP
GpgolMessageEvents
::
OnWrite
(
LPEXCHEXTCALLBACK
eecb
)
{
LPDISPATCH
obj
;
HWND
hwnd
=
NULL
;
bool
sign
,
encrypt
,
need_crypto
;
int
bodyfmt
;
if
(
FAILED
(
eecb
->
GetWindow
(
&
hwnd
)))
hwnd
=
NULL
;
log_debug
(
"%s:%s: received (hwnd=%p)"
,
SRCNAME
,
__func__
,
hwnd
);
need_crypto
=
(
!
get_crypto_flags
(
hwnd
,
&
sign
,
&
encrypt
)
&&
(
sign
||
encrypt
));
/* If we are going to encrypt, check that the BodyFormat is
something we support. This helps avoiding surprise by sending
out unencrypted messages. */
if
(
need_crypto
&&
!
opt
.
disable_gpgol
)
{
obj
=
get_eecb_object
(
eecb
);
if
(
!
obj
)
bodyfmt
=
-1
;
else
{
bodyfmt
=
get_oom_int
(
obj
,
"BodyFormat"
);
gpgol_release
(
obj
);
}
if
(
bodyfmt
==
1
)
m_want_html
=
0
;
else
if
(
bodyfmt
==
2
)
m_want_html
=
1
;
else
{
log_debug
(
"%s:%s: BodyFormat is %d"
,
SRCNAME
,
__func__
,
bodyfmt
);
MessageBox
(
hwnd
,
_
(
"Sorry, we can only encrypt plain text messages and
\n
"
"no RTF messages. Please make sure that only the text
\n
"
"format has been selected."
),
"GpgOL"
,
MB_ICONERROR
|
MB_OK
);
m_bWriteFailed
=
TRUE
;
return
E_FAIL
;
}
}
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. EECB is a
pointer to the IExchExtCallback interface. Returns: S_FALSE to
signal Exchange to continue calling extensions. We return E_FAIL
to signals Exchange an error; the message will not be sent. Note
that we don't return S_OK because this would mean that we rolled
back the write operation and that no further extensions should be
called. */
STDMETHODIMP
GpgolMessageEvents
::
OnWriteComplete
(
LPEXCHEXTCALLBACK
eecb
,
ULONG
flags
)
{
HRESULT
hrReturn
=
S_FALSE
;
LPMESSAGE
msg
=
NULL
;
LPMDB
pMDB
=
NULL
;
HWND
hwnd
=
NULL
;
int
rc
;
if
(
FAILED
(
eecb
->
GetWindow
(
&
hwnd
)))
hwnd
=
NULL
;
log_debug
(
"%s:%s: received (hwnd=%p)"
,
SRCNAME
,
__func__
,
hwnd
);
if
(
flags
&
(
EEME_FAILED
|
EEME_COMPLETE_FAILED
))
return
S_FALSE
;
/* We don't need to rollback anything in case
other extensions flagged a failure. */
if
(
opt
.
disable_gpgol
)
return
S_FALSE
;
if
(
!
m_bOnSubmitActive
)
/* The user is just saving the message. */
return
S_FALSE
;
if
(
m_bWriteFailed
)
/* Operation failed already. */
return
S_FALSE
;
/* Get the object and call the encryption or signing function. */
HRESULT
hr
=
eecb
->
GetObject
(
&
pMDB
,
(
LPMAPIPROP
*
)
&
msg
);
if
(
SUCCEEDED
(
hr
))
{
protocol_t
proto
=
PROTOCOL_UNKNOWN
;
/* Let the UI server select
the protocol. */
bool
sign
,
encrypt
;
if
(
get_crypto_flags
(
hwnd
,
&
sign
,
&
encrypt
))
rc
=
-1
;
else
if
(
encrypt
&&
sign
)
rc
=
message_sign_encrypt
(
msg
,
proto
,
hwnd
);
else
if
(
encrypt
&&
!
sign
)
rc
=
message_encrypt
(
msg
,
proto
,
hwnd
);
else
if
(
!
encrypt
&&
sign
)
rc
=
message_sign
(
msg
,
proto
,
hwnd
);
else
{
/* In case this is a forward message which is not to be
signed or encrypted we need to remove a possible body
attachment. */
if
(
mapi_delete_gpgol_body_attachment
(
msg
))
mapi_save_changes
(
msg
,
KEEP_OPEN_READWRITE
);
rc
=
0
;
}
if
(
rc
)
{
hrReturn
=
E_FAIL
;
m_bWriteFailed
=
TRUE
;
}
}
ul_release
(
msg
,
__func__
,
__LINE__
);
ul_release
(
pMDB
,
__func__
,
__LINE__
);
return
hrReturn
;
}
/* Called by Exchange when the user selects the "check names" command.
EECB is a pointer to the IExchExtCallback interface. Returns
S_FALSE to signal Exchange to continue calling extensions. */
STDMETHODIMP
GpgolMessageEvents
::
OnCheckNames
(
LPEXCHEXTCALLBACK
eecb
)
{
(
void
)
eecb
;
log_debug
(
"%s:%s: received
\n
"
,
SRCNAME
,
__func__
);
return
S_FALSE
;
}
/* Called by Exchange when "check names" command is complete.
EECB is a pointer to the IExchExtCallback interface. Returns
S_FALSE to signal Exchange to continue calling extensions. */
STDMETHODIMP
GpgolMessageEvents
::
OnCheckNamesComplete
(
LPEXCHEXTCALLBACK
eecb
,
ULONG
flags
)
{
(
void
)
eecb
;
(
void
)
flags
;
log_debug
(
"%s:%s: received
\n
"
,
SRCNAME
,
__func__
);
return
S_FALSE
;
}
/* Called by Exchange before the message data will be written and
submitted to MAPI. EECB is a pointer to the IExchExtCallback
interface. Returns S_FALSE to signal Exchange to continue calling
extensions. */
STDMETHODIMP
GpgolMessageEvents
::
OnSubmit
(
LPEXCHEXTCALLBACK
eecb
)
{
(
void
)
eecb
;
log_debug
(
"%s:%s: received
\n
"
,
SRCNAME
,
__func__
);
m_bOnSubmitActive
=
TRUE
;
m_bWriteFailed
=
FALSE
;
return
S_FALSE
;
}
/* Called by Exchange after the message has been submitted to MAPI.
EECB is a pointer to the IExchExtCallback interface. */
STDMETHODIMP_
(
VOID
)
GpgolMessageEvents
::
OnSubmitComplete
(
LPEXCHEXTCALLBACK
eecb
,
ULONG
flags
)
{
(
void
)
eecb
;
(
void
)
flags
;
log_debug
(
"%s:%s: received
\n
"
,
SRCNAME
,
__func__
);
m_bOnSubmitActive
=
FALSE
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Mon, Dec 23, 3:24 PM (1 d, 44 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
78/ad/a6d3c5535adfde0485dbb979a9ec
Attached To
rO GpgOL
Event Timeline
Log In to Comment