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.

634 lines
22 KiB

  1. // ==============================================================================
  2. // I M N T N E F . C P P
  3. // ==============================================================================
  4. #define INITGUID
  5. #define USES_IID_IMessage
  6. #define USES_IID_IMAPIPropData
  7. #include <windows.h>
  8. #include <assert.h>
  9. #include <ole2.h>
  10. #include <initguid.h>
  11. #include <mapiguid.h>
  12. #include <mapi.h>
  13. #include <mapix.h>
  14. #include <mapiutil.h>
  15. #include <tnef.h>
  16. // =====================================================================================
  17. // G L O B A L S
  18. // =====================================================================================
  19. HINSTANCE g_hInst = NULL;
  20. LPMAPISESSION g_lpSession = NULL;
  21. LPADRBOOK g_lpAdrBook = NULL;
  22. // =====================================================================================
  23. // S T R U C T U R E S
  24. // =====================================================================================
  25. class CImnMsg : public IMessage
  26. {
  27. private:
  28. ULONG m_cRef;
  29. LPPROPDATA m_lpPropData;
  30. public:
  31. // =====================================================================================
  32. // Creation
  33. // =====================================================================================
  34. CImnMsg ();
  35. ~CImnMsg ();
  36. // =====================================================================================
  37. // IUnknown
  38. // =====================================================================================
  39. STDMETHODIMP QueryInterface (REFIID riid, LPVOID *ppvObj);
  40. STDMETHODIMP_(ULONG) AddRef ();
  41. STDMETHODIMP_(ULONG) Release ();
  42. // =====================================================================================
  43. // IMAPIProp
  44. // =====================================================================================
  45. STDMETHODIMP CopyProps (LPSPropTagArray lpIncludeProps, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, LPCIID lpInterface, LPVOID lpDestObj, ULONG ulFlags, LPSPropProblemArray FAR * lppProblems);
  46. STDMETHODIMP CopyTo (ULONG ciidExclude, LPCIID rgiidExclude, LPSPropTagArray lpExcludeProps, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, LPCIID lpInterface, LPVOID lpDestObj, ULONG ulFlags, LPSPropProblemArray FAR * lppProblems);
  47. STDMETHODIMP DeleteProps (LPSPropTagArray lpPropTagArray, LPSPropProblemArray FAR * lppProblems);
  48. STDMETHODIMP GetIDsFromNames (ULONG cPropNames, LPMAPINAMEID FAR * lppPropNames, ULONG ulFlags, LPSPropTagArray FAR * lppPropTags);
  49. STDMETHODIMP GetLastError (HRESULT hResult, ULONG ulFlags, LPMAPIERROR FAR * lppMAPIError);
  50. STDMETHODIMP GetNamesFromIDs (LPSPropTagArray FAR * lppPropTags, LPGUID lpPropSetGuid, ULONG ulFlags, ULONG FAR * lpcPropNames, LPMAPINAMEID FAR * FAR * lpppPropNames);
  51. STDMETHODIMP GetPropList (ULONG ulFlags, LPSPropTagArray FAR * lppPropTagArray);
  52. STDMETHODIMP GetProps (LPSPropTagArray lpPropTagArray, ULONG ulFlags, ULONG FAR * lpcValues, LPSPropValue FAR * lppPropArray);
  53. STDMETHODIMP OpenProperty (ULONG ulPropTag, LPCIID lpiid, ULONG ulInterfaceOptions, ULONG ulFlags, LPUNKNOWN FAR * lppUnk);
  54. STDMETHODIMP SaveChanges (ULONG ulFlags);
  55. STDMETHODIMP SetProps (ULONG cValues, LPSPropValue lpPropArray, LPSPropProblemArray FAR * lppProblems);
  56. // =====================================================================================
  57. // IMessage
  58. // =====================================================================================
  59. STDMETHODIMP CreateAttach (LPCIID lpInterface, ULONG ulFlags, ULONG FAR * lpulAttachmentNum, LPATTACH FAR * lppAttach);
  60. STDMETHODIMP DeleteAttach (ULONG ulAttachmentNum, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, ULONG ulFlags);
  61. STDMETHODIMP GetAttachmentTable (ULONG ulFlags, LPMAPITABLE FAR * lppTable);
  62. STDMETHODIMP GetRecipientTable (ULONG ulFlags, LPMAPITABLE FAR * lppTable);
  63. STDMETHODIMP ModifyRecipients (ULONG ulFlags, LPADRLIST lpMods);
  64. STDMETHODIMP OpenAttach (ULONG ulAttachmentNum, LPCIID lpInterface, ULONG ulFlags, LPATTACH FAR * lppAttach);
  65. STDMETHODIMP SetReadFlag (ULONG ulFlags);
  66. STDMETHODIMP SubmitMessage (ULONG ulFlags);
  67. };
  68. // =====================================================================================
  69. // P R O T O T Y P E S
  70. // =====================================================================================
  71. HRESULT HrCopyStream (LPSTREAM lpstmIn, LPSTREAM lpstmOut, ULONG *pcb);
  72. HRESULT HrRewindStream (LPSTREAM lpstm);
  73. // =====================================================================================
  74. // D l l M a i n
  75. // =====================================================================================
  76. int APIENTRY DllMain (HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
  77. {
  78. switch (dwReason)
  79. {
  80. case DLL_PROCESS_ATTACH:
  81. g_hInst = hInstance;
  82. return 1;
  83. case DLL_PROCESS_DETACH:
  84. return 1;
  85. }
  86. // Done
  87. return 0;
  88. }
  89. // =====================================================================================
  90. // H r I n i t
  91. // =====================================================================================
  92. HRESULT HrInit (BOOL fInit)
  93. {
  94. // Locals
  95. HRESULT hr = S_OK;
  96. // If initing
  97. if (fInit)
  98. {
  99. // iNIT
  100. hr = MAPIInitialize (NULL);
  101. if (FAILED (hr))
  102. goto exit;
  103. // Logon to mapi
  104. if (g_lpSession == NULL)
  105. {
  106. hr = MAPILogonEx (0, NULL, NULL, MAPI_NO_MAIL | MAPI_USE_DEFAULT, &g_lpSession);
  107. if (FAILED (hr))
  108. {
  109. if (g_lpSession)
  110. {
  111. g_lpSession->Release ();
  112. g_lpSession = NULL;
  113. }
  114. goto exit;
  115. }
  116. }
  117. // Get an address book object
  118. if (g_lpAdrBook == NULL)
  119. {
  120. hr = g_lpSession->OpenAddressBook (0, NULL, AB_NO_DIALOG, &g_lpAdrBook);
  121. if (FAILED (hr))
  122. {
  123. if (g_lpAdrBook)
  124. {
  125. g_lpAdrBook->Release ();
  126. g_lpAdrBook = NULL;
  127. }
  128. goto exit;
  129. }
  130. }
  131. }
  132. else
  133. {
  134. // Release Address Book
  135. if (g_lpAdrBook)
  136. {
  137. g_lpAdrBook->Release ();
  138. g_lpAdrBook = NULL;
  139. }
  140. // Log off session
  141. if (g_lpSession)
  142. {
  143. g_lpSession->Logoff (0, 0, 0);
  144. g_lpSession->Release ();
  145. g_lpSession = NULL;
  146. }
  147. // MAPI de-init
  148. MAPIUninitialize ();
  149. }
  150. exit:
  151. // Done
  152. return hr;
  153. }
  154. // =====================================================================================
  155. // HrGetTnefRtfStream
  156. // =====================================================================================
  157. HRESULT HrGetTnefRtfStream (LPSTREAM lpstmTnef, LPSTREAM lpstmRtf)
  158. {
  159. // Locals
  160. HRESULT hr = S_OK;
  161. SYSTEMTIME st;
  162. WORD wKey;
  163. LPITNEF lpTnef = NULL;
  164. LPSTREAM lpstmRtfComp = NULL, lpstmRtfUncomp = NULL;
  165. CImnMsg *lpImnMsg = NULL;
  166. ULONG cValues;
  167. LPSPropValue lpPropValue = NULL;
  168. SizedSPropTagArray (1, spa) = {1, { PR_RTF_COMPRESSED } };
  169. // Bad init
  170. if (!g_lpSession || !g_lpAdrBook || !lpstmTnef || !lpstmRtf)
  171. {
  172. hr = E_INVALIDARG;
  173. goto exit;
  174. }
  175. // Bullet style uniquification for wKey
  176. GetSystemTime (&st);
  177. wKey = (st.wHour << 8) + st.wSecond;
  178. // Create one of my message objects
  179. lpImnMsg = new CImnMsg;
  180. if (lpImnMsg == NULL)
  181. {
  182. hr = E_FAIL;
  183. goto exit;
  184. }
  185. // Initiates a TNEF session
  186. hr = OpenTnefStreamEx (NULL, lpstmTnef, "WINMAIL.DAT", TNEF_DECODE,
  187. (LPMESSAGE)lpImnMsg, wKey, g_lpAdrBook, &lpTnef);
  188. if (FAILED (hr))
  189. goto exit;
  190. // ExtractProps
  191. hr = lpTnef->ExtractProps (TNEF_PROP_INCLUDE, (SPropTagArray *)&spa, NULL);
  192. if (FAILED (hr))
  193. goto exit;
  194. // RTF stream
  195. hr = lpImnMsg->GetProps ((SPropTagArray *)&spa, 0, &cValues, &lpPropValue);
  196. if (FAILED (hr))
  197. goto exit;
  198. // Property not found ?
  199. if (PROP_TYPE (lpPropValue[0].ulPropTag) == PT_ERROR)
  200. {
  201. hr = E_FAIL;
  202. goto exit;
  203. }
  204. // Create Hglobal
  205. hr = CreateStreamOnHGlobal (NULL, TRUE, &lpstmRtfComp);
  206. if (FAILED (hr))
  207. goto exit;
  208. // Write my binary into lpstmRtfComp
  209. hr = lpstmRtfComp->Write (lpPropValue[0].Value.bin.lpb, lpPropValue[0].Value.bin.cb, NULL);
  210. if (FAILED (hr))
  211. goto exit;
  212. // Commit and rewind the stream
  213. hr = lpstmRtfComp->Commit (STGC_DEFAULT);
  214. if (FAILED (hr))
  215. goto exit;
  216. // Rewind
  217. hr = HrRewindStream (lpstmRtfComp);
  218. if (FAILED (hr))
  219. goto exit;
  220. // un compress it
  221. hr = WrapCompressedRTFStream (lpstmRtfComp, 0, &lpstmRtfUncomp);
  222. if (FAILED (hr))
  223. goto exit;
  224. // Copy strem
  225. hr = HrCopyStream (lpstmRtfUncomp, lpstmRtf, NULL);
  226. if (FAILED (hr))
  227. goto exit;
  228. // Rewind lpstmRtf
  229. hr = HrRewindStream (lpstmRtf);
  230. if (FAILED (hr))
  231. goto exit;
  232. exit:
  233. // Cleanup
  234. if (lpPropValue)
  235. MAPIFreeBuffer (lpPropValue);
  236. if (lpTnef)
  237. lpTnef->Release ();
  238. if (lpstmRtfComp)
  239. lpstmRtfComp->Release ();
  240. if (lpstmRtfUncomp)
  241. lpstmRtfUncomp->Release ();
  242. if (lpImnMsg)
  243. lpImnMsg->Release ();
  244. // Done
  245. return hr;
  246. }
  247. // =====================================================================================
  248. // HrCopyStream - caller must do the commit
  249. // =====================================================================================
  250. HRESULT HrCopyStream (LPSTREAM lpstmIn, LPSTREAM lpstmOut, ULONG *pcb)
  251. {
  252. // Locals
  253. HRESULT hr = S_OK;
  254. BYTE buf[4096];
  255. ULONG cbRead = 0, cbTotal = 0;
  256. do
  257. {
  258. hr = lpstmIn->Read (buf, sizeof (buf), &cbRead);
  259. if (FAILED (hr))
  260. goto exit;
  261. if (cbRead == 0) break;
  262. hr = lpstmOut->Write (buf, cbRead, NULL);
  263. if (FAILED (hr))
  264. goto exit;
  265. cbTotal += cbRead;
  266. }
  267. while (cbRead == sizeof (buf));
  268. exit:
  269. if (pcb)
  270. *pcb = cbTotal;
  271. return hr;
  272. }
  273. // =====================================================================================
  274. // HrRewindStream
  275. // =====================================================================================
  276. HRESULT HrRewindStream (LPSTREAM lpstm)
  277. {
  278. LARGE_INTEGER liOrigin = {0,0};
  279. return lpstm->Seek (liOrigin, STREAM_SEEK_SET, NULL);
  280. }
  281. // =====================================================================================
  282. // CImnMsg::~CImnMsg
  283. // =====================================================================================
  284. CImnMsg::CImnMsg ()
  285. {
  286. m_cRef = 1;
  287. CreateIProp (&IID_IMAPIPropData, (ALLOCATEBUFFER *)MAPIAllocateBuffer,
  288. (ALLOCATEMORE *)MAPIAllocateMore, (FREEBUFFER *)MAPIFreeBuffer,
  289. NULL, &m_lpPropData);
  290. assert (m_lpPropData);
  291. }
  292. // =====================================================================================
  293. // CImnMsg::~CImnMsg
  294. // =====================================================================================
  295. CImnMsg::~CImnMsg ()
  296. {
  297. if (m_lpPropData)
  298. m_lpPropData->Release ();
  299. }
  300. // =====================================================================================
  301. // Add Ref
  302. // =====================================================================================
  303. STDMETHODIMP_(ULONG) CImnMsg::AddRef ()
  304. {
  305. ++m_cRef;
  306. return m_cRef;
  307. }
  308. // =====================================================================================
  309. // Release
  310. // =====================================================================================
  311. STDMETHODIMP_(ULONG) CImnMsg::Release ()
  312. {
  313. ULONG uCount = --m_cRef;
  314. if (!uCount)
  315. delete this;
  316. return uCount;
  317. }
  318. // =====================================================================================
  319. // CImnMsg::QueryInterface
  320. // =====================================================================================
  321. STDMETHODIMP CImnMsg::QueryInterface(REFIID riid, LPVOID * ppvObj)
  322. {
  323. // Locals
  324. HRESULT hr = S_OK;
  325. // Init
  326. *ppvObj = NULL;
  327. // IUnknown or IExchExt interface, this is it dude
  328. if (IID_IUnknown == riid)
  329. {
  330. *ppvObj = (LPUNKNOWN)(IUnknown *)this;
  331. }
  332. // IID_IMessage
  333. else if (IID_IMessage == riid)
  334. {
  335. *ppvObj = (LPUNKNOWN)(IMessage *)this;
  336. }
  337. // IID_IMAPIProp
  338. else if (IID_IMAPIPropData == riid)
  339. {
  340. assert (m_lpPropData);
  341. *ppvObj = (LPUNKNOWN)(IMAPIProp *)m_lpPropData;
  342. }
  343. // Else, interface is not supported
  344. else
  345. hr = E_NOINTERFACE;
  346. // Increment Reference Count
  347. if (NULL != *ppvObj)
  348. ((LPUNKNOWN)*ppvObj)->AddRef();
  349. // Done
  350. return hr;
  351. }
  352. // =====================================================================================
  353. // CImnMsg::CopyProps
  354. // =====================================================================================
  355. STDMETHODIMP CImnMsg::CopyProps (LPSPropTagArray lpIncludeProps, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, LPCIID lpInterface, LPVOID lpDestObj, ULONG ulFlags, LPSPropProblemArray FAR * lppProblems)
  356. {
  357. if (m_lpPropData == NULL)
  358. {
  359. assert (m_lpPropData);
  360. return E_FAIL;
  361. }
  362. return m_lpPropData->CopyProps (lpIncludeProps, ulUIParam, lpProgress, lpInterface, lpDestObj, ulFlags, lppProblems);
  363. }
  364. // =====================================================================================
  365. // CImnMsg::CopyTo
  366. // =====================================================================================
  367. STDMETHODIMP CImnMsg::CopyTo (ULONG ciidExclude, LPCIID rgiidExclude, LPSPropTagArray lpExcludeProps, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, LPCIID lpInterface, LPVOID lpDestObj, ULONG ulFlags, LPSPropProblemArray FAR * lppProblems)
  368. {
  369. if (m_lpPropData == NULL)
  370. {
  371. assert (m_lpPropData);
  372. return E_FAIL;
  373. }
  374. return m_lpPropData->CopyTo (ciidExclude, rgiidExclude, lpExcludeProps, ulUIParam, lpProgress, lpInterface, lpDestObj, ulFlags, lppProblems);
  375. }
  376. // =====================================================================================
  377. // CImnMsg::DeleteProps
  378. // =====================================================================================
  379. STDMETHODIMP CImnMsg::DeleteProps (LPSPropTagArray lpPropTagArray, LPSPropProblemArray FAR * lppProblems)
  380. {
  381. if (m_lpPropData == NULL)
  382. {
  383. assert (m_lpPropData);
  384. return E_FAIL;
  385. }
  386. return m_lpPropData->DeleteProps (lpPropTagArray, lppProblems);
  387. }
  388. // =====================================================================================
  389. // CImnMsg::GetIDsFromNames
  390. // =====================================================================================
  391. STDMETHODIMP CImnMsg::GetIDsFromNames (ULONG cPropNames, LPMAPINAMEID FAR * lppPropNames, ULONG ulFlags, LPSPropTagArray FAR * lppPropTags)
  392. {
  393. if (m_lpPropData == NULL)
  394. {
  395. assert (m_lpPropData);
  396. return E_FAIL;
  397. }
  398. return m_lpPropData->GetIDsFromNames (cPropNames, lppPropNames, ulFlags, lppPropTags);
  399. }
  400. // =====================================================================================
  401. // CImnMsg::GetLastError
  402. // =====================================================================================
  403. STDMETHODIMP CImnMsg::GetLastError (HRESULT hResult, ULONG ulFlags, LPMAPIERROR FAR * lppMAPIError)
  404. {
  405. if (m_lpPropData == NULL)
  406. {
  407. assert (m_lpPropData);
  408. return E_FAIL;
  409. }
  410. return m_lpPropData->GetLastError (hResult, ulFlags, lppMAPIError);
  411. }
  412. // =====================================================================================
  413. // CImnMsg::GetNamesFromIDs
  414. // =====================================================================================
  415. STDMETHODIMP CImnMsg::GetNamesFromIDs (LPSPropTagArray FAR * lppPropTags, LPGUID lpPropSetGuid, ULONG ulFlags, ULONG FAR * lpcPropNames, LPMAPINAMEID FAR * FAR * lpppPropNames)
  416. {
  417. if (m_lpPropData == NULL)
  418. {
  419. assert (m_lpPropData);
  420. return E_FAIL;
  421. }
  422. return m_lpPropData->GetNamesFromIDs (lppPropTags, lpPropSetGuid, ulFlags, lpcPropNames, lpppPropNames);
  423. }
  424. // =====================================================================================
  425. // CImnMsg::GetPropList
  426. // =====================================================================================
  427. STDMETHODIMP CImnMsg::GetPropList (ULONG ulFlags, LPSPropTagArray FAR * lppPropTagArray)
  428. {
  429. if (m_lpPropData == NULL)
  430. {
  431. assert (m_lpPropData);
  432. return E_FAIL;
  433. }
  434. return m_lpPropData->GetPropList (ulFlags, lppPropTagArray);
  435. }
  436. // =====================================================================================
  437. // CImnMsg::GetProps
  438. // =====================================================================================
  439. STDMETHODIMP CImnMsg::GetProps (LPSPropTagArray lpPropTagArray, ULONG ulFlags, ULONG FAR * lpcValues, LPSPropValue FAR * lppPropArray)
  440. {
  441. if (m_lpPropData == NULL)
  442. {
  443. assert (m_lpPropData);
  444. return E_FAIL;
  445. }
  446. return m_lpPropData->GetProps (lpPropTagArray, ulFlags, lpcValues, lppPropArray);
  447. }
  448. // =====================================================================================
  449. // CImnMsg::OpenProperty
  450. // =====================================================================================
  451. STDMETHODIMP CImnMsg::OpenProperty (ULONG ulPropTag, LPCIID lpiid, ULONG ulInterfaceOptions, ULONG ulFlags, LPUNKNOWN FAR * lppUnk)
  452. {
  453. if (m_lpPropData == NULL)
  454. {
  455. assert (m_lpPropData);
  456. return E_FAIL;
  457. }
  458. return m_lpPropData->OpenProperty (ulPropTag, lpiid, ulInterfaceOptions, ulFlags, lppUnk);
  459. }
  460. // =====================================================================================
  461. // CImnMsg::SaveChanges
  462. // =====================================================================================
  463. STDMETHODIMP CImnMsg::SaveChanges (ULONG ulFlags)
  464. {
  465. if (m_lpPropData == NULL)
  466. {
  467. assert (m_lpPropData);
  468. return E_FAIL;
  469. }
  470. return m_lpPropData->SaveChanges (ulFlags);
  471. }
  472. // =====================================================================================
  473. // CImnMsg::SetProps
  474. // =====================================================================================
  475. STDMETHODIMP CImnMsg::SetProps (ULONG cValues, LPSPropValue lpPropArray, LPSPropProblemArray FAR * lppProblems)
  476. {
  477. if (m_lpPropData == NULL)
  478. {
  479. assert (m_lpPropData);
  480. return E_FAIL;
  481. }
  482. return m_lpPropData->SetProps (cValues, lpPropArray, lppProblems);
  483. }
  484. // =====================================================================================
  485. // CImnMsg::CreateAttach
  486. // =====================================================================================
  487. STDMETHODIMP CImnMsg::CreateAttach (LPCIID lpInterface, ULONG ulFlags, ULONG FAR * lpulAttachmentNum, LPATTACH FAR * lppAttach)
  488. {
  489. assert (FALSE);
  490. return E_NOTIMPL;
  491. }
  492. // =====================================================================================
  493. // CImnMsg::DeleteAttach
  494. // =====================================================================================
  495. STDMETHODIMP CImnMsg::DeleteAttach (ULONG ulAttachmentNum, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, ULONG ulFlags)
  496. {
  497. assert (FALSE);
  498. return E_NOTIMPL;
  499. }
  500. // =====================================================================================
  501. // CImnMsg::GetAttachmentTable
  502. // =====================================================================================
  503. STDMETHODIMP CImnMsg::GetAttachmentTable (ULONG ulFlags, LPMAPITABLE FAR * lppTable)
  504. {
  505. assert (FALSE);
  506. return E_NOTIMPL;
  507. }
  508. // =====================================================================================
  509. // CImnMsg::GetRecipientTable
  510. // =====================================================================================
  511. STDMETHODIMP CImnMsg::GetRecipientTable (ULONG ulFlags, LPMAPITABLE FAR * lppTable)
  512. {
  513. assert (FALSE);
  514. return E_NOTIMPL;
  515. }
  516. // =====================================================================================
  517. // CImnMsg::ModifyRecipients
  518. // =====================================================================================
  519. STDMETHODIMP CImnMsg::ModifyRecipients (ULONG ulFlags, LPADRLIST lpMods)
  520. {
  521. assert (FALSE);
  522. return E_NOTIMPL;
  523. }
  524. // =====================================================================================
  525. // CImnMsg::OpenAttach
  526. // =====================================================================================
  527. STDMETHODIMP CImnMsg::OpenAttach (ULONG ulAttachmentNum, LPCIID lpInterface, ULONG ulFlags, LPATTACH FAR * lppAttach)
  528. {
  529. assert (FALSE);
  530. return E_NOTIMPL;
  531. }
  532. // =====================================================================================
  533. // CImnMsg::SetReadFlag
  534. // =====================================================================================
  535. STDMETHODIMP CImnMsg::SetReadFlag (ULONG ulFlags)
  536. {
  537. assert (FALSE);
  538. return E_NOTIMPL;
  539. }
  540. // =====================================================================================
  541. // CImnMsg::SubmitMessage
  542. // =====================================================================================
  543. STDMETHODIMP CImnMsg::SubmitMessage (ULONG ulFlags)
  544. {
  545. assert (FALSE);
  546. return E_NOTIMPL;
  547. }