SaveAsFile crashes on certain Attachments!

  • Thread starter Thread starter MikeJohnson
  • Start date Start date
M

MikeJohnson

Here is my Outlook Object model code:

int iNumAttachments = pAttachments->GetCount();

for (int i = 1; i <= iNumAttachments; i++)
{
Attachment* pAttachment = pAttachments->Item(i);
if (pAttachment)
{
string strAttachment = GetAttachmentName (pAttachment);
_bstr_t bstrAttachment = strAttachment.c_str();
HRESULT hr = pAttachment->SaveAsFile (bstrAttachment);
}
}

This code always crashes in SaveAsFile, apparently on the same
attachment, after saving several attachments successfully!

The crashing object must be messed up-
When I examine it's interface table with the debugger:
pAttachment
IDispatch
IUnknown
__vfptr[0] = 0x00000000

The underlying IUnknown of this object looks bad.

Any thoughts?
Is my code clean?

Thanks!
-Mike
 
Okay the bug was mine.
You can see it in the code below:

Attachment* pAttachment = pAttachments->Item(i);
if (pAttachment)
{
string strAttachment = GetAttachmentName (pAttachment);
// Use attachment name here...
}

The compiler-generated method:

inline AttachmentPtr Attachments::Item (const _variant_t& Index)

returns an AttachmentPtr object, NOT an Attachment* !

Silly me for assuming that Attachment* and AttachmentPtr are
synonymous!
(I think my erroneous assumption is understandable,
as Windows historically has been rife with typedefs like INT_PTR,
ULONG_PTR, and DNS_TYPE_PTR. (Granted these macros are capitalized.))

As I said in a related post, I am not too familiar with COM and
smart pointers.

So I think something similar to the following happened:

Attachments::Item returned an AttachmentPtr object by value.
My code stores the returned object in an Attachment*, so
the compiler generated code to call _com_ptr_t::operator Interface*().
I think operator Interface*() might have returned a pointer into the
AttachmentPtr object returned from Item(), or possibly a pointer
to the AttachmentPtr object itself.
My method GetAttachmentName expected a 32-bit pointer as its first
parameter. Instead, the object passed on the stack was an entire
data structure (AttachmentPtr), passed by value??
Thus the stack cleanup code cleaned up the wrong amount of stack,
resulting in stack corruption after several passes through this method.

I think the analysis above is close, but not correct.

Does anyone else have a more correct analysis?

Thanks,
--Mike



Dmitry said:
Do you check that bstrAttachment is a valid fully qualified file name?

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool

MikeJohnson said:
Here is my Outlook Object model code:

int iNumAttachments = pAttachments->GetCount();

for (int i = 1; i <= iNumAttachments; i++)
{
Attachment* pAttachment = pAttachments->Item(i);
if (pAttachment)
{
string strAttachment = GetAttachmentName (pAttachment);
_bstr_t bstrAttachment = strAttachment.c_str();
HRESULT hr = pAttachment->SaveAsFile (bstrAttachment);
}
}

This code always crashes in SaveAsFile, apparently on the same
attachment, after saving several attachments successfully!

The crashing object must be messed up-
When I examine it's interface table with the debugger:
pAttachment
IDispatch
IUnknown
__vfptr[0] = 0x00000000

The underlying IUnknown of this object looks bad.

Any thoughts?
Is my code clean?

Thanks!
-Mike
 
Back
Top