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.

5112 lines
154 KiB

  1. #include "pch.hxx"
  2. #include "note.h"
  3. #include "header.h"
  4. #include "envcid.h"
  5. #include "envguid.h"
  6. #include "bodyutil.h"
  7. #include "sigs.h"
  8. #include "mehost.h"
  9. #include "conman.h"
  10. #include "menuutil.h"
  11. #include "url.h"
  12. #include "fonts.h"
  13. #include "multlang.h"
  14. #include "statnery.h"
  15. #include "spell.h"
  16. #include "oleutil.h"
  17. #include "htmlhelp.h"
  18. #include "shared.h"
  19. #include "acctutil.h"
  20. #include "menures.h"
  21. #include "instance.h"
  22. #include "inetcfg.h"
  23. #include "ipab.h"
  24. #include "msgprop.h"
  25. #include "finder.h"
  26. #include "tbbands.h"
  27. #include "demand.h"
  28. #include "multiusr.h"
  29. #include <ruleutil.h>
  30. #include "instance.h"
  31. #include "mapiutil.h"
  32. #include "regutil.h"
  33. #include "storecb.h"
  34. #include "receipts.h"
  35. #include "mirror.h"
  36. #include "secutil.h"
  37. #include "seclabel.h"
  38. #include "shlwapip.h"
  39. #include "mshtmcid.h"
  40. #define cxRect(rc) (rc.right - rc.left)
  41. #define cyRect(rc) (rc.bottom - rc.top)
  42. #define cyMinEdit 30
  43. enum {
  44. MORFS_UNKNOWN = 0,
  45. MORFS_CLEARING,
  46. MORFS_SETTING,
  47. };
  48. // Static Variables
  49. static const TCHAR c_szEditWebPage[] = "EditWebPages";
  50. static DWORD g_dwTlsActiveNote = 0xffffffff;
  51. static HIMAGELIST g_himlToolbar = 0;
  52. static RECT g_rcLastResize = {50,30,450,450}; // default size
  53. static HACCEL g_hAccelRead = 0,
  54. g_hAccelSend = 0;
  55. //Static Functions
  56. void SetTlsGlobalActiveNote(CNote* pNote)
  57. {
  58. SideAssert(0 != TlsSetValue(g_dwTlsActiveNote, pNote));
  59. }
  60. CNote* GetTlsGlobalActiveNote(void)
  61. {
  62. return (CNote*)TlsGetValue(g_dwTlsActiveNote);
  63. }
  64. void InitTlsActiveNote()
  65. {
  66. // Allocate a global TLS active note index
  67. g_dwTlsActiveNote = TlsAlloc();
  68. Assert(g_dwTlsActiveNote != 0xffffffff);
  69. SideAssert(0 != TlsSetValue(g_dwTlsActiveNote, NULL));
  70. }
  71. void DeInitTlsActiveNote()
  72. {
  73. // Free the tls index
  74. TlsFree(g_dwTlsActiveNote);
  75. g_dwTlsActiveNote = 0xffffffff;
  76. }
  77. // *************************
  78. HRESULT CreateOENote(IUnknown *pUnkOuter, IUnknown **ppUnknown)
  79. {
  80. TraceCall("CreateOENote");
  81. Assert(ppUnknown);
  82. *ppUnknown = NULL;
  83. // Create me
  84. CNote *pNew = new CNote();
  85. if (NULL == pNew)
  86. return TraceResult(E_OUTOFMEMORY);
  87. // Cast to unknown
  88. *ppUnknown = SAFECAST(pNew, IOENote *);
  89. // Done
  90. return S_OK;
  91. }
  92. // *************************
  93. BOOL Note_Init(BOOL fInit)
  94. {
  95. static BOOL fInited=FALSE;
  96. WNDCLASSW wc;
  97. DOUTL(4, "Note_Init: %d", (int)fInit);
  98. if(fInit)
  99. {
  100. if(fInited)
  101. {
  102. DOUTL(4, "Note_Init: already inited");
  103. return TRUE;
  104. }
  105. wc.style = CS_BYTEALIGNWINDOW;
  106. wc.lpfnWndProc = CNote::ExtNoteWndProc;
  107. wc.cbClsExtra = 0;
  108. wc.cbWndExtra = 0;
  109. wc.hInstance = g_hInst;
  110. wc.hIcon = LoadIcon(g_hLocRes, MAKEINTRESOURCE(idiMessageAtt));
  111. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  112. wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
  113. wc.lpszMenuName = NULL;
  114. wc.lpszClassName = c_wszNoteWndClass;
  115. if(!RegisterClassWrapW(&wc))
  116. return FALSE;
  117. if(!FHeader_Init(TRUE))
  118. return FALSE;
  119. fInited=TRUE;
  120. DOUTL(4, "Note_Init: success");
  121. return TRUE;
  122. }
  123. else
  124. {
  125. // save back to registry
  126. UnregisterClassWrapW(c_wszNoteWndClass, g_hInst);
  127. if(g_himlToolbar)
  128. {
  129. ImageList_Destroy(g_himlToolbar);
  130. g_himlToolbar=0;
  131. }
  132. FHeader_Init(FALSE);
  133. fInited=FALSE;
  134. DOUTL(4, "Note_Init: deinit OK");
  135. return TRUE;
  136. }
  137. }
  138. HRESULT _HrBlockSender(RULE_TYPE typeRule, IMimeMessage * pMsg, HWND hwnd)
  139. {
  140. HRESULT hr = S_OK;
  141. ADDRESSPROPS rSender = {0};
  142. CHAR szRes[CCHMAX_STRINGRES];
  143. LPSTR pszResult = NULL;
  144. // Check incoming params
  145. if ((NULL == pMsg) || (NULL == hwnd))
  146. {
  147. hr = E_INVALIDARG;
  148. goto exit;
  149. }
  150. // Get the address to add
  151. rSender.dwProps = IAP_EMAIL;
  152. hr = pMsg->GetSender(&rSender);
  153. if (FAILED(hr))
  154. {
  155. goto exit;
  156. }
  157. Assert(ISFLAGSET(rSender.dwProps, IAP_EMAIL));
  158. if ((NULL == rSender.pszEmail) || ('\0' == rSender.pszEmail[0]))
  159. {
  160. goto exit;
  161. }
  162. // Add the sender to the list
  163. hr = RuleUtil_HrAddBlockSender(typeRule, rSender.pszEmail);
  164. if (FAILED(hr))
  165. {
  166. goto exit;
  167. }
  168. // Load the template string
  169. AthLoadString(idsSenderAdded, szRes, sizeof(szRes));
  170. // Allocate the space to hold the final string
  171. DWORD cchSize = (lstrlen(szRes) + lstrlen(rSender.pszEmail) + 1);
  172. hr = HrAlloc((VOID **) &pszResult, sizeof(*pszResult) * cchSize);
  173. if (FAILED(hr))
  174. {
  175. goto exit;
  176. }
  177. // Build up the warning string
  178. wnsprintf(pszResult, cchSize, szRes, rSender.pszEmail);
  179. // Show the success dialog
  180. AthMessageBox(hwnd, MAKEINTRESOURCE(idsAthena), pszResult, NULL, MB_OK | MB_ICONINFORMATION);
  181. // Set the return value
  182. hr = S_OK;
  183. exit:
  184. SafeMemFree(pszResult);
  185. g_pMoleAlloc->FreeAddressProps(&rSender);
  186. if (FAILED(hr))
  187. {
  188. AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthena),
  189. MAKEINTRESOURCEW(idsSenderError), NULL, MB_OK | MB_ICONERROR);
  190. }
  191. return hr;
  192. }
  193. // *************************
  194. LRESULT CALLBACK CNote::ExtNoteWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  195. {
  196. CNote *pNote=0;
  197. if(msg==WM_CREATE)
  198. {
  199. pNote=(CNote*)((LPCREATESTRUCT)lParam)->lpCreateParams;
  200. if(pNote && pNote->WMCreate(hwnd))
  201. return 0;
  202. else
  203. return -1;
  204. }
  205. pNote = (CNote*)GetWndThisPtr(hwnd);
  206. if(pNote)
  207. {
  208. return pNote->WndProc(hwnd, msg, wParam, lParam);
  209. }
  210. else
  211. return DefWindowProcWrapW(hwnd, msg, wParam, lParam);
  212. }
  213. // *************************
  214. CNote::CNote()
  215. {
  216. // Initialized in Init:
  217. // m_rHtmlOpt
  218. // m_rPlainOpt
  219. // Set before used:
  220. // m_pTabStopArray
  221. CoIncrementInit("CNote", MSOEAPI_START_SHOWERRORS, NULL, NULL);
  222. m_punkPump = NULL;
  223. m_pHdr = NULL;
  224. m_pMsg = NULL;
  225. m_pCancel = NULL;
  226. m_pstatus = NULL;
  227. m_pMsgSite = NULL;
  228. m_pPrstMime = NULL;
  229. m_pBodyObj2 = NULL;
  230. m_pCmdTargetHdr = NULL;
  231. m_pCmdTargetBody = NULL;
  232. m_pDropTargetHdr = NULL;
  233. m_pTridentDropTarget = NULL;
  234. m_pToolbarObj = NULL;
  235. m_hwnd = 0;
  236. m_hMenu = 0;
  237. m_hIcon = 0;
  238. m_hbmBack = 0;
  239. m_hCursor = 0;
  240. m_hCharset = 0;
  241. m_hTimeout = 0;
  242. m_hwndRebar = 0;
  243. m_hwndFocus = 0;
  244. m_hwndOwner = 0;
  245. m_hmenuLater = 0;
  246. m_hwndToolbar = 0;
  247. m_hmenuAccounts = 0;
  248. m_hmenuLanguage = 0;
  249. m_dwNoteAction = 0;
  250. m_dwIdentCookie = 0;
  251. m_dwNoteCreateFlags = 0;
  252. m_dwMarkOnReplyForwardState = MORFS_UNKNOWN;
  253. m_dwCBMarkType = MARK_MAX;
  254. m_OrigOperationType = SOT_INVALID;
  255. m_fHtml = TRUE;
  256. m_fMail = TRUE;
  257. m_fCBCopy = FALSE;
  258. m_fReadNote = FALSE;
  259. m_fProgress = FALSE;
  260. m_fCommitSave = TRUE;
  261. m_fTabStopsSet = FALSE;
  262. m_fCompleteMsg = FALSE;
  263. m_fHasBeenSaved = FALSE;
  264. m_fPackageImages = TRUE;
  265. m_fWindowDisabled = FALSE;
  266. m_fHeaderUIActive = FALSE;
  267. m_fOrgCmdWasDelete = FALSE;
  268. m_fUseReplyHeaders = FALSE;
  269. m_fCBDestroyWindow = FALSE;
  270. m_fBypassDropTests = FALSE;
  271. m_fOnDocReadyHandled = FALSE;
  272. m_fOriginallyWasRead = FALSE;
  273. m_fUseStationeryFonts = FALSE;
  274. m_fBodyContainsFrames = FALSE;
  275. m_fPreventConflictDlg = FALSE;
  276. m_fInternal = FALSE;
  277. m_fForceClose = FALSE;
  278. m_pLabel = NULL;
  279. if(FPresentPolicyRegInfo() && IsSMIME3Supported())
  280. {
  281. m_fSecurityLabel = !!DwGetOption(OPT_USE_LABELS);
  282. HrGetOELabel(&m_pLabel);
  283. }
  284. else
  285. m_fSecurityLabel = FALSE;
  286. if(IsSMIME3Supported())
  287. {
  288. m_fSecReceiptRequest = !!DwGetOption(OPT_SECREC_USE);
  289. }
  290. else
  291. m_fSecReceiptRequest = FALSE;
  292. m_ulPct = 0;
  293. m_iIndexOfBody = -1;
  294. m_cRef = 1;
  295. m_cAcctMenu = 0;
  296. m_cAcctLater = 0;
  297. m_cTabStopCount = 0;
  298. m_fStatusbarVisible = !!DwGetOption(OPT_SHOW_NOTE_STATUSBAR);
  299. m_fFormatbarVisible = !!DwGetOption(OPT_SHOW_NOTE_FMTBAR);
  300. InitializeCriticalSection(&m_csNoteState);
  301. m_nisNoteState = NIS_INIT;
  302. if (!g_hAccelRead)
  303. g_hAccelRead = LoadAccelerators(g_hLocRes, MAKEINTRESOURCE(IDA_READ_NOTE_ACCEL));
  304. if (!g_hAccelSend)
  305. g_hAccelSend = LoadAccelerators(g_hLocRes, MAKEINTRESOURCE(IDA_SEND_NOTE_ACCEL));
  306. ZeroMemory(&m_hlDisabled, sizeof(HWNDLIST));
  307. m_dwRequestMDNLocked = GetLockKeyValue(c_szRequestMDNLocked);
  308. }
  309. // *************************
  310. CNote::~CNote()
  311. {
  312. if (0 != m_hmenuLanguage)
  313. {
  314. // unload global MIME language codepage data
  315. DeinitMultiLanguage();
  316. DestroyMenu(m_hmenuLanguage);
  317. }
  318. if (m_hMenu != NULL)
  319. DestroyMenu(m_hMenu);
  320. if (m_hIcon)
  321. DestroyIcon(m_hIcon);
  322. if (m_hbmBack)
  323. DeleteObject(m_hbmBack);
  324. // sometimes we get a setfocus in our processing of DestroyWindow
  325. // this causes a WM_ACTIVATE to the note without a corresponding
  326. // WM_DEACTIVATE. if at the time the note dies, the global note ptr
  327. // has our this ptr in it, null it out to be safe.
  328. if (this == GetTlsGlobalActiveNote())
  329. {
  330. Assert(!(m_dwNoteCreateFlags & OENCF_MODAL));
  331. SetTlsGlobalActiveNote(NULL);
  332. }
  333. SafeMemFree(m_pLabel);
  334. ReleaseObj(m_pMsg);
  335. ReleaseObj(m_pHdr);
  336. ReleaseObj(m_pstatus);
  337. ReleaseObj(m_pCancel);
  338. ReleaseObj(m_pMsgSite);
  339. ReleaseObj(m_punkPump);
  340. ReleaseObj(m_pPrstMime);
  341. ReleaseObj(m_pBodyObj2);
  342. ReleaseObj(m_pCmdTargetHdr);
  343. ReleaseObj(m_pCmdTargetBody);
  344. ReleaseObj(m_pDropTargetHdr);
  345. ReleaseObj(m_pTridentDropTarget);
  346. SafeRelease(m_pToolbarObj);
  347. CallbackCloseTimeout(&m_hTimeout);
  348. DeleteCriticalSection(&m_csNoteState);
  349. CoDecrementInit("CNote", NULL);
  350. }
  351. // *************************
  352. ULONG CNote::AddRef()
  353. {
  354. return ++m_cRef;
  355. }
  356. // *************************
  357. ULONG CNote::Release()
  358. {
  359. if (--m_cRef == 0)
  360. {
  361. delete this;
  362. return 0;
  363. }
  364. return m_cRef;
  365. }
  366. // *************************
  367. HRESULT CNote::QueryInterface(REFIID riid, LPVOID FAR *ppvObj)
  368. {
  369. HRESULT hr;
  370. if(!ppvObj)
  371. return E_INVALIDARG;
  372. if (IsEqualIID(riid, IID_IUnknown))
  373. *ppvObj = ((IUnknown *)(IOENote *)this);
  374. else if(IsEqualIID(riid, IID_IOENote))
  375. *ppvObj = (IOENote *)this;
  376. else if (IsEqualIID(riid, IID_IBodyOptions))
  377. *ppvObj = (IBodyOptions *)this;
  378. else if(IsEqualIID(riid, IID_IDropTarget))
  379. *ppvObj = (IDropTarget *)this;
  380. else if (IsEqualIID(riid, IID_IHeaderSite))
  381. *ppvObj = (IHeaderSite *)this;
  382. else if(IsEqualIID(riid, IID_IPersistMime))
  383. *ppvObj = (IPersistMime *)this;
  384. else if(IsEqualIID(riid, IID_IServiceProvider))
  385. *ppvObj = (IServiceProvider *)this;
  386. else if (IsEqualIID(riid, IID_IDockingWindowSite))
  387. *ppvObj = (IDockingWindowSite*)this;
  388. else if (IsEqualIID(riid, IID_IIdentityChangeNotify))
  389. *ppvObj = (IIdentityChangeNotify*)this;
  390. else if (IsEqualIID(riid, IID_IOleCommandTarget))
  391. *ppvObj = (IOleCommandTarget*)this;
  392. else if (IsEqualIID(riid, IID_IStoreCallback))
  393. *ppvObj = (IStoreCallback *) this;
  394. else if (IsEqualIID(riid, IID_ITimeoutCallback))
  395. *ppvObj = (ITimeoutCallback *) this;
  396. else
  397. {
  398. *ppvObj = NULL;
  399. hr = E_NOINTERFACE;
  400. goto exit;
  401. }
  402. ((IUnknown *)*ppvObj)->AddRef();
  403. hr = NOERROR;
  404. exit:
  405. return hr;
  406. }
  407. // *************************
  408. HRESULT CNote::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pCmdText)
  409. {
  410. HRESULT hr = OLECMDERR_E_UNKNOWNGROUP;
  411. if (!rgCmds)
  412. return E_INVALIDARG;
  413. if (!pguidCmdGroup)
  414. return hr;
  415. // We are closing down
  416. if (!m_pMsgSite)
  417. return E_UNEXPECTED;
  418. if (m_pCmdTargetHdr)
  419. m_pCmdTargetHdr->QueryStatus(pguidCmdGroup, cCmds, rgCmds, pCmdText);
  420. if (m_pCmdTargetBody)
  421. m_pCmdTargetBody->QueryStatus(pguidCmdGroup, cCmds, rgCmds, pCmdText);
  422. MenuUtil_NewMessageIDsQueryStatus(pguidCmdGroup, cCmds, rgCmds, pCmdText, m_fMail);
  423. if (IsEqualGUID(CMDSETID_OutlookExpress, *pguidCmdGroup))
  424. {
  425. DWORD dwStatusFlags = 0;
  426. BOOL fCompleteMsg = !!m_fCompleteMsg;
  427. BOOL fHtmlSettingsOK = m_fHtml && !m_fBodyContainsFrames;
  428. m_pMsgSite->GetStatusFlags(&dwStatusFlags);
  429. for (ULONG ul = 0; ul < cCmds; ul++)
  430. {
  431. ULONG cmdID = rgCmds[ul].cmdID;
  432. // There are certain cases that need to be overridden even if the earlier
  433. // components enabled or disabled them. They are in this switch statement.
  434. switch (cmdID)
  435. {
  436. // Until trident allows printing in edit mode, don't allow this. RAID 35635
  437. case ID_PRINT:
  438. case ID_PRINT_NOW:
  439. rgCmds[ul].cmdf = QS_ENABLED(fCompleteMsg && m_fReadNote);
  440. continue;
  441. }
  442. if (0 != rgCmds[ul].cmdf)
  443. continue;
  444. switch (cmdID)
  445. {
  446. case ID_POPUP_LANGUAGE:
  447. rgCmds[ul].cmdf = QS_ENABLED(fCompleteMsg);
  448. break;
  449. case ID_NOTE_SAVE_AS:
  450. rgCmds[ul].cmdf = QS_ENABLED(fCompleteMsg || !m_fReadNote);
  451. break;
  452. case ID_WORK_OFFLINE:
  453. rgCmds[ul].cmdf = QS_CHECKED(g_pConMan->IsGlobalOffline());
  454. break;
  455. case ID_CREATE_RULE_FROM_MESSAGE:
  456. case ID_BLOCK_SENDER:
  457. rgCmds[ul].cmdf = QS_ENABLED(m_fReadNote && !m_fBodyContainsFrames && (0 == (OEMSF_RULESNOTENABLED & dwStatusFlags)));
  458. break;
  459. case ID_REPLY:
  460. case ID_REPLY_ALL:
  461. rgCmds[ul].cmdf = QS_ENABLED(m_fReadNote && !m_fBodyContainsFrames && fCompleteMsg);
  462. break;
  463. case ID_REPLY_GROUP:
  464. rgCmds[ul].cmdf = QS_ENABLED(m_fReadNote && !m_fBodyContainsFrames && !m_fMail && fCompleteMsg);
  465. break;
  466. case ID_FORWARD:
  467. case ID_FORWARD_AS_ATTACH:
  468. rgCmds[ul].cmdf = QS_ENABLED(m_fReadNote && fCompleteMsg);
  469. break;
  470. case ID_UNSCRAMBLE:
  471. rgCmds[ul].cmdf = QS_ENABLED(!m_fMail && m_fReadNote);
  472. break;
  473. case ID_POPUP_FORMAT:
  474. case ID_INSERT_SIGNATURE:
  475. rgCmds[ul].cmdf = QS_ENABLED(!m_fBodyContainsFrames);
  476. break;
  477. case ID_NOTE_COPY_TO_FOLDER:
  478. rgCmds[ul].cmdf = QS_ENABLED(fCompleteMsg && (OEMSF_CAN_COPY & dwStatusFlags));
  479. break;
  480. // Can move message if is readnote, or compose note where the message was store based.
  481. case ID_NOTE_MOVE_TO_FOLDER:
  482. rgCmds[ul].cmdf = QS_ENABLED(fCompleteMsg && (OEMSF_CAN_MOVE & dwStatusFlags) && (m_fReadNote || (OENA_COMPOSE == m_dwNoteAction)));
  483. break;
  484. case ID_NOTE_DELETE:
  485. // We should be able to delete anything that msgsite says we can delete
  486. // so long as we are a read note, or we are a drafts message.
  487. rgCmds[ul].cmdf = QS_ENABLED((OEMSF_CAN_DELETE & dwStatusFlags) && (m_fReadNote || (OENA_COMPOSE == m_dwNoteAction)));
  488. break;
  489. case ID_REDO:
  490. rgCmds[ul].cmdf = QS_ENABLED(m_fHeaderUIActive);
  491. break;
  492. case ID_SAVE:
  493. rgCmds[ul].cmdf = QS_ENABLED(fCompleteMsg && (OEMSF_CAN_SAVE & dwStatusFlags) && (m_fOnDocReadyHandled || !m_fReadNote));
  494. break;
  495. case ID_NEXT_UNREAD_MESSAGE:
  496. case ID_NEXT_MESSAGE:
  497. rgCmds[ul].cmdf = QS_ENABLED(OEMSF_CAN_NEXT & dwStatusFlags);
  498. break;
  499. case ID_POPUP_NEXT:
  500. rgCmds[ul].cmdf = QS_ENABLED((OEMSF_CAN_PREV & dwStatusFlags) || (OEMSF_CAN_NEXT & dwStatusFlags));
  501. break;
  502. case ID_MARK_THREAD_READ:
  503. rgCmds[ul].cmdf = QS_ENABLED(OEMSF_THREADING_ENABLED & dwStatusFlags);
  504. break;
  505. case ID_NEXT_UNREAD_THREAD:
  506. rgCmds[ul].cmdf = QS_ENABLED((OEMSF_THREADING_ENABLED & dwStatusFlags) && (OEMSF_CAN_NEXT & dwStatusFlags));
  507. break;
  508. case ID_PREVIOUS:
  509. rgCmds[ul].cmdf = QS_ENABLED(OEMSF_CAN_PREV & dwStatusFlags);
  510. break;
  511. case ID_FORMAT_COLOR:
  512. case ID_FORMAT_COLOR1:
  513. case ID_FORMAT_COLOR2:
  514. case ID_FORMAT_COLOR3:
  515. case ID_FORMAT_COLOR4:
  516. case ID_FORMAT_COLOR5:
  517. case ID_FORMAT_COLOR6:
  518. case ID_FORMAT_COLOR7:
  519. case ID_FORMAT_COLOR8:
  520. case ID_FORMAT_COLOR9:
  521. case ID_FORMAT_COLOR10:
  522. case ID_FORMAT_COLOR11:
  523. case ID_FORMAT_COLOR12:
  524. case ID_FORMAT_COLOR13:
  525. case ID_FORMAT_COLOR14:
  526. case ID_FORMAT_COLOR15:
  527. case ID_FORMAT_COLOR16:
  528. case ID_BACK_COLOR_AUTO:
  529. case ID_FORMAT_COLORAUTO:
  530. case ID_POPUP_BACKGROUND:
  531. rgCmds[ul].cmdf = QS_ENABLED(fHtmlSettingsOK);
  532. break;
  533. case ID_FORMATTING_TOOLBAR:
  534. rgCmds[ul].cmdf = QS_ENABLECHECK((m_fHtml && !m_fBodyContainsFrames), m_fFormatbarVisible);
  535. break;
  536. case ID_SHOW_TOOLBAR:
  537. rgCmds[ul].cmdf = QS_CHECKED(m_fToolbarVisible);
  538. break;
  539. case ID_STATUS_BAR:
  540. rgCmds[ul].cmdf = QS_CHECKED(m_fStatusbarVisible);
  541. break;
  542. case ID_SEND_OBJECTS:
  543. rgCmds[ul].cmdf = QS_ENABLECHECK(fHtmlSettingsOK, m_fPackageImages);
  544. break;
  545. case ID_RICH_TEXT:
  546. rgCmds[ul].cmdf = QS_RADIOED(m_fHtml);
  547. break;
  548. case ID_PLAIN_TEXT:
  549. rgCmds[ul].cmdf = QS_RADIOED(!m_fHtml);
  550. break;
  551. case ID_FLAG_MESSAGE:
  552. rgCmds[ul].cmdf = QS_ENABLECHECK(OEMSF_CAN_MARK & dwStatusFlags, IsFlagged());
  553. break;
  554. case ID_WATCH_THREAD:
  555. rgCmds[ul].cmdf = QS_CHECKED(IsFlagged(ARF_WATCH));
  556. break;
  557. case ID_IGNORE_THREAD:
  558. rgCmds[ul].cmdf = QS_CHECKED(IsFlagged(ARF_IGNORE));
  559. break;
  560. case ID_POPUP_NEW:
  561. case ID_NOTE_PROPERTIES:
  562. case ID_CLOSE:
  563. case ID_POPUP_FIND:
  564. case ID_POPUP_LANGUAGE_DEFERRED:
  565. case ID_POPUP_FONTS:
  566. case ID_ADDRESS_BOOK:
  567. case ID_POPUP_ADDRESS_BOOK:
  568. case ID_ADD_SENDER:
  569. case ID_ADD_ALL_TO:
  570. case ID_POPUP_TOOLBAR:
  571. case ID_CUSTOMIZE:
  572. // Help Menus
  573. case ID_HELP_CONTENTS:
  574. case ID_README:
  575. case ID_POPUP_MSWEB:
  576. case ID_MSWEB_FREE_STUFF:
  577. case ID_MSWEB_PRODUCT_NEWS:
  578. case ID_MSWEB_FAQ:
  579. case ID_MSWEB_SUPPORT:
  580. case ID_MSWEB_FEEDBACK:
  581. case ID_MSWEB_BEST:
  582. case ID_MSWEB_SEARCH:
  583. case ID_MSWEB_HOME:
  584. case ID_MSWEB_HOTMAIL:
  585. case ID_ABOUT:
  586. case ID_FIND_MESSAGE:
  587. case ID_FIND_PEOPLE:
  588. case ID_FIND_TEXT:
  589. case ID_SELECT_ALL:
  590. case ID_POPUP_LANGUAGE_MORE:
  591. case ID_SEND_NOW:
  592. case ID_SEND_LATER:
  593. case ID_SEND_MESSAGE:
  594. case ID_SEND_DEFAULT:
  595. rgCmds[ul].cmdf = QS_ENABLED(TRUE);
  596. break;
  597. case ID_REQUEST_READRCPT:
  598. if (m_fMail)
  599. {
  600. rgCmds[ul].cmdf = QS_CHECKFORLATCH(!m_dwRequestMDNLocked,
  601. !!(dwStatusFlags & OEMSF_MDN_REQUEST));
  602. }
  603. else
  604. {
  605. rgCmds[ul].cmdf = QS_ENABLED(FALSE);
  606. }
  607. break;
  608. case ID_INCLUDE_LABEL:
  609. if(m_pHdr->IsHeadSigned() == S_OK)
  610. rgCmds[ul].cmdf = QS_CHECKED(m_fSecurityLabel);
  611. else
  612. rgCmds[ul].cmdf = QS_ENABLED(FALSE);
  613. break;
  614. case ID_LABEL_SETTINGS:
  615. if(m_pHdr->IsHeadSigned() == S_OK)
  616. rgCmds[ul].cmdf = QS_ENABLED(m_fSecurityLabel);
  617. else
  618. rgCmds[ul].cmdf = QS_ENABLED(FALSE);
  619. break;
  620. case ID_SEC_RECEIPT_REQUEST:
  621. if(m_pHdr->IsHeadSigned() == S_OK)
  622. rgCmds[ul].cmdf = QS_CHECKED(m_fSecReceiptRequest);
  623. else
  624. rgCmds[ul].cmdf = QS_ENABLED(FALSE);
  625. default:
  626. if ((ID_LANG_FIRST <= cmdID) && (ID_LANG_LAST >= cmdID))
  627. {
  628. rgCmds[ul].cmdf = OLECMDF_SUPPORTED | SetMimeLanguageCheckMark(CustomGetCPFromCharset(m_hCharset, m_fReadNote), cmdID - ID_LANG_FIRST);
  629. }
  630. if (((ID_ADD_RECIPIENT_FIRST <= cmdID) && (ID_ADD_RECIPIENT_LAST >= cmdID)) ||
  631. ((ID_APPLY_STATIONERY_0 <= cmdID) && (ID_APPLY_STATIONERY_NONE >= cmdID)))
  632. rgCmds[ul].cmdf = QS_ENABLED(TRUE);
  633. else if ((ID_SIGNATURE_FIRST <= cmdID) && (ID_SIGNATURE_LAST >= cmdID))
  634. rgCmds[ul].cmdf = QS_ENABLED(!m_fBodyContainsFrames);
  635. break;
  636. }
  637. }
  638. hr = S_OK;
  639. }
  640. return hr;
  641. }
  642. // *************************
  643. HRESULT CNote::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
  644. {
  645. return E_NOTIMPL;
  646. }
  647. // *************************
  648. HRESULT CNote::ClearDirtyFlag()
  649. {
  650. m_pBodyObj2->HrSetDirtyFlag(FALSE);
  651. HeaderExecCommand(MSOEENVCMDID_DIRTY, MSOCMDEXECOPT_DODEFAULT, NULL);
  652. return S_OK;
  653. }
  654. // *************************
  655. HRESULT CNote::IsDirty(void)
  656. {
  657. OLECMD rgCmd[] = {{MSOEENVCMDID_DIRTY, 0}};
  658. BOOL fBodyDirty = FALSE;
  659. m_pBodyObj2->HrIsDirty(&fBodyDirty);
  660. if (fBodyDirty)
  661. return S_OK;
  662. if (m_pCmdTargetHdr)
  663. m_pCmdTargetHdr->QueryStatus(&CGID_Envelope, 1, rgCmd, NULL);
  664. return (0 != (rgCmd[0].cmdf&OLECMDF_ENABLED)) ? S_OK : S_FALSE;
  665. }
  666. // *************************
  667. HRESULT CNote::Load(LPMIMEMESSAGE pMsg)
  668. {
  669. HRESULT hr;
  670. VARIANTARG var;
  671. IPersistMime *pPMHdr=0;
  672. BOOL fWarnUser = (OENA_WEBPAGE == m_dwNoteAction ) ||
  673. (OENA_COMPOSE == m_dwNoteAction ) ||
  674. (OENA_STATIONERY == m_dwNoteAction ) ||
  675. (OENA_FORWARD == m_dwNoteAction);
  676. if (!m_pHdr)
  677. return E_FAIL;
  678. // OnDocumentReady will get call on the CheckForFramesets function.
  679. // Don't want that document ready to matter. Set this flag to true so
  680. // the doc ready doesn't do anything. Once the check is done, we will
  681. // set this flag to false again.
  682. m_fOnDocReadyHandled = TRUE;
  683. // If not a read note and contains frames, need to see what user wants to do
  684. if (!m_fReadNote)
  685. {
  686. hr = HrCheckForFramesets(pMsg, fWarnUser);
  687. if (FAILED(hr))
  688. goto Exit;
  689. if (hr == S_READONLY)
  690. m_fBodyContainsFrames = TRUE;
  691. }
  692. ReplaceInterface(m_pMsg, pMsg);
  693. // The next OnDocumentReady should be run.
  694. m_fOnDocReadyHandled = FALSE;
  695. hr = m_pHdr->QueryInterface(IID_IPersistMime, (LPVOID*)&pPMHdr);
  696. if (FAILED(hr))
  697. return hr;
  698. hr = pPMHdr->Load(pMsg);
  699. if (FAILED(hr))
  700. goto Exit;
  701. m_pHdr->SetFlagState(IsFlagged(ARF_FLAGGED) ? MARK_MESSAGE_FLAGGED : MARK_MESSAGE_UNFLAGGED);
  702. if (IsFlagged(ARF_WATCH))
  703. m_pHdr->SetFlagState(MARK_MESSAGE_WATCH);
  704. else if (IsFlagged(ARF_IGNORE))
  705. m_pHdr->SetFlagState(MARK_MESSAGE_IGNORE);
  706. else
  707. m_pHdr->SetFlagState(MARK_MESSAGE_NORMALTHREAD);
  708. if (m_fCompleteMsg)
  709. hr = m_pPrstMime->Load(pMsg);
  710. CheckAndForceEncryption();
  711. Exit:
  712. if (FAILED(hr))
  713. // ~~~ This should eventually be an html error message
  714. m_pBodyObj2->HrUnloadAll(idsErrHtmlBodyFailedToLoad, NULL);
  715. ReleaseObj(pPMHdr);
  716. return hr;
  717. }
  718. // *************************
  719. void CNote::CheckAndForceEncryption()
  720. {
  721. BOOL fCheck = FALSE;
  722. if(m_fSecurityLabel && m_pLabel)
  723. {
  724. DWORD dwFlags;
  725. if (SUCCEEDED(HrGetPolicyFlags(m_pLabel->pszObjIdSecurityPolicy, &dwFlags)))
  726. {
  727. if(dwFlags & SMIME_POLICY_MODULE_FORCE_ENCRYPTION)
  728. fCheck = TRUE;
  729. }
  730. }
  731. m_pHdr->ForceEncryption(&fCheck, TRUE);
  732. }
  733. // *************************
  734. HRESULT CNote::SetCharsetUnicodeIfNeeded(IMimeMessage *pMsg)
  735. {
  736. HRESULT hr = S_OK;
  737. VARIANTARG va;
  738. PROPVARIANT Variant;
  739. int ret;
  740. HCHARSET hCharSet;
  741. UINT cpID = 0;
  742. // Call dialog only if sending a mime message
  743. // See raid 8436 or 79339 in the IE/OE 5 database. We can't send
  744. // unicode encoding unless we are a mime message.
  745. if (m_fHtml || m_rPlainOpt.fMime)
  746. {
  747. m_fPreventConflictDlg = FALSE;
  748. if (SUCCEEDED(GetCharset(&hCharSet)))
  749. {
  750. cpID = CustomGetCPFromCharset(hCharSet, FALSE);
  751. }
  752. else
  753. {
  754. pMsg->GetCharset(&hCharSet);
  755. cpID = CustomGetCPFromCharset(hCharSet, FALSE);
  756. }
  757. // Check to see if have chars that don't work in encoding
  758. va.vt = VT_UI4;
  759. va.ulVal = cpID;
  760. IF_FAILEXIT(hr = m_pCmdTargetBody->Exec(&CMDSETID_MimeEdit, MECMDID_CANENCODETEXT, 0, &va, NULL));
  761. if (MIME_S_CHARSET_CONFLICT == hr)
  762. {
  763. // Don't let header call conflict dialog again
  764. m_fPreventConflictDlg = TRUE;
  765. ret = IntlCharsetConflictDialogBox();
  766. if (idcSendAsUnicode == ret)
  767. {
  768. // User choose to send as Unicode (UTF8). set new charset and resnd
  769. hCharSet = GetMimeCharsetFromCodePage(CP_UTF8);
  770. ChangeCharset(hCharSet);
  771. }
  772. else if (IDOK != ret)
  773. {
  774. // return to edit mode and bail out
  775. hr = MAPI_E_USER_CANCEL;
  776. goto exit;
  777. }
  778. }
  779. }
  780. else
  781. // Since we are not mime, don't show dialog ever.
  782. m_fPreventConflictDlg = TRUE;
  783. exit:
  784. return hr;
  785. }
  786. // *************************
  787. HRESULT CNote::Save(LPMIMEMESSAGE pMsg, DWORD dwFlags)
  788. {
  789. HRESULT hr;
  790. IPersistMime* pPersistMimeHdr=0;
  791. DWORD dwHtmlFlags = PMS_TEXT;
  792. if(!m_pHdr)
  793. IF_FAILEXIT(hr = E_FAIL);
  794. IF_FAILEXIT(hr = SetCharsetUnicodeIfNeeded(pMsg));
  795. IF_FAILEXIT(hr = m_pHdr->QueryInterface(IID_IPersistMime, (LPVOID*)&pPersistMimeHdr));
  796. IF_FAILEXIT(hr = pPersistMimeHdr->Save(pMsg, TRUE));
  797. if (m_fHtml)
  798. dwHtmlFlags |= PMS_HTML;
  799. IF_FAILEXIT(hr = m_pPrstMime->Save(pMsg, dwHtmlFlags));
  800. UpdateMsgOptions(pMsg);
  801. // During a send, don't want to commit at this time. m_fCommitSave
  802. // is set to false during a send.
  803. if (m_fCommitSave)
  804. {
  805. hr = pMsg->Commit(0);
  806. // temporary hack for #27823
  807. if((hr == MIME_E_SECURITY_NOSIGNINGCERT) ||
  808. (hr == MIME_E_SECURITY_ENCRYPTNOSENDERCERT) ||
  809. (hr == MIME_E_SECURITY_CERTERROR) ||
  810. (hr == MIME_E_SECURITY_NOCERT) ) // too early for this error
  811. hr = S_OK;
  812. }
  813. exit:
  814. ReleaseObj(pPersistMimeHdr);
  815. return hr;
  816. }
  817. // *************************
  818. HRESULT CNote::InitNew(void)
  819. {
  820. return E_NOTIMPL;
  821. }
  822. // *************************
  823. HRESULT CNote::GetClassID(CLSID *pClsID)
  824. {
  825. return NOERROR;
  826. }
  827. // *************************
  828. HRESULT CNote::SignatureEnabled(BOOL fAuto)
  829. {
  830. int cSig;
  831. HRESULT hr;
  832. DWORD dwSigFlag;
  833. if (m_fBodyContainsFrames || m_fReadNote || (OENA_WEBPAGE == m_dwNoteAction))
  834. return S_FALSE;
  835. if (FAILED(g_pSigMgr->GetSignatureCount(&cSig)) || (0 == cSig))
  836. return S_FALSE;
  837. if (!fAuto) // for non-auto scenario's it's cool to insert a sig, as there is one.
  838. return S_OK;
  839. // From this point down, we are only talking about insertion upon creation
  840. if (OENCF_NOSIGNATURE & m_dwNoteCreateFlags)
  841. return S_FALSE;
  842. dwSigFlag = DwGetOption(OPT_SIGNATURE_FLAGS);
  843. // if its a sendnote: check autonew. for automatically appending the signature. We only append on a virgin sendnote or a stationery sendnote.
  844. // as if it's been saved to the store, the signature is already there.
  845. // if in a reply or forward, then check for auto-reply.
  846. switch (m_dwNoteAction)
  847. {
  848. // If it is a compose note, make sure it wasn't from the store or file system, that it doesn't have any
  849. // body parts, and that the sig flag is set
  850. case OENA_COMPOSE:
  851. {
  852. Assert(m_pMsgSite);
  853. if (m_pMsgSite)
  854. hr = (!m_fOriginallyWasRead && (S_FALSE == HrHasBodyParts(m_pMsg)) && (dwSigFlag & SIGFLAG_AUTONEW)) ? S_OK : S_FALSE;
  855. else
  856. hr = S_FALSE;
  857. break;
  858. }
  859. // For stationery, check sig flag
  860. case OENA_STATIONERY:
  861. {
  862. hr = (dwSigFlag & SIGFLAG_AUTONEW) ? S_OK : S_FALSE;
  863. break;
  864. }
  865. // Check sig flag
  866. case OENA_REPLYTOAUTHOR:
  867. case OENA_REPLYTONEWSGROUP:
  868. case OENA_REPLYALL:
  869. case OENA_FORWARD:
  870. case OENA_FORWARDBYATTACH:
  871. {
  872. hr = (dwSigFlag & SIGFLAG_AUTOREPLY) ? S_OK : S_FALSE;
  873. break;
  874. }
  875. default:
  876. AssertSz(FALSE, "Bad note action type for signature");
  877. hr = S_FALSE;
  878. }
  879. return hr;
  880. }
  881. // *************************
  882. HRESULT CNote::GetSignature(LPCSTR szSigID, LPDWORD pdwSigOptions, BSTR *pbstr)
  883. {
  884. HRESULT hr;
  885. IImnAccount *pAcct = NULL;
  886. GETSIGINFO si;
  887. if (m_fBodyContainsFrames)
  888. return E_NOTIMPL;
  889. hr = m_pHdr->HrGetAccountInHeader(&pAcct);
  890. if (FAILED(hr))
  891. return hr;
  892. si.szSigID = szSigID;
  893. si.pAcct = pAcct;
  894. si.hwnd = m_hwnd;
  895. si.fHtmlOk = m_fHtml;
  896. si.fMail = m_fMail;
  897. si.uCodePage = GetACP();
  898. hr = HrGetMailNewsSignature(&si, pdwSigOptions, pbstr);
  899. ReleaseObj(pAcct);
  900. return hr;
  901. }
  902. // *************************
  903. HRESULT CNote::GetMarkAsReadTime(LPDWORD pdwSecs)
  904. {
  905. // Notes don't care about mark as read timers, only Views
  906. return E_NOTIMPL;
  907. }
  908. // *************************
  909. HRESULT CNote::GetFlags(LPDWORD pdwFlags)
  910. {
  911. DWORD dwMsgSiteFlags = 0;
  912. if (!pdwFlags)
  913. return E_INVALIDARG;
  914. *pdwFlags= BOPT_FROM_NOTE;
  915. Assert(m_pMsgSite);
  916. if (m_pMsgSite)
  917. m_pMsgSite->GetStatusFlags(&dwMsgSiteFlags);
  918. // if a readnote, we can auto-inline attachments
  919. if (m_fReadNote)
  920. *pdwFlags |= BOPT_AUTOINLINE;
  921. // set HTML flag
  922. if (m_fHtml)
  923. *pdwFlags |= BOPT_HTML;
  924. else
  925. *pdwFlags |= BOPT_NOFONTTAG;
  926. if (IsReplyNote())
  927. {
  928. // If block quote option is ON, and is HTML messages
  929. if (m_fHtml && DwGetOption(m_fMail?OPT_MAIL_MSG_HTML_INDENT_REPLY:OPT_NEWS_MSG_HTML_INDENT_REPLY))
  930. *pdwFlags |= BOPT_BLOCKQUOTE;
  931. // Set this in all cases except where we are a reply note and the INCLUDEMSG is not set
  932. if (DwGetOption(OPT_INCLUDEMSG))
  933. *pdwFlags |= BOPT_INCLUDEMSG;
  934. }
  935. else
  936. *pdwFlags |= BOPT_INCLUDEMSG;
  937. // If is reply or forward...
  938. if (IsReplyNote() || (OENA_FORWARD == m_dwNoteAction) || (OENA_FORWARDBYATTACH == m_dwNoteAction) )
  939. {
  940. *pdwFlags |= BOPT_REPLYORFORWARD;
  941. // ... and spell ignore is set
  942. if(DwGetOption(OPT_SPELLIGNOREPROTECT))
  943. *pdwFlags |= BOPT_SPELLINGOREORIGINAL;
  944. }
  945. // If not a read note, or a compose note that started as a compose note (ie one that was previously saved)
  946. if (!m_fReadNote && !m_fOriginallyWasRead)
  947. *pdwFlags |= BOPT_AUTOTEXT;
  948. if (!m_fReadNote && m_fPackageImages)
  949. *pdwFlags |= BOPT_SENDIMAGES;
  950. // ugh. OK, this is big-time sleazy. We found a security hole in SP1. To
  951. // plug this we need to at reply and forward time
  952. // mark incoming images etc as NOSEND=1 links. We do this for all messages
  953. // EXCEPT stationery or webpages
  954. if ((OENA_STATIONERY == m_dwNoteAction) || (OENA_WEBPAGE == m_dwNoteAction))
  955. *pdwFlags |= BOPT_SENDEXTERNALS;
  956. if (m_fUseStationeryFonts)
  957. *pdwFlags |= BOPT_NOFONTTAG;
  958. if (m_fReadNote && (dwMsgSiteFlags & OEMSF_SEC_UI_ENABLED))
  959. *pdwFlags |= BOPT_SECURITYUIENABLED;
  960. if (dwMsgSiteFlags & OEMSF_FROM_STORE)
  961. *pdwFlags |= BOPT_FROMSTORE;
  962. if (dwMsgSiteFlags & OEMSF_UNREAD)
  963. *pdwFlags |= BOPT_UNREAD;
  964. if (!m_fBodyContainsFrames && m_fUseReplyHeaders)
  965. *pdwFlags |= BOPT_USEREPLYHEADER;
  966. if (m_fMail)
  967. *pdwFlags |= BOPT_MAIL;
  968. return S_OK;
  969. }
  970. // *************************
  971. HRESULT CNote::GetInfo(BODYOPTINFO *pBOI)
  972. {
  973. HRESULT hr = S_OK;
  974. if (m_fBodyContainsFrames)
  975. return E_NOTIMPL;
  976. if (pBOI->dwMask & BOPTF_QUOTECHAR)
  977. {
  978. pBOI->chQuote = NULL;
  979. // we allow quote char in plain-text mode only
  980. if (!m_fHtml && (IsReplyNote() || (OENA_FORWARD == m_dwNoteAction)))
  981. pBOI->chQuote =(CHAR)DwGetOption(m_fMail?OPT_MAILINDENT:OPT_NEWSINDENT);
  982. }
  983. if (pBOI->dwMask & BOPTF_REPLYTICKCOLOR)
  984. pBOI->dwReplyTickColor = DwGetOption(m_fMail?OPT_MAIL_FONTCOLOR:OPT_NEWS_FONTCOLOR);
  985. if (pBOI->dwMask & BOPTF_COMPOSEFONT)
  986. hr = HrGetComposeFontString(pBOI->rgchComposeFont, ARRAYSIZE(pBOI->rgchComposeFont), m_fMail);
  987. return hr;
  988. }
  989. HRESULT CNote::GetAccount(IImnAccount **ppAcct)
  990. {
  991. HRESULT hr = S_OK;
  992. #ifdef YST
  993. FOLDERINFO fi;
  994. FOLDERID FolderID;
  995. hr = m_pMsgSite->GetFolderID(&FolderID);
  996. if (FOLDERID_INVALID != FolderID)
  997. {
  998. hr = g_pStore->GetFolderInfo(FolderID, &fi);
  999. if (SUCCEEDED(hr))
  1000. {
  1001. // Set account based upon the folder ID passed down
  1002. if (FOLDER_LOCAL != fi.tyFolder)
  1003. {
  1004. char szAcctId[CCHMAX_ACCOUNT_NAME];
  1005. hr = GetFolderAccountId(&fi, szAcctId, ARRAYSIZE(szAcctId));
  1006. if (SUCCEEDED(hr))
  1007. hr = g_pAcctMan->FindAccount(AP_ACCOUNT_ID, szAcctId, ppAcct);
  1008. }
  1009. else
  1010. hr = m_pMsgSite->GetCurrentAccount(ppAcct);
  1011. g_pStore->FreeRecord(&fi);
  1012. }
  1013. }
  1014. else
  1015. hr = E_FAIL;
  1016. #endif // 0
  1017. hr = m_pHdr->HrGetAccountInHeader(ppAcct);
  1018. return(hr);
  1019. }
  1020. // *************************
  1021. void CNote::WMSize(int cxNote, int cyNote, BOOL fInternal)
  1022. {
  1023. RECT rc;
  1024. int cy = 0;
  1025. // assume the header autosizes itself..., unless an internal size requires we recalc...
  1026. if(fInternal)
  1027. {
  1028. // if the size is coming from the header... figure out the current size
  1029. // of the note... as cxNote and cyNote are bogus at this point...
  1030. GetClientRect(m_hwnd, &rc);
  1031. cxNote = cxRect(rc);
  1032. cyNote = cyRect(rc);
  1033. }
  1034. if (m_pToolbarObj)
  1035. {
  1036. //Ideally we should be calling ResizeBorderDW. But
  1037. HWND rebarHwnd = m_hwndRebar;
  1038. m_pToolbarObj->ResizeBorderDW(&rc, (IUnknown*)(IDockingWindowSite*)this, 0);
  1039. GetWindowRect(GetParent(rebarHwnd), &rc);
  1040. cy += cyRect(rc);
  1041. }
  1042. ResizeChildren(cxNote, cyNote, cy, fInternal);
  1043. }
  1044. void CNote::ResizeChildren(int cxNote, int cyNote, int cy, BOOL fInternal)
  1045. {
  1046. int cyBottom;
  1047. RECT rc;
  1048. int cyStatus = 0;
  1049. static int cxBorder = 0,
  1050. cyBorder = 0;
  1051. if(!cxBorder || !cyBorder)
  1052. {
  1053. cyBorder = GetSystemMetrics(SM_CYBORDER);
  1054. cxBorder = GetSystemMetrics(SM_CXBORDER);
  1055. }
  1056. // size the header
  1057. GetClientRect(m_hwnd, &rc);
  1058. // remember the actual bottom
  1059. cyBottom = rc.bottom;
  1060. cy += 4;
  1061. InflateRect(&rc, -1, -1);
  1062. rc.bottom = GetRequiredHdrHeight();
  1063. rc.top = cy;
  1064. rc.bottom += rc.top;
  1065. if(!fInternal && m_pHdr)
  1066. m_pHdr->SetRect(&rc);
  1067. // WARNING: the header may resize itself during a size, due to an edit
  1068. // growing
  1069. cy += GetRequiredHdrHeight()+2;
  1070. cy += cyBorder;
  1071. if (m_pstatus)
  1072. {
  1073. m_pstatus->OnSize(cxNote, cyNote);
  1074. m_pstatus->GetHeight(&cyStatus);
  1075. }
  1076. rc.top = cy;
  1077. rc.bottom = cyBottom-cyBorder; // edit has a minimum size, clip if if gets too tight...
  1078. rc.bottom -= cyStatus;
  1079. if (m_pBodyObj2)
  1080. m_pBodyObj2->HrSetSize(&rc);
  1081. }
  1082. // *************************
  1083. BOOL CNote::IsReplyNote()
  1084. {
  1085. return ((OENA_REPLYTOAUTHOR == m_dwNoteAction) || (OENA_REPLYTONEWSGROUP == m_dwNoteAction) || (OENA_REPLYALL == m_dwNoteAction));
  1086. }
  1087. // *************************
  1088. HRESULT CNote::Resize(void)
  1089. {
  1090. WMSize(0, 0, TRUE);
  1091. return S_OK;
  1092. }
  1093. // *************************
  1094. HRESULT CNote::UpdateTitle()
  1095. {
  1096. HRESULT hr;
  1097. WCHAR wszTitle[cchHeaderMax+1];
  1098. Assert(m_pHdr);
  1099. *wszTitle = 0x0000;
  1100. hr = m_pHdr->GetTitle(wszTitle, ARRAYSIZE(wszTitle));
  1101. if(SUCCEEDED(hr))
  1102. SetWindowTextWrapW(m_hwnd, wszTitle);
  1103. return hr;
  1104. }
  1105. // *************************
  1106. HRESULT CNote::Update(void)
  1107. {
  1108. m_pToolbarObj->Update();
  1109. UpdateTitle();
  1110. return S_OK;
  1111. }
  1112. // *************************
  1113. HRESULT CNote::OnSetFocus(HWND hwndFrom)
  1114. {
  1115. HWND hwndBody;
  1116. // setfocus from a kid and not a body. make sure we
  1117. // UIDeactivate the docobj
  1118. SideAssert(m_pBodyObj2->HrGetWindow(&hwndBody)==NOERROR);
  1119. if(hwndFrom != hwndBody)
  1120. m_pBodyObj2->HrUIActivate(FALSE);
  1121. // if focus goes to a kid, update the toolbar
  1122. m_pToolbarObj->Update();
  1123. // focus is going to a kid. Enable/Disable the formatbar
  1124. m_pBodyObj2->HrUpdateFormatBar();
  1125. return S_OK;
  1126. }
  1127. // *************************
  1128. HRESULT CNote::OnUIActivate()
  1129. {
  1130. m_fHeaderUIActive = TRUE;
  1131. return OnSetFocus(0);
  1132. }
  1133. // *************************
  1134. HRESULT CNote::OnKillFocus()
  1135. {
  1136. m_pToolbarObj->Update();
  1137. return S_OK;
  1138. }
  1139. // *************************
  1140. HRESULT CNote::OnUIDeactivate(BOOL)
  1141. {
  1142. m_fHeaderUIActive = FALSE;
  1143. return OnKillFocus();
  1144. }
  1145. // *************************
  1146. HRESULT CNote::IsHTML(void)
  1147. {
  1148. return m_fHtml ? S_OK : S_FALSE;
  1149. }
  1150. HRESULT CNote::IsModal()
  1151. {
  1152. return (m_dwNoteCreateFlags & OENCF_MODAL) ? S_OK : S_FALSE;
  1153. }
  1154. // *************************
  1155. HRESULT CNote::SetHTML(BOOL fHTML)
  1156. {
  1157. m_fHtml = !!fHTML;
  1158. return NOERROR;
  1159. }
  1160. #ifdef SMIME_V3
  1161. // return selected label in note
  1162. // S_OK user select label
  1163. // S_FALSE user uncheck using security labels
  1164. HRESULT CNote::GetLabelFromNote(PSMIME_SECURITY_LABEL *pplabel)
  1165. {
  1166. if(m_fSecurityLabel && m_fMail)
  1167. {
  1168. *pplabel = m_pLabel;
  1169. return S_OK;
  1170. }
  1171. else
  1172. {
  1173. *pplabel = NULL;
  1174. return S_FALSE;
  1175. }
  1176. }
  1177. HRESULT CNote::IsSecReceiptRequest(void)
  1178. {
  1179. if(m_fSecReceiptRequest)
  1180. return(S_OK);
  1181. else
  1182. return(S_FALSE);
  1183. }
  1184. HRESULT CNote::IsForceEncryption(void)
  1185. {
  1186. return(m_pHdr->ForceEncryption(NULL, FALSE));
  1187. }
  1188. #endif // SMIME_V3
  1189. // *************************
  1190. HRESULT CNote::SaveAttachment(void)
  1191. {
  1192. return m_pBodyObj2 ? m_pBodyObj2->HrSaveAttachment() : E_FAIL;
  1193. }
  1194. // *************************
  1195. HRESULT CNote::DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  1196. {
  1197. DWORD dwEffectSave = *pdwEffect;;
  1198. m_fBypassDropTests = FALSE;
  1199. Assert(m_pDropTargetHdr && m_pTridentDropTarget);
  1200. if (m_pHdr->HrIsDragSource() == S_OK)
  1201. {
  1202. m_fBypassDropTests = TRUE; // treated as drop to itself.
  1203. *pdwEffect = DROPEFFECT_NONE;
  1204. return S_OK;
  1205. }
  1206. m_pDropTargetHdr->DragEnter(pDataObj, grfKeyState, pt, pdwEffect);
  1207. if (*pdwEffect == DROPEFFECT_NONE)
  1208. {
  1209. if (!m_fHtml) // plain text mode. If there is no text, we should not take it.
  1210. {
  1211. IEnumFORMATETC* pEnum = NULL;
  1212. FORMATETC fetc = {0};
  1213. ULONG celtFetched = 0;
  1214. BOOL fCFTEXTFound = FALSE;
  1215. // see if there is CF_TEXT format
  1216. if (SUCCEEDED(pDataObj->EnumFormatEtc(DATADIR_GET, &pEnum)))
  1217. {
  1218. pEnum->Reset();
  1219. while (S_OK == pEnum->Next(1, &fetc, &celtFetched))
  1220. {
  1221. Assert(celtFetched == 1);
  1222. if (fetc.cfFormat == CF_TEXT)
  1223. {
  1224. fCFTEXTFound = TRUE;
  1225. break;
  1226. }
  1227. }
  1228. pEnum->Release();
  1229. }
  1230. if (!fCFTEXTFound) // no CF_TEXT, cannot drop in plain text mode.
  1231. {
  1232. *pdwEffect = DROPEFFECT_NONE;
  1233. m_fBypassDropTests = TRUE; // treated as drop to itself.
  1234. return S_OK;
  1235. }
  1236. }
  1237. *pdwEffect = dwEffectSave;
  1238. m_pTridentDropTarget->DragEnter(pDataObj, grfKeyState, pt, pdwEffect);
  1239. }
  1240. return S_OK;
  1241. }
  1242. // *************************
  1243. HRESULT CNote::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  1244. {
  1245. DWORD dwEffectSave = *pdwEffect;
  1246. if (m_fBypassDropTests)
  1247. {
  1248. *pdwEffect = DROPEFFECT_NONE;
  1249. return S_OK;
  1250. }
  1251. m_pDropTargetHdr->DragOver(grfKeyState, pt, pdwEffect);
  1252. if (*pdwEffect == DROPEFFECT_NONE)
  1253. {
  1254. *pdwEffect = dwEffectSave;
  1255. m_pTridentDropTarget->DragOver(grfKeyState, pt, pdwEffect);
  1256. }
  1257. return S_OK;
  1258. }
  1259. // *************************
  1260. HRESULT CNote::DragLeave(void)
  1261. {
  1262. if (m_fBypassDropTests)
  1263. return S_OK;
  1264. m_pDropTargetHdr->DragLeave();
  1265. m_pTridentDropTarget->DragLeave();
  1266. return NOERROR;
  1267. }
  1268. // *************************
  1269. HRESULT CNote::Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  1270. {
  1271. IDataObject *pDataObjNew = NULL;
  1272. HRESULT hr = S_OK;
  1273. STGMEDIUM stgmed;
  1274. DWORD dwEffectSave = *pdwEffect;
  1275. ZeroMemory(&stgmed, sizeof(stgmed));
  1276. if (m_fBypassDropTests)
  1277. {
  1278. *pdwEffect = DROPEFFECT_NONE;
  1279. return NOERROR;
  1280. }
  1281. m_pDropTargetHdr->Drop(pDataObj, grfKeyState, pt, pdwEffect);
  1282. if (*pdwEffect == DROPEFFECT_NONE) // it is Trident's drag&drop
  1283. {
  1284. if(!m_fHtml)
  1285. {
  1286. hr = m_pBodyObj2->PublicFilterDataObject(pDataObj, &pDataObjNew);
  1287. if(FAILED(hr))
  1288. return E_UNEXPECTED;
  1289. }
  1290. else
  1291. {
  1292. pDataObjNew = pDataObj;
  1293. pDataObj->AddRef();
  1294. }
  1295. *pdwEffect = dwEffectSave;
  1296. m_pTridentDropTarget->Drop(pDataObjNew, grfKeyState, pt, pdwEffect);
  1297. }
  1298. ReleaseObj(pDataObjNew);
  1299. return hr;
  1300. }
  1301. // *************************
  1302. HRESULT CNote::InitWindows(RECT *prc, HWND hwndOwner)
  1303. {
  1304. HWND hwnd;
  1305. HMENU hMenu;
  1306. RECT rcCreate,
  1307. rc;
  1308. HCURSOR hcur;
  1309. HWND hwndCapture;
  1310. DWORD dwStyle = WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN;
  1311. HRESULT hr = S_OK;
  1312. DWORD dwExStyle = WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT | (IS_BIDI_LOCALIZED_SYSTEM() ? RTL_MIRRORED_WINDOW : 0L);
  1313. WINDOWPLACEMENT wp = {0};
  1314. Assert(hwndOwner == NULL || IsWindow(hwndOwner));
  1315. m_hwndOwner = hwndOwner;
  1316. hcur=SetCursor(LoadCursor(NULL, IDC_WAIT));
  1317. if(!Note_Init(TRUE))
  1318. IF_FAILEXIT(hr = E_FAIL);
  1319. if(prc)
  1320. CopyRect(&rcCreate, prc);
  1321. else
  1322. CopyRect(&rcCreate, &g_rcLastResize);
  1323. m_hMenu = LoadMenu(g_hLocRes, MAKEINTRESOURCE(m_fReadNote?IDR_READ_NOTE_MENU:IDR_SEND_NOTE_MENU));
  1324. MenuUtil_ReplaceHelpMenu(m_hMenu);
  1325. MenuUtil_ReplaceNewMsgMenus(m_hMenu);
  1326. if (m_dwNoteCreateFlags & OENCF_MODAL)
  1327. {
  1328. // Check to make sure nobody has captured the mouse from us
  1329. hwndCapture = GetCapture();
  1330. if (hwndCapture)
  1331. SendMessage(hwndCapture, WM_CANCELMODE, 0, 0);
  1332. // Let's make sure we have a real topmost owner
  1333. if (m_hwndOwner)
  1334. {
  1335. HWND hwndParent = GetParent(m_hwndOwner);
  1336. // IsChild checks the WM_CHILD bit in the window. This will only be
  1337. // set with controls or subs of a window. So, a dialog's parent might be
  1338. // a note, but that dialog will not be a child of the parent.
  1339. // RAID 37188
  1340. while(IsChild(hwndParent, m_hwndOwner))
  1341. {
  1342. m_hwndOwner = hwndParent;
  1343. hwndParent = GetParent(m_hwndOwner);
  1344. }
  1345. // Lose the minimize box for modal notes if there is a parent
  1346. dwStyle &= ~WS_MINIMIZEBOX;
  1347. }
  1348. }
  1349. hwnd = CreateWindowExWrapW( dwExStyle,
  1350. c_wszNoteWndClass,
  1351. NULL, //caption set by en_change of subject
  1352. dwStyle,
  1353. prc?rcCreate.left:CW_USEDEFAULT, // use windows default for x and y.
  1354. prc?rcCreate.top:CW_USEDEFAULT,
  1355. cxRect(rcCreate), cyRect(rcCreate), m_hwndOwner, NULL, g_hInst, (LPVOID)this);
  1356. IF_NULLEXIT(hwnd);
  1357. if ((m_dwNoteCreateFlags & OENCF_MODAL) && (NULL != m_hwndOwner))
  1358. EnableWindow(m_hwndOwner, FALSE);
  1359. if ( GetOption(OPT_MAILNOTEPOSEX, (LPVOID)&wp, sizeof(wp)) )
  1360. {
  1361. wp.length = sizeof(wp);
  1362. wp.showCmd = SW_HIDE;
  1363. SetWindowPlacement(hwnd, &wp);
  1364. }
  1365. else
  1366. {
  1367. CenterDialog(hwnd);
  1368. }
  1369. exit:
  1370. SetCursor(hcur);
  1371. return hr;
  1372. }
  1373. // *************************
  1374. HRESULT CNote::Init(DWORD dwAction, DWORD dwCreateFlags, RECT *prc, HWND hwnd, INIT_MSGSITE_STRUCT *pInitStruct, IOEMsgSite *pMsgSite, IUnknown *punkPump)
  1375. {
  1376. HRESULT hr,
  1377. tempHr = S_OK;
  1378. IMimeMessage *pMsg = NULL;
  1379. DWORD dwFormatFlags,
  1380. dwStatusFlags = 0,
  1381. dwMsgFlags = (OENA_FORWARDBYATTACH == dwAction) ? (OEGM_ORIGINAL|OEGM_AS_ATTACH) : NOFLAGS;
  1382. LPSTR pszUnsent = NULL;
  1383. BOOL fBool = FALSE,
  1384. fOffline=FALSE;
  1385. Assert((pInitStruct && !pMsgSite)|| (!pInitStruct && pMsgSite));
  1386. ReplaceInterface(m_punkPump, punkPump);
  1387. // If passed in an INIT_MSGSITE_STRUCT, must convert it to a pMsgSite
  1388. if (pInitStruct)
  1389. {
  1390. m_pMsgSite = new COEMsgSite();
  1391. if (!m_pMsgSite)
  1392. {
  1393. hr = E_OUTOFMEMORY;
  1394. goto exit;
  1395. }
  1396. Assert(pInitStruct);
  1397. hr = m_pMsgSite->Init(pInitStruct);
  1398. if (FAILED(hr))
  1399. goto exit;
  1400. }
  1401. else
  1402. ReplaceInterface(m_pMsgSite, pMsgSite);
  1403. if(m_pMsgSite)
  1404. m_pMsgSite->GetStatusFlags(&dwStatusFlags);
  1405. AssertSz(m_pMsgSite, "Why don't we have a msgSite???");
  1406. m_dwNoteAction = dwAction;
  1407. m_fReadNote = !!(OENA_READ == m_dwNoteAction);
  1408. m_fOriginallyWasRead = m_fReadNote;
  1409. m_dwNoteCreateFlags = dwCreateFlags;
  1410. // The storeCallback needs to be set. m_hwnd will be reset once we have a valid handle
  1411. m_hwnd = hwnd;
  1412. m_pMsgSite->SetStoreCallback(this);
  1413. hr = m_pMsgSite->GetMessage(&pMsg, &fBool, dwMsgFlags, &tempHr);
  1414. if (FAILED(hr))
  1415. goto exit;
  1416. // Raid 80277; Set default charset
  1417. if(OENA_FORWARDBYATTACH == dwAction)
  1418. {
  1419. if (NULL == g_hDefaultCharsetForMail)
  1420. ReadSendMailDefaultCharset();
  1421. pMsg->SetCharset(g_hDefaultCharsetForMail, CSET_APPLY_ALL);
  1422. }
  1423. m_fCompleteMsg = !!fBool; // m_f* is a bitfield
  1424. fOffline = (hr == HR_S_OFFLINE);
  1425. switch (m_dwNoteAction)
  1426. {
  1427. case OENA_REPLYTOAUTHOR:
  1428. case OENA_FORWARDBYATTACH:
  1429. case OENA_FORWARD:
  1430. m_fMail = TRUE;
  1431. break;
  1432. case OENA_REPLYTONEWSGROUP:
  1433. m_fMail = FALSE;
  1434. case OENA_STATIONERY:
  1435. case OENA_WEBPAGE:
  1436. case OENA_COMPOSE:
  1437. m_fMail = (0 == (m_dwNoteCreateFlags & OENCF_NEWSFIRST));
  1438. break;
  1439. case OENA_REPLYALL:
  1440. case OENA_READ:
  1441. {
  1442. DWORD dwStatusFlags = 0;
  1443. hr = m_pMsgSite->GetStatusFlags(&dwStatusFlags);
  1444. if (FAILED(hr))
  1445. goto exit;
  1446. m_fMail = (0 == (OEMSF_BASEISNEWS & dwStatusFlags));
  1447. break;
  1448. }
  1449. }
  1450. ProcessIncompleteAccts(hwnd);
  1451. hr = ProcessICW(hwnd, m_fMail ? FOLDER_LOCAL : FOLDER_NEWS);
  1452. if (FAILED(hr))
  1453. goto exit;
  1454. // If this is an unsent message and is a read note, then change the type to compose. This needs
  1455. // to happen after setting the m_fMail flag since we mangle the noteAction.
  1456. ChangeReadToComposeIfUnsent(pMsg);
  1457. if (m_fMail)
  1458. {
  1459. m_fPackageImages = !!DwGetOption(OPT_MAIL_SENDINLINEIMAGES);
  1460. dwFormatFlags = FMT_MAIL;
  1461. }
  1462. else
  1463. {
  1464. PROPVARIANT var;
  1465. IImnAccount *pAcct = NULL;
  1466. TCHAR szAcctID[CCHMAX_ACCOUNT_NAME];
  1467. DWORD dw;
  1468. m_fPackageImages = !!DwGetOption(OPT_NEWS_SENDINLINEIMAGES);
  1469. *szAcctID = 0;
  1470. dwFormatFlags = FMT_NEWS;
  1471. // Bug #24267 - Check the message object for a server name before defaulting
  1472. // to the default server.
  1473. var.vt = VT_LPSTR;
  1474. if (SUCCEEDED(pMsg->GetProp(PIDTOSTR(PID_ATT_ACCOUNTID), NOFLAGS, &var)))
  1475. {
  1476. StrCpyN(szAcctID, var.pszVal, ARRAYSIZE(szAcctID));
  1477. SafeMemFree(var.pszVal);
  1478. }
  1479. if (*szAcctID)
  1480. hr = g_pAcctMan->FindAccount(AP_ACCOUNT_ID, szAcctID, &pAcct);
  1481. // No account present, or the listed one no longer exists try to get the default
  1482. if (!*szAcctID || (*szAcctID && FAILED(hr)))
  1483. hr = m_pMsgSite->GetDefaultAccount(ACCT_NEWS, &pAcct);
  1484. if ((OENA_WEBPAGE == dwAction) || (OENA_STATIONERY == dwAction))
  1485. dwFormatFlags |= FMT_FORCE_HTML;
  1486. else if (SUCCEEDED(hr) && pAcct && SUCCEEDED(pAcct->GetPropDw(AP_NNTP_POST_FORMAT, &dw)))
  1487. {
  1488. if (dw == POST_USE_HTML)
  1489. dwFormatFlags |= FMT_FORCE_HTML;
  1490. else if (dw == POST_USE_PLAIN_TEXT)
  1491. dwFormatFlags |= FMT_FORCE_PLAIN;
  1492. else
  1493. Assert(dw == POST_USE_DEFAULT);
  1494. }
  1495. ReleaseObj(pAcct);
  1496. }
  1497. GetDefaultOptInfo(&m_rHtmlOpt, &m_rPlainOpt, &fBool, dwFormatFlags);
  1498. switch (m_dwNoteAction)
  1499. {
  1500. case OENA_FORWARDBYATTACH:
  1501. m_fHtml = !!fBool;
  1502. break;
  1503. case OENA_COMPOSE:
  1504. if (m_fOriginallyWasRead)
  1505. {
  1506. DWORD dwFlags = 0;
  1507. pMsg->GetFlags(&dwFlags);
  1508. m_fHtml = !!(dwFlags & IMF_HTML);
  1509. }
  1510. else
  1511. m_fHtml = !!fBool;
  1512. break;
  1513. case OENA_STATIONERY:
  1514. case OENA_WEBPAGE:
  1515. case OENA_READ:
  1516. m_fHtml = TRUE; // HTML is always cool in a readnote
  1517. break;
  1518. case OENA_REPLYTOAUTHOR:
  1519. case OENA_REPLYTONEWSGROUP:
  1520. case OENA_REPLYALL:
  1521. case OENA_FORWARD:
  1522. // when replying, if option to repect sender format is on, do so
  1523. if (DwGetOption(OPT_REPLYINORIGFMT))
  1524. {
  1525. DWORD dwFlags = 0;
  1526. pMsg->GetFlags(&dwFlags);
  1527. m_fHtml = !!(dwFlags & IMF_HTML);
  1528. }
  1529. else
  1530. m_fHtml = !!fBool;
  1531. // Bug 76570, 76575
  1532. // Set security label
  1533. if(pMsg)
  1534. {
  1535. SECSTATE SecState;
  1536. HrGetSecurityState(pMsg, &SecState, NULL);
  1537. // only in case of signing message check label
  1538. if(IsSigned(SecState.type))
  1539. {
  1540. PCRYPT_ATTRIBUTE pattrLabel;
  1541. LPBYTE pbLabel = NULL;
  1542. DWORD cbLabel;
  1543. PSMIME_SECURITY_LABEL plabel = NULL;
  1544. IMimeSecurity2 * pSMIME3 = NULL;
  1545. IMimeBody *pBody = NULL;
  1546. if(pMsg->BindToObject(HBODY_ROOT, IID_IMimeBody, (void **)&pBody) == S_OK)
  1547. {
  1548. if(pBody->QueryInterface(IID_IMimeSecurity2, (LPVOID *) &pSMIME3) == S_OK)
  1549. {
  1550. // Get label attribute
  1551. if(pSMIME3->GetAttribute(0, 0, SMIME_ATTRIBUTE_SET_SIGNED,
  1552. 0, szOID_SMIME_Security_Label,
  1553. &pattrLabel) == S_OK)
  1554. {
  1555. // decode label
  1556. if(CryptDecodeObjectEx(X509_ASN_ENCODING,
  1557. szOID_SMIME_Security_Label,
  1558. pattrLabel->rgValue[0].pbData,
  1559. pattrLabel->rgValue[0].cbData,
  1560. CRYPT_DECODE_ALLOC_FLAG,
  1561. &CryptDecodeAlloc, &plabel, &cbLabel))
  1562. {
  1563. if(plabel)
  1564. {
  1565. m_fSecurityLabel = TRUE;
  1566. SafeMemFree(m_pLabel);
  1567. m_pLabel = plabel;
  1568. }
  1569. }
  1570. }
  1571. else
  1572. { // Secure receipt is binary message and pMsg->GetFlags always will retutn non-HTML, but we
  1573. // forward (or Replay) with our HTML screen and need to set this to HTML.
  1574. if(CheckSecReceipt(pMsg) == S_OK)
  1575. m_fHtml = TRUE;
  1576. }
  1577. SafeRelease(pSMIME3);
  1578. }
  1579. ReleaseObj(pBody);
  1580. }
  1581. }
  1582. CleanupSECSTATE(&SecState);
  1583. }
  1584. break;
  1585. }
  1586. hr = InitWindows(prc, (dwCreateFlags & OENCF_MODAL) ? hwnd : 0);
  1587. if (FAILED(hr))
  1588. goto exit;
  1589. hr = Load(pMsg);
  1590. if (FAILED(hr))
  1591. goto exit;
  1592. if (FAILED(tempHr))
  1593. ShowErrorScreen(tempHr);
  1594. m_fFullHeaders = (S_OK == m_pHdr->FullHeadersShowing());
  1595. if (fOffline)
  1596. ShowErrorScreen(HR_E_OFFLINE);
  1597. hr = InitMenusAndToolbars();
  1598. // Register with identity manager
  1599. SideAssert(SUCCEEDED(hr = MU_RegisterIdentityNotifier((IUnknown *)(IOENote *)this, &m_dwIdentCookie)));
  1600. exit:
  1601. ReleaseObj(pMsg);
  1602. if (FAILED(hr) && m_pMsgSite && !pMsgSite)
  1603. m_pMsgSite->Close();
  1604. return hr;
  1605. }
  1606. // Will return after close if is modal, otherwise returns immediately
  1607. HRESULT CNote::Show(void)
  1608. {
  1609. ShowWindow(m_hwnd, SW_SHOW);
  1610. SetForegroundWindow(m_hwnd);
  1611. if (m_dwNoteCreateFlags & OENCF_MODAL)
  1612. {
  1613. MSG msg;
  1614. HWNDLIST hwndList;
  1615. EnableThreadWindows(&hwndList, FALSE, 0, m_hwnd);
  1616. while (GetMessageWrapW(&msg, NULL, 0, 0))
  1617. {
  1618. // This is a member function, so don't need to wrap
  1619. if (TranslateAccelerator(&msg) == S_OK)
  1620. continue;
  1621. ::TranslateMessage(&msg);
  1622. ::DispatchMessageWrapW(&msg);
  1623. }
  1624. EnableThreadWindows(&hwndList, TRUE, 0, m_hwnd);
  1625. }
  1626. return S_OK;
  1627. }
  1628. // *************************
  1629. BOOL CNote::WMCreate(HWND hwnd)
  1630. {
  1631. LPTBBUTTON lpButtons;
  1632. ULONG cBtns;
  1633. HWND hwndRebar;
  1634. CMimeEditDocHost *pNoteBody;
  1635. DWORD dwStyle;
  1636. RECT rc;
  1637. VARIANTARG var;
  1638. IUnknown *pUnk = NULL;
  1639. REBARBANDINFO rbbi;
  1640. m_hwnd = hwnd;
  1641. SetWndThisPtr(hwnd, this);
  1642. AddRef();
  1643. Assert(IsWindow(m_hwnd));
  1644. SetProp(hwnd, c_szOETopLevel, (HANDLE)TRUE);
  1645. //Create a new bandsclass and intialize it
  1646. m_pToolbarObj = new CBands();
  1647. if (!m_pToolbarObj)
  1648. return FALSE;
  1649. m_pToolbarObj->HrInit(0, m_hMenu, PARENT_TYPE_NOTE);
  1650. m_pToolbarObj->SetSite((IOENote*)this);
  1651. m_pToolbarObj->ShowDW(TRUE);
  1652. m_pToolbarObj->SetFolderType(GetNoteType());
  1653. m_fToolbarVisible = m_pToolbarObj->IsToolbarVisible();
  1654. m_hwndToolbar = m_pToolbarObj->GetToolbarWnd();
  1655. m_hwndRebar = m_pToolbarObj->GetRebarWnd();
  1656. pNoteBody = new CMimeEditDocHost(MEBF_INNERCLIENTEDGE);
  1657. if (!pNoteBody)
  1658. return FALSE;
  1659. pNoteBody->QueryInterface(IID_IBodyObj2, (LPVOID *)&m_pBodyObj2);
  1660. pNoteBody->Release();
  1661. if (!m_pBodyObj2)
  1662. return FALSE;
  1663. m_pBodyObj2->QueryInterface(IID_IPersistMime, (LPVOID*)&m_pPrstMime);
  1664. if (!m_pPrstMime)
  1665. return FALSE;
  1666. m_pstatus = new CStatusBar();
  1667. if (NULL == m_pstatus)
  1668. return FALSE;
  1669. m_pstatus->Initialize(m_hwnd, SBI_HIDE_SPOOLER | SBI_HIDE_CONNECTED | SBI_HIDE_FILTERED);
  1670. m_pstatus->ShowStatus(m_fStatusbarVisible);
  1671. m_pBodyObj2->HrSetStatusBar(m_pstatus);
  1672. CreateInstance_Envelope(NULL, (IUnknown**)&pUnk);
  1673. if (!pUnk)
  1674. return FALSE;
  1675. pUnk->QueryInterface(IID_IHeader, (LPVOID*)&m_pHdr);
  1676. pUnk->Release();
  1677. if (!m_pHdr)
  1678. return FALSE;
  1679. m_pHdr->QueryInterface(IID_IDropTarget, (LPVOID*)&m_pDropTargetHdr);
  1680. if (!m_pDropTargetHdr)
  1681. return FALSE;
  1682. m_pHdr->QueryInterface(IID_IOleCommandTarget, (LPVOID*)&m_pCmdTargetHdr);
  1683. if (!m_pCmdTargetHdr)
  1684. return FALSE;
  1685. if (!m_fMail)
  1686. HeaderExecCommand(MSOEENVCMDID_NEWS, MSOCMDEXECOPT_DODEFAULT, NULL);
  1687. var.vt = VT_I4;
  1688. var.lVal = m_dwNoteAction;
  1689. HeaderExecCommand(MSOEENVCMDID_SETACTION, MSOCMDEXECOPT_DODEFAULT, &var);
  1690. if (FAILED(m_pHdr->Init((IHeaderSite*)this, hwnd)))
  1691. return FALSE;
  1692. if (FAILED(InitBodyObj()))
  1693. return FALSE;
  1694. // Set focus in the To: line
  1695. switch (m_dwNoteAction)
  1696. {
  1697. case OENA_COMPOSE:
  1698. case OENA_FORWARD:
  1699. case OENA_FORWARDBYATTACH:
  1700. case OENA_WEBPAGE:
  1701. case OENA_STATIONERY:
  1702. m_pHdr->SetInitFocus(FALSE);
  1703. break;
  1704. }
  1705. m_pBodyObj2->SetEventSink((IMimeEditEventSink *) this);
  1706. SetForegroundWindow(m_hwnd);
  1707. return TRUE;
  1708. }
  1709. // *************************
  1710. void CNote::InitSendAndBccBtns()
  1711. {
  1712. DWORD idiIcon;
  1713. HICON hIconTemp = 0;
  1714. Assert(m_hwnd);
  1715. if (m_fMail)
  1716. idiIcon = m_fReadNote?idiMsgPropSent:idiMsgPropUnSent;
  1717. else
  1718. idiIcon = m_fReadNote?idiArtPropPost:idiArtPropUnpost;
  1719. // don't have to free HICON loaded from LoadIcon
  1720. SendMessage(m_hwnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(g_hLocRes, MAKEINTRESOURCE(idiIcon)));
  1721. if (m_fMail)
  1722. idiIcon = m_fReadNote?idiSmallMsgPropSent:idiSmallMsgPropUnSent;
  1723. else
  1724. idiIcon = m_fReadNote?idiSmallArtPropPost:idiSmallArtPropUnpost;
  1725. if(m_hIcon)
  1726. {
  1727. hIconTemp = m_hIcon;
  1728. }
  1729. m_hIcon = (HICON)LoadImage(g_hLocRes, MAKEINTRESOURCE(idiIcon), IMAGE_ICON,
  1730. GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);
  1731. // don't have to free HICON loaded from LoadIcon
  1732. SendMessage(m_hwnd, WM_SETICON, ICON_SMALL, (LPARAM)m_hIcon);
  1733. if(hIconTemp)
  1734. {
  1735. //Bug #101345 - (erici) ICON leaked when 'Previous' or 'Next' button clicked
  1736. DestroyIcon(hIconTemp);
  1737. }
  1738. // If this is a news send note, then we spruce up the send button on the toolbar
  1739. if ((FALSE == m_fReadNote) && (FALSE == m_fMail))
  1740. {
  1741. TBBUTTONINFO tbi;
  1742. ZeroMemory(&tbi, sizeof(TBBUTTONINFO));
  1743. tbi.cbSize = sizeof(TBBUTTONINFO);
  1744. tbi.dwMask = TBIF_IMAGE;
  1745. tbi.iImage = TBIMAGE_SEND_NEWS;
  1746. SendMessage(m_hwndToolbar, TB_SETBUTTONINFO, ID_SEND_DEFAULT, (LPARAM) &tbi);
  1747. }
  1748. }
  1749. // *************************
  1750. HRESULT CNote::HeaderExecCommand(UINT uCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn)
  1751. {
  1752. HRESULT hr = S_FALSE;
  1753. if (uCmdID && m_pCmdTargetHdr)
  1754. hr = m_pCmdTargetHdr->Exec(&CGID_Envelope, uCmdID, nCmdExecOpt, pvaIn, NULL);
  1755. return hr;
  1756. }
  1757. // *************************
  1758. HRESULT CNote::InitBodyObj()
  1759. {
  1760. DWORD dwBodyStyle = MESTYLE_NOHEADER;
  1761. HRESULT hr;
  1762. int idsErr=0;
  1763. hr = m_pBodyObj2->HrInit(m_hwnd, IBOF_TABLINKS, (IBodyOptions *)this);
  1764. if (FAILED(hr))
  1765. goto fail;
  1766. hr = m_pBodyObj2->QueryInterface(IID_IOleCommandTarget, (LPVOID*)&m_pCmdTargetBody);
  1767. if (FAILED(hr))
  1768. goto fail;
  1769. hr = m_pBodyObj2->HrShow(TRUE);
  1770. if (FAILED(hr))
  1771. goto fail;
  1772. // if not in html mode, don't show format bar...
  1773. // we do this test here, as HrLoad could determine that a previously saved message
  1774. // is indeed in html, which overrides the default setting
  1775. if(!m_fHtml)
  1776. m_fFormatbarVisible = FALSE;
  1777. if (!m_fReadNote && !m_fBodyContainsFrames && m_fFormatbarVisible)
  1778. dwBodyStyle = MESTYLE_FORMATBAR;
  1779. m_pBodyObj2->HrEnableHTMLMode(m_fHtml);
  1780. m_pBodyObj2->HrSetStyle(dwBodyStyle);
  1781. // all is groovey
  1782. return hr;
  1783. fail:
  1784. switch (hr)
  1785. {
  1786. case INET_E_UNKNOWN_PROTOCOL:
  1787. idsErr = idsErrLoadProtocolBad;
  1788. break;
  1789. default:
  1790. idsErr = idsErrNoteDeferedInit;
  1791. break;
  1792. }
  1793. AthMessageBoxW(g_hwndInit, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErr), NULL, MB_OK);
  1794. return hr;
  1795. }
  1796. // *************************
  1797. HRESULT CNote::InitMenusAndToolbars()
  1798. {
  1799. DWORD dwStatusFlags;
  1800. HRESULT hr;
  1801. BOOL fComposeNote,
  1802. fCompleteMsg = !!m_fCompleteMsg, // m_fCompleteMsg is a bit field.
  1803. fNextPrevious;
  1804. HMENU hMenu = m_hMenu;
  1805. m_fUseReplyHeaders = FALSE;
  1806. Assert(m_pMsgSite);
  1807. if (m_pMsgSite)
  1808. m_pMsgSite->GetStatusFlags(&dwStatusFlags);
  1809. switch (m_dwNoteAction)
  1810. {
  1811. case OENA_FORWARDBYATTACH:
  1812. case OENA_COMPOSE:
  1813. // if it's a virgin compose-note, we check the regsettings to see if they want to compose
  1814. // from a stationery file. If so, we set the html stream to that file.
  1815. if (m_fHtml && !(m_dwNoteCreateFlags & OENCF_NOSTATIONERY) && (OEMSF_VIRGIN & dwStatusFlags))
  1816. SetComposeStationery();
  1817. break;
  1818. case OENA_STATIONERY:
  1819. if (m_dwNoteCreateFlags & OENCF_USESTATIONERYFONT)
  1820. m_fUseStationeryFonts = TRUE;
  1821. break;
  1822. case OENA_REPLYTOAUTHOR:
  1823. case OENA_REPLYTONEWSGROUP:
  1824. case OENA_REPLYALL:
  1825. case OENA_FORWARD:
  1826. m_fUseReplyHeaders = TRUE;
  1827. break;
  1828. }
  1829. InitSendAndBccBtns();
  1830. if (m_fMail)
  1831. {
  1832. if (m_fReadNote || IsReplyNote())
  1833. m_pBodyObj2->HrUIActivate(TRUE);
  1834. }
  1835. else
  1836. {
  1837. if ((OENA_COMPOSE == m_dwNoteAction) && (OEMSF_VIRGIN & dwStatusFlags))
  1838. // for a sendnote in news, put focus in the subject as the to: line is filled in. bug #24720
  1839. m_pHdr->SetInitFocus(TRUE);
  1840. else
  1841. // else , always put focus in the BODY
  1842. m_pBodyObj2->HrUIActivate(TRUE);
  1843. }
  1844. RECT rc;
  1845. GetClientRect(m_hwnd, &rc);
  1846. SendMessage(m_hwnd, WM_SIZE, SIZE_RESTORED, MAKELPARAM(rc.right, rc.bottom));
  1847. // put us into edit mode if not a readnote...
  1848. hr=m_pBodyObj2->HrSetEditMode(!m_fReadNote && !m_fBodyContainsFrames);
  1849. if (FAILED(hr))
  1850. goto error;
  1851. if (m_fBodyContainsFrames)
  1852. DisableSendNoteOnlyMenus();
  1853. // get the character set of the message being loaded
  1854. if (m_pMsg)
  1855. m_pMsg->GetCharset(&m_hCharset);
  1856. error:
  1857. return hr;
  1858. }
  1859. // *************************
  1860. void CNote::DisableSendNoteOnlyMenus()
  1861. {
  1862. }
  1863. // *************************
  1864. HACCEL CNote::GetAcceleratorTable()
  1865. {
  1866. return (m_fReadNote ? g_hAccelRead : g_hAccelSend);
  1867. }
  1868. // *************************
  1869. HRESULT CNote::TranslateAccelerator(LPMSG lpmsg)
  1870. {
  1871. HWND hwndT,
  1872. hwndFocus;
  1873. if (IsMenuMessage(lpmsg) == S_OK)
  1874. return S_OK;
  1875. // handle the mousewheel messages for this note
  1876. if ((g_msgMSWheel && (lpmsg->message == g_msgMSWheel)) || (lpmsg->message == WM_MOUSEWHEEL))
  1877. {
  1878. POINT pt;
  1879. HWND hwndT;
  1880. pt.x = GET_X_LPARAM(lpmsg->lParam);
  1881. pt.y = GET_Y_LPARAM(lpmsg->lParam);
  1882. hwndT = WindowFromPoint(pt);
  1883. hwndFocus = GetFocus();
  1884. if (hwndT != m_hwnd && IsChild(m_hwnd, hwndT))
  1885. SendMessage(hwndT, lpmsg->message, lpmsg->wParam, lpmsg->lParam);
  1886. else if (hwndFocus != m_hwnd && IsChild(m_hwnd, hwndFocus))
  1887. SendMessage(hwndFocus, lpmsg->message, lpmsg->wParam, lpmsg->wParam);
  1888. else
  1889. return S_FALSE;
  1890. return S_OK;
  1891. }
  1892. // our accelerators have higher priority.
  1893. if(::TranslateAcceleratorWrapW(m_hwnd, GetAcceleratorTable(), lpmsg))
  1894. return S_OK;
  1895. // see if the body want it for the docobject...
  1896. if(m_pBodyObj2 &&
  1897. m_pBodyObj2->HrTranslateAccelerator(lpmsg)==S_OK)
  1898. return S_OK;
  1899. if (lpmsg->message == WM_KEYDOWN &&
  1900. lpmsg->wParam == VK_TAB &&
  1901. !(GetKeyState(VK_CONTROL) & 0x8000 ))
  1902. {
  1903. BOOL fGoForward = ( GetKeyState( VK_SHIFT ) & 0x8000 ) == 0;
  1904. CycleThroughControls(fGoForward);
  1905. return S_OK;
  1906. }
  1907. return S_FALSE;
  1908. }
  1909. // *************************
  1910. LRESULT CNote::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1911. {
  1912. LRESULT lResult;
  1913. LRESULT lres;
  1914. MSG Menumsg;
  1915. HWND hwndActive;
  1916. WINDOWPLACEMENT wp;
  1917. Menumsg.hwnd = hwnd;
  1918. Menumsg.message = msg;
  1919. Menumsg.wParam = wParam;
  1920. Menumsg.lParam = lParam;
  1921. if (m_pToolbarObj && (m_pToolbarObj->TranslateMenuMessage(&Menumsg, &lres) == S_OK))
  1922. return lres;
  1923. wParam = Menumsg.wParam;
  1924. lParam = Menumsg.lParam;
  1925. switch(msg)
  1926. {
  1927. case WM_ENABLE:
  1928. if (!m_fInternal)
  1929. {
  1930. Assert (wParam || (m_hlDisabled.cHwnd == NULL && m_hlDisabled.rgHwnd == NULL));
  1931. EnableThreadWindows(&m_hlDisabled, !!wParam, ETW_OE_WINDOWS_ONLY, hwnd);
  1932. g_hwndActiveModal = wParam ? NULL : hwnd;
  1933. }
  1934. break;
  1935. case WM_OE_DESTROYNOTE:
  1936. m_fForceClose = 1;
  1937. SendMessage(hwnd, WM_CLOSE, 0, 0);
  1938. break;
  1939. case WM_OENOTE_ON_COMPLETE:
  1940. _OnComplete((STOREOPERATIONTYPE)lParam, (HRESULT) wParam);
  1941. break;
  1942. case WM_OE_ENABLETHREADWINDOW:
  1943. m_fInternal = 1;
  1944. EnableWindow(hwnd, (BOOL)wParam);
  1945. m_fInternal = 0;
  1946. break;
  1947. case WM_OE_ACTIVATETHREADWINDOW:
  1948. hwndActive = GetLastActivePopup(hwnd);
  1949. if (hwndActive && IsWindowEnabled(hwndActive) && IsWindowVisible(hwndActive))
  1950. ActivatePopupWindow(hwndActive);
  1951. break;
  1952. case NWM_GETDROPTARGET:
  1953. SafeRelease(m_pTridentDropTarget);
  1954. m_pTridentDropTarget = (IDropTarget*) wParam;
  1955. if (m_pTridentDropTarget)
  1956. m_pTridentDropTarget->AddRef();
  1957. AddRef();
  1958. return (LRESULT)(IDropTarget *) this;
  1959. case WM_DESTROY:
  1960. // Unregister with Identity manager
  1961. if (m_dwIdentCookie != 0)
  1962. {
  1963. MU_UnregisterIdentityNotifier(m_dwIdentCookie);
  1964. m_dwIdentCookie = 0;
  1965. }
  1966. wp.length = sizeof(wp);
  1967. GetWindowPlacement(hwnd, &wp);
  1968. SetOption(OPT_MAILNOTEPOSEX, (LPVOID)&wp, sizeof(wp), NULL, 0);
  1969. RemoveProp(hwnd, c_szOETopLevel);
  1970. DeinitSigPopupMenu(hwnd);
  1971. if(m_pBodyObj2)
  1972. {
  1973. m_pBodyObj2->HrSetStatusBar(NULL);
  1974. m_pBodyObj2->HrClose();
  1975. }
  1976. SafeRelease(m_pTridentDropTarget);
  1977. if (m_pToolbarObj)
  1978. {
  1979. DWORD dwReserved = 0;
  1980. m_pToolbarObj->SetSite(NULL);
  1981. m_pToolbarObj->CloseDW(dwReserved);
  1982. }
  1983. if (m_pCancel)
  1984. m_pCancel->Cancel(CT_ABORT);
  1985. if (m_pMsgSite)
  1986. m_pMsgSite->Close();
  1987. break;
  1988. case WM_NCDESTROY:
  1989. DOUTL(8, "CNote::WMNCDESTROY");
  1990. WMNCDestroy();
  1991. return 0;
  1992. case WM_ACTIVATEAPP:
  1993. if (wParam && g_hwndActiveModal && g_hwndActiveModal != hwnd &&
  1994. !IsWindowEnabled(hwnd))
  1995. {
  1996. // $MODAL
  1997. // if we are getting activated, and are disabled then
  1998. // bring our 'active' window to the top
  1999. Assert (IsWindow(g_hwndActiveModal));
  2000. PostMessage(g_hwndActiveModal, WM_OE_ACTIVATETHREADWINDOW, 0, 0);
  2001. }
  2002. break;
  2003. case WM_SYSCOMMAND:
  2004. // if we're minimizing, get the control with focus, as when we get the
  2005. // next WM_ACTIVATE we will already be minimized
  2006. if (wParam == SC_MINIMIZE)
  2007. m_hwndFocus = GetFocus();
  2008. break;
  2009. case WM_ACTIVATE:
  2010. if (m_pBodyObj2)
  2011. m_pBodyObj2->HrFrameActivate(LOWORD(wParam) != WA_INACTIVE);
  2012. break;
  2013. case WM_ENDSESSION:
  2014. DOUTL(2, "CNote::WM_ENDSESSION");
  2015. if (wParam)
  2016. DestroyWindow(hwnd);
  2017. return 0;
  2018. case WM_QUERYENDSESSION:
  2019. DOUTL(2, "CNote::WM_QUERYENDSESSION");
  2020. // fall thro'
  2021. case WM_CLOSE:
  2022. if (!m_fForceClose && !FCanClose())
  2023. return 0;
  2024. // listen-up:
  2025. // we have to do this EnableWindowof the modal owner in the WM_CLOSE
  2026. // handler, as WM_DESTROY is too late - USER may have SetFocus to the next
  2027. // active toplevel z-order window (as the note has been hidden by then) - if the
  2028. // window is in another process SetFocus back to the owner will be ignored.
  2029. // Also, in the places we call DestroyWindow we need to make sure we go thro' this
  2030. // WM_CLOSE handler. So all calls to DestroyWindow instead call WM_OE_DESTROYNOTE
  2031. // which sets an internal flag to force down the note (so we don't prompt if dirty)
  2032. // and then calls WM_CLOSE, which falls thro' to DefWndProc and results in a DestroyWindow
  2033. // got it?
  2034. if (m_dwNoteCreateFlags & OENCF_MODAL)
  2035. {
  2036. // Need to enable the owner window
  2037. if (NULL != m_hwndOwner)
  2038. {
  2039. EnableWindow(m_hwndOwner, TRUE);
  2040. }
  2041. }
  2042. break;
  2043. case WM_MEASUREITEM:
  2044. if(m_pBodyObj2 &&
  2045. m_pBodyObj2->HrWMMeasureMenuItem(hwnd, (LPMEASUREITEMSTRUCT)lParam)==S_OK)
  2046. return 0;
  2047. break;
  2048. case WM_DRAWITEM:
  2049. if(m_pBodyObj2 &&
  2050. m_pBodyObj2->HrWMDrawMenuItem(hwnd, (LPDRAWITEMSTRUCT)lParam)==S_OK)
  2051. return 0;
  2052. break;
  2053. case WM_DROPFILES:
  2054. if (m_pHdr)
  2055. m_pHdr->DropFiles((HDROP)wParam, FALSE);
  2056. return 0;
  2057. case WM_COMMAND:
  2058. WMCommand( GET_WM_COMMAND_HWND(wParam, lParam),
  2059. GET_WM_COMMAND_ID(wParam, lParam),
  2060. GET_WM_COMMAND_CMD(wParam, lParam));
  2061. return 0;
  2062. case WM_INITMENUPOPUP:
  2063. return WMInitMenuPopup(hwnd, (HMENU)wParam, (UINT)LOWORD(lParam));
  2064. case WM_GETMINMAXINFO:
  2065. WMGetMinMaxInfo((LPMINMAXINFO)lParam);
  2066. break;
  2067. case WM_MENUSELECT:
  2068. if (LOWORD(wParam)>=ID_STATIONERY_RECENT_0 && LOWORD(wParam)<=ID_STATIONERY_RECENT_9)
  2069. {
  2070. m_pstatus->ShowSimpleText(MAKEINTRESOURCE(idsRSListGeneralHelp));
  2071. return 0;
  2072. }
  2073. if (LOWORD(wParam)>=ID_APPLY_STATIONERY_0 && LOWORD(wParam)<=ID_APPLY_STATIONERY_9)
  2074. {
  2075. m_pstatus->ShowSimpleText(MAKEINTRESOURCE(idsApplyStationeryGeneralHelp));
  2076. return 0;
  2077. }
  2078. if (LOWORD(wParam)>=ID_SIGNATURE_FIRST && LOWORD(wParam)<=ID_SIGNATURE_LAST)
  2079. {
  2080. m_pstatus->ShowSimpleText(MAKEINTRESOURCE(idsInsertSigGeneralHelp));
  2081. return 0;
  2082. }
  2083. if (LOWORD(wParam)>=ID_FORMAT_FIRST && LOWORD(wParam)<=ID_FORMAT_LAST)
  2084. {
  2085. m_pstatus->ShowSimpleText(MAKEINTRESOURCE(idsApplyFormatGeneralHelp));
  2086. return 0;
  2087. }
  2088. HandleMenuSelect(m_pstatus, wParam, lParam);
  2089. return 0;
  2090. case NWM_TESTGETDISP:
  2091. case NWM_TESTGETADDR:
  2092. return lTestHook(msg, wParam, lParam);
  2093. case NWM_UPDATETOOLBAR:
  2094. m_pToolbarObj->Update();
  2095. return 0;
  2096. case NWM_PASTETOATTACHMENT:
  2097. if (m_pHdr)
  2098. m_pHdr->DropFiles((HDROP)wParam, (BOOL)lParam);
  2099. return 0;
  2100. case WM_CONTEXTMENU:
  2101. break;
  2102. case WM_SIZE:
  2103. if(wParam==SIZE_RESTORED) // update global last-size
  2104. GetWindowRect(hwnd, &g_rcLastResize);
  2105. WMSize(LOWORD(lParam), HIWORD(lParam), FALSE);
  2106. break;
  2107. case WM_NOTIFY:
  2108. WMNotify((int) wParam, (NMHDR *)lParam);
  2109. break;
  2110. case WM_SETCURSOR:
  2111. if (!!m_fWindowDisabled)
  2112. {
  2113. HourGlass();
  2114. return TRUE;
  2115. }
  2116. break;
  2117. case WM_DISPLAYCHANGE:
  2118. {
  2119. WINDOWPLACEMENT wp;
  2120. wp.length = sizeof(wp);
  2121. GetWindowPlacement(hwnd, &wp);
  2122. SetWindowPlacement(hwnd, &wp);
  2123. }
  2124. // Drop through
  2125. case WM_WININICHANGE:
  2126. case WM_SYSCOLORCHANGE:
  2127. case WM_QUERYNEWPALETTE:
  2128. case WM_PALETTECHANGED:
  2129. {
  2130. HWND hwndT;
  2131. // pass down to trident
  2132. if (m_pBodyObj2 &&
  2133. m_pBodyObj2->HrGetWindow(&hwndT)==S_OK)
  2134. SendMessage(hwndT, msg, wParam, lParam);
  2135. if (m_pToolbarObj &&
  2136. m_pToolbarObj->GetWindow(&hwndT)==S_OK)
  2137. SendMessage(hwndT, msg, wParam, lParam);
  2138. }
  2139. break;
  2140. default:
  2141. if (g_msgMSWheel && (msg == g_msgMSWheel))
  2142. {
  2143. HWND hwndFocus = GetFocus();
  2144. if (hwndFocus != hwnd)
  2145. return SendMessage(hwndFocus, msg, wParam, lParam);
  2146. }
  2147. break;
  2148. }
  2149. lResult=DefWindowProcWrapW(hwnd, msg, wParam, lParam);
  2150. if (msg==WM_ACTIVATE)
  2151. {
  2152. // need to post-process this
  2153. // save the control with the focus don't do this is we're
  2154. // minimized, otherwise GetFocus()==m_hwnd
  2155. if (!HIWORD(wParam))
  2156. {
  2157. // if not minimized, save/restore child focus
  2158. if ((LOWORD(wParam) == WA_INACTIVE))
  2159. {
  2160. // if deactivating then save the focus
  2161. m_hwndFocus = GetFocus();
  2162. DOUTL(4, "Focus was on 0x%x", m_hwndFocus);
  2163. }
  2164. else
  2165. {
  2166. // if activating, and not minimized then restore focus
  2167. if (IsWindow(m_hwndFocus) &&
  2168. IsChild(hwnd, m_hwndFocus))
  2169. {
  2170. DOUTL(4, "Restoring Focus to: 0x%x", m_hwndFocus);
  2171. SetFocus(m_hwndFocus);
  2172. }
  2173. }
  2174. }
  2175. if (!(m_dwNoteCreateFlags & OENCF_MODAL))
  2176. SetTlsGlobalActiveNote((LOWORD(wParam)==WA_INACTIVE)?NULL:this);
  2177. DOUTL(8, "CNote::WMActivate:: %x", GetTlsGlobalActiveNote());
  2178. }
  2179. return lResult;
  2180. }
  2181. // *************************
  2182. BOOL CNote::FCanClose()
  2183. {
  2184. int id;
  2185. HRESULT hr = S_OK;
  2186. if(IsDirty()==S_FALSE)
  2187. return TRUE;
  2188. // TODO: set the title properly
  2189. id = AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsSaveChangesMsg), NULL, MB_YESNOCANCEL|MB_ICONWARNING);
  2190. if(id==IDCANCEL)
  2191. return FALSE;
  2192. // Note - It's the job of the subclass to display any UI that might
  2193. // describe why saving failed.
  2194. if (id == IDYES)
  2195. hr = SaveMessage(NOFLAGS);
  2196. if (FAILED(hr))
  2197. {
  2198. if (E_PENDING == hr)
  2199. m_fCBDestroyWindow = TRUE;
  2200. return FALSE;
  2201. }
  2202. return TRUE;
  2203. }
  2204. // *************************
  2205. HRESULT CNote::SaveMessage(DWORD dwSaveFlags)
  2206. {
  2207. HRESULT hr;
  2208. IMimeMessage *pMsg = NULL;
  2209. IImnAccount *pAcct = NULL;
  2210. hr = HrCreateMessage(&pMsg);
  2211. if (FAILED(hr))
  2212. goto exit;
  2213. hr = Save(pMsg, 0);
  2214. if (SUCCEEDED(hr))
  2215. {
  2216. hr = m_pHdr->HrGetAccountInHeader(&pAcct);
  2217. if (FAILED(hr))
  2218. goto exit;
  2219. dwSaveFlags |= OESF_UNSENT;
  2220. if (m_fOriginallyWasRead && (OENA_COMPOSE == m_dwNoteAction))
  2221. dwSaveFlags |= OESF_SAVE_IN_ORIG_FOLDER;
  2222. if(IsSecure(pMsg))
  2223. {
  2224. if(AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail),
  2225. MAKEINTRESOURCEW(idsSaveSecMsgToDraft), NULL, MB_OKCANCEL) == IDCANCEL)
  2226. {
  2227. hr = MAPI_E_USER_CANCEL;
  2228. goto exit;
  2229. }
  2230. else
  2231. {
  2232. PROPVARIANT rVariant;
  2233. IMimeBody *pBody = NULL;
  2234. rVariant.vt = VT_BOOL;
  2235. rVariant.boolVal = TRUE;
  2236. hr = pMsg->BindToObject(HBODY_ROOT, IID_IMimeBody, (void **)&pBody);
  2237. if(SUCCEEDED(hr))
  2238. {
  2239. pBody->SetOption(OID_NOSECURITY_ONSAVE, &rVariant);
  2240. ReleaseObj(pBody);
  2241. }
  2242. }
  2243. }
  2244. m_fHasBeenSaved = TRUE;
  2245. _SetPendingOp(SOT_PUT_MESSAGE);
  2246. hr = m_pMsgSite->Save(pMsg, dwSaveFlags, pAcct);
  2247. if (SUCCEEDED(hr))
  2248. _OnComplete(SOT_PUT_MESSAGE, S_OK);
  2249. else
  2250. if (hr == E_PENDING)
  2251. EnableNote(FALSE);
  2252. }
  2253. exit:
  2254. ReleaseObj(pAcct);
  2255. ReleaseObj(pMsg);
  2256. return hr;
  2257. }
  2258. // *************************
  2259. void CNote::WMNCDestroy()
  2260. {
  2261. if (m_dwNoteCreateFlags & OENCF_MODAL)
  2262. PostQuitMessage(0);
  2263. SetWndThisPtr(m_hwnd, NULL);
  2264. m_hwnd=NULL;
  2265. Release();
  2266. }
  2267. // *************************
  2268. void CNote::ChangeReadToComposeIfUnsent(IMimeMessage *pMsg)
  2269. {
  2270. DWORD dwStatusFlags = 0;
  2271. if (m_fReadNote && SUCCEEDED(m_pMsgSite->GetStatusFlags(&dwStatusFlags)) &&
  2272. (OEMSF_UNSENT & dwStatusFlags))
  2273. {
  2274. m_dwNoteAction = OENA_COMPOSE;
  2275. m_fReadNote = FALSE;
  2276. }
  2277. }
  2278. // *************************
  2279. void CNote::ReloadMessageFromSite(BOOL fOriginal)
  2280. {
  2281. IMimeMessage *pMsg = NULL;
  2282. BOOL fBool = FALSE,
  2283. fTempHtml;
  2284. DWORD dwBodyStyle = MESTYLE_NOHEADER,
  2285. dwMsgFlags;
  2286. HRESULT hr = S_OK,
  2287. tempHr;
  2288. if (OENA_FORWARDBYATTACH == m_dwNoteAction)
  2289. dwMsgFlags = (OEGM_ORIGINAL|OEGM_AS_ATTACH);
  2290. else
  2291. dwMsgFlags = (fOriginal ? OEGM_ORIGINAL : NOFLAGS);
  2292. hr = m_pMsgSite->GetMessage(&pMsg, &fBool, dwMsgFlags, &tempHr);
  2293. if (SUCCEEDED(hr))
  2294. {
  2295. // ~~~ Check what happens here if message is not downloaded and hit forward as attach
  2296. DWORD dwFlags = 0;
  2297. m_fCompleteMsg = !!fBool;
  2298. // All notes will be read note unless unsent
  2299. m_dwNoteAction = OENA_READ;
  2300. m_fOriginallyWasRead = TRUE;
  2301. m_fReadNote = TRUE;
  2302. // Is this an unsent message and is a read note? Then should be a compose.
  2303. ChangeReadToComposeIfUnsent(pMsg);
  2304. // This needs to be called for the case where we load an IMAP message. In this
  2305. // case we don't know if it is html or not. We won't know until after it is
  2306. // downloaded. That is what is happening at this point. Before we do our
  2307. // load, let's make sure that we have set m_fHtml properly. RAID 46327
  2308. if(CheckSecReceipt(pMsg) == S_OK)
  2309. fTempHtml = TRUE;
  2310. else
  2311. {
  2312. pMsg->GetFlags(&dwFlags);
  2313. fTempHtml = !!(dwFlags & IMF_HTML);
  2314. }
  2315. // If m_fHtml was already set correctly, then don't do it again.
  2316. if (fTempHtml != m_fHtml)
  2317. {
  2318. m_fFormatbarVisible = m_fHtml = fTempHtml;
  2319. if (!m_fReadNote && !m_fBodyContainsFrames && m_fFormatbarVisible)
  2320. dwBodyStyle = MESTYLE_FORMATBAR;
  2321. m_pBodyObj2->HrSetStyle(dwBodyStyle);
  2322. m_pBodyObj2->HrEnableHTMLMode(m_fHtml);
  2323. }
  2324. Load(pMsg);
  2325. InitMenusAndToolbars();
  2326. pMsg->Release();
  2327. if (FAILED(tempHr))
  2328. ShowErrorScreen(tempHr);
  2329. }
  2330. else
  2331. {
  2332. if (E_FAIL == hr)
  2333. m_fCBDestroyWindow = TRUE;
  2334. }
  2335. }
  2336. // *************************
  2337. HRESULT CNote::WMCommand(HWND hwndCmd, int id, WORD wCmd)
  2338. {
  2339. int iRet = 0;
  2340. DWORD dwFlags = 0;
  2341. FOLDERID folderID = FOLDERID_INVALID;
  2342. DOUTL(4, "CNote::WMCommand");
  2343. OLECMD cmd;
  2344. // We can hit this via accelerators. Since accelerators don't go through
  2345. // QueryStatus(), we need to make sure this should really be enabled.
  2346. cmd.cmdID = id;
  2347. cmd.cmdf = 0;
  2348. if (FAILED(QueryStatus(&CMDSETID_OutlookExpress, 1, &cmd, NULL)) || (0 == (cmd.cmdf & OLECMDF_ENABLED)))
  2349. return (S_OK);
  2350. // see if any of these are for the body control, if so we're done...
  2351. if(m_pBodyObj2 && SUCCEEDED(m_pBodyObj2->HrWMCommand(hwndCmd, id, wCmd)))
  2352. return S_OK;
  2353. // give the header a shot after the note is done
  2354. if (m_pHdr &&
  2355. m_pHdr->WMCommand(hwndCmd, id, wCmd)==S_OK)
  2356. return S_OK;
  2357. // Don't handle anything that isn't a menu item or accelerator
  2358. if (wCmd <= 1)
  2359. {
  2360. if ((id == ID_SEND_NOW) || (id >= ID_SEND_NOW_ACCOUNT_FIRST && id <= ID_SEND_NOW_ACCOUNT_LAST) ||
  2361. (id == ID_SEND_LATER) || (id >= ID_SEND_LATER_ACCOUNT_FIRST && id <= ID_SEND_LATER_ACCOUNT_LAST))
  2362. {
  2363. HrSendMail(id);
  2364. return S_OK;
  2365. }
  2366. if (id >= ID_LANG_FIRST && id <= ID_LANG_LAST)
  2367. {
  2368. SwitchLanguage(id);
  2369. return S_OK;
  2370. }
  2371. if (id>=ID_ADD_RECIPIENT_FIRST && id<=ID_ADD_RECIPIENT_LAST)
  2372. {
  2373. if (m_pHdr)
  2374. m_pHdr->AddRecipient(id - ID_ADD_RECIPIENT_FIRST);
  2375. return S_OK;
  2376. }
  2377. if (id > ID_MSWEB_BASE && id < ID_MSWEB_LAST)
  2378. {
  2379. OnHelpGoto(m_hwnd, id);
  2380. return S_OK;
  2381. }
  2382. // Handle all "create new note" IDs
  2383. Assert(m_pMsgSite);
  2384. if (m_pMsgSite)
  2385. {
  2386. m_pMsgSite->GetFolderID(&folderID);
  2387. if (MenuUtil_HandleNewMessageIDs(id, m_hwnd, folderID, m_fMail, (m_dwNoteCreateFlags & OENCF_MODAL)?TRUE:FALSE, m_punkPump))
  2388. return S_OK;
  2389. }
  2390. // ONLY processing menu accelerators
  2391. switch(id)
  2392. {
  2393. case ID_SEND_DEFAULT:
  2394. HrSendMail(DwGetOption(OPT_SENDIMMEDIATE) && !g_pConMan->IsGlobalOffline() ? ID_SEND_NOW : ID_SEND_LATER);
  2395. return S_OK;
  2396. case ID_ABOUT:
  2397. DoAboutAthena(m_hwnd, idiMail);
  2398. return S_OK;
  2399. case ID_SAVE:
  2400. SaveMessage(NOFLAGS);
  2401. return S_OK;
  2402. case ID_NOTE_DELETE:
  2403. {
  2404. HRESULT hr;
  2405. m_fOrgCmdWasDelete = TRUE;
  2406. _SetPendingOp(SOT_DELETING_MESSAGES);
  2407. hr = m_pMsgSite->Delete(NOFLAGS);
  2408. if (SUCCEEDED(hr))
  2409. _OnComplete(SOT_DELETING_MESSAGES, S_OK);
  2410. else
  2411. {
  2412. if (hr == E_PENDING)
  2413. EnableNote(FALSE);
  2414. else
  2415. AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrDeleteMsg), NULL, MB_OK);
  2416. }
  2417. return S_OK;
  2418. }
  2419. case ID_NOTE_COPY_TO_FOLDER:
  2420. case ID_NOTE_MOVE_TO_FOLDER:
  2421. {
  2422. HRESULT hr;
  2423. IMimeMessage *pMsg = NULL;
  2424. DWORD dwStatusFlags = 0;
  2425. m_fCBCopy = (ID_NOTE_COPY_TO_FOLDER == id);
  2426. m_pMsgSite->GetStatusFlags(&dwStatusFlags);
  2427. if (S_OK == IsDirty() || ((OEMSF_FROM_MSG | OEMSF_VIRGIN) & dwStatusFlags))
  2428. {
  2429. CommitChangesInNote();
  2430. pMsg = m_pMsg;
  2431. }
  2432. if(IsSecure(m_pMsg) && !m_fReadNote)
  2433. {
  2434. if(AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail),
  2435. MAKEINTRESOURCEW(idsSaveSecMsgToFolder), NULL, MB_OKCANCEL) == IDCANCEL)
  2436. return S_OK;
  2437. else
  2438. {
  2439. PROPVARIANT rVariant;
  2440. IMimeBody *pBody = NULL;
  2441. rVariant.vt = VT_BOOL;
  2442. rVariant.boolVal = TRUE;
  2443. hr = m_pMsg->BindToObject(HBODY_ROOT, IID_IMimeBody, (void **)&pBody);
  2444. if(SUCCEEDED(hr))
  2445. {
  2446. pBody->SetOption(OID_NOSECURITY_ONSAVE, &rVariant);
  2447. ReleaseObj(pBody);
  2448. }
  2449. }
  2450. }
  2451. _SetPendingOp(SOT_COPYMOVE_MESSAGE);
  2452. hr = m_pMsgSite->DoCopyMoveToFolder(m_fCBCopy, pMsg, !m_fReadNote);
  2453. if (SUCCEEDED(hr))
  2454. _OnComplete(SOT_COPYMOVE_MESSAGE, S_OK);
  2455. else if (E_PENDING == hr)
  2456. EnableNote(FALSE);
  2457. return S_OK;
  2458. }
  2459. case ID_NEXT_UNREAD_MESSAGE:
  2460. case ID_NEXT_UNREAD_THREAD:
  2461. case ID_NEXT_UNREAD_ARTICLE:
  2462. dwFlags = OENF_UNREAD;
  2463. if (ID_NEXT_UNREAD_THREAD == id)
  2464. dwFlags |= OENF_THREAD;
  2465. // Fall through
  2466. case ID_PREVIOUS:
  2467. case ID_NEXT_MESSAGE:
  2468. {
  2469. HRESULT hr;
  2470. dwFlags |= (m_fMail ? OENF_SKIPMAIL : OENF_SKIPNEWS);
  2471. hr = m_pMsgSite->DoNextPrev((ID_PREVIOUS != id), dwFlags);
  2472. if (SUCCEEDED(hr))
  2473. {
  2474. ReloadMessageFromSite();
  2475. AssertSz(!m_fCBDestroyWindow, "Shouldn't need to destroy the window...");
  2476. }
  2477. #ifdef DEBUG
  2478. // All DoNextPrev does is set the new message ID. Should never need to go
  2479. // E_PENDING to get that information
  2480. else if (E_PENDING == hr)
  2481. AssertSz(FALSE, "Didn't expect to get an E_PENDING with NextPrev.");
  2482. #endif
  2483. else
  2484. MessageBeep(MB_OK);
  2485. return S_OK;
  2486. }
  2487. case ID_MARK_THREAD_READ:
  2488. MarkMessage(MARK_MESSAGE_READ, APPLY_CHILDREN);
  2489. return S_OK;
  2490. case ID_NOTE_PROPERTIES:
  2491. DoProperties();
  2492. return S_OK;
  2493. case ID_REPLY:
  2494. case ID_REPLY_GROUP:
  2495. case ID_REPLY_ALL:
  2496. case ID_FORWARD:
  2497. case ID_FORWARD_AS_ATTACH:
  2498. {
  2499. DWORD dwAction = 0;
  2500. RECT rc;
  2501. HRESULT hr = S_OK;
  2502. GetWindowRect(m_hwnd, &rc);
  2503. switch (id)
  2504. {
  2505. case ID_REPLY: dwAction = OENA_REPLYTOAUTHOR; break;
  2506. case ID_REPLY_GROUP: dwAction = OENA_REPLYTONEWSGROUP; break;
  2507. case ID_REPLY_ALL: dwAction = OENA_REPLYALL; break;
  2508. case ID_FORWARD: dwAction = OENA_FORWARD; break;
  2509. case ID_FORWARD_AS_ATTACH: dwAction = OENA_FORWARDBYATTACH; break;
  2510. default: AssertSz(dwAction, "We are about to create a note with no action."); break;
  2511. };
  2512. AssertSz(m_pMsgSite, "We are about to create a note with a null m_pMsgSite.");
  2513. hr = CreateAndShowNote(dwAction, m_dwNoteCreateFlags, NULL, m_hwnd, m_punkPump, &rc, m_pMsgSite);
  2514. if (SUCCEEDED(hr))
  2515. {
  2516. // Since the new note has this site now, I don't need to keep track of it.
  2517. // More importantly, if I do, I break the new note since I will try to
  2518. // close the msgsite on my destroy notification. If I haven't released it,
  2519. // I would then null out items in
  2520. SafeRelease(m_pMsgSite);
  2521. PostMessage(m_hwnd, WM_OE_DESTROYNOTE, 0, 0);
  2522. }
  2523. else if (m_fReadNote && (MAPI_E_USER_CANCEL != hr))
  2524. AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrReplyForward), NULL, MB_OK);
  2525. return S_OK;
  2526. }
  2527. case ID_HELP_CONTENTS:
  2528. OEHtmlHelp(GetParent(m_hwnd), c_szMailHelpFileHTML, HH_DISPLAY_TOPIC, (DWORD_PTR) (LPCSTR) c_szCtxHelpDefault);
  2529. return S_OK;
  2530. case ID_README:
  2531. DoReadme(m_hwnd);
  2532. break;
  2533. case ID_SEND_OBJECTS:
  2534. m_fPackageImages = !m_fPackageImages;
  2535. return S_OK;
  2536. case ID_NEW_CONTACT:
  2537. #if 0
  2538. Assert(g_pABInit);
  2539. if (g_pABInit)
  2540. g_pABInit->NewContact( m_hwnd );
  2541. #endif
  2542. nyi("New contact");
  2543. return S_OK;
  2544. case ID_NOTE_SAVE_AS:
  2545. SaveMessageAs();
  2546. return S_OK;
  2547. case ID_CHECK_NAMES:
  2548. HeaderExecCommand(MSOEENVCMDID_CHECKNAMES, MSOCMDEXECOPT_PROMPTUSER, NULL);
  2549. return S_OK;
  2550. case ID_SELECT_RECIPIENTS:
  2551. HeaderExecCommand(MSOEENVCMDID_SELECTRECIPIENTS, MSOCMDEXECOPT_DODEFAULT, NULL);
  2552. return S_OK;
  2553. case ID_SELECT_NEWSGROUPS:
  2554. HeaderExecCommand(MSOEENVCMDID_PICKNEWSGROUPS, MSOCMDEXECOPT_DODEFAULT, NULL);
  2555. return S_OK;
  2556. case ID_NEWSGROUPS:
  2557. HeaderExecCommand(MSOEENVCMDID_PICKNEWSGROUPS, MSOCMDEXECOPT_DODEFAULT, NULL);
  2558. return S_OK;
  2559. case ID_ADDRESS_BOOK:
  2560. HeaderExecCommand(MSOEENVCMDID_VIEWCONTACTS, MSOCMDEXECOPT_DODEFAULT, NULL);
  2561. return S_OK;
  2562. case ID_CREATE_RULE_FROM_MESSAGE:
  2563. {
  2564. MESSAGEINFO msginfo = {0};
  2565. return HrCreateRuleFromMessage(m_hwnd, (FALSE == m_fMail) ? CRFMF_NEWS : CRFMF_MAIL, &msginfo, m_pMsg);
  2566. }
  2567. break;
  2568. case ID_BLOCK_SENDER:
  2569. {
  2570. return _HrBlockSender((FALSE == m_fMail) ? RULE_TYPE_NEWS : RULE_TYPE_MAIL, m_pMsg, m_hwnd);
  2571. }
  2572. break;
  2573. case ID_FIND_MESSAGE:
  2574. DoFindMsg(FOLDERID_ROOT, FOLDER_ROOTNODE);
  2575. break;
  2576. case ID_FIND_PEOPLE:
  2577. {
  2578. TCHAR szWABExePath[MAX_PATH];
  2579. if(S_OK == HrLoadPathWABEXE(szWABExePath, sizeof(szWABExePath)))
  2580. ShellExecute(NULL, "open", szWABExePath, "/find", "", SW_SHOWNORMAL);
  2581. break;
  2582. }
  2583. case ID_OPTIONS:
  2584. ShowOptions(m_hwnd, ATHENA_OPTIONS, 0, NULL);
  2585. break;
  2586. case ID_ACCOUNTS:
  2587. {
  2588. DoAccountListDialog(m_hwnd, m_fMail?ACCT_MAIL:ACCT_NEWS);
  2589. break;
  2590. }
  2591. case ID_ADD_ALL_TO:
  2592. HeaderExecCommand(MSOEENVCMDID_ADDALLONTO, MSOCMDEXECOPT_DODEFAULT, NULL);
  2593. break;
  2594. case ID_ADD_SENDER:
  2595. if(m_fMail)
  2596. {
  2597. if (m_pHdr)
  2598. m_pHdr->AddRecipient(-1);
  2599. }
  2600. else
  2601. HeaderExecCommand(MSOEENVCMDID_ADDSENDER, MSOCMDEXECOPT_DODEFAULT, NULL);
  2602. return S_OK;
  2603. case ID_INSERT_CONTACT_INFO:
  2604. HeaderExecCommand(MSOEENVCMDID_VCARD, MSOCMDEXECOPT_DODEFAULT, NULL);
  2605. return S_OK;
  2606. case ID_FULL_HEADERS:
  2607. m_fFullHeaders = !m_fFullHeaders;
  2608. if(m_pHdr)
  2609. m_pHdr->ShowAdvancedHeaders(m_fFullHeaders);
  2610. if (m_fMail)
  2611. SetDwOption((m_fReadNote ? OPT_MAILNOTEADVREAD : OPT_MAILNOTEADVSEND), m_fFullHeaders, NULL, 0);
  2612. else
  2613. SetDwOption((m_fReadNote ? OPT_NEWSNOTEADVREAD : OPT_NEWSNOTEADVSEND), m_fFullHeaders, NULL, 0);
  2614. return S_OK;
  2615. case ID_CUT:
  2616. SendMessage(GetFocus(), WM_CUT, 0, 0);
  2617. return S_OK;
  2618. case ID_NOTE_COPY:
  2619. case ID_COPY:
  2620. SendMessage(GetFocus(), WM_COPY, 0, 0);
  2621. return S_OK;
  2622. case ID_PASTE:
  2623. SendMessage(GetFocus(), WM_PASTE, 0, 0);
  2624. return S_OK;
  2625. case ID_SHOW_TOOLBAR:
  2626. ToggleToolbar();
  2627. return S_OK;
  2628. case ID_CUSTOMIZE:
  2629. SendMessage(m_hwndToolbar, TB_CUSTOMIZE, 0, 0);
  2630. break;
  2631. case ID_FORMATTING_TOOLBAR:
  2632. ToggleFormatbar();
  2633. return S_OK;
  2634. case ID_STATUS_BAR:
  2635. ToggleStatusbar();
  2636. return S_OK;
  2637. case ID_UNDO:
  2638. Edit_Undo(GetFocus());
  2639. return S_OK;
  2640. case ID_SELECT_ALL:
  2641. Edit_SetSel(GetFocus(), 0, -1);
  2642. return S_OK;
  2643. case ID_CLOSE:
  2644. SendMessage(m_hwnd, WM_CLOSE, 0, 0);
  2645. return S_OK;
  2646. case ID_SPELLING:
  2647. if (FCheckSpellAvail() && (!m_fReadNote))
  2648. {
  2649. HWND hwndFocus = GetFocus();
  2650. HRESULT hr;
  2651. hr = m_pBodyObj2->HrSpellCheck(FALSE);
  2652. if(FAILED(hr))
  2653. AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrSpellGenericSpell), NULL, MB_OK | MB_ICONSTOP);
  2654. SetFocus(hwndFocus);
  2655. }
  2656. return S_OK;
  2657. case ID_FORMAT_SETTINGS:
  2658. FormatSettings();
  2659. return S_OK;
  2660. case ID_WORK_OFFLINE:
  2661. if (g_pConMan)
  2662. g_pConMan->SetGlobalOffline(!g_pConMan->IsGlobalOffline(), hwndCmd);
  2663. if (m_pToolbarObj)
  2664. m_pToolbarObj->Update();
  2665. break;
  2666. case ID_RICH_TEXT:
  2667. case ID_PLAIN_TEXT:
  2668. // noops
  2669. if(id==ID_RICH_TEXT && m_fHtml)
  2670. return S_OK;
  2671. if(id==ID_PLAIN_TEXT && !m_fHtml)
  2672. return S_OK;
  2673. // if going to plain, warn the user he'll loose formatting...
  2674. if((ID_PLAIN_TEXT == id) &&
  2675. (IDCANCEL == DoDontShowMeAgainDlg(m_hwnd, c_szDSHtmlToPlain, MAKEINTRESOURCE(idsAthena),
  2676. MAKEINTRESOURCE(idsWarnHTMLToPlain), MB_OKCANCEL)))
  2677. return S_OK;
  2678. m_fHtml=!!(id==ID_RICH_TEXT);
  2679. m_fFormatbarVisible=!!m_fHtml;
  2680. m_pBodyObj2->HrSetStyle(m_fHtml ? MESTYLE_FORMATBAR : MESTYLE_NOHEADER);
  2681. m_pBodyObj2->HrEnableHTMLMode(m_fHtml);
  2682. // if going into plain-mode blow away formatting
  2683. if (!m_fHtml)
  2684. m_pBodyObj2->HrDowngradeToPlainText();
  2685. return S_OK;
  2686. case ID_DIGITALLY_SIGN:
  2687. HeaderExecCommand(MSOEENVCMDID_DIGSIGN, MSOCMDEXECOPT_DODEFAULT, NULL);
  2688. return S_OK;
  2689. case ID_ENCRYPT:
  2690. if(m_pHdr->ForceEncryption(NULL, FALSE) == S_FALSE)
  2691. HeaderExecCommand(MSOEENVCMDID_ENCRYPT, MSOCMDEXECOPT_DODEFAULT, NULL);
  2692. return S_OK;
  2693. case ID_INCLUDE_LABEL:
  2694. m_fSecurityLabel = !m_fSecurityLabel;
  2695. CheckAndForceEncryption();
  2696. return S_OK;
  2697. case ID_LABEL_SETTINGS:
  2698. if(m_pLabel)
  2699. {
  2700. if(DialogBoxParamWrapW(g_hLocRes, MAKEINTRESOURCEW(iddSelectLabel),
  2701. m_hwnd, SecurityLabelsDlgProc, (LPARAM) &m_pLabel) != IDOK)
  2702. return (S_FALSE);
  2703. CheckAndForceEncryption();
  2704. }
  2705. return S_OK;
  2706. case ID_SEC_RECEIPT_REQUEST:
  2707. m_fSecReceiptRequest = !m_fSecReceiptRequest;
  2708. break;
  2709. case ID_FLAG_MESSAGE:
  2710. m_dwCBMarkType = (!IsFlagged(ARF_FLAGGED)) ? MARK_MESSAGE_FLAGGED : MARK_MESSAGE_UNFLAGGED;
  2711. MarkMessage(m_dwCBMarkType, APPLY_SPECIFIED);
  2712. return S_OK;
  2713. case ID_WATCH_THREAD:
  2714. m_dwCBMarkType = (!IsFlagged(ARF_WATCH)) ? MARK_MESSAGE_WATCH : MARK_MESSAGE_NORMALTHREAD;
  2715. MarkMessage(m_dwCBMarkType, APPLY_SPECIFIED);
  2716. return S_OK;
  2717. case ID_IGNORE_THREAD:
  2718. m_dwCBMarkType = (!IsFlagged(ARF_IGNORE)) ? MARK_MESSAGE_IGNORE : MARK_MESSAGE_NORMALTHREAD;
  2719. MarkMessage(m_dwCBMarkType, APPLY_SPECIFIED);
  2720. return S_OK;
  2721. case ID_APPLY_STATIONERY_0:
  2722. case ID_APPLY_STATIONERY_1:
  2723. case ID_APPLY_STATIONERY_2:
  2724. case ID_APPLY_STATIONERY_3:
  2725. case ID_APPLY_STATIONERY_4:
  2726. case ID_APPLY_STATIONERY_5:
  2727. case ID_APPLY_STATIONERY_6:
  2728. case ID_APPLY_STATIONERY_7:
  2729. case ID_APPLY_STATIONERY_8:
  2730. case ID_APPLY_STATIONERY_9:
  2731. case ID_APPLY_STATIONERY_MORE:
  2732. case ID_APPLY_STATIONERY_NONE:
  2733. {
  2734. AssertSz(m_fHtml, "QueryStatus should have caught this and not let this function run.");
  2735. HRESULT hr;
  2736. WCHAR wszBuf[INTERNET_MAX_URL_LENGTH+1];
  2737. *wszBuf = 0;
  2738. switch (id)
  2739. {
  2740. case ID_APPLY_STATIONERY_MORE:
  2741. hr = HrGetMoreStationeryFileName(m_hwnd, wszBuf);
  2742. break;
  2743. case ID_APPLY_STATIONERY_NONE:
  2744. *wszBuf=0;
  2745. hr = NOERROR;
  2746. break;
  2747. default:
  2748. hr = HrGetStationeryFileName(id - ID_APPLY_STATIONERY_0, wszBuf);
  2749. if (FAILED(hr))
  2750. {
  2751. AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthena),
  2752. MAKEINTRESOURCEW(idsErrStationeryNotFound), NULL, MB_OK | MB_ICONERROR);
  2753. HrRemoveFromStationeryMRU(wszBuf);
  2754. }
  2755. break;
  2756. }
  2757. if(m_pBodyObj2 && SUCCEEDED(hr))
  2758. {
  2759. hr = m_pBodyObj2->HrApplyStationery(wszBuf);
  2760. if(SUCCEEDED(hr))
  2761. HrAddToStationeryMRU(wszBuf);
  2762. }
  2763. return S_OK;
  2764. case IDOK:
  2765. case IDCANCEL:
  2766. // ignore these
  2767. return S_OK;
  2768. case ID_REQUEST_READRCPT:
  2769. m_pMsgSite->Notify(OEMSN_TOGGLE_READRCPT_REQ);
  2770. return S_OK;
  2771. default:
  2772. if(id>=ID_ADDROBJ_OLE_FIRST && id <=ID_ADDROBJ_OLE_LAST)
  2773. {
  2774. DoNoteOleVerb(id-ID_ADDROBJ_OLE_FIRST);
  2775. return S_OK;
  2776. }
  2777. }
  2778. }
  2779. }
  2780. if(wCmd==NHD_SIZECHANGE &&
  2781. id==idcNoteHdr)
  2782. {
  2783. DOUTL(8, "CNote::NHD_SIZECHANGE - doing note WMSize");
  2784. //header control is requesting a resize
  2785. WMSize(NULL, NULL, TRUE);
  2786. return S_OK;
  2787. }
  2788. return S_FALSE;
  2789. }
  2790. // *************************
  2791. BOOL CNote::IsFlagged(DWORD dwFlag)
  2792. {
  2793. BOOL fFlagged = FALSE;
  2794. MESSAGEFLAGS dwCurrFlags = 0;
  2795. Assert(m_pMsgSite);
  2796. if (m_pMsgSite)
  2797. {
  2798. // Readnote and compose note are the only ones that can be flagged. The others might
  2799. // be flagged in the store, but since we are replying or forwarding, etc, they can't
  2800. // be flagged. RAID 37729
  2801. if ((m_fReadNote || (OENA_COMPOSE == m_dwNoteAction)) && SUCCEEDED(m_pMsgSite->GetMessageFlags(&dwCurrFlags)))
  2802. fFlagged = (0 != (dwFlag & dwCurrFlags));
  2803. }
  2804. return fFlagged;
  2805. }
  2806. // *************************
  2807. void CNote::DeferedLanguageMenu()
  2808. {
  2809. HMENU hMenu = m_hMenu;
  2810. Assert (hMenu);
  2811. if (!m_hmenuLanguage)
  2812. { // load global MIME language codepage data
  2813. InitMultiLanguage();
  2814. }
  2815. else
  2816. {
  2817. // Charset chaching mechanism requires us to reconstruct
  2818. // language menu every time
  2819. DestroyMenu(m_hmenuLanguage);
  2820. }
  2821. m_hmenuLanguage = CreateMimeLanguageMenu(m_fMail, m_fReadNote, CustomGetCPFromCharset(m_hCharset, m_fReadNote));
  2822. }
  2823. // *************************
  2824. LRESULT CNote::WMInitMenuPopup(HWND hwnd, HMENU hmenuPopup, UINT uPos)
  2825. {
  2826. MENUITEMINFO mii;
  2827. HMENU hmenuMain;
  2828. HWND hwndFocus=GetFocus();
  2829. DWORD dwFlags=0;
  2830. BOOL fEnableStyleMenu = FALSE;
  2831. hmenuMain = m_hMenu;
  2832. mii.cbSize = sizeof(MENUITEMINFO);
  2833. mii.fMask = MIIM_ID | MIIM_SUBMENU;
  2834. if (hmenuMain == NULL ||!GetMenuItemInfo(hmenuMain, uPos, TRUE, &mii) || mii.hSubMenu != hmenuPopup)
  2835. {
  2836. if (GetMenuItemInfo(hmenuMain, ID_POPUP_LANGUAGE_DEFERRED, FALSE, &mii) && mii.hSubMenu == hmenuPopup)
  2837. {
  2838. mii.wID=ID_POPUP_LANGUAGE;
  2839. mii.fMask = MIIM_ID;
  2840. SetMenuItemInfo(hmenuMain, ID_POPUP_LANGUAGE_DEFERRED, FALSE, &mii);
  2841. }
  2842. mii.fMask = MIIM_ID | MIIM_SUBMENU;
  2843. if (GetMenuItemInfo(hmenuMain, ID_POPUP_LANGUAGE, FALSE, &mii) && mii.hSubMenu == hmenuPopup)
  2844. {
  2845. DeferedLanguageMenu();
  2846. mii.fMask = MIIM_SUBMENU;
  2847. mii.wID=ID_POPUP_LANGUAGE;
  2848. hmenuPopup = mii.hSubMenu = m_hmenuLanguage;
  2849. SetMenuItemInfo(hmenuMain, ID_POPUP_LANGUAGE, FALSE, &mii);
  2850. }
  2851. else return 1;
  2852. }
  2853. switch (mii.wID)
  2854. {
  2855. case ID_POPUP_FILE:
  2856. case ID_POPUP_EDIT:
  2857. case ID_POPUP_VIEW:
  2858. break;
  2859. case ID_POPUP_INSERT:
  2860. InitSigPopupMenu(hmenuPopup, NULL);
  2861. break;
  2862. case ID_POPUP_FORMAT:
  2863. {
  2864. AddStationeryMenu(hmenuPopup, ID_POPUP_STATIONERY, ID_APPLY_STATIONERY_0, ID_APPLY_STATIONERY_MORE);
  2865. fEnableStyleMenu = TRUE;
  2866. break;
  2867. }
  2868. case ID_POPUP_TOOLS:
  2869. if (m_fMail)
  2870. {
  2871. DeleteMenu(hmenuPopup, ID_SELECT_NEWSGROUPS, MF_BYCOMMAND);
  2872. #ifdef SMIME_V3
  2873. if (!FPresentPolicyRegInfo())
  2874. {
  2875. DeleteMenu(hmenuPopup, ID_INCLUDE_LABEL, MF_BYCOMMAND);
  2876. DeleteMenu(hmenuPopup, ID_LABEL_SETTINGS, MF_BYCOMMAND);
  2877. m_fSecurityLabel = FALSE;
  2878. }
  2879. if(!IsSMIME3Supported())
  2880. {
  2881. DeleteMenu(hmenuPopup, ID_SEC_RECEIPT_REQUEST, MF_BYCOMMAND);
  2882. m_fSecReceiptRequest = FALSE;
  2883. }
  2884. #endif
  2885. }
  2886. else
  2887. {
  2888. DeleteMenu(hmenuPopup, ID_REQUEST_READRCPT, MF_BYCOMMAND);
  2889. #ifdef SMIME_V3
  2890. DeleteMenu(hmenuPopup, ID_INCLUDE_LABEL, MF_BYCOMMAND);
  2891. DeleteMenu(hmenuPopup, ID_LABEL_SETTINGS, MF_BYCOMMAND);
  2892. DeleteMenu(hmenuPopup, ID_SEC_RECEIPT_REQUEST, MF_BYCOMMAND);
  2893. m_fSecurityLabel = FALSE;
  2894. m_fSecReceiptRequest = FALSE;
  2895. #endif
  2896. }
  2897. if (GetMenuItemInfo(hmenuPopup, ID_POPUP_ADDRESS_BOOK, FALSE, &mii))
  2898. m_pHdr->UpdateRecipientMenu(mii.hSubMenu);
  2899. break;
  2900. case ID_POPUP_MESSAGE:
  2901. {
  2902. AddStationeryMenu(hmenuPopup, ID_POPUP_NEW_MSG, ID_STATIONERY_RECENT_0, ID_STATIONERY_MORE);
  2903. break;
  2904. }
  2905. case ID_POPUP_LANGUAGE:
  2906. {
  2907. if (m_pBodyObj2)
  2908. m_pBodyObj2->HrOnInitMenuPopup(hmenuPopup, ID_POPUP_LANGUAGE);
  2909. break;
  2910. }
  2911. }
  2912. MenuUtil_EnablePopupMenu(hmenuPopup, this);
  2913. if (fEnableStyleMenu)
  2914. {
  2915. if (m_pBodyObj2)
  2916. m_pBodyObj2->UpdateBackAndStyleMenus(hmenuPopup);
  2917. }
  2918. return S_OK;
  2919. }
  2920. // *************************
  2921. void CNote::RemoveNewMailIcon(void)
  2922. {
  2923. HRESULT hr;
  2924. FOLDERINFO fiFolderInfo;
  2925. FOLDERID idFolder;
  2926. // If a message is marked (read or deleted) and it's from the Inbox,
  2927. // remove the new mail notification icon from the tray
  2928. if (NULL == g_pInstance || NULL == m_pMsgSite || NULL == g_pStore)
  2929. return;
  2930. hr = m_pMsgSite->GetFolderID(&idFolder);
  2931. if (FAILED(hr))
  2932. return;
  2933. hr = g_pStore->GetFolderInfo(idFolder, &fiFolderInfo);
  2934. if (SUCCEEDED(hr))
  2935. {
  2936. if (FOLDER_INBOX == fiFolderInfo.tySpecial)
  2937. g_pInstance->UpdateTrayIcon(TRAYICONACTION_REMOVE);
  2938. g_pStore->FreeRecord(&fiFolderInfo);
  2939. }
  2940. }
  2941. // *************************
  2942. LRESULT CNote::OnInitMenuPopup(HWND hwnd, HMENU hmenuPopup, UINT uPos, UINT wID)
  2943. {
  2944. return 0;
  2945. }
  2946. // *************************
  2947. void CNote::WMGetMinMaxInfo(LPMINMAXINFO pmmi)
  2948. {
  2949. MINMAXINFO mmi={0};
  2950. RECT rc;
  2951. int cy;
  2952. ULONG cyAttMan=0;
  2953. HWND hwnd;
  2954. cy=GetRequiredHdrHeight();
  2955. Assert(IsWindow(m_hwndToolbar));
  2956. if(IsWindowVisible(m_hwndToolbar))
  2957. {
  2958. GetWindowRect(m_hwndToolbar, &rc);
  2959. cy += cyRect(rc);
  2960. }
  2961. cy += GetSystemMetrics(SM_CYCAPTION);
  2962. cy += GetSystemMetrics(SM_CYMENU);
  2963. cy += 2*cyMinEdit;
  2964. pmmi->ptMinTrackSize.x=200; //hack
  2965. pmmi->ptMinTrackSize.y=cy;
  2966. }
  2967. // *************************
  2968. INT CNote::GetRequiredHdrHeight()
  2969. {
  2970. RECT rc={0};
  2971. if(m_pHdr)
  2972. m_pHdr->GetRect(&rc);
  2973. return cyRect(rc);
  2974. }
  2975. // *************************
  2976. LONG CNote::lTestHook(UINT uMsg, WPARAM wParam, LPARAM lParam)
  2977. {
  2978. return 0;
  2979. }
  2980. // *************************
  2981. void CNote::WMNotify(int idFrom, NMHDR *pnmh)
  2982. {
  2983. switch(pnmh->code)
  2984. {
  2985. case NM_SETFOCUS:
  2986. if (pnmh)
  2987. OnSetFocus(pnmh->hwndFrom);
  2988. break;
  2989. case NM_KILLFOCUS:
  2990. OnKillFocus();
  2991. break;
  2992. case BDN_DOWNLOADCOMPLETE:
  2993. OnDocumentReady();
  2994. break;
  2995. case BDN_MARKASSECURE:
  2996. MarkMessage(MARK_MESSAGE_NOSECUI, APPLY_SPECIFIED);
  2997. break;
  2998. case TBN_DROPDOWN:
  2999. OnDropDown(m_hwnd, pnmh);
  3000. break;
  3001. }
  3002. }
  3003. // *************************
  3004. void CNote::OnDocumentReady()
  3005. {
  3006. if (!m_fOnDocReadyHandled && m_fCompleteMsg)
  3007. {
  3008. HRESULT hr;
  3009. DWORD dwStatusFlags;
  3010. m_fOnDocReadyHandled = TRUE;
  3011. m_pMsgSite->GetStatusFlags(&dwStatusFlags);
  3012. // once, we've got a successfull download, we can init the attachment manager.
  3013. // we can't do this before, as we have to wait until Trident has requested MHTML parts so we
  3014. // can mark them as inlined. If we're in a reply or reply all then we have to remove the unused
  3015. // attachments at this time
  3016. if (IsReplyNote())
  3017. HrRemoveAttachments(m_pMsg, FALSE);
  3018. // #62618: hack. if forwarding a multi/altern in (force) plain-text mode then the html part
  3019. // shows up as an attachment
  3020. // we call GetTextBody here on the html body if we're a plaintext node in forward so that
  3021. // PID_ATT_RENDERED is set before we load teh attachment well
  3022. if (m_dwNoteAction == OENA_FORWARD && m_fHtml == FALSE)
  3023. {
  3024. HBODY hBody;
  3025. IStream *pstm;
  3026. if (m_pMsg &&
  3027. !FAILED(m_pMsg->GetTextBody(TXT_HTML, IET_DECODED, &pstm, NULL)))
  3028. pstm->Release();
  3029. }
  3030. if (m_pHdr)
  3031. {
  3032. if (FAILED(m_pHdr->OnDocumentReady(m_pMsg)))
  3033. AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrAttmanLoadFail), NULL, MB_OK|MB_ICONEXCLAMATION);
  3034. m_pHdr->SetVCard((OEMSF_FROM_MSG|OEMSF_VIRGIN) & dwStatusFlags);
  3035. }
  3036. ClearDirtyFlag();
  3037. // RAID-25300 - FE-J:Athena: Newsgroup article and mail sent with charset=_autodetect
  3038. // Internet Encoded and Windows Encoding are CPI_AUTODETECT
  3039. {
  3040. INETCSETINFO CsetInfo ;
  3041. HCHARSET hCharset = NULL ;
  3042. int nIdm = 0 ;
  3043. // if it is a new message, check if charset equals to default charset
  3044. if ((OENA_COMPOSE == m_dwNoteAction) && (OEMSF_VIRGIN & dwStatusFlags))
  3045. {
  3046. // defer default charset reading until now ..
  3047. if (g_hDefaultCharsetForMail==NULL)
  3048. ReadSendMailDefaultCharset();
  3049. if (m_hCharset != g_hDefaultCharsetForMail )
  3050. hCharset = g_hDefaultCharsetForMail ;
  3051. // get CharsetInfo from HCHARSET
  3052. if ( hCharset)
  3053. MimeOleGetCharsetInfo(hCharset,&CsetInfo);
  3054. else
  3055. MimeOleGetCharsetInfo(m_hCharset,&CsetInfo);
  3056. }
  3057. else
  3058. // get CharsetInfo from HCHARSET
  3059. MimeOleGetCharsetInfo(m_hCharset,&CsetInfo);
  3060. // re-map CP_JAUTODETECT and CP_KAUTODETECT if necessary
  3061. // re-map iso-2022-jp to default charset if they are in the same category
  3062. if (!m_fReadNote)
  3063. {
  3064. hCharset = GetMimeCharsetFromCodePage(GetMapCP(CsetInfo.cpiInternet, FALSE));
  3065. }
  3066. else
  3067. {
  3068. VARIANTARG va;
  3069. va.vt = VT_BOOL;
  3070. va.boolVal = VARIANT_TRUE;
  3071. m_pCmdTargetBody->Exec(&CMDSETID_MimeEdit, MECMDID_TABLINKS, 0, &va, NULL);
  3072. }
  3073. // has a new charset defined, change it
  3074. ChangeCharset(hCharset);
  3075. // if user want's auto complete, enable it once we're fully loaded
  3076. if (DwGetOption(OPT_USEAUTOCOMPLETE))
  3077. HeaderExecCommand(MSOEENVCMDID_AUTOCOMPLETE, MSOCMDEXECOPT_DODEFAULT, NULL);
  3078. if (m_fReadNote && m_fMail && m_pMsgSite)
  3079. {
  3080. if(m_pMsgSite->Notify(OEMSN_PROCESS_READRCPT_REQ) != S_OK)
  3081. return;
  3082. }
  3083. }
  3084. if(DwGetOption(OPT_RTL_MSG_DIR) && ((m_dwNoteAction == OENA_FORWARDBYATTACH) || (OEMSF_VIRGIN & dwStatusFlags)))
  3085. {
  3086. if(FAILED(m_pCmdTargetBody->Exec(&CMDSETID_Forms3, IDM_DIRRTL, OLECMDEXECOPT_DODEFAULT, NULL, NULL)))
  3087. AthMessageBoxW(g_hwndInit, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrRTLDirFailed), NULL, MB_OK);
  3088. }
  3089. EnterCriticalSection(&m_csNoteState);
  3090. if(m_nisNoteState == NIS_INIT)
  3091. m_nisNoteState = NIS_NORMAL;
  3092. LeaveCriticalSection(&m_csNoteState);
  3093. }
  3094. }
  3095. HRESULT CNote::ChangeCharset(HCHARSET hCharset)
  3096. {
  3097. HRESULT hr = S_OK;
  3098. if (hCharset && (hCharset != m_hCharset))
  3099. {
  3100. Assert(m_pBodyObj2);
  3101. IF_FAILEXIT(hr = m_pBodyObj2->HrSetCharset(hCharset));
  3102. // set the new charset into the message and call HrLanguageChange to update the headers
  3103. m_hCharset = hCharset;
  3104. if (m_pMsg)
  3105. m_pMsg->SetCharset(hCharset, CSET_APPLY_ALL);
  3106. if (m_pHdr)
  3107. m_pHdr->ChangeLanguage(m_pMsg);
  3108. UpdateTitle();
  3109. }
  3110. exit:
  3111. return hr;
  3112. }
  3113. HRESULT CNote::GetCharset(HCHARSET *phCharset)
  3114. {
  3115. Assert(phCharset);
  3116. *phCharset = m_hCharset;
  3117. return S_OK;
  3118. }
  3119. // *************************
  3120. LRESULT CNote::OnDropDown(HWND hwnd, LPNMHDR lpnmh)
  3121. {
  3122. UINT i;
  3123. HMENU hMenuPopup;
  3124. RECT rc;
  3125. DWORD dwCmd;
  3126. TBNOTIFY *ptbn = (TBNOTIFY *)lpnmh;
  3127. if (ptbn->iItem == ID_SET_PRIORITY)
  3128. {
  3129. hMenuPopup = LoadPopupMenu(IDR_PRIORITY_POPUP);
  3130. if (hMenuPopup != NULL)
  3131. {
  3132. for (i = 0; i < 3; i++)
  3133. CheckMenuItem(hMenuPopup, i, MF_UNCHECKED | MF_BYPOSITION);
  3134. m_pHdr->GetPriority(&i);
  3135. Assert(i != priNone);
  3136. CheckMenuItem(hMenuPopup, 2 - i, MF_CHECKED | MF_BYPOSITION);
  3137. DoToolbarDropdown(hwnd, lpnmh, hMenuPopup);
  3138. DestroyMenu(hMenuPopup);
  3139. }
  3140. }
  3141. else if (ptbn->iItem == ID_INSERT_SIGNATURE)
  3142. {
  3143. hMenuPopup = CreatePopupMenu();
  3144. if (hMenuPopup != NULL)
  3145. {
  3146. FillSignatureMenu(hMenuPopup, NULL);
  3147. DoToolbarDropdown(hwnd, lpnmh, hMenuPopup);
  3148. DestroyMenu(hMenuPopup);
  3149. }
  3150. }
  3151. else if(ptbn->iItem == ID_POPUP_LANGUAGE)
  3152. {
  3153. DeferedLanguageMenu();
  3154. hMenuPopup = m_hmenuLanguage;
  3155. if(hMenuPopup)
  3156. {
  3157. MenuUtil_EnablePopupMenu(hMenuPopup, this);
  3158. DoToolbarDropdown(hwnd, lpnmh, hMenuPopup);
  3159. }
  3160. }
  3161. return(TBDDRET_DEFAULT);
  3162. }
  3163. // *************************
  3164. void CNote::UpdateMsgOptions(LPMIMEMESSAGE pMsg)
  3165. {
  3166. // Store the options onto the message object
  3167. SideAssert(SUCCEEDED(HrSetMailOptionsOnMessage(pMsg, &m_rHtmlOpt, &m_rPlainOpt, m_hCharset, m_fHtml)));
  3168. }
  3169. // *************************
  3170. HRESULT CNote::SetComposeStationery()
  3171. {
  3172. LPSTREAM pstm;
  3173. WCHAR wszFile[MAX_PATH];
  3174. HRESULT hr=E_FAIL;
  3175. HCHARSET hCharset;
  3176. ENCODINGTYPE ietEncoding = IET_DECODED;
  3177. BOOL fLittleEndian;
  3178. AssertSz(m_fHtml, "Are you sure you want to set stationery in plain-text mode??");
  3179. if (!(m_dwNoteCreateFlags & OENCF_NOSTATIONERY) && m_pMsg &&
  3180. DwGetOption(m_fMail?OPT_MAIL_USESTATIONERY:OPT_NEWS_USESTATIONERY) &&
  3181. SUCCEEDED(GetDefaultStationeryName(m_fMail, wszFile)))
  3182. {
  3183. if (SUCCEEDED(hr = HrCreateBasedWebPage(wszFile, &pstm)))
  3184. {
  3185. if (S_OK == HrIsStreamUnicode(pstm, &fLittleEndian))
  3186. {
  3187. if (SUCCEEDED(MimeOleFindCharset("utf-8", &hCharset)))
  3188. {
  3189. m_pMsg->SetCharset(hCharset, CSET_APPLY_ALL);
  3190. }
  3191. ietEncoding = IET_UNICODE;
  3192. }
  3193. hr = m_pMsg->SetTextBody(TXT_HTML, ietEncoding, NULL, pstm, NULL);
  3194. pstm->Release();
  3195. m_fUseStationeryFonts = TRUE;
  3196. }
  3197. }
  3198. return hr;
  3199. }
  3200. // *************************
  3201. HRESULT CNote::CycleThroughControls(BOOL fForward)
  3202. {
  3203. HRESULT hr = CheckTabStopArrays();
  3204. if (SUCCEEDED(hr))
  3205. {
  3206. int index, newIndex;
  3207. BOOL fFound = FALSE;
  3208. HWND hCurr = GetFocus();
  3209. for (index = 0; index < m_cTabStopCount; index++)
  3210. if (hCurr == m_pTabStopArray[index])
  3211. {
  3212. fFound = TRUE;
  3213. break;
  3214. }
  3215. newIndex = fFound ? GetNextIndex(index, fForward) : m_iIndexOfBody;
  3216. if (newIndex == m_iIndexOfBody)
  3217. m_pBodyObj2->HrUIActivate(TRUE);
  3218. else
  3219. SetFocus(m_pTabStopArray[newIndex]);
  3220. }
  3221. return hr;
  3222. }
  3223. // *************************
  3224. HRESULT CNote::CheckTabStopArrays()
  3225. {
  3226. HRESULT hr = S_OK;
  3227. if (m_fTabStopsSet)
  3228. return S_OK;
  3229. m_fTabStopsSet = TRUE;
  3230. HWND *pArray = m_pTabStopArray;
  3231. int cCount = MAX_HEADER_COMP;
  3232. hr = m_pHdr->GetTabStopArray(pArray, &cCount);
  3233. if (FAILED(hr))
  3234. goto error;
  3235. pArray += cCount;
  3236. m_cTabStopCount = cCount;
  3237. cCount = MAX_BODY_COMP;
  3238. hr = m_pBodyObj2->GetTabStopArray(pArray, &cCount);
  3239. if (FAILED(hr))
  3240. goto error;
  3241. // This assumes that the first in the list returned from m_pBodyObj2-GetTabStopArray
  3242. // is the Trident window handle. If that changes where it returns more than one
  3243. // handle, or something else, this simple index scheme won't work
  3244. m_iIndexOfBody = m_cTabStopCount;
  3245. pArray += cCount;
  3246. m_cTabStopCount += cCount;
  3247. cCount = MAX_ATTMAN_COMP;
  3248. m_cTabStopCount += cCount;
  3249. return S_OK;
  3250. error:
  3251. m_cTabStopCount = 0;
  3252. m_fTabStopsSet = FALSE;
  3253. return hr;
  3254. }
  3255. // *************************
  3256. int CNote::GetNextIndex(int index, BOOL fForward)
  3257. {
  3258. LONG style;
  3259. int cTotalTested = 0;
  3260. BOOL fGoodHandleFound;
  3261. do
  3262. {
  3263. if (fForward)
  3264. {
  3265. index++;
  3266. if (index >= m_cTabStopCount)
  3267. index = 0;
  3268. }
  3269. else
  3270. {
  3271. // If this is true, other asserts should have fired before now.
  3272. Assert(m_cTabStopCount > 0);
  3273. index--;
  3274. if (index < 0)
  3275. index = m_cTabStopCount - 1;
  3276. }
  3277. style = GetWindowLong(m_pTabStopArray[index], GWL_STYLE);
  3278. cTotalTested++;
  3279. fGoodHandleFound = ((0 == (style & WS_DISABLED)) &&
  3280. (style & WS_VISIBLE) &&
  3281. ((style & WS_TABSTOP) || (index == m_iIndexOfBody))); // Trident doesn't mark itself as a tabstop
  3282. } while (!fGoodHandleFound && (cTotalTested < m_cTabStopCount));
  3283. if (cTotalTested >= m_cTabStopCount)
  3284. index = m_iIndexOfBody;
  3285. return index;
  3286. }
  3287. // *************************
  3288. HRESULT CreateAndShowNote(DWORD dwAction, DWORD dwCreateFlags, INIT_MSGSITE_STRUCT *pInitStruct,
  3289. HWND hwnd, IUnknown *punk, RECT *prc, IOEMsgSite *pMsgSite)
  3290. {
  3291. HRESULT hr = S_OK;
  3292. CNote *pNote = NULL;
  3293. AssertSz((pMsgSite || pInitStruct), "Should have either a pInitStruct or a pMsgSite...");
  3294. // If we are coming from news, we might need to pass off this call to the smapi
  3295. // client. If we reply or forward a message that was news, pass it off to smapi
  3296. if ((OENCF_NEWSFIRST & dwCreateFlags) && ((OENA_REPLYTOAUTHOR == dwAction) || (OENA_FORWARD == dwAction) || (OENA_FORWARDBYATTACH == dwAction)))
  3297. {
  3298. // fIsDefaultMailConfiged hits the reg, only check for last result
  3299. if (!FIsDefaultMailConfiged())
  3300. {
  3301. IOEMsgSite *pSite = NULL;
  3302. CStoreCB *pCB = NULL;
  3303. //send using smapi
  3304. if (pInitStruct)
  3305. {
  3306. pCB = new CStoreCB;
  3307. if (!pCB)
  3308. hr = E_OUTOFMEMORY;
  3309. if (SUCCEEDED(hr))
  3310. hr = pCB->Initialize(hwnd, MAKEINTRESOURCE(idsSendingToOutbox), TRUE);
  3311. if (SUCCEEDED(hr))
  3312. pSite = new COEMsgSite();
  3313. if (!pSite)
  3314. hr = E_OUTOFMEMORY;
  3315. if (SUCCEEDED(hr))
  3316. hr = pSite->Init(pInitStruct);
  3317. if (SUCCEEDED(hr))
  3318. pSite->SetStoreCallback(pCB);
  3319. }
  3320. else
  3321. ReplaceInterface(pSite, pMsgSite);
  3322. if (pSite)
  3323. {
  3324. if (SUCCEEDED(hr))
  3325. {
  3326. IMimeMessage *pMsg = NULL;
  3327. BOOL fCompleteMsg;
  3328. HRESULT hres = E_FAIL;
  3329. DWORD dwMsgFlags = (OENA_FORWARDBYATTACH == dwAction) ? (OEGM_ORIGINAL|OEGM_AS_ATTACH) : NOFLAGS;
  3330. hr = pSite->GetMessage(&pMsg, &fCompleteMsg, dwMsgFlags, &hres);
  3331. if (E_PENDING == hr)
  3332. {
  3333. AssertSz((pCB && pMsgSite), "Should never get E_PENDING with pMsgSite being NULL");
  3334. pCB->Block();
  3335. pCB->Close();
  3336. hr = pSite->GetMessage(&pMsg, &fCompleteMsg, dwMsgFlags, &hres);
  3337. }
  3338. if (pCB)
  3339. pCB->Close();
  3340. if (SUCCEEDED(hr))
  3341. {
  3342. if (SUCCEEDED(hres))
  3343. hr = NewsUtil_ReFwdByMapi(hwnd, pMsg, dwAction);
  3344. pMsg->Release();
  3345. }
  3346. }
  3347. // Don't want to close the site if it came from another note...
  3348. if (!pMsgSite)
  3349. pSite->Close();
  3350. pSite->Release();
  3351. }
  3352. ReleaseObj(pCB);
  3353. // if we succeeded, then we need to tell the creator that we
  3354. // cancelled the creation through OE and went with the smapi client
  3355. return (FAILED(hr) ? hr : MAPI_E_USER_CANCEL);
  3356. }
  3357. }
  3358. //We are the default smapi client
  3359. pNote = new CNote;
  3360. if (pNote)
  3361. hr = pNote->Init(dwAction, dwCreateFlags, prc, hwnd, pInitStruct, pMsgSite, punk);
  3362. else
  3363. hr = E_OUTOFMEMORY;
  3364. if (SUCCEEDED(hr))
  3365. hr = pNote->Show();
  3366. ReleaseObj(pNote);
  3367. if (FAILED(hr))
  3368. AthErrorMessageW(hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrNewsCantOpen), hr);
  3369. return hr;
  3370. }
  3371. // *************************
  3372. HRESULT CNote::SaveMessageAs()
  3373. {
  3374. HRESULT hr=S_OK;
  3375. IMimeMessage *pSecMsg=NULL;
  3376. BOOL fCanbeDurt = !m_fReadNote;
  3377. PROPVARIANT rVariant;
  3378. IMimeBody *pBody = NULL;
  3379. // Raid #25822: we can't just get the message source if it
  3380. // is a secure message
  3381. if (m_fReadNote/* && IsSecure(m_pMsg)*/)
  3382. {
  3383. // Won't care about these since the user already loaded the message
  3384. BOOL fCompleteMsg = FALSE;
  3385. HRESULT tempHr = S_OK;
  3386. m_pMsgSite->GetMessage(&pSecMsg, &fCompleteMsg, OEGM_ORIGINAL, &tempHr);
  3387. AssertSz(fCompleteMsg && SUCCEEDED(tempHr), "Shouldn't have reached this point if the load failed now.");
  3388. }
  3389. else
  3390. {
  3391. hr = CommitChangesInNote();
  3392. if (FAILED(hr))
  3393. goto error;
  3394. // if a compose note, set the X-Unsent header if saving to .eml files, and save the props.
  3395. MimeOleSetBodyPropA(m_pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_XUNSENT), NOFLAGS, "1");
  3396. if(IsSecure(m_pMsg))
  3397. {
  3398. if(AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail),
  3399. MAKEINTRESOURCEW(idsSaveSecMsgToFolder), NULL, MB_OKCANCEL) == IDCANCEL)
  3400. goto error;
  3401. else
  3402. {
  3403. rVariant.vt = VT_BOOL;
  3404. rVariant.boolVal = TRUE;
  3405. hr = m_pMsg->BindToObject(HBODY_ROOT, IID_IMimeBody, (void **)&pBody);
  3406. if(SUCCEEDED(hr))
  3407. {
  3408. pBody->SetOption(OID_NOSECURITY_ONSAVE, &rVariant);
  3409. ReleaseObj(pBody);
  3410. }
  3411. fCanbeDurt = FALSE;
  3412. }
  3413. }
  3414. }
  3415. // SaveMessageToFile displays a failure error.
  3416. _SetPendingOp(SOT_PUT_MESSAGE);
  3417. hr = HrSaveMessageToFile(m_hwnd, (pSecMsg ? pSecMsg : m_pMsg), m_pMsg, !m_fMail, fCanbeDurt);
  3418. if (SUCCEEDED(hr))
  3419. _OnComplete(SOT_PUT_MESSAGE, S_OK);
  3420. else if (E_PENDING == hr)
  3421. {
  3422. EnableNote(FALSE);
  3423. hr = S_OK;
  3424. }
  3425. error:
  3426. ReleaseObj(pSecMsg);
  3427. return hr;
  3428. }
  3429. // *************************
  3430. HRESULT CNote::CommitChangesInNote()
  3431. {
  3432. LPMIMEMESSAGE pMsg=0;
  3433. HRESULT hr=S_OK;
  3434. Assert(m_pMsg);
  3435. if (!m_fReadNote && !m_fBodyContainsFrames)
  3436. {
  3437. if (FAILED(HrCreateMessage(&pMsg)))
  3438. return E_FAIL;
  3439. hr = Save(pMsg, 0);
  3440. if (SUCCEEDED(hr))
  3441. ReplaceInterface(m_pMsg, pMsg)
  3442. pMsg->Release();
  3443. }
  3444. return hr;
  3445. }
  3446. // *************************
  3447. void CNote::ToggleFormatbar()
  3448. {
  3449. m_fFormatbarVisible = !m_fFormatbarVisible;
  3450. SetDwOption(OPT_SHOW_NOTE_FMTBAR, m_fFormatbarVisible, NULL, 0);
  3451. m_pBodyObj2->HrSetStyle(m_fFormatbarVisible ? MESTYLE_FORMATBAR : MESTYLE_NOHEADER);
  3452. }
  3453. // *************************
  3454. void CNote::ToggleStatusbar()
  3455. {
  3456. RECT rc;
  3457. m_fStatusbarVisible = !m_fStatusbarVisible;
  3458. SetDwOption(OPT_SHOW_NOTE_STATUSBAR, m_fStatusbarVisible, NULL, 0);
  3459. m_pstatus->ShowStatus(m_fStatusbarVisible);
  3460. // cause a size
  3461. GetWindowRect(m_hwnd, &rc);
  3462. WMSize(rc.right-rc.left, rc.bottom-rc.top, FALSE);
  3463. }
  3464. // *************************
  3465. HRESULT CNote::ToggleToolbar()
  3466. {
  3467. RECT rc;
  3468. m_fToolbarVisible = !m_fToolbarVisible;
  3469. if (m_pToolbarObj)
  3470. m_pToolbarObj->HideToolbar(!m_fToolbarVisible);
  3471. GetWindowRect(m_hwnd, &rc);
  3472. // cause a size
  3473. WMSize(rc.right-rc.left, rc.bottom-rc.top, FALSE);
  3474. return S_OK;
  3475. }
  3476. // *************************
  3477. void CNote::FormatSettings()
  3478. {
  3479. AssertSz(m_fReadNote, "this is broken for readnote!!!");
  3480. if (m_fHtml)
  3481. FGetHTMLOptions(m_hwnd, &m_rHtmlOpt);
  3482. else
  3483. FGetPlainOptions(m_hwnd, &m_rPlainOpt);
  3484. }
  3485. // *************************
  3486. void CNote::SwitchLanguage(int idm)
  3487. {
  3488. HCHARSET hCharset, hOldCharset;
  3489. HRESULT hr;
  3490. hCharset = GetMimeCharsetFromMenuID(idm);
  3491. if (!hCharset || (hCharset == m_hCharset))
  3492. return;
  3493. hOldCharset = m_hCharset;
  3494. // View|Language in a view does not affect the listview as in v1. It only affect the preview.
  3495. // the user can change his default charset to get changes in the listview
  3496. // setcharset on the body object will cause it to refresh with new fonts etc.
  3497. hr = ChangeCharset(hCharset);
  3498. if (FAILED(hr))
  3499. {
  3500. AthMessageBoxW( m_hwnd, MAKEINTRESOURCEW(idsAthena),
  3501. MAKEINTRESOURCEW((hr == hrIncomplete)?idsViewLangMimeDBBad:idsErrViewLanguage),
  3502. NULL, MB_OK|MB_ICONEXCLAMATION);
  3503. goto Exit;
  3504. }
  3505. // here after we ask user if he wants to add this change to charset remapping list
  3506. m_pMsgSite->SwitchLanguage(hOldCharset, hCharset);
  3507. Exit:
  3508. return;
  3509. }
  3510. // *************************
  3511. BOOL CNote::DoProperties()
  3512. {
  3513. NOMSGDATA noMsgData;
  3514. MSGPROP msgProp;
  3515. UINT pri;
  3516. TCHAR szSubj[256];
  3517. TCHAR szLocation[1024];
  3518. LPSTR pszLocation = NULL;
  3519. WCHAR wszLocation[1024];
  3520. BOOL fSucceeded;
  3521. msgProp.pNoMsgData = &noMsgData;
  3522. msgProp.hwndParent = m_hwnd;
  3523. msgProp.type = (m_fMail ? MSGPROPTYPE_MAIL : MSGPROPTYPE_NEWS);
  3524. msgProp.mpStartPage = MP_GENERAL;
  3525. msgProp.szFolderName = 0; // This one needs to have special handling
  3526. msgProp.pSecureMsg = NULL;
  3527. msgProp.lpWabal = NULL;
  3528. msgProp.szFolderName = szLocation;
  3529. *szLocation = 0;
  3530. m_pMsgSite->GetLocation(wszLocation, ARRAYSIZE(wszLocation));
  3531. pszLocation = PszToANSI(CP_ACP, wszLocation);
  3532. StrCpyN(szLocation, pszLocation, ARRAYSIZE(szLocation));
  3533. MemFree(pszLocation);
  3534. if (m_fReadNote)
  3535. {
  3536. msgProp.dwFlags = ARF_RECEIVED;
  3537. msgProp.pMsg = m_pMsg;
  3538. msgProp.fSecure = IsSecure(msgProp.pMsg);
  3539. if (msgProp.fSecure)
  3540. {
  3541. BOOL fCompleteMsg = FALSE;
  3542. HRESULT tempHr = S_OK;
  3543. m_pMsgSite->GetMessage(&msgProp.pSecureMsg, &fCompleteMsg, OEGM_ORIGINAL, &tempHr);
  3544. AssertSz(fCompleteMsg && SUCCEEDED(tempHr), "Shouldn't have reached this point if the load failed now.");
  3545. HrGetWabalFromMsg(msgProp.pMsg, &msgProp.lpWabal);
  3546. }
  3547. }
  3548. else
  3549. {
  3550. msgProp.dwFlags = ARF_UNSENT;
  3551. msgProp.pMsg = NULL;
  3552. }
  3553. m_pHdr->GetPriority(&pri);
  3554. if (pri==priLow)
  3555. noMsgData.Pri=IMSG_PRI_LOW;
  3556. else if (pri==priHigh)
  3557. noMsgData.Pri=IMSG_PRI_HIGH;
  3558. else
  3559. noMsgData.Pri=IMSG_PRI_NORMAL;
  3560. noMsgData.pszFrom = NULL;
  3561. noMsgData.pszSent = NULL;
  3562. noMsgData.ulSize = 0;
  3563. noMsgData.cAttachments = 0;
  3564. m_pHdr->HrGetAttachCount(&noMsgData.cAttachments);
  3565. GetWindowText(m_hwnd, szSubj, sizeof(szSubj)/sizeof(TCHAR));
  3566. noMsgData.pszSubject = szSubj;
  3567. msgProp.fFromListView = FALSE;
  3568. fSucceeded = (S_OK == HrMsgProperties(&msgProp));
  3569. ReleaseObj(msgProp.lpWabal);
  3570. ReleaseObj(msgProp.pSecureMsg);
  3571. return fSucceeded;
  3572. }
  3573. // *************************
  3574. HRESULT CNote::HrSendMail(int id)
  3575. {
  3576. IImnAccount *pAccount=NULL;
  3577. ULONG i;
  3578. BOOL fFound=FALSE;
  3579. HRESULT hr;
  3580. BOOL fSendLater = (id == ID_SEND_LATER);
  3581. VARIANTARG varIn;
  3582. DWORD dwMsgSiteFlags=0;
  3583. // Do spell check if needed
  3584. if (FCheckSpellAvail() && FCheckOnSend())
  3585. {
  3586. HWND hwndFocus=GetFocus();
  3587. hr=m_pBodyObj2->HrSpellCheck(TRUE);
  3588. if (FAILED(hr) || hr==HR_S_SPELLCANCEL)
  3589. {
  3590. if (AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsSpellMsgSendOK), NULL, MB_YESNO | MB_ICONEXCLAMATION ) != IDYES)
  3591. {
  3592. SetFocus(hwndFocus);
  3593. return E_FAIL;
  3594. }
  3595. }
  3596. }
  3597. if (!m_fMail && m_pBodyObj2)
  3598. {
  3599. BOOL fEmpty = FALSE;
  3600. if (SUCCEEDED(m_pBodyObj2->HrIsEmpty(&fEmpty)) && fEmpty)
  3601. {
  3602. if (AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsNoTextInNewsPost), NULL, MB_YESNO | MB_ICONEXCLAMATION ) != IDYES)
  3603. return MAPI_E_USER_CANCEL;
  3604. }
  3605. }
  3606. // During the send, a call to the note save gets made. During
  3607. // that call, IMimeMessage::Commit gets called. That is a big perf hit.
  3608. // It turns out that commit will get called a second time anyway. So
  3609. // set a flag to tell the save not to commit.
  3610. m_fCommitSave = FALSE;
  3611. hr = HeaderExecCommand(MSOEENVCMDID_SEND, fSendLater?MSOCMDEXECOPT_DODEFAULT:MSOCMDEXECOPT_DONTPROMPTUSER, NULL);
  3612. m_fCommitSave = TRUE;
  3613. // REVIEW: dhaws: I don't think this happens anymore. I think the send call no longer returns the conflict
  3614. //RAID 8780: This message MIME_S_CHARSET_CONFLICT will get propagated to here. Now change it to an E_FAIL;
  3615. if (MIME_S_CHARSET_CONFLICT == hr)
  3616. hr = E_FAIL;
  3617. if (FAILED(hr))
  3618. goto error;
  3619. if (m_pMsgSite)
  3620. m_pMsgSite->GetStatusFlags(&dwMsgSiteFlags);
  3621. // If has been saved, then this note is store based in drafts and
  3622. // need to delete the draft.
  3623. if (((OENA_COMPOSE == m_dwNoteAction) || m_fHasBeenSaved) && !(dwMsgSiteFlags & OEMSF_FROM_FAT))
  3624. {
  3625. HRESULT hr;
  3626. _SetPendingOp(SOT_DELETING_MESSAGES);
  3627. hr = m_pMsgSite->Delete(DELETE_MESSAGE_NOTRASHCAN | DELETE_MESSAGE_NOPROMPT);
  3628. if (SUCCEEDED(hr))
  3629. {
  3630. m_fCBDestroyWindow = TRUE;
  3631. _OnComplete(SOT_DELETING_MESSAGES, S_OK);
  3632. }
  3633. else if (E_PENDING == hr)
  3634. {
  3635. EnableNote(FALSE);
  3636. m_fCBDestroyWindow = TRUE;
  3637. }
  3638. else
  3639. {
  3640. // ~~~ Can we handle this a bit better???
  3641. AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrDeleteMsg), NULL, MB_OK);
  3642. }
  3643. }
  3644. // If note is reply or forward, then mark the message as appropriate
  3645. else if (IsReplyNote() || (OENA_FORWARD == m_dwNoteAction) || (OENA_FORWARDBYATTACH == m_dwNoteAction))
  3646. {
  3647. HRESULT hr;
  3648. BOOL fForwarded = (OENA_FORWARD == m_dwNoteAction) || (OENA_FORWARDBYATTACH == m_dwNoteAction);
  3649. // Clear any previous flags so we don't show both, only the most recent
  3650. m_dwMarkOnReplyForwardState = MORFS_CLEARING;
  3651. hr = MarkMessage(fForwarded ? MARK_MESSAGE_UNREPLIED : MARK_MESSAGE_UNFORWARDED, APPLY_SPECIFIED);
  3652. if (FAILED(hr) && (E_PENDING != hr))
  3653. {
  3654. // Even though we have an error, we can still close the note because the send did work.
  3655. PostMessage(m_hwnd, WM_OE_DESTROYNOTE, 0, 0);
  3656. m_dwMarkOnReplyForwardState = MORFS_UNKNOWN;
  3657. }
  3658. }
  3659. // Web Page and stationery
  3660. else
  3661. PostMessage(m_hwnd, WM_OE_DESTROYNOTE, 0, 0);
  3662. error:
  3663. ReleaseObj(pAccount);
  3664. return hr;
  3665. }
  3666. // *************************
  3667. HRESULT CNote::QueryService(REFGUID guidService, REFIID riid, LPVOID *ppvObject)
  3668. {
  3669. if (IsEqualGUID(guidService, IID_IOEMsgSite) &&
  3670. IsEqualGUID(riid, IID_IOEMsgSite))
  3671. {
  3672. if (!m_pMsgSite)
  3673. return E_FAIL;
  3674. *ppvObject = (LPVOID)m_pMsgSite;
  3675. m_pMsgSite->AddRef();
  3676. return S_OK;
  3677. }
  3678. return E_NOINTERFACE;
  3679. }
  3680. // *************************
  3681. HRESULT CNote::MarkMessage(MARK_TYPE dwFlags, APPLYCHILDRENTYPE dwApplyType)
  3682. {
  3683. HRESULT hr;
  3684. // [PaulHi] 6/8/99 We need to restore the pending operation
  3685. // if the MarkMessage() call fails.
  3686. STOREOPERATIONTYPE tyPrevOperation = m_OrigOperationType;
  3687. _SetPendingOp(SOT_SET_MESSAGEFLAGS);
  3688. hr = m_pMsgSite->MarkMessage(dwFlags, dwApplyType);
  3689. if (SUCCEEDED(hr))
  3690. _OnComplete(SOT_SET_MESSAGEFLAGS, S_OK);
  3691. else if (E_PENDING == hr)
  3692. {
  3693. EnableNote(FALSE);
  3694. EnterCriticalSection(&m_csNoteState);
  3695. if(m_nisNoteState == NIS_INIT)
  3696. m_nisNoteState = NIS_FIXFOCUS;
  3697. LeaveCriticalSection(&m_csNoteState);
  3698. hr = S_OK;
  3699. }
  3700. else
  3701. {
  3702. // Restore previous operation to ensure the note window will be
  3703. // re-enabled.
  3704. _SetPendingOp(tyPrevOperation);
  3705. }
  3706. return hr;
  3707. }
  3708. HRESULT CNote::_SetPendingOp(STOREOPERATIONTYPE tyOperation)
  3709. {
  3710. m_OrigOperationType = tyOperation;
  3711. return S_OK;
  3712. }
  3713. void CNote::EnableNote(BOOL fEnable)
  3714. {
  3715. Assert (IsWindow(m_hwnd));
  3716. m_fInternal = 1;
  3717. if (fEnable)
  3718. {
  3719. if (m_fWindowDisabled)
  3720. {
  3721. EnableWindow(m_hwnd, TRUE);
  3722. if (m_hCursor)
  3723. {
  3724. SetCursor(m_hCursor);
  3725. m_hCursor = 0;
  3726. }
  3727. m_fWindowDisabled = FALSE;
  3728. }
  3729. }
  3730. else
  3731. {
  3732. if (!m_fWindowDisabled)
  3733. {
  3734. m_fWindowDisabled = TRUE;
  3735. EnableWindow(m_hwnd, FALSE);
  3736. m_hCursor = HourGlass();
  3737. }
  3738. }
  3739. m_fInternal = 0;
  3740. }
  3741. // *************************
  3742. void CNote::SetStatusText(LPSTR szBuf)
  3743. {
  3744. if(m_pstatus)
  3745. m_pstatus->SetStatusText(szBuf);
  3746. }
  3747. // *************************
  3748. void CNote::SetProgressPct(INT iPct)
  3749. {
  3750. // if (m_pstatus)
  3751. // m_pstatus->SetProgressBarPos(1, iPct, FALSE);
  3752. }
  3753. // *************************
  3754. HRESULT CNote::GetBorderDW(IUnknown* punkSrc, LPRECT lprectBorder)
  3755. {
  3756. GetClientRect(m_hwnd, lprectBorder);
  3757. DOUTL(4, "CNote::GetBorderDW called returning=%x,%x,%x,%x",
  3758. lprectBorder->left, lprectBorder->top, lprectBorder->right, lprectBorder->bottom);
  3759. return S_OK;
  3760. }
  3761. // *************************
  3762. HRESULT CNote::RequestBorderSpaceDW(IUnknown* punkSrc, LPCBORDERWIDTHS pborderwidths)
  3763. {
  3764. DOUTL(4, "CNote::ReqestBorderSpaceST pborderwidths=%x,%x,%x,%x",
  3765. pborderwidths->left, pborderwidths->top, pborderwidths->right, pborderwidths->bottom);
  3766. return S_OK;
  3767. }
  3768. // *************************
  3769. HRESULT CNote::SetBorderSpaceDW(IUnknown* punkSrc, LPCBORDERWIDTHS pborderwidths)
  3770. {
  3771. DOUTL(4, "CNote::SetBorderSpaceDW pborderwidths=%x,%x,%x,%x",
  3772. pborderwidths->left, pborderwidths->top, pborderwidths->right, pborderwidths->bottom);
  3773. RECT rcNote = {0};
  3774. GetClientRect(m_hwnd, &rcNote);
  3775. //WMSize(cxRect(rcNote), cyRect(rcNote), FALSE);
  3776. ResizeChildren(cxRect(rcNote), cyRect(rcNote), pborderwidths->top, FALSE);
  3777. return S_OK;
  3778. }
  3779. // *************************
  3780. HRESULT CNote::GetWindow(HWND * lphwnd)
  3781. {
  3782. *lphwnd = m_hwnd;
  3783. return (m_hwnd ? S_OK : E_FAIL);
  3784. }
  3785. // *************************
  3786. BYTE CNote::GetNoteType()
  3787. {
  3788. BYTE retval;
  3789. if (m_fReadNote)
  3790. retval = m_fMail ? MailReadNoteType : NewsReadNoteType;
  3791. else
  3792. retval = m_fMail ? MailSendNoteType : NewsSendNoteType;
  3793. return retval;
  3794. }
  3795. // *************************
  3796. HRESULT CNote::IsMenuMessage(MSG *lpmsg)
  3797. {
  3798. Assert(m_pToolbarObj);
  3799. if (m_pToolbarObj)
  3800. return m_pToolbarObj->IsMenuMessage(lpmsg);
  3801. else
  3802. return S_FALSE;
  3803. }
  3804. // *************************
  3805. HRESULT CNote::EventOccurred(DWORD nCmdID, IMimeMessage *)
  3806. {
  3807. switch (nCmdID)
  3808. {
  3809. case MEHC_CMD_MARK_AS_READ:
  3810. RemoveNewMailIcon();
  3811. MarkMessage(MARK_MESSAGE_READ, APPLY_SPECIFIED);
  3812. break;
  3813. case MEHC_CMD_CONNECT:
  3814. if (g_pConMan)
  3815. g_pConMan->SetGlobalOffline(FALSE);
  3816. ReloadMessageFromSite(TRUE);
  3817. AssertSz(!m_fCBDestroyWindow, "Shouldn't need to destroy the window...");
  3818. break;
  3819. default:
  3820. return S_FALSE;
  3821. }
  3822. return S_OK;
  3823. }
  3824. // *************************
  3825. HRESULT CNote::QuerySwitchIdentities()
  3826. {
  3827. IImnAccount *pAcct = NULL;
  3828. DWORD dwServType;
  3829. HRESULT hr;
  3830. if (!IsWindowEnabled(m_hwnd))
  3831. {
  3832. Assert(IsWindowVisible(m_hwnd));
  3833. return E_PROCESS_CANCELLED_SWITCH;
  3834. }
  3835. if (IsDirty() != S_FALSE)
  3836. {
  3837. if (FAILED(hr = m_pHdr->HrGetAccountInHeader(&pAcct)))
  3838. goto fail;
  3839. if (FAILED(hr = pAcct->GetServerTypes(&dwServType)))
  3840. goto fail;
  3841. ReleaseObj(pAcct);
  3842. pAcct = NULL;
  3843. SetForegroundWindow(m_hwnd);
  3844. if (!!(dwServType & SRV_POP3) || !!(dwServType & SRV_NNTP))
  3845. {
  3846. if (!FCanClose())
  3847. return E_USER_CANCELLED;
  3848. }
  3849. else
  3850. {
  3851. // IMAP and HTTPMail would have to remote the note, which they
  3852. // can't do at this point, so fail the switch until the window is closed.
  3853. AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsCantSaveMsg),
  3854. MAKEINTRESOURCEW(idsNoteCantSwitchIdentity),
  3855. NULL, MB_OK | MB_ICONEXCLAMATION);
  3856. return E_USER_CANCELLED;
  3857. }
  3858. }
  3859. return S_OK;
  3860. fail:
  3861. ReleaseObj(pAcct);
  3862. return E_PROCESS_CANCELLED_SWITCH;
  3863. }
  3864. // *************************
  3865. HRESULT CNote::SwitchIdentities()
  3866. {
  3867. HRESULT hr;
  3868. if (IsDirty() != S_FALSE)
  3869. hr = SaveMessage(OESF_FORCE_LOCAL_DRAFT);
  3870. SendMessage(m_hwnd, WM_CLOSE, 0, 0);
  3871. return S_OK;
  3872. }
  3873. // *************************
  3874. HRESULT CNote::IdentityInformationChanged(DWORD dwType)
  3875. {
  3876. return S_OK;
  3877. }
  3878. // *************************
  3879. HRESULT CNote::OnBegin(STOREOPERATIONTYPE tyOperation, STOREOPERATIONINFO *pOpInfo,
  3880. IOperationCancel *pCancel)
  3881. {
  3882. Assert(m_pCancel == NULL);
  3883. if (NULL != pCancel)
  3884. {
  3885. m_pCancel = pCancel;
  3886. m_pCancel->AddRef();
  3887. }
  3888. return(S_OK);
  3889. }
  3890. // *************************
  3891. void CNote::ShowErrorScreen(HRESULT hr)
  3892. {
  3893. switch (hr)
  3894. {
  3895. case IXP_E_NNTP_ARTICLE_FAILED:
  3896. case STORE_E_EXPIRED:
  3897. if (m_pBodyObj2)
  3898. m_pBodyObj2->LoadHtmlErrorPage(c_szErrPage_Expired);
  3899. break;
  3900. case HR_E_USER_CANCEL_CONNECT:
  3901. case HR_E_OFFLINE:
  3902. if (m_pBodyObj2)
  3903. m_pBodyObj2->LoadHtmlErrorPage(c_szErrPage_Offline);
  3904. SetFocus(m_hwnd);
  3905. break;
  3906. case STG_E_MEDIUMFULL:
  3907. if (m_pBodyObj2)
  3908. m_pBodyObj2->LoadHtmlErrorPage(c_szErrPage_DiskFull);
  3909. break;
  3910. case MIME_E_SECURITY_CANTDECRYPT:
  3911. if (m_pBodyObj2)
  3912. m_pBodyObj2->LoadHtmlErrorPage(c_szErrPage_SMimeEncrypt);
  3913. break;
  3914. #ifdef SMIME_V3
  3915. case MIME_E_SECURITY_LABELACCESSDENIED:
  3916. case MIME_E_SECURITY_LABELACCESSCANCELLED:
  3917. case MIME_E_SECURITY_LABELCORRUPT:
  3918. if (m_pBodyObj2)
  3919. m_pBodyObj2->LoadHtmlErrorPage(c_szErrPage_SMimeLabel);
  3920. break;
  3921. #endif // SMIME_V3
  3922. case MAPI_E_USER_CANCEL:
  3923. if (m_pBodyObj2)
  3924. m_pBodyObj2->LoadHtmlErrorPage(c_szErrPage_DownloadCanceled);
  3925. break;
  3926. default:
  3927. if (m_pBodyObj2)
  3928. m_pBodyObj2->LoadHtmlErrorPage(c_szErrPage_GenFailure);
  3929. break;
  3930. }
  3931. m_fCompleteMsg = FALSE;
  3932. }
  3933. // *************************
  3934. HRESULT CNote::OnProgress(STOREOPERATIONTYPE tyOperation, DWORD dwCurrent,
  3935. DWORD dwMax, LPCSTR pszStatus)
  3936. {
  3937. TCHAR szRes[CCHMAX_STRINGRES],
  3938. szRes2[CCHMAX_STRINGRES],
  3939. szRes3[CCHMAX_STRINGRES];
  3940. MSG msg;
  3941. if (m_pstatus && pszStatus)
  3942. m_pstatus->SetStatusText(const_cast<LPSTR>(pszStatus));
  3943. CallbackCloseTimeout(&m_hTimeout);
  3944. switch (tyOperation)
  3945. {
  3946. case SOT_GET_MESSAGE:
  3947. if (m_pstatus)
  3948. {
  3949. if (0 != dwMax)
  3950. {
  3951. if (!m_fProgress)
  3952. {
  3953. m_fProgress = TRUE;
  3954. m_pstatus->ShowProgress(dwMax);
  3955. }
  3956. if (m_pstatus)
  3957. m_pstatus->SetProgress(dwCurrent);
  3958. if (!pszStatus)
  3959. {
  3960. AthLoadString(idsDownloadingArticle, szRes, ARRAYSIZE(szRes));
  3961. wnsprintf(szRes2, ARRAYSIZE(szRes2), szRes, (100 * dwCurrent ) / dwMax );
  3962. m_pstatus->SetStatusText(szRes2);
  3963. }
  3964. }
  3965. else if (0 != dwCurrent)
  3966. {
  3967. // dwCurrent is non-zero, but no max has been specified.
  3968. // This implies that dwCurrent is a byte count.
  3969. AthLoadString(idsDownloadArtBytes, szRes, ARRAYSIZE(szRes));
  3970. AthFormatSizeK(dwCurrent, szRes2, ARRAYSIZE(szRes2));
  3971. wnsprintf(szRes3, ARRAYSIZE(szRes3), szRes, szRes2);
  3972. m_pstatus->SetStatusText(szRes3);
  3973. }
  3974. }
  3975. break;
  3976. }
  3977. return S_OK;
  3978. }
  3979. // *************************
  3980. HRESULT CNote::OnComplete(STOREOPERATIONTYPE tyOperation, HRESULT hrComplete, LPSTOREOPERATIONINFO pOpInfo, LPSTOREERROR pErrorInfo)
  3981. {
  3982. if ((SOT_PUT_MESSAGE == tyOperation) && SUCCEEDED(hrComplete) && pOpInfo && m_pMsgSite)
  3983. m_pMsgSite->UpdateCallbackInfo(pOpInfo);
  3984. // Close any timeout dialog, if present
  3985. CallbackCloseTimeout(&m_hTimeout);
  3986. if (m_pstatus)
  3987. {
  3988. if (m_fProgress)
  3989. {
  3990. m_pstatus->HideProgress();
  3991. m_fProgress = FALSE;
  3992. }
  3993. m_pstatus->SetStatusText(const_cast<LPSTR>(c_szEmpty));
  3994. }
  3995. if (m_pCancel != NULL)
  3996. {
  3997. m_pCancel->Release();
  3998. m_pCancel = NULL;
  3999. }
  4000. PostMessage(m_hwnd, WM_OENOTE_ON_COMPLETE, hrComplete, (DWORD)tyOperation);
  4001. // This is not a very neat fix. But, at this time it is a safe fix.
  4002. // Here is the reason why we can't do it any other place.
  4003. // _OnComplete posts a destroy message to the note window depending on the operation.
  4004. // To avoid this object from being destroyed before this function returns, the above
  4005. // message is posted. Since there is no way to pass in the error info through PostMessage,
  4006. // we will handle this error here. I am not handling other operation types because some
  4007. // of them do get handled in _OnComplete
  4008. if (tyOperation == SOT_DELETING_MESSAGES)
  4009. {
  4010. // Display an Error on Failures
  4011. if (FAILED(hrComplete) && hrComplete != HR_E_OFFLINE)
  4012. {
  4013. // Call into my swanky utility
  4014. CallbackDisplayError(m_hwnd, hrComplete, pErrorInfo);
  4015. }
  4016. }
  4017. return S_OK;
  4018. }
  4019. // *************************
  4020. void CNote::_OnComplete(STOREOPERATIONTYPE tyOperation, HRESULT hrComplete)
  4021. {
  4022. BOOL fExpectedComplete = TRUE;
  4023. STOREOPERATIONTYPE tyNewOp = SOT_INVALID;
  4024. m_pMsgSite->OnComplete(tyOperation, hrComplete, &tyNewOp);
  4025. if ((SOT_INVALID != tyNewOp) && (SOT_INVALID != m_OrigOperationType))
  4026. m_OrigOperationType = tyNewOp;
  4027. if (SUCCEEDED(hrComplete))
  4028. {
  4029. switch (tyOperation)
  4030. {
  4031. case SOT_GET_MESSAGE:
  4032. switch (hrComplete)
  4033. {
  4034. case S_OK:
  4035. ReloadMessageFromSite();
  4036. AssertSz(!m_fCBDestroyWindow, "Shouldn't need to destroy the window...");
  4037. break;
  4038. case S_FALSE:
  4039. // S_FALSE means the operation was canceled
  4040. ShowErrorScreen(MAPI_E_USER_CANCEL);
  4041. break;
  4042. }
  4043. break;
  4044. case SOT_PUT_MESSAGE:
  4045. ClearDirtyFlag();
  4046. break;
  4047. case SOT_DELETING_MESSAGES:
  4048. if (!m_fCBDestroyWindow && m_fOrgCmdWasDelete)
  4049. ReloadMessageFromSite(TRUE);
  4050. m_fOrgCmdWasDelete = FALSE;
  4051. break;
  4052. case SOT_COPYMOVE_MESSAGE:
  4053. if (!m_fCBCopy)
  4054. ReloadMessageFromSite();
  4055. break;
  4056. case SOT_SET_MESSAGEFLAGS:
  4057. if ((MARK_MAX != m_dwCBMarkType) && m_pHdr)
  4058. {
  4059. m_pHdr->SetFlagState(m_dwCBMarkType);
  4060. m_dwCBMarkType = MARK_MAX;
  4061. }
  4062. if (MORFS_UNKNOWN != m_dwMarkOnReplyForwardState)
  4063. {
  4064. if (MORFS_CLEARING == m_dwMarkOnReplyForwardState)
  4065. {
  4066. HRESULT hr;
  4067. BOOL fForwarded = (OENA_FORWARD == m_dwNoteAction) || (OENA_FORWARDBYATTACH == m_dwNoteAction);
  4068. MARK_TYPE dwMarkType = (fForwarded ? MARK_MESSAGE_FORWARDED : MARK_MESSAGE_REPLIED);
  4069. m_dwMarkOnReplyForwardState = MORFS_SETTING;
  4070. hr = MarkMessage(dwMarkType, APPLY_SPECIFIED);
  4071. if (FAILED(hr) && (E_PENDING != hr))
  4072. m_dwMarkOnReplyForwardState = MORFS_UNKNOWN;
  4073. }
  4074. else
  4075. {
  4076. PostMessage(m_hwnd, WM_OE_DESTROYNOTE, 0, 0);
  4077. m_dwMarkOnReplyForwardState = MORFS_UNKNOWN;
  4078. }
  4079. }
  4080. // Remove new mail notification icon
  4081. RemoveNewMailIcon();
  4082. break;
  4083. default:
  4084. fExpectedComplete = FALSE;
  4085. break;
  4086. }
  4087. }
  4088. else
  4089. {
  4090. switch (tyOperation)
  4091. {
  4092. case SOT_GET_MESSAGE:
  4093. ShowErrorScreen(hrComplete);
  4094. break;
  4095. case SOT_PUT_MESSAGE:
  4096. if (FAILED(hrComplete))
  4097. {
  4098. HRESULT hrTemp;
  4099. // Can't save to remote server for whatever reason. Save to local Drafts instead
  4100. // First, inform user of the situation, if special folders SHOULD have worked
  4101. if (STORE_E_NOREMOTESPECIALFLDR != hrComplete)
  4102. {
  4103. AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthena),
  4104. MAKEINTRESOURCEW(idsForceSaveToLocalDrafts),
  4105. NULL, MB_OK | MB_ICONEXCLAMATION);
  4106. }
  4107. hrTemp = SaveMessage(OESF_FORCE_LOCAL_DRAFT);
  4108. TraceError(hrTemp);
  4109. }
  4110. break;
  4111. case SOT_SET_MESSAGEFLAGS:
  4112. if (MORFS_UNKNOWN != m_dwMarkOnReplyForwardState)
  4113. m_dwMarkOnReplyForwardState = MORFS_UNKNOWN;
  4114. break;
  4115. case SOT_DELETING_MESSAGES:
  4116. m_fOrgCmdWasDelete = FALSE;
  4117. break;
  4118. default:
  4119. fExpectedComplete = FALSE;
  4120. break;
  4121. }
  4122. }
  4123. // If the original operation was originated from the note, then
  4124. // we will need to re-enable the note as well as check to see
  4125. // if we need to close the window.
  4126. if (tyOperation == m_OrigOperationType)
  4127. {
  4128. _SetPendingOp(SOT_INVALID);
  4129. EnableNote(TRUE);
  4130. EnterCriticalSection(&m_csNoteState);
  4131. if ((tyOperation == SOT_SET_MESSAGEFLAGS) && (m_nisNoteState == NIS_FIXFOCUS))
  4132. {
  4133. if(GetForegroundWindow() == m_hwnd)
  4134. m_pBodyObj2->HrFrameActivate(TRUE);
  4135. else
  4136. m_pBodyObj2->HrGetWindow(&m_hwndFocus);
  4137. m_nisNoteState = NIS_NORMAL;
  4138. }
  4139. LeaveCriticalSection(&m_csNoteState);
  4140. if (!!m_fCBDestroyWindow)
  4141. {
  4142. m_fCBDestroyWindow = FALSE;
  4143. PostMessage(m_hwnd, WM_OE_DESTROYNOTE, 0, 0);
  4144. }
  4145. }
  4146. }
  4147. // *************************
  4148. HRESULT CNote::OnTimeout(LPINETSERVER pServer, LPDWORD pdwTimeout, IXPTYPE ixpServerType)
  4149. {
  4150. // Display a timeout dialog
  4151. return CallbackOnTimeout(pServer, ixpServerType, *pdwTimeout, (ITimeoutCallback *)this, &m_hTimeout);
  4152. }
  4153. // *************************
  4154. HRESULT CNote::CanConnect(LPCSTR pszAccountId, DWORD dwFlags)
  4155. {
  4156. // Call into general CanConnect Utility
  4157. //return CallbackCanConnect(pszAccountId, m_hwnd, FALSE);
  4158. //Always TRUE will prompt to go online if we are offline, which is what we want to do.
  4159. return CallbackCanConnect(pszAccountId, m_hwnd, TRUE);
  4160. }
  4161. // *************************
  4162. HRESULT CNote::OnLogonPrompt(LPINETSERVER pServer, IXPTYPE ixpServerType)
  4163. {
  4164. // Close any timeout dialog, if present
  4165. CallbackCloseTimeout(&m_hTimeout);
  4166. // Call into general OnLogonPrompt Utility
  4167. return CallbackOnLogonPrompt(m_hwnd, pServer, ixpServerType);
  4168. }
  4169. // *************************
  4170. HRESULT CNote::OnPrompt(HRESULT hrError, LPCTSTR pszText, LPCTSTR pszCaption, UINT uType, INT *piUserResponse)
  4171. {
  4172. // Close any timeout dialog, if present
  4173. CallbackCloseTimeout(&m_hTimeout);
  4174. // Call into my swanky utility
  4175. return CallbackOnPrompt(m_hwnd, hrError, pszText, pszCaption, uType, piUserResponse);
  4176. }
  4177. // *************************
  4178. HRESULT CNote::GetParentWindow(DWORD dwReserved, HWND *phwndParent)
  4179. {
  4180. *phwndParent = m_hwnd;
  4181. return(S_OK);
  4182. }
  4183. // *************************
  4184. HRESULT CNote::OnTimeoutResponse(TIMEOUTRESPONSE eResponse)
  4185. {
  4186. HRESULT hr = S_OK;
  4187. // Call into general timeout response utility
  4188. if (NULL != m_pCancel)
  4189. hr = CallbackOnTimeoutResponse(eResponse, m_pCancel, &m_hTimeout);
  4190. return hr;
  4191. }
  4192. // *************************
  4193. HRESULT CNote::CheckCharsetConflict()
  4194. {
  4195. return m_fPreventConflictDlg ? S_FALSE : S_OK;
  4196. }