Windows2003-3790/inetcore/outlookexpress/import/exchange/mapiconv.cpp
2020-09-30 16:53:55 +02:00

966 lines
30 KiB
C++

// =====================================================================================
// m a p c o n v . c p p
// conver a MAPI message to and from an RFC 822/RFC 1521 (mime) internet message
// =====================================================================================
#include "pch.hxx"
#include <newimp.h>
#include "Imnapi.h"
#include "Mapiconv.h"
#include <impapi.h>
#include <import.h>
#include "demand.h"
LPSTR MapiStringDup (LPCTSTR lpcsz, LPVOID lpobj);
HRESULT HrImsgRecipToMapiRecip(LPMESSAGE lpMessage, LPIMSG lpImsg);
HRESULT HrImsgAttachToMapiAttach(LPMESSAGE lpMessage, LPIMSG lpImsg);
// =====================================================================================
// MAPI Message Properties that I want
// =====================================================================================
#define PR_BODY_HTML PROP_TAG( PT_TSTRING, 0x1013)
enum
{
colSenderAddrType,
colSenderName,
colSenderEMail,
colDelegateAddrType,
colDelegateName,
colDelegateEMail,
colSubject,
colReceiveTime,
colSendTime,
colPriority,
colFlags,
colLast1
};
SizedSPropTagArray (colLast1, sptMessageProps) =
{
colLast1,
{
PR_SENDER_ADDRTYPE,
PR_SENDER_NAME,
PR_SENDER_EMAIL_ADDRESS,
PR_SENT_REPRESENTING_ADDRTYPE,
PR_SENT_REPRESENTING_NAME,
PR_SENT_REPRESENTING_EMAIL_ADDRESS,
PR_SUBJECT,
PR_MESSAGE_DELIVERY_TIME,
PR_CLIENT_SUBMIT_TIME,
PR_IMPORTANCE,
PR_MESSAGE_FLAGS
}
};
// =====================================================================================
// MAPI Recip Props
// =====================================================================================
enum
{
colRecipAddrType,
colRecipName,
colRecipAddress,
colRecipType,
colLast2
};
SizedSPropTagArray (colLast2, sptRecipProps) =
{
colLast2,
{
PR_ADDRTYPE,
PR_DISPLAY_NAME,
PR_EMAIL_ADDRESS,
PR_RECIPIENT_TYPE
}
};
// =====================================================================================
// MAPI Attachment Props
// =====================================================================================
enum
{
colAttMethod,
colAttNum,
colAttLongFilename,
colAttPathname,
colAttTag,
colAttFilename,
colAttExtension,
colAttSize,
colLast3
};
SizedSPropTagArray (colLast3, sptAttProps) =
{
colLast3,
{
PR_ATTACH_METHOD,
PR_ATTACH_NUM,
PR_ATTACH_LONG_FILENAME,
PR_ATTACH_PATHNAME,
PR_ATTACH_TAG,
PR_ATTACH_FILENAME,
PR_ATTACH_EXTENSION,
PR_ATTACH_SIZE
}
};
char *GetRecipAddress(LPSPropValue ppropAddr, LPSPropValue ppropType)
{
char *sz, *szT;
sz = NULL;
if (PROP_TYPE(ppropAddr->ulPropTag) != PT_ERROR &&
PROP_TYPE(ppropType->ulPropTag) != PT_ERROR)
{
szT = ppropType->Value.lpszA;
if (lstrcmp(szT, "SMTP") == 0 || lstrcmp(szT, "MSNINET") == 0)
{
sz = PszDup(ppropAddr->Value.lpszA);
}
else if (lstrcmp(szT, "MSN") == 0 || lstrcmp(szT, "MSNLIST") == 0)
{
szT = ppropAddr->Value.lpszA;
DWORD cch = lstrlen(szT) + 16;
if (MemAlloc((void **)&sz, cch*sizeof(sz[0])))
{
StrCpyN(sz, szT, cch);
StrCatBuff(sz, "@msn.com", cch);
}
}
}
return(sz);
}
// =====================================================================================
// HrMapiToImsg
// =====================================================================================
HRESULT HrMapiToImsg (LPMESSAGE lpMessage, LPIMSG lpImsg)
{
// Locals
LPSPropValue ppropAddr, ppropType, ppropName;
TCHAR szUnk[128];
int cchUnk;
TCHAR *sz, *szT;
HRESULT hr;
ULONG cProp, i;
LPSPropValue lpMsgPropValue = NULL;
LPSRowSet lpRecipRows = NULL, lpAttRows = NULL;
LPMAPITABLE lptblRecip = NULL, lptblAtt = NULL;
LPATTACH lpAttach = NULL;
LPMESSAGE lpMsgAtt = NULL;
LPSTREAM lpstmBody = NULL;
cchUnk = LoadString(g_hInstImp, idsAddressUnknownFmt, szUnk, ARRAYSIZE(szUnk));
// Zero init
ZeroMemory (lpImsg, sizeof (IMSG));
// Get the propsw
hr = lpMessage->GetProps ((LPSPropTagArray)&sptMessageProps, 0, &cProp, &lpMsgPropValue);
if (FAILED (hr))
goto exit;
// Subject
if (PROP_TYPE(lpMsgPropValue[colSubject].ulPropTag) != PT_ERROR)
lpImsg->lpszSubject = PszDup(lpMsgPropValue[colSubject].Value.lpszA);
// Body
if (SUCCEEDED(lpMessage->OpenProperty(PR_BODY_HTML, (LPIID)&IID_IStream, 0, 0, (LPUNKNOWN *)&lpstmBody)))
{
if (SUCCEEDED(hr = CreateStreamOnHFile (NULL, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL, &lpImsg->lpstmHtml)))
hr = HrCopyStream(lpstmBody, lpImsg->lpstmHtml, NULL);
lpstmBody->Release();
lpstmBody = NULL;
if (FAILED(hr))
goto exit;
}
else if (SUCCEEDED(lpMessage->OpenProperty(PR_BODY, (LPIID)&IID_IStream, 0, 0, (LPUNKNOWN *)&lpstmBody)))
{
if (SUCCEEDED(hr = CreateStreamOnHFile (NULL, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL, &lpImsg->lpstmBody)))
hr = HrCopyStream(lpstmBody, lpImsg->lpstmBody, NULL);
lpstmBody->Release();
lpstmBody = NULL;
if (FAILED(hr))
goto exit;
}
// Send Time
if (PROP_TYPE(lpMsgPropValue[colSendTime].ulPropTag) != PT_ERROR)
CopyMemory(&lpImsg->ftSend, &lpMsgPropValue[colSendTime].Value.ft, sizeof (FILETIME));
// Receive Time
if (PROP_TYPE(lpMsgPropValue[colReceiveTime].ulPropTag) != PT_ERROR)
CopyMemory(&lpImsg->ftReceive, &lpMsgPropValue[colReceiveTime].Value.ft, sizeof (FILETIME));
// Priority
lpImsg->wPriority = PRI_NORMAL;
if (PROP_TYPE(lpMsgPropValue[colPriority].ulPropTag) != PT_ERROR)
{
switch (lpMsgPropValue[colPriority].Value.l)
{
case IMPORTANCE_LOW:
lpImsg->wPriority = PRI_LOW;
break;
case IMPORTANCE_HIGH:
lpImsg->wPriority = PRI_HIGH;
break;
case IMPORTANCE_NORMAL:
default:
lpImsg->wPriority = PRI_NORMAL;
break;
}
}
// message flags
if (PROP_TYPE(lpMsgPropValue[colFlags].ulPropTag) != PT_ERROR)
lpImsg->uFlags = lpMsgPropValue[colFlags].Value.ul;
// Get the recipient table
hr = lpMessage->GetRecipientTable (0, &lptblRecip);
if (FAILED (hr))
goto exit;
// Get all the rows of the recipient table
hr = lpHrQueryAllRows (lptblRecip, (LPSPropTagArray)&sptRecipProps, NULL, NULL, 0, &lpRecipRows);
if (FAILED (hr))
goto exit;
// Allocate Recipient Array
lpImsg->cAddress = lpRecipRows->cRows + 1;
if (!MemAlloc((void **)&lpImsg->lpIaddr, sizeof (IADDRINFO) * lpImsg->cAddress))
{
hr = E_OUTOFMEMORY;
goto exit;
}
ZeroMemory(lpImsg->lpIaddr, sizeof (IADDRINFO) * lpImsg->cAddress);
ppropAddr = &lpMsgPropValue[colDelegateEMail];
ppropType = &lpMsgPropValue[colDelegateAddrType];
ppropName = &lpMsgPropValue[colDelegateName];
if (PROP_TYPE(ppropAddr->ulPropTag) == PT_ERROR ||
PROP_TYPE(ppropType->ulPropTag) == PT_ERROR)
{
ppropAddr = &lpMsgPropValue[colSenderEMail];
ppropType = &lpMsgPropValue[colSenderAddrType];
ppropName = &lpMsgPropValue[colSenderName];
}
// Originator of the message "From: "
lpImsg->lpIaddr[0].dwType = IADDR_FROM;
lpImsg->lpIaddr[0].lpszAddress = GetRecipAddress(ppropAddr, ppropType);
if (PROP_TYPE(ppropName->ulPropTag) != PT_ERROR)
{
szT = ppropName->Value.lpszA;
if (lpImsg->lpIaddr[0].lpszAddress != NULL)
{
sz = PszDup(szT);
}
else
{
lpImsg->lpIaddr[0].lpszAddress = PszDup(szT);
DWORD cchSz = lstrlen(szT) + cchUnk;
if (!MemAlloc((void **)&sz, cchSz*sizeof(sz[0])))
{
hr = E_OUTOFMEMORY;
goto exit;
}
wnsprintf(sz, cchSz, szUnk, szT);
}
lpImsg->lpIaddr[0].lpszDisplay = sz;
}
// Add in the rest of the recipients
for (i=0; i<lpRecipRows->cRows; i++)
{
Assert (i+1 < lpImsg->cAddress);
if (PROP_TYPE(lpRecipRows->aRow[i].lpProps[colRecipType].ulPropTag) != PT_ERROR)
{
switch (lpRecipRows->aRow[i].lpProps[colRecipType].Value.ul)
{
case MAPI_TO:
case 0x10000000: /* MAPI_P1: */
lpImsg->lpIaddr[i+1].dwType = IADDR_TO;
break;
case MAPI_ORIG:
lpImsg->lpIaddr[i+1].dwType = IADDR_FROM;
break;
case MAPI_CC:
lpImsg->lpIaddr[i+1].dwType = IADDR_CC;
break;
case MAPI_BCC:
lpImsg->lpIaddr[i+1].dwType = IADDR_BCC;
break;
default:
Assert (FALSE);
lpImsg->lpIaddr[i+1].dwType = IADDR_TO;
break;
}
}
else
{
lpImsg->lpIaddr[i+1].dwType = IADDR_TO;
}
lpImsg->lpIaddr[i+1].lpszAddress = GetRecipAddress(&lpRecipRows->aRow[i].lpProps[colRecipAddress], &lpRecipRows->aRow[i].lpProps[colRecipAddrType]);
if (PROP_TYPE(lpRecipRows->aRow[i].lpProps[colRecipName].ulPropTag) != PT_ERROR)
{
szT = lpRecipRows->aRow[i].lpProps[colRecipName].Value.lpszA;
if (lpImsg->lpIaddr[i + 1].lpszAddress != NULL)
{
sz = PszDup(szT);
}
else
{
lpImsg->lpIaddr[i+1].lpszAddress = PszDup(szT);
DWORD cchSz = lstrlen(szT) + cchUnk;
if (!MemAlloc((void **)&sz, cchSz*sizeof(sz[0])))
{
hr = E_OUTOFMEMORY;
goto exit;
}
wnsprintf(sz, cchSz, szUnk, szT);
}
lpImsg->lpIaddr[i + 1].lpszDisplay = sz;
}
}
// Free Rows
if (lpRecipRows)
lpFreeProws (lpRecipRows);
lpRecipRows = NULL;
// Attachments
hr = lpMessage->GetAttachmentTable (0, &lptblAtt);
if (FAILED (hr))
goto exit;
// Get all the rows of the recipient table
hr = lpHrQueryAllRows (lptblAtt, (LPSPropTagArray)&sptAttProps, NULL, NULL, 0, &lpAttRows);
if (FAILED (hr))
goto exit;
// Allocate files list
if (lpAttRows->cRows == 0)
goto exit;
// Allocate memory
lpImsg->cAttach = lpAttRows->cRows;
if (!MemAlloc((void **)&lpImsg->lpIatt, sizeof (IATTINFO) * lpImsg->cAttach))
{
hr = E_OUTOFMEMORY;
goto exit;
}
// Zero init
ZeroMemory (lpImsg->lpIatt, sizeof (IATTINFO) * lpImsg->cAttach);
// Walk the rows
for (i=0; i<lpAttRows->cRows; i++)
{
if (PROP_TYPE(lpAttRows->aRow[i].lpProps[colAttMethod].ulPropTag) != PT_ERROR &&
PROP_TYPE(lpAttRows->aRow[i].lpProps[colAttNum].ulPropTag) != PT_ERROR)
{
// Basic Properties
if (PROP_TYPE(lpAttRows->aRow[i].lpProps[colAttPathname].ulPropTag) != PT_ERROR)
{
sz = lpAttRows->aRow[i].lpProps[colAttPathname].Value.lpszA;
if (!FIsEmpty(sz))
lpImsg->lpIatt[i].lpszPathName = PszDup(sz);
}
if (PROP_TYPE(lpAttRows->aRow[i].lpProps[colAttFilename].ulPropTag) != PT_ERROR)
{
sz = lpAttRows->aRow[i].lpProps[colAttFilename].Value.lpszA;
if (!FIsEmpty(sz))
lpImsg->lpIatt[i].lpszFileName = PszDup(sz);
}
if (lpImsg->lpIatt[i].lpszFileName == NULL &&
PROP_TYPE(lpAttRows->aRow[i].lpProps[colAttLongFilename].ulPropTag) != PT_ERROR)
{
sz = lpAttRows->aRow[i].lpProps[colAttLongFilename].Value.lpszA;
if (!FIsEmpty(sz))
lpImsg->lpIatt[i].lpszFileName = PszDup(sz);
}
if (PROP_TYPE(lpAttRows->aRow[i].lpProps[colAttExtension].ulPropTag) != PT_ERROR)
{
sz = lpAttRows->aRow[i].lpProps[colAttExtension].Value.lpszA;
if (!FIsEmpty(sz))
lpImsg->lpIatt[i].lpszExt = PszDup(sz);
}
// Open the attachment
hr = lpMessage->OpenAttach (lpAttRows->aRow[i].lpProps[colAttNum].Value.l, NULL, MAPI_BEST_ACCESS, &lpAttach);
if (FAILED (hr))
{
lpImsg->lpIatt[i].fError = TRUE;
continue;
}
// Handle the attachment method
switch (lpAttRows->aRow[i].lpProps[colAttMethod].Value.ul)
{
case NO_ATTACHMENT:
lpImsg->lpIatt[i].dwType = 0;
lpImsg->lpIatt[i].fError = TRUE;
break;
case ATTACH_BY_REF_RESOLVE:
case ATTACH_BY_VALUE:
lpImsg->lpIatt[i].dwType = IATT_FILE;
hr = lpAttach->OpenProperty (PR_ATTACH_DATA_BIN, (LPIID)&IID_IStream, 0, 0, (LPUNKNOWN *)&lpImsg->lpIatt[i].lpstmAtt);
if (FAILED (hr))
lpImsg->lpIatt[i].fError = TRUE;
break;
case ATTACH_BY_REF_ONLY:
case ATTACH_BY_REFERENCE:
lpImsg->lpIatt[i].dwType = IATT_FILE;
hr = CreateStreamOnHFile (lpImsg->lpIatt[i].lpszPathName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL, &lpImsg->lpIatt[i].lpstmAtt);
if (FAILED (hr))
lpImsg->lpIatt[i].fError = TRUE;
break;
case ATTACH_EMBEDDED_MSG:
lpImsg->lpIatt[i].dwType = IATT_MSG;
hr = lpAttach->OpenProperty (PR_ATTACH_DATA_OBJ, (LPIID)&IID_IMessage, 0, 0, (LPUNKNOWN *)&lpMsgAtt);
if (FAILED (hr) || lpMsgAtt == NULL)
lpImsg->lpIatt[i].fError = TRUE;
else
{
if (!MemAlloc((void **)&lpImsg->lpIatt[i].lpImsg, sizeof (IMSG)))
lpImsg->lpIatt[i].fError = TRUE;
else
{
hr = HrMapiToImsg (lpMsgAtt, lpImsg->lpIatt[i].lpImsg);
if (FAILED (hr))
lpImsg->lpIatt[i].fError = TRUE;
}
lpMsgAtt->Release ();
lpMsgAtt = NULL;
}
break;
case ATTACH_OLE:
default:
lpImsg->lpIatt[i].dwType = IATT_OLE;
lpImsg->lpIatt[i].fError = TRUE;
break;
}
// Free Attachment
if (lpAttach)
lpAttach->Release ();
lpAttach = NULL;
}
}
hr = S_OK;
exit:
// Cleanup
if (lpAttach)
lpAttach->Release ();
if (lptblAtt)
lptblAtt->Release ();
if (lpAttRows)
lpFreeProws (lpAttRows);
if (lpRecipRows)
lpFreeProws (lpRecipRows);
if (lpMsgPropValue)
lpMAPIFreeBuffer (lpMsgPropValue);
if (lptblRecip)
lptblRecip->Release ();
if (lpMsgAtt)
lpMsgAtt->Release ();
if (lpstmBody)
lpstmBody->Release ();
// Done
return hr;
}
// =====================================================================================
//
// HrImsgToMapi: lpImsg => lpMessage
//
// assumes lpMessage is initialized.
//
// =====================================================================================
HRESULT HrImsgToMapi(LPIMSG lpImsg, LPMESSAGE lpMessage)
{
// Locals
LPSTREAM lpstmBody;
HRESULT hr = S_OK;
ULONG i, cProp;
LPSPropValue lpMsgPropValue = NULL;
ULONG cPropMax = 13;
/*
properties to copy:
PR_SENDER_ADDRTYPE,
PR_SENDER_NAME,
PR_SENDER_EMAIL_ADDRESS,
PR_SUBJECT,
PR_MESSAGE_DELIVERY_TIME,
PR_IMPORTANCE,
PR_MESSAGE_FLAGS
PR_MESSAGE_CLASS
PR_SENT_REPRESENTING_NAME,
PR_SENT_REPRESENTING_EMAIL_ADDRESS,
PR_SENT_REPRESENTING_ADDRTYPE,
*/
Assert(lpMessage != NULL);
// create the propvalue array
hr = lpMAPIAllocateBuffer(cPropMax*sizeof(SPropValue), (LPVOID FAR*)&lpMsgPropValue);
if (FAILED(hr))
goto exit;
ZeroMemory(lpMsgPropValue, cPropMax*sizeof(SPropValue));
cProp = 0;
lpMsgPropValue[cProp].Value.lpszA = MapiStringDup("IPM.Note", lpMsgPropValue);
lpMsgPropValue[cProp].ulPropTag = PR_MESSAGE_CLASS;
cProp++;
// Subject
if (lpImsg->lpszSubject)
{
lpMsgPropValue[cProp].Value.lpszA = MapiStringDup(lpImsg->lpszSubject, lpMsgPropValue);
lpMsgPropValue[cProp].ulPropTag = PR_SUBJECT;
cProp++;
Assert(cProp <= cPropMax);
}
// Send Time
CopyMemory(&lpMsgPropValue[cProp].Value.ft, &lpImsg->ftSend, sizeof (FILETIME));
lpMsgPropValue[cProp].ulPropTag = PR_CLIENT_SUBMIT_TIME;
cProp++;
Assert(cProp <= cPropMax);
// Receive Time
CopyMemory(&lpMsgPropValue[cProp].Value.ft, &lpImsg->ftReceive, sizeof (FILETIME));
lpMsgPropValue[cProp].ulPropTag = PR_MESSAGE_DELIVERY_TIME;
cProp++;
Assert(cProp <= cPropMax);
// Priority
lpMsgPropValue[cProp].ulPropTag = PR_IMPORTANCE;
switch (lpImsg->wPriority)
{
case PRI_HIGH:
lpMsgPropValue[cProp].Value.l = IMPORTANCE_HIGH;
break;
case PRI_LOW:
lpMsgPropValue[cProp].Value.l = IMPORTANCE_LOW;
break;
case PRI_NORMAL:
default:
lpMsgPropValue[cProp].Value.l = IMPORTANCE_NORMAL;
break;
}
cProp++;
Assert(cProp <= cPropMax);
// Message flags
lpMsgPropValue[cProp].ulPropTag = PR_MESSAGE_FLAGS;
lpMsgPropValue[cProp].Value.ul = lpImsg->uFlags;
cProp++;
Assert(cProp <= cPropMax);
// recipients
if (FAILED(hr = HrImsgRecipToMapiRecip(lpMessage, lpImsg)))
goto exit;
// sender information
for (i = 0; i < lpImsg->cAddress; i++)
{
Assert(lpImsg->lpIaddr != NULL);
if (lpImsg->lpIaddr[i].dwType == IADDR_FROM)
{
Assert(lpImsg->lpIaddr[i].lpszAddress);
Assert(lpImsg->lpIaddr[i].lpszDisplay);
lpMsgPropValue[cProp].Value.lpszA = MapiStringDup(lpImsg->lpIaddr[i].lpszDisplay, lpMsgPropValue);
lpMsgPropValue[cProp].ulPropTag = PR_SENDER_NAME;
cProp++;
lpMsgPropValue[cProp].Value.lpszA = MapiStringDup(lpImsg->lpIaddr[i].lpszDisplay, lpMsgPropValue);
lpMsgPropValue[cProp].ulPropTag = PR_SENT_REPRESENTING_NAME;
cProp++;
Assert(cProp <= cPropMax);
lpMsgPropValue[cProp].Value.lpszA = MapiStringDup(lpImsg->lpIaddr[i].lpszAddress, lpMsgPropValue);
lpMsgPropValue[cProp].ulPropTag = PR_SENDER_EMAIL_ADDRESS;
cProp++;
lpMsgPropValue[cProp].Value.lpszA = MapiStringDup(lpImsg->lpIaddr[i].lpszAddress, lpMsgPropValue);
lpMsgPropValue[cProp].ulPropTag = PR_SENT_REPRESENTING_EMAIL_ADDRESS;
cProp++;
Assert(cProp <= cPropMax);
lpMsgPropValue[cProp].Value.lpszA = MapiStringDup("SMTP", lpMsgPropValue);
lpMsgPropValue[cProp].ulPropTag = PR_SENDER_ADDRTYPE;
cProp++;
lpMsgPropValue[cProp].Value.lpszA = MapiStringDup("SMTP", lpMsgPropValue);
lpMsgPropValue[cProp].ulPropTag = PR_SENT_REPRESENTING_ADDRTYPE;
cProp++;
Assert(cProp <= cPropMax);
break;
}
}
// attachment information
if (FAILED(hr = HrImsgAttachToMapiAttach(lpMessage, lpImsg)))
goto exit;
// save changes
if (FAILED(hr = lpMessage->SetProps(cProp, lpMsgPropValue, NULL)))
goto exit;
// Body
if (lpImsg->lpstmHtml &&
SUCCEEDED(lpMessage->OpenProperty(PR_BODY_HTML, (LPIID)&IID_IStream, 0, MAPI_CREATE | MAPI_MODIFY, (LPUNKNOWN *)&lpstmBody)))
{
hr = HrCopyStream(lpImsg->lpstmHtml, lpstmBody, NULL);
lpstmBody->Release();
if (FAILED(hr))
goto exit;
}
if (lpImsg->lpstmBody &&
SUCCEEDED(lpMessage->OpenProperty(PR_BODY, (LPIID)&IID_IStream, 0, MAPI_CREATE | MAPI_MODIFY, (LPUNKNOWN *)&lpstmBody)))
{
hr = HrCopyStream(lpImsg->lpstmBody, lpstmBody, NULL);
lpstmBody->Release();
if (FAILED(hr))
goto exit;
}
if (FAILED(hr = lpMessage->SaveChanges(0)))
goto exit;
exit:
if (lpMsgPropValue)
lpMAPIFreeBuffer (lpMsgPropValue);
return hr;
}
HRESULT HrImsgAttachToMapiAttach(LPMESSAGE lpMessage, LPIMSG lpImsg)
{
ULONG i, iAttach;
HRESULT hr = S_OK;
if (!lpMessage || !lpImsg)
return E_FAIL;
if (lpImsg->cAttach == 0)
return S_OK;
if (!lpImsg->lpIatt)
return E_FAIL;
/*
attachment properties and indices:
colAttMethod,
colAttNum,
colAttLongFilename,
colAttPathname,
colAttTag,
colAttFilename,
colAttExtension,
colAttSize,
colLast3
PR_ATTACH_METHOD,
PR_ATTACH_NUM,
PR_ATTACH_LONG_FILENAME,
PR_ATTACH_PATHNAME,
PR_ATTACH_TAG,
PR_ATTACH_FILENAME,
PR_ATTACH_EXTENSION,
PR_ATTACH_SIZE
*/
for (i=0; i<lpImsg->cAttach; i++)
{
LPSPropValue rgPropVals = 0;
ULONG cb = 0, cProp = 0;
HRESULT hropen;
LPMESSAGE lpmsg = NULL;
LPSTREAM lpstm = 0;
LPIATTINFO lpiatt = (LPIATTINFO)&(lpImsg->lpIatt[i]);
LPATTACH lpAttach = 0;
Assert(lpiatt);
if (lpiatt->fError)
continue;
if (FAILED(lpMessage->CreateAttach(NULL, NULL, &iAttach, &lpAttach)))
goto cleanup;
if (FAILED(lpMAPIAllocateBuffer(sizeof(SPropValue)*colLast3, (LPVOID*)&rgPropVals)))
goto cleanup;
ZeroMemory(rgPropVals, sizeof(SPropValue)*colLast3);
if (lpiatt->lpszPathName)
{
rgPropVals[cProp].ulPropTag = PR_ATTACH_PATHNAME;
rgPropVals[cProp].Value.lpszA = MapiStringDup(lpiatt->lpszPathName, rgPropVals);
cProp++;
}
if (lpiatt->lpszFileName)
{
rgPropVals[cProp].ulPropTag = PR_ATTACH_FILENAME;
rgPropVals[cProp].Value.lpszA = MapiStringDup(lpiatt->lpszFileName, rgPropVals);
cProp++;
}
if (lpiatt->lpszExt)
{
rgPropVals[cProp].ulPropTag = PR_ATTACH_EXTENSION;
rgPropVals[cProp].Value.lpszA = MapiStringDup(lpiatt->lpszExt, rgPropVals);
cProp++;
}
switch(lpiatt->dwType)
{
case IATT_FILE:
rgPropVals[cProp].ulPropTag = PR_OBJECT_TYPE;
rgPropVals[cProp].Value.ul = MAPI_ATTACH;
cProp++;
rgPropVals[cProp].ulPropTag = PR_ATTACH_METHOD;
rgPropVals[cProp].Value.ul = ATTACH_BY_VALUE;
cProp++;
hropen = lpAttach->OpenProperty(PR_ATTACH_DATA_BIN, (LPIID)&IID_IStream,
STGM_WRITE, MAPI_MODIFY | MAPI_CREATE,
(LPUNKNOWN *)&lpstm);
if (!FAILED(hropen))
{
Assert(lpstm != NULL);
if (!FAILED(HrCopyStream(lpiatt->lpstmAtt, lpstm, &cb)))
lpstm->Commit(0);
lpstm->Release();
lpstm=0;
}
break;
case IATT_MSG:
rgPropVals[cProp].ulPropTag = PR_OBJECT_TYPE;
rgPropVals[cProp].Value.ul = MAPI_MESSAGE;
cProp++;
rgPropVals[cProp].ulPropTag = PR_ATTACH_METHOD;
rgPropVals[cProp].Value.ul = ATTACH_EMBEDDED_MSG;
cProp++;
hropen = lpAttach->OpenProperty(PR_ATTACH_DATA_OBJ, (LPIID)&IID_IMessage,
0, MAPI_MODIFY | MAPI_CREATE,
(LPUNKNOWN *)&lpmsg);
if (!FAILED(hropen))
{
Assert(lpmsg != NULL);
HrImsgToMapi(lpiatt->lpImsg, lpmsg);
lpmsg->Release();
lpmsg = NULL;
}
break;
default:
AssertSz(FALSE, "Unexpected attachment type!");
break;
}
// need to set the property
hr = lpAttach->SetProps(cProp, rgPropVals, NULL);
if (FAILED(hr))
goto cleanup;
hr = lpAttach->SaveChanges(0);
if (FAILED(hr))
goto cleanup;
cleanup:
if (rgPropVals)
{
lpMAPIFreeBuffer(rgPropVals);
rgPropVals = 0;
}
if (lpAttach)
{
lpAttach->Release();
lpAttach = 0;
}
}
return hr;
}
// =====================================================================================
//
// HrImsgRecipToMapiRecip:
//
// =====================================================================================
HRESULT HrImsgRecipToMapiRecip(LPMESSAGE lpMessage, LPIMSG lpImsg)
{
LPADRENTRY lpadrentry;
ULONG cb, i;
LPADRLIST lpadrlist = 0;
LPSPropValue rgPropVals = 0;
HRESULT hr = E_FAIL;
if (lpImsg == NULL)
return(E_FAIL);
if (lpImsg->cAddress == 0)
return(S_OK);
if (lpMessage == NULL || lpImsg->lpIaddr == NULL)
return(E_FAIL);
cb = sizeof(ADRLIST) + lpImsg->cAddress * sizeof(ADRENTRY);
if (FAILED(lpMAPIAllocateBuffer(cb, (LPVOID*)&lpadrlist)))
return(E_OUTOFMEMORY);
ZeroMemory(lpadrlist, cb);
// enumerate through the recipient list
for (i = 0; i < lpImsg->cAddress; i++)
{
if (lpImsg->lpIaddr[i].dwType == IADDR_FROM)
continue;
lpadrentry = (LPADRENTRY)&(lpadrlist->aEntries[lpadrlist->cEntries]);
// this memory is freed by lpMessage
if (FAILED(lpMAPIAllocateBuffer(sizeof(SPropValue) * colLast2, (LPVOID *)&rgPropVals)))
{
hr = E_OUTOFMEMORY;
goto exit;
}
lpadrentry->cValues = 0;
lpadrentry->rgPropVals = rgPropVals;
lpadrlist->cEntries++;
rgPropVals[colRecipAddrType].ulPropTag = PR_ADDRTYPE;
rgPropVals[colRecipAddrType].Value.lpszA = MapiStringDup("SMTP", rgPropVals);
lpadrentry->cValues++;
Assert(lpadrentry->cValues <= colLast2);
rgPropVals[colRecipName].ulPropTag = PR_DISPLAY_NAME;
rgPropVals[colRecipName].Value.lpszA = MapiStringDup(lpImsg->lpIaddr[i].lpszDisplay, rgPropVals);
lpadrentry->cValues++;
Assert(lpadrentry->cValues <= colLast2);
rgPropVals[colRecipAddress].ulPropTag = PR_EMAIL_ADDRESS;
rgPropVals[colRecipAddress].Value.lpszA = MapiStringDup(lpImsg->lpIaddr[i].lpszAddress, rgPropVals);
lpadrentry->cValues++;
Assert(lpadrentry->cValues <= colLast2);
rgPropVals[colRecipType].ulPropTag = PR_RECIPIENT_TYPE;
switch(lpImsg->lpIaddr[i].dwType)
{
case IADDR_FROM:
rgPropVals[colRecipType].Value.ul = MAPI_ORIG;
break;
case IADDR_CC:
rgPropVals[colRecipType].Value.ul = MAPI_CC;
break;
case IADDR_BCC:
rgPropVals[colRecipType].Value.ul = MAPI_BCC;
break;
case IADDR_TO:
default:
rgPropVals[colRecipType].Value.ul = MAPI_TO;
break;
}
lpadrentry->cValues++;
Assert(lpadrentry->cValues <= colLast2);
// reset the variable so we don't free up on exit
rgPropVals = 0;
}
hr = lpMessage->ModifyRecipients(MODRECIP_ADD, lpadrlist);
exit:
// Free the buffers
for (i = 0; i < lpadrlist->cEntries; i++)
lpMAPIFreeBuffer(lpadrlist->aEntries[i].rgPropVals);
lpMAPIFreeBuffer(lpadrlist);
return(hr);
}
LPSTR MapiStringDup (LPCTSTR lpcsz, LPVOID lpobj)
{
LPSTR lpszDup = NULL;
if (lpcsz == NULL)
return NULL;
INT nLen = lstrlen (lpcsz) + 1;
if (lpobj)
{
if (FAILED(lpMAPIAllocateMore(nLen*sizeof(TCHAR), lpobj, (LPVOID FAR*)&lpszDup)))
return NULL;
}
else
{
if (FAILED(lpMAPIAllocateBuffer(nLen*sizeof(TCHAR), (LPVOID FAR*)&lpszDup)))
return NULL;
}
CopyMemory (lpszDup, lpcsz, nLen*sizeof(TCHAR));
return lpszDup;
}