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.

965 lines
30 KiB

  1. // =====================================================================================
  2. // m a p c o n v . c p p
  3. // conver a MAPI message to and from an RFC 822/RFC 1521 (mime) internet message
  4. // =====================================================================================
  5. #include "pch.hxx"
  6. #include <newimp.h>
  7. #include "Imnapi.h"
  8. #include "Mapiconv.h"
  9. #include <impapi.h>
  10. #include <import.h>
  11. #include "demand.h"
  12. LPSTR MapiStringDup (LPCTSTR lpcsz, LPVOID lpobj);
  13. HRESULT HrImsgRecipToMapiRecip(LPMESSAGE lpMessage, LPIMSG lpImsg);
  14. HRESULT HrImsgAttachToMapiAttach(LPMESSAGE lpMessage, LPIMSG lpImsg);
  15. // =====================================================================================
  16. // MAPI Message Properties that I want
  17. // =====================================================================================
  18. #define PR_BODY_HTML PROP_TAG( PT_TSTRING, 0x1013)
  19. enum
  20. {
  21. colSenderAddrType,
  22. colSenderName,
  23. colSenderEMail,
  24. colDelegateAddrType,
  25. colDelegateName,
  26. colDelegateEMail,
  27. colSubject,
  28. colReceiveTime,
  29. colSendTime,
  30. colPriority,
  31. colFlags,
  32. colLast1
  33. };
  34. SizedSPropTagArray (colLast1, sptMessageProps) =
  35. {
  36. colLast1,
  37. {
  38. PR_SENDER_ADDRTYPE,
  39. PR_SENDER_NAME,
  40. PR_SENDER_EMAIL_ADDRESS,
  41. PR_SENT_REPRESENTING_ADDRTYPE,
  42. PR_SENT_REPRESENTING_NAME,
  43. PR_SENT_REPRESENTING_EMAIL_ADDRESS,
  44. PR_SUBJECT,
  45. PR_MESSAGE_DELIVERY_TIME,
  46. PR_CLIENT_SUBMIT_TIME,
  47. PR_IMPORTANCE,
  48. PR_MESSAGE_FLAGS
  49. }
  50. };
  51. // =====================================================================================
  52. // MAPI Recip Props
  53. // =====================================================================================
  54. enum
  55. {
  56. colRecipAddrType,
  57. colRecipName,
  58. colRecipAddress,
  59. colRecipType,
  60. colLast2
  61. };
  62. SizedSPropTagArray (colLast2, sptRecipProps) =
  63. {
  64. colLast2,
  65. {
  66. PR_ADDRTYPE,
  67. PR_DISPLAY_NAME,
  68. PR_EMAIL_ADDRESS,
  69. PR_RECIPIENT_TYPE
  70. }
  71. };
  72. // =====================================================================================
  73. // MAPI Attachment Props
  74. // =====================================================================================
  75. enum
  76. {
  77. colAttMethod,
  78. colAttNum,
  79. colAttLongFilename,
  80. colAttPathname,
  81. colAttTag,
  82. colAttFilename,
  83. colAttExtension,
  84. colAttSize,
  85. colLast3
  86. };
  87. SizedSPropTagArray (colLast3, sptAttProps) =
  88. {
  89. colLast3,
  90. {
  91. PR_ATTACH_METHOD,
  92. PR_ATTACH_NUM,
  93. PR_ATTACH_LONG_FILENAME,
  94. PR_ATTACH_PATHNAME,
  95. PR_ATTACH_TAG,
  96. PR_ATTACH_FILENAME,
  97. PR_ATTACH_EXTENSION,
  98. PR_ATTACH_SIZE
  99. }
  100. };
  101. char *GetRecipAddress(LPSPropValue ppropAddr, LPSPropValue ppropType)
  102. {
  103. char *sz, *szT;
  104. sz = NULL;
  105. if (PROP_TYPE(ppropAddr->ulPropTag) != PT_ERROR &&
  106. PROP_TYPE(ppropType->ulPropTag) != PT_ERROR)
  107. {
  108. szT = ppropType->Value.lpszA;
  109. if (lstrcmp(szT, "SMTP") == 0 || lstrcmp(szT, "MSNINET") == 0)
  110. {
  111. sz = PszDup(ppropAddr->Value.lpszA);
  112. }
  113. else if (lstrcmp(szT, "MSN") == 0 || lstrcmp(szT, "MSNLIST") == 0)
  114. {
  115. szT = ppropAddr->Value.lpszA;
  116. DWORD cch = lstrlen(szT) + 16;
  117. if (MemAlloc((void **)&sz, cch*sizeof(sz[0])))
  118. {
  119. StrCpyN(sz, szT, cch);
  120. StrCatBuff(sz, "@msn.com", cch);
  121. }
  122. }
  123. }
  124. return(sz);
  125. }
  126. // =====================================================================================
  127. // HrMapiToImsg
  128. // =====================================================================================
  129. HRESULT HrMapiToImsg (LPMESSAGE lpMessage, LPIMSG lpImsg)
  130. {
  131. // Locals
  132. LPSPropValue ppropAddr, ppropType, ppropName;
  133. TCHAR szUnk[128];
  134. int cchUnk;
  135. TCHAR *sz, *szT;
  136. HRESULT hr;
  137. ULONG cProp, i;
  138. LPSPropValue lpMsgPropValue = NULL;
  139. LPSRowSet lpRecipRows = NULL, lpAttRows = NULL;
  140. LPMAPITABLE lptblRecip = NULL, lptblAtt = NULL;
  141. LPATTACH lpAttach = NULL;
  142. LPMESSAGE lpMsgAtt = NULL;
  143. LPSTREAM lpstmBody = NULL;
  144. cchUnk = LoadString(g_hInstImp, idsAddressUnknownFmt, szUnk, ARRAYSIZE(szUnk));
  145. // Zero init
  146. ZeroMemory (lpImsg, sizeof (IMSG));
  147. // Get the propsw
  148. hr = lpMessage->GetProps ((LPSPropTagArray)&sptMessageProps, 0, &cProp, &lpMsgPropValue);
  149. if (FAILED (hr))
  150. goto exit;
  151. // Subject
  152. if (PROP_TYPE(lpMsgPropValue[colSubject].ulPropTag) != PT_ERROR)
  153. lpImsg->lpszSubject = PszDup(lpMsgPropValue[colSubject].Value.lpszA);
  154. // Body
  155. if (SUCCEEDED(lpMessage->OpenProperty(PR_BODY_HTML, (LPIID)&IID_IStream, 0, 0, (LPUNKNOWN *)&lpstmBody)))
  156. {
  157. if (SUCCEEDED(hr = CreateStreamOnHFile (NULL, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL, &lpImsg->lpstmHtml)))
  158. hr = HrCopyStream(lpstmBody, lpImsg->lpstmHtml, NULL);
  159. lpstmBody->Release();
  160. lpstmBody = NULL;
  161. if (FAILED(hr))
  162. goto exit;
  163. }
  164. else if (SUCCEEDED(lpMessage->OpenProperty(PR_BODY, (LPIID)&IID_IStream, 0, 0, (LPUNKNOWN *)&lpstmBody)))
  165. {
  166. if (SUCCEEDED(hr = CreateStreamOnHFile (NULL, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL, &lpImsg->lpstmBody)))
  167. hr = HrCopyStream(lpstmBody, lpImsg->lpstmBody, NULL);
  168. lpstmBody->Release();
  169. lpstmBody = NULL;
  170. if (FAILED(hr))
  171. goto exit;
  172. }
  173. // Send Time
  174. if (PROP_TYPE(lpMsgPropValue[colSendTime].ulPropTag) != PT_ERROR)
  175. CopyMemory(&lpImsg->ftSend, &lpMsgPropValue[colSendTime].Value.ft, sizeof (FILETIME));
  176. // Receive Time
  177. if (PROP_TYPE(lpMsgPropValue[colReceiveTime].ulPropTag) != PT_ERROR)
  178. CopyMemory(&lpImsg->ftReceive, &lpMsgPropValue[colReceiveTime].Value.ft, sizeof (FILETIME));
  179. // Priority
  180. lpImsg->wPriority = PRI_NORMAL;
  181. if (PROP_TYPE(lpMsgPropValue[colPriority].ulPropTag) != PT_ERROR)
  182. {
  183. switch (lpMsgPropValue[colPriority].Value.l)
  184. {
  185. case IMPORTANCE_LOW:
  186. lpImsg->wPriority = PRI_LOW;
  187. break;
  188. case IMPORTANCE_HIGH:
  189. lpImsg->wPriority = PRI_HIGH;
  190. break;
  191. case IMPORTANCE_NORMAL:
  192. default:
  193. lpImsg->wPriority = PRI_NORMAL;
  194. break;
  195. }
  196. }
  197. // message flags
  198. if (PROP_TYPE(lpMsgPropValue[colFlags].ulPropTag) != PT_ERROR)
  199. lpImsg->uFlags = lpMsgPropValue[colFlags].Value.ul;
  200. // Get the recipient table
  201. hr = lpMessage->GetRecipientTable (0, &lptblRecip);
  202. if (FAILED (hr))
  203. goto exit;
  204. // Get all the rows of the recipient table
  205. hr = lpHrQueryAllRows (lptblRecip, (LPSPropTagArray)&sptRecipProps, NULL, NULL, 0, &lpRecipRows);
  206. if (FAILED (hr))
  207. goto exit;
  208. // Allocate Recipient Array
  209. lpImsg->cAddress = lpRecipRows->cRows + 1;
  210. if (!MemAlloc((void **)&lpImsg->lpIaddr, sizeof (IADDRINFO) * lpImsg->cAddress))
  211. {
  212. hr = E_OUTOFMEMORY;
  213. goto exit;
  214. }
  215. ZeroMemory(lpImsg->lpIaddr, sizeof (IADDRINFO) * lpImsg->cAddress);
  216. ppropAddr = &lpMsgPropValue[colDelegateEMail];
  217. ppropType = &lpMsgPropValue[colDelegateAddrType];
  218. ppropName = &lpMsgPropValue[colDelegateName];
  219. if (PROP_TYPE(ppropAddr->ulPropTag) == PT_ERROR ||
  220. PROP_TYPE(ppropType->ulPropTag) == PT_ERROR)
  221. {
  222. ppropAddr = &lpMsgPropValue[colSenderEMail];
  223. ppropType = &lpMsgPropValue[colSenderAddrType];
  224. ppropName = &lpMsgPropValue[colSenderName];
  225. }
  226. // Originator of the message "From: "
  227. lpImsg->lpIaddr[0].dwType = IADDR_FROM;
  228. lpImsg->lpIaddr[0].lpszAddress = GetRecipAddress(ppropAddr, ppropType);
  229. if (PROP_TYPE(ppropName->ulPropTag) != PT_ERROR)
  230. {
  231. szT = ppropName->Value.lpszA;
  232. if (lpImsg->lpIaddr[0].lpszAddress != NULL)
  233. {
  234. sz = PszDup(szT);
  235. }
  236. else
  237. {
  238. lpImsg->lpIaddr[0].lpszAddress = PszDup(szT);
  239. DWORD cchSz = lstrlen(szT) + cchUnk;
  240. if (!MemAlloc((void **)&sz, cchSz*sizeof(sz[0])))
  241. {
  242. hr = E_OUTOFMEMORY;
  243. goto exit;
  244. }
  245. wnsprintf(sz, cchSz, szUnk, szT);
  246. }
  247. lpImsg->lpIaddr[0].lpszDisplay = sz;
  248. }
  249. // Add in the rest of the recipients
  250. for (i=0; i<lpRecipRows->cRows; i++)
  251. {
  252. Assert (i+1 < lpImsg->cAddress);
  253. if (PROP_TYPE(lpRecipRows->aRow[i].lpProps[colRecipType].ulPropTag) != PT_ERROR)
  254. {
  255. switch (lpRecipRows->aRow[i].lpProps[colRecipType].Value.ul)
  256. {
  257. case MAPI_TO:
  258. case 0x10000000: /* MAPI_P1: */
  259. lpImsg->lpIaddr[i+1].dwType = IADDR_TO;
  260. break;
  261. case MAPI_ORIG:
  262. lpImsg->lpIaddr[i+1].dwType = IADDR_FROM;
  263. break;
  264. case MAPI_CC:
  265. lpImsg->lpIaddr[i+1].dwType = IADDR_CC;
  266. break;
  267. case MAPI_BCC:
  268. lpImsg->lpIaddr[i+1].dwType = IADDR_BCC;
  269. break;
  270. default:
  271. Assert (FALSE);
  272. lpImsg->lpIaddr[i+1].dwType = IADDR_TO;
  273. break;
  274. }
  275. }
  276. else
  277. {
  278. lpImsg->lpIaddr[i+1].dwType = IADDR_TO;
  279. }
  280. lpImsg->lpIaddr[i+1].lpszAddress = GetRecipAddress(&lpRecipRows->aRow[i].lpProps[colRecipAddress], &lpRecipRows->aRow[i].lpProps[colRecipAddrType]);
  281. if (PROP_TYPE(lpRecipRows->aRow[i].lpProps[colRecipName].ulPropTag) != PT_ERROR)
  282. {
  283. szT = lpRecipRows->aRow[i].lpProps[colRecipName].Value.lpszA;
  284. if (lpImsg->lpIaddr[i + 1].lpszAddress != NULL)
  285. {
  286. sz = PszDup(szT);
  287. }
  288. else
  289. {
  290. lpImsg->lpIaddr[i+1].lpszAddress = PszDup(szT);
  291. DWORD cchSz = lstrlen(szT) + cchUnk;
  292. if (!MemAlloc((void **)&sz, cchSz*sizeof(sz[0])))
  293. {
  294. hr = E_OUTOFMEMORY;
  295. goto exit;
  296. }
  297. wnsprintf(sz, cchSz, szUnk, szT);
  298. }
  299. lpImsg->lpIaddr[i + 1].lpszDisplay = sz;
  300. }
  301. }
  302. // Free Rows
  303. if (lpRecipRows)
  304. lpFreeProws (lpRecipRows);
  305. lpRecipRows = NULL;
  306. // Attachments
  307. hr = lpMessage->GetAttachmentTable (0, &lptblAtt);
  308. if (FAILED (hr))
  309. goto exit;
  310. // Get all the rows of the recipient table
  311. hr = lpHrQueryAllRows (lptblAtt, (LPSPropTagArray)&sptAttProps, NULL, NULL, 0, &lpAttRows);
  312. if (FAILED (hr))
  313. goto exit;
  314. // Allocate files list
  315. if (lpAttRows->cRows == 0)
  316. goto exit;
  317. // Allocate memory
  318. lpImsg->cAttach = lpAttRows->cRows;
  319. if (!MemAlloc((void **)&lpImsg->lpIatt, sizeof (IATTINFO) * lpImsg->cAttach))
  320. {
  321. hr = E_OUTOFMEMORY;
  322. goto exit;
  323. }
  324. // Zero init
  325. ZeroMemory (lpImsg->lpIatt, sizeof (IATTINFO) * lpImsg->cAttach);
  326. // Walk the rows
  327. for (i=0; i<lpAttRows->cRows; i++)
  328. {
  329. if (PROP_TYPE(lpAttRows->aRow[i].lpProps[colAttMethod].ulPropTag) != PT_ERROR &&
  330. PROP_TYPE(lpAttRows->aRow[i].lpProps[colAttNum].ulPropTag) != PT_ERROR)
  331. {
  332. // Basic Properties
  333. if (PROP_TYPE(lpAttRows->aRow[i].lpProps[colAttPathname].ulPropTag) != PT_ERROR)
  334. {
  335. sz = lpAttRows->aRow[i].lpProps[colAttPathname].Value.lpszA;
  336. if (!FIsEmpty(sz))
  337. lpImsg->lpIatt[i].lpszPathName = PszDup(sz);
  338. }
  339. if (PROP_TYPE(lpAttRows->aRow[i].lpProps[colAttFilename].ulPropTag) != PT_ERROR)
  340. {
  341. sz = lpAttRows->aRow[i].lpProps[colAttFilename].Value.lpszA;
  342. if (!FIsEmpty(sz))
  343. lpImsg->lpIatt[i].lpszFileName = PszDup(sz);
  344. }
  345. if (lpImsg->lpIatt[i].lpszFileName == NULL &&
  346. PROP_TYPE(lpAttRows->aRow[i].lpProps[colAttLongFilename].ulPropTag) != PT_ERROR)
  347. {
  348. sz = lpAttRows->aRow[i].lpProps[colAttLongFilename].Value.lpszA;
  349. if (!FIsEmpty(sz))
  350. lpImsg->lpIatt[i].lpszFileName = PszDup(sz);
  351. }
  352. if (PROP_TYPE(lpAttRows->aRow[i].lpProps[colAttExtension].ulPropTag) != PT_ERROR)
  353. {
  354. sz = lpAttRows->aRow[i].lpProps[colAttExtension].Value.lpszA;
  355. if (!FIsEmpty(sz))
  356. lpImsg->lpIatt[i].lpszExt = PszDup(sz);
  357. }
  358. // Open the attachment
  359. hr = lpMessage->OpenAttach (lpAttRows->aRow[i].lpProps[colAttNum].Value.l, NULL, MAPI_BEST_ACCESS, &lpAttach);
  360. if (FAILED (hr))
  361. {
  362. lpImsg->lpIatt[i].fError = TRUE;
  363. continue;
  364. }
  365. // Handle the attachment method
  366. switch (lpAttRows->aRow[i].lpProps[colAttMethod].Value.ul)
  367. {
  368. case NO_ATTACHMENT:
  369. lpImsg->lpIatt[i].dwType = 0;
  370. lpImsg->lpIatt[i].fError = TRUE;
  371. break;
  372. case ATTACH_BY_REF_RESOLVE:
  373. case ATTACH_BY_VALUE:
  374. lpImsg->lpIatt[i].dwType = IATT_FILE;
  375. hr = lpAttach->OpenProperty (PR_ATTACH_DATA_BIN, (LPIID)&IID_IStream, 0, 0, (LPUNKNOWN *)&lpImsg->lpIatt[i].lpstmAtt);
  376. if (FAILED (hr))
  377. lpImsg->lpIatt[i].fError = TRUE;
  378. break;
  379. case ATTACH_BY_REF_ONLY:
  380. case ATTACH_BY_REFERENCE:
  381. lpImsg->lpIatt[i].dwType = IATT_FILE;
  382. hr = CreateStreamOnHFile (lpImsg->lpIatt[i].lpszPathName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL, &lpImsg->lpIatt[i].lpstmAtt);
  383. if (FAILED (hr))
  384. lpImsg->lpIatt[i].fError = TRUE;
  385. break;
  386. case ATTACH_EMBEDDED_MSG:
  387. lpImsg->lpIatt[i].dwType = IATT_MSG;
  388. hr = lpAttach->OpenProperty (PR_ATTACH_DATA_OBJ, (LPIID)&IID_IMessage, 0, 0, (LPUNKNOWN *)&lpMsgAtt);
  389. if (FAILED (hr) || lpMsgAtt == NULL)
  390. lpImsg->lpIatt[i].fError = TRUE;
  391. else
  392. {
  393. if (!MemAlloc((void **)&lpImsg->lpIatt[i].lpImsg, sizeof (IMSG)))
  394. lpImsg->lpIatt[i].fError = TRUE;
  395. else
  396. {
  397. hr = HrMapiToImsg (lpMsgAtt, lpImsg->lpIatt[i].lpImsg);
  398. if (FAILED (hr))
  399. lpImsg->lpIatt[i].fError = TRUE;
  400. }
  401. lpMsgAtt->Release ();
  402. lpMsgAtt = NULL;
  403. }
  404. break;
  405. case ATTACH_OLE:
  406. default:
  407. lpImsg->lpIatt[i].dwType = IATT_OLE;
  408. lpImsg->lpIatt[i].fError = TRUE;
  409. break;
  410. }
  411. // Free Attachment
  412. if (lpAttach)
  413. lpAttach->Release ();
  414. lpAttach = NULL;
  415. }
  416. }
  417. hr = S_OK;
  418. exit:
  419. // Cleanup
  420. if (lpAttach)
  421. lpAttach->Release ();
  422. if (lptblAtt)
  423. lptblAtt->Release ();
  424. if (lpAttRows)
  425. lpFreeProws (lpAttRows);
  426. if (lpRecipRows)
  427. lpFreeProws (lpRecipRows);
  428. if (lpMsgPropValue)
  429. lpMAPIFreeBuffer (lpMsgPropValue);
  430. if (lptblRecip)
  431. lptblRecip->Release ();
  432. if (lpMsgAtt)
  433. lpMsgAtt->Release ();
  434. if (lpstmBody)
  435. lpstmBody->Release ();
  436. // Done
  437. return hr;
  438. }
  439. // =====================================================================================
  440. //
  441. // HrImsgToMapi: lpImsg => lpMessage
  442. //
  443. // assumes lpMessage is initialized.
  444. //
  445. // =====================================================================================
  446. HRESULT HrImsgToMapi(LPIMSG lpImsg, LPMESSAGE lpMessage)
  447. {
  448. // Locals
  449. LPSTREAM lpstmBody;
  450. HRESULT hr = S_OK;
  451. ULONG i, cProp;
  452. LPSPropValue lpMsgPropValue = NULL;
  453. ULONG cPropMax = 13;
  454. /*
  455. properties to copy:
  456. PR_SENDER_ADDRTYPE,
  457. PR_SENDER_NAME,
  458. PR_SENDER_EMAIL_ADDRESS,
  459. PR_SUBJECT,
  460. PR_MESSAGE_DELIVERY_TIME,
  461. PR_IMPORTANCE,
  462. PR_MESSAGE_FLAGS
  463. PR_MESSAGE_CLASS
  464. PR_SENT_REPRESENTING_NAME,
  465. PR_SENT_REPRESENTING_EMAIL_ADDRESS,
  466. PR_SENT_REPRESENTING_ADDRTYPE,
  467. */
  468. Assert(lpMessage != NULL);
  469. // create the propvalue array
  470. hr = lpMAPIAllocateBuffer(cPropMax*sizeof(SPropValue), (LPVOID FAR*)&lpMsgPropValue);
  471. if (FAILED(hr))
  472. goto exit;
  473. ZeroMemory(lpMsgPropValue, cPropMax*sizeof(SPropValue));
  474. cProp = 0;
  475. lpMsgPropValue[cProp].Value.lpszA = MapiStringDup("IPM.Note", lpMsgPropValue);
  476. lpMsgPropValue[cProp].ulPropTag = PR_MESSAGE_CLASS;
  477. cProp++;
  478. // Subject
  479. if (lpImsg->lpszSubject)
  480. {
  481. lpMsgPropValue[cProp].Value.lpszA = MapiStringDup(lpImsg->lpszSubject, lpMsgPropValue);
  482. lpMsgPropValue[cProp].ulPropTag = PR_SUBJECT;
  483. cProp++;
  484. Assert(cProp <= cPropMax);
  485. }
  486. // Send Time
  487. CopyMemory(&lpMsgPropValue[cProp].Value.ft, &lpImsg->ftSend, sizeof (FILETIME));
  488. lpMsgPropValue[cProp].ulPropTag = PR_CLIENT_SUBMIT_TIME;
  489. cProp++;
  490. Assert(cProp <= cPropMax);
  491. // Receive Time
  492. CopyMemory(&lpMsgPropValue[cProp].Value.ft, &lpImsg->ftReceive, sizeof (FILETIME));
  493. lpMsgPropValue[cProp].ulPropTag = PR_MESSAGE_DELIVERY_TIME;
  494. cProp++;
  495. Assert(cProp <= cPropMax);
  496. // Priority
  497. lpMsgPropValue[cProp].ulPropTag = PR_IMPORTANCE;
  498. switch (lpImsg->wPriority)
  499. {
  500. case PRI_HIGH:
  501. lpMsgPropValue[cProp].Value.l = IMPORTANCE_HIGH;
  502. break;
  503. case PRI_LOW:
  504. lpMsgPropValue[cProp].Value.l = IMPORTANCE_LOW;
  505. break;
  506. case PRI_NORMAL:
  507. default:
  508. lpMsgPropValue[cProp].Value.l = IMPORTANCE_NORMAL;
  509. break;
  510. }
  511. cProp++;
  512. Assert(cProp <= cPropMax);
  513. // Message flags
  514. lpMsgPropValue[cProp].ulPropTag = PR_MESSAGE_FLAGS;
  515. lpMsgPropValue[cProp].Value.ul = lpImsg->uFlags;
  516. cProp++;
  517. Assert(cProp <= cPropMax);
  518. // recipients
  519. if (FAILED(hr = HrImsgRecipToMapiRecip(lpMessage, lpImsg)))
  520. goto exit;
  521. // sender information
  522. for (i = 0; i < lpImsg->cAddress; i++)
  523. {
  524. Assert(lpImsg->lpIaddr != NULL);
  525. if (lpImsg->lpIaddr[i].dwType == IADDR_FROM)
  526. {
  527. Assert(lpImsg->lpIaddr[i].lpszAddress);
  528. Assert(lpImsg->lpIaddr[i].lpszDisplay);
  529. lpMsgPropValue[cProp].Value.lpszA = MapiStringDup(lpImsg->lpIaddr[i].lpszDisplay, lpMsgPropValue);
  530. lpMsgPropValue[cProp].ulPropTag = PR_SENDER_NAME;
  531. cProp++;
  532. lpMsgPropValue[cProp].Value.lpszA = MapiStringDup(lpImsg->lpIaddr[i].lpszDisplay, lpMsgPropValue);
  533. lpMsgPropValue[cProp].ulPropTag = PR_SENT_REPRESENTING_NAME;
  534. cProp++;
  535. Assert(cProp <= cPropMax);
  536. lpMsgPropValue[cProp].Value.lpszA = MapiStringDup(lpImsg->lpIaddr[i].lpszAddress, lpMsgPropValue);
  537. lpMsgPropValue[cProp].ulPropTag = PR_SENDER_EMAIL_ADDRESS;
  538. cProp++;
  539. lpMsgPropValue[cProp].Value.lpszA = MapiStringDup(lpImsg->lpIaddr[i].lpszAddress, lpMsgPropValue);
  540. lpMsgPropValue[cProp].ulPropTag = PR_SENT_REPRESENTING_EMAIL_ADDRESS;
  541. cProp++;
  542. Assert(cProp <= cPropMax);
  543. lpMsgPropValue[cProp].Value.lpszA = MapiStringDup("SMTP", lpMsgPropValue);
  544. lpMsgPropValue[cProp].ulPropTag = PR_SENDER_ADDRTYPE;
  545. cProp++;
  546. lpMsgPropValue[cProp].Value.lpszA = MapiStringDup("SMTP", lpMsgPropValue);
  547. lpMsgPropValue[cProp].ulPropTag = PR_SENT_REPRESENTING_ADDRTYPE;
  548. cProp++;
  549. Assert(cProp <= cPropMax);
  550. break;
  551. }
  552. }
  553. // attachment information
  554. if (FAILED(hr = HrImsgAttachToMapiAttach(lpMessage, lpImsg)))
  555. goto exit;
  556. // save changes
  557. if (FAILED(hr = lpMessage->SetProps(cProp, lpMsgPropValue, NULL)))
  558. goto exit;
  559. // Body
  560. if (lpImsg->lpstmHtml &&
  561. SUCCEEDED(lpMessage->OpenProperty(PR_BODY_HTML, (LPIID)&IID_IStream, 0, MAPI_CREATE | MAPI_MODIFY, (LPUNKNOWN *)&lpstmBody)))
  562. {
  563. hr = HrCopyStream(lpImsg->lpstmHtml, lpstmBody, NULL);
  564. lpstmBody->Release();
  565. if (FAILED(hr))
  566. goto exit;
  567. }
  568. if (lpImsg->lpstmBody &&
  569. SUCCEEDED(lpMessage->OpenProperty(PR_BODY, (LPIID)&IID_IStream, 0, MAPI_CREATE | MAPI_MODIFY, (LPUNKNOWN *)&lpstmBody)))
  570. {
  571. hr = HrCopyStream(lpImsg->lpstmBody, lpstmBody, NULL);
  572. lpstmBody->Release();
  573. if (FAILED(hr))
  574. goto exit;
  575. }
  576. if (FAILED(hr = lpMessage->SaveChanges(0)))
  577. goto exit;
  578. exit:
  579. if (lpMsgPropValue)
  580. lpMAPIFreeBuffer (lpMsgPropValue);
  581. return hr;
  582. }
  583. HRESULT HrImsgAttachToMapiAttach(LPMESSAGE lpMessage, LPIMSG lpImsg)
  584. {
  585. ULONG i, iAttach;
  586. HRESULT hr = S_OK;
  587. if (!lpMessage || !lpImsg)
  588. return E_FAIL;
  589. if (lpImsg->cAttach == 0)
  590. return S_OK;
  591. if (!lpImsg->lpIatt)
  592. return E_FAIL;
  593. /*
  594. attachment properties and indices:
  595. colAttMethod,
  596. colAttNum,
  597. colAttLongFilename,
  598. colAttPathname,
  599. colAttTag,
  600. colAttFilename,
  601. colAttExtension,
  602. colAttSize,
  603. colLast3
  604. PR_ATTACH_METHOD,
  605. PR_ATTACH_NUM,
  606. PR_ATTACH_LONG_FILENAME,
  607. PR_ATTACH_PATHNAME,
  608. PR_ATTACH_TAG,
  609. PR_ATTACH_FILENAME,
  610. PR_ATTACH_EXTENSION,
  611. PR_ATTACH_SIZE
  612. */
  613. for (i=0; i<lpImsg->cAttach; i++)
  614. {
  615. LPSPropValue rgPropVals = 0;
  616. ULONG cb = 0, cProp = 0;
  617. HRESULT hropen;
  618. LPMESSAGE lpmsg = NULL;
  619. LPSTREAM lpstm = 0;
  620. LPIATTINFO lpiatt = (LPIATTINFO)&(lpImsg->lpIatt[i]);
  621. LPATTACH lpAttach = 0;
  622. Assert(lpiatt);
  623. if (lpiatt->fError)
  624. continue;
  625. if (FAILED(lpMessage->CreateAttach(NULL, NULL, &iAttach, &lpAttach)))
  626. goto cleanup;
  627. if (FAILED(lpMAPIAllocateBuffer(sizeof(SPropValue)*colLast3, (LPVOID*)&rgPropVals)))
  628. goto cleanup;
  629. ZeroMemory(rgPropVals, sizeof(SPropValue)*colLast3);
  630. if (lpiatt->lpszPathName)
  631. {
  632. rgPropVals[cProp].ulPropTag = PR_ATTACH_PATHNAME;
  633. rgPropVals[cProp].Value.lpszA = MapiStringDup(lpiatt->lpszPathName, rgPropVals);
  634. cProp++;
  635. }
  636. if (lpiatt->lpszFileName)
  637. {
  638. rgPropVals[cProp].ulPropTag = PR_ATTACH_FILENAME;
  639. rgPropVals[cProp].Value.lpszA = MapiStringDup(lpiatt->lpszFileName, rgPropVals);
  640. cProp++;
  641. }
  642. if (lpiatt->lpszExt)
  643. {
  644. rgPropVals[cProp].ulPropTag = PR_ATTACH_EXTENSION;
  645. rgPropVals[cProp].Value.lpszA = MapiStringDup(lpiatt->lpszExt, rgPropVals);
  646. cProp++;
  647. }
  648. switch(lpiatt->dwType)
  649. {
  650. case IATT_FILE:
  651. rgPropVals[cProp].ulPropTag = PR_OBJECT_TYPE;
  652. rgPropVals[cProp].Value.ul = MAPI_ATTACH;
  653. cProp++;
  654. rgPropVals[cProp].ulPropTag = PR_ATTACH_METHOD;
  655. rgPropVals[cProp].Value.ul = ATTACH_BY_VALUE;
  656. cProp++;
  657. hropen = lpAttach->OpenProperty(PR_ATTACH_DATA_BIN, (LPIID)&IID_IStream,
  658. STGM_WRITE, MAPI_MODIFY | MAPI_CREATE,
  659. (LPUNKNOWN *)&lpstm);
  660. if (!FAILED(hropen))
  661. {
  662. Assert(lpstm != NULL);
  663. if (!FAILED(HrCopyStream(lpiatt->lpstmAtt, lpstm, &cb)))
  664. lpstm->Commit(0);
  665. lpstm->Release();
  666. lpstm=0;
  667. }
  668. break;
  669. case IATT_MSG:
  670. rgPropVals[cProp].ulPropTag = PR_OBJECT_TYPE;
  671. rgPropVals[cProp].Value.ul = MAPI_MESSAGE;
  672. cProp++;
  673. rgPropVals[cProp].ulPropTag = PR_ATTACH_METHOD;
  674. rgPropVals[cProp].Value.ul = ATTACH_EMBEDDED_MSG;
  675. cProp++;
  676. hropen = lpAttach->OpenProperty(PR_ATTACH_DATA_OBJ, (LPIID)&IID_IMessage,
  677. 0, MAPI_MODIFY | MAPI_CREATE,
  678. (LPUNKNOWN *)&lpmsg);
  679. if (!FAILED(hropen))
  680. {
  681. Assert(lpmsg != NULL);
  682. HrImsgToMapi(lpiatt->lpImsg, lpmsg);
  683. lpmsg->Release();
  684. lpmsg = NULL;
  685. }
  686. break;
  687. default:
  688. AssertSz(FALSE, "Unexpected attachment type!");
  689. break;
  690. }
  691. // need to set the property
  692. hr = lpAttach->SetProps(cProp, rgPropVals, NULL);
  693. if (FAILED(hr))
  694. goto cleanup;
  695. hr = lpAttach->SaveChanges(0);
  696. if (FAILED(hr))
  697. goto cleanup;
  698. cleanup:
  699. if (rgPropVals)
  700. {
  701. lpMAPIFreeBuffer(rgPropVals);
  702. rgPropVals = 0;
  703. }
  704. if (lpAttach)
  705. {
  706. lpAttach->Release();
  707. lpAttach = 0;
  708. }
  709. }
  710. return hr;
  711. }
  712. // =====================================================================================
  713. //
  714. // HrImsgRecipToMapiRecip:
  715. //
  716. // =====================================================================================
  717. HRESULT HrImsgRecipToMapiRecip(LPMESSAGE lpMessage, LPIMSG lpImsg)
  718. {
  719. LPADRENTRY lpadrentry;
  720. ULONG cb, i;
  721. LPADRLIST lpadrlist = 0;
  722. LPSPropValue rgPropVals = 0;
  723. HRESULT hr = E_FAIL;
  724. if (lpImsg == NULL)
  725. return(E_FAIL);
  726. if (lpImsg->cAddress == 0)
  727. return(S_OK);
  728. if (lpMessage == NULL || lpImsg->lpIaddr == NULL)
  729. return(E_FAIL);
  730. cb = sizeof(ADRLIST) + lpImsg->cAddress * sizeof(ADRENTRY);
  731. if (FAILED(lpMAPIAllocateBuffer(cb, (LPVOID*)&lpadrlist)))
  732. return(E_OUTOFMEMORY);
  733. ZeroMemory(lpadrlist, cb);
  734. // enumerate through the recipient list
  735. for (i = 0; i < lpImsg->cAddress; i++)
  736. {
  737. if (lpImsg->lpIaddr[i].dwType == IADDR_FROM)
  738. continue;
  739. lpadrentry = (LPADRENTRY)&(lpadrlist->aEntries[lpadrlist->cEntries]);
  740. // this memory is freed by lpMessage
  741. if (FAILED(lpMAPIAllocateBuffer(sizeof(SPropValue) * colLast2, (LPVOID *)&rgPropVals)))
  742. {
  743. hr = E_OUTOFMEMORY;
  744. goto exit;
  745. }
  746. lpadrentry->cValues = 0;
  747. lpadrentry->rgPropVals = rgPropVals;
  748. lpadrlist->cEntries++;
  749. rgPropVals[colRecipAddrType].ulPropTag = PR_ADDRTYPE;
  750. rgPropVals[colRecipAddrType].Value.lpszA = MapiStringDup("SMTP", rgPropVals);
  751. lpadrentry->cValues++;
  752. Assert(lpadrentry->cValues <= colLast2);
  753. rgPropVals[colRecipName].ulPropTag = PR_DISPLAY_NAME;
  754. rgPropVals[colRecipName].Value.lpszA = MapiStringDup(lpImsg->lpIaddr[i].lpszDisplay, rgPropVals);
  755. lpadrentry->cValues++;
  756. Assert(lpadrentry->cValues <= colLast2);
  757. rgPropVals[colRecipAddress].ulPropTag = PR_EMAIL_ADDRESS;
  758. rgPropVals[colRecipAddress].Value.lpszA = MapiStringDup(lpImsg->lpIaddr[i].lpszAddress, rgPropVals);
  759. lpadrentry->cValues++;
  760. Assert(lpadrentry->cValues <= colLast2);
  761. rgPropVals[colRecipType].ulPropTag = PR_RECIPIENT_TYPE;
  762. switch(lpImsg->lpIaddr[i].dwType)
  763. {
  764. case IADDR_FROM:
  765. rgPropVals[colRecipType].Value.ul = MAPI_ORIG;
  766. break;
  767. case IADDR_CC:
  768. rgPropVals[colRecipType].Value.ul = MAPI_CC;
  769. break;
  770. case IADDR_BCC:
  771. rgPropVals[colRecipType].Value.ul = MAPI_BCC;
  772. break;
  773. case IADDR_TO:
  774. default:
  775. rgPropVals[colRecipType].Value.ul = MAPI_TO;
  776. break;
  777. }
  778. lpadrentry->cValues++;
  779. Assert(lpadrentry->cValues <= colLast2);
  780. // reset the variable so we don't free up on exit
  781. rgPropVals = 0;
  782. }
  783. hr = lpMessage->ModifyRecipients(MODRECIP_ADD, lpadrlist);
  784. exit:
  785. // Free the buffers
  786. for (i = 0; i < lpadrlist->cEntries; i++)
  787. lpMAPIFreeBuffer(lpadrlist->aEntries[i].rgPropVals);
  788. lpMAPIFreeBuffer(lpadrlist);
  789. return(hr);
  790. }
  791. LPSTR MapiStringDup (LPCTSTR lpcsz, LPVOID lpobj)
  792. {
  793. LPSTR lpszDup = NULL;
  794. if (lpcsz == NULL)
  795. return NULL;
  796. INT nLen = lstrlen (lpcsz) + 1;
  797. if (lpobj)
  798. {
  799. if (FAILED(lpMAPIAllocateMore(nLen*sizeof(TCHAR), lpobj, (LPVOID FAR*)&lpszDup)))
  800. return NULL;
  801. }
  802. else
  803. {
  804. if (FAILED(lpMAPIAllocateBuffer(nLen*sizeof(TCHAR), (LPVOID FAR*)&lpszDup)))
  805. return NULL;
  806. }
  807. CopyMemory (lpszDup, lpcsz, nLen*sizeof(TCHAR));
  808. return lpszDup;
  809. }