SaveAsFile crashes on certain Attachments!

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
 
M

MikeJohnson

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::eek:perator 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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top