J
Jim
Hello,
I'm still working on my Extended MAPI wrapper code to avoid the
Outlook security warning when reading objMailItem.Body.
This approach seems to work:
HrMAPIFindDefaultMsgStore
OpenMsgStore
OpenEntry
HrGetOneProp(.., PR_BODY, ..)
if MAPI_E_NOT_FOUND
no body text -- return ok
if ! MAPI_E_NOT_ENOUGH_MEMORY
return body text from Value.lpszA
OpenProperty(PR_BODY, ..)
IStream->Read(bf, ..)
return body text in bf
But I ran into a problem where after quite a lot of processing
(induced by scrolling through 1000 Inbox items several times, reading
each Inbox item via the Extended MAPI wrapper code above), the call
from Outlook to the Extended MAPI wrapper logic above would suddenly
slow down. Each call would suspend for about five seconds and then
succeed. It was as if I ran into some kind of Windows internal
resource timeout and recovery logic.
I tried a lot of different things, including disabling different parts
of the cleanup code (not shown above). The problem finally went away
when I *stopped* calling Release() on the IStream used to read PR_BODY
after the call to OpenProperty.
I went back and reviewed several web examples of Extended MAPI source,
and found that some call Release() for the IStream and some don't.
Here is one that calls Release():
http://www.wischik.com/lu/programmer/mapi_utils.html
char *bodybuf=0; unsigned int bodysize=0;
IStream *istream;
hr = imsg->OpenProperty(PR_BODY, &IID_IStream, STGM_READ,
0, (IUnknown**)&istream);
if (hr==S_OK)
{
AvailableOffline = true;
STATSTG stg = {0};
hr = istream->Stat(&stg,STATFLAG_NONAME);
if (hr==S_OK)
{
bodysize = stg.cbSize.LowPart;
bodybuf = new char[bodysize+1];
ULONG red; hr = istream->Read(bodybuf, bodysize, &red);
if (hr!=S_OK) bodysize=0;
else if (red<bodysize) bodysize=red;
bodybuf[bodysize]=0;
}
istream->Release();
}
Whereas Microsoft in this source example does *not* call Release() for
the IStream:
http://support.microsoft.com/?kbid=239795
Yet Microsoft states elsewhere, in a more general discussion, that
Release() should be called:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/
exchserv/html/perform_0vjn.asp
Use the Win32 IStream interface functions. This interface is
used by all the preceding functions to return a Stream object
and a pointer which should be used for memory allocation and
deallocation. To free the Stream object, the application or
provider must call the OLE IStream::Release method.
I can only guess that calling Release() for the message returned by
OpenProperty() implicitly calls Release() for the IStream, and it is
an error for my application to also call Release() for the IStream.
Without calling Release() for the IStream, my application is working.
I can read PR_BODY via my Extended MAPI wrapper for *many* iterations
without any apparent problems. But I am nervous that I really should
be calling Release() for the IStream.
What do you do in your Extended MAPI code? Do you call Release() for
the IStream?
A second quick question. The example code above from www.wischik.com
calls Stat() after OpenProperty(), before calling Read() on the
IStream. Is there any benefit to this? Is it necessary for any
reason? Microsoft does not call Stat() in their KB239795 sample code.
Thanks.
Jim
I'm still working on my Extended MAPI wrapper code to avoid the
Outlook security warning when reading objMailItem.Body.
This approach seems to work:
HrMAPIFindDefaultMsgStore
OpenMsgStore
OpenEntry
HrGetOneProp(.., PR_BODY, ..)
if MAPI_E_NOT_FOUND
no body text -- return ok
if ! MAPI_E_NOT_ENOUGH_MEMORY
return body text from Value.lpszA
OpenProperty(PR_BODY, ..)
IStream->Read(bf, ..)
return body text in bf
But I ran into a problem where after quite a lot of processing
(induced by scrolling through 1000 Inbox items several times, reading
each Inbox item via the Extended MAPI wrapper code above), the call
from Outlook to the Extended MAPI wrapper logic above would suddenly
slow down. Each call would suspend for about five seconds and then
succeed. It was as if I ran into some kind of Windows internal
resource timeout and recovery logic.
I tried a lot of different things, including disabling different parts
of the cleanup code (not shown above). The problem finally went away
when I *stopped* calling Release() on the IStream used to read PR_BODY
after the call to OpenProperty.
I went back and reviewed several web examples of Extended MAPI source,
and found that some call Release() for the IStream and some don't.
Here is one that calls Release():
http://www.wischik.com/lu/programmer/mapi_utils.html
char *bodybuf=0; unsigned int bodysize=0;
IStream *istream;
hr = imsg->OpenProperty(PR_BODY, &IID_IStream, STGM_READ,
0, (IUnknown**)&istream);
if (hr==S_OK)
{
AvailableOffline = true;
STATSTG stg = {0};
hr = istream->Stat(&stg,STATFLAG_NONAME);
if (hr==S_OK)
{
bodysize = stg.cbSize.LowPart;
bodybuf = new char[bodysize+1];
ULONG red; hr = istream->Read(bodybuf, bodysize, &red);
if (hr!=S_OK) bodysize=0;
else if (red<bodysize) bodysize=red;
bodybuf[bodysize]=0;
}
istream->Release();
}
Whereas Microsoft in this source example does *not* call Release() for
the IStream:
http://support.microsoft.com/?kbid=239795
Yet Microsoft states elsewhere, in a more general discussion, that
Release() should be called:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/
exchserv/html/perform_0vjn.asp
Use the Win32 IStream interface functions. This interface is
used by all the preceding functions to return a Stream object
and a pointer which should be used for memory allocation and
deallocation. To free the Stream object, the application or
provider must call the OLE IStream::Release method.
I can only guess that calling Release() for the message returned by
OpenProperty() implicitly calls Release() for the IStream, and it is
an error for my application to also call Release() for the IStream.
Without calling Release() for the IStream, my application is working.
I can read PR_BODY via my Extended MAPI wrapper for *many* iterations
without any apparent problems. But I am nervous that I really should
be calling Release() for the IStream.
What do you do in your Extended MAPI code? Do you call Release() for
the IStream?
A second quick question. The example code above from www.wischik.com
calls Stat() after OpenProperty(), before calling Read() on the
IStream. Is there any benefit to this? Is it necessary for any
reason? Microsoft does not call Stat() in their KB239795 sample code.
Thanks.
Jim