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.

1655 lines
52 KiB

  1. // --------------------------------------------------------------------------------
  2. // Mimetest.cpp
  3. //
  4. // This is a console app that has various types of functions that highlight the
  5. // most typical ways to use mimeole. This console app also acts as a test program
  6. // for mimeole, but does not actually do anything.
  7. //
  8. // Here are the files you need to use mimeole:
  9. //
  10. // mimeole.h - This is the main header file. It is generated from mimeole.idl.
  11. // mimeole.idl - This is the interface definition file. It has a little bit of
  12. // documentation. A client should use this file to find out info
  13. // about mimeole interfaces, data types, utility functions, etc.
  14. // inetcomm.dll - This is the DLL that contains the implementation of everything
  15. // in mimeole.h. You should run regsvr32.exe on inetcomm.dll.
  16. // msoert2.dll - inetcomm.dll statically links to this dll. msoert2 is the Microsoft
  17. // Outlook Express runtime library. msoert2.dll is part of the Outlook
  18. // Express installation. This DLL does not require any registration.
  19. // shlwapi.dll - inetcomm.dll statically links to this dll. shlwapi is part of the
  20. // Internet Explorer installation. shlwapi does not require any
  21. // registration.
  22. // mlang.dll - inetcomm.dll will dynamically load this dll. mlang is used to support
  23. // various character set translations. mlang stands for multi-language.
  24. // This DLL is part of the Internet Explorer installation. You should
  25. // run regsvr32.exe on mlang.dll to register it.
  26. // urlmon.dll - inetcomm.dll will dynamically load this dll. urlmon is used by
  27. // inetcomm to support various parts of MHTML as well as rendering
  28. // MHTML inside of the IE browser.
  29. // SMIME - SMIME support in mimeole requires the crypto API, which is part of
  30. // the IE installation.
  31. // Notes: shlwapi and msoert2, as well as any other DLLs that inetcomm.dll statically
  32. // links to must be either in the same directory as inetcomm.dll, or be located
  33. // in a directory that is in the system path.
  34. //
  35. // The DLLs that inetcomm dynamically load are not required. Inetcomm will still
  36. // work, although certain functionality will be disabled.
  37. // --------------------------------------------------------------------------------
  38. // --------------------------------------------------------------------------------
  39. // To use mimeole objects, per COM rules, you must have one file in your project that
  40. // has the #define INITGUID line, and then include mimeole.h. This will cause all of
  41. // the CLSIDs and IIDs to be defined.
  42. // --------------------------------------------------------------------------------
  43. #define INITGUID
  44. // --------------------------------------------------------------------------------
  45. // This is simply my precompiled header
  46. // --------------------------------------------------------------------------------
  47. #include "pch.h"
  48. #include <shlwapi.h>
  49. #include <shlwapip.h>
  50. // --------------------------------------------------------------------------------
  51. // Part of the initguid process
  52. // --------------------------------------------------------------------------------
  53. #include <initguid.h>
  54. // --------------------------------------------------------------------------------
  55. // Primary mimeole header file
  56. // --------------------------------------------------------------------------------
  57. #include <mimeole.h>
  58. #define DEFINE_HOTSTORE
  59. // --------------------------------------------------------------------------------
  60. // I'm disable various parts of MOSERT so that I can use it from within this test
  61. // program.
  62. // --------------------------------------------------------------------------------
  63. #define MSOERT_NO_PROTSTOR
  64. #define MSOERT_NO_BYTESTM
  65. #define MSOERT_NO_STRPARSE
  66. #define MSOERT_NO_ENUMFMT
  67. #define MSOERT_NO_CLOGFILE
  68. #define MSOERT_NO_DATAOBJ
  69. // --------------------------------------------------------------------------------
  70. // I know you don't have this, but you can if you want it. This header has a bunch
  71. // of slick macros. I will try not to use too many of them.
  72. // --------------------------------------------------------------------------------
  73. #include "d:\\athena\\inc\\msoert.h"
  74. // --------------------------------------------------------------------------------
  75. // Test function Prototypes
  76. // --------------------------------------------------------------------------------
  77. HRESULT MimeTestAppendRfc822(IMimeMessage **ppMessage);
  78. HRESULT MimeTestSettingContentLocation(IMimeMessage **ppMessage);
  79. HRESULT MimeTestGetMultiValueAddressProp(IMimeMessage **ppMessage);
  80. HRESULT MimeTestLookupCharsetHandle(LPCSTR pszCharset, LPHCHARSET phCharset);
  81. HRESULT MimeTestSettingReplyTo(IMimeMessage **ppMessage);
  82. HRESULT MimeTestSplitMessageIntoParts(void);
  83. HRESULT MimeTestRecombineMessageParts(LPWSTR *prgpszFile, ULONG cFiles);
  84. HRESULT MimeTestIsContentType(IMimeMessage **ppMessage);
  85. HRESULT MimeTestBodyStream(IMimeMessage **ppMessage);
  86. HRESULT MimeTestDeleteBody(IMimeMessage **ppMessage);
  87. HRESULT MimeTestEnumHeaderTable(IMimeMessage **ppMessage);
  88. HRESULT MimeTestCDO(IMimeMessage **ppMessage);
  89. // --------------------------------------------------------------------------------
  90. // Utility functions used by mimetest
  91. // --------------------------------------------------------------------------------
  92. HRESULT DumpStreamToConsole(IStream *pStream);
  93. HRESULT ReportError(LPCSTR pszFunction, INT nLine, LPCSTR pszErrorText, HRESULT hrResult);
  94. HRESULT ReportStatus(LPCSTR pszStatusText);
  95. HRESULT CreateMimeMessage(IMimeMessage **ppMessage);
  96. HRESULT SaveMimeMessage(IMimeMessage *pMessage, MIMESAVETYPE savetype, IStream **ppStream);
  97. // --------------------------------------------------------------------------------
  98. // Testing Switches
  99. // --------------------------------------------------------------------------------
  100. // #define TEST_MimeTestAppendRfc822
  101. // #define TEST_MimeTestSettingContentLocation
  102. // #define TEST_MimeTestGetMultiValueAddressProp
  103. // #define TEST_MimeTestSettingReplyTo
  104. // #define TEST_MimeTestSplitMessageIntoParts
  105. // #define TEST_MimeTestIsContentType
  106. // #define TEST_MimeTestBodyStream
  107. // #define TEST_MimeTestDeleteBody
  108. // #define TEST_MimeTestEnumHeaderTable
  109. #define TEST_MimeTestCDO
  110. // --------------------------------------------------------------------------------
  111. // MimeTest Entry Point
  112. // --------------------------------------------------------------------------------
  113. void __cdecl main(int argc, char *argv[])
  114. {
  115. // Locals
  116. HRESULT hr;
  117. IMimeMessage *pMessage=NULL;
  118. // You must always call this if you are going to use COM
  119. hr = CoInitialize(NULL);
  120. if (FAILED(hr))
  121. {
  122. ReportError("main", __LINE__, "CoInitialize failed.", hr);
  123. exit(1);
  124. }
  125. IDatabaseTable *pTable;
  126. HROWSET hRowset;
  127. MESSAGEINFO Message;
  128. CoCreateInstance(CLSID_DatabaseTable, NULL, CLSCTX_INPROC_SERVER, IID_IDatabaseTable, (LPVOID *)&pTable);
  129. pTable->Open("d:\\store\\00000004.dbx", 0, &g_MessageTableSchema, NULL);
  130. pTable->CreateRowset(IINDEX_SUBJECT, 0, &hRowset);
  131. while (S_OK == pTable->QueryRowset(hRowset, 1, (LPVOID *)&Message, NULL))
  132. {
  133. printf("%08d: %s\n", Message.idMessage, Message.pszSubject);
  134. pTable->FreeRecord(&Message);
  135. }
  136. pTable->CloseRowset(&hRowset);
  137. pTable->Release();
  138. exit(1);
  139. // ----------------------------------------------------------------------------
  140. // TEST_MimeTestCDO
  141. // ----------------------------------------------------------------------------
  142. #ifdef TEST_MimeTestCDO
  143. MimeTestCDO(NULL);
  144. #endif
  145. // ----------------------------------------------------------------------------
  146. // TEST_MimeTestEnumHeaderTable
  147. // ----------------------------------------------------------------------------
  148. #ifdef TEST_MimeTestEnumHeaderTable
  149. hr = MimeTestEnumHeaderTable(NULL);
  150. if (FAILED(hr))
  151. {
  152. ReportError("main", __LINE__, "MimeTestEnumHeaderTable failed.", hr);
  153. goto exit;
  154. }
  155. #endif
  156. // ----------------------------------------------------------------------------
  157. // TEST_MimeTestDeleteBody
  158. // ----------------------------------------------------------------------------
  159. #ifdef TEST_MimeTestDeleteBody
  160. hr = MimeTestDeleteBody(NULL);
  161. if (FAILED(hr))
  162. {
  163. ReportError("main", __LINE__, "MimeTestDeleteBody failed.", hr);
  164. goto exit;
  165. }
  166. #endif
  167. // ----------------------------------------------------------------------------
  168. // TEST_MimeTestBodyStream
  169. // ----------------------------------------------------------------------------
  170. #ifdef TEST_MimeTestBodyStream
  171. hr = MimeTestBodyStream(NULL);
  172. if (FAILED(hr))
  173. {
  174. ReportError("main", __LINE__, "MimeTestBodyStream failed.", hr);
  175. goto exit;
  176. }
  177. #endif
  178. // ----------------------------------------------------------------------------
  179. // TEST_MimeTestIsContentType
  180. // ----------------------------------------------------------------------------
  181. #ifdef TEST_MimeTestIsContentType
  182. hr = MimeTestIsContentType(NULL);
  183. if (FAILED(hr))
  184. {
  185. ReportError("main", __LINE__, "MimeTestIsContentType failed.", hr);
  186. goto exit;
  187. }
  188. #endif
  189. // ----------------------------------------------------------------------------
  190. // TEST_MimeTestAppendRfc822
  191. // ----------------------------------------------------------------------------
  192. #ifdef TEST_MimeTestAppendRfc822
  193. hr = MimeTestAppendRfc822(NULL);
  194. if (FAILED(hr))
  195. {
  196. ReportError("main", __LINE__, "MimeTestAppendRfc822 failed.", hr);
  197. goto exit;
  198. }
  199. #endif
  200. // ----------------------------------------------------------------------------
  201. // TEST_MimeTestGetMultiValueAddressProp
  202. // ----------------------------------------------------------------------------
  203. #ifdef TEST_MimeTestGetMultiValueAddressProp
  204. hr = MimeTestGetMultiValueAddressProp(NULL);
  205. if (FAILED(hr))
  206. {
  207. ReportError("main", __LINE__, "MimeTestAppendRfc822 failed.", hr);
  208. goto exit;
  209. }
  210. #endif
  211. // ----------------------------------------------------------------------------
  212. // TEST_MimeTestSettingContentLocation
  213. // ----------------------------------------------------------------------------
  214. #ifdef TEST_MimeTestSettingContentLocation
  215. hr = MimeTestSettingContentLocation(NULL);
  216. if (FAILED(hr))
  217. {
  218. ReportError("main", __LINE__, "MimeTestSettingContentLocation failed.", hr);
  219. goto exit;
  220. }
  221. #endif
  222. // ----------------------------------------------------------------------------
  223. // TEST_MimeTestSettingReplyTo
  224. // ----------------------------------------------------------------------------
  225. #ifdef TEST_MimeTestSettingReplyTo
  226. hr = MimeTestSettingReplyTo(NULL);
  227. if (FAILED(hr))
  228. {
  229. ReportError("main", __LINE__, "MimeTestSettingReplyTo failed.", hr);
  230. goto exit;
  231. }
  232. #endif
  233. // ----------------------------------------------------------------------------
  234. // TEST_MimeTestSplitMessageIntoParts
  235. // ----------------------------------------------------------------------------
  236. #ifdef TEST_MimeTestSplitMessageIntoParts
  237. hr = MimeTestSplitMessageIntoParts();
  238. if (FAILED(hr))
  239. {
  240. ReportError("main", __LINE__, "MimeTestSplitMessageIntoParts failed.", hr);
  241. goto exit;
  242. }
  243. #endif
  244. exit:
  245. // Cleanup
  246. if (pMessage)
  247. pMessage->Release();
  248. // I called CoInitialize, so lets call this...
  249. CoUninitialize();
  250. // Done
  251. exit(1);
  252. }
  253. // --------------------------------------------------------------------------------
  254. // MimeTestCDO
  255. // --------------------------------------------------------------------------------
  256. //#define RAID_17675
  257. #define RAID_20406
  258. //#define RAID_29961
  259. HRESULT MimeTestCDO(IMimeMessage **ppMessage)
  260. {
  261. // Locals
  262. HRESULT hr=S_OK;
  263. IMimeMessage *pMessage=NULL;
  264. IPersistFile *pPersistFile=NULL;
  265. PROPVARIANT Variant;
  266. LPSTR psz;
  267. FINDBODY FindBody={0};
  268. HBODY hBody;
  269. HCHARSET hCharset;
  270. IMimeBody *pBody=NULL;
  271. IMimeInternational *pInternat=NULL;
  272. // Create a message object
  273. hr = CreateMimeMessage(&pMessage);
  274. if (FAILED(hr))
  275. goto exit;
  276. #ifdef RAID_29961
  277. hr = CoCreateInstance(CLSID_IMimeInternational, NULL, CLSCTX_INPROC_SERVER, IID_IMimeInternational, (LPVOID *)&pInternat);
  278. if (FAILED(hr))
  279. goto exit;
  280. hr = pMessage->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile);
  281. if (FAILED(hr))
  282. goto exit;
  283. hr = pPersistFile->Load(L"j:\\test\\raid29961.eml", STGM_READ | STGM_SHARE_DENY_NONE);
  284. if (FAILED(hr))
  285. goto exit;
  286. FindBody.pszPriType = "text";
  287. FindBody.pszSubType = "plain";
  288. hr = pMessage->FindFirst(&FindBody, &hBody);
  289. if (FAILED(hr))
  290. goto exit;
  291. hr = pMessage->BindToObject(hBody, IID_IMimeBody, (LPVOID *)&pBody);
  292. if (FAILED(hr))
  293. goto exit;
  294. hr = pInternat->FindCharset("iso-8859-7", &hCharset);
  295. if (FAILED(hr))
  296. goto exit;
  297. hr = pBody->SetCharset(hCharset, CSET_APPLY_ALL);
  298. if (FAILED(hr))
  299. goto exit;
  300. pBody->Release();
  301. pBody = NULL;
  302. hr = pMessage->FindNext(&FindBody, &hBody);
  303. if (FAILED(hr))
  304. goto exit;
  305. hr = pMessage->BindToObject(hBody, IID_IMimeBody, (LPVOID *)&pBody);
  306. if (FAILED(hr))
  307. goto exit;
  308. hr = pInternat->FindCharset("iso-8859-4", &hCharset);
  309. if (FAILED(hr))
  310. goto exit;
  311. hr = pBody->SetCharset(hCharset, CSET_APPLY_ALL);
  312. if (FAILED(hr))
  313. goto exit;
  314. pBody->Release();
  315. pBody = NULL;
  316. hr = pInternat->FindCharset("iso-8859-3", &hCharset);
  317. if (FAILED(hr))
  318. goto exit;
  319. hr = pMessage->SetCharset(hCharset, CSET_APPLY_UNTAGGED);
  320. if (FAILED(hr))
  321. goto exit;
  322. hr = pPersistFile->Save(L"j:\\test\\raid29961_saved.eml", FALSE);
  323. if (FAILED(hr))
  324. goto exit;
  325. #endif
  326. #ifdef RAID_17675
  327. // Get an IPersistFile
  328. hr = pMessage->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile);
  329. if (FAILED(hr))
  330. goto exit;
  331. // Load
  332. hr = pPersistFile->Load(L"c:\\test\\cdo.eml", STGM_READ | STGM_SHARE_DENY_NONE);
  333. if (FAILED(hr))
  334. goto exit;
  335. ZeroMemory(&Variant, sizeof(PROPVARIANT));
  336. Variant.vt = VT_EMPTY;
  337. hr = pMessage->SetProp("par:content-type:charset", 0, &Variant);
  338. // if (FAILED(hr))
  339. // goto exit;
  340. Variant.vt = VT_LPSTR;
  341. hr = pMessage->GetProp("par:content-type:charset", 0, &Variant);
  342. if (FAILED(hr))
  343. goto exit;
  344. #endif // RAID_17675
  345. #ifdef RAID_20406
  346. // Get an IPersistFile
  347. hr = pMessage->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile);
  348. if (FAILED(hr))
  349. goto exit;
  350. // Load
  351. hr = pPersistFile->Load(L"c:\\test\\address.eml", STGM_READ | STGM_SHARE_DENY_NONE);
  352. if (FAILED(hr))
  353. goto exit;
  354. pMessage->GetAddressFormat(IAT_TO, AFT_DISPLAY_FRIENDLY, &psz);
  355. printf("AFT_DISPLAY_FRIENDLY: %s\n", psz);
  356. CoTaskMemFree(psz);
  357. pMessage->GetAddressFormat(IAT_TO, AFT_DISPLAY_EMAIL, &psz);
  358. printf("AFT_DISPLAY_EMAIL: %s\n", psz);
  359. CoTaskMemFree(psz);
  360. pMessage->GetAddressFormat(IAT_TO, AFT_DISPLAY_BOTH, &psz);
  361. printf("AFT_DISPLAY_BOTH: %s\n", psz);
  362. CoTaskMemFree(psz);
  363. pMessage->GetAddressFormat(IAT_TO, AFT_RFC822_DECODED, &psz);
  364. printf("AFT_RFC822_DECODED: %s\n", psz);
  365. CoTaskMemFree(psz);
  366. pMessage->GetAddressFormat(IAT_TO, AFT_RFC822_ENCODED, &psz);
  367. printf("AFT_RFC822_ENCODED: %s\n", psz);
  368. CoTaskMemFree(psz);
  369. pMessage->GetAddressFormat(IAT_TO, AFT_RFC822_TRANSMIT, &psz);
  370. printf("AFT_RFC822_TRANSMIT: %s\n", psz);
  371. CoTaskMemFree(psz);
  372. #endif // RAID_20406
  373. exit:
  374. // Cleanup
  375. if (pMessage)
  376. pMessage->Release();
  377. if (pPersistFile)
  378. pPersistFile->Release();
  379. if (pInternat)
  380. pInternat->Release();
  381. // Done
  382. return(hr);
  383. }
  384. // --------------------------------------------------------------------------------
  385. // MimeTestEnumHeaderTable
  386. // --------------------------------------------------------------------------------
  387. HRESULT MimeTestEnumHeaderTable(IMimeMessage **ppMessage)
  388. {
  389. // Locals
  390. HRESULT hr=S_OK;
  391. IMimeMessage *pMessage=NULL;
  392. IPersistFile *pPersistFile=NULL;
  393. IMimeHeaderTable *pTable=NULL;
  394. IMimeEnumHeaderRows *pEnum=NULL;
  395. ENUMHEADERROW Row;
  396. // Create a message object
  397. hr = CreateMimeMessage(&pMessage);
  398. if (FAILED(hr))
  399. {
  400. ReportError("MimeTestEnumHeaderTable", __LINE__, "CreateMimeMessage failed.", hr);
  401. goto exit;
  402. }
  403. // Get an IPersistFile
  404. hr = pMessage->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile);
  405. if (FAILED(hr))
  406. {
  407. ReportError("MimeTestEnumHeaderTable", __LINE__, "IMimeMessage::QueryInterface(IID_IPersistFile) failed.", hr);
  408. goto exit;
  409. }
  410. // Load
  411. hr = pPersistFile->Load(L"c:\\test\\multiadd.eml", STGM_READ | STGM_SHARE_DENY_NONE);
  412. if (FAILED(hr))
  413. {
  414. ReportError("MimeTestEnumHeaderTable", __LINE__, "IPersistFile::Load failed.", hr);
  415. goto exit;
  416. }
  417. // Get Enumerator
  418. hr = pMessage->BindToObject(HBODY_ROOT, IID_IMimeHeaderTable, (LPVOID *)&pTable);
  419. if (FAILED(hr))
  420. {
  421. ReportError("MimeTestEnumHeaderTable", __LINE__, "pMessage->BindToObject(HBODY_ROOT, IID_IMimeHeaderTable, ...) failed.", hr);
  422. goto exit;
  423. }
  424. // EnumRows
  425. hr = pTable->EnumRows(NULL, 0, &pEnum);
  426. if (FAILED(hr))
  427. {
  428. ReportError("MimeTestEnumHeaderTable", __LINE__, "pTable->EnumRows failed.", hr);
  429. goto exit;
  430. }
  431. // Loop
  432. while (S_OK == pEnum->Next(1, &Row, NULL))
  433. {
  434. printf("%s: %s\n", Row.pszHeader, Row.pszData);
  435. CoTaskMemFree(Row.pszHeader);
  436. CoTaskMemFree(Row.pszData);
  437. }
  438. // Return a message object
  439. if (ppMessage)
  440. {
  441. (*ppMessage) = pMessage;
  442. (*ppMessage)->AddRef();
  443. }
  444. exit:
  445. // Cleanup
  446. if (pPersistFile)
  447. pPersistFile->Release();
  448. if (pMessage)
  449. pMessage->Release();
  450. if (pTable)
  451. pTable->Release();
  452. if (pEnum)
  453. pEnum->Release();
  454. // Done
  455. return hr;
  456. }
  457. // --------------------------------------------------------------------------------
  458. // MimeTestDeleteBody
  459. // --------------------------------------------------------------------------------
  460. HRESULT MimeTestDeleteBody(IMimeMessage **ppMessage)
  461. {
  462. // Locals
  463. HRESULT hr=S_OK;
  464. IMimeMessage *pMessage=NULL;
  465. IPersistFile *pPersistFile=NULL;
  466. HBODY hBody;
  467. // Create a message object
  468. hr = CreateMimeMessage(&pMessage);
  469. if (FAILED(hr))
  470. {
  471. ReportError("MimeTestDeleteBody", __LINE__, "CreateMimeMessage failed.", hr);
  472. goto exit;
  473. }
  474. // Get an IPersistFile
  475. hr = pMessage->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile);
  476. if (FAILED(hr))
  477. {
  478. ReportError("MimeTestDeleteBody", __LINE__, "IMimeMessage::QueryInterface(IID_IPersistFile) failed.", hr);
  479. goto exit;
  480. }
  481. // Load
  482. hr = pPersistFile->Load(L"d:\\test\\delbody.eml", STGM_READ | STGM_SHARE_DENY_NONE);
  483. if (FAILED(hr))
  484. {
  485. ReportError("MimeTestDeleteBody", __LINE__, "IPersistFile::Load failed.", hr);
  486. goto exit;
  487. }
  488. // Load
  489. hr = pPersistFile->Load(L"d:\\test\\delbody.eml", STGM_READ | STGM_SHARE_DENY_NONE);
  490. if (FAILED(hr))
  491. {
  492. ReportError("MimeTestDeleteBody", __LINE__, "IPersistFile::Load failed.", hr);
  493. goto exit;
  494. }
  495. goto exit;
  496. // Get the root body
  497. hr = pMessage->GetBody(IBL_ROOT, NULL, &hBody);
  498. if (FAILED(hr))
  499. {
  500. ReportError("MimeTestDeleteBody", __LINE__, "pMessage->GetBody failed.", hr);
  501. goto exit;
  502. }
  503. // Get the root body
  504. hr = pMessage->GetBody(IBL_FIRST, hBody, &hBody);
  505. if (FAILED(hr))
  506. {
  507. ReportError("MimeTestDeleteBody", __LINE__, "pMessage->GetBody failed.", hr);
  508. goto exit;
  509. }
  510. // Delete the Root
  511. hr = pMessage->DeleteBody(hBody, DELETE_PROMOTE_CHILDREN);
  512. if (FAILED(hr))
  513. {
  514. ReportError("MimeTestDeleteBody", __LINE__, "pMessage->DeleteBody failed.", hr);
  515. goto exit;
  516. }
  517. // Get the root body
  518. hr = pMessage->GetBody(IBL_ROOT, NULL, &hBody);
  519. if (FAILED(hr))
  520. {
  521. ReportError("MimeTestDeleteBody", __LINE__, "pMessage->GetBody failed.", hr);
  522. goto exit;
  523. }
  524. // Delete the Root
  525. hr = pMessage->DeleteBody(hBody, 0);
  526. if (FAILED(hr))
  527. {
  528. ReportError("MimeTestDeleteBody", __LINE__, "pMessage->DeleteBody failed.", hr);
  529. goto exit;
  530. }
  531. // Return a message object
  532. if (ppMessage)
  533. {
  534. (*ppMessage) = pMessage;
  535. (*ppMessage)->AddRef();
  536. }
  537. exit:
  538. // Cleanup
  539. if (pPersistFile)
  540. pPersistFile->Release();
  541. if (pMessage)
  542. pMessage->Release();
  543. // Done
  544. return hr;
  545. }
  546. // --------------------------------------------------------------------------------
  547. // MimeTestBodyStream
  548. // --------------------------------------------------------------------------------
  549. #if 0
  550. HRESULT MimeTestBodyStream(IMimeMessage **ppMessage)
  551. {
  552. // Locals
  553. HRESULT hr=S_OK;
  554. IMimeMessage *pMessage=NULL;
  555. IStream *pStmSave=NULL;
  556. IStream *pStmBody=NULL;
  557. IStream *pStmText=NULL;
  558. IStream *pStmTxtOut=NULL;
  559. IMimeBody *pBody=NULL;
  560. PROPVARIANT rVariant;
  561. IWaveAudio *pWave=NULL;
  562. IWaveStream *pStmWave=NULL;
  563. DWORD cAttach;
  564. HBODY hBody;
  565. HBODY *prghAttach=NULL;
  566. DWORD cb;
  567. DWORD dw;
  568. // Create a message object
  569. hr = CreateMimeMessage(&pMessage);
  570. if (FAILED(hr))
  571. {
  572. ReportError("MimeTestBodyStream", __LINE__, "CreateMimeMessage failed.", hr);
  573. goto exit;
  574. }
  575. // Create a stream in which to save the message...
  576. hr = CreateStreamOnHGlobal(NULL, TRUE, &pStmText);
  577. if (FAILED(hr))
  578. {
  579. ReportError("MimeTestBodyStream", __LINE__, "CreateStreamOnHGlobal failed", hr);
  580. goto exit;
  581. }
  582. // Write some text into pStmText
  583. hr = pStmText->Write("Testing BodyStream.", lstrlen("Testing BodyStream."), NULL);
  584. if (FAILED(hr))
  585. {
  586. ReportError("MimeTestBodyStream", __LINE__, "pStmText->Write failed", hr);
  587. goto exit;
  588. }
  589. // Commit
  590. pStmText->Commit(STGC_DEFAULT);
  591. // Rewind it
  592. HrRewindStream(pStmText);
  593. // Set the text body
  594. hr = pMessage->SetTextBody(TXT_PLAIN, IET_BINARY, NULL, pStmText, NULL);
  595. if (FAILED(hr))
  596. {
  597. ReportError("MimeTestBodyStream", __LINE__, "pMessage->SetTextBody failed", hr);
  598. goto exit;
  599. }
  600. // Attach a file
  601. hr = pMessage->AttachFile("d:\\waveedit\\test.wav", NULL, NULL);
  602. if (FAILED(hr))
  603. {
  604. ReportError("MimeTestBodyStream", __LINE__, "IMimeMessage::AttachFile failed.", hr);
  605. goto exit;
  606. }
  607. // Save that bad boy to a stream
  608. hr = CreateTempFileStream(&pStmSave);
  609. if (FAILED(hr))
  610. {
  611. ReportError("MimeTestBodyStream", __LINE__, "CreateTempFileStream failed.", hr);
  612. goto exit;
  613. }
  614. // Save the message
  615. hr = pMessage->Save(pStmSave, TRUE);
  616. if (FAILED(hr))
  617. {
  618. ReportError("MimeTestBodyStream", __LINE__, "pMessage->Save failed.", hr);
  619. goto exit;
  620. }
  621. // Commit
  622. pStmSave->Commit(STGC_DEFAULT);
  623. // Release pMessage
  624. pMessage->Release();
  625. pMessage = NULL;
  626. // Rewind pStmSave
  627. HrRewindStream(pStmSave);
  628. // Create a new message object
  629. hr = CreateMimeMessage(&pMessage);
  630. if (FAILED(hr))
  631. {
  632. ReportError("MimeTestBodyStream", __LINE__, "CreateMimeMessage failed.", hr);
  633. goto exit;
  634. }
  635. // Load that message object
  636. hr = pMessage->Load(pStmSave);
  637. if (FAILED(hr))
  638. {
  639. ReportError("MimeTestBodyStream", __LINE__, "IMimeMessage::Load failed.", hr);
  640. goto exit;
  641. }
  642. // Get the text body
  643. hr = pMessage->GetTextBody(TXT_PLAIN, IET_BINARY, &pStmTxtOut, &hBody);
  644. if (FAILED(hr))
  645. {
  646. ReportError("MimeTestBodyStream", __LINE__, "pMessage->GetTextBody failed.", hr);
  647. goto exit;
  648. }
  649. // Get the attachment, should be the wave file
  650. hr = pMessage->GetAttachments(&cAttach, &prghAttach);
  651. if (FAILED(hr))
  652. {
  653. ReportError("MimeTestBodyStream", __LINE__, "pMessage->GetAttachments failed.", hr);
  654. goto exit;
  655. }
  656. // Get the root body
  657. hr = pMessage->BindToObject(prghAttach[0], IID_IMimeBody, (LPVOID *)&pBody);
  658. if (FAILED(hr))
  659. {
  660. ReportError("MimeTestBodyStream", __LINE__, "IMimeMessage::BindToObject failed.", hr);
  661. goto exit;
  662. }
  663. // Get the data stream
  664. hr = pBody->SaveToFile(IET_BINARY, "d:\\waveedit\\test.new");
  665. if (FAILED(hr))
  666. {
  667. ReportError("MimeTestBodyStream", __LINE__, "IMimeBody::GetData failed.", hr);
  668. goto exit;
  669. }
  670. // Get the data stream
  671. hr = pBody->GetData(IET_BINARY, &pStmBody);
  672. if (FAILED(hr))
  673. {
  674. ReportError("MimeTestBodyStream", __LINE__, "IMimeBody::GetData failed.", hr);
  675. goto exit;
  676. }
  677. // Feed this into waveedit
  678. #if 0
  679. hr = CreateWaveEditObject(IID_IWaveAudio, (LPVOID *)&pWave);
  680. if (FAILED(hr))
  681. {
  682. ReportError("MimeTestBodyStream", __LINE__, "CreateWaveEditObject failed.", hr);
  683. goto exit;
  684. }
  685. // Get pStmWave
  686. hr = pWave->QueryInterface(IID_IWaveStream, (LPVOID *)&pStmWave);
  687. if (FAILED(hr))
  688. {
  689. ReportError("MimeTestBodyStream", __LINE__, "pWave->QueryInterface(IID_IWaveStream...) failed.", hr);
  690. goto exit;
  691. }
  692. // Open the stream
  693. hr = pStmWave->StreamOpen(pStmBody);
  694. if (FAILED(hr))
  695. {
  696. ReportError("MimeTestBodyStream", __LINE__, "pStmWave->StreamOpen failed.", hr);
  697. goto exit;
  698. }
  699. pWave->GetNumSamples(&dw);
  700. // Play it
  701. hr = pWave->Play(WAVE_MAPPER, 0, dw);
  702. if (FAILED(hr))
  703. {
  704. ReportError("MimeTestBodyStream", __LINE__, "pStmWave->Play failed.", hr);
  705. goto exit;
  706. }
  707. #endif
  708. Sleep(8000);
  709. exit:
  710. // Cleanup
  711. if (pMessage)
  712. pMessage->Release();
  713. if (pBody)
  714. pBody->Release();
  715. if (pStmBody)
  716. pStmBody->Release();
  717. if (pStmSave)
  718. pStmSave->Release();
  719. if (pWave)
  720. pWave->Release();
  721. if (pStmWave)
  722. pStmWave->Release();
  723. if (pStmText)
  724. pStmText->Release();
  725. if (pStmTxtOut)
  726. pStmTxtOut->Release();
  727. if (prghAttach)
  728. CoTaskMemFree(prghAttach);
  729. // Done
  730. return hr;
  731. }
  732. #endif
  733. // --------------------------------------------------------------------------------
  734. // MimeTestIsContentType
  735. // --------------------------------------------------------------------------------
  736. HRESULT MimeTestIsContentType(IMimeMessage **ppMessage)
  737. {
  738. // Locals
  739. HRESULT hr=S_OK;
  740. IMimeMessage *pMessage=NULL;
  741. IPersistFile *pPersistFile=NULL;
  742. HBODY hBody;
  743. // Create a message object
  744. hr = CreateMimeMessage(&pMessage);
  745. if (FAILED(hr))
  746. {
  747. ReportError("MimeTestIsContentType", __LINE__, "CreateMimeMessage failed.", hr);
  748. goto exit;
  749. }
  750. // Get an IPersistFile
  751. hr = pMessage->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile);
  752. if (FAILED(hr))
  753. {
  754. ReportError("MimeTestIsContentType", __LINE__, "IMimeMessage::QueryInterface(IID_IPersistFile) failed.", hr);
  755. goto exit;
  756. }
  757. // Load
  758. hr = pPersistFile->Load(L"d:\\test\\vlad.eml", STGM_READ | STGM_SHARE_DENY_NONE);
  759. if (FAILED(hr))
  760. {
  761. ReportError("MimeTestIsContentType", __LINE__, "IPersistFile::Load failed.", hr);
  762. goto exit;
  763. }
  764. // Get the root body
  765. hr = pMessage->GetBody(IBL_ROOT, NULL, &hBody);
  766. // Test for content-Type
  767. hr = pMessage->IsContentType(hBody, "multipart", NULL);
  768. if (S_OK == hr)
  769. printf("The root body of the message is a multipart.");
  770. else if (S_FALSE == hr)
  771. printf("The root body of the message is NOT a multipart.");
  772. // Return a message object
  773. if (ppMessage)
  774. {
  775. (*ppMessage) = pMessage;
  776. (*ppMessage)->AddRef();
  777. }
  778. exit:
  779. // Cleanup
  780. if (pPersistFile)
  781. pPersistFile->Release();
  782. if (pMessage)
  783. pMessage->Release();
  784. // Done
  785. return hr;
  786. }
  787. // --------------------------------------------------------------------------------
  788. // MimeTestSplitMessageIntoParts - How to split a large message into smaller parts
  789. // --------------------------------------------------------------------------------
  790. HRESULT MimeTestSplitMessageIntoParts(void)
  791. {
  792. // Locals
  793. HRESULT hr=S_OK;
  794. IMimeMessageParts *pParts=NULL;
  795. IMimeEnumMessageParts *pEnumParts=NULL;
  796. IMimeMessage *pMessage=NULL;
  797. IMimeMessage *pMsgPart=NULL;
  798. IStream *pStream=NULL;
  799. IPersistFile *pPersistFile=NULL;
  800. ULONG c;
  801. ULONG cFiles=0;
  802. ULONG i;
  803. LPWSTR *prgpszFile=NULL;
  804. PROPVARIANT rVariant;
  805. // Init the variant
  806. ZeroMemory(&rVariant, sizeof(PROPVARIANT));
  807. // Create a message object
  808. hr = CreateMimeMessage(&pMessage);
  809. if (FAILED(hr))
  810. {
  811. ReportError("MimeTestSplitMessageIntoParts", __LINE__, "CreateMimeMessage failed.", hr);
  812. goto exit;
  813. }
  814. // Attach a large file
  815. hr = pMessage->AttachFile("c:\\winnt\\winnt256.bmp", NULL, NULL);
  816. if (FAILED(hr))
  817. {
  818. ReportError("MimeTestSplitMessageIntoParts", __LINE__, "IMimeMessage::AttachFile(...) failed.", hr);
  819. goto exit;
  820. }
  821. // Split the message into parts
  822. hr = pMessage->SplitMessage(65536, &pParts);
  823. if (FAILED(hr))
  824. {
  825. ReportError("MimeTestSplitMessageIntoParts", __LINE__, "IMimeMessage::SplitMessage(...) failed.", hr);
  826. goto exit;
  827. }
  828. // Get the number of parts
  829. hr = pParts->CountParts(&cFiles);
  830. if (FAILED(hr))
  831. {
  832. ReportError("MimeTestSplitMessageIntoParts", __LINE__, "IMimeMessageParts::EnumParts(...) failed.", hr);
  833. goto exit;
  834. }
  835. // Allocate an array
  836. prgpszFile = (LPWSTR *)CoTaskMemAlloc(sizeof(LPWSTR) * cFiles);
  837. if (NULL == prgpszFile)
  838. {
  839. ReportError("MimeTestSplitMessageIntoParts", __LINE__, "CoTaskMemAlloc Failed.", hr);
  840. goto exit;
  841. }
  842. // Init
  843. ZeroMemory(prgpszFile, sizeof(LPWSTR) * cFiles);
  844. // Enumerate the parts
  845. hr = pParts->EnumParts(&pEnumParts);
  846. if (FAILED(hr))
  847. {
  848. ReportError("MimeTestSplitMessageIntoParts", __LINE__, "IMimeMessageParts::EnumParts(...) failed.", hr);
  849. goto exit;
  850. }
  851. // INit loop var
  852. i = 0;
  853. // Enumerate the parts
  854. while (SUCCEEDED(pEnumParts->Next(1, &pMsgPart, &c)) && 1 == c)
  855. {
  856. // Setup the variant
  857. rVariant.vt = VT_LPWSTR;
  858. // Get a filename, in unicode
  859. hr = pMsgPart->GetBodyProp(HBODY_ROOT, PIDTOSTR(PID_ATT_GENFNAME), 0, &rVariant);
  860. if (FAILED(hr))
  861. {
  862. ReportError("MimeTestSplitMessageIntoParts", __LINE__, "IMimeMessage::GetBodyProp(HBODY_ROOT, PID_ATT_GENFNAME (Unicode), ...) failed.", hr);
  863. goto exit;
  864. }
  865. // QI for IPersistFile
  866. hr = pMsgPart->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile);
  867. if (FAILED(hr))
  868. {
  869. ReportError("MimeTestSplitMessageIntoParts", __LINE__, "IMimeMessage::QueryInterface(IID_IPersistFile, ...) failed.", hr);
  870. goto exit;
  871. }
  872. // Get the message source and dump to file...
  873. hr = pPersistFile->Save(rVariant.pwszVal, FALSE);
  874. if (FAILED(hr))
  875. {
  876. ReportError("MimeTestSplitMessageIntoParts", __LINE__, "IPersistFile::Save(...) failed.", hr);
  877. goto exit;
  878. }
  879. // Save the filename
  880. prgpszFile[i++] = rVariant.pwszVal;
  881. rVariant.pwszVal = NULL;
  882. // Release the message
  883. pMsgPart->Release();
  884. pMsgPart = NULL;
  885. pPersistFile->Release();
  886. pPersistFile = NULL;
  887. }
  888. // Lets recombine those message parts
  889. MimeTestRecombineMessageParts(prgpszFile, cFiles);
  890. exit:
  891. // Cleanup
  892. if (pStream)
  893. pStream->Release();
  894. if (pMessage)
  895. pMessage->Release();
  896. if (pParts)
  897. pParts->Release();
  898. if (pEnumParts)
  899. pEnumParts->Release();
  900. if (pMsgPart)
  901. pMsgPart->Release();
  902. if (pPersistFile)
  903. pPersistFile->Release();
  904. if (rVariant.pwszVal)
  905. CoTaskMemFree(rVariant.pwszVal);
  906. if (prgpszFile)
  907. {
  908. for (i=0; i<cFiles; i++)
  909. if (prgpszFile[i])
  910. CoTaskMemFree(prgpszFile[i]);
  911. CoTaskMemFree(prgpszFile);
  912. }
  913. // Done
  914. return hr;
  915. }
  916. // --------------------------------------------------------------------------------
  917. // MimeTestRecombineMessageParts
  918. // --------------------------------------------------------------------------------
  919. HRESULT MimeTestRecombineMessageParts(LPWSTR *prgpszFile, ULONG cFiles)
  920. {
  921. // Locals
  922. HRESULT hr=S_OK;
  923. ULONG i=0;
  924. IMimeMessageParts *pParts=NULL;
  925. IMimeMessage *pMsgPart=NULL;
  926. IMimeMessage *pMessage=NULL;
  927. IPersistFile *pPersistFile=NULL;
  928. // Create a message object
  929. hr = CoCreateInstance(CLSID_IMimeMessageParts, NULL, CLSCTX_INPROC_SERVER, IID_IMimeMessageParts, (LPVOID *)&pParts);
  930. if (FAILED(hr))
  931. {
  932. ReportError("MimeTestRecombineMessageParts", __LINE__, "CoCreateInstance(CLSID_IMimeMessageParts, ...) failed.", hr);
  933. goto exit;
  934. }
  935. // Loop through the files
  936. for (i=0; i<cFiles; i++)
  937. {
  938. // Create a mime message object
  939. hr = CreateMimeMessage(&pMsgPart);
  940. if (FAILED(hr))
  941. {
  942. ReportError("MimeTestRecombineMessageParts", __LINE__, "CreateMimeMessage failed.", hr);
  943. goto exit;
  944. }
  945. // Get an IPersistFile
  946. hr = pMsgPart->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile);
  947. if (FAILED(hr))
  948. {
  949. ReportError("MimeTestRecombineMessageParts", __LINE__, "IMimeMessage::QueryInterface(IID_IPersistFile, ...) failed.", hr);
  950. goto exit;
  951. }
  952. // Get the message source and dump to file...
  953. hr = pPersistFile->Load(prgpszFile[i], STGM_READ | STGM_SHARE_DENY_NONE);
  954. if (FAILED(hr))
  955. {
  956. ReportError("MimeTestRecombineMessageParts", __LINE__, "IPersistFile::Load(...) failed.", hr);
  957. goto exit;
  958. }
  959. // Add the message into the parts list
  960. hr = pParts->AddPart(pMsgPart);
  961. if (FAILED(hr))
  962. {
  963. ReportError("MimeTestRecombineMessageParts", __LINE__, "IMimeMessageParts::AddPart(...) failed.", hr);
  964. goto exit;
  965. }
  966. // Cleanup
  967. pMsgPart->Release();
  968. pMsgPart = NULL;
  969. pPersistFile->Release();
  970. pPersistFile = NULL;
  971. }
  972. // Combine all the parts into a new message
  973. hr = pParts->CombineParts(&pMessage);
  974. if (FAILED(hr))
  975. {
  976. ReportError("MimeTestRecombineMessageParts", __LINE__, "IMimeMessageParts::CombineParts(...) failed.", hr);
  977. goto exit;
  978. }
  979. // Get an IPersistFile
  980. hr = pMessage->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile);
  981. if (FAILED(hr))
  982. {
  983. ReportError("MimeTestRecombineMessageParts", __LINE__, "IMimeMessage::QueryInterface(IID_IPersistFile, ...) failed.", hr);
  984. goto exit;
  985. }
  986. // Get the message source and dump to file...
  987. hr = pPersistFile->Save(L"combined.eml", FALSE);
  988. if (FAILED(hr))
  989. {
  990. ReportError("MimeTestRecombineMessageParts", __LINE__, "IPersistFile::Save(...) failed.", hr);
  991. goto exit;
  992. }
  993. exit:
  994. // Cleanup
  995. if (pParts)
  996. pParts->Release();
  997. if (pMsgPart)
  998. pMsgPart->Release();
  999. if (pMessage)
  1000. pMessage->Release();
  1001. if (pPersistFile)
  1002. pPersistFile->Release();
  1003. // Done
  1004. return hr;
  1005. }
  1006. // --------------------------------------------------------------------------------
  1007. // MimeTestLookupCharsetHandle
  1008. // --------------------------------------------------------------------------------
  1009. HRESULT MimeTestLookupCharsetHandle(LPCSTR pszCharset, LPHCHARSET phCharset)
  1010. {
  1011. // Locals
  1012. HRESULT hr=S_OK;
  1013. INETCSETINFO rCharset;
  1014. IMimeInternational *pInternat=NULL;
  1015. // Create a message object
  1016. hr = CoCreateInstance(CLSID_IMimeInternational, NULL, CLSCTX_INPROC_SERVER, IID_IMimeInternational, (LPVOID *)&pInternat);
  1017. if (FAILED(hr))
  1018. {
  1019. ReportError("MimeTestLookupCharsetHandle", __LINE__, "CoCreateInstance(CLSID_IMimeInternational, ...) failed.", hr);
  1020. goto exit;
  1021. }
  1022. // Look for character set
  1023. hr = pInternat->FindCharset(pszCharset, phCharset);
  1024. if (FAILED(hr))
  1025. {
  1026. ReportError("MimeTestLookupCharsetHandle", __LINE__, "IMimeInternational::FindCharset(...) failed.", hr);
  1027. goto exit;
  1028. }
  1029. // Lets lookup some character set information
  1030. hr = pInternat->GetCharsetInfo(*phCharset, &rCharset);
  1031. if (FAILED(hr))
  1032. {
  1033. ReportError("MimeTestLookupCharsetHandle", __LINE__, "IMimeInternational::GetCharsetInfo(...) failed.", hr);
  1034. goto exit;
  1035. }
  1036. // Print some stuff
  1037. printf("Charset Name: %s, Windows Codepage: %d, Internet Codepage: %d\n", rCharset.szName, rCharset.cpiWindows, rCharset.cpiInternet);
  1038. exit:
  1039. // Clenaup
  1040. if (pInternat)
  1041. pInternat->Release();
  1042. // Done
  1043. return hr;
  1044. }
  1045. // --------------------------------------------------------------------------------
  1046. // MimeTestSettingContentLocation - How to set the Content-Location header
  1047. // --------------------------------------------------------------------------------
  1048. HRESULT MimeTestSettingContentLocation(IMimeMessage **ppMessage)
  1049. {
  1050. // Locals
  1051. HRESULT hr=S_OK;
  1052. IMimeMessage *pMessage=NULL;
  1053. IStream *pStream=NULL;
  1054. PROPVARIANT rVariant;
  1055. HCHARSET hCharset;
  1056. // Create a message object
  1057. hr = CreateMimeMessage(&pMessage);
  1058. if (FAILED(hr))
  1059. {
  1060. ReportError("MimeTestSettingContentLocation", __LINE__, "CreateMimeMessage failed.", hr);
  1061. goto exit;
  1062. }
  1063. // Setup a variant, I can pass in unicode or ansi
  1064. rVariant.vt = VT_LPWSTR;
  1065. rVariant.pwszVal = L"http://www.microsoft.com";
  1066. // Set the Content-Location of the message
  1067. hr = pMessage->SetProp(PIDTOSTR(PID_HDR_CNTLOC), 0, &rVariant);
  1068. if (FAILED(hr))
  1069. {
  1070. ReportError("MimeTestSettingContentLocation", __LINE__, "IMimeMessage::SetProp(PIDTOSTR(PID_HDR_CNTLOC), 0, ...) failed.", hr);
  1071. goto exit;
  1072. }
  1073. // Setup a variant, I can pass in unicode or ansi
  1074. rVariant.vt = VT_LPSTR;
  1075. rVariant.pszVal = "\"Ken Dacey\" <postmaster>";
  1076. // Set the Content-Location of the message
  1077. hr = pMessage->SetProp(PIDTOSTR(PID_HDR_FROM), 0, &rVariant);
  1078. if (FAILED(hr))
  1079. {
  1080. ReportError("MimeTestSettingContentLocation", __LINE__, "IMimeMessage::SetProp(PIDTOSTR(PID_HDR_FROM), 0, ...) failed.", hr);
  1081. goto exit;
  1082. }
  1083. // I could also set the content-location like this:
  1084. //
  1085. // 1) pMessage->SetBodyProp(HBODY_ROOT, PIDTOSTR(PID_HDR_CNTLOC), 0, &rVariant);
  1086. //
  1087. // 2) pMessage->BindToObject(HBODY_ROOT, IID_IMimePropertySet, (LPVOID *)&pProps);
  1088. // pProps->SetProp(PIDTOSTR(PID_HDR_CNTLOC), 0, &rVariant);
  1089. // Lets save the message in UTF-7
  1090. #if 0
  1091. hr = MimeTestLookupCharsetHandle("utf-8", &hCharset);
  1092. if (FAILED(hr))
  1093. {
  1094. ReportError("MimeTestSettingContentLocation", __LINE__, "MimeTestLookupCharsetHandle(\"utf-7\", ...) failed.", hr);
  1095. goto exit;
  1096. }
  1097. // Set the charset onto the message
  1098. hr = pMessage->SetCharset(hCharset, CSET_APPLY_ALL);
  1099. if (FAILED(hr))
  1100. {
  1101. ReportError("MimeTestSettingContentLocation", __LINE__, "IMimeMessage::SetCharset(\"utf-7\", CSET_APPLY_ALL) failed.", hr);
  1102. goto exit;
  1103. }
  1104. #endif
  1105. // Save the mime message to a stream
  1106. hr = SaveMimeMessage(pMessage, SAVE_RFC1521, &pStream);
  1107. if (FAILED(hr))
  1108. {
  1109. ReportError("MimeTestSettingContentLocation", __LINE__, "SaveMimeMessage(...) failed.", hr);
  1110. goto exit;
  1111. }
  1112. // Dump the stream to the console, and then wait for input so that the user can view it...
  1113. ReportStatus("\n");
  1114. DumpStreamToConsole(pStream);
  1115. // Return a message object
  1116. if (ppMessage)
  1117. {
  1118. (*ppMessage) = pMessage;
  1119. (*ppMessage)->AddRef();
  1120. }
  1121. exit:
  1122. // Cleanup
  1123. if (pStream)
  1124. pStream->Release();
  1125. if (pMessage)
  1126. pMessage->Release();
  1127. // Done
  1128. return hr;
  1129. }
  1130. // --------------------------------------------------------------------------------
  1131. // MimeTestSettingReplyTo - How to set the Reply-To header
  1132. // --------------------------------------------------------------------------------
  1133. HRESULT MimeTestSettingReplyTo(IMimeMessage **ppMessage)
  1134. {
  1135. // Locals
  1136. HRESULT hr=S_OK;
  1137. IMimeMessage *pMessage=NULL;
  1138. IStream *pStream=NULL;
  1139. PROPVARIANT rVariant;
  1140. // Create a message object
  1141. hr = CreateMimeMessage(&pMessage);
  1142. if (FAILED(hr))
  1143. {
  1144. ReportError("MimeTestSettingReplyTo", __LINE__, "CreateMimeMessage failed.", hr);
  1145. goto exit;
  1146. }
  1147. // Setup a variant, I can pass in unicode or ansi
  1148. rVariant.vt = VT_LPWSTR;
  1149. rVariant.pwszVal = L"Steven Bailey <[email protected]>";
  1150. // Set the Content-Location of the message
  1151. hr = pMessage->SetProp(PIDTOSTR(PID_HDR_REPLYTO), 0, &rVariant);
  1152. if (FAILED(hr))
  1153. {
  1154. ReportError("MimeTestSettingReplyTo", __LINE__, "IMimeMessage::SetProp(PIDTOSTR(PID_HDR_REPLYTO), 0, ...) failed.", hr);
  1155. goto exit;
  1156. }
  1157. // Save the mime message to a stream
  1158. hr = SaveMimeMessage(pMessage, SAVE_RFC1521, &pStream);
  1159. if (FAILED(hr))
  1160. {
  1161. ReportError("MimeTestSettingContentLocation", __LINE__, "SaveMimeMessage(...) failed.", hr);
  1162. goto exit;
  1163. }
  1164. // Dump the stream to the console, and then wait for input so that the user can view it...
  1165. ReportStatus("\n");
  1166. DumpStreamToConsole(pStream);
  1167. // Return a message object
  1168. if (ppMessage)
  1169. {
  1170. (*ppMessage) = pMessage;
  1171. (*ppMessage)->AddRef();
  1172. }
  1173. exit:
  1174. // Cleanup
  1175. if (pStream)
  1176. pStream->Release();
  1177. if (pMessage)
  1178. pMessage->Release();
  1179. // Done
  1180. return hr;
  1181. }
  1182. // --------------------------------------------------------------------------------
  1183. // MimeTestGetMultiValueAddressProp
  1184. // --------------------------------------------------------------------------------
  1185. HRESULT MimeTestGetMultiValueAddressProp(IMimeMessage **ppMessage)
  1186. {
  1187. // Locals
  1188. HRESULT hr=S_OK;
  1189. PROPVARIANT rVariant;
  1190. IMimeMessage *pMessage=NULL;
  1191. // Create a message with some addresses in it
  1192. hr = MimeTestAppendRfc822(&pMessage);
  1193. if (FAILED(hr))
  1194. {
  1195. ReportError("MimeTestGetMultiValueAddressProp", __LINE__, "MimeTestAppendRfc822 failed.", hr);
  1196. goto exit;
  1197. }
  1198. // Setup the Variant
  1199. rVariant.vt = VT_LPSTR;
  1200. // Get PID_HDR_TO
  1201. hr = pMessage->GetProp(PIDTOSTR(PID_HDR_TO), 0, &rVariant);
  1202. if (FAILED(hr))
  1203. {
  1204. ReportError("MimeTestGetMultiValueAddressProp", __LINE__, "IMimeMessage::GetProp(PIDTOSTR(PID_HDR_TO), ...) failed.", hr);
  1205. goto exit;
  1206. }
  1207. // Printf It
  1208. printf("PID_HDR_TO = %s\n", rVariant.pszVal);
  1209. // Free it
  1210. CoTaskMemFree(rVariant.pszVal);
  1211. exit:
  1212. // Cleanup
  1213. if (pMessage)
  1214. pMessage->Release();
  1215. // Done
  1216. return hr;
  1217. }
  1218. // --------------------------------------------------------------------------------
  1219. // MimeTestAppendRfc822 - Test IMimeAddressTable::AppendRfc822
  1220. // --------------------------------------------------------------------------------
  1221. HRESULT MimeTestAppendRfc822(IMimeMessage **ppMessage)
  1222. {
  1223. // Locals
  1224. HRESULT hr=S_OK;
  1225. IMimeMessage *pMessage=NULL;
  1226. IMimeAddressTable *pAdrTable=NULL;
  1227. IStream *pStream=NULL;
  1228. // Create a message object
  1229. hr = CreateMimeMessage(&pMessage);
  1230. if (FAILED(hr))
  1231. {
  1232. ReportError("MimeTestAppendRfc822", __LINE__, "CreateMimeMessage failed.", hr);
  1233. goto exit;
  1234. }
  1235. // Get the address table for the message. The address table should only be used on the root body object.
  1236. hr = pMessage->BindToObject(HBODY_ROOT, IID_IMimeAddressTable, (LPVOID *)&pAdrTable);
  1237. if (FAILED(hr))
  1238. {
  1239. ReportError("MimeTestAppendRfc822", __LINE__, "IMimeMessage::BindToObject(HBDOY_ROOT, IID_IMimeAddressTable, ...) failed.", hr);
  1240. goto exit;
  1241. }
  1242. // Append an RFC 822 formatted addresses
  1243. hr = pAdrTable->AppendRfc822(IAT_TO, IET_DECODED, "test1 <[email protected]>");
  1244. if (FAILED(hr))
  1245. {
  1246. ReportError("MimeTestAppendRfc822", __LINE__, "IMimeAddressTable::AppendRfc822(...) failed.", hr);
  1247. goto exit;
  1248. }
  1249. // Append an RFC 822 formatted addresses
  1250. hr = pAdrTable->AppendRfc822(IAT_TO, IET_DECODED, "to2 <[email protected]>");
  1251. if (FAILED(hr))
  1252. {
  1253. ReportError("MimeTestAppendRfc822", __LINE__, "IMimeAddressTable::AppendRfc822(...) failed.", hr);
  1254. goto exit;
  1255. }
  1256. // Append an RFC 822 formatted addresses
  1257. hr = pAdrTable->AppendRfc822(IAT_TO, IET_DECODED, "to3 <[email protected]>");
  1258. if (FAILED(hr))
  1259. {
  1260. ReportError("MimeTestAppendRfc822", __LINE__, "IMimeAddressTable::AppendRfc822(...) failed.", hr);
  1261. goto exit;
  1262. }
  1263. // Save the mime message to a stream
  1264. hr = SaveMimeMessage(pMessage, SAVE_RFC1521, &pStream);
  1265. if (FAILED(hr))
  1266. {
  1267. ReportError("MimeTestAppendRfc822", __LINE__, "SaveMimeMessage(...) failed.", hr);
  1268. goto exit;
  1269. }
  1270. // Dump the stream to the console, and then wait for input so that the user can view it...
  1271. ReportStatus("\n");
  1272. DumpStreamToConsole(pStream);
  1273. // Return a message object
  1274. if (ppMessage)
  1275. {
  1276. (*ppMessage) = pMessage;
  1277. (*ppMessage)->AddRef();
  1278. }
  1279. exit:
  1280. // Cleanup
  1281. if (pStream)
  1282. pStream->Release();
  1283. if (pAdrTable)
  1284. pAdrTable->Release();
  1285. if (pMessage)
  1286. pMessage->Release();
  1287. // Done
  1288. return hr;
  1289. }
  1290. // --------------------------------------------------------------------------------
  1291. // CreateMimeMessage - Basic way of creating a COM object.
  1292. // --------------------------------------------------------------------------------
  1293. HRESULT CreateMimeMessage(IMimeMessage **ppMessage)
  1294. {
  1295. // Locals
  1296. HRESULT hr;
  1297. // Create a message object
  1298. hr = CoCreateInstance(CLSID_IMimeMessage, NULL, CLSCTX_INPROC_SERVER, IID_IMimeMessage, (LPVOID *)ppMessage);
  1299. if (FAILED(hr))
  1300. {
  1301. ReportError("CreateMimeMessage", __LINE__, "CoCreateInstance(CLSID_IMimeMessage, ...) failed.", hr);
  1302. goto exit;
  1303. }
  1304. // You must always initnew the message object
  1305. hr = (*ppMessage)->InitNew();
  1306. if (FAILED(hr))
  1307. {
  1308. ReportError("CreateMimeMessage", __LINE__, "IMimeMessage::InitNew() failed.", hr);
  1309. goto exit;
  1310. }
  1311. exit:
  1312. // Done
  1313. return hr;
  1314. }
  1315. // --------------------------------------------------------------------------------
  1316. // Saves a MIME message
  1317. // --------------------------------------------------------------------------------
  1318. HRESULT SaveMimeMessage(IMimeMessage *pMessage, MIMESAVETYPE savetype, IStream **ppStream)
  1319. {
  1320. // Locals
  1321. HRESULT hr;
  1322. PROPVARIANT rOption;
  1323. // Set the save format option into the message object. The OID_xxx types are defined
  1324. // in mimeole.idl. Go to that file for more information.
  1325. rOption.vt = VT_UI4;
  1326. rOption.ulVal = savetype;
  1327. hr = pMessage->SetOption(OID_SAVE_FORMAT, &rOption);
  1328. if (FAILED(hr))
  1329. {
  1330. ReportError("SaveMimeMessage", __LINE__, "IMimeMessage::SetOption(OID_SAVE_FORMAT, ...) failed", hr);
  1331. goto exit;
  1332. }
  1333. // Create a stream in which to save the message...
  1334. hr = CreateStreamOnHGlobal(NULL, TRUE, ppStream);
  1335. if (FAILED(hr))
  1336. {
  1337. ReportError("SaveMimeMessage", __LINE__, "CreateStreamOnHGlobal failed", hr);
  1338. goto exit;
  1339. }
  1340. // Call the save method on IMimeMessage. Mimeole will call commit on the stream object.
  1341. // After this call, the stream will be positioned at the end.
  1342. hr = pMessage->Save(*ppStream, TRUE);
  1343. if (FAILED(hr))
  1344. {
  1345. ReportError("SaveMimeMessage", __LINE__, "IMimeMessage::Save(...) failed", hr);
  1346. goto exit;
  1347. }
  1348. exit:
  1349. // Done
  1350. return hr;
  1351. }
  1352. // --------------------------------------------------------------------------------
  1353. // ReportError - Simple function to report an error that has an HRESULT
  1354. // --------------------------------------------------------------------------------
  1355. HRESULT ReportError(LPCSTR pszFunction, INT nLine, LPCSTR pszErrorText, HRESULT hrResult)
  1356. {
  1357. printf("Error(HR = 0x%08X) in %s on line %d - %s\n", hrResult, pszFunction, nLine, pszErrorText);
  1358. return hrResult;
  1359. }
  1360. // --------------------------------------------------------------------------------
  1361. // ReportStatus - Simple function to report a string to the user
  1362. // --------------------------------------------------------------------------------
  1363. HRESULT ReportStatus(LPCSTR pszStatusText)
  1364. {
  1365. printf("Status: %s\n", pszStatusText);
  1366. return S_OK;
  1367. }
  1368. // --------------------------------------------------------------------------------
  1369. // DumpStreamToConsole
  1370. // --------------------------------------------------------------------------------
  1371. HRESULT DumpStreamToConsole(IStream *pStream)
  1372. {
  1373. // Locals
  1374. HRESULT hr=S_OK;
  1375. BYTE rgbBuffer[2048];
  1376. ULONG cbRead;
  1377. // This is an msoert function
  1378. HrStreamSeekSet(pStream, 0);
  1379. while(1)
  1380. {
  1381. // Read a block from the stream
  1382. hr = pStream->Read(rgbBuffer, sizeof(rgbBuffer), &cbRead);
  1383. if (FAILED(hr))
  1384. {
  1385. ReportError("DumpStreamToConsole", __LINE__, "DumpStreamToConsole - IStream::Read failed.", hr);
  1386. break;
  1387. }
  1388. // If nothing read, then were done
  1389. if (0 == cbRead)
  1390. break;
  1391. // Print it
  1392. printf("%s", (LPSTR)rgbBuffer);
  1393. }
  1394. // Finaly LF
  1395. printf("\n");
  1396. // Done
  1397. return hr;
  1398. }
  1399. /*
  1400. DWORD i=1;
  1401. DWORD dw;
  1402. CHAR szDate[255];
  1403. HROWSET hRowset;
  1404. FOLDERINFO Folder;
  1405. MESSAGEINFO Message;
  1406. IMessageStore *pStore;
  1407. IMessageFolder *pFolder;
  1408. CoCreateInstance(CLSID_MessageStore, NULL, CLSCTX_INPROC_SERVER, IID_IMessageStore, (LPVOID *)&pStore);
  1409. pStore->Initialize("d:\\storetest");
  1410. pStore->OpenSpecialFolder(FOLDERID_LOCAL_STORE, FOLDER_INBOX, &pFolder);
  1411. pFolder->CreateRowset(IINDEX_SUBJECT, 0, &hRowset);
  1412. while(S_OK == pFolder->QueryRowset(hRowset, 1, (LPVOID *)&Message, NULL))
  1413. {
  1414. dw = FDTF_DEFAULT;
  1415. SHFormatDateTimeA(&Message.ftReceived, &dw, szDate, 255);
  1416. if (Message.pszNormalSubj)
  1417. printf("%05d: %s, %s, %d\n", i, Message.pszNormalSubj, szDate, Message.idMessage);
  1418. else
  1419. printf("%05d: <Empty>, %s, %d\n", i, szDate, Message.idMessage);
  1420. pFolder->FreeRecord(&Message);
  1421. i++;
  1422. }
  1423. pFolder->CloseRowset(&hRowset);
  1424. pFolder->Release();
  1425. pStore->Release();
  1426. exit(1);
  1427. */