Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

460 lines
15 KiB

// =====================================================================================
// 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 "Imnapi.h"
#include "Exchrep.h"
#include "Mapiconv.h"
#include "Error.h"
HRESULT HrCopyStream (LPSTREAM lpstmIn, LPSTREAM lpstmOut, ULONG *pcb);
// =====================================================================================
// MAPI Message Properties that I want
// =====================================================================================
enum
{
colSenderAddrType,
colSenderName,
colSenderEMail,
colSubject,
colDeliverTime,
colBody,
colPriority,
colLast1
};
SizedSPropTagArray (colLast1, sptMessageProps) =
{
colLast1,
{
PR_SENDER_ADDRTYPE,
PR_SENDER_NAME,
PR_SENDER_EMAIL_ADDRESS,
PR_SUBJECT,
PR_MESSAGE_DELIVERY_TIME,
PR_BODY,
PR_PRIORITY
}
};
// =====================================================================================
// 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,
colAttLongPathname,
colAttPathname,
colAttTag,
colAttFilename,
colAttExtension,
colAttSize,
colLast3
};
SizedSPropTagArray (colLast3, sptAttProps) =
{
colLast3,
{
PR_ATTACH_METHOD,
PR_ATTACH_NUM,
PR_ATTACH_LONG_FILENAME,
PR_ATTACH_LONG_PATHNAME,
PR_ATTACH_PATHNAME,
PR_ATTACH_TAG,
PR_ATTACH_FILENAME,
PR_ATTACH_EXTENSION,
PR_ATTACH_SIZE
}
};
// =============================================================================================
// StringDup - duplicates a string
// =============================================================================================
LPTSTR StringDup (LPCTSTR lpcsz)
{
// Locals
LPTSTR lpszDup;
if (lpcsz == NULL)
return NULL;
INT nLen = lstrlen (lpcsz) + 1;
lpszDup = (LPTSTR)malloc (nLen * sizeof (TCHAR));
if (lpszDup)
CopyMemory (lpszDup, lpcsz, nLen);
return lpszDup;
}
// =====================================================================================
// HrMapiToImsg
// =====================================================================================
HRESULT HrMapiToImsg (LPMESSAGE lpMessage, LPIMSG lpImsg)
{
// Locals
HRESULT hr = S_OK;
ULONG cProp, i;
LPSPropValue lpMsgPropValue = NULL;
LPSRowSet lpRecipRows = NULL, lpAttRows = NULL;
LPMAPITABLE lptblRecip = NULL, lptblAtt = NULL;
LPATTACH lpAttach = NULL;
LPMESSAGE lpMsgAtt = NULL;
LPSTREAM lpstmRtfComp = NULL, lpstmRtf = NULL;
// 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 = StringDup (lpMsgPropValue[colSubject].Value.lpszA);
// Body
if (PROP_TYPE(lpMsgPropValue[colBody].ulPropTag) != PT_ERROR)
lpImsg->lpszBody = StringDup (lpMsgPropValue[colBody].Value.lpszA);
// RTF
if (!FAILED (lpMessage->OpenProperty (PR_RTF_COMPRESSED, (LPIID)&IID_IStream, 0, 0, (LPUNKNOWN *)&lpstmRtfComp)))
if (!FAILED (WrapCompressedRTFStream (lpstmRtfComp, 0, &lpstmRtf)))
if (!FAILED (CreateStreamOnHFile (NULL, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL, &lpImsg->lpstmRtf)))
HrCopyStream (lpstmRtf, lpImsg->lpstmRtf, NULL);
// Delivery Time
if (PROP_TYPE(lpMsgPropValue[colDeliverTime].ulPropTag) != PT_ERROR)
CopyMemory (&lpImsg->ftDelivery, &lpMsgPropValue[colDeliverTime].Value.ft, sizeof (FILETIME));
// Priority
lpImsg->wPriority = PRI_NORMAL;
if (PROP_TYPE(lpMsgPropValue[colPriority].ulPropTag) != PT_ERROR)
{
switch (lpMsgPropValue[colPriority].Value.l)
{
case PRIO_NORMAL:
lpImsg->wPriority = PRI_NORMAL;
break;
case PRIO_URGENT:
lpImsg->wPriority = PRI_HIGH;
break;
case PRIO_NONURGENT:
default:
lpImsg->wPriority = PRI_LOW;
break;
}
}
// Get the recipient table
hr = lpMessage->GetRecipientTable (0, &lptblRecip);
if (FAILED (hr))
goto exit;
// Get all the rows of the recipient table
hr = HrQueryAllRows (lptblRecip, (LPSPropTagArray)&sptRecipProps, NULL, NULL, 0, &lpRecipRows);
if (FAILED (hr))
goto exit;
// Allocate Recipient Array
lpImsg->cAddress = lpRecipRows->cRows + 1;
lpImsg->lpIaddr = (LPIADDRINFO)malloc (sizeof (IADDRINFO) * lpImsg->cAddress);
if (lpImsg->lpIaddr == NULL)
goto exit;
// Originator of the message "From: "
lpImsg->lpIaddr[0].dwType = IADDR_FROM;
if (PROP_TYPE(lpMsgPropValue[colSenderName].ulPropTag) != PT_ERROR)
{
lpImsg->lpIaddr[0].lpszDisplay = StringDup (lpMsgPropValue[colSenderName].Value.lpszA);
lpImsg->lpIaddr[0].lpszAddress = StringDup (lpMsgPropValue[colSenderName].Value.lpszA);
}
if (PROP_TYPE(lpMsgPropValue[colSenderEMail].ulPropTag) != PT_ERROR &&
PROP_TYPE(lpMsgPropValue[colSenderAddrType].ulPropTag) != PT_ERROR &&
lstrcmpi (lpMsgPropValue[colSenderAddrType].Value.lpszA, "SMTP") == 0)
{
lpImsg->lpIaddr[0].lpszAddress = StringDup (lpMsgPropValue[colSenderEMail].Value.lpszA);
}
// 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:
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;
if (PROP_TYPE(lpRecipRows->aRow[i].lpProps[colRecipName].ulPropTag) != PT_ERROR)
{
lpImsg->lpIaddr[i+1].lpszDisplay = StringDup (lpRecipRows->aRow[i].lpProps[colRecipName].Value.lpszA);
lpImsg->lpIaddr[i+1].lpszAddress = StringDup (lpRecipRows->aRow[i].lpProps[colRecipName].Value.lpszA);
}
if (PROP_TYPE(lpRecipRows->aRow[i].lpProps[colRecipName].ulPropTag) != PT_ERROR &&
PROP_TYPE(lpMsgPropValue[colRecipAddrType].ulPropTag) != PT_ERROR &&
lstrcmpi (lpMsgPropValue[colRecipAddrType].Value.lpszA, "SMTP") == 0)
{
lpImsg->lpIaddr[i+1].lpszAddress = StringDup (lpRecipRows->aRow[i].lpProps[colRecipAddress].Value.lpszA);
}
}
// Free Rows
if (lpRecipRows)
FreeProws (lpRecipRows);
lpRecipRows = NULL;
// Attachments
hr = lpMessage->GetAttachmentTable (0, &lptblAtt);
if (FAILED (hr))
goto exit;
// Get all the rows of the recipient table
hr = HrQueryAllRows (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;
lpImsg->lpIatt = (LPIATTINFO)malloc (sizeof (IATTINFO) * lpImsg->cAttach);
if (lpImsg->lpIatt == NULL)
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)
lpImsg->lpIatt[i].lpszPathName = StringDup (lpAttRows->aRow[i].lpProps[colAttPathname].Value.lpszA);
if (PROP_TYPE(lpAttRows->aRow[i].lpProps[colAttFilename].ulPropTag) != PT_ERROR)
lpImsg->lpIatt[i].lpszFileName = StringDup (lpAttRows->aRow[i].lpProps[colAttFilename].Value.lpszA);
if (PROP_TYPE(lpAttRows->aRow[i].lpProps[colAttExtension].ulPropTag) != PT_ERROR)
lpImsg->lpIatt[i].lpszExt = StringDup (lpAttRows->aRow[i].lpProps[colAttExtension].Value.lpszA);
// 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
{
lpImsg->lpIatt[i].lpImsg = (LPIMSG)malloc (sizeof (IMSG));
if (lpImsg->lpIatt[i].lpImsg == NULL)
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;
}
}
exit:
// Cleanup
if (lpAttach)
lpAttach->Release ();
if (lptblAtt)
lptblAtt->Release ();
if (lpAttRows)
FreeProws (lpAttRows);
if (lpRecipRows)
FreeProws (lpRecipRows);
if (lpMsgPropValue)
MAPIFreeBuffer (lpMsgPropValue);
if (lptblRecip)
lptblRecip->Release ();
if (lpMsgAtt)
lpMsgAtt->Release ();
if (lpstmRtfComp)
lpstmRtfComp->Release ();
if (lpstmRtf)
lpstmRtf->Release ();
// Done
return hr;
}
void AssertSzFn(LPSTR szMsg, LPSTR szFile, int nLine)
{
static const char rgch1[] = "File %s, line %d:";
static const char rgch2[] = "Unknown file:";
static const char szAssert[] = "Assert Failure";
char rgch[512];
char *lpsz;
int ret, cch;
if (szFile)
wnsprintf(rgch, ARRAYSIZE(rgch),rgch1, szFile, nLine);
else
StrCpyN(rgch, rgch2,ARRAYSIZE(rgch));
cch = lstrlen(rgch);
Assert(lstrlen(szMsg)<(512-cch-3));
lpsz = &rgch[cch];
*lpsz++ = '\n';
*lpsz++ = '\n';
StrCpyN(lpsz, szMsg, (ARRAYSIZE(rgch)-cch-2));
ret = MessageBox(GetActiveWindow(), rgch, szAssert, MB_ABORTRETRYIGNORE|MB_ICONHAND|MB_SYSTEMMODAL|MB_SETFOREGROUND);
if (ret != IDIGNORE)
DebugBreak();
/* Force a hard exit w/ a GP-fault so that Dr. Watson generates a nice stack trace log. */
if (ret == IDABORT)
*(LPBYTE)0 = 1; // write to address 0 causes GP-fault
}
// =====================================================================================
// HrCopyStream - caller must do the commit
// =====================================================================================
HRESULT HrCopyStream (LPSTREAM lpstmIn, LPSTREAM lpstmOut, ULONG *pcb)
{
// Locals
HRESULT hr = S_OK;
BYTE buf[4096];
ULONG cbRead = 0, cbTotal = 0;
do
{
hr = lpstmIn->Read (buf, sizeof (buf), &cbRead);
if (FAILED (hr))
goto exit;
if (cbRead == 0) break;
hr = lpstmOut->Write (buf, cbRead, NULL);
if (FAILED (hr))
goto exit;
cbTotal += cbRead;
}
while (cbRead == sizeof (buf));
exit:
if (pcb)
*pcb = cbTotal;
return hr;
}