C
clc
Setting:
Outlook 2003 (SP2)
Windows XP (SP2)
VS2005 C++
Outlook Object Modal 11
MAPI
Problem:
Whenever I save RTF directly to the JournalItem using the code below it is as if the item is left open and not saved. Two symptoms:
1) Opening and changing the item again using only Outlook Object Model I get the error "0xfbc40109 - The operation cannot be performed because the message has been changed."
2) Even if no errors occur, the JournalItem is not updated. It is as if the items is updated with the new data, but not saved or committed. The message still appears to be opened.
Please help!
Ben
Code:
If I create an intem in outlook like this (code shortened for readability)
// Create the Journalitem in our example and set no other properties because we just want a valid EntryID.
_JournalItemPtr pItem pItem = (_JournalItemPtr) m_pStore->polApp->CreateItem( olJournalItem );
pItem->Save();
pItem->Close(olSave);
pItem = NULL;
// Now we use our own routine to get a ptr to the item from Outlook and fill in the details of the Item
pItem = pFolder->FindItem( pEntry ); // UPDATE
pItem->Start = ...mydate
pItem->Subject = ...mysubject
pitem->Save()
pItem->Close(olSave)
// We use MAPI to save our RTF code to the same message zbBody is a stream to a raw RTF code
hr = m_pStore->SetMapiItemRTFBody( (LPTSTR) pItem->GetEntryID(), zbBody);
HRESULT CStore::SetMapiItemRTFBody(LPCTSTR szEID, const ZBlob& zb )
{
HRESULT hr = NOERROR;
BOOL bUpdated = false;
LPBYTE lpbMsgID = NULL;
LPMESSAGE lppMsg = NULL;
LPSTREAM lpRTFCompressed = NULL;
LPSTREAM lpRTFStream = NULL;
LPSPropValue pPropSuppMask = NULL;
ULONG cbWritten = 0;
ULONG cbMsgID = 0;
ULONG uType = 0;
if (!IsHexEntryIDValid(CW2A(szEID)))
return ResultFromScode(E_INVALIDARG);
cbMsgID = (ULONG) _tcslen(szEID) / 2;
hr = MAPIAllocateBuffer( cbMsgID, (void **) &lpbMsgID );
if (FAILED(hr)) return hr;
if( !FBinFromHex((LPTSTR) (LPSTR) CW2A(szEID), lpbMsgID) )
{
hr = ResultFromScode(E_INVALIDARG);
goto Quit;
}
hr = m_pMapiStore->OpenEntry(cbMsgID, (LPENTRYID) lpbMsgID, NULL, MAPI_BEST_ACCESS | MAPI_NO_CACHE, &uType, (LPUNKNOWN *) &lppMsg);
if( FAILED(hr) )
goto Quit;
// Call the message's IMAPIProp::OpenProperty method to open the PR_RTF_COMPRESSED property,
// specifying IID_IStream as the interface identifier and setting the MAPI_CREATE flag.
hr = lppMsg->OpenProperty(PR_RTF_COMPRESSED, &IID_IStream, 0, MAPI_MODIFY | MAPI_CREATE, (LPUNKNOWN *) &lpRTFCompressed);
if (FAILED(hr))
goto Quit;
hr = HrGetOneProp(lppMsg, PR_STORE_SUPPORT_MASK, &pPropSuppMask);
if (FAILED(hr))
goto Quit;
// Call the WrapCompressedRTFStream function, passing the STORE_UNCOMPRESSED_RTF flag if the STORE_UNCOMPRESSED_RTF
// bit is set in the message store's PR_STORE_SUPPORT_MASK property and get IStream pointer for uncompressed RTF,
// to which we will write
hr = WrapCompressedRTFStream(lpRTFCompressed, MAPI_MODIFY | (pPropSuppMask->Value.l & STORE_UNCOMPRESSED_RTF), &lpRTFStream);
// Call either IStream::Write or IStream::CopyTo to write the message text to the stream returned
// from WrapCompressedRTFStream. Write the text that was passed to the uncompressed RTF strea
hr = lpRTFStream->Write( zb.GetPtr(), zb.GetSize(), &cbWritten );
if (FAILED(hr))
goto Quit;
// Call the Commit and Release methods on the stream returned from the OpenProperty method
hr = lpRTFStream->Commit(STGC_OVERWRITE);
if (FAILED(hr))
goto Quit;
// Sync the RTF and plain text properties of the Message
hr = RTFSync(lppMsg, RTF_SYNC_RTF_CHANGED, &bUpdated);
if (FAILED(hr))
goto Quit;
// If the message was updated, save changes to the message
if (bUpdated)
{
hr = lppMsg->SaveChanges(0); // KEEP_OPEN_READWRITE);
if( hr == MAPI_E_OBJECT_CHANGED )
hr = lppMsg->SaveChanges(FORCE_SAVE);
lppMsg->SubmitMessage(0);
}
Quit:
if( pPropSuppMask)
MAPIFreeBuffer(pPropSuppMask);
UlRelease(lppMsg);
UlRelease(lpRTFStream);
UlRelease(lpRTFCompressed);
MAPIFreeBuffer(lpbMsgID);
return hr;
}
Outlook 2003 (SP2)
Windows XP (SP2)
VS2005 C++
Outlook Object Modal 11
MAPI
Problem:
Whenever I save RTF directly to the JournalItem using the code below it is as if the item is left open and not saved. Two symptoms:
1) Opening and changing the item again using only Outlook Object Model I get the error "0xfbc40109 - The operation cannot be performed because the message has been changed."
2) Even if no errors occur, the JournalItem is not updated. It is as if the items is updated with the new data, but not saved or committed. The message still appears to be opened.
Please help!
Ben
Code:
If I create an intem in outlook like this (code shortened for readability)
// Create the Journalitem in our example and set no other properties because we just want a valid EntryID.
_JournalItemPtr pItem pItem = (_JournalItemPtr) m_pStore->polApp->CreateItem( olJournalItem );
pItem->Save();
pItem->Close(olSave);
pItem = NULL;
// Now we use our own routine to get a ptr to the item from Outlook and fill in the details of the Item
pItem = pFolder->FindItem( pEntry ); // UPDATE
pItem->Start = ...mydate
pItem->Subject = ...mysubject
pitem->Save()
pItem->Close(olSave)
// We use MAPI to save our RTF code to the same message zbBody is a stream to a raw RTF code
hr = m_pStore->SetMapiItemRTFBody( (LPTSTR) pItem->GetEntryID(), zbBody);
HRESULT CStore::SetMapiItemRTFBody(LPCTSTR szEID, const ZBlob& zb )
{
HRESULT hr = NOERROR;
BOOL bUpdated = false;
LPBYTE lpbMsgID = NULL;
LPMESSAGE lppMsg = NULL;
LPSTREAM lpRTFCompressed = NULL;
LPSTREAM lpRTFStream = NULL;
LPSPropValue pPropSuppMask = NULL;
ULONG cbWritten = 0;
ULONG cbMsgID = 0;
ULONG uType = 0;
if (!IsHexEntryIDValid(CW2A(szEID)))
return ResultFromScode(E_INVALIDARG);
cbMsgID = (ULONG) _tcslen(szEID) / 2;
hr = MAPIAllocateBuffer( cbMsgID, (void **) &lpbMsgID );
if (FAILED(hr)) return hr;
if( !FBinFromHex((LPTSTR) (LPSTR) CW2A(szEID), lpbMsgID) )
{
hr = ResultFromScode(E_INVALIDARG);
goto Quit;
}
hr = m_pMapiStore->OpenEntry(cbMsgID, (LPENTRYID) lpbMsgID, NULL, MAPI_BEST_ACCESS | MAPI_NO_CACHE, &uType, (LPUNKNOWN *) &lppMsg);
if( FAILED(hr) )
goto Quit;
// Call the message's IMAPIProp::OpenProperty method to open the PR_RTF_COMPRESSED property,
// specifying IID_IStream as the interface identifier and setting the MAPI_CREATE flag.
hr = lppMsg->OpenProperty(PR_RTF_COMPRESSED, &IID_IStream, 0, MAPI_MODIFY | MAPI_CREATE, (LPUNKNOWN *) &lpRTFCompressed);
if (FAILED(hr))
goto Quit;
hr = HrGetOneProp(lppMsg, PR_STORE_SUPPORT_MASK, &pPropSuppMask);
if (FAILED(hr))
goto Quit;
// Call the WrapCompressedRTFStream function, passing the STORE_UNCOMPRESSED_RTF flag if the STORE_UNCOMPRESSED_RTF
// bit is set in the message store's PR_STORE_SUPPORT_MASK property and get IStream pointer for uncompressed RTF,
// to which we will write
hr = WrapCompressedRTFStream(lpRTFCompressed, MAPI_MODIFY | (pPropSuppMask->Value.l & STORE_UNCOMPRESSED_RTF), &lpRTFStream);
// Call either IStream::Write or IStream::CopyTo to write the message text to the stream returned
// from WrapCompressedRTFStream. Write the text that was passed to the uncompressed RTF strea
hr = lpRTFStream->Write( zb.GetPtr(), zb.GetSize(), &cbWritten );
if (FAILED(hr))
goto Quit;
// Call the Commit and Release methods on the stream returned from the OpenProperty method
hr = lpRTFStream->Commit(STGC_OVERWRITE);
if (FAILED(hr))
goto Quit;
// Sync the RTF and plain text properties of the Message
hr = RTFSync(lppMsg, RTF_SYNC_RTF_CHANGED, &bUpdated);
if (FAILED(hr))
goto Quit;
// If the message was updated, save changes to the message
if (bUpdated)
{
hr = lppMsg->SaveChanges(0); // KEEP_OPEN_READWRITE);
if( hr == MAPI_E_OBJECT_CHANGED )
hr = lppMsg->SaveChanges(FORCE_SAVE);
lppMsg->SubmitMessage(0);
}
Quit:
if( pPropSuppMask)
MAPIFreeBuffer(pPropSuppMask);
UlRelease(lppMsg);
UlRelease(lpRTFStream);
UlRelease(lpRTFCompressed);
MAPIFreeBuffer(lpbMsgID);
return hr;
}