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.

1930 lines
56 KiB

  1. #include "pch.hxx"
  2. #include "msgsite.h"
  3. #include "secutil.h"
  4. #include "mailutil.h"
  5. #include "conman.h"
  6. #include "newfldr.h"
  7. #include "storutil.h"
  8. #include "msoeobj.h"
  9. #include "regutil.h"
  10. #include "mapiutil.h"
  11. #include "browser.h"
  12. #include "receipts.h"
  13. #include "shlwapip.h"
  14. #include "msoert.h"
  15. // ****************************************
  16. COEMsgSite::COEMsgSite()
  17. {
  18. m_pMsg = NULL;
  19. m_pOrigMsg = NULL;
  20. m_pStoreCB = NULL;
  21. m_pMsgTable = NULL;
  22. m_pListSelect = NULL;
  23. m_pCBMsgFolder = NULL;
  24. m_fCBCopy = FALSE;
  25. m_fCBSavedInDrafts = FALSE;
  26. m_fCBSaveInFolderAndDelOrig = FALSE;
  27. m_fGotNewID = FALSE;
  28. m_fHeaderOnly = FALSE;
  29. m_fValidMessage = FALSE;
  30. m_fNeedToLoadMsg = TRUE;
  31. m_fHaveCBMessageID = TRUE;
  32. m_fThreadingEnabled = FALSE;
  33. m_fReloadMessageFlag = TRUE;
  34. m_dwArfFlags = 0;
  35. m_dwMSAction = MSA_IDLE;
  36. m_dwCMFState = CMF_UNINITED;
  37. m_dwOrigFolderIsImap = OFIMAP_UNDEFINED;
  38. m_cRef = 1;
  39. m_FolderID = FOLDERID_INVALID;
  40. m_CBFolderID = FOLDERID_INVALID;
  41. m_MessageID = 0;
  42. m_CBMessageID = 0;
  43. m_NewMessageID = 0;
  44. *m_rgwchFileName = 0;
  45. m_pFolderReleaseOnComplete = NULL;
  46. m_dwMDNFlags = 0;
  47. if (!!DwGetOption(OPT_MDN_SEND_REQUEST))
  48. m_dwMDNFlags |= MDN_REQUEST;
  49. }
  50. // ****************************************
  51. COEMsgSite::~COEMsgSite()
  52. {
  53. Assert(!m_pMsg);
  54. Assert(!m_pOrigMsg);
  55. Assert(!m_pMsgTable);
  56. Assert(!m_pStoreCB);
  57. Assert(!m_pListSelect);
  58. AssertSz(!m_pCBMsgFolder, "Who missed freeing this?");
  59. ReleaseObj(m_pFolderReleaseOnComplete);
  60. }
  61. // ****************************************
  62. HRESULT COEMsgSite::QueryInterface(REFIID riid, LPVOID FAR *lplpObj)
  63. {
  64. if(!lplpObj)
  65. return E_INVALIDARG;
  66. *lplpObj = NULL;
  67. if (IsEqualIID(riid, IID_IUnknown))
  68. *lplpObj = (LPVOID)this;
  69. else
  70. return E_NOINTERFACE;
  71. AddRef();
  72. return NOERROR;
  73. }
  74. // ****************************************
  75. ULONG COEMsgSite::AddRef()
  76. {
  77. return ++m_cRef;
  78. }
  79. // ****************************************
  80. ULONG COEMsgSite::Release()
  81. {
  82. if(--m_cRef==0)
  83. {
  84. delete this;
  85. return 0;
  86. }
  87. return m_cRef;
  88. }
  89. // ****************************************
  90. BOOL COEMsgSite::ThreadingEnabled(void)
  91. {
  92. BOOL fEnabled = FALSE;
  93. FOLDERSORTINFO SortInfo;
  94. Assert(OEMSIT_MSG_TABLE == m_dwInitType);
  95. if (SUCCEEDED(m_pMsgTable->GetSortInfo(&SortInfo)))
  96. fEnabled = SortInfo.fThreaded;
  97. return fEnabled;
  98. }
  99. // ****************************************
  100. HRESULT COEMsgSite::Init(INIT_MSGSITE_STRUCT *pInitStruct)
  101. {
  102. // WARNING!!! pStoreCB will not have been setup by this point.
  103. // Use it in this function only if you are sure things will work.
  104. // For instance, the hwnd will not get setup yet so GetCallbackHwnd
  105. // will not work appropriatly.
  106. Assert(pInitStruct);
  107. HRESULT hr = S_OK;
  108. m_dwInitType = pInitStruct->dwInitType;
  109. m_fValidMessage = TRUE;
  110. switch (m_dwInitType)
  111. {
  112. case OEMSIT_MSG_TABLE:
  113. {
  114. Assert (m_pMsgTable==NULL);
  115. ReplaceInterface(m_pMsgTable, pInitStruct->initTable.pMsgTable);
  116. if (m_pMsgTable)
  117. m_pMsgTable->ConnectionAddRef();
  118. ReplaceInterface(m_pListSelect, pInitStruct->initTable.pListSelect);
  119. hr = m_pMsgTable->GetRowMessageId(pInitStruct->initTable.rowIndex, &m_MessageID);
  120. if (FAILED(hr))
  121. break;
  122. m_FolderID = pInitStruct->folderID;
  123. m_fThreadingEnabled = ThreadingEnabled();
  124. break;
  125. }
  126. case OEMSIT_STORE:
  127. AssertSz(FALSE, "Can't init using the store...");
  128. hr = E_UNEXPECTED;
  129. break;
  130. case OEMSIT_FAT:
  131. StrCpyNW(m_rgwchFileName, pInitStruct->pwszFile, ARRAYSIZE(m_rgwchFileName));
  132. break;
  133. case OEMSIT_MSG:
  134. m_FolderID = pInitStruct->folderID;
  135. ReplaceInterface(m_pMsg, pInitStruct->pMsg);
  136. break;
  137. case OEMSIT_VIRGIN:
  138. m_FolderID = pInitStruct->folderID;
  139. break;
  140. default:
  141. hr = E_UNEXPECTED;
  142. break;
  143. }
  144. /* ~~~ Took this out of mailnote.cpp HrInit(pcni) code. How do we get this to work???
  145. ~~~ It is suppose to notify us if a folder has been deleted. In that case, we would
  146. ~~~ need to convert the msgSite to a msg based msgsite.
  147. if (m_pMsgTable)
  148. m_pMsgTable->Advise(GetCallbackHwnd());
  149. if (FAILED(hr = CreateNotify(&m_pFldrDelNotify)) ||
  150. FAILED(hr = m_pFldrDelNotify->Initialize((TCHAR *)c_szFolderDelNotify)) ||
  151. FAILED(hr = m_pFldrDelNotify->Register(GetCallbackHwnd(), g_hwndInit, FALSE)))
  152. goto error;
  153. */
  154. return hr;
  155. }
  156. // ****************************************
  157. HRESULT COEMsgSite::GetStatusFlags(DWORD *pdwFlags)
  158. {
  159. DWORD dwNewFlags = OEMSF_CAN_COPY | OEMSF_CAN_SAVE;
  160. if (!!(m_dwMDNFlags & MDN_REQUEST))
  161. {
  162. dwNewFlags |= OEMSF_MDN_REQUEST;
  163. }
  164. switch (m_dwInitType)
  165. {
  166. case OEMSIT_MSG_TABLE:
  167. case OEMSIT_STORE:
  168. {
  169. FOLDERTYPE folderType = GetFolderType(m_FolderID);
  170. dwNewFlags |= OEMSF_CAN_MARK | OEMSF_FROM_STORE;
  171. // GetMessageFlags is fairly intensive to be called as often as GetStatusFlags
  172. // is called. Since this flag really only matters at load time, we will only go
  173. // and get the value after a load from store. Otherwise, we will use the
  174. // cached value from m_fSecUI.
  175. if (m_fReloadMessageFlag)
  176. {
  177. m_dwArfFlags = 0;
  178. GetMessageFlags(&m_dwArfFlags);
  179. m_fReloadMessageFlag = FALSE;
  180. }
  181. if (0 == (m_dwArfFlags & ARF_READ))
  182. dwNewFlags |= OEMSF_UNREAD;
  183. // If we came from a store and we are a new folder, then can't delete
  184. if (FOLDER_NEWS != folderType)
  185. {
  186. dwNewFlags |= OEMSF_CAN_MOVE;
  187. if (0 == (m_dwArfFlags & ARF_ENDANGERED))
  188. dwNewFlags |= OEMSF_CAN_DELETE;
  189. if ((FOLDER_HTTPMAIL == folderType) || (FOLDER_IMAP == folderType))
  190. dwNewFlags |= OEMSF_RULESNOTENABLED;
  191. }
  192. if (OEMSIT_MSG_TABLE == m_dwInitType)
  193. {
  194. dwNewFlags |= OEMSF_CAN_NEXT|OEMSF_CAN_PREV;
  195. if (m_fThreadingEnabled)
  196. dwNewFlags |= OEMSF_THREADING_ENABLED;
  197. }
  198. if (m_dwArfFlags & ARF_UNSENT)
  199. {
  200. // If we are table based, need to do extra checking for IMAP message in find folder
  201. if (OEMSIT_MSG_TABLE == m_dwInitType)
  202. {
  203. if (OFIMAP_UNDEFINED == m_dwOrigFolderIsImap)
  204. {
  205. FOLDERINFO fi;
  206. if (SUCCEEDED(g_pStore->GetFolderInfo(m_FolderID, &fi)))
  207. {
  208. // If is a find folder, check to see if message is IMAP
  209. if (FOLDER_FINDRESULTS & (fi.dwFlags))
  210. {
  211. // Get original folder for this message (ie, not the find folder)
  212. IMessageFolder *pMsgFolder = NULL;
  213. if (SUCCEEDED(g_pStore->OpenFolder(m_FolderID, NULL, NOFLAGS, &pMsgFolder)))
  214. {
  215. // If original folder type is IMAP, then don't set unsent flag
  216. FOLDERID folderID;
  217. if (SUCCEEDED(pMsgFolder->GetMessageFolderId(m_MessageID, &folderID)))
  218. {
  219. FOLDERTYPE origFolderType = GetFolderType(folderID);
  220. if (FOLDER_IMAP != origFolderType)
  221. {
  222. m_dwOrigFolderIsImap = OFIMAP_FALSE;
  223. dwNewFlags |= OEMSF_UNSENT;
  224. }
  225. else
  226. m_dwOrigFolderIsImap = OFIMAP_TRUE;
  227. }
  228. pMsgFolder->Release();
  229. }
  230. }
  231. else
  232. dwNewFlags |= OEMSF_UNSENT;
  233. g_pStore->FreeRecord(&fi);
  234. }
  235. }
  236. else
  237. if (OFIMAP_FALSE == m_dwOrigFolderIsImap)
  238. dwNewFlags |= OEMSF_UNSENT;
  239. }
  240. else
  241. dwNewFlags |= OEMSF_UNSENT;
  242. }
  243. if (0 == (m_dwArfFlags & ARF_NOSECUI))
  244. dwNewFlags |= OEMSF_SEC_UI_ENABLED;
  245. if (m_dwArfFlags & ARF_NEWSMSG)
  246. dwNewFlags |= OEMSF_BASEISNEWS;
  247. break;
  248. }
  249. case OEMSIT_FAT:
  250. {
  251. LPWSTR pwszUnsent = NULL,
  252. pwszExt = PathFindExtensionW(m_rgwchFileName);
  253. dwNewFlags |= OEMSF_CAN_DELETE | OEMSF_CAN_MOVE | OEMSF_SEC_UI_ENABLED;
  254. dwNewFlags |= OEMSF_FROM_FAT;
  255. if (SUCCEEDED(MimeOleGetBodyPropW(m_pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_XUNSENT), NOFLAGS, &pwszUnsent)))
  256. {
  257. if (FALSE == FIsEmptyW(pwszUnsent))
  258. dwNewFlags |= OEMSF_UNSENT;
  259. SafeMemFree(pwszUnsent);
  260. }
  261. if (0 == StrCmpW(pwszExt, c_wszNwsExt))
  262. dwNewFlags |= OEMSF_BASEISNEWS;
  263. break;
  264. }
  265. case OEMSIT_MSG:
  266. dwNewFlags |= OEMSF_FROM_MSG;
  267. break;
  268. case OEMSIT_VIRGIN:
  269. dwNewFlags |= OEMSF_VIRGIN | OEMSF_UNSENT;
  270. break;
  271. }
  272. *pdwFlags = dwNewFlags;
  273. return S_OK;
  274. }
  275. // ****************************************
  276. HRESULT COEMsgSite::DeleteFromStore(DELETEMESSAGEFLAGS dwFlags)
  277. {
  278. HRESULT hr;
  279. AssertSz(!m_pCBMsgFolder, "Someone forgot to release this baby.");
  280. Assert(m_pStoreCB);
  281. hr = g_pStore->OpenFolder(m_FolderID, NULL, NOFLAGS, &m_pCBMsgFolder);
  282. if (SUCCEEDED(hr))
  283. {
  284. MESSAGEIDLIST list;
  285. FOLDERINFO fi;
  286. list.cMsgs = 1;
  287. list.prgidMsg = &m_MessageID;
  288. hr = m_pCBMsgFolder->DeleteMessages(dwFlags, &list, NULL, m_pStoreCB);
  289. if (E_PENDING != hr)
  290. SafeRelease(m_pCBMsgFolder);
  291. }
  292. return hr;
  293. }
  294. // ****************************************
  295. HRESULT COEMsgSite::DeleteFromMsgTable(DELETEMESSAGEFLAGS dwFlags)
  296. {
  297. HRESULT hr;
  298. ROWINDEX iRow = -1,
  299. iNewRow = -1;
  300. AssertSz(m_pMsgTable, "How can you be OEMSIT_MSG_TABLE and not have a table");
  301. m_fGotNewID = FALSE;
  302. hr = m_pMsgTable->GetRowIndex(m_MessageID, &iRow);
  303. if (FAILED(hr))
  304. goto Exit;
  305. if (SUCCEEDED(m_pMsgTable->GetNextRow(iRow, GETNEXT_NEXT, ROWMSG_ALL, 0, &iNewRow)) &&
  306. SUCCEEDED(m_pMsgTable->GetRowMessageId(iNewRow, &m_NewMessageID)))
  307. m_fGotNewID = TRUE;
  308. hr = m_pMsgTable->DeleteRows(dwFlags, 1, &iRow, FALSE, m_pStoreCB);
  309. if (FAILED(hr) && (E_PENDING != hr))
  310. AthMessageBoxW(GetCallbackHwnd(), MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrDeleteMsg), NULL, MB_OK);
  311. Exit:
  312. return hr;
  313. }
  314. // ****************************************
  315. HRESULT COEMsgSite::Delete(DELETEMESSAGEFLAGS dwFlags)
  316. {
  317. HRESULT hr;
  318. m_dwMSAction = MSA_DELETE;
  319. switch (m_dwInitType)
  320. {
  321. case OEMSIT_MSG_TABLE:
  322. hr = DeleteFromMsgTable(dwFlags);
  323. break;
  324. case OEMSIT_STORE:
  325. hr = DeleteFromStore(dwFlags);
  326. m_fValidMessage = FALSE;
  327. break;
  328. case OEMSIT_FAT:
  329. DeleteFileWrapW(m_rgwchFileName);
  330. m_fValidMessage = FALSE;
  331. m_dwMSAction = MSA_IDLE;
  332. break;
  333. // With these two, there is nothing to delete.
  334. case OEMSIT_MSG:
  335. case OEMSIT_VIRGIN:
  336. hr = S_OK;
  337. break;
  338. default:
  339. AssertSz(FALSE, "Weren't prepared to handle this initType");
  340. hr = E_UNEXPECTED;
  341. break;
  342. }
  343. return hr;
  344. }
  345. // ****************************************
  346. HRESULT COEMsgSite::DoNextPrev(BOOL fNext, DWORD dwFlags)
  347. {
  348. HRESULT hr;
  349. if (OEMSIT_MSG_TABLE == m_dwInitType)
  350. {
  351. ROWMESSAGETYPE tyMsg;
  352. ROWINDEX iRow = 0,
  353. iNewRow = 0;
  354. MESSAGEID idNewMark;
  355. GETNEXTFLAGS dwNextFlags = 0;
  356. GETNEXTTYPE tyDir = fNext?GETNEXT_NEXT:GETNEXT_PREVIOUS;
  357. AssertSz(m_pMsgTable, "How can you be OEMSIT_MSG_TABLE and not have a table");
  358. hr = m_pMsgTable->GetRowIndex(m_MessageID, &iRow);
  359. if (FAILED(hr))
  360. goto Exit;
  361. if (dwFlags&OENF_SKIPMAIL)
  362. tyMsg = ROWMSG_MAIL;
  363. else if (dwFlags&OENF_SKIPNEWS)
  364. tyMsg = ROWMSG_NEWS;
  365. else
  366. tyMsg = ROWMSG_ALL;
  367. if (dwFlags&OENF_UNREAD)
  368. dwNextFlags |= GETNEXT_UNREAD;
  369. if (dwFlags&OENF_THREAD)
  370. dwNextFlags |= GETNEXT_THREAD;
  371. hr = m_pMsgTable->GetNextRow(iRow, tyDir, tyMsg, dwNextFlags, &iNewRow);
  372. if (FAILED(hr))
  373. goto Exit;
  374. hr = m_pMsgTable->GetRowMessageId(iNewRow, &idNewMark);
  375. if (FAILED(hr))
  376. goto Exit;
  377. if (m_pListSelect)
  378. m_pListSelect->SetActiveRow(iNewRow);
  379. m_MessageID = idNewMark;
  380. m_fNeedToLoadMsg = TRUE;
  381. }
  382. else
  383. hr = E_UNEXPECTED;
  384. Exit:
  385. AssertSz(E_PENDING != hr, "COEMsgSite::DoNextPrev not setup to handle E_PENDING.");
  386. return hr;
  387. }
  388. // ****************************************
  389. HRESULT COEMsgSite::DoCopyMoveFromMsgToFldr(IMimeMessage *pMsg, BOOL fUnSent)
  390. {
  391. HRESULT hr = E_UNEXPECTED;
  392. if (m_fCBCopy)
  393. {
  394. hr = m_pCBMsgFolder->SaveMessage(NULL, SAVE_MESSAGE_GENID, fUnSent?ARF_UNSENT:NOFLAGS, 0, pMsg, m_pStoreCB);
  395. if (SUCCEEDED(hr))
  396. {
  397. m_dwCMFState = CMF_MSG_TO_FOLDER;
  398. OnComplete(SOT_COPYMOVE_MESSAGE, S_OK);
  399. }
  400. }
  401. else
  402. AssertSz(FALSE, "Can't move a message based on a message. Only copy.");
  403. return hr;
  404. }
  405. // ****************************************
  406. HRESULT COEMsgSite::DoCopyMoveFromStoreToFldr(BOOL fUnSent)
  407. {
  408. HRESULT hr;
  409. MESSAGEID msgID = 0;
  410. hr = SaveMessageInFolder(m_pStoreCB, m_pCBMsgFolder, m_pMsg, fUnSent?ARF_UNSENT:NOFLAGS, &msgID, TRUE);
  411. if (SUCCEEDED(hr))
  412. {
  413. m_dwCMFState = CMF_STORE_TO_FOLDER;
  414. OnComplete(SOT_COPYMOVE_MESSAGE, S_OK);
  415. }
  416. return hr;
  417. }
  418. // ****************************************
  419. HRESULT COEMsgSite::DoCopyMoveFromTableToFldr(void)
  420. {
  421. HRESULT hr;
  422. IMessageFolder *pSrcFolder = NULL;
  423. MESSAGEIDLIST rMsgIDList;
  424. LPMESSAGEINFO pMsgInfo;
  425. ROWINDEX iRow, iNewRow;
  426. MESSAGEID msgID;
  427. FOLDERID folderID = 0;
  428. Assert(m_pStoreCB);
  429. m_fGotNewID = FALSE;
  430. if (m_pFolderReleaseOnComplete != NULL)
  431. return E_FAIL;
  432. hr = g_pStore->OpenFolder(m_FolderID, NULL, NOFLAGS, &pSrcFolder);
  433. if (FAILED(hr))
  434. goto Exit;
  435. hr = m_pMsgTable->GetRowIndex(m_MessageID, &iRow);
  436. if (FAILED(hr))
  437. goto Exit;
  438. // If we are moving, then we need to get the next item in the list
  439. if (!m_fCBCopy && SUCCEEDED(m_pMsgTable->GetNextRow(iRow, GETNEXT_NEXT, ROWMSG_ALL, 0, &iNewRow)) &&
  440. SUCCEEDED(m_pMsgTable->GetRowMessageId(iNewRow, &m_NewMessageID)))
  441. m_fGotNewID = TRUE;
  442. hr = m_pMsgTable->GetRow(iRow, &pMsgInfo);
  443. if (FAILED(hr))
  444. goto Exit;
  445. msgID = pMsgInfo->idMessage;
  446. m_pMsgTable->ReleaseRow(pMsgInfo);
  447. rMsgIDList.cAllocated = 0;
  448. rMsgIDList.cMsgs = 1;
  449. rMsgIDList.prgidMsg = &msgID;
  450. if (SUCCEEDED(m_pCBMsgFolder->GetFolderId(&folderID)))
  451. {
  452. m_CBFolderID = folderID;
  453. m_CBMessageID = msgID;
  454. }
  455. else
  456. {
  457. m_CBFolderID = FOLDERID_INVALID;
  458. m_dwInitType = OEMSIT_MSG;
  459. }
  460. hr = pSrcFolder->CopyMessages(m_pCBMsgFolder, m_fCBCopy?0:COPY_MESSAGE_MOVE, &rMsgIDList, NULL, NULL, m_pStoreCB);
  461. if (SUCCEEDED(hr))
  462. {
  463. m_dwCMFState = CMF_TABLE_TO_FOLDER;
  464. OnComplete(SOT_COPYMOVE_MESSAGE, S_OK);
  465. }
  466. if (hr == E_PENDING)
  467. {
  468. ReplaceInterface(m_pFolderReleaseOnComplete, pSrcFolder);
  469. SafeRelease(pSrcFolder);
  470. }
  471. Exit:
  472. ReleaseObj(pSrcFolder);
  473. return hr;
  474. }
  475. // ****************************************
  476. HRESULT COEMsgSite::DoCopyMoveFromFATToFldr(BOOL fUnSent)
  477. {
  478. IMimeMessage *pMsg = NULL;
  479. HRESULT hr = S_OK;
  480. // Need original message, because m_pMsg is without security...
  481. hr = HrCreateMessage(&pMsg);
  482. if (FAILED(hr))
  483. return hr;
  484. hr = HrLoadMsgFromFileW(pMsg, m_rgwchFileName);
  485. hr = SaveMessageInFolder(m_pStoreCB, m_pCBMsgFolder, pMsg, fUnSent?ARF_UNSENT:NOFLAGS, &m_CBMessageID, TRUE);
  486. if (SUCCEEDED(hr))
  487. {
  488. m_fHaveCBMessageID = TRUE;
  489. m_dwCMFState = CMF_FAT_TO_FOLDER;
  490. OnComplete(SOT_COPYMOVE_MESSAGE, S_OK);
  491. }
  492. SafeRelease(pMsg);
  493. return hr;
  494. }
  495. // ****************************************
  496. HRESULT COEMsgSite::DoCopyMoveToFolder(BOOL fCopy, IMimeMessage *pMsg, BOOL fUnSent)
  497. {
  498. HRESULT hr;
  499. FOLDERID newFolderID;
  500. Assert(m_pStoreCB);
  501. AssertSz(NULL == m_pCBMsgFolder, "Someone forgot to release the folder");
  502. m_fCBCopy = fCopy;
  503. m_dwMSAction = MSA_COPYMOVE;
  504. hr = SelectFolderDialog(GetCallbackHwnd(), SFD_SELECTFOLDER, m_FolderID,
  505. FD_DISABLESERVERS | TREEVIEW_NONEWS |
  506. (m_fCBCopy?FD_COPYFLAGS:FD_MOVEFLAGS),
  507. MAKEINTRESOURCE(m_fCBCopy?idsCopy:idsMove),
  508. MAKEINTRESOURCE(m_fCBCopy?idsCopyCaption:idsMoveCaption),
  509. &newFolderID);
  510. // Only want to do the copy if:
  511. // 1- The new folder is not invalid
  512. // 2- Can open the needed folder
  513. if (SUCCEEDED(hr) && (newFolderID != FOLDERID_INVALID) &&
  514. SUCCEEDED(hr = g_pStore->OpenFolder(newFolderID, NULL, NOFLAGS, &m_pCBMsgFolder)))
  515. {
  516. if (pMsg)
  517. hr = DoCopyMoveFromMsgToFldr(pMsg, fUnSent);
  518. else
  519. switch (m_dwInitType)
  520. {
  521. case OEMSIT_MSG_TABLE:
  522. hr = DoCopyMoveFromTableToFldr();
  523. break;
  524. case OEMSIT_STORE:
  525. hr = DoCopyMoveFromStoreToFldr(fUnSent);
  526. break;
  527. case OEMSIT_FAT:
  528. hr = DoCopyMoveFromFATToFldr(fUnSent);
  529. break;
  530. case OEMSIT_VIRGIN:
  531. case OEMSIT_MSG:
  532. hr = DoCopyMoveFromMsgToFldr(m_pMsg, fUnSent);
  533. break;
  534. }
  535. if (E_PENDING != hr)
  536. SafeRelease(m_pCBMsgFolder);
  537. }
  538. if (FAILED(hr) && (E_PENDING != hr) && (hrUserCancel != hr))
  539. AthErrorMessageW(GetCallbackHwnd(), MAKEINTRESOURCEW(idsAthenaNews), MAKEINTRESOURCEW(idsCantSaveMsg), hr);
  540. return hr;
  541. }
  542. // ****************************************
  543. HRESULT COEMsgSite::Save(IMimeMessage *pMsg, DWORD dwFlags, IImnAccount *pAcct)
  544. {
  545. HRESULT hr;
  546. WORD wMessageFlags = 0;
  547. ACCTTYPE acctType = ACCT_MAIL;
  548. AssertSz(!m_pCBMsgFolder, "Someone forgot to release this baby.");
  549. m_fCBSaveInFolderAndDelOrig = !!(dwFlags & OESF_SAVE_IN_ORIG_FOLDER);
  550. m_fCBSavedInDrafts = FALSE;
  551. m_dwMSAction = MSA_SAVE;
  552. pAcct->GetAccountType(&acctType);
  553. if (ACCT_NEWS == acctType)
  554. wMessageFlags |= ARF_NEWSMSG;
  555. if (dwFlags & OESF_UNSENT)
  556. wMessageFlags |= ARF_UNSENT;
  557. if (dwFlags & OESF_READ)
  558. wMessageFlags |= ARF_READ;
  559. // Decide if want to save to drafts or some other folder
  560. if ((OEMSIT_MSG_TABLE == m_dwInitType) && m_fCBSaveInFolderAndDelOrig)
  561. {
  562. m_CBFolderID = m_FolderID;
  563. hr = g_pStore->OpenFolder(m_FolderID, NULL, NOFLAGS, &m_pCBMsgFolder);
  564. }
  565. else
  566. {
  567. FOLDERID idStore;
  568. m_fCBSavedInDrafts = TRUE;
  569. // Find store ID of account in the header
  570. // If have problems getting the special folder on the server, then use
  571. // the local store drafts.
  572. if (dwFlags & OESF_FORCE_LOCAL_DRAFT)
  573. idStore = FOLDERID_LOCAL_STORE;
  574. else
  575. {
  576. IImnAccount *pSaveAcct = NULL;
  577. if (ACCT_NEWS == acctType)
  578. GetDefaultAccount(ACCT_MAIL, &pSaveAcct);
  579. else
  580. ReplaceInterface(pSaveAcct, pAcct);
  581. if (pSaveAcct)
  582. {
  583. DWORD dw = 0;
  584. CHAR szAcctId[CCHMAX_ACCOUNT_NAME];
  585. hr = pSaveAcct->GetPropSz(AP_ACCOUNT_ID, szAcctId, ARRAYSIZE(szAcctId));
  586. if (SUCCEEDED(hr))
  587. hr = g_pStore->FindServerId(szAcctId, &idStore);
  588. pSaveAcct->Release();
  589. }
  590. else
  591. hr = E_FAIL;
  592. if (FAILED(hr))
  593. idStore = FOLDERID_LOCAL_STORE;
  594. }
  595. hr = g_pStore->OpenSpecialFolder(idStore, NULL, FOLDER_DRAFT, &m_pCBMsgFolder);
  596. // If failed opening special folder and we weren't trying local folders, try
  597. // using local folders now.
  598. if (FAILED(hr) && (idStore != FOLDERID_LOCAL_STORE))
  599. hr = g_pStore->OpenSpecialFolder(FOLDERID_LOCAL_STORE, NULL, FOLDER_DRAFT, &m_pCBMsgFolder);
  600. if (SUCCEEDED(hr))
  601. {
  602. m_CBFolderID = FOLDERID_INVALID;
  603. m_pCBMsgFolder->GetFolderId(&m_CBFolderID);
  604. }
  605. }
  606. if (FAILED(hr))
  607. goto Exit;
  608. m_CBMessageID = m_MessageID;
  609. // Save message to the folder
  610. hr = SaveMessageInFolder(m_pStoreCB, m_pCBMsgFolder, pMsg, wMessageFlags, &m_CBMessageID, TRUE);
  611. if (SUCCEEDED(hr))
  612. m_fHaveCBMessageID = TRUE;
  613. else if (E_PENDING == hr)
  614. {
  615. ReplaceInterface(m_pMsg, pMsg);
  616. m_fHaveCBMessageID = FALSE;
  617. }
  618. Exit:
  619. if (E_PENDING != hr)
  620. SafeRelease(m_pCBMsgFolder);
  621. if (FAILED(hr) && (hrUserCancel != hr) && (E_PENDING != hr))
  622. {
  623. int idsErr = ((MIME_E_URL_NOTFOUND == hr) ? idsErrSaveDownloadFail : idsCantSaveMsg);
  624. AthMessageBoxW(GetCallbackHwnd(), MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsCantSaveMsg), NULL, MB_OK);
  625. }
  626. return hr;
  627. }
  628. // ****************************************
  629. // Use to split this function into one for news and one for mail. Don't think that
  630. // we need to do that anymore. If there is any difference, that should probably
  631. // be moved into the message mangling phase. I can't see anything else that would
  632. // be different.
  633. #ifdef SMIME_V3
  634. HRESULT COEMsgSite::SendMsg(IMimeMessage *pMsg, BOOL fSendImmediately, BOOL fMail, IHeaderSite *pHeaderSite)
  635. #else
  636. HRESULT COEMsgSite::SendMsg(IMimeMessage *pMsg, BOOL fSendImmediately, BOOL fMail)
  637. #endif // SMIME_V3
  638. {
  639. HRESULT hr;
  640. // Figure out whether we need to request for MDNs. Doing it here skips processing it in smapi.
  641. if (fMail &&
  642. (!!(m_dwMDNFlags & MDN_REQUEST)) &&
  643. (!IsMDN(pMsg)))
  644. {
  645. LPWSTR pwsz = NULL;
  646. if (SUCCEEDED(MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_FROM), NOFLAGS, &pwsz)))
  647. {
  648. MimeOleSetBodyPropW(pMsg, HBODY_ROOT, STR_HDR_DISP_NOTIFICATION_TO, NOFLAGS, pwsz);
  649. MemFree(pwsz);
  650. }
  651. }
  652. // Account should already be setup in the message by this time.
  653. if (IsSecure(pMsg))
  654. #ifdef SMIME_V3
  655. hr = SendSecureMailToOutBox(m_pStoreCB, pMsg, fSendImmediately, FALSE, fMail, pHeaderSite);
  656. #else
  657. hr = SendSecureMailToOutBox(m_pStoreCB, pMsg, fSendImmediately, FALSE, fMail);
  658. #endif // SMIME_V3
  659. else
  660. hr = SendMailToOutBox(m_pStoreCB, pMsg, fSendImmediately, FALSE, fMail);
  661. return hr;
  662. }
  663. // ****************************************
  664. BOOL COEMsgSite::NeedToSendNews(IMimePropertySet *pPropSet)
  665. {
  666. MIMEPROPINFO mimePropInfo;
  667. AssertSz(pPropSet, "A property set needs to be passed in.");
  668. if (SUCCEEDED(pPropSet->GetPropInfo(PIDTOSTR(PID_HDR_NEWSGROUPS), &mimePropInfo)))
  669. return TRUE;
  670. if (SUCCEEDED(pPropSet->GetPropInfo(PIDTOSTR(PID_HDR_FOLLOWUPTO), &mimePropInfo)))
  671. return TRUE;
  672. return FALSE;
  673. }
  674. // ****************************************
  675. BOOL COEMsgSite::NeedToSendMail(IMimePropertySet *pPropSet)
  676. {
  677. MIMEPROPINFO mimePropInfo;
  678. AssertSz(pPropSet, "A property set needs to be passed in.");
  679. if (SUCCEEDED(pPropSet->GetPropInfo(PIDTOSTR(PID_HDR_TO), &mimePropInfo)))
  680. return TRUE;
  681. if (SUCCEEDED(pPropSet->GetPropInfo(PIDTOSTR(PID_HDR_CC), &mimePropInfo)))
  682. return TRUE;
  683. if (SUCCEEDED(pPropSet->GetPropInfo(PIDTOSTR(PID_HDR_BCC), &mimePropInfo)))
  684. return TRUE;
  685. return FALSE;
  686. }
  687. // ****************************************
  688. HRESULT COEMsgSite::ClearHeaders(ULONG cNames, LPCSTR *prgszName, IMimePropertySet *pPropSet)
  689. {
  690. HRESULT hr = S_OK;
  691. for (ULONG i = 0; i < cNames; i++)
  692. pPropSet->DeleteProp(*prgszName++);
  693. return S_OK;
  694. }
  695. // ****************************************
  696. #ifdef SMIME_V3
  697. HRESULT COEMsgSite::SendToOutbox(IMimeMessage *pMsg, BOOL fSendImmediate, IHeaderSite *pHeaderSite)
  698. #else
  699. HRESULT COEMsgSite::SendToOutbox(IMimeMessage *pMsg, BOOL fSendImmediate)
  700. #endif // SMIME_V3
  701. {
  702. HRESULT hr;
  703. BOOL fSendMail,
  704. fSendNews,
  705. fSendBoth;
  706. IMimePropertySet *pPropSet = NULL,
  707. *pTempPropSet = NULL;
  708. PROPVARIANT var;
  709. IImnAccount *pAccount = NULL;
  710. ACCTTYPE acctType;
  711. IMimeMessage *pTempMsg = NULL;
  712. LPCSTR rgszMailOnlyHeaders[] =
  713. {
  714. PIDTOSTR(PID_HDR_TO),
  715. PIDTOSTR(PID_HDR_CC),
  716. PIDTOSTR(PID_HDR_BCC),
  717. PIDTOSTR(PID_HDR_XPRI),
  718. PIDTOSTR(PID_HDR_XMSPRI),
  719. PIDTOSTR(PID_HDR_APPARTO),
  720. PIDTOSTR(PID_HDR_COMMENT),
  721. PIDTOSTR(PID_HDR_SENDER),
  722. PIDTOSTR(PID_HDR_XMAILER),
  723. PIDTOSTR(PID_HDR_RECEIVED),
  724. PIDTOSTR(PID_HDR_DISP_NOTIFICATION_TO)
  725. };
  726. LPCSTR rgszNewsOnlyHeaders[] =
  727. {
  728. PIDTOSTR(PID_HDR_NEWSGROUPS),
  729. PIDTOSTR(PID_HDR_PATH),
  730. PIDTOSTR(PID_HDR_FOLLOWUPTO),
  731. PIDTOSTR(PID_HDR_EXPIRES),
  732. PIDTOSTR(PID_HDR_REFS),
  733. PIDTOSTR(PID_HDR_DISTRIB),
  734. PIDTOSTR(PID_HDR_ORG),
  735. PIDTOSTR(PID_HDR_KEYWORDS),
  736. PIDTOSTR(PID_HDR_SUMMARY),
  737. PIDTOSTR(PID_HDR_APPROVED),
  738. PIDTOSTR(PID_HDR_LINES),
  739. PIDTOSTR(PID_HDR_XREF),
  740. PIDTOSTR(PID_HDR_CONTROL)
  741. };
  742. // Common headers between mail and news that can be left where they are
  743. // PID_HDR_FROM PID_HDR_DATE PID_HDR_SUBJECT PID_HDR_MESSAGEID
  744. // PID_HDR_REPLYTO PID_HDR_CNTTYPE PID_HDR_CNTXFER PID_HDR_CNTDESC
  745. // PID_HDR_CNTDISP PID_HDR_CNTBASE PID_HDR_CNTLOC PID_HDR_CNTID
  746. // PID_HDR_MIMEVER PID_HDR_ENCODING PID_HDR_ENCRYPTED
  747. m_dwMSAction = MSA_SEND;
  748. hr = pMsg->BindToObject(HBODY_ROOT, IID_IMimePropertySet, (LPVOID *)&pPropSet);
  749. if(FAILED(hr))
  750. return hr;
  751. fSendMail = NeedToSendMail(pPropSet);
  752. fSendNews = NeedToSendNews(pPropSet);
  753. fSendBoth = fSendMail && fSendNews;
  754. PropVariantInit(&var);
  755. if((!fSendMail) && (!fSendNews))
  756. {
  757. hr = hrNoRecipients;
  758. goto Exit;
  759. }
  760. var.vt = VT_LPSTR;
  761. hr = pMsg->GetProp(PIDTOSTR(PID_ATT_ACCOUNTID), NOFLAGS, &var);
  762. if (FAILED(hr))
  763. goto Exit;
  764. hr = g_pAcctMan->FindAccount(AP_ACCOUNT_ID, var.pszVal, &pAccount);
  765. if (FAILED(hr))
  766. goto Exit;
  767. hr = pAccount->GetAccountType(&acctType);
  768. if (FAILED(hr))
  769. goto Exit;
  770. if (fSendBoth)
  771. {
  772. hr = HrDupeMsg(pMsg, &pTempMsg);
  773. if (FAILED(hr))
  774. goto Exit;
  775. hr = pTempMsg->BindToObject(HBODY_ROOT, IID_IMimePropertySet, (LPVOID *)&pTempPropSet);
  776. if(FAILED(hr))
  777. return hr;
  778. hr = ClearHeaders(ARRAYSIZE(rgszMailOnlyHeaders), rgszMailOnlyHeaders, pPropSet);
  779. if (FAILED(hr))
  780. goto Exit;
  781. hr = ClearHeaders(ARRAYSIZE(rgszNewsOnlyHeaders), rgszNewsOnlyHeaders, pTempPropSet);
  782. if (FAILED(hr))
  783. goto Exit;
  784. }
  785. // If going to do both news and mail, then must send news first. The spooler will
  786. // block and say it is busy if we send mail first. If we send mail second, then
  787. // the spooler has a special flag that says when you are done being busy, send
  788. // any mail that you have in your outbox.
  789. if (fSendNews)
  790. {
  791. if (ACCT_MAIL == acctType)
  792. {
  793. IImnAccount *pTempAccount = NULL;
  794. if (SUCCEEDED(GetDefaultAccount(ACCT_NEWS, &pTempAccount)))
  795. {
  796. HrSetAccountByAccount(pMsg, pTempAccount);
  797. pTempAccount->Release();
  798. }
  799. }
  800. #ifdef SMIME_V3
  801. hr = SendMsg(pMsg, fSendImmediate, FALSE, pHeaderSite);
  802. #else
  803. hr = SendMsg(pMsg, fSendImmediate, FALSE);
  804. #endif // SMIME_V3
  805. if (FAILED(hr) && (E_PENDING != hr))
  806. goto Exit;
  807. // Tell the user this is being sent to the server but might not appear
  808. // right away.
  809. if (fSendImmediate && !g_pConMan->IsGlobalOffline())
  810. DoDontShowMeAgainDlg(GetCallbackHwnd(), c_szDSSendNews,
  811. MAKEINTRESOURCE(idsPostNews),
  812. MAKEINTRESOURCE(idsPostSentToServer),
  813. MB_OK);
  814. if (fSendBoth)
  815. pMsg = pTempMsg;
  816. }
  817. if (fSendMail)
  818. {
  819. if (ACCT_NEWS == acctType)
  820. {
  821. //If we are not the smapi client forward it to whoever it is.
  822. if (!FIsDefaultMailConfiged())
  823. {
  824. hr = NewsUtil_ReFwdByMapi(GetCallbackHwnd(), pMsg, MSGTYPE_CC);
  825. goto Exit;
  826. }
  827. IImnAccount *pTempAccount = NULL;
  828. if (SUCCEEDED(GetDefaultAccount(ACCT_MAIL, &pTempAccount)))
  829. {
  830. HrSetAccountByAccount(pMsg, pTempAccount);
  831. pTempAccount->Release();
  832. }
  833. }
  834. #ifdef SMIME_V3
  835. hr = SendMsg(pMsg, fSendImmediate, TRUE, pHeaderSite);
  836. #else
  837. hr = SendMsg(pMsg, fSendImmediate, TRUE);
  838. #endif // SMIME_V3
  839. }
  840. Exit:
  841. SafeMemFree(var.pszVal);
  842. ReleaseObj(pAccount);
  843. ReleaseObj(pPropSet);
  844. ReleaseObj(pTempPropSet);
  845. ReleaseObj(pTempMsg);
  846. return hr;
  847. }
  848. // ****************************************
  849. HRESULT COEMsgSite::GetLocation(LPWSTR rgwchLocation, DWORD cchSize)
  850. {
  851. FOLDERINFO fi;
  852. LPWSTR pwszName = NULL;
  853. HRESULT hr = S_OK;
  854. BOOL fFreeFolder = FALSE;
  855. switch (m_dwInitType)
  856. {
  857. case OEMSIT_MSG_TABLE:
  858. case OEMSIT_STORE:
  859. if (SUCCEEDED(g_pStore->GetFolderInfo(m_FolderID, &fi)))
  860. {
  861. Assert(fi.pszName);
  862. fFreeFolder = TRUE;
  863. IF_NULLEXIT(pwszName = PszToUnicode(CP_ACP, fi.pszName));
  864. StrCpyNW(rgwchLocation, pwszName, cchSize);
  865. }
  866. else
  867. *rgwchLocation = 0;
  868. break;
  869. case OEMSIT_FAT:
  870. StrCpyNW(rgwchLocation, m_rgwchFileName, cchSize);
  871. break;
  872. case OEMSIT_MSG:
  873. case OEMSIT_VIRGIN:
  874. *rgwchLocation = 0;
  875. break;
  876. }
  877. exit:
  878. if (fFreeFolder)
  879. g_pStore->FreeRecord(&fi);
  880. MemFree(pwszName);
  881. return hr;
  882. }
  883. // ****************************************
  884. HRESULT COEMsgSite::MarkMessage(MARK_TYPE dwType, APPLYCHILDRENTYPE dwApplyType)
  885. {
  886. HRESULT hr = E_FAIL;
  887. if (OEMSIT_MSG_TABLE == m_dwInitType)
  888. {
  889. ROWINDEX iRow = 0;
  890. hr = m_pMsgTable->GetRowIndex(m_MessageID, &iRow);
  891. if (SUCCEEDED(hr))
  892. hr = m_pMsgTable->Mark(&iRow, 1, dwApplyType, dwType, m_pStoreCB);
  893. }
  894. return hr;
  895. }
  896. // ****************************************
  897. HRESULT COEMsgSite::GetMessageFlags(MESSAGEFLAGS *pdwFlags)
  898. {
  899. HRESULT hr = S_OK;
  900. *pdwFlags = 0;
  901. if (!m_pMsgTable)
  902. {
  903. hr = E_FAIL;
  904. goto Exit;
  905. }
  906. if (OEMSIT_MSG_TABLE == m_dwInitType)
  907. {
  908. ROWINDEX iRow = 0;
  909. LPMESSAGEINFO pMsgInfo;
  910. hr = m_pMsgTable->GetRowIndex(m_MessageID, &iRow);
  911. if (FAILED(hr))
  912. goto Exit;
  913. hr = m_pMsgTable->GetRow(iRow, &pMsgInfo);
  914. if (FAILED(hr))
  915. goto Exit;
  916. *pdwFlags = pMsgInfo->dwFlags;
  917. m_pMsgTable->ReleaseRow(pMsgInfo);
  918. }
  919. Exit:
  920. return hr;
  921. }
  922. // ****************************************
  923. HRESULT COEMsgSite::GetDefaultAccount(ACCTTYPE acctType, IImnAccount **ppAcct)
  924. {
  925. HRESULT hr = E_FAIL,
  926. hr2;
  927. LPMESSAGEINFO pMsgInfo = NULL;
  928. ROWINDEX iRow;
  929. DWORD dwFlags = 0;
  930. Assert(ppAcct);
  931. if(OEMSIT_MSG_TABLE == m_dwInitType)
  932. {
  933. if (ACCT_MAIL == acctType)
  934. {
  935. IF_FAILEXIT(GetMessageFlags(&dwFlags));
  936. if (!!(dwFlags & ARF_NEWSMSG))
  937. goto exit;
  938. }
  939. IF_FAILEXIT(hr = m_pMsgTable->GetRowIndex(m_MessageID, &iRow));
  940. IF_FAILEXIT(hr = m_pMsgTable->GetRow(iRow, &pMsgInfo));
  941. IF_FAILEXIT(hr = g_pAcctMan->FindAccount(AP_ACCOUNT_ID, pMsgInfo->pszAcctId, ppAcct));
  942. }
  943. exit:
  944. if(FAILED(hr))
  945. hr = g_pAcctMan->GetDefaultAccount(acctType, ppAcct);
  946. if(pMsgInfo)
  947. {
  948. // We don't want to mask hr, so we'll just test an alternative HRESULT
  949. hr2 = m_pMsgTable->ReleaseRow(pMsgInfo);
  950. if(FAILED(hr2))
  951. TraceResult(hr2);
  952. }
  953. return hr;
  954. }
  955. // ****************************************
  956. HRESULT COEMsgSite::LoadMessageFromStore(void)
  957. {
  958. HRESULT hr;
  959. IMessageFolder *pMsgFolder = NULL;
  960. hr = g_pStore->OpenFolder(m_FolderID, NULL, NOFLAGS, &pMsgFolder);
  961. if (SUCCEEDED(hr))
  962. {
  963. IMimeMessage *pMsg = NULL;
  964. //Can only get into this state in a drafts message, so don't need worry about security
  965. hr = pMsgFolder->OpenMessage(m_MessageID, 0/* OPEN_MESSAGE_SECURE*/, &pMsg, NULL);
  966. if (SUCCEEDED(hr))
  967. {
  968. ReplaceInterface(m_pMsg, pMsg);
  969. pMsg->Release();
  970. }
  971. pMsgFolder->Release();
  972. }
  973. return hr;
  974. }
  975. // ****************************************
  976. HRESULT COEMsgSite::LoadMessageFromRow(IMimeMessage **ppMsg, ROWINDEX row)
  977. {
  978. HRESULT hr;
  979. LPMESSAGEINFO pInfo;
  980. AssertSz(!(*ppMsg), "We create a message in this function.");
  981. hr = m_pMsgTable->GetRow(row, &pInfo);
  982. if (SUCCEEDED(hr))
  983. {
  984. m_dwMSAction = MSA_GET_MESSAGE;
  985. hr = CreateMessageFromInfo(pInfo, ppMsg, m_FolderID);
  986. m_fHeaderOnly = TRUE;
  987. // now we wait until the message has downloaded and reload in
  988. // OnComplete
  989. m_pMsgTable->ReleaseRow(pInfo);
  990. }
  991. return hr;
  992. }
  993. // ****************************************
  994. HRESULT COEMsgSite::LoadMessageFromTable(BOOL fGetOriginal, HRESULT *phr)
  995. {
  996. IMimeMessage *pMsg = NULL;
  997. BOOL fOffline=FALSE;
  998. ROWINDEX rowIndex = 0;
  999. HRESULT hr,
  1000. tempHr = S_OK;
  1001. hr = m_pMsgTable->GetRowIndex(m_MessageID, &rowIndex);
  1002. if (FAILED(hr))
  1003. goto Exit;
  1004. m_fHeaderOnly = FALSE;
  1005. hr = m_pMsgTable->OpenMessage(rowIndex, (fGetOriginal ? OPEN_MESSAGE_SECURE : 0), &pMsg, m_pStoreCB);
  1006. if (FAILED(hr) || hr == STORE_S_ALREADYPENDING)
  1007. {
  1008. tempHr = hr;
  1009. hr = LoadMessageFromRow(&pMsg, rowIndex);
  1010. if (SUCCEEDED(hr))
  1011. {
  1012. switch (tempHr)
  1013. {
  1014. case E_NOT_ONLINE:
  1015. hr = HR_S_OFFLINE;
  1016. break;
  1017. case STORE_S_ALREADYPENDING:
  1018. case E_PENDING:
  1019. {
  1020. LPMESSAGEINFO pmiMsgInfo;
  1021. // Save the MsgID of msg we're trying to load. This way if user quickly loads
  1022. // several msgs into note, we won't re-enter MSA_IDLE until the desired msg loads
  1023. if (SUCCEEDED(m_pMsgTable->GetRow(rowIndex, &pmiMsgInfo)))
  1024. {
  1025. m_MessageID = pmiMsgInfo->idMessage;
  1026. m_pMsgTable->ReleaseRow(pmiMsgInfo);
  1027. }
  1028. else
  1029. m_MessageID = 0; // This means show the next msg we get!
  1030. tempHr = S_OK;
  1031. break;
  1032. }
  1033. }
  1034. }
  1035. if (FAILED(hr))
  1036. goto Exit;
  1037. }
  1038. else
  1039. {
  1040. m_dwArfFlags = 0;
  1041. GetMessageFlags(&m_dwArfFlags);
  1042. }
  1043. *phr = tempHr;
  1044. ReplaceInterface(m_pMsg, pMsg);
  1045. Exit:
  1046. ReleaseObj(pMsg);
  1047. return hr;
  1048. }
  1049. // ****************************************
  1050. HRESULT COEMsgSite::LoadMessageFromFAT(BOOL fGetOriginal, HRESULT *phr)
  1051. {
  1052. IMimeMessage *pMsg = NULL;
  1053. HRESULT hr;
  1054. hr = HrCreateMessage(&pMsg);
  1055. if (FAILED(hr))
  1056. return hr;
  1057. //bobn: We need to make sure we know the default charset
  1058. HGetDefaultCharset(NULL);
  1059. hr = HrLoadMsgFromFileW(pMsg, m_rgwchFileName);
  1060. if (SUCCEEDED(hr))
  1061. {
  1062. if(!fGetOriginal)
  1063. *phr = HandleSecurity(NULL, pMsg);
  1064. //if (SUCCEEDED(hr))
  1065. ReplaceInterface(m_pMsg, pMsg);
  1066. }
  1067. SafeRelease(pMsg);
  1068. return hr;
  1069. }
  1070. // ****************************************
  1071. HRESULT COEMsgSite::GetFolderID(FOLDERID *folderID)
  1072. {
  1073. Assert(folderID);
  1074. *folderID = m_FolderID;
  1075. return S_OK;
  1076. }
  1077. // ****************************************
  1078. HRESULT COEMsgSite::SetAccountInfo(void)
  1079. {
  1080. HRESULT hr = S_OK;
  1081. FOLDERINFO fi;
  1082. PROPVARIANT var;
  1083. // Check to see if need an account in the message.
  1084. var.vt = VT_LPSTR;
  1085. if (FAILED(m_pMsg->GetProp(PIDTOSTR(PID_ATT_ACCOUNTID), NOFLAGS, &var)) || !(var.pszVal))
  1086. {
  1087. if (FOLDERID_INVALID != m_FolderID)
  1088. {
  1089. hr = g_pStore->GetFolderInfo(m_FolderID, &fi);
  1090. if (SUCCEEDED(hr))
  1091. {
  1092. // Set account based upon the folder ID passed down
  1093. if (FOLDER_LOCAL != fi.tyFolder)
  1094. {
  1095. char szAcctId[CCHMAX_ACCOUNT_NAME];
  1096. IImnAccount *pAcct = NULL;
  1097. if (SUCCEEDED(GetFolderAccountId(&fi, szAcctId, ARRAYSIZE(szAcctId))) && SUCCEEDED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, szAcctId, &pAcct)))
  1098. {
  1099. HrSetAccountByAccount(m_pMsg, pAcct);
  1100. pAcct->Release();
  1101. }
  1102. // If not a server node, set the newgroup
  1103. if ((FOLDER_NEWS == fi.tyFolder) && (0 == (FOLDER_SERVER & fi.dwFlags)))
  1104. hr = MimeOleSetBodyPropA(m_pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_NEWSGROUPS), NOFLAGS, fi.pszName);
  1105. }
  1106. g_pStore->FreeRecord(&fi);
  1107. }
  1108. }
  1109. }
  1110. else
  1111. SafeMemFree(var.pszVal);
  1112. return hr;
  1113. }
  1114. // ****************************************
  1115. HRESULT COEMsgSite::CreateMsgWithAccountInfo(void)
  1116. {
  1117. HRESULT hr;
  1118. SafeRelease(m_pMsg);
  1119. hr = HrCreateMessage(&m_pMsg);
  1120. if (SUCCEEDED(hr))
  1121. {
  1122. if(g_hDefaultCharsetForMail)
  1123. m_pMsg->SetCharset(g_hDefaultCharsetForMail, CSET_APPLY_ALL);
  1124. hr = SetAccountInfo();
  1125. }
  1126. return hr;
  1127. }
  1128. // ****************************************
  1129. HRESULT COEMsgSite::GetMessage(IMimeMessage **ppMsg, BOOL *pfCompleteMsg, DWORD dwMessageFlags, HRESULT *phr)
  1130. {
  1131. HRESULT hr = S_OK;
  1132. BOOL fGetOriginal = (OEGM_ORIGINAL & dwMessageFlags);
  1133. if (!m_fValidMessage)
  1134. return E_FAIL;
  1135. *phr = S_OK;
  1136. if (m_fNeedToLoadMsg || fGetOriginal)
  1137. {
  1138. switch (m_dwInitType)
  1139. {
  1140. case OEMSIT_MSG_TABLE:
  1141. hr = LoadMessageFromTable(fGetOriginal, phr);
  1142. break;
  1143. case OEMSIT_STORE:
  1144. hr = LoadMessageFromStore();
  1145. break;
  1146. case OEMSIT_FAT:
  1147. hr = LoadMessageFromFAT(fGetOriginal, phr);
  1148. break;
  1149. case OEMSIT_MSG:
  1150. hr = SetAccountInfo();
  1151. break;
  1152. case OEMSIT_VIRGIN:
  1153. hr = CreateMsgWithAccountInfo();
  1154. break;
  1155. }
  1156. m_fNeedToLoadMsg = FALSE;
  1157. }
  1158. if (SUCCEEDED(hr) && !m_fHeaderOnly && (OEGM_AS_ATTACH &dwMessageFlags))
  1159. {
  1160. IMimeMessage *pMsgFwd = NULL;
  1161. PROPVARIANT var;
  1162. hr = HrCreateMessage(&pMsgFwd);
  1163. if (SUCCEEDED(hr))
  1164. hr = pMsgFwd->AttachObject(IID_IMimeMessage, (LPVOID)m_pMsg, NULL);
  1165. var.vt = VT_LPSTR;
  1166. if (SUCCEEDED(m_pMsg->GetProp(PIDTOSTR(PID_ATT_ACCOUNTID), NOFLAGS, &var)))
  1167. {
  1168. pMsgFwd->SetProp(PIDTOSTR(PID_ATT_ACCOUNTID), NOFLAGS, &var);
  1169. }
  1170. if (SUCCEEDED(hr))
  1171. {
  1172. ReplaceInterface(m_pMsg, pMsgFwd);
  1173. pMsgFwd->Release();
  1174. m_dwInitType = OEMSIT_MSG;
  1175. }
  1176. }
  1177. if (fGetOriginal)
  1178. m_fReloadMessageFlag = TRUE;
  1179. if (SUCCEEDED(hr))
  1180. {
  1181. ReplaceInterface((*ppMsg), m_pMsg);
  1182. *pfCompleteMsg = !m_fHeaderOnly;
  1183. m_fNeedToLoadMsg = !!m_fHeaderOnly;
  1184. if (!m_pMsg)
  1185. hr = E_FAIL;
  1186. }
  1187. return hr;
  1188. }
  1189. // *************************
  1190. BOOL COEMsgSite::FCanConnect()
  1191. {
  1192. IImnAccount *pAcct = NULL;
  1193. HRESULT hr;
  1194. BOOL fRet = TRUE;
  1195. hr = GetDefaultAccount(ACCT_MAIL, &pAcct);
  1196. if (SUCCEEDED(hr))
  1197. {
  1198. hr = g_pConMan->CanConnect(pAcct);
  1199. pAcct->Release();
  1200. }
  1201. fRet = (S_OK == hr);
  1202. return(fRet);
  1203. }
  1204. // ****************************************
  1205. HWND COEMsgSite::GetCallbackHwnd()
  1206. {
  1207. HWND hwnd;
  1208. Assert(m_pStoreCB);
  1209. if (SUCCEEDED(m_pStoreCB->GetParentWindow(0, &hwnd)))
  1210. return hwnd;
  1211. return 0;
  1212. }
  1213. // ****************************************
  1214. HRESULT COEMsgSite::Close(void)
  1215. {
  1216. SafeRelease(m_pMsg);
  1217. SafeRelease(m_pOrigMsg);
  1218. if (m_pMsgTable)
  1219. {
  1220. m_pMsgTable->ConnectionRelease();
  1221. m_pMsgTable->Release();
  1222. m_pMsgTable = NULL;
  1223. }
  1224. SafeRelease(m_pStoreCB);
  1225. SafeRelease(m_pListSelect);
  1226. return S_OK;
  1227. }
  1228. // ****************************************
  1229. HRESULT COEMsgSite::SetStoreCallback(IStoreCallback *pStoreCB)
  1230. {
  1231. ReplaceInterface(m_pStoreCB, pStoreCB);
  1232. return S_OK;
  1233. }
  1234. // ****************************************
  1235. HRESULT COEMsgSite::SwitchLanguage(HCHARSET hOldCharset, HCHARSET hNewCharset)
  1236. {
  1237. DWORD dwCodePage = 0;
  1238. INETCSETINFO CsetInfo;
  1239. BOOL fSaveLang = TRUE;
  1240. ROWINDEX iRow = 0;
  1241. HRESULT hr = S_OK;
  1242. if (OEMSIT_MSG_TABLE != m_dwInitType)
  1243. goto Exit;
  1244. if (FAILED(m_pMsgTable->GetRowIndex(m_MessageID, &iRow)))
  1245. goto Exit;
  1246. #if 0
  1247. if (SUCCEEDED(m_pMsgTable->GetLanguage(iRow, &dwCodePage)))
  1248. {
  1249. DWORD dwFlag ;
  1250. m_pMsg->GetFlags(&dwFlag);
  1251. // for tagged message only
  1252. if ((dwFlag & IMF_CSETTAGGED) && !dwCodePage )
  1253. fSaveLang = TRUE; // was !IntlCharsetMapLanguageCheck(hOldCharset, hNewCharset); We have
  1254. }
  1255. #endif
  1256. // save language change to message store
  1257. if (fSaveLang)
  1258. {
  1259. MimeOleGetCharsetInfo(hNewCharset, &CsetInfo);
  1260. dwCodePage = CsetInfo.cpiInternet;
  1261. // Get index again incase user changed row during dialog
  1262. if (FAILED(m_pMsgTable->GetRowIndex(m_MessageID, &iRow)))
  1263. goto Exit;
  1264. hr = m_pMsgTable->SetLanguage(1, &iRow, dwCodePage);
  1265. if (FAILED(hr))
  1266. AthMessageBoxW( GetCallbackHwnd(), MAKEINTRESOURCEW(idsAthena),
  1267. MAKEINTRESOURCEW((hr == hrIncomplete)?idsViewLangMimeDBBad:idsErrViewLanguage),
  1268. NULL, MB_OK|MB_ICONEXCLAMATION);
  1269. }
  1270. Exit:
  1271. return hr;
  1272. }
  1273. // ****************************************
  1274. HRESULT COEMsgSite::OnComplete(STOREOPERATIONTYPE tyOperation, HRESULT hrComplete, STOREOPERATIONTYPE *ptyNewOp)
  1275. {
  1276. // Action wasn't inited in MsgSite
  1277. if (MSA_IDLE == m_dwMSAction)
  1278. return S_OK;
  1279. if (ptyNewOp)
  1280. *ptyNewOp = SOT_INVALID;
  1281. switch (tyOperation)
  1282. {
  1283. case SOT_GET_MESSAGE:
  1284. HandleGetMessage(hrComplete);
  1285. break;
  1286. case SOT_DELETING_MESSAGES:
  1287. HandleDelete(hrComplete);
  1288. break;
  1289. case SOT_PUT_MESSAGE:
  1290. HandlePut(hrComplete, ptyNewOp);
  1291. break;
  1292. case SOT_COPYMOVE_MESSAGE:
  1293. HandleCopyMove(hrComplete);
  1294. SafeRelease(m_pFolderReleaseOnComplete);
  1295. break;
  1296. #ifdef DEBUG
  1297. default:
  1298. AssertSz(!m_pCBMsgFolder, "How did we get here with a CBMsgFolder");
  1299. #endif
  1300. }
  1301. return S_OK;
  1302. }
  1303. // ****************************************
  1304. HRESULT COEMsgSite::UpdateCallbackInfo(LPSTOREOPERATIONINFO pOpInfo)
  1305. {
  1306. if (pOpInfo->idMessage != MESSAGEID_INVALID)
  1307. {
  1308. m_fHaveCBMessageID = TRUE;
  1309. m_CBMessageID = pOpInfo->idMessage;
  1310. }
  1311. return S_OK;
  1312. }
  1313. // ****************************************
  1314. // Need to handle MSA_SAVE, MSA_SEND, MSA_COPYMOVE
  1315. void COEMsgSite::HandlePut(HRESULT hr, STOREOPERATIONTYPE *ptyNewOp)
  1316. {
  1317. // If is COPYMOVE, simply redirect to proper function
  1318. if (MSA_COPYMOVE == m_dwMSAction)
  1319. {
  1320. HandleCopyMove(hr);
  1321. if (ptyNewOp)
  1322. *ptyNewOp = SOT_PUT_MESSAGE;
  1323. return;
  1324. }
  1325. SafeRelease(m_pCBMsgFolder);
  1326. if (FAILED(hr))
  1327. goto Exit;
  1328. switch (m_dwMSAction)
  1329. {
  1330. case MSA_SAVE:
  1331. {
  1332. // Decide whether need to delete old message or not
  1333. switch (m_dwInitType)
  1334. {
  1335. case OEMSIT_MSG_TABLE:
  1336. {
  1337. if (m_fCBSaveInFolderAndDelOrig)
  1338. {
  1339. ROWINDEX iRow = 0;
  1340. hr = m_pMsgTable->GetRowIndex(m_MessageID, &iRow);
  1341. if (SUCCEEDED(hr))
  1342. hr = m_pMsgTable->DeleteRows(
  1343. DELETE_MESSAGE_NOTRASHCAN |
  1344. DELETE_MESSAGE_NOPROMPT |
  1345. DELETE_MESSAGE_MAYIGNORENOTRASH,
  1346. 1, &iRow, FALSE, m_pStoreCB);
  1347. if (SUCCEEDED(hr))
  1348. OnComplete(SOT_DELETING_MESSAGES, S_OK);
  1349. else if ((E_PENDING == hr) && ptyNewOp)
  1350. *ptyNewOp = SOT_DELETING_MESSAGES;
  1351. }
  1352. else
  1353. {
  1354. m_dwInitType = OEMSIT_STORE;
  1355. m_fThreadingEnabled = FALSE;
  1356. m_FolderID = m_CBFolderID;
  1357. }
  1358. m_MessageID = m_CBMessageID;
  1359. if (!m_fHaveCBMessageID)
  1360. {
  1361. m_dwInitType = OEMSIT_MSG;
  1362. }
  1363. break;
  1364. }
  1365. // Always delete since our message was in drafts and is being saved to drafts
  1366. case OEMSIT_STORE:
  1367. {
  1368. hr = DeleteFromStore(
  1369. DELETE_MESSAGE_NOTRASHCAN |
  1370. DELETE_MESSAGE_NOPROMPT |
  1371. DELETE_MESSAGE_MAYIGNORENOTRASH);
  1372. if ((E_PENDING == hr) && ptyNewOp)
  1373. *ptyNewOp = SOT_DELETING_MESSAGES;
  1374. else if (SUCCEEDED(hr))
  1375. OnComplete(SOT_DELETING_MESSAGES, S_OK);
  1376. break;
  1377. }
  1378. case OEMSIT_FAT:
  1379. case OEMSIT_MSG:
  1380. case OEMSIT_VIRGIN:
  1381. // This folder id should always be drafts.
  1382. m_FolderID = m_CBFolderID;
  1383. if ((FOLDERID_INVALID != m_FolderID) && m_fHaveCBMessageID)
  1384. {
  1385. m_MessageID = m_CBMessageID;
  1386. m_dwInitType = OEMSIT_STORE;
  1387. m_fThreadingEnabled = FALSE;
  1388. }
  1389. else
  1390. m_dwInitType = OEMSIT_MSG;
  1391. break;
  1392. }
  1393. if (m_fCBSavedInDrafts)
  1394. DoDontShowMeAgainDlg(GetCallbackHwnd(), c_szDSSavedInSavedItems,
  1395. MAKEINTRESOURCE(idsSavedMessage),
  1396. MAKEINTRESOURCE(idsSavedInDrafts),
  1397. MB_OK);
  1398. break;
  1399. }
  1400. // Don't do anything with send. Just be happy that it worked.
  1401. case MSA_SEND:
  1402. break;
  1403. default:
  1404. AssertSz(FALSE, "Didn't expect to get PUT with other MsgSite action.");
  1405. }
  1406. Exit:
  1407. if (hr != E_PENDING)
  1408. m_dwMSAction = MSA_IDLE;
  1409. }
  1410. void COEMsgSite::HandleGetMessage(HRESULT hr)
  1411. {
  1412. if (SUCCEEDED(hr))
  1413. {
  1414. HRESULT tempHr;
  1415. LoadMessageFromTable(TRUE, &tempHr);
  1416. AssertSz(SUCCEEDED(tempHr), "If hr succeeded, tempHr should have as well.");
  1417. m_fHeaderOnly = FALSE;
  1418. Notify(OEMSN_UPDATE_PREVIEW);
  1419. SetFocus(GetCallbackHwnd());
  1420. }
  1421. // Success or failure, we've loaded the target msg. Go to idle
  1422. m_dwMSAction = MSA_IDLE;
  1423. }
  1424. HRESULT COEMsgSite::Notify(DWORD dwNotifyID)
  1425. {
  1426. HRESULT hr = S_OK;
  1427. switch (dwNotifyID)
  1428. {
  1429. case OEMSN_UPDATE_PREVIEW:
  1430. {
  1431. if ((OEMSIT_MSG_TABLE == m_dwInitType) && (0 != m_MessageID))
  1432. {
  1433. ROWINDEX iRow = 0;
  1434. if (SUCCEEDED(m_pMsgTable->GetRowIndex(m_MessageID, &iRow)))
  1435. m_pListSelect->SetActiveRow(iRow);
  1436. }
  1437. break;
  1438. }
  1439. case OEMSN_TOGGLE_READRCPT_REQ:
  1440. {
  1441. if (!!(m_dwMDNFlags & MDN_REQUEST))
  1442. {
  1443. m_dwMDNFlags = m_dwMDNFlags & (~MDN_REQUEST);
  1444. }
  1445. else
  1446. {
  1447. m_dwMDNFlags |= MDN_REQUEST;
  1448. }
  1449. break;
  1450. }
  1451. case OEMSN_PROCESS_READRCPT_REQ:
  1452. {
  1453. ROWINDEX rowIndex = 0;
  1454. if ((OEMSIT_MSG_TABLE == m_dwInitType) && (0 != m_MessageID))
  1455. {
  1456. IF_FAILEXIT(hr = m_pMsgTable->GetRowIndex(m_MessageID, &rowIndex));
  1457. if (!(m_dwArfFlags & ARF_READ))
  1458. {
  1459. IF_FAILEXIT(hr = ProcessReturnReceipts(m_pMsgTable, m_pStoreCB, rowIndex, READRECEIPT, m_FolderID, m_pMsg));
  1460. }
  1461. }
  1462. break;
  1463. }
  1464. }
  1465. exit:
  1466. return hr;
  1467. }
  1468. // ****************************************
  1469. // Need to handle MSA_DELETE, MSA_COPYMOVE, and MSA_SAVE
  1470. void COEMsgSite::HandleDelete(HRESULT hr)
  1471. {
  1472. AssertSz((MSA_DELETE == m_dwMSAction) || (MSA_COPYMOVE == m_dwMSAction) || (MSA_SAVE == m_dwMSAction),
  1473. "Didn't expect to get DELETE with other MsgSite action.");
  1474. SafeRelease(m_pCBMsgFolder);
  1475. // If came from COPYMOVE, then don't do anything here.
  1476. if (FAILED(hr))
  1477. goto exit;
  1478. if (MSA_COPYMOVE == m_dwMSAction)
  1479. {
  1480. m_FolderID = m_CBFolderID;
  1481. m_MessageID = m_CBMessageID;
  1482. }
  1483. else if (MSA_SAVE == m_dwMSAction)
  1484. {
  1485. m_FolderID = m_CBFolderID;
  1486. m_MessageID = m_CBMessageID;
  1487. if (m_pListSelect && (OEMSIT_MSG_TABLE == m_dwInitType))
  1488. {
  1489. ROWINDEX iRow = 0;
  1490. if (SUCCEEDED(m_pMsgTable->GetRowIndex(m_MessageID, &iRow)))
  1491. m_pListSelect->SetActiveRow(iRow);
  1492. }
  1493. }
  1494. // Then this must be a straight delete
  1495. else
  1496. switch (m_dwInitType)
  1497. {
  1498. case OEMSIT_MSG_TABLE:
  1499. if (m_fGotNewID)
  1500. {
  1501. m_MessageID = m_NewMessageID;
  1502. m_fNeedToLoadMsg = TRUE;
  1503. if (m_pListSelect)
  1504. {
  1505. ROWINDEX iRow = 0;
  1506. if (SUCCEEDED(m_pMsgTable->GetRowIndex(m_MessageID, &iRow)))
  1507. m_pListSelect->SetActiveRow(iRow);
  1508. }
  1509. }
  1510. else
  1511. {
  1512. m_fValidMessage = FALSE;
  1513. }
  1514. break;
  1515. // Do nothing if from store
  1516. case OEMSIT_STORE:
  1517. break;
  1518. }
  1519. exit:
  1520. // If doing copy move, I expect SOT_DELETING_MESSAGES to be called before SOT_COPYMOVE_MESSAGE
  1521. m_dwMSAction = MSA_IDLE;
  1522. }
  1523. // ****************************************
  1524. // Need to handle MSA_COPYMOVE
  1525. void COEMsgSite::HandleCopyMove(HRESULT hr)
  1526. {
  1527. AssertSz(MSA_COPYMOVE == m_dwMSAction, "Didn't expect to get COPYMOVE with other MsgSite action.");
  1528. SafeRelease(m_pCBMsgFolder);
  1529. if (FAILED(hr) || m_fCBCopy)
  1530. goto Exit;
  1531. switch (m_dwCMFState)
  1532. {
  1533. case CMF_MSG_TO_FOLDER:
  1534. // Don't need to worry about anything
  1535. break;
  1536. case CMF_TABLE_TO_FOLDER:
  1537. {
  1538. // If we are moving and there is a valid bookmark to go to, then set up the note to have the next message
  1539. if (m_fGotNewID)
  1540. {
  1541. m_MessageID = m_NewMessageID;
  1542. m_fNeedToLoadMsg = TRUE;
  1543. }
  1544. else
  1545. m_fValidMessage = FALSE;
  1546. break;
  1547. }
  1548. case CMF_STORE_TO_FOLDER:
  1549. {
  1550. FOLDERID folderID;
  1551. MESSAGEIDLIST rMsgIDList;
  1552. Assert(m_pStoreCB);
  1553. rMsgIDList.cAllocated = 0;
  1554. rMsgIDList.cMsgs = 1;
  1555. rMsgIDList.prgidMsg = &m_MessageID;
  1556. hr = g_pStore->OpenFolder(m_FolderID, NULL, NOFLAGS, &m_pCBMsgFolder);
  1557. if (FAILED(hr))
  1558. goto Exit;
  1559. // Don't really care if this works.
  1560. hr = m_pCBMsgFolder->DeleteMessages(
  1561. DELETE_MESSAGE_NOTRASHCAN |
  1562. DELETE_MESSAGE_NOPROMPT |
  1563. DELETE_MESSAGE_MAYIGNORENOTRASH,
  1564. &rMsgIDList, NULL, m_pStoreCB);
  1565. AssertSz(E_PENDING != hr, "Didn't expect E_PENDING here.")
  1566. if (SUCCEEDED(hr))
  1567. OnComplete(SOT_DELETING_MESSAGES, S_OK);
  1568. break;
  1569. }
  1570. case CMF_FAT_TO_FOLDER:
  1571. {
  1572. DeleteFileWrapW(m_rgwchFileName);
  1573. // Need to shut down the note.
  1574. m_fValidMessage = FALSE;
  1575. break;
  1576. }
  1577. }
  1578. Exit:
  1579. // I expect SOT_DELETING_MESSAGES to be called before SOT_COPYMOVE_MESSAGE
  1580. m_dwMSAction = MSA_IDLE;
  1581. m_dwCMFState = CMF_UNINITED;
  1582. }