I am facing a strange issue.It is working well with outlook 2K3 but not anymore on outlook 2K7 and 2K10.
Problem –
If I drag a file from my application and drop onto the message body in a new message in outlook 2007 nothing happens. Instead the expected behavior is – file should attach to the message. It work well in outlook 2003 and I haven’t made any change in my code.
If I drag file from my application and drop on to windows desktop, it works without any problem. Now if I drag the same file from Windows desktop and drop onto the new message in outlook 2007, file gets attached. This leaves me guessing that there is something need to change in my code but I unable to figure out.
Investigation –
We have implemented the CFSTR_FILEDESCRIPTOR, CFSTR_FILECONTENTS and CF_TXT in the CDataObject::Getdata() method.
I have noticed is that in case of Outlook 2007, when I drop file (from my application) to message body in new message, only CFSTR_FILEDESCRIPTOR clipboard format is called.
While in case of Outlook 2003, if I drop file (from my application) to message body in new message CDataObject::GetData() is called two times, CFSTR_FILEDESCRIPTOR followed by CFSTR_FILECONTENTS clipboard formats.
In the second file contents are extracted since GetData is not called second time hence file is not attached to email. Following is the sample code.
Does anyone know what could be the reason? Or what else i can try to narrow down the issue.
STDMETHODIMP CDataObject::GetData (
LPFORMATETC pFE,
LPSTGMEDIUM pSTM)
{
HGLOBAL hMem;
LPFILEGROUPDESCRIPTOR pfgd;
UINT uFormat, uBytes;
void* p;
m_uFmtUsed = 0;
uFormat = pFE->cfFormat;
// FILEDESCRIPTOR format
if (uFormat == m_fe[0].cfFormat)
{
if (!(pFE->dwAspect & DVASPECT_CONTENT))
return DV_E_DVASPECT;
if (!(pFE->tymed & TYMED_HGLOBAL))
return DV_E_FORMATETC;
hMem=GlobalAlloc (GMEM_SHARE | GMEM_MOVEABLE,
sizeof(FILEGROUPDESCRIPTOR));
if (hMem == NULL)
return STG_E_MEDIUMFULL;
pfgd = (LPFILEGROUPDESCRIPTOR)GlobalLock (hMem);
pfgd->cItems = 1;
pfgd->fgd[0].dwFlags = FD_ATTRIBUTES;
pfgd->fgd[0].dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
lstrcpy (pfgd->fgd[0].cFileName, m_pszName);
GlobalUnlock (hMem);
pSTM->hGlobal = hMem;
pSTM->tymed = TYMED_HGLOBAL;
pSTM->pUnkForRelease = NULL;
m_uFmtUsed = uFormat;
return S_OK;
}
// FILECONTENTS clipboard format
else if (uFormat == m_fe[1].cfFormat)
{
if (!(pFE->dwAspect & DVASPECT_CONTENT))
return DV_E_DVASPECT;
if (!(pFE->tymed & TYMED_HGLOBAL))
return DV_E_FORMATETC;
if (!m_pData)
{
m_pData = PKDropGetData (
m_pStruct, FALSE, FALSE, &uBytes);
}
hMem = GlobalAlloc (GMEM_SHARE|GMEM_MOVEABLE, uBytes);
if (hMem == NULL)
return STG_E_MEDIUMFULL;
p = GlobalLock (hMem);
memcpy (p, m_pData, uBytes);
GlobalUnlock (hMem);
pSTM->hGlobal = hMem;
pSTM->tymed = TYMED_HGLOBAL;
pSTM->pUnkForRelease = NULL;
m_uFmtUsed = uFormat;
return S_OK;
}
....
.....
....
return DV_E_FORMATETC;
}
QueryGetData(LPFORMATETC pFE )
{
UINT uFormat = pFE->cfFormat;
BOOL bRet = FALSE;
if (uFormat == m_fe[0].cfFormat) // filegroupdescriptor
{
bRet = (BOOL)(pFE->tymed & TYMED_HGLOBAL);
}
else if (uFormat == m_fe[1].cfFormat) // filecontents
{
bRet = (BOOL)(pFE->tymed & TYMED_HGLOBAL);
}
else
bRet = false;
----
----
return (bRet ? S_OK : DV_E_FORMATETC);
}
To debug this, run it up in the debugger and stick a break point on this line:
Then step through.
Notes:
If it was being called twice before, once with CFSTR_FILEDESCRIPTOR and then again with CFSTR_FILECONTENTS, that means that it failed the first time, probably because you didn’t support the desired
TYMED. Then it is trying again with CFSTR_FILECONTENTS.I suspect that CFSTR_FILEDESCRIPTOR never worked, and Outlook is simply no longer trying the second format after the first fails.
QueryGetDataorEnumFORMATETC?If so, Outlook may be asking for FILEGROUPDESCRIPTOR in, say, an IStream, and when you return an error it is simply giving up.