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.

1412 lines
32 KiB

  1. /*
  2. * o e d o c s . c p p
  3. *
  4. * Purpose:
  5. * sample code for demo of OE object model. Implements a very limited
  6. * subset of funcitonality
  7. *
  8. * History
  9. *
  10. * Copyright (C) Microsoft Corp. 1995, 1996.
  11. */
  12. #include <pch.hxx>
  13. #include <resource.h>
  14. #include <strconst.h>
  15. #include "demand.h"
  16. #include "dllmain.h"
  17. #include "msoert.h"
  18. #include "msoeobj.h"
  19. #include "oedocs.h"
  20. #include "instance.h"
  21. #include "msgfldr.h"
  22. #include "msgtable.h"
  23. #include "mailutil.h"
  24. #include "oleutil.h"
  25. #include "mshtmdid.h"
  26. #include "shlwapi.h"
  27. static ITypeLib *g_pTypeLib=NULL;
  28. HRESULT CreateOEFolder(IMessageFolder *pFolder, IDispatch **ppdisp);
  29. HRESULT CreateOEMessage(IMimeMessage *pMsg, IMessageFolder *pFolder, OEMSGDATA *pMsgData, IDispatch **ppdisp);
  30. HRESULT FindFolder(BSTR bstr, LONG lIndex, IMessageFolder **ppFolder);
  31. void FreeOEMsgData(POEMSGDATA pMsgData);
  32. HRESULT EnsureTypeLib();
  33. LPWSTR StringFromColIndex(DWORD dw);
  34. DWORD ColIndexFromString(LPWSTR pszW);
  35. /*
  36. * C O E M a i l
  37. */
  38. COEMail::COEMail(IUnknown *pUnkOuter)
  39. {
  40. m_cRef=1;
  41. m_pFolders = NULL;
  42. CoIncrementInit("COEMail::COEMail", MSOEAPI_START_SHOWERRORS, NULL, NULL);
  43. }
  44. COEMail::~COEMail()
  45. {
  46. ReleaseObj(m_pFolders);
  47. CoDecrementInit("COEMail::COEMail", NULL);
  48. }
  49. HRESULT COEMail::PrivateQueryInterface(REFIID riid, LPVOID *lplpObj)
  50. {
  51. if(!lplpObj)
  52. return E_INVALIDARG;
  53. *lplpObj = NULL;
  54. if (IsEqualIID(riid, IID_IUnknown))
  55. *lplpObj = (LPVOID)(IOEMail *)this;
  56. else if (IsEqualIID(riid, IID_IDispatch))
  57. *lplpObj = (LPVOID)(IDispatch *)(CBaseDisp *)this;
  58. else if (IsEqualIID(riid, IID_IOEMail))
  59. *lplpObj = (LPVOID)(IOEMail *)this;
  60. else
  61. return E_NOINTERFACE;
  62. AddRef();
  63. return NOERROR;
  64. }
  65. // *** IOEMail **
  66. HRESULT COEMail::get_folders(IOEFolderCollection **p)
  67. {
  68. COEFolderCollection *pNew=NULL;
  69. HRESULT hr=S_OK;
  70. if (!m_pFolders)
  71. {
  72. pNew = new COEFolderCollection(NULL);
  73. if (!pNew)
  74. return E_OUTOFMEMORY;
  75. hr = pNew->Init();
  76. if (FAILED(hr))
  77. goto error;
  78. m_pFolders = (IOEFolderCollection *)pNew;
  79. pNew = NULL; // don't free
  80. }
  81. *p = m_pFolders;
  82. m_pFolders->AddRef();
  83. error:
  84. ReleaseObj(pNew);
  85. return hr;
  86. }
  87. HRESULT COEMail::get_version(BSTR *pbstr)
  88. {
  89. *pbstr = SysAllocString(L"Outlook Express v5.0");
  90. return S_OK;
  91. }
  92. HRESULT COEMail::get_newMsg(IDispatch **ppDisp)
  93. {
  94. COEMessage *pNew=NULL;
  95. HRESULT hr;
  96. IMimeMessage *pMsg=NULL;
  97. pNew = new COEMessage();
  98. if (!pNew)
  99. return E_OUTOFMEMORY;
  100. hr = MimeOleCreateMessage(NULL, &pMsg);
  101. if (FAILED(hr))
  102. goto error;
  103. hr = pNew->Init(pMsg, NULL, NULL);
  104. if (FAILED(hr))
  105. goto error;
  106. hr = pNew->QueryInterface(IID_IDispatch, (LPVOID *)ppDisp);
  107. error:
  108. ReleaseObj(pNew);
  109. ReleaseObj(pMsg);
  110. return hr;
  111. }
  112. HRESULT COEMail::Init()
  113. {
  114. return InitBaseDisp((LPVOID *)(IOEMail *)this, IID_IOEMail, g_pTypeLib);
  115. }
  116. HRESULT EnsureTypeLib()
  117. {
  118. TCHAR szDll[MAX_PATH];
  119. LPWSTR pszW;
  120. // BUG BUG BUG: hack to get typelib loaded quickly. NOT THREAD SAFE
  121. if (!g_pTypeLib)
  122. {
  123. GetModuleFileName(g_hInst, szDll, ARRAYSIZE(szDll));
  124. pszW = PszToUnicode(GetACP(), szDll);
  125. if (pszW)
  126. {
  127. LoadTypeLib(pszW, &g_pTypeLib);
  128. MemFree(pszW);
  129. }
  130. }
  131. if (!g_pTypeLib)
  132. return E_FAIL;
  133. // BUG BUG BUG: hack to get typelib loaded quickly. NOT THREAD SAFE
  134. return S_OK;
  135. }
  136. HRESULT CreateInstance_OEMail(IUnknown *pUnkOuter, IUnknown **ppUnknown)
  137. {
  138. // Locals
  139. COEMail *pMail=NULL;
  140. HRESULT hr=S_OK;
  141. if (NULL != pUnkOuter)
  142. return CLASS_E_NOAGGREGATION;
  143. pMail = new COEMail(NULL);
  144. if (!pMail)
  145. return E_OUTOFMEMORY;
  146. hr = EnsureTypeLib();
  147. if (FAILED(hr))
  148. goto error;
  149. hr = pMail->Init();
  150. if (FAILED(hr))
  151. goto error;
  152. *ppUnknown = (IUnknown *)(IOEMail *)pMail;
  153. pMail->AddRef();
  154. error:
  155. ReleaseObj(pMail);
  156. return hr;
  157. }
  158. /*
  159. * C O E F o l d e r C o l l e c t i o n
  160. */
  161. COEFolderCollection::COEFolderCollection(IUnknown *pUnkOuter)
  162. {
  163. m_cRef=1;
  164. CoIncrementInit("COEFolderCollection::COEFolderCollection", MSOEAPI_START_SHOWERRORS, NULL, NULL);
  165. }
  166. COEFolderCollection::~COEFolderCollection()
  167. {
  168. CoDecrementInit("COEFolderCollection::COEFolderCollection", NULL);
  169. }
  170. HRESULT COEFolderCollection::PrivateQueryInterface(REFIID riid, LPVOID *lplpObj)
  171. {
  172. if(!lplpObj)
  173. return E_INVALIDARG;
  174. *lplpObj = NULL;
  175. if (IsEqualIID(riid, IID_IUnknown))
  176. *lplpObj = (LPVOID)(IOEFolderCollection *)this;
  177. else if (IsEqualIID(riid, IID_IDispatch))
  178. *lplpObj = (LPVOID)(IDispatch *)(CBaseDisp *)this;
  179. else if (IsEqualIID(riid, IID_IOEFolderCollection))
  180. *lplpObj = (LPVOID)(IOEFolderCollection *)this;
  181. else
  182. return E_NOINTERFACE;
  183. AddRef();
  184. return NOERROR;
  185. }
  186. HRESULT COEFolderCollection::Init()
  187. {
  188. return InitBaseDisp((LPVOID *)(IOEFolderCollection *)this, IID_IOEFolderCollection, g_pTypeLib);
  189. }
  190. // *** COEFolderCollection **
  191. HRESULT COEFolderCollection::put_length(long v)
  192. {
  193. return E_NOTIMPL;
  194. }
  195. HRESULT COEFolderCollection::get_length(long * p)
  196. {
  197. FOLDERINFO fi;
  198. *p = 0;
  199. Assert(g_pStore);
  200. if (!FAILED(g_pStore->GetFolderInfo(FOLDERID_LOCAL_STORE, &fi)))
  201. *p = fi.cChildren;
  202. return S_OK;
  203. }
  204. HRESULT COEFolderCollection::get__newEnum(IUnknown **p)
  205. {
  206. return E_NOTIMPL;
  207. }
  208. HRESULT COEFolderCollection::item(VARIANT name, VARIANT index, IDispatch** ppdisp)
  209. {
  210. switch(name.vt)
  211. {
  212. case VT_BSTR:
  213. return FindFolderByName(name.bstrVal, ppdisp);
  214. case VT_I4:
  215. return FindFolderByIndex(name.lVal, ppdisp);
  216. }
  217. return E_NOTIMPL;
  218. }
  219. HRESULT COEFolderCollection::FindFolderByName(BSTR bstrName, IDispatch** ppdisp)
  220. {
  221. HRESULT hr=E_FAIL;
  222. IMessageFolder *pFolder;
  223. if (FindFolder(bstrName, NULL, &pFolder)==S_OK)
  224. {
  225. hr = CreateOEFolder(pFolder, ppdisp);
  226. pFolder->Release();
  227. }
  228. return hr;
  229. }
  230. HRESULT COEFolderCollection::FindFolderByIndex(LONG lIndex, IDispatch **ppdisp)
  231. {
  232. HRESULT hr=E_FAIL;
  233. IMessageFolder *pFolder;
  234. *ppdisp=NULL;
  235. if (FindFolder(NULL, lIndex, &pFolder)==S_OK)
  236. {
  237. hr = CreateOEFolder(pFolder, ppdisp);
  238. pFolder->Release();
  239. }
  240. return hr;
  241. }
  242. /*
  243. * C O E F o l d e r
  244. */
  245. HRESULT CreateOEFolder(IMessageFolder *pFolder, IDispatch **ppdisp)
  246. {
  247. COEFolder *pNew;
  248. HRESULT hr;
  249. pNew = new COEFolder();
  250. if (!pNew)
  251. return E_OUTOFMEMORY;
  252. hr = pNew->Init(pFolder);
  253. if (FAILED(hr))
  254. goto error;
  255. hr = pNew->QueryInterface(IID_IDispatch, (LPVOID *)ppdisp);
  256. error:
  257. ReleaseObj(pNew);
  258. return hr;
  259. }
  260. COEFolder::COEFolder()
  261. {
  262. m_cRef=1;
  263. m_pFolder = NULL;
  264. m_pMessages=NULL;
  265. CoIncrementInit("COEFolder::COEFolder", MSOEAPI_START_SHOWERRORS, NULL, NULL);
  266. }
  267. COEFolder::~COEFolder()
  268. {
  269. ReleaseObj(m_pFolder);
  270. ReleaseObj(m_pMessages);
  271. CoDecrementInit("COEFolder::COEFolder", NULL);
  272. }
  273. HRESULT COEFolder::PrivateQueryInterface(REFIID riid, LPVOID *lplpObj)
  274. {
  275. if(!lplpObj)
  276. return E_INVALIDARG;
  277. *lplpObj = NULL;
  278. if (IsEqualIID(riid, IID_IUnknown))
  279. *lplpObj = (LPVOID)(IOEFolder *)this;
  280. else if (IsEqualIID(riid, IID_IDispatch))
  281. *lplpObj = (LPVOID)(IDispatch *)(CBaseDisp *)this;
  282. else if (IsEqualIID(riid, IID_IOEFolder))
  283. *lplpObj = (LPVOID)(IOEFolder *)this;
  284. else if (IsEqualIID(riid, IID_OLEDBSimpleProvider))
  285. *lplpObj = (LPVOID)(OLEDBSimpleProvider *)this;
  286. else
  287. return E_NOINTERFACE;
  288. AddRef();
  289. return NOERROR;
  290. }
  291. HRESULT COEFolder::Init(IMessageFolder *pFolder)
  292. {
  293. FOLDERID dwFolder;
  294. ReplaceInterface(m_pFolder, pFolder);
  295. if (FAILED(pFolder->GetFolderId(&dwFolder)) ||
  296. FAILED(g_pStore->GetFolderInfo(dwFolder, &m_fi)))
  297. return E_FAIL;
  298. return InitBaseDisp((LPVOID *)(IOEFolder *)this, IID_IOEFolder, g_pTypeLib);
  299. }
  300. // *** COEFolder**
  301. HRESULT COEFolder::get_messages(IOEMessageCollection **p)
  302. {
  303. COEMessageCollection *pNew=NULL;
  304. HRESULT hr=S_OK;
  305. *p = NULL;
  306. if (!m_pMessages)
  307. {
  308. pNew = new COEMessageCollection(NULL);
  309. if (!pNew)
  310. return E_OUTOFMEMORY;
  311. hr = pNew->Init(m_pFolder);
  312. if (FAILED(hr))
  313. goto error;
  314. m_pMessages = (IOEMessageCollection *)pNew;
  315. pNew = NULL; // don't free
  316. }
  317. *p = m_pMessages;
  318. m_pMessages->AddRef();
  319. error:
  320. ReleaseObj(pNew);
  321. return S_OK;
  322. }
  323. HRESULT COEFolder::get_name(BSTR *pbstr)
  324. {
  325. *pbstr = NULL;
  326. return HrLPSZToBSTR(m_fi.szName, pbstr);
  327. }
  328. HRESULT COEFolder::put_name(BSTR bstr)
  329. {
  330. return E_NOTIMPL;
  331. }
  332. HRESULT COEFolder::get_size(LONG *pl)
  333. {
  334. *pl = 999;//;m_fi.cbUsed;
  335. return S_OK;
  336. }
  337. HRESULT COEFolder::get_unread(LONG *pl)
  338. {
  339. *pl = m_fi.cUnread;
  340. return S_OK;
  341. }
  342. HRESULT COEFolder::get_id(LONG *pl)
  343. {
  344. *pl = (LONG)m_fi.idFolder;
  345. return S_OK;
  346. }
  347. HRESULT COEFolder::get_count(LONG *pl)
  348. {
  349. *pl = m_fi.cMessages;
  350. return S_OK;
  351. }
  352. HRESULT FindFolder(BSTR bstr, LONG lIndex, IMessageFolder **ppFolder)
  353. {
  354. FOLDERID idFolder=0;
  355. HRESULT hr=E_FAIL;
  356. TCHAR szFolder[MAX_PATH];
  357. LONG c=0;
  358. FOLDERINFO fi;
  359. if (bstr)
  360. WideCharToMultiByte(CP_ACP, 0, (WCHAR*)bstr, -1, szFolder, MAX_PATH, NULL, NULL);
  361. if (!FAILED(g_pStore->GetFolderInfo(FOLDERID_LOCAL_STORE, &fi)) &&
  362. !FAILED(g_pStore->GetFolderInfo(fi.idChild, &fi)))
  363. {
  364. do
  365. {
  366. // walk immediate children
  367. if (bstr)
  368. {
  369. if (lstrcmp(fi.szName, szFolder)==0)
  370. {
  371. idFolder = fi.idFolder;
  372. break;
  373. }
  374. }
  375. else
  376. {
  377. if (lIndex == c++)
  378. {
  379. idFolder = fi.idFolder;
  380. break;
  381. }
  382. }
  383. }
  384. while (!FAILED(g_pStore->GetFolderInfo(fi.idSibling, &fi)));
  385. }
  386. if (idFolder)
  387. hr = g_pStore->OpenFolder(idFolder, ppFolder);
  388. return hr;
  389. }
  390. /*
  391. * C O E M e s s a g e C o l l e c t i o n
  392. */
  393. COEMessageCollection::COEMessageCollection(IUnknown *pUnkOuter)
  394. {
  395. m_cRef=1;
  396. m_pFolder=NULL;
  397. m_pTable=0;
  398. CoIncrementInit("COEMessageCollection::COEMessageCollection", MSOEAPI_START_SHOWERRORS, NULL, NULL);
  399. }
  400. COEMessageCollection::~COEMessageCollection()
  401. {
  402. ReleaseObj(m_pFolder);
  403. ReleaseObj(m_pTable);
  404. CoDecrementInit("COEMessageCollection::COEMessageCollection", NULL);
  405. }
  406. HRESULT COEMessageCollection::PrivateQueryInterface(REFIID riid, LPVOID *lplpObj)
  407. {
  408. if(!lplpObj)
  409. return E_INVALIDARG;
  410. *lplpObj = NULL;
  411. if (IsEqualIID(riid, IID_IUnknown))
  412. *lplpObj = (LPVOID)(IOEFolderCollection *)this;
  413. else if (IsEqualIID(riid, IID_IDispatch))
  414. *lplpObj = (LPVOID)(IDispatch *)(CBaseDisp *)this;
  415. else if (IsEqualIID(riid, IID_IOEFolderCollection))
  416. *lplpObj = (LPVOID)(IOEFolderCollection *)this;
  417. else
  418. return E_NOINTERFACE;
  419. AddRef();
  420. return NOERROR;
  421. }
  422. HRESULT COEMessageCollection::Init(IMessageFolder *pFolder)
  423. {
  424. FOLDERID idFolder;
  425. CMessageTable *pNew=NULL;
  426. HRESULT hr;
  427. if (!pFolder)
  428. return E_INVALIDARG;
  429. ReplaceInterface(m_pFolder, pFolder);
  430. pFolder->GetFolderId(&idFolder);
  431. pNew = new CMessageTable();
  432. if (pNew == NULL)
  433. return E_OUTOFMEMORY;
  434. hr = pNew->Initialize(idFolder, FALSE);
  435. if (FAILED(hr))
  436. goto error;
  437. hr = pNew->QueryInterface(IID_IMessageTable, (LPVOID *)&m_pTable);
  438. if (FAILED(hr))
  439. goto error;
  440. hr = InitBaseDisp((LPVOID *)(IOEMessageCollection *)this, IID_IOEMessageCollection, g_pTypeLib);
  441. if (FAILED(hr))
  442. goto error;
  443. error:
  444. ReleaseObj(pNew);
  445. return hr;
  446. }
  447. // *** COEMessageCollection **
  448. HRESULT COEMessageCollection::put_length(long v)
  449. {
  450. return E_NOTIMPL;
  451. }
  452. HRESULT COEMessageCollection::get_length(long * pl)
  453. {
  454. *pl = 0;
  455. if (m_pTable)
  456. m_pTable->GetCount(MESSAGE_COUNT_VISIBLE, (ULONG *)pl);
  457. return S_OK;
  458. }
  459. HRESULT COEMessageCollection::get__newEnum(IUnknown **p)
  460. {
  461. return E_NOTIMPL;
  462. }
  463. HRESULT COEMessageCollection::item(VARIANT name, VARIANT index, IDispatch** ppdisp)
  464. {
  465. if (name.vt == VT_I4)
  466. return FindMessageByIndex(name.lVal, ppdisp);
  467. return E_NOTIMPL;
  468. }
  469. HRESULT COEMessageCollection::FindMessageByIndex(LONG l, IDispatch** ppdisp)
  470. {
  471. HRESULT hr = E_FAIL;
  472. MESSAGEINFO msginfo;
  473. POEMSGDATA pMsgData;
  474. if (m_pTable->GetRow(l, &msginfo)==S_OK)
  475. {
  476. if (!MemAlloc((LPVOID *)&pMsgData, sizeof(OEMSGDATA)))
  477. return E_OUTOFMEMORY;
  478. pMsgData->pszSubj = PszDup(msginfo.pszSubject);
  479. pMsgData->pszTo = PszDup(msginfo.pszDisplayTo);
  480. pMsgData->pszCc = PszDup("<not available>");
  481. pMsgData->pszFrom = PszDup(msginfo.pszDisplayFrom);
  482. pMsgData->ftReceived = msginfo.ftReceived;
  483. pMsgData->msgid = msginfo.idMessage;
  484. //m_pFolder->OpenMessage(msginfo.dwMsgId, FALSE, NULL, &pMsg)==S_OK)
  485. // OEMessage frees the data object
  486. hr = CreateOEMessage(NULL, m_pFolder, pMsgData, ppdisp);
  487. if (FAILED(hr))
  488. FreeOEMsgData(pMsgData);
  489. }
  490. return hr;
  491. }
  492. void FreeOEMsgData(POEMSGDATA pMsgData)
  493. {
  494. if (pMsgData)
  495. {
  496. MemFree(pMsgData->pszSubj);
  497. MemFree(pMsgData->pszTo);
  498. MemFree(pMsgData->pszCc);
  499. MemFree(pMsgData->pszFrom);
  500. MemFree(pMsgData);
  501. }
  502. }
  503. /*
  504. * C O E M e s s a g e
  505. */
  506. HRESULT CreateOEMessage(IMimeMessage *pMsg, IMessageFolder *pFolder, OEMSGDATA *pMsgData, IDispatch **ppdisp)
  507. {
  508. COEMessage *pNew;
  509. HRESULT hr;
  510. pNew = new COEMessage();
  511. if (!pNew)
  512. return E_OUTOFMEMORY;
  513. hr = pNew->Init(pMsg, pFolder, pMsgData);
  514. if (FAILED(hr))
  515. goto error;
  516. hr = pNew->QueryInterface(IID_IDispatch, (LPVOID *)ppdisp);
  517. if (FAILED(hr))
  518. goto error;
  519. error:
  520. ReleaseObj(pNew);
  521. return hr;
  522. }
  523. COEMessage::COEMessage()
  524. {
  525. m_cRef=1;
  526. m_pMsg = NULL;
  527. m_pMsgData = NULL;
  528. m_pFolder = NULL;
  529. CoIncrementInit("COEMessage::COEMessage", MSOEAPI_START_SHOWERRORS, NULL, NULL);
  530. }
  531. COEMessage::~COEMessage()
  532. {
  533. FreeOEMsgData(m_pMsgData);
  534. ReleaseObj(m_pMsg);
  535. ReleaseObj(m_pFolder);
  536. CoDecrementInit("COEMessage::COEMessage", NULL);
  537. }
  538. HRESULT COEMessage::PrivateQueryInterface(REFIID riid, LPVOID *lplpObj)
  539. {
  540. if(!lplpObj)
  541. return E_INVALIDARG;
  542. *lplpObj = NULL;
  543. if (IsEqualIID(riid, IID_IUnknown))
  544. *lplpObj = (LPVOID)(IOEMessage *)this;
  545. else if (IsEqualIID(riid, IID_IDispatch))
  546. *lplpObj = (LPVOID)(IDispatch *)(CBaseDisp *)this;
  547. else if (IsEqualIID(riid, IID_IOEMessage))
  548. *lplpObj = (LPVOID)(IOEMessage *)this;
  549. else
  550. return E_NOINTERFACE;
  551. AddRef();
  552. return NOERROR;
  553. }
  554. HRESULT COEMessage::Init(IMimeMessage *pMsg, IMessageFolder *pFolder, OEMSGDATA *pMsgData)
  555. {
  556. ReplaceInterface(m_pFolder, pFolder);
  557. ReplaceInterface(m_pMsg, pMsg);
  558. m_pMsgData = pMsgData;
  559. return InitBaseDisp((LPVOID *)(IOEMessage *)this, IID_IOEMessage, g_pTypeLib);
  560. }
  561. // *** COEMessage **
  562. HRESULT COEMessage::get_subject(BSTR *pbstr)
  563. {
  564. LPSTR psz;
  565. if (!m_pMsg)
  566. {
  567. HrLPSZToBSTR(m_pMsgData->pszSubj, pbstr);
  568. return S_OK;
  569. }
  570. if (MimeOleGetBodyPropA(m_pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_SUBJECT), NOFLAGS, &psz)==S_OK)
  571. {
  572. HrLPSZToBSTR(psz, pbstr);
  573. MemFree(psz);
  574. return S_OK;
  575. }
  576. return E_FAIL;
  577. }
  578. HRESULT COEMessage::put_subject(BSTR bstr)
  579. {
  580. LPSTR psz;
  581. BindToMessage();
  582. if (HrBSTRToLPSZ(CP_ACP, bstr, &psz)==S_OK)
  583. {
  584. MimeOleSetBodyPropA(m_pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_SUBJECT), NOFLAGS, psz);
  585. MemFree(psz);
  586. }
  587. return S_OK;
  588. }
  589. HRESULT COEMessage::get_to(BSTR *pbstr)
  590. {
  591. LPSTR psz;
  592. *pbstr = NULL;
  593. if (!m_pMsg)
  594. {
  595. HrLPSZToBSTR(m_pMsgData->pszTo, pbstr);
  596. return S_OK;
  597. }
  598. if (m_pMsg->GetAddressFormat(IAT_TO, AFT_DISPLAY_FRIENDLY, &psz)==S_OK)
  599. {
  600. HrLPSZToBSTR(psz, pbstr);
  601. MemFree(psz);
  602. }
  603. return S_OK;
  604. }
  605. HRESULT COEMessage::put_to(BSTR bstr)
  606. {
  607. LPSTR psz;
  608. BindToMessage();
  609. if (HrBSTRToLPSZ(CP_ACP, bstr, &psz)==S_OK)
  610. {
  611. MimeOleSetBodyPropA(m_pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_TO), NOFLAGS, psz);
  612. MemFree(psz);
  613. }
  614. return S_OK;
  615. }
  616. HRESULT COEMessage::get_cc(BSTR *pbstr)
  617. {
  618. LPSTR psz;
  619. if (!m_pMsg)
  620. {
  621. HrLPSZToBSTR(m_pMsgData->pszCc, pbstr);
  622. return S_OK;
  623. }
  624. *pbstr = NULL;
  625. if (m_pMsg->GetAddressFormat(IAT_CC, AFT_DISPLAY_FRIENDLY, &psz)==S_OK)
  626. {
  627. HrLPSZToBSTR(psz, pbstr);
  628. MemFree(psz);
  629. }
  630. return S_OK;
  631. }
  632. HRESULT COEMessage::put_cc(BSTR bstr)
  633. {
  634. LPSTR psz;
  635. BindToMessage();
  636. if (HrBSTRToLPSZ(CP_ACP, bstr, &psz)==S_OK)
  637. {
  638. MimeOleSetBodyPropA(m_pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_CC), NOFLAGS, psz);
  639. MemFree(psz);
  640. }
  641. return S_OK;
  642. }
  643. HRESULT COEMessage::get_sender(BSTR *pbstr)
  644. {
  645. LPSTR psz;
  646. *pbstr = NULL;
  647. if (!m_pMsg)
  648. {
  649. HrLPSZToBSTR(m_pMsgData->pszFrom, pbstr);
  650. return S_OK;
  651. }
  652. if (m_pMsg->GetAddressFormat(IAT_FROM, AFT_DISPLAY_FRIENDLY, &psz)==S_OK)
  653. {
  654. HrLPSZToBSTR(psz, pbstr);
  655. MemFree(psz);
  656. }
  657. return S_OK;
  658. }
  659. HRESULT COEMessage::put_sender(BSTR bstr)
  660. {
  661. LPSTR psz;
  662. BindToMessage();
  663. if (HrBSTRToLPSZ(CP_ACP, bstr, &psz)==S_OK)
  664. {
  665. MimeOleSetBodyPropA(m_pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_FROM), NOFLAGS, psz);
  666. MemFree(psz);
  667. }
  668. return S_OK;
  669. }
  670. HRESULT COEMessage::get_text(BSTR *pbstr)
  671. {
  672. IStream *pstm;
  673. BindToMessage();
  674. if (m_pMsg->GetTextBody(TXT_PLAIN, IET_DECODED, &pstm, NULL)==S_OK)
  675. {
  676. HrIStreamToBSTR(GetACP(), pstm, pbstr);
  677. pstm->Release();
  678. return S_OK;
  679. }
  680. return E_FAIL;
  681. }
  682. HRESULT COEMessage::put_text(BSTR bstr)
  683. {
  684. IStream *pstm;
  685. LPSTR psz;
  686. BindToMessage();
  687. if (HrBSTRToLPSZ(CP_ACP, bstr, &psz)==S_OK)
  688. {
  689. if (MimeOleCreateVirtualStream(&pstm)==S_OK)
  690. {
  691. pstm->Write(psz, lstrlen(psz), NULL);
  692. m_pMsg->SetTextBody(TXT_PLAIN, IET_BINARY, NULL, pstm, NULL);
  693. pstm->Release();
  694. }
  695. MemFree(psz);
  696. }
  697. return S_OK;
  698. }
  699. HRESULT COEMessage::get_html(BSTR *pbstr)
  700. {
  701. IStream *pstm;
  702. BindToMessage();
  703. if (m_pMsg->GetTextBody(TXT_HTML, IET_DECODED, &pstm, NULL)==S_OK)
  704. {
  705. HrIStreamToBSTR(GetACP(), pstm, pbstr);
  706. pstm->Release();
  707. return S_OK;
  708. }
  709. return E_FAIL;
  710. }
  711. HRESULT COEMessage::put_html(BSTR bstr)
  712. {
  713. IStream *pstm;
  714. LPSTR psz;
  715. if (HrBSTRToLPSZ(CP_ACP, bstr, &psz)==S_OK)
  716. {
  717. if (MimeOleCreateVirtualStream(&pstm)==S_OK)
  718. {
  719. pstm->Write(psz, lstrlen(psz), NULL);
  720. m_pMsg->SetTextBody(TXT_HTML, IET_BINARY, NULL, pstm, NULL);
  721. pstm->Release();
  722. }
  723. MemFree(psz);
  724. }
  725. return S_OK;
  726. }
  727. HRESULT COEMessage::get_url(BSTR *pbstr)
  728. {
  729. IStream *pstm;
  730. BindToMessage();
  731. // BUGBUGBUG: this is a terrible hack also. We can't get a persistent URL moniker to
  732. // the MHTML document (not yet investigated), so for the purpose of this demo-code
  733. // we'll use a tmp file
  734. if (m_pMsg->GetMessageSource(&pstm, 0)==S_OK)
  735. {
  736. WriteStreamToFile(pstm, "c:\\oe_temp$.eml", CREATE_ALWAYS, GENERIC_WRITE);
  737. pstm->Release();
  738. }
  739. *pbstr = SysAllocString(L"c:\\oe_temp$.eml");
  740. return S_OK;
  741. }
  742. HRESULT COEMessage::get_date(BSTR *pbstr)
  743. {
  744. PROPVARIANT pv;
  745. TCHAR rgch[MAX_PATH];
  746. FILETIME *pft=0;
  747. *pbstr = NULL;
  748. if (!m_pMsg)
  749. {
  750. pft = &m_pMsgData->ftReceived;
  751. }
  752. else
  753. {
  754. // Get Receive Time
  755. pv.vt = VT_FILETIME;
  756. if (SUCCEEDED(m_pMsg->GetProp(PIDTOSTR(PID_ATT_RECVTIME), 0, &pv)))
  757. pft = &pv.filetime;
  758. }
  759. if (pft)
  760. {
  761. *rgch=0;
  762. CchFileTimeToDateTimeSz(pft, rgch, sizeof(rgch)/sizeof(TCHAR), DTM_NOSECONDS);
  763. HrLPSZToBSTR(rgch, pbstr);
  764. }
  765. return S_OK;
  766. }
  767. HRESULT COEMessage::send()
  768. {
  769. TCHAR sz[MAX_PATH];
  770. // use default account to send
  771. if (SUCCEEDED(g_pAcctMan->GetDefaultAccountName(ACCT_MAIL, sz, ARRAYSIZE(sz))))
  772. {
  773. PROPVARIANT rUserData;
  774. rUserData.vt = VT_LPSTR;
  775. rUserData.pszVal = sz;
  776. m_pMsg->SetProp(PIDTOSTR(PID_ATT_ACCOUNT), NOFLAGS, &rUserData);
  777. }
  778. HrSendMailToOutBox(g_hwndInit, m_pMsg, TRUE, TRUE);
  779. return S_OK;
  780. }
  781. HRESULT COEMessage::BindToMessage()
  782. {
  783. if (m_pMsg)
  784. return S_OK;
  785. Assert (m_pFolder && m_pMsgData);
  786. return m_pFolder->OpenMessage(m_pMsgData->msgid, NULL, &m_pMsg, NULL);
  787. }
  788. COEMsgTable::COEMsgTable()
  789. {
  790. m_cRef=1;
  791. m_pTable=0;
  792. m_pDSListen=0;
  793. m_fAsc=TRUE;
  794. m_col=COLUMN_RECEIVED;
  795. m_pDataSrcListener=0;
  796. CoIncrementInit("COEMsgTable::COEMsgTable", MSOEAPI_START_SHOWERRORS, NULL, NULL);
  797. }
  798. COEMsgTable::~COEMsgTable()
  799. {
  800. ReleaseObj(m_pTable);
  801. ReleaseObj(m_pDSListen);
  802. ReleaseObj(m_pDataSrcListener);
  803. CoDecrementInit("COEMsgTable::COEMsgTable", NULL);
  804. }
  805. HRESULT COEMsgTable::PrivateQueryInterface(REFIID riid, LPVOID *lplpObj)
  806. {
  807. if(!lplpObj)
  808. return E_INVALIDARG;
  809. *lplpObj = NULL;
  810. if (IsEqualIID(riid, IID_IUnknown))
  811. *lplpObj = (LPVOID)(OLEDBSimpleProvider *)this;
  812. else if (IsEqualIID(riid, IID_OLEDBSimpleProvider))
  813. *lplpObj = (LPVOID)(OLEDBSimpleProvider *)this;
  814. else if (IsEqualIID(riid, IID_IDispatch))
  815. *lplpObj = (LPVOID)(IDispatch *)(CBaseDisp *)this;
  816. else if (IsEqualIID(riid, IID_IDispatchEx))
  817. *lplpObj = (LPVOID)(IDispatchEx *)this;
  818. else if (IsEqualIID(riid, IID_IOEMsgList))
  819. *lplpObj = (LPVOID)(IOEMsgList *)this;
  820. else
  821. {
  822. DbgPrintInterface(riid, "COEMsgTable::", 1024);
  823. return E_NOINTERFACE;
  824. }
  825. AddRef();
  826. return NOERROR;
  827. }
  828. HRESULT COEMsgTable::Init()
  829. {
  830. FOLDERINFO fi;
  831. HRESULT hr;
  832. g_pStore->GetSpecialFolderInfo(FOLDERID_LOCAL_STORE, FOLDER_INBOX, &fi);
  833. // hr = CoCreateInstance(CLSID_MessageTable, NULL, CLSCTX_INPROC_SERVER,
  834. IID_IMessageTable, (LPVOID *)&m_pTable);
  835. if (FAILED(hr))
  836. goto error;
  837. hr = m_pTable->Initialize(fi.idFolder, FALSE);
  838. if (FAILED(hr))
  839. goto error;
  840. hr = EnsureTypeLib();
  841. if (FAILED(hr))
  842. goto error;
  843. hr = InitBaseDisp((LPVOID *)(IOEMsgList *)this, IID_IOEMsgList, g_pTypeLib);
  844. error:
  845. return hr;
  846. }
  847. HRESULT COEMsgTable::getRowCount(long *pcRows)
  848. {
  849. *pcRows = 0;
  850. if (m_pTable)
  851. m_pTable->GetCount(MESSAGE_COUNT_VISIBLE, (ULONG *)pcRows);
  852. return S_OK;
  853. }
  854. HRESULT COEMsgTable::getColumnCount(long *pcColumns)
  855. {
  856. *pcColumns=COLUMN_MAX;
  857. return S_OK;
  858. }
  859. HRESULT COEMsgTable::getRWStatus(long iRow, long iColumn, OSPRW *prwStatus)
  860. {
  861. *prwStatus = OSPRW_READONLY;
  862. return S_OK;
  863. }
  864. HRESULT COEMsgTable::getVariant(long iRow, long iColumn, OSPFORMAT format, VARIANT __RPC_FAR *pVar)
  865. {
  866. MESSAGEINFO msginfo;
  867. LPSTR pszData = NULL;
  868. TCHAR rgch[MAX_PATH];
  869. pVar->vt = VT_NULL;
  870. if (iRow == 0)
  871. {
  872. // return headings if row==0
  873. pVar->vt = VT_BSTR;
  874. pVar->bstrVal = SysAllocString(StringFromColIndex(iColumn-1));
  875. return S_OK;
  876. }
  877. if (m_pTable->GetRow(iRow-1, &msginfo)==S_OK)
  878. {
  879. switch (iColumn-1)
  880. {
  881. case COLUMN_MSGID:
  882. wnsprintf(rgch,ARRAYSIZE(rgch), "%d", msginfo.idMessage);
  883. pszData = rgch;
  884. break;
  885. case COLUMN_SUBJECT:
  886. pszData = msginfo.pszSubject;
  887. break;
  888. case COLUMN_TO:
  889. pszData = msginfo.pszDisplayTo;
  890. break;
  891. case COLUMN_FROM:
  892. pszData = msginfo.pszDisplayFrom;
  893. break;
  894. case COLUMN_RECEIVED:
  895. pszData = rgch;
  896. *rgch=0;
  897. CchFileTimeToDateTimeSz(&msginfo.ftReceived, rgch, sizeof(rgch)/sizeof(TCHAR), DTM_NOSECONDS);
  898. break;
  899. default:
  900. pVar->vt = VT_NULL;
  901. pVar->lVal = NULL;
  902. return S_OK;
  903. }
  904. }
  905. if (pszData)
  906. {
  907. pVar->vt = VT_BSTR;
  908. HrLPSZToBSTR(pszData, &pVar->bstrVal);
  909. }
  910. else
  911. AssertSz(0, "bad");
  912. return S_OK;
  913. }
  914. HRESULT COEMsgTable::setVariant(long iRow, long iColumn, OSPFORMAT format, VARIANT Var)
  915. {
  916. AssertSz(0, "READONLY Table");
  917. return E_NOTIMPL;
  918. }
  919. HRESULT COEMsgTable::getLocale(BSTR *pbstrLocale)
  920. {
  921. nyi("DATABINDING::getLocale");
  922. return E_NOTIMPL;
  923. }
  924. HRESULT COEMsgTable::deleteRows(long iRow, long cRows, long *pcRowsDeleted)
  925. {
  926. AssertSz(0, "READONLY Table");
  927. return E_NOTIMPL;
  928. }
  929. HRESULT COEMsgTable::insertRows(long iRow, long cRows, long *pcRowsInserted)
  930. {
  931. AssertSz(0, "READONLY Table");
  932. return E_NOTIMPL;
  933. }
  934. HRESULT COEMsgTable::find(long iRowStart, long iColumn, VARIANT val, OSPFIND findFlags, OSPCOMP compType, long *piRowFound)
  935. {
  936. nyi("DATABINDING::find");
  937. return E_NOTIMPL;
  938. }
  939. HRESULT COEMsgTable::addOLEDBSimpleProviderListener(OLEDBSimpleProviderListener *pospIListener)
  940. {
  941. ReplaceInterface(m_pDSListen, pospIListener);
  942. if (pospIListener)
  943. pospIListener->transferComplete(OSPXFER_COMPLETE);
  944. return S_OK;
  945. }
  946. HRESULT COEMsgTable::removeOLEDBSimpleProviderListener(OLEDBSimpleProviderListener *pospIListener)
  947. {
  948. SafeRelease(m_pDSListen);
  949. return S_OK;
  950. }
  951. HRESULT COEMsgTable::isAsync(BOOL *pbAsynch)
  952. {
  953. *pbAsynch = FALSE;
  954. return S_OK;
  955. }
  956. HRESULT COEMsgTable::getEstimatedRows(long *piRows)
  957. {
  958. return getRowCount(piRows);
  959. }
  960. HRESULT COEMsgTable::stopTransfer()
  961. {
  962. return S_OK;
  963. }
  964. HRESULT CreateInstance_OEMsgTable(IUnknown *pUnkOuter, IUnknown **ppUnknown)
  965. {
  966. // Locals
  967. COEMsgTable *pMsgTable=NULL;
  968. HRESULT hr;
  969. if (NULL != pUnkOuter)
  970. return CLASS_E_NOAGGREGATION;
  971. pMsgTable = new COEMsgTable();
  972. if (!pMsgTable)
  973. return E_OUTOFMEMORY;
  974. hr = pMsgTable->Init();
  975. if (FAILED(hr))
  976. goto error;
  977. hr = pMsgTable->QueryInterface(IID_IUnknown, (LPVOID *)ppUnknown);
  978. error:
  979. ReleaseObj(pMsgTable);
  980. return hr;
  981. }
  982. HRESULT COEMsgTable::GetDispID(BSTR bstrName, DWORD grfdex, DISPID *pid)
  983. {
  984. return DispGetIDsOfNames(m_pTypeInfo, &bstrName, 1, pid);
  985. }
  986. HRESULT COEMsgTable::InvokeEx(DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
  987. {
  988. switch (id)
  989. {
  990. case DISPID_MSDATASRCINTERFACE:
  991. pvarRes->vt = VT_UNKNOWN;
  992. pvarRes->punkVal = (OLEDBSimpleProvider *)this;
  993. AddRef();
  994. return S_OK;
  995. case DISPID_ADVISEDATASRCCHANGEEVENT:
  996. if (pdp->cArgs == 1 && pdp->rgvarg[0].vt == VT_UNKNOWN)
  997. {
  998. ReplaceInterface(m_pDataSrcListener, (DataSourceListener *)pdp->rgvarg[0].punkVal);
  999. return S_OK;
  1000. }
  1001. else
  1002. return E_INVALIDARG;
  1003. default:
  1004. return DispInvoke(m_pUnkInvoke, m_pTypeInfo, id, wFlags, pdp, pvarRes, pei, NULL);
  1005. }
  1006. return E_NOTIMPL;
  1007. }
  1008. HRESULT COEMsgTable::DeleteMemberByName(BSTR bstrName, DWORD grfdex)
  1009. {
  1010. return E_NOTIMPL;
  1011. }
  1012. HRESULT COEMsgTable::DeleteMemberByDispID(DISPID id)
  1013. {
  1014. return E_NOTIMPL;
  1015. }
  1016. HRESULT COEMsgTable::GetMemberProperties(DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
  1017. {
  1018. return E_NOTIMPL;
  1019. }
  1020. HRESULT COEMsgTable::GetMemberName(DISPID id, BSTR *pbstrName)
  1021. {
  1022. return E_NOTIMPL;
  1023. }
  1024. HRESULT COEMsgTable::GetNextDispID(DWORD grfdex, DISPID id, DISPID *pid)
  1025. {
  1026. return E_NOTIMPL;
  1027. }
  1028. HRESULT COEMsgTable::GetNameSpaceParent(IUnknown **ppunk)
  1029. {
  1030. return E_NOTIMPL;
  1031. }
  1032. HRESULT COEMsgTable::put_sortColumn(BSTR bstr)
  1033. {
  1034. FOLDERSORTINFO fsi={0};
  1035. m_col = (COLUMN_ID)ColIndexFromString(bstr);
  1036. fsi.idSort = m_col;
  1037. fsi.dwFlags = m_fAsc ? SORT_ASCENDING : 0;
  1038. fsi.fForceSort = FALSE;
  1039. if (m_pTable)
  1040. m_pTable->SetSortInfo(&fsi);
  1041. return S_OK;
  1042. }
  1043. HRESULT COEMsgTable::get_sortColumn(BSTR *pbstr)
  1044. {
  1045. *pbstr = SysAllocString(StringFromColIndex(m_col));
  1046. return S_OK;
  1047. }
  1048. HRESULT COEMsgTable::put_sortDirection(VARIANT_BOOL v)
  1049. {
  1050. FOLDERSORTINFO fsi;
  1051. m_fAsc = (v == VARIANT_TRUE);
  1052. fsi.idSort = m_col;
  1053. fsi.dwFlags = m_fAsc ? SORT_ASCENDING : 0;
  1054. fsi.fForceSort = FALSE;
  1055. if (m_pTable)
  1056. m_pTable->SetSortInfo(&fsi);
  1057. return S_OK;
  1058. }
  1059. HRESULT COEMsgTable::get_sortDirection(VARIANT_BOOL *pv)
  1060. {
  1061. *pv = m_fAsc ? VARIANT_TRUE : VARIANT_FALSE;
  1062. return S_OK;
  1063. }
  1064. HRESULT COEMsgTable::test()
  1065. {
  1066. if (m_pDataSrcListener)
  1067. m_pDataSrcListener->dataMemberChanged(NULL);
  1068. return S_OK;
  1069. }
  1070. static const WCHAR c_szOESubjW[] = L"oeSubj",
  1071. c_szOEToW[] = L"oeTo",
  1072. c_szOEFromW[] = L"oeFrom",
  1073. c_szOEMsgIdW[] = L"oeMsgId",
  1074. c_szOEReceivedW[] = L"oeDate";
  1075. DWORD ColIndexFromString(LPWSTR pszW)
  1076. {
  1077. if (StrCmpIW(c_szOESubjW, pszW)==0)
  1078. return COLUMN_SUBJECT;
  1079. else
  1080. if (StrCmpIW(c_szOEToW, pszW)==0)
  1081. return COLUMN_TO;
  1082. else
  1083. if (StrCmpIW(c_szOEReceivedW, pszW)==0)
  1084. return COLUMN_RECEIVED;
  1085. else
  1086. if (StrCmpIW(c_szOEFromW, pszW)==0)
  1087. return COLUMN_FROM;
  1088. else
  1089. if (StrCmpIW(c_szOEMsgIdW, pszW)==0)
  1090. return COLUMN_MSGID;
  1091. return (DWORD)-1;
  1092. }
  1093. LPWSTR StringFromColIndex(DWORD dw)
  1094. {
  1095. switch (dw)
  1096. {
  1097. case COLUMN_MSGID:
  1098. return (LPWSTR)c_szOEMsgIdW;
  1099. case COLUMN_SUBJECT:
  1100. return (LPWSTR)c_szOESubjW;
  1101. case COLUMN_TO:
  1102. return (LPWSTR)c_szOEToW;
  1103. case COLUMN_FROM:
  1104. return (LPWSTR)c_szOEFromW;
  1105. case COLUMN_RECEIVED:
  1106. return (LPWSTR)c_szOEReceivedW;
  1107. }
  1108. return NULL;
  1109. }