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.

8536 lines
248 KiB

  1. //*************************************************
  2. // h e a d e r . c p p
  3. //
  4. // Purpose:
  5. // implements Header UI for Read|SendNote
  6. //
  7. // Owner:
  8. // brettm.
  9. //
  10. // History:
  11. // July '95: Created
  12. //
  13. // Copyright (C) Microsoft Corp. 1993, 1994.
  14. //*************************************************
  15. #include <pch.hxx>
  16. #include <richedit.h>
  17. #include <resource.h>
  18. #include <thormsgs.h>
  19. #include "oleutil.h"
  20. #include "fonts.h"
  21. #include "error.h"
  22. #include "header.h"
  23. #include "options.h"
  24. #include "note.h"
  25. #include "ipab.h"
  26. #include "addrobj.h"
  27. #include "hotlinks.h"
  28. #include <mimeole.h>
  29. #include <secutil.h>
  30. #include <xpcomm.h>
  31. #include "menuutil.h"
  32. #include "shlwapi.h"
  33. #include "envcid.h"
  34. #include "ourguid.h"
  35. #include "mimeutil.h"
  36. #include "strconst.h"
  37. #include "mailutil.h"
  38. #include "regutil.h"
  39. #include "spoolapi.h"
  40. #include "init.h"
  41. #include "instance.h"
  42. #include "attman.h"
  43. #include "envguid.h"
  44. #include <inetcfg.h> //ICW
  45. #include <pickgrp.h>
  46. #include "menures.h"
  47. #include "storecb.h"
  48. #include "mimeolep.h"
  49. #include "multlang.h"
  50. #include "mirror.h"
  51. #include "seclabel.h"
  52. #include "shlwapip.h"
  53. #include "reutil.h"
  54. #include <iert.h>
  55. #include "msgprop.h"
  56. #include "demand.h"
  57. ASSERTDATA
  58. extern UINT GetCurColorRes(void);
  59. class CFieldSizeMgr : public CPrivateUnknown,
  60. public IFontCacheNotify,
  61. public IConnectionPoint
  62. {
  63. public:
  64. // IUnknown
  65. virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj) {
  66. return CPrivateUnknown::QueryInterface(riid, ppvObj); };
  67. virtual STDMETHODIMP_(ULONG) AddRef(void) {
  68. return CPrivateUnknown::AddRef();};
  69. virtual STDMETHODIMP_(ULONG) Release(void) {
  70. return CPrivateUnknown::Release(); };
  71. // IFontCacheNotify
  72. HRESULT STDMETHODCALLTYPE OnPreFontChange(void);
  73. HRESULT STDMETHODCALLTYPE OnPostFontChange(void);
  74. // IConnectionPoint
  75. HRESULT STDMETHODCALLTYPE GetConnectionInterface(IID *pIID);
  76. HRESULT STDMETHODCALLTYPE GetConnectionPointContainer(IConnectionPointContainer **ppCPC);
  77. HRESULT STDMETHODCALLTYPE Advise(IUnknown *pUnkSink, DWORD *pdwCookie);
  78. HRESULT STDMETHODCALLTYPE Unadvise(DWORD dwCookie);
  79. HRESULT STDMETHODCALLTYPE EnumConnections(IEnumConnections **ppEnum);
  80. // CPrivateUnknown
  81. HRESULT PrivateQueryInterface(REFIID riid, LPVOID * ppvObj);
  82. int GetScalingFactor(void);
  83. void ResetGlobalSizes(void);
  84. HRESULT Init(void);
  85. // This one should only be called from headers' OnPostFontChange calls
  86. BOOL FontsChanged(void) {return m_fFontsChanged;}
  87. CFieldSizeMgr(IUnknown *pUnkOuter=NULL);
  88. ~CFieldSizeMgr();
  89. private:
  90. IUnknownList *m_pAdviseRegistry;
  91. CRITICAL_SECTION m_rAdviseCritSect;
  92. BOOL m_fFontsChanged;
  93. DWORD m_dwFontNotify;
  94. };
  95. // **********************************************************
  96. // ***** Debug stuff for handling painting and resizing *****
  97. // **********************************************************
  98. const int PAINTING_DEBUG_LEVEL = 4;
  99. const int RESIZING_DEBUG_LEVEL = 8;
  100. const int GEN_HEADER_DEBUG_LEVEL = 16;
  101. #ifdef DEBUG
  102. class StackRegistry {
  103. public:
  104. StackRegistry(LPSTR pszTitle, INT_PTR p1 = 0, INT_PTR p2 = 0, INT_PTR p3 = 0, INT_PTR p4 = 0, INT_PTR p5 = 0);
  105. ~StackRegistry();
  106. private:
  107. int m_StackLevel;
  108. CHAR m_szTitle[256+1];
  109. static int gm_cStackLevel;
  110. static int gm_strLen;
  111. static LPSTR gm_Indent;
  112. };
  113. int StackRegistry::gm_cStackLevel = 0;
  114. LPSTR StackRegistry::gm_Indent = "------------------------------";
  115. int StackRegistry::gm_strLen = lstrlen(gm_Indent);
  116. StackRegistry::StackRegistry(LPSTR pszTitle, INT_PTR p1, INT_PTR p2, INT_PTR p3, INT_PTR p4, INT_PTR p5)
  117. {
  118. gm_cStackLevel++;
  119. m_StackLevel = (gm_cStackLevel > gm_strLen) ? gm_strLen : gm_cStackLevel;
  120. StrCpyN(m_szTitle, pszTitle, ARRAYSIZE(m_szTitle));
  121. m_szTitle[256] = 0;
  122. if (1 == gm_cStackLevel)
  123. DOUTL(RESIZING_DEBUG_LEVEL, "\n*********** BEGIN TRACE ***********");
  124. DOUTL(RESIZING_DEBUG_LEVEL, "IN*** %s%s - %x, %x, %x, %x, %x", gm_Indent+gm_strLen-m_StackLevel, m_szTitle, p1, p2, p3, p4, p5);
  125. }
  126. StackRegistry::~StackRegistry()
  127. {
  128. DOUTL(RESIZING_DEBUG_LEVEL, "OUT** %s%s", gm_Indent+gm_strLen-m_StackLevel, m_szTitle);
  129. if (1 == gm_cStackLevel)
  130. DOUTL(RESIZING_DEBUG_LEVEL, "************ END TRACE ************\n");
  131. gm_cStackLevel--;
  132. Assert(gm_cStackLevel >= 0);
  133. }
  134. #define STACK StackRegistry stack
  135. #else
  136. // BUGBUG (neilbren) WIN64
  137. // Figure out when __noop was introduced (MSC_VER ?) so we don't have to key off of WIN64
  138. #define STACK __noop
  139. #endif
  140. // ******************************
  141. // ***** End of debug stuff *****
  142. // ******************************
  143. // c o n s t a n t s
  144. const DWORD SETWINPOS_DEF_FLAGS = SWP_NOZORDER|SWP_NOACTIVATE;
  145. #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
  146. #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
  147. #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
  148. #define WC_ATHHEADER wszHeaderWndClass
  149. #define RGB_TRANSPARENT RGB(255,0,255)
  150. #define HDM_TESTQUERYPRI (WM_USER + 1)
  151. #define cxBorder (GetSystemMetrics(SM_CXBORDER))
  152. #define cyBorder (GetSystemMetrics(SM_CYBORDER))
  153. // HDRCB_VCARD must remain -1 and all others must be negative
  154. enum {
  155. HDRCB_VCARD = -1,
  156. HDRCB_SIGNED = -2,
  157. HDRCB_ENCRYPT = -3,
  158. HDRCB_NO_BUTTON = -4
  159. };
  160. // WARNING:: This next macro is only to be used with g_rgBtnInd inside the CNoteHdr class.
  161. // Make sure that they match the entries in g_rgBtnInd
  162. #define BUTTON_STATES m_fDigSigned, m_fEncrypted, m_fVCard
  163. #define BUTTON_USE_IN_COMPOSE FALSE, FALSE, TRUE
  164. static const DWORD g_rgBtnInd[] = {HDRCB_SIGNED, HDRCB_ENCRYPT, HDRCB_VCARD};
  165. static const int cchMaxWab = 512;
  166. static const int cxTBButton = 16;
  167. static const int BUTTON_BUFFER = 2;
  168. static const int cxBtn = 16;
  169. static const int cyBtn = cxBtn;
  170. static const int cxFlags = 12;
  171. static const int cyFlags = cxFlags;
  172. static const int cxFlagsDelta = cxFlags + 4;
  173. static const int MAX_ATTACH_PIXEL_HEIGHT = 50;
  174. static const int ACCT_ENTRY_SIZE = CCHMAX_ACCOUNT_NAME + CCHMAX_EMAIL_ADDRESS + 10;
  175. static const int INVALID_PHCI_Y = -1;
  176. static const int cMaxRecipMenu = (ID_ADD_RECIPIENT_LAST-ID_ADD_RECIPIENT_FIRST);
  177. static const int NUM_COMBO_LINES = 9;
  178. static const int MAX_RICHEDIT_LINES = 4;
  179. static const int DEFER_WINDOW_SIZE = MAX_HEADER_COMP + 1 + 1 + 1 + 5; // +1=header window, +1=field resize, +1 toolbar
  180. static const LPTSTR GRP_DELIMITERS = " ,\t;\n\r";
  181. #define c_wszEmpty L""
  182. #define c_aszEmpty ""
  183. // t y p e d e f s
  184. typedef struct TIPLOOKUP_tag
  185. {
  186. int idm;
  187. int ids;
  188. } TIPLOOKUP;
  189. typedef struct CMDMAPING_tag
  190. {
  191. DWORD cmdIdOffice,
  192. cmdIdOE;
  193. } CMDMAPING;
  194. typedef struct PERSISTHEADER_tag
  195. {
  196. DWORD cbSize; // size so we can version the stuct
  197. DWORD dwRes1, // padding just in case...
  198. dwRes2;
  199. } PERSISTHEADER;
  200. #define cchMaxSubject 256
  201. typedef struct WELLINIT_tag
  202. {
  203. INT idField;
  204. ULONG uMAPI;
  205. } WELLINIT, *PWELLINIT;
  206. // s t a t i c d a t a
  207. static HIMAGELIST g_himlStatus = 0,
  208. g_himlBtns = 0,
  209. g_himlSecurity = 0;
  210. static TCHAR g_szStatFlagged[cchHeaderMax+1] = c_aszEmpty,
  211. g_szStatLowPri[cchHeaderMax+1] = c_aszEmpty,
  212. g_szStatHighPri[cchHeaderMax+1] = c_aszEmpty,
  213. g_szStatWatched[cchHeaderMax+1] = c_aszEmpty,
  214. g_szStatIgnored[cchHeaderMax+1] = c_aszEmpty,
  215. g_szStatFormat1[cchHeaderMax+1] = c_aszEmpty,
  216. g_szStatFormat2[cchHeaderMax+1] = c_aszEmpty,
  217. g_szStatFormat3[cchHeaderMax+1] = c_aszEmpty,
  218. g_szStatUnsafeAtt[cchHeaderMax+1] = c_aszEmpty;
  219. static CFieldSizeMgr *g_pFieldSizeMgr = NULL;
  220. static WNDPROC g_lpfnREWndProc = NULL;
  221. static CHARFORMAT g_cfHeader = {0};
  222. static int g_cyFont = 0,
  223. g_cyLabelHeight = 0;
  224. static char const szButton[]="BUTTON";
  225. static WCHAR const wszHeaderWndClass[]=L"OE_Envelope";
  226. // KEEP in ssync with c_rgTipLookup
  227. const TBBUTTON c_btnsOfficeEnvelope[]=
  228. {
  229. {TBIMAGE_SEND_MAIL, ID_SEND_NOW, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, -1},
  230. __TOOLBAR_SEP__,
  231. { TBIMAGE_CHECK_NAMES, ID_CHECK_NAMES, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, -1},
  232. { TBIMAGE_ADDRESS_BOOK, ID_ADDRESS_BOOK, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0, 0}, 0, -1},
  233. __TOOLBAR_SEP__,
  234. {TBIMAGE_SET_PRIORITY, ID_SET_PRIORITY, TBSTATE_ENABLED, TBSTYLE_DROPDOWN, {0,0}, 0, -1},
  235. {TBIMAGE_INSERT_ATTACHMENT, ID_INSERT_ATTACHMENT, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, -1},
  236. __TOOLBAR_SEP__,
  237. { TBIMAGE_ENVELOPE_BCC, ID_ENV_BCC, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, -1}
  238. };
  239. // KEEP in ssync with c_btnsOfficeEnvelope
  240. const TIPLOOKUP c_rgTipLookup[] =
  241. {
  242. {ID_SEND_NOW, idsSendMsgTT},
  243. {ID_CHECK_NAMES, idsCheckNamesTT},
  244. {ID_ADDRESS_BOOK, idsAddressBookTT},
  245. {ID_SET_PRIORITY, idsSetPriorityTT},
  246. {ID_INSERT_ATTACHMENT, idsInsertFileTT},
  247. {ID_ENV_BCC, idsEnvBccTT}
  248. };
  249. // Prototypes
  250. HRESULT ParseFollowup(LPMIMEMESSAGE pMsg, LPTSTR* ppszGroups, BOOL* pfPoster);
  251. DWORD HdrGetRichEditText(HWND hwnd, LPWSTR pwchBuff, DWORD dwNumChars, BOOL fSelection);
  252. void HdrSetRichEditText(HWND hwnd, LPWSTR pwchBuff, BOOL fReplace);
  253. // i n l i n e s
  254. void HdrSetRichEditText(HWND hwnd, LPWSTR pwchBuff, BOOL fReplace)
  255. {
  256. if (!hwnd)
  257. return;
  258. PHCI phci = (HCI*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  259. AssertSz(phci, "We are calling HdrSetRichEditText on a non-richedit control");
  260. SetRichEditText(hwnd, pwchBuff, fReplace, phci->pDoc, (phci->dwFlags & HCF_READONLY));
  261. }
  262. DWORD HdrGetRichEditText(HWND hwnd, LPWSTR pwchBuff, DWORD dwNumChars, BOOL fSelection)
  263. {
  264. if (!hwnd)
  265. return 0;
  266. PHCI phci = (HCI*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  267. AssertSz(phci, "We are calling HdrSetRichEditText on a non-richedit control");
  268. return GetRichEditText(hwnd, pwchBuff, dwNumChars, fSelection, phci->pDoc);
  269. }
  270. inline void GetRealClientRect(HWND hwnd, RECT *prc)
  271. {
  272. GetClientRect(hwnd, prc);
  273. AdjustWindowRectEx(prc, GetWindowLong(hwnd, GWL_STYLE), FALSE, GetWindowLong(hwnd, GWL_EXSTYLE));
  274. }
  275. inline int GetCtrlWidth(HWND hwnd)
  276. {
  277. RECT rc;
  278. GetWindowRect(hwnd, &rc);
  279. return rc.right - rc.left;
  280. }
  281. inline int GetControlSize(BOOL fIncludeBorder, int cLines)
  282. {
  283. int size = cLines * g_cyFont;
  284. // If borders, include the metrics
  285. if (fIncludeBorder)
  286. size += 7;
  287. return size;
  288. }
  289. inline int GetCtrlHeight(HWND hwnd)
  290. {
  291. DWORD id = GetWindowLong(hwnd, GWL_ID);
  292. if (idFromCombo == id)
  293. {
  294. return GetControlSize(TRUE, 1);
  295. }
  296. else
  297. {
  298. RECT rc;
  299. GetWindowRect(hwnd, &rc);
  300. return rc.bottom - rc.top;
  301. }
  302. }
  303. inline int GetStatusHeight(int cLines) {return ((cyBtn<g_cyFont)?GetControlSize(TRUE, cLines):((cyBtn-4)*cLines + 2*cyBorder + 6)); }
  304. inline int CYOfStatusLine() { return ((cyBtn<g_cyFont)?g_cyFont:(cyBtn - 4)); }
  305. inline int ControlXBufferSize() { return 10 * cxBorder; }
  306. inline int ControlYBufferSize() { return 4 * cyBorder; }
  307. inline int PaddingOfLabels() { return 2 * ControlXBufferSize(); }
  308. inline int CXOfButtonToLabel() { return 4*cxBorder + cxBtn; }
  309. inline BOOL ButtonInLabels(int iBtn) { return (iBtn > HDRCB_VCARD); }
  310. inline HFONT GetFont(BOOL fBold) { return HGetSystemFont(fBold?FNT_SYS_ICON_BOLD:FNT_SYS_ICON); }
  311. static IMSGPRIORITY priLookup[3]=
  312. { IMSG_PRI_LOW,
  313. IMSG_PRI_NORMAL,
  314. IMSG_PRI_HIGH
  315. };
  316. #define HCI_ENTRY(flg,opt,ide,idb,idsl,idse,idst) \
  317. { \
  318. flg, opt, \
  319. ide, idb, \
  320. idsl, idse, idst, \
  321. NOFLAGS, TRUE, \
  322. NULL, NULL, \
  323. 0, 0, 0, 0, \
  324. c_wszEmpty, c_wszEmpty \
  325. }
  326. static int rgIDTabOrderMailSend[] =
  327. {
  328. idFromCombo, idADTo,
  329. idADCc, idADBCc,
  330. idTXTSubject, idwAttachWell
  331. };
  332. static HCI rgMailHeaderSend[]=
  333. {
  334. HCI_ENTRY(HCF_COMBO|HCF_ADVANCED|HCF_BORDER,
  335. 0,
  336. idFromCombo, 0,
  337. idsFromField, NULL,
  338. NULL),
  339. HCI_ENTRY(HCF_MULTILINE|HCF_HASBUTTON|HCF_ADDRBOOK|HCF_ADDRWELL|HCF_BORDER,
  340. 0,
  341. idADTo, idbtnTo,
  342. idsToField, idsEmptyTo,
  343. idsTTRecipients),
  344. HCI_ENTRY(HCF_MULTILINE|HCF_HASBUTTON|HCF_ADDRBOOK|HCF_ADDRWELL|HCF_BORDER,
  345. 0,
  346. idADCc, idbtnCc,
  347. idsCcField, idsEmptyCc,
  348. idsTTRecipients),
  349. HCI_ENTRY(HCF_MULTILINE|HCF_HASBUTTON|HCF_ADDRBOOK|HCF_ADDRWELL|HCF_ADVANCED|HCF_BORDER,
  350. 0,
  351. idADBCc, idbtnBCc,
  352. idsBCcField, idsEmptyBCc,
  353. idsTTRecipients),
  354. HCI_ENTRY(HCF_USECHARSET|HCF_BORDER,
  355. 0,
  356. idTXTSubject, 0,
  357. idsSubjectField, idsEmptySubject,
  358. idsTTSubject),
  359. HCI_ENTRY(HCF_BORDER|HCF_ATTACH,
  360. 0,
  361. idwAttachWell, 0,
  362. idsAttachment, 0,
  363. idsTTAttachment),
  364. };
  365. static int rgIDTabOrderMailRead[] =
  366. {
  367. idADFrom, idTXTDate,
  368. idADTo, idADCc,
  369. idTXTSubject, idwAttachWell,
  370. idSecurity
  371. };
  372. static HCI rgMailHeaderRead[]=
  373. {
  374. HCI_ENTRY(HCF_MULTILINE|HCF_READONLY|HCF_ADDRWELL,
  375. 0,
  376. idADFrom, 0,
  377. idsFromField, idsNoFromField,
  378. NULL),
  379. HCI_ENTRY(HCF_READONLY,
  380. 0,
  381. idTXTDate, 0,
  382. idsDateField, NULL,
  383. NULL),
  384. HCI_ENTRY(HCF_MULTILINE|HCF_READONLY|HCF_ADDRWELL,
  385. 0,
  386. idADTo, 0,
  387. idsToField, idsNoCcOrTo,
  388. NULL),
  389. HCI_ENTRY(HCF_MULTILINE|HCF_READONLY|HCF_ADVANCED|HCF_ADDRWELL,
  390. 0,
  391. idADCc, 0,
  392. idsCcField, idsNoCcOrTo,
  393. NULL),
  394. HCI_ENTRY(HCF_READONLY|HCF_USECHARSET,
  395. 0,
  396. idTXTSubject, 0,
  397. idsSubjectField, idsEmptySubjectRO,
  398. NULL),
  399. HCI_ENTRY(HCF_READONLY|HCF_BORDER|HCF_ATTACH,
  400. 0,
  401. idwAttachWell, 0,
  402. idsAttachment, 0,
  403. NULL),
  404. HCI_ENTRY(HCF_READONLY|HCF_ADVANCED, // HCF_ADVANCED will hide it when empty
  405. 0,
  406. idSecurity, 0,
  407. idsSecurityField, NULL,
  408. NULL),
  409. };
  410. static int rgIDTabOrderNewsSend[] =
  411. {
  412. idFromCombo, idADNewsgroups,
  413. idTXTFollowupTo, idADCc,
  414. idADReplyTo, idTXTDistribution,
  415. idTXTKeywords, idTXTSubject,
  416. idwAttachWell, idADApproved,
  417. idTxtControl
  418. };
  419. static HCI rgNewsHeaderSend[]=
  420. {
  421. HCI_ENTRY(HCF_COMBO|HCF_ADVANCED|HCF_BORDER,
  422. 0,
  423. idFromCombo, 0,
  424. idsNewsServer, NULL,
  425. NULL),
  426. HCI_ENTRY(HCF_MULTILINE|HCF_HASBUTTON|HCF_NEWSPICK|HCF_BORDER,
  427. 0,
  428. idADNewsgroups, idbtnTo,
  429. idsNewsgroupsField, idsEmptyNewsgroups,
  430. idsTTNewsgroups),
  431. HCI_ENTRY(HCF_ADVANCED|HCF_HASBUTTON|HCF_NEWSPICK|HCF_MULTILINE|HCF_USECHARSET|HCF_BORDER,
  432. 0,
  433. idTXTFollowupTo, idbtnFollowup,
  434. idsFollowupToField, idsEmptyFollowupTo,
  435. idsTTFollowup),
  436. HCI_ENTRY(HCF_MULTILINE|HCF_ADDRWELL|HCF_HASBUTTON|HCF_ADDRBOOK|HCF_BORDER,
  437. 0,
  438. idADCc, idbtnCc,
  439. idsCcField, idsEmptyCc,
  440. idsTTRecipients),
  441. HCI_ENTRY(HCF_ADVANCED|HCF_ADDRWELL|HCF_HASBUTTON|HCF_ADDRBOOK|HCF_BORDER,
  442. 0,
  443. idADReplyTo, idbtnReplyTo,
  444. idsReplyToField, idsEmptyReplyTo,
  445. idsTTReplyTo),
  446. HCI_ENTRY(HCF_MULTILINE|HCF_ADVANCED|HCF_BORDER,
  447. 0,
  448. idTXTDistribution, 0,
  449. idsDistributionField, idsEmptyDistribution,
  450. idsTTDistribution),
  451. HCI_ENTRY(HCF_MULTILINE|HCF_ADVANCED|HCF_USECHARSET|HCF_BORDER,
  452. 0,
  453. idTXTKeywords, 0,
  454. idsKeywordsField, idsEmptyKeywords,
  455. idsTTKeywords),
  456. HCI_ENTRY(HCF_USECHARSET|HCF_BORDER,
  457. 0,
  458. idTXTSubject, 0,
  459. idsSubjectField, idsEmptySubject,
  460. idsTTSubject),
  461. HCI_ENTRY(HCF_BORDER|HCF_ATTACH,
  462. 0,
  463. idwAttachWell, 0,
  464. idsAttachment, 0,
  465. idsTTAttachment),
  466. HCI_ENTRY(HCF_ADVANCED|HCF_OPTIONAL,
  467. OPT_NEWSMODERATOR,
  468. idADApproved, 0,
  469. idsApprovedField, idsEmptyApproved,
  470. idsTTApproved),
  471. HCI_ENTRY(HCF_ADVANCED|HCF_OPTIONAL,
  472. OPT_NEWSCONTROLHEADER,
  473. idTxtControl, 0,
  474. idsControlField, idsEmptyControl,
  475. idsTTControl),
  476. };
  477. static int rgIDTabOrderNewsRead[] =
  478. {
  479. idADFrom, idADReplyTo,
  480. idTXTOrg, idTXTDate,
  481. idADNewsgroups, idTXTFollowupTo,
  482. idTXTDistribution, idTXTKeywords,
  483. idTXTSubject, idwAttachWell,
  484. idSecurity
  485. };
  486. static HCI rgNewsHeaderRead[]=
  487. {
  488. HCI_ENTRY(HCF_MULTILINE|HCF_READONLY|HCF_ADDRWELL,
  489. 0,
  490. idADFrom, 0,
  491. idsFromField, idsNoFromField,
  492. NULL),
  493. HCI_ENTRY(HCF_READONLY|HCF_ADVANCED|HCF_ADDRWELL,
  494. 0,
  495. idADReplyTo, 0,
  496. idsReplyToField, idsNotSpecified,
  497. NULL),
  498. HCI_ENTRY(HCF_READONLY|HCF_ADVANCED|HCF_USECHARSET,
  499. 0,
  500. idTXTOrg, 0,
  501. idsOrgField, idsNotSpecified,
  502. NULL),
  503. HCI_ENTRY(HCF_READONLY,
  504. 0,
  505. idTXTDate, 0,
  506. idsDateField, idsNotSpecified,
  507. NULL),
  508. HCI_ENTRY(HCF_MULTILINE|HCF_READONLY,
  509. 0,
  510. idADNewsgroups, 0,
  511. idsNewsgroupsField, idsNotSpecified,
  512. NULL),
  513. HCI_ENTRY(HCF_READONLY|HCF_ADVANCED,
  514. 0,
  515. idTXTFollowupTo, 0,
  516. idsFollowupToField, idsNotSpecified,
  517. NULL),
  518. HCI_ENTRY(HCF_MULTILINE|HCF_READONLY|HCF_ADVANCED,
  519. 0,
  520. idTXTDistribution, 0,
  521. idsDistributionField, idsNotSpecified,
  522. NULL),
  523. HCI_ENTRY(HCF_MULTILINE|HCF_READONLY|HCF_ADVANCED|HCF_USECHARSET,
  524. 0,
  525. idTXTKeywords, 0,
  526. idsKeywordsField, idsNotSpecified,
  527. NULL),
  528. HCI_ENTRY(HCF_READONLY|HCF_USECHARSET,
  529. 0,
  530. idTXTSubject, 0,
  531. idsSubjectField, idsEmptySubjectRO,
  532. NULL),
  533. HCI_ENTRY(HCF_READONLY|HCF_BORDER|HCF_ATTACH,
  534. 0,
  535. idwAttachWell, 0,
  536. idsAttachment, 0,
  537. NULL),
  538. HCI_ENTRY(HCF_READONLY|HCF_ADVANCED,
  539. 0,
  540. idSecurity, 0,
  541. idsSecurityField, NULL,
  542. NULL),
  543. };
  544. // p r o t o t y p e s
  545. void _ValidateNewsgroups(LPWSTR pszGroups);
  546. INT_PTR CALLBACK _PlainWarnDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  547. #ifdef DEBUG
  548. void DEBUGHdrName(HWND hwnd);
  549. void DEBUGDumpHdr(HWND hwnd, int cHdr, PHCI rgHCI)
  550. {
  551. PHCI phci;
  552. char sz[cchHeaderMax+1];
  553. RECT rc;
  554. HWND hwndEdit;
  555. #ifndef DEBUG_SIZINGCODE
  556. return;
  557. #endif
  558. DOUTL(GEN_HEADER_DEBUG_LEVEL, "-----");
  559. for (int i=0; i<(int)cHdr; i++)
  560. {
  561. phci=&rgHCI[i];
  562. hwndEdit=GetDlgItem(hwnd, phci->idEdit);
  563. GetChildRect(hwnd, hwndEdit, &rc);
  564. DEBUGHdrName(hwndEdit);
  565. wnsprintf(sz, ARRAYSIZE(sz), "\tat:(%d,%d) \tsize:(%d,%d)\r\n", rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top);
  566. OutputDebugString(sz);
  567. }
  568. GetWindowRect(hwnd, &rc);
  569. DOUTL(GEN_HEADER_DEBUG_LEVEL, "HeaderSize: (%d,%d)\r\n-----", rc.right-rc.left, rc.bottom-rc.top);
  570. }
  571. void DEBUGHdrName(HWND hwnd)
  572. {
  573. char sz[cchHeaderMax+1];
  574. char *psz=0;
  575. switch (GetDlgCtrlID(hwnd))
  576. {
  577. case idTXTSubject:
  578. psz="Subject";
  579. break;
  580. case idTXTOrg:
  581. psz="Org";
  582. break;
  583. case idADTo:
  584. psz="To";
  585. break;
  586. case idADCc:
  587. psz="Cc";
  588. break;
  589. case idADFrom:
  590. psz="From";
  591. break;
  592. case idTXTDate:
  593. psz="Date";
  594. break;
  595. case idTXTDistribution:
  596. psz="Distribution";
  597. break;
  598. case idADApproved:
  599. psz="Approved";
  600. break;
  601. case idADReplyTo:
  602. psz="ReplyTo";
  603. break;
  604. case idTXTKeywords:
  605. psz="Keywords";
  606. break;
  607. case idADNewsgroups:
  608. psz="NewsGroup";
  609. break;
  610. case idTXTFollowupTo:
  611. psz="FollowUp";
  612. break;
  613. default:
  614. psz="<Unknown>";
  615. break;
  616. }
  617. wnsprintf(sz, ARRAYSIZE(sz), "%s: ", psz);
  618. OutputDebugString(sz);
  619. }
  620. #endif
  621. // FHeader_Init
  622. //
  623. // Purpose: called to init and de-init global header stuff, eg.
  624. // wndclasses, static data etc.
  625. //
  626. // Comments:
  627. // TODO: defer this initialisation
  628. //
  629. BOOL FHeader_Init(BOOL fInit)
  630. {
  631. WNDCLASSW wc={0};
  632. static BOOL s_fInited=FALSE;
  633. BOOL fSucceeded = TRUE;
  634. if (fInit)
  635. {
  636. if (s_fInited)
  637. goto exit;
  638. Assert(!g_pFieldSizeMgr);
  639. g_pFieldSizeMgr = new CFieldSizeMgr;
  640. if (!g_pFieldSizeMgr || FAILED(g_pFieldSizeMgr->Init()))
  641. {
  642. fSucceeded = FALSE;
  643. goto exit;
  644. }
  645. wc.style = 0;
  646. wc.lpfnWndProc = CNoteHdr::ExtCNoteHdrWndProc;
  647. wc.hInstance = g_hInst;
  648. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  649. wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
  650. wc.lpszClassName = WC_ATHHEADER;
  651. if (!RegisterClassWrapW(&wc))
  652. {
  653. fSucceeded = FALSE;
  654. goto exit;
  655. }
  656. g_himlStatus=ImageList_LoadBitmap(g_hLocRes, MAKEINTRESOURCE(idbHeaderStatus), cxFlags, 0, RGB_TRANSPARENT);
  657. if (!g_himlStatus)
  658. {
  659. fSucceeded = FALSE;
  660. goto exit;
  661. }
  662. g_himlBtns=ImageList_LoadBitmap(g_hLocRes, MAKEINTRESOURCE(idbBtns), cxBtn, 0, RGB_TRANSPARENT);
  663. if (!g_himlBtns)
  664. {
  665. fSucceeded = FALSE;
  666. goto exit;
  667. }
  668. g_himlSecurity=ImageList_LoadBitmap(g_hLocRes, MAKEINTRESOURCE(idbSecurity), cxBtn, 0, RGB_TRANSPARENT);
  669. if (!g_himlSecurity)
  670. {
  671. fSucceeded = FALSE;
  672. goto exit;
  673. }
  674. ImageList_SetBkColor(g_himlStatus, CLR_NONE);
  675. ImageList_SetBkColor(g_himlBtns, CLR_NONE);
  676. ImageList_SetBkColor(g_himlSecurity, CLR_NONE);
  677. AthLoadString(idsStatusFlagged, g_szStatFlagged, cchHeaderMax);
  678. AthLoadString(idsStatusLowPri, g_szStatLowPri, cchHeaderMax);
  679. AthLoadString(idsStatusHighPri, g_szStatHighPri, cchHeaderMax);
  680. AthLoadString(idsStatusWatched, g_szStatWatched, cchHeaderMax);
  681. AthLoadString(idsStatusIgnored, g_szStatIgnored, cchHeaderMax);
  682. AthLoadString(idsStatusFormat1, g_szStatFormat1, cchHeaderMax);
  683. AthLoadString(idsStatusFormat2, g_szStatFormat2, cchHeaderMax);
  684. AthLoadString(idsStatusFormat3, g_szStatFormat3, cchHeaderMax);
  685. AthLoadString(idsStatusUnsafeAttach, g_szStatUnsafeAtt, cchHeaderMax);
  686. s_fInited=TRUE;
  687. }
  688. // De-Init ******
  689. else
  690. {
  691. UnregisterClassWrapW(WC_ATHHEADER, g_hInst);
  692. if (g_himlStatus)
  693. {
  694. ImageList_Destroy(g_himlStatus);
  695. g_himlStatus = 0;
  696. }
  697. if (g_himlBtns)
  698. {
  699. ImageList_Destroy(g_himlBtns);
  700. g_himlBtns = 0;
  701. }
  702. if (g_himlSecurity)
  703. {
  704. ImageList_Destroy(g_himlSecurity);
  705. g_himlSecurity = 0;
  706. }
  707. s_fInited=FALSE;
  708. SafeRelease(g_pFieldSizeMgr);
  709. }
  710. exit:
  711. if (!fSucceeded)
  712. SafeRelease(g_pFieldSizeMgr);
  713. return fSucceeded;
  714. }
  715. HRESULT CreateInstance_Envelope(IUnknown *pUnkOuter, IUnknown **ppUnknown)
  716. {
  717. // Locals
  718. HRESULT hr=S_OK;
  719. CNoteHdr *pNew=NULL;
  720. // Trace
  721. TraceCall("CreateInstance_Envelope");
  722. if (NULL != pUnkOuter)
  723. return CLASS_E_NOAGGREGATION;
  724. // Invalid Arg
  725. Assert(NULL != ppUnknown && NULL == pUnkOuter);
  726. // Create
  727. IF_NULLEXIT(pNew = new CNoteHdr);
  728. // Return the Innter
  729. *ppUnknown = (IMsoEnvelope*) pNew;
  730. exit:
  731. // Done
  732. return hr;
  733. }
  734. CNoteHdr::CNoteHdr()
  735. {
  736. // Not initialised
  737. // Member: Initialised In:
  738. // --------------------+---------------------------
  739. // m_wNoteType Finit
  740. m_cRef = 1;
  741. m_cHCI = 0;
  742. m_cAccountIDs = 0;
  743. m_iCurrComboIndex = 0;
  744. m_hwnd = 0;
  745. m_hwndLastFocus = 0;
  746. m_hwndRebar = 0;
  747. m_pri = priNorm; // default to Normal Pri
  748. m_cfAccept = CF_NULL;
  749. m_ntNote = OENA_COMPOSE;
  750. m_fMail = TRUE;
  751. m_fVCard = FALSE;
  752. m_fDirty = FALSE;
  753. m_fInSize = FALSE;
  754. m_fFlagged = FALSE;
  755. m_fAdvanced = FALSE;
  756. m_fResizing = FALSE;
  757. m_fUIActive = FALSE;
  758. m_fDigSigned = FALSE;
  759. m_fEncrypted = FALSE;
  760. m_fSkipLayout = TRUE; // Skip layout until after load
  761. m_fSignTrusted = TRUE;
  762. m_fOfficeInit = FALSE;
  763. m_fStillLoading = TRUE;
  764. m_fEncryptionOK = TRUE;
  765. m_fHandleChange = TRUE;
  766. m_fAutoComplete = FALSE;
  767. m_fSendImmediate = FALSE;
  768. m_fVCardSave = !m_fVCard;
  769. m_fSecurityInited = FALSE;
  770. m_fAddressesChanged = FALSE;
  771. m_fForceEncryption = FALSE;
  772. m_fThisHeadDigSigned = FALSE;
  773. m_fThisHeadEncrypted = FALSE;
  774. m_fDropTargetRegister = FALSE;
  775. m_pMsg = NULL;
  776. m_lpWab = NULL;
  777. m_rgHCI = NULL;
  778. m_hwndTT = NULL;
  779. m_pTable = NULL;
  780. m_lpWabal = NULL;
  781. m_pszRefs = NULL;
  782. m_pMsgSend = NULL;
  783. m_hCharset = NULL;
  784. m_pAccount = NULL;
  785. m_hInitRef = NULL;
  786. m_lpAttMan = NULL;
  787. m_hwndParent = NULL;
  788. m_pAddrWells = NULL;
  789. m_hwndToolbar = NULL;
  790. m_pHeaderSite = NULL;
  791. m_pEnvelopeSite = NULL;
  792. m_pMsoComponentMgr = NULL;
  793. m_lpszSecurityField = NULL;
  794. m_ppAccountIDs = NULL;
  795. *m_szLastLang = 0;
  796. m_MarkType = MARK_MESSAGE_NORMALTHREAD;
  797. m_hwndOldCapture = NULL;
  798. m_dwCurrentBtn = HDRCB_NO_BUTTON;
  799. m_dwClickedBtn = HDRCB_NO_BUTTON;
  800. m_dwEffect = 0;
  801. m_cCapture = 0;
  802. m_dwDragType = 0;
  803. m_dwComponentMgrID = 0;
  804. m_dwIMEStartCount = 0;
  805. m_dwFontNotify = 0;
  806. m_dxTBOffset = 0;
  807. m_grfKeyState = 0;
  808. m_cxLeftMargin = 0;
  809. m_himl = NULL;
  810. m_fPoster = FALSE;
  811. ZeroMemory(&m_SecState, sizeof(m_SecState));
  812. }
  813. CNoteHdr::~CNoteHdr()
  814. {
  815. Assert (m_pMsgSend==NULL);
  816. if (m_hwnd)
  817. DestroyWindow(m_hwnd);
  818. ReleaseObj(m_pTable);
  819. ReleaseObj(m_lpWabal);
  820. ReleaseObj(m_lpWab);
  821. SafeMemFree(m_pszRefs);
  822. ReleaseObj(m_pAccount);
  823. CleanupSECSTATE(&m_SecState);
  824. ReleaseObj(m_lpAttMan);
  825. ReleaseObj(m_pMsg);
  826. SafeMemFree(m_lpszSecurityField);
  827. if (m_pAddrWells)
  828. delete m_pAddrWells;
  829. if (m_himl)
  830. ImageList_Destroy(m_himl);
  831. if (m_fOfficeInit)
  832. HrOfficeInitialize(FALSE);
  833. if (m_cAccountIDs)
  834. {
  835. while (m_cAccountIDs--)
  836. SafeMemFree(m_ppAccountIDs[m_cAccountIDs]);
  837. }
  838. SafeMemFree(m_ppAccountIDs);
  839. }
  840. ULONG CNoteHdr::AddRef()
  841. {
  842. return ++m_cRef;
  843. }
  844. ULONG CNoteHdr::Release()
  845. {
  846. if (--m_cRef==0)
  847. {
  848. delete this;
  849. return 0;
  850. }
  851. return m_cRef;
  852. }
  853. HRESULT CNoteHdr::QueryInterface(REFIID riid, LPVOID *lplpObj)
  854. {
  855. if (!lplpObj)
  856. return E_INVALIDARG;
  857. *lplpObj = NULL;
  858. if (IsEqualIID(riid, IID_IUnknown))
  859. *lplpObj = (LPVOID)this;
  860. else if (IsEqualIID(riid, IID_IHeader))
  861. *lplpObj = (LPVOID)(LPHEADER)this;
  862. else if (IsEqualIID(riid, IID_IMsoEnvelope))
  863. *lplpObj = (LPVOID)(IMsoEnvelope*)this;
  864. else if (IsEqualIID(riid, IID_IMsoComponent))
  865. *lplpObj = (LPVOID)(IMsoComponent*)this;
  866. else if (IsEqualIID(riid, IID_IPersistMime))
  867. *lplpObj = (LPVOID)(LPPERSISTMIME)this;
  868. else if (IsEqualIID(riid, IID_IOleCommandTarget))
  869. *lplpObj = (LPVOID)(LPOLECOMMANDTARGET)this;
  870. else if (IsEqualIID(riid, IID_IDropTarget))
  871. *lplpObj = (LPVOID)(IDropTarget*)this;
  872. else if (IsEqualIID(riid, IID_IFontCacheNotify))
  873. *lplpObj = (LPVOID)(IFontCacheNotify*)this;
  874. else
  875. return E_NOINTERFACE;
  876. AddRef();
  877. return NOERROR;
  878. }
  879. // IOleCommandTarget
  880. HRESULT CNoteHdr::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pCmdText)
  881. {
  882. ULONG ul;
  883. HWND hwndFocus = GetFocus();
  884. DWORD dwFlags = 0;
  885. BOOL fFound = FALSE;
  886. if (!rgCmds)
  887. return E_INVALIDARG;
  888. for (int i=0; i<(int)m_cHCI; i++)
  889. {
  890. // if it's in our control-list and not a combobox
  891. if (hwndFocus == GetDlgItem(m_hwnd, m_rgHCI[i].idEdit) &&
  892. !(m_rgHCI[i].dwFlags & HCF_COMBO))
  893. {
  894. GetEditDisableFlags(hwndFocus, &dwFlags);
  895. fFound = TRUE;
  896. break;
  897. }
  898. }
  899. if (pguidCmdGroup == NULL)
  900. {
  901. for (ul=0;ul<cCmds; ul++)
  902. {
  903. switch (rgCmds[ul].cmdID)
  904. {
  905. case cmdidSend:
  906. case cmdidCheckNames:
  907. case cmdidAttach:
  908. case cmdidOptions:
  909. case cmdidSelectNames:
  910. case cmdidFocusTo:
  911. case cmdidFocusCc:
  912. case cmdidFocusSubject:
  913. // office commands enabled if we have an env-site
  914. rgCmds[ul].cmdf = m_pEnvelopeSite ? OLECMDF_ENABLED|OLECMDF_SUPPORTED : 0;
  915. break;
  916. case OLECMDID_CUT:
  917. case OLECMDID_PASTE:
  918. case OLECMDID_COPY:
  919. case OLECMDID_UNDO:
  920. case OLECMDID_SELECTALL:
  921. if (fFound)
  922. HrQueryToolbarButtons(dwFlags, pguidCmdGroup, &rgCmds[ul]);
  923. break;
  924. default:
  925. rgCmds[ul].cmdf = 0;
  926. break;
  927. }
  928. }
  929. return NOERROR;
  930. }
  931. else if (IsEqualGUID(CMDSETID_OutlookExpress, *pguidCmdGroup))
  932. {
  933. BOOL fReadOnly = IsReadOnly(),
  934. fMailAndNotReadOnly = m_fMail && !fReadOnly;
  935. UINT pri;
  936. GetPriority(&pri);
  937. for (ULONG ul = 0; ul < cCmds; ul++)
  938. {
  939. ULONG cmdID = rgCmds[ul].cmdID;
  940. if (0 != rgCmds[ul].cmdf)
  941. continue;
  942. switch (cmdID)
  943. {
  944. case ID_SELECT_RECIPIENTS:
  945. case ID_SELECT_NEWSGROUPS:
  946. case ID_INSERT_ATTACHMENT:
  947. rgCmds[ul].cmdf = QS_ENABLED(!fReadOnly);
  948. break;
  949. case ID_INSERT_CONTACT_INFO:
  950. HrGetVCardState(&rgCmds[ul].cmdf);
  951. break;
  952. case ID_ENCRYPT:
  953. if(m_fForceEncryption)
  954. {
  955. if(!m_fDigSigned)
  956. rgCmds[ul].cmdf = QS_ENABLECHECK(fMailAndNotReadOnly, m_fEncrypted);
  957. else
  958. break;
  959. }
  960. else
  961. rgCmds[ul].cmdf = QS_ENABLECHECK(fMailAndNotReadOnly, m_fEncrypted);
  962. break;
  963. case ID_DIGITALLY_SIGN:
  964. rgCmds[ul].cmdf = QS_ENABLECHECK(!fReadOnly && 0 == (g_dwAthenaMode & MODE_NEWSONLY), m_fDigSigned);
  965. break;
  966. case ID_SET_PRIORITY:
  967. case ID_POPUP_PRIORITY:
  968. rgCmds[ul].cmdf = QS_ENABLED(fMailAndNotReadOnly);
  969. break;
  970. case ID_PRIORITY_HIGH:
  971. case ID_PRIORITY_NORMAL:
  972. case ID_PRIORITY_LOW:
  973. rgCmds[ul].cmdf = QS_ENABLERADIO(fMailAndNotReadOnly, (pri == UINT(ID_PRIORITY_LOW - cmdID)));
  974. break;
  975. case ID_CHECK_NAMES:
  976. rgCmds[ul].cmdf = QS_ENABLED(TRUE);
  977. break;
  978. case ID_FULL_HEADERS:
  979. rgCmds[ul].cmdf = QS_ENABLECHECK(TRUE, m_fAdvanced);
  980. break;
  981. case ID_CUT:
  982. case ID_COPY:
  983. case ID_NOTE_COPY:
  984. case ID_PASTE:
  985. case ID_UNDO:
  986. case ID_SELECT_ALL:
  987. if (fFound)
  988. HrQueryToolbarButtons(dwFlags, pguidCmdGroup, &rgCmds[ul]);
  989. break;
  990. }
  991. }
  992. }
  993. else if (IsEqualGUID(*pguidCmdGroup, CGID_Envelope))
  994. {
  995. for (ul=0;ul<cCmds; ul++)
  996. {
  997. switch (rgCmds[ul].cmdID)
  998. {
  999. case MSOEENVCMDID_VCARD:
  1000. HrGetVCardState(&rgCmds[ul].cmdf);
  1001. break;
  1002. case MSOEENVCMDID_DIGSIGN:
  1003. rgCmds[ul].cmdf = QS_ENABLECHECK(!IsReadOnly(), m_fDigSigned);
  1004. break;
  1005. case MSOEENVCMDID_ENCRYPT:
  1006. if(m_fForceEncryption)
  1007. {
  1008. if(!m_fDigSigned)
  1009. rgCmds[ul].cmdf = QS_ENABLECHECK(m_fMail && !IsReadOnly(), m_fEncrypted);
  1010. else
  1011. break;
  1012. }
  1013. else
  1014. rgCmds[ul].cmdf = QS_ENABLECHECK(m_fMail && !IsReadOnly(), m_fEncrypted);
  1015. break;
  1016. case MSOEENVCMDID_DIRTY:
  1017. {
  1018. BOOL fDirty;
  1019. fDirty = m_fDirty || (m_lpAttMan && m_lpAttMan->HrIsDirty()==S_OK);
  1020. if (fDirty)
  1021. rgCmds[ul].cmdf = MSOCMDF_ENABLED;
  1022. else
  1023. rgCmds[ul].cmdf = 0;
  1024. }
  1025. break;
  1026. case MSOEENVCMDID_SEND:
  1027. case MSOEENVCMDID_CHECKNAMES:
  1028. case MSOEENVCMDID_AUTOCOMPLETE:
  1029. case MSOEENVCMDID_SETACTION:
  1030. case MSOEENVCMDID_PRIORITY:
  1031. rgCmds[ul].cmdf = MSOCMDF_ENABLED;
  1032. break;
  1033. default:
  1034. rgCmds[ul].cmdf = 0;
  1035. break;
  1036. }
  1037. }
  1038. return NOERROR;
  1039. }
  1040. return OLECMDERR_E_UNKNOWNGROUP;
  1041. }
  1042. // IOleCommandTarget
  1043. HRESULT CNoteHdr::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
  1044. {
  1045. HRESULT hr = NOERROR;
  1046. HWND hwndFocus;
  1047. UINT msg = 0;
  1048. WPARAM wParam = 0;
  1049. LPARAM lParam = 0;
  1050. BOOL fOfficeCmd=FALSE;
  1051. if (pguidCmdGroup == NULL)
  1052. {
  1053. switch (nCmdID)
  1054. {
  1055. case OLECMDID_CUT:
  1056. msg = WM_CUT;
  1057. break;
  1058. case OLECMDID_PASTE:
  1059. msg = WM_PASTE;
  1060. break;
  1061. case OLECMDID_COPY:
  1062. msg = WM_COPY;
  1063. break;
  1064. case OLECMDID_UNDO:
  1065. msg = WM_UNDO;
  1066. break;
  1067. case OLECMDID_SELECTALL:
  1068. msg = EM_SETSEL;
  1069. lParam = (LPARAM)(INT)-1;
  1070. break;
  1071. case OLECMDID_CLEARSELECTION:
  1072. msg = WM_CLEAR;
  1073. break;
  1074. default:
  1075. hr = _ConvertOfficeCmdIDToOE(&nCmdID);
  1076. if (hr==S_OK)
  1077. { //if sucess, nCmdId now points to an OE command
  1078. fOfficeCmd = TRUE;
  1079. goto oe_cmd;
  1080. }
  1081. else
  1082. hr = OLECMDERR_E_NOTSUPPORTED;
  1083. }
  1084. if (0 != msg)
  1085. {
  1086. hwndFocus = GetFocus();
  1087. if (IsChild(m_hwnd, hwndFocus))
  1088. SendMessage(hwndFocus, msg, wParam, lParam);
  1089. }
  1090. return hr;
  1091. }
  1092. else if (IsEqualGUID(*pguidCmdGroup, CGID_Envelope))
  1093. {
  1094. oe_cmd:
  1095. switch (nCmdID)
  1096. {
  1097. case MSOEENVCMDID_ATTACHFILE:
  1098. if (m_lpAttMan)
  1099. m_lpAttMan->WMCommand(0, ID_INSERT_ATTACHMENT, NULL);
  1100. break;
  1101. case MSOEENVCMDID_FOCUSTO:
  1102. ::SetFocus(GetDlgItem(m_hwnd, idADTo));
  1103. break;
  1104. case MSOEENVCMDID_FOCUSCC:
  1105. ::SetFocus(GetDlgItem(m_hwnd, idADCc));
  1106. break;
  1107. case MSOEENVCMDID_FOCUSSUBJ:
  1108. ::SetFocus(GetDlgItem(m_hwnd, idTXTSubject));
  1109. break;
  1110. case MSOEENVCMDID_SEND:
  1111. if (MSOCMDEXECOPT_DONTPROMPTUSER == nCmdExecOpt)
  1112. m_fSendImmediate = TRUE;
  1113. else
  1114. m_fSendImmediate = FALSE;
  1115. hr = HrSend();
  1116. break;
  1117. case MSOEENVCMDID_NEWS:
  1118. m_fMail = FALSE;
  1119. break;
  1120. case MSOEENVCMDID_CHECKNAMES:
  1121. hr = HrCheckNames((MSOCMDEXECOPT_PROMPTUSER == nCmdExecOpt)? FALSE: TRUE, TRUE);
  1122. if (!m_fMail)
  1123. {
  1124. hr = HrCheckGroups(FALSE);
  1125. if (hrNoRecipients == hr)
  1126. hr = S_OK;
  1127. }
  1128. break;
  1129. case MSOEENVCMDID_AUTOCOMPLETE:
  1130. m_fAutoComplete = TRUE;
  1131. break;
  1132. case MSOEENVCMDID_VIEWCONTACTS:
  1133. hr = HrViewContacts();
  1134. break;
  1135. case MSOEENVCMDID_DIGSIGN:
  1136. hr = HrHandleSecurityIDMs(TRUE);
  1137. break;
  1138. case MSOEENVCMDID_ENCRYPT:
  1139. hr = HrHandleSecurityIDMs(FALSE);
  1140. break;
  1141. case MSOEENVCMDID_SETACTION:
  1142. if (pvaIn->vt == VT_I4)
  1143. m_ntNote = pvaIn->lVal;
  1144. break;
  1145. case MSOEENVCMDID_SELECTRECIPIENTS:
  1146. hr = HrPickNames(0);
  1147. break;
  1148. case MSOEENVCMDID_ADDSENDER:
  1149. hr = HrAddSender();
  1150. break;
  1151. case MSOEENVCMDID_ADDALLONTO:
  1152. hr = HrAddAllOnToList();
  1153. break;
  1154. case MSOEENVCMDID_PICKNEWSGROUPS:
  1155. if (!m_fMail)
  1156. {
  1157. if (idTXTFollowupTo == GetWindowLong(GetFocus(), GWL_ID))
  1158. OnButtonClick(idbtnFollowup);
  1159. else
  1160. OnButtonClick(idbtnTo);
  1161. }
  1162. break;
  1163. case MSOEENVCMDID_VCARD:
  1164. m_fVCard = !m_fVCard;
  1165. hr = HrOnOffVCard();
  1166. break;
  1167. case MSOEENVCMDID_DIRTY:
  1168. _ClearDirtyFlag();
  1169. break;
  1170. default:
  1171. hr = OLECMDERR_E_NOTSUPPORTED;
  1172. }
  1173. // suppress OE errors when running under office-envelope
  1174. if (fOfficeCmd && hr != OLECMDERR_E_NOTSUPPORTED)
  1175. hr = S_OK;
  1176. return hr;
  1177. }
  1178. return OLECMDERR_E_UNKNOWNGROUP;
  1179. }
  1180. BOOL CNoteHdr::IsReplyNote()
  1181. {
  1182. return (m_ntNote==OENA_REPLYTOAUTHOR || m_ntNote==OENA_REPLYTONEWSGROUP || m_ntNote==OENA_REPLYALL);
  1183. }
  1184. //////////////////////////////////////////////////////////////////////////////
  1185. // IPersistMime::Load
  1186. // before calling this function, need to set m_ntNote by MSOEENVCMDID_SETACTION.
  1187. HRESULT CNoteHdr::Load(LPMIMEMESSAGE pMsg)
  1188. {
  1189. HRESULT hr=S_OK;
  1190. HCHARSET hCharset = NULL;
  1191. PROPVARIANT var;
  1192. Assert(pMsg);
  1193. if (!pMsg)
  1194. return E_INVALIDARG;
  1195. m_fStillLoading = TRUE;
  1196. m_fSkipLayout = TRUE;
  1197. m_fHandleChange = TRUE;
  1198. ReplaceInterface(m_pMsg, pMsg);
  1199. pMsg->GetCharset(&hCharset);
  1200. // bug #43295
  1201. // If we are in same codepages, we can pass FALSE to UpdateCharSetFont().
  1202. // But if we are in the differnet codepages, we need to update font to
  1203. // display the header (decoded) in the correct codepage.
  1204. // UpdateCharSetFonts(hCharset, FALSE);
  1205. if (hCharset)
  1206. HrUpdateCharSetFonts(hCharset, hCharset != m_hCharset);
  1207. // If there is an account set in the message, make sure that we use it.
  1208. var.vt = VT_LPSTR;
  1209. if (SUCCEEDED(pMsg->GetProp(PIDTOSTR(PID_ATT_ACCOUNTID), NOFLAGS, &var)))
  1210. {
  1211. IImnAccount *pAcct = NULL;
  1212. if (SUCCEEDED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, var.pszVal, &pAcct)))
  1213. {
  1214. HWND hwndCombo = GetDlgItem(m_hwnd, idFromCombo);
  1215. if (hwndCombo)
  1216. {
  1217. int cEntries = ComboBox_GetCount(hwndCombo);
  1218. for (int i = 0; i < cEntries; i++)
  1219. {
  1220. LPSTR idStr = (LPSTR)ComboBox_GetItemData(hwndCombo, i);
  1221. if (0 == lstrcmp(idStr, var.pszVal))
  1222. {
  1223. ComboBox_SetCurSel(hwndCombo, i);
  1224. m_iCurrComboIndex = i;
  1225. ReplaceInterface(m_pAccount, pAcct);
  1226. break;
  1227. }
  1228. }
  1229. }
  1230. else
  1231. ReplaceInterface(m_pAccount, pAcct);
  1232. pAcct->Release();
  1233. }
  1234. SafeMemFree(var.pszVal);
  1235. }
  1236. HrInitSecurity();
  1237. HrUpdateSecurity(pMsg);
  1238. // Modify subject if need to add a Fw: or a Re:
  1239. if (m_ntNote==OENA_FORWARD || IsReplyNote())
  1240. HrSetReplySubject(pMsg, OENA_FORWARD != m_ntNote);
  1241. else
  1242. HrSetupNote(pMsg);
  1243. SetReferences(pMsg);
  1244. if (m_fMail)
  1245. hr = HrSetMailRecipients(pMsg);
  1246. else
  1247. hr = HrSetNewsRecipients(pMsg);
  1248. if (OENA_READ == m_ntNote)
  1249. _SetEmptyFieldStrings();
  1250. // Update fiels, which depends from language
  1251. _UpdateTextFields(FALSE);
  1252. // setup priority, default to normal if a reply
  1253. if (!IsReplyNote())
  1254. HrSetPri(pMsg);
  1255. // on reply's auto add to the wab
  1256. else
  1257. HrAutoAddToWAB();
  1258. HrClearUndoStack();
  1259. m_fSkipLayout = FALSE;
  1260. ReLayout();
  1261. m_fDirty=FALSE;
  1262. if (m_pHeaderSite)
  1263. m_pHeaderSite->Update();
  1264. return hr;
  1265. }
  1266. void CNoteHdr::_SetEmptyFieldStrings(void)
  1267. {
  1268. PHCI phci = m_rgHCI;
  1269. AssertSz((OENA_READ == m_ntNote), "Should only get here in a read note.");
  1270. // No longer want EN_CHANGE messages to be handled in the richedits. At this
  1271. // point we will be setting text in the edits but don't want the phci->fEmpty
  1272. // to be set. That message causes the phci->fEmpty to be set.
  1273. m_fHandleChange = FALSE;
  1274. for (int i = 0; (ULONG)i < m_cHCI; i++, phci++)
  1275. if (phci->fEmpty)
  1276. {
  1277. if (0 == (phci->dwFlags & (HCF_COMBO|HCF_ATTACH)))
  1278. HdrSetRichEditText(GetDlgItem(m_hwnd, phci->idEdit), phci->szEmpty, FALSE);
  1279. else
  1280. SetWindowTextWrapW(GetDlgItem(m_hwnd, phci->idEdit), phci->szEmpty);
  1281. }
  1282. }
  1283. HRESULT CNoteHdr::_AttachVCard(IMimeMessage *pMsg)
  1284. {
  1285. HRESULT hr = 0;
  1286. LPWAB lpWab = 0;
  1287. TCHAR szVCardName[MAX_PATH],
  1288. szTempDir[MAX_PATH],
  1289. szVCardTempFile[MAX_PATH],
  1290. szVCFName[MAX_PATH];
  1291. UINT uFile=0;
  1292. INT iLen=0;
  1293. LPTSTR lptstr = NULL;
  1294. LPSTREAM pstmFile=NULL,
  1295. pstmCopy=NULL;
  1296. *szVCardName = 0;
  1297. *szTempDir = 0;
  1298. *szVCardTempFile = 0;
  1299. *szVCFName = 0;
  1300. if (m_lpAttMan && (S_OK == m_lpAttMan->HrCheckVCardExists(m_fMail)))
  1301. goto error;
  1302. hr = HrCreateWabObject(&lpWab);
  1303. if(FAILED(hr))
  1304. goto error;
  1305. GetOption(m_fMail?OPT_MAIL_VCARDNAME:OPT_NEWS_VCARDNAME, szVCardName, MAX_PATH);
  1306. if(*szVCardName == '\0')
  1307. {
  1308. hr = E_FAIL;
  1309. goto error;
  1310. }
  1311. GetTempPath(sizeof(szTempDir), szTempDir);
  1312. uFile = GetTempFileName(szTempDir, "VCF", 0, szVCardTempFile);
  1313. if (uFile == 0)
  1314. {
  1315. hr = E_FAIL;
  1316. goto error;
  1317. }
  1318. hr = lpWab->HrCreateVCardFile(szVCardName, szVCardTempFile);
  1319. if(FAILED(hr))
  1320. goto error;
  1321. hr = OpenFileStream((LPSTR)szVCardTempFile, OPEN_EXISTING, GENERIC_READ, &pstmFile);
  1322. if(FAILED(hr))
  1323. goto error;
  1324. hr = MimeOleCreateVirtualStream(&pstmCopy);
  1325. if(FAILED(hr))
  1326. goto error;
  1327. hr = HrCopyStream(pstmFile, pstmCopy, NULL);
  1328. if(FAILED(hr))
  1329. goto error;
  1330. wnsprintf(szVCFName, ARRAYSIZE(szVCFName), "%s%s", szVCardName, ".vcf");
  1331. hr = pMsg->AttachFile(szVCFName, pstmCopy, FALSE);
  1332. if(FAILED(hr))
  1333. goto error;
  1334. error:
  1335. ReleaseObj(pstmFile);
  1336. ReleaseObj(pstmCopy);
  1337. ReleaseObj(lpWab);
  1338. DeleteFile(szVCardTempFile);
  1339. return hr;
  1340. }
  1341. // IPersistMime::Save
  1342. HRESULT CNoteHdr::Save(LPMIMEMESSAGE pMsg, DWORD dwFlags)
  1343. {
  1344. HRESULT hr = NOERROR;
  1345. BOOL fSkipCheck = FALSE;
  1346. Assert(m_lpWabal);
  1347. // If sending, then previously did a CheckNames passing FALSE. If get here,
  1348. // then either all the names are resolved, or we are not sending so don't care
  1349. // what error codes are returned.
  1350. HrCheckNames(TRUE, FALSE);
  1351. // RAID 41350. If the save fails after leaving the header, the header
  1352. // recipients might be in a bad state. Make sure that they are resolved again
  1353. // after the save.
  1354. m_fAddressesChanged = TRUE;
  1355. // Is the security inited???
  1356. if(dwFlags != 0)
  1357. m_fSecurityInited = FALSE;
  1358. // This call will check if the dialog has been shown or if we are not mime and
  1359. // therefore should not show the dialog either.
  1360. if (m_pHeaderSite)
  1361. fSkipCheck = (S_OK != m_pHeaderSite->CheckCharsetConflict());
  1362. if (fSkipCheck)
  1363. {
  1364. IF_FAILEXIT(hr = _UnicodeSafeSave(pMsg, FALSE));
  1365. // Ignore any charset conflict errors.
  1366. hr = S_OK;
  1367. }
  1368. else
  1369. {
  1370. IF_FAILEXIT(hr = _UnicodeSafeSave(pMsg, TRUE));
  1371. if (MIME_S_CHARSET_CONFLICT == hr)
  1372. {
  1373. int ret;
  1374. PROPVARIANT Variant;
  1375. HCHARSET hCharset;
  1376. // Setup the Variant
  1377. Variant.vt = VT_UI4;
  1378. if (m_pEnvelopeSite && m_fShowedUnicodeDialog)
  1379. ret = m_iUnicodeDialogResult;
  1380. else
  1381. {
  1382. ret = IntlCharsetConflictDialogBox();
  1383. if (m_pEnvelopeSite)
  1384. {
  1385. m_fShowedUnicodeDialog = TRUE;
  1386. m_iUnicodeDialogResult = ret;
  1387. }
  1388. }
  1389. // Save As Is...
  1390. if (ret == IDOK)
  1391. {
  1392. IF_FAILEXIT(hr = _UnicodeSafeSave(pMsg, FALSE));
  1393. // User choose to send as is. Bail out and pretend no charset conflict
  1394. hr = S_OK;
  1395. }
  1396. // Save as Unicode
  1397. else if (ret == idcSendAsUnicode)
  1398. {
  1399. // User choose to send as Unicode (UTF8). set new charset and resnd
  1400. hCharset = GetMimeCharsetFromCodePage(CP_UTF8);
  1401. if (m_pHeaderSite)
  1402. m_pHeaderSite->ChangeCharset(hCharset);
  1403. else
  1404. {
  1405. pMsg->SetCharset(hCharset, CSET_APPLY_ALL);
  1406. ChangeLanguage(m_pMsg);
  1407. // bobn [6/23/99] Raid 77019
  1408. // If we switch to unicode and we're a word note, we
  1409. // need to remember that we're unicode so that we
  1410. // will not have the body encoding out of sync with
  1411. // the header encoding
  1412. if (m_pEnvelopeSite)
  1413. m_hCharset = hCharset;
  1414. }
  1415. IF_FAILEXIT(hr = _UnicodeSafeSave(pMsg, FALSE));
  1416. Assert(MIME_S_CHARSET_CONFLICT != hr);
  1417. }
  1418. else
  1419. {
  1420. // return to edit mode and bail out
  1421. hr = MAPI_E_USER_CANCEL;
  1422. goto exit;
  1423. }
  1424. }
  1425. else
  1426. {
  1427. IF_FAILEXIT(hr = _UnicodeSafeSave(pMsg, FALSE));
  1428. Assert(MIME_S_CHARSET_CONFLICT != hr);
  1429. }
  1430. }
  1431. exit:
  1432. return hr;
  1433. }
  1434. HRESULT CNoteHdr::_UnicodeSafeSave(IMimeMessage *pMsg, BOOL fCheckConflictOnly)
  1435. {
  1436. HRESULT hr = S_OK;
  1437. UINT cpID = 0;
  1438. WCHAR wsz[cchMaxSubject+1];
  1439. PROPVARIANT rVariant;
  1440. SYSTEMTIME st;
  1441. HdrGetRichEditText(GetDlgItem(m_hwnd, idTXTSubject), wsz, ARRAYSIZE(wsz), FALSE);
  1442. // All checks in here had better exit if get a MIME_S_CHARSET_CONFLICT
  1443. if (fCheckConflictOnly)
  1444. {
  1445. HCHARSET hCharSet;
  1446. BOOL fGetDefault = TRUE;
  1447. // Get charset for header
  1448. if (m_pHeaderSite)
  1449. {
  1450. if (SUCCEEDED(m_pHeaderSite->GetCharset(&hCharSet)))
  1451. {
  1452. cpID = CustomGetCPFromCharset(hCharSet, FALSE);
  1453. fGetDefault = FALSE;
  1454. }
  1455. }
  1456. // Get default charset if didn't get one from header
  1457. if (fGetDefault)
  1458. {
  1459. pMsg->GetCharset(&hCharSet);
  1460. cpID = CustomGetCPFromCharset(hCharSet, FALSE);
  1461. }
  1462. // If we are unicode, then there is no need to check because
  1463. // we will always work, so exit.
  1464. if (CP_UTF7 == cpID || CP_UTF8 == cpID || CP_UNICODE == cpID)
  1465. goto exit;
  1466. IF_FAILEXIT(hr = HrSetSenderInfoUtil(pMsg, m_pAccount, m_lpWabal, m_fMail, cpID, TRUE));
  1467. if (MIME_S_CHARSET_CONFLICT == hr)
  1468. goto exit;
  1469. IF_FAILEXIT(hr = HrSafeToEncodeToCP(wsz, cpID));
  1470. if (MIME_S_CHARSET_CONFLICT == hr)
  1471. goto exit;
  1472. if (m_pszRefs)
  1473. {
  1474. IF_FAILEXIT(hr = HrSafeToEncodeToCP(m_pszRefs, cpID));
  1475. if (MIME_S_CHARSET_CONFLICT == hr)
  1476. goto exit;
  1477. }
  1478. IF_FAILEXIT(hr = HrCheckDisplayNames(m_lpWabal, cpID));
  1479. if (MIME_S_CHARSET_CONFLICT == hr)
  1480. goto exit;
  1481. if (m_lpAttMan)
  1482. {
  1483. IF_FAILEXIT(hr = m_lpAttMan->CheckAttachNameSafeWithCP(cpID));
  1484. if (MIME_S_CHARSET_CONFLICT == hr)
  1485. goto exit;
  1486. }
  1487. if (!m_fMail)
  1488. {
  1489. IF_FAILEXIT(hr = HrNewsSave(pMsg, cpID, TRUE));
  1490. if (MIME_S_CHARSET_CONFLICT == hr)
  1491. goto exit;
  1492. }
  1493. // this checking produced a 4 bugs in OE 5.01 and 5.5 and I disaable it (YST)
  1494. #ifdef YST
  1495. if (m_pEnvelopeSite)
  1496. {
  1497. IF_FAILEXIT(hr = _CheckMsoBodyCharsetConflict(cpID));
  1498. if (MIME_S_CHARSET_CONFLICT == hr)
  1499. goto exit;
  1500. }
  1501. #endif
  1502. }
  1503. else
  1504. {
  1505. // ************************
  1506. // This portion only happens on save, so don't try to do for fCheckConflictOnly
  1507. // Anything not in this section had better be mirrored in the fCheckConflictOnly block above
  1508. IF_FAILEXIT(hr = HrSetAccountByAccount(pMsg, m_pAccount));
  1509. if (m_fVCard)
  1510. {
  1511. HWND hwndFocus=GetFocus();
  1512. hr = _AttachVCard(pMsg);
  1513. if (FAILED(hr))
  1514. {
  1515. if (AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(m_fMail?idsAthenaMail:idsAthenaNews),
  1516. MAKEINTRESOURCEW(idsErrAttachVCard), NULL, MB_YESNO | MB_ICONEXCLAMATION ) != IDYES)
  1517. {
  1518. ::SetFocus(hwndFocus);
  1519. IF_FAILEXIT(hr);
  1520. }
  1521. }
  1522. }
  1523. // set the time
  1524. rVariant.vt = VT_FILETIME;
  1525. GetSystemTime(&st);
  1526. SystemTimeToFileTime(&st, &rVariant.filetime);
  1527. pMsg->SetProp(PIDTOSTR(PID_ATT_SENTTIME), 0, &rVariant);
  1528. // Priority
  1529. if (m_pri!=priNone)
  1530. {
  1531. rVariant.vt = VT_UI4;
  1532. rVariant.ulVal = priLookup[m_pri];
  1533. pMsg->SetProp(PIDTOSTR(PID_ATT_PRIORITY), 0, &rVariant);
  1534. }
  1535. IF_FAILEXIT(hr = HrSaveSecurity(pMsg));
  1536. // end of save only portion.
  1537. // *************************
  1538. m_lpWabal->DeleteRecipType(MAPI_ORIG);
  1539. IF_FAILEXIT(hr = HrSetSenderInfoUtil(pMsg, m_pAccount, m_lpWabal, m_fMail, 0, FALSE));
  1540. IF_FAILEXIT(hr = MimeOleSetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_SUBJECT), NOFLAGS, wsz));
  1541. if (m_pszRefs)
  1542. IF_FAILEXIT(hr = MimeOleSetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_REFS), NOFLAGS, m_pszRefs));
  1543. // This must be called after HrSaveSecurity
  1544. IF_FAILEXIT(hr = HrSetWabalOnMsg(pMsg, m_lpWabal));
  1545. if (m_lpAttMan)
  1546. IF_FAILEXIT(hr = m_lpAttMan->Save(pMsg, 0));
  1547. if (!m_fMail)
  1548. IF_FAILEXIT(hr = HrNewsSave(pMsg, cpID, FALSE));
  1549. }
  1550. exit:
  1551. return hr;
  1552. }
  1553. // IPersist::GetClassID
  1554. HRESULT CNoteHdr::GetClassID(CLSID *pClsID)
  1555. {
  1556. //TODO:
  1557. *pClsID = CLSID_OEEnvelope;
  1558. return NOERROR;
  1559. }
  1560. //////////////////////////////////////////////////////////////////////////////
  1561. // IHeader::SetRect
  1562. HRESULT CNoteHdr::SetRect(LPRECT prc)
  1563. {
  1564. MoveWindow(m_hwnd, prc->left, prc->top, prc->right-prc->left, prc->bottom - prc->top, TRUE);
  1565. return NOERROR;
  1566. }
  1567. // IHeader::GetRect
  1568. HRESULT CNoteHdr::GetRect(LPRECT prcView)
  1569. {
  1570. GetRealClientRect(m_hwnd, prcView);
  1571. return NOERROR;
  1572. }
  1573. // IHeader::Init
  1574. HRESULT CNoteHdr::Init(IHeaderSite* pHeaderSite, HWND hwndParent)
  1575. {
  1576. if (pHeaderSite==NULL || hwndParent==NULL)
  1577. return E_INVALIDARG;
  1578. m_pHeaderSite = pHeaderSite;
  1579. m_pHeaderSite->AddRef();
  1580. m_hwndParent = hwndParent;
  1581. return HrInit(NULL);
  1582. }
  1583. // IHeader::SetPriority
  1584. HRESULT CNoteHdr::SetPriority(UINT pri)
  1585. {
  1586. RECT rc;
  1587. if ((UINT)m_pri != pri)
  1588. {
  1589. m_pri = pri;
  1590. InvalidateStatus();
  1591. ReLayout();
  1592. SetDirtyFlag();
  1593. }
  1594. return NOERROR;
  1595. }
  1596. // IHeader::GetPriority
  1597. HRESULT CNoteHdr::GetPriority(UINT* ppri)
  1598. {
  1599. *ppri = m_pri;
  1600. return NOERROR;
  1601. }
  1602. // Update fiels, which depends from language
  1603. void CNoteHdr::_UpdateTextFields(BOOL fSetWabal)
  1604. {
  1605. LPWSTR lpszOrg = NULL,
  1606. lpszSubj = NULL,
  1607. lpszKeywords = NULL;
  1608. if (IsReadOnly())
  1609. {
  1610. // if it's a readnote, reload the header that depend on a charset
  1611. MimeOleGetBodyPropW(m_pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_SUBJECT), NOFLAGS, &lpszSubj);
  1612. MimeOleGetBodyPropW(m_pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_KEYWORDS), NOFLAGS, &lpszKeywords);
  1613. MimeOleGetBodyPropW(m_pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_ORG), NOFLAGS, &lpszOrg);
  1614. if(lpszOrg)
  1615. {
  1616. HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTOrg), lpszOrg, FALSE);
  1617. MemFree(lpszOrg);
  1618. }
  1619. if(lpszKeywords)
  1620. {
  1621. HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTKeywords), lpszKeywords, FALSE);
  1622. MemFree(lpszKeywords);
  1623. }
  1624. if(lpszSubj)
  1625. {
  1626. HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTSubject), lpszSubj, FALSE);
  1627. MemFree(lpszSubj);
  1628. }
  1629. if (fSetWabal)
  1630. {
  1631. LPWABAL lpWabal = NULL;
  1632. Assert(m_hwnd);
  1633. Assert(m_pMsg);
  1634. Assert(m_lpWabal);
  1635. if (SUCCEEDED(HrGetWabalFromMsg(m_pMsg, &lpWabal)))
  1636. {
  1637. ReplaceInterface(m_lpWabal, lpWabal);
  1638. if (SUCCEEDED(m_pAddrWells->HrSetWabal(m_lpWabal)))
  1639. {
  1640. m_lpWabal->HrResolveNames(NULL, FALSE);
  1641. m_pAddrWells->HrDisplayWells(m_hwnd);
  1642. }
  1643. }
  1644. ReleaseObj(lpWabal);
  1645. }
  1646. m_fDirty = FALSE; // don't make dirty if a readnote
  1647. }
  1648. }
  1649. // IHeader::ChangeLanguage
  1650. HRESULT CNoteHdr::ChangeLanguage(LPMIMEMESSAGE pMsg)
  1651. {
  1652. HCHARSET hCharset=NULL;
  1653. if (!pMsg)
  1654. return E_INVALIDARG;
  1655. pMsg->GetCharset(&hCharset);
  1656. // Update fields, which depends from language
  1657. _UpdateTextFields(TRUE);
  1658. // update the fonts scripts etc
  1659. HrUpdateCharSetFonts(hCharset, TRUE);
  1660. // notify the addr wells that the font need to change
  1661. m_pAddrWells->OnFontChange();
  1662. return S_OK;
  1663. }
  1664. HRESULT CNoteHdr::OnPreFontChange()
  1665. {
  1666. HWND hwndFrom=GetDlgItem(m_hwnd, idFromCombo);
  1667. if (hwndFrom)
  1668. SendMessage(hwndFrom, WM_SETFONT, 0, 0);
  1669. return S_OK;
  1670. }
  1671. HRESULT CNoteHdr::OnPostFontChange()
  1672. {
  1673. ULONG cxNewLeftMargin = _GetLeftMargin();
  1674. HWND hwndFrom=GetDlgItem(m_hwnd, idFromCombo);
  1675. HFONT hFont;
  1676. HWND hwndBlock = HwndStartBlockingPaints(m_hwnd);
  1677. BOOL fLayout=FALSE;
  1678. if (g_pFieldSizeMgr->FontsChanged() || (m_cxLeftMargin != cxNewLeftMargin))
  1679. {
  1680. m_cxLeftMargin = cxNewLeftMargin;
  1681. fLayout=TRUE;
  1682. }
  1683. // update the fonts
  1684. ChangeLanguage(m_pMsg);
  1685. // update the account combo
  1686. if (hwndFrom &&
  1687. g_lpIFontCache &&
  1688. g_lpIFontCache->GetFont(FNT_SYS_ICON, NULL, &hFont)==S_OK)
  1689. SendMessage(hwndFrom, WM_SETFONT, (WPARAM)hFont, 0);
  1690. if (fLayout)
  1691. ReLayout();
  1692. if (hwndBlock)
  1693. StopBlockingPaints(hwndBlock);
  1694. return S_OK;
  1695. }
  1696. // IHeader::GetTitle
  1697. HRESULT CNoteHdr::GetTitle(LPWSTR pwszTitle, ULONG cch)
  1698. {
  1699. // Locals
  1700. static WCHAR s_wszNoteTitle[cchHeaderMax+1] = L"";
  1701. static DWORD s_cLenTitle = 0;
  1702. INETCSETINFO CsetInfo;
  1703. UINT uiCodePage = 0;
  1704. HRESULT hr = S_OK;
  1705. LPWSTR pwszLang = NULL;
  1706. BOOL fWinNT = g_OSInfo.dwPlatformId == VER_PLATFORM_WIN32_NT;
  1707. if (pwszTitle==NULL || cch==0)
  1708. return E_INVALIDARG;
  1709. if (*s_wszNoteTitle == L'\0')
  1710. {
  1711. if (fWinNT)
  1712. {
  1713. AthLoadStringW(idsNoteLangTitle, s_wszNoteTitle, ARRAYSIZE(s_wszNoteTitle));
  1714. // -4 for the %1 and %2 that will be replaced
  1715. s_cLenTitle = lstrlenW(s_wszNoteTitle) - 4;
  1716. }
  1717. else
  1718. {
  1719. AthLoadStringW(idsNoteLangTitle9x, s_wszNoteTitle, ARRAYSIZE(s_wszNoteTitle));
  1720. // -2 for the %s that will be replaced
  1721. s_cLenTitle = lstrlenW(s_wszNoteTitle) - 2;
  1722. }
  1723. }
  1724. if (m_hCharset)
  1725. {
  1726. MimeOleGetCharsetInfo(m_hCharset,&CsetInfo);
  1727. uiCodePage = CsetInfo.cpiWindows;
  1728. }
  1729. if (uiCodePage == 0 || uiCodePage == GetACP())
  1730. {
  1731. HdrGetRichEditText(GetDlgItem(m_hwnd, idTXTSubject), pwszTitle, cch-1, FALSE);
  1732. if (0 == *pwszTitle)
  1733. AthLoadStringW((OENA_READ == m_ntNote) ? idsNoSubject : idsNewNote, pwszTitle, cch-1);
  1734. ConvertTabsToSpacesW(pwszTitle);
  1735. }
  1736. else
  1737. {
  1738. AssertSz(cch > (ARRAYSIZE(CsetInfo.szName) + s_cLenTitle), "Won't fit language. Get bigger cch!!!");
  1739. // if no lang pack then s_szLastLang is empty and we need to try to restore message header
  1740. IF_NULLEXIT(pwszLang = PszToUnicode(CP_ACP, *m_szLastLang ? m_szLastLang : CsetInfo.szName));
  1741. if (fWinNT)
  1742. {
  1743. WCHAR wszSubj[cchHeaderMax+1];
  1744. DWORD cchLang,
  1745. cchTotal,
  1746. cchSubj;
  1747. LPSTR pArgs[2];
  1748. *wszSubj = 0;
  1749. HdrGetRichEditText(GetDlgItem(m_hwnd, idTXTSubject), wszSubj, ARRAYSIZE(wszSubj), FALSE);
  1750. if (0 == *wszSubj)
  1751. AthLoadStringW((OENA_READ == m_ntNote) ? idsNoSubject : idsNewNote, wszSubj, ARRAYSIZE(wszSubj));
  1752. ConvertTabsToSpacesW(wszSubj);
  1753. cchSubj = lstrlenW(wszSubj);
  1754. cchLang = lstrlenW(pwszLang);
  1755. cchTotal = s_cLenTitle + cchLang + cchSubj + 1;
  1756. // If too big, truncate the subject, not language since
  1757. // asserting that we have enough for language.
  1758. if (cchTotal > cch)
  1759. {
  1760. cchSubj -= (cchTotal - cch);
  1761. wszSubj[cchSubj] = L'\0';
  1762. }
  1763. pArgs[0] = (LPSTR)wszSubj;
  1764. pArgs[1] = (LPSTR)pwszLang;
  1765. *pwszTitle = L'\0';
  1766. FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
  1767. s_wszNoteTitle,
  1768. 0, 0,
  1769. pwszTitle,
  1770. cch,
  1771. (va_list*)pArgs);
  1772. }
  1773. else
  1774. {
  1775. wnsprintfW(pwszTitle, cch, s_wszNoteTitle, pwszLang);
  1776. }
  1777. }
  1778. exit:
  1779. MemFree(pwszLang);
  1780. return hr;
  1781. }
  1782. void CNoteHdr::_AddRecipTypeToMenu(HMENU hmenu)
  1783. {
  1784. ADRINFO adrInfo;
  1785. WCHAR wszDisp[256];
  1786. ULONG uPos=0;
  1787. BOOL fFound = m_lpWabal->FGetFirst(&adrInfo);
  1788. while (fFound && (uPos < cMaxRecipMenu))
  1789. {
  1790. if (adrInfo.lRecipType==MAPI_TO || adrInfo.lRecipType==MAPI_CC)
  1791. {
  1792. if(lstrlenW(adrInfo.lpwszDisplay) > 255)
  1793. {
  1794. StrCpyNW(wszDisp, adrInfo.lpwszDisplay, 255);
  1795. wszDisp[255] = '\0';
  1796. }
  1797. else
  1798. {
  1799. StrCpyNW(wszDisp, adrInfo.lpwszDisplay, ARRAYSIZE(wszDisp));
  1800. }
  1801. AppendMenuWrapW(hmenu, MF_STRING , ID_ADD_RECIPIENT_FIRST+uPos, wszDisp);
  1802. uPos++;
  1803. }
  1804. fFound = m_lpWabal->FGetNext(&adrInfo);
  1805. }
  1806. }
  1807. // IHeader::UpdateRecipientMenu
  1808. HRESULT CNoteHdr::UpdateRecipientMenu(HMENU hmenu)
  1809. {
  1810. HRESULT hr = E_FAIL;
  1811. BOOL fSucceeded = TRUE;
  1812. // destory current recipients
  1813. while (fSucceeded)
  1814. fSucceeded = DeleteMenu(hmenu, 2, MF_BYPOSITION);
  1815. if (!m_lpWabal)
  1816. return E_FAIL;
  1817. // Add To: and Cc: people
  1818. _AddRecipTypeToMenu(hmenu);
  1819. return NOERROR;
  1820. }
  1821. // IHeader::SetInitFocus
  1822. HRESULT CNoteHdr::SetInitFocus(BOOL fSubject)
  1823. {
  1824. if (m_rgHCI)
  1825. {
  1826. if (fSubject)
  1827. ::SetFocus(GetDlgItem(m_hwnd, idTXTSubject));
  1828. else
  1829. {
  1830. if (0 == (m_rgHCI[0].dwFlags & HCF_COMBO))
  1831. ::SetFocus(GetDlgItem(m_hwnd, m_rgHCI[0].idEdit));
  1832. else
  1833. ::SetFocus(GetDlgItem(m_hwnd, m_rgHCI[1].idEdit));
  1834. }
  1835. }
  1836. return NOERROR;
  1837. }
  1838. // IHeader::SetVCard
  1839. HRESULT CNoteHdr::SetVCard(BOOL fFresh)
  1840. {
  1841. HRESULT hr = NOERROR;
  1842. TCHAR szBuf[MAX_PATH];
  1843. LPWAB lpWab = NULL;
  1844. ULONG cbEID=0;
  1845. LPENTRYID lpEID = NULL;
  1846. WORD wVCard;
  1847. if (m_ntNote == OENA_READ)
  1848. wVCard = (m_lpAttMan->HrFVCard() == S_OK) ? VCardTRUE : VCardFALSE;
  1849. else if (!fFresh) //not a fresh note.
  1850. wVCard = VCardFALSE;
  1851. else if (m_ntNote == OENA_FORWARD)
  1852. wVCard = (m_lpAttMan->HrCheckVCardExists(m_fMail) == S_OK) ? VCardFALSE : VCardDONTKNOW;
  1853. else
  1854. wVCard = VCardDONTKNOW;
  1855. if (wVCard != VCardDONTKNOW)
  1856. m_fVCard = wVCard;
  1857. else
  1858. {
  1859. hr = HrGetVCardName(szBuf, sizeof(szBuf));
  1860. if (FAILED(hr)) // no vcard name selected
  1861. {
  1862. if (m_fMail)
  1863. SetDwOption(OPT_MAIL_ATTACHVCARD, FALSE, NULL, 0);
  1864. else
  1865. SetDwOption(OPT_NEWS_ATTACHVCARD, FALSE, NULL, 0);
  1866. }
  1867. if (m_fMail)
  1868. m_fVCard = (BOOL)DwGetOption(OPT_MAIL_ATTACHVCARD);
  1869. else
  1870. m_fVCard = (BOOL)DwGetOption(OPT_NEWS_ATTACHVCARD);
  1871. }
  1872. hr = HrOnOffVCard();
  1873. if (FAILED(hr))
  1874. goto error;
  1875. error:
  1876. ReleaseObj(lpWab);
  1877. return hr;
  1878. }
  1879. // IHeader::IsSecured
  1880. HRESULT CNoteHdr::IsSecured()
  1881. {
  1882. if (m_fDigSigned || m_fEncrypted)
  1883. return S_OK;
  1884. else
  1885. return S_FALSE;
  1886. }
  1887. HRESULT CNoteHdr::IsHeadSigned()
  1888. {
  1889. if (m_fDigSigned)
  1890. return S_OK;
  1891. else
  1892. return S_FALSE;
  1893. }
  1894. // set ForvrEncryption form policy module if fSet is TRUE
  1895. // if fSet is not set then returns S_FALSE if ForceEncryption was not set
  1896. HRESULT CNoteHdr::ForceEncryption(BOOL *fEncrypt, BOOL fSet)
  1897. {
  1898. HRESULT hr = S_FALSE;
  1899. if(fSet)
  1900. {
  1901. Assert(fEncrypt);
  1902. if(m_fDigSigned)
  1903. {
  1904. if(*fEncrypt)
  1905. m_fEncrypted = TRUE;
  1906. }
  1907. m_fForceEncryption = *fEncrypt;
  1908. if(m_ntNote != OENA_READ)
  1909. HrUpdateSecurity();
  1910. hr = S_OK;
  1911. }
  1912. else if(m_fForceEncryption && m_fDigSigned)
  1913. {
  1914. m_fEncrypted = TRUE;
  1915. hr = S_OK;
  1916. }
  1917. return(hr);
  1918. }
  1919. // IHeader::AddRecipient
  1920. HRESULT CNoteHdr::AddRecipient(int idOffset)
  1921. {
  1922. BOOL fFound;
  1923. ULONG uPos=0;
  1924. ADRINFO adrInfo;
  1925. LPADRINFO lpAdrInfo=0;
  1926. LPWAB lpWab;
  1927. HRESULT hr=E_FAIL;
  1928. Assert(m_lpWabal);
  1929. fFound = m_lpWabal->FGetFirst(&adrInfo);
  1930. while (fFound &&
  1931. (uPos < cMaxRecipMenu))
  1932. {
  1933. if (idOffset==-1 &&
  1934. adrInfo.lRecipType==MAPI_ORIG)
  1935. {
  1936. lpAdrInfo=&adrInfo;
  1937. break;
  1938. }
  1939. if (adrInfo.lRecipType==MAPI_TO || adrInfo.lRecipType==MAPI_CC)
  1940. {
  1941. if (idOffset==(int)uPos)
  1942. {
  1943. lpAdrInfo=&adrInfo;
  1944. break;
  1945. }
  1946. uPos++;
  1947. }
  1948. fFound=m_lpWabal->FGetNext(&adrInfo);
  1949. }
  1950. if (lpAdrInfo &&
  1951. !FAILED (HrCreateWabObject (&lpWab)))
  1952. {
  1953. hr=lpWab->HrAddToWAB(m_hwnd, lpAdrInfo);
  1954. lpWab->Release ();
  1955. }
  1956. if (FAILED(hr) && hr!=MAPI_E_USER_CANCEL)
  1957. {
  1958. if (hr==MAPI_E_COLLISION)
  1959. AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrAddrDupe), NULL, MB_OK);
  1960. else
  1961. AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrAddToWAB), NULL, MB_OK);
  1962. }
  1963. return NOERROR;
  1964. }
  1965. // IHeader::OnDocumentReady
  1966. HRESULT CNoteHdr::OnDocumentReady(LPMIMEMESSAGE pMsg)
  1967. {
  1968. HRESULT hr = S_OK;
  1969. m_fStillLoading = FALSE;
  1970. if (m_lpAttMan)
  1971. hr = m_lpAttMan->Load(pMsg);
  1972. return hr;
  1973. }
  1974. // IHeader::DropFiles
  1975. HRESULT CNoteHdr::DropFiles(HDROP hDrop, BOOL fMakeLinks)
  1976. {
  1977. HRESULT hr = S_OK;
  1978. if (m_lpAttMan)
  1979. hr = m_lpAttMan->HrDropFiles(hDrop, fMakeLinks);
  1980. return hr;
  1981. }
  1982. //////////////////////////////////////////////////////////////////////////////
  1983. // IMsoEnvelope:Init
  1984. HRESULT CNoteHdr::Init(IUnknown* punk, IMsoEnvelopeSite* pesit, DWORD grfInit)
  1985. {
  1986. HRESULT hr = S_OK;
  1987. if (punk == NULL && pesit == NULL && grfInit == 0)
  1988. {
  1989. SafeRelease(m_pEnvelopeSite);
  1990. hr = E_FAIL;
  1991. goto Exit;
  1992. }
  1993. if (pesit==NULL)
  1994. {
  1995. hr = E_INVALIDARG;
  1996. goto Exit;
  1997. }
  1998. ReplaceInterface(m_pEnvelopeSite, pesit);
  1999. hr = HrInit(NULL);
  2000. if (FAILED(hr))
  2001. goto Exit;
  2002. if (grfInit & ENV_INIT_FROMSTREAM)
  2003. {
  2004. IStream *pstm = NULL;
  2005. // no IStream to work with?
  2006. if (!punk)
  2007. return E_INVALIDARG;
  2008. hr = punk->QueryInterface(IID_IStream, (LPVOID*)&pstm);
  2009. if (!FAILED(hr))
  2010. {
  2011. hr = _LoadFromStream(pstm);
  2012. pstm->Release();
  2013. }
  2014. }
  2015. _SetButtonText(ID_SEND_NOW, MAKEINTRESOURCE((grfInit & ENV_INIT_DOCBEHAVIOR)?idsEnvSendCopy:idsEnvSend));
  2016. Exit:
  2017. return hr;
  2018. }
  2019. // IMsoEnvelope::SetParent
  2020. // we create the envelope window here
  2021. HRESULT CNoteHdr::SetParent(HWND hwndParent)
  2022. {
  2023. Assert (IsWindow(m_hwnd));
  2024. ShowWindow(m_hwnd, hwndParent ? SW_SHOW : SW_HIDE);
  2025. if (hwndParent)
  2026. {
  2027. _RegisterWithComponentMgr(TRUE);
  2028. _RegisterAsDropTarget(TRUE);
  2029. _RegisterWithFontCache(TRUE);
  2030. }
  2031. else
  2032. {
  2033. _RegisterWithComponentMgr(FALSE);
  2034. _RegisterAsDropTarget(FALSE);
  2035. _RegisterWithFontCache(FALSE);
  2036. }
  2037. m_hwndParent = hwndParent?hwndParent:g_hwndInit;
  2038. ::SetParent(m_hwnd, m_hwndParent);
  2039. if (hwndParent)
  2040. ReLayout();
  2041. return S_OK;
  2042. }
  2043. // IMsoEnvelope::Resize
  2044. HRESULT CNoteHdr::Resize(LPCRECT prc)
  2045. {
  2046. MoveWindow(m_hwnd, prc->left, prc->top, prc->right - prc->left, prc->bottom - prc->top, TRUE);
  2047. return NOERROR;
  2048. }
  2049. // IMsoEnvelope::Show
  2050. HRESULT CNoteHdr::Show(BOOL fShow)
  2051. {
  2052. ShowWindow(m_hwnd, fShow ? SW_SHOW : SW_HIDE);
  2053. return NOERROR;
  2054. }
  2055. // IMsoEnvelope::SetHelpMode
  2056. HRESULT CNoteHdr::SetHelpMode(BOOL fEnter)
  2057. {
  2058. return NOERROR;
  2059. }
  2060. // IMsoEnvelope::Save
  2061. HRESULT CNoteHdr::Save(IStream* pstm, DWORD grfSave)
  2062. {
  2063. HRESULT hr = S_OK;
  2064. IMimeMessage *pMsg = NULL;
  2065. PERSISTHEADER rPersistHdr;
  2066. if (pstm == NULL)
  2067. return E_INVALIDARG;
  2068. hr = WriteClassStm(pstm, CLSID_OEEnvelope);
  2069. if (!FAILED(hr))
  2070. {
  2071. ZeroMemory(&rPersistHdr, sizeof(PERSISTHEADER));
  2072. rPersistHdr.cbSize = sizeof(PERSISTHEADER);
  2073. hr = pstm->Write(&rPersistHdr, sizeof(PERSISTHEADER), NULL);
  2074. if (!FAILED(hr))
  2075. {
  2076. hr = HrCreateMessage(&pMsg);
  2077. if (!FAILED(hr))
  2078. {
  2079. hr = Save(pMsg, 0);
  2080. if (!FAILED(hr))
  2081. hr = pMsg->Save(pstm, FALSE);
  2082. pMsg->Release();
  2083. }
  2084. }
  2085. }
  2086. _ClearDirtyFlag();
  2087. return hr;
  2088. }
  2089. // IMsoEnvelope::GetAttach
  2090. HRESULT CNoteHdr::GetAttach(const WCHAR* wszName,IStream** ppstm)
  2091. {
  2092. return NOERROR;
  2093. }
  2094. HRESULT CNoteHdr::SetAttach(const WCHAR* wszName, const WCHAR *wszCID, IStream **ppstm, DWORD *pgrfAttach)
  2095. {
  2096. IStream *pstm=0;
  2097. HBODY hBody;
  2098. LPWSTR pszCntTypeW=NULL;
  2099. HRESULT hr;
  2100. PROPVARIANT pv;
  2101. if (!m_pMsgSend)
  2102. return E_FAIL;
  2103. IF_FAILEXIT(hr = MimeOleCreateVirtualStream(&pstm));
  2104. IF_FAILEXIT(hr = m_pMsgSend->AttachURL(NULL, NULL, 0, pstm, NULL, &hBody));
  2105. // strip off cid: header
  2106. if (StrCmpNIW(wszCID, L"CID:", 4)==0)
  2107. wszCID += 4;
  2108. IF_FAILEXIT(hr = MimeOleSetBodyPropW(m_pMsgSend, hBody, PIDTOSTR(PID_HDR_CNTID), 0, wszCID));
  2109. IF_FAILEXIT(hr = MimeOleSetBodyPropW(m_pMsgSend, hBody, PIDTOSTR(STR_ATT_FILENAME), 0, wszName));
  2110. FindMimeFromData(NULL, wszName, NULL, NULL, NULL, 0, &pszCntTypeW, 0);
  2111. pv.vt = pszCntTypeW ? VT_LPWSTR : VT_LPSTR;
  2112. if (pszCntTypeW)
  2113. pv.pwszVal = pszCntTypeW;
  2114. else
  2115. pv.pszVal = (LPSTR)STR_MIME_APPL_STREAM; // if FindMimeFromData fails use application/octect-stream
  2116. IF_FAILEXIT(hr = m_pMsgSend->SetBodyProp(hBody, PIDTOSTR(PID_HDR_CNTTYPE), 0, &pv));
  2117. *ppstm = pstm;
  2118. pstm->AddRef();
  2119. exit:
  2120. ReleaseObj(pstm);
  2121. return hr;
  2122. }
  2123. // IMsoEnvelope::NewAttach
  2124. HRESULT CNoteHdr::NewAttach(const WCHAR* pwzName,DWORD grfAttach)
  2125. {
  2126. return NOERROR;
  2127. }
  2128. // IMsoEnvelope::SetFocus
  2129. HRESULT CNoteHdr::SetFocus(DWORD grfFocus)
  2130. {
  2131. if (!m_rgHCI)
  2132. return S_OK;
  2133. if (grfFocus & ENV_FOCUS_TAB)
  2134. {
  2135. // reverse tab in from word, focus on well if visible or subject
  2136. if (IsWindowVisible(GetDlgItem(m_hwnd, idwAttachWell)))
  2137. ::SetFocus(GetDlgItem(m_hwnd, idwAttachWell));
  2138. else
  2139. ::SetFocus(GetDlgItem(m_hwnd, idTXTSubject));
  2140. }
  2141. else if (grfFocus & ENV_FOCUS_INITIAL)
  2142. SetInitFocus(FALSE);
  2143. else if (grfFocus & ENV_FOCUS_RESTORE && m_hwndLastFocus)
  2144. ::SetFocus(m_hwndLastFocus);
  2145. return NOERROR;
  2146. }
  2147. // IMsoEnvelope::GetHeaderInfo
  2148. HRESULT CNoteHdr::GetHeaderInfo(ULONG dispid, DWORD grfHeader, void** pszData)
  2149. {
  2150. HRESULT hr = E_FAIL;
  2151. if (!pszData)
  2152. return E_INVALIDARG;
  2153. *pszData = NULL;
  2154. if (dispid == dispidSubject)
  2155. hr = HrGetFieldText((LPWSTR*)pszData, idTXTSubject);
  2156. return hr;
  2157. }
  2158. // IMsoEnvelope::SetHeaderInfo
  2159. HRESULT CNoteHdr::SetHeaderInfo(ULONG dispid, const void *pv)
  2160. {
  2161. HRESULT hr = S_OK;
  2162. LPSTR psz = NULL;
  2163. switch (dispid)
  2164. {
  2165. case dispidSubject:
  2166. HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTSubject), (LPWSTR)pv, FALSE);
  2167. break;
  2168. case dispidSendBtnText:
  2169. {
  2170. IF_NULLEXIT(psz = PszToANSI(GetACP(), (LPWSTR)pv));
  2171. _SetButtonText(ID_SEND_NOW, psz);
  2172. break;
  2173. }
  2174. }
  2175. exit:
  2176. MemFree(psz);
  2177. return NOERROR;
  2178. }
  2179. // IMsoEnvelope::IsDirty
  2180. HRESULT CNoteHdr::IsDirty()
  2181. {
  2182. if (m_fDirty || (m_lpAttMan && (m_lpAttMan->HrIsDirty()==S_OK)))
  2183. return S_OK;
  2184. else
  2185. return S_FALSE;
  2186. }
  2187. // IMsoEnvelope::GetLastError
  2188. HRESULT CNoteHdr::GetLastError(HRESULT hr, WCHAR __RPC_FAR *wszBuf, ULONG cchBuf)
  2189. {
  2190. DWORD ids;
  2191. switch (hr)
  2192. {
  2193. case E_NOTIMPL:
  2194. ids = idsNYIGeneral;
  2195. break;
  2196. default:
  2197. ids = idsGenericError;
  2198. }
  2199. AthLoadStringW(ids, wszBuf, cchBuf);
  2200. return S_OK;
  2201. }
  2202. // IMsoEnvelope::DoDebug
  2203. HRESULT CNoteHdr::DoDebug(DWORD grfDebug)
  2204. {
  2205. return S_OK;
  2206. }
  2207. ////////////////////////////////////////////////////////////////////////////////////////
  2208. // IMsoComponent::FDebugMessage
  2209. BOOL CNoteHdr::FDebugMessage(HMSOINST hinst, UINT message, WPARAM wParam, LPARAM lParam)
  2210. {
  2211. return TRUE;
  2212. }
  2213. // IMsoComponent::FPreTranslateMessage
  2214. BOOL CNoteHdr::FPreTranslateMessage(MSG *pMsg)
  2215. {
  2216. HWND hwnd;
  2217. BOOL fShift;
  2218. // Invalid ARgs
  2219. if (NULL == pMsg)
  2220. return FALSE;
  2221. // check if it's US, or one of our children
  2222. if (pMsg->hwnd != m_hwnd && !IsChild(m_hwnd, pMsg->hwnd))
  2223. return FALSE;
  2224. if (pMsg->message == WM_KEYDOWN &&
  2225. pMsg->wParam == VK_ESCAPE &&
  2226. GetFocus() == m_hwndToolbar &&
  2227. m_hwndLastFocus)
  2228. {
  2229. // when focus is inthe toolbar, we're not UIActive (cheaper than subclassing to catch WM_SETFOCUS\WM_KILLFOCUS
  2230. // as toolbar doesn't send NM_SETFOCUS). So we special case ESCAPE to drop the focus from the toolbar
  2231. ::SetFocus(m_hwndLastFocus);
  2232. return TRUE;
  2233. }
  2234. // check to see if we are UIActive
  2235. if (!m_fUIActive)
  2236. return FALSE;
  2237. // check and see if it's one of our accelerators
  2238. if (::TranslateAcceleratorWrapW(m_hwnd, GetAcceleratorTable(), pMsg))
  2239. return TRUE;
  2240. // handle tab-key here
  2241. if (pMsg->message == WM_KEYDOWN &&
  2242. pMsg->wParam == VK_TAB)
  2243. {
  2244. fShift = ( GetKeyState(VK_SHIFT ) & 0x8000) != 0;
  2245. if (!fShift &&
  2246. (GetKeyState(VK_CONTROL) & 0x8000))
  2247. {
  2248. // ctrl-TAB means focus to the toolbar
  2249. ::SetFocus(m_hwndToolbar);
  2250. return TRUE;
  2251. }
  2252. hwnd = _GetNextDlgTabItem(m_hwnd, pMsg->hwnd, fShift);
  2253. if (hwnd != NULL)
  2254. ::SetFocus(hwnd);
  2255. else
  2256. if (m_pEnvelopeSite)
  2257. m_pEnvelopeSite->SetFocus(TRUE);
  2258. return TRUE;
  2259. }
  2260. // pass the accelerators to the envelopesite
  2261. if (m_pEnvelopeSite &&
  2262. (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST) &&
  2263. m_pEnvelopeSite->TranslateAccelerators(pMsg)==S_OK)
  2264. return TRUE;
  2265. // see if it's a message for our child controls
  2266. if (pMsg->message != WM_SYSCHAR &&
  2267. IsDialogMessageWrapW(m_hwnd, pMsg))
  2268. return TRUE;
  2269. return FALSE;
  2270. }
  2271. // IMsoComponent::OnEnterState
  2272. void CNoteHdr::OnEnterState(ULONG uStateID, BOOL fEnter)
  2273. {
  2274. return;
  2275. }
  2276. // IMsoComponent::OnAppActivate
  2277. void CNoteHdr::OnAppActivate(BOOL fActive, DWORD dwOtherThreadID)
  2278. {
  2279. return;
  2280. }
  2281. // IMsoComponent::OnLoseActivation
  2282. void CNoteHdr::OnLoseActivation()
  2283. {
  2284. return;
  2285. }
  2286. // IMsoComponent::OnActivationChange
  2287. void CNoteHdr::OnActivationChange(IMsoComponent *pic, BOOL fSameComponent, const MSOCRINFO *pcrinfo, BOOL fHostIsActivating, const MSOCHOSTINFO *pchostinfo, DWORD dwReserved)
  2288. {
  2289. return;
  2290. }
  2291. // IMsoComponent::FDoIdle
  2292. BOOL CNoteHdr::FDoIdle(DWORD grfidlef)
  2293. {
  2294. return FALSE;
  2295. }
  2296. // IMsoComponent::FContinueMessageLoop
  2297. BOOL CNoteHdr::FContinueMessageLoop(ULONG uReason, void *pvLoopData, MSG *pMsgPeeked)
  2298. {
  2299. return FALSE;
  2300. }
  2301. // IMsoComponent::FQueryTerminate
  2302. BOOL CNoteHdr::FQueryTerminate(BOOL fPromptUser)
  2303. {
  2304. return TRUE;
  2305. }
  2306. // IMsoComponent::Terminate
  2307. void CNoteHdr::Terminate()
  2308. {
  2309. _RegisterWithComponentMgr(FALSE);
  2310. if (m_hwnd)
  2311. DestroyWindow(m_hwnd);
  2312. }
  2313. // IMsoComponent::HwndGetWindow
  2314. HWND CNoteHdr::HwndGetWindow(DWORD dwWhich, DWORD dwReserved)
  2315. {
  2316. HWND hwnd = NULL;
  2317. switch (dwWhich)
  2318. {
  2319. case msocWindowComponent:
  2320. case msocWindowDlgOwner:
  2321. hwnd = m_hwnd;
  2322. break;
  2323. case msocWindowFrameOwner:
  2324. hwnd = GetParent(m_hwnd);
  2325. break;
  2326. case msocWindowFrameToplevel:
  2327. {
  2328. if (m_pEnvelopeSite)
  2329. m_pEnvelopeSite->GetFrameWnd(&hwnd);
  2330. return hwnd;
  2331. }
  2332. }
  2333. return hwnd;
  2334. }
  2335. // HrUpdateCharSetFonts
  2336. //
  2337. // Purpose: Creates the controls on the header dialog
  2338. // calculates and sets up all initial coordinates
  2339. //
  2340. //
  2341. // Comments:
  2342. //
  2343. HRESULT CNoteHdr::HrUpdateCharSetFonts(HCHARSET hCharset, BOOL fUpdateFields)
  2344. {
  2345. PHCI phci;
  2346. HWND hwnd;
  2347. INT iHC;
  2348. TCHAR sz[cchHeaderMax+1];
  2349. BOOL fDirty=m_fDirty;
  2350. INETCSETINFO rCharset;
  2351. HRESULT hr = E_FAIL;
  2352. // Check Params
  2353. Assert(hCharset);
  2354. // No font cache, bummer
  2355. if (!g_lpIFontCache)
  2356. return E_FAIL;
  2357. // Get Charset Information
  2358. if (SUCCEEDED(MimeOleGetCharsetInfo(hCharset, &rCharset)))
  2359. {
  2360. HFONT hHeaderFont, hSystemFont;
  2361. if ((m_hCharset != hCharset) || (0 == *m_szLastLang))
  2362. {
  2363. *m_szLastLang = 0;
  2364. GetMimeCharsetForTitle(hCharset, NULL, m_szLastLang, ARRAYSIZE(m_szLastLang) - 1, IsReadOnly());
  2365. // Save Charset
  2366. m_hCharset = hCharset;
  2367. }
  2368. // If don't update fields, then just return
  2369. if (!fUpdateFields)
  2370. return S_OK;
  2371. // Get charset charformat
  2372. hHeaderFont = HGetCharSetFont(FNT_SYS_ICON, hCharset);
  2373. hSystemFont = GetFont(FALSE);
  2374. // Loop through header fields
  2375. for (iHC=0; iHC<(int)m_cHCI; iHC++)
  2376. {
  2377. // Get info
  2378. phci = &m_rgHCI[iHC];
  2379. hwnd = GetDlgItem(m_hwnd, phci->idEdit);
  2380. //Assert(hwndRE);
  2381. if (!hwnd)
  2382. continue;
  2383. switch (phci->dwFlags & (HCF_COMBO|HCF_ATTACH))
  2384. {
  2385. case HCF_COMBO:
  2386. case HCF_ATTACH:
  2387. SendMessage(hwnd, WM_SETFONT, (WPARAM)hSystemFont, MAKELPARAM(TRUE, 0));
  2388. break;
  2389. // richedit
  2390. // REVIEW: Why are we only doing a request resize when we have the USECHARSET flag set???
  2391. case 0:
  2392. if (phci->dwFlags & HCF_USECHARSET)
  2393. {
  2394. SetFontOnRichEdit(hwnd, hHeaderFont);
  2395. SendMessage(hwnd, EM_REQUESTRESIZE, 0, 0);
  2396. }
  2397. else
  2398. {
  2399. SetFontOnRichEdit(hwnd, hSystemFont);
  2400. }
  2401. break;
  2402. default:
  2403. AssertSz(FALSE, "How did we get something that is combo and attach???");
  2404. break;
  2405. }
  2406. }
  2407. // Don't let this make the note dirty
  2408. if (fDirty)
  2409. SetDirtyFlag();
  2410. else
  2411. m_fDirty=FALSE;
  2412. hr = S_OK;
  2413. }
  2414. return hr;
  2415. }
  2416. //
  2417. // WMCreate
  2418. //
  2419. // Purpose: Creates the controls on the header dialog
  2420. // calculates and sets up all initial coordinates
  2421. //
  2422. //
  2423. // Comments:
  2424. //
  2425. BOOL CNoteHdr::WMCreate()
  2426. {
  2427. HWND hwnd;
  2428. LONG lStyleFlags,
  2429. lExStyleFlags,
  2430. lMask;
  2431. int cy,
  2432. cx,
  2433. cxButtons = ControlXBufferSize();
  2434. HFONT hFont;
  2435. TOOLINFO ti;
  2436. PHCI phci;
  2437. RECT rc;
  2438. CAddrWellCB *pawcb;
  2439. CHARFORMAT cfHeaderCset;
  2440. HRESULT hr;
  2441. LPCWSTR pwszTitle = NULL;
  2442. BOOL fSubjectField;
  2443. Assert(g_cyFont); // should have been setup already
  2444. if (m_pEnvelopeSite)
  2445. {
  2446. // if we are the office-envelope, create a toolbar
  2447. if (_CreateEnvToolbar())
  2448. return FALSE;
  2449. }
  2450. cy = ControlYBufferSize() + m_dxTBOffset;
  2451. cx = 0;
  2452. if (S_OK != HrInitFieldList())
  2453. return FALSE;
  2454. //BROKEN: using system charformat here as not CSET info with MIMEOLE
  2455. // Get charset for cset
  2456. {
  2457. hFont = GetFont(FALSE);
  2458. if (hFont != 0)
  2459. {
  2460. hr = FontToCharformat(hFont, &g_cfHeader);
  2461. }
  2462. hFont = HGetCharSetFont(FNT_SYS_ICON, m_hCharset);
  2463. if (hFont != 0)
  2464. {
  2465. hr = FontToCharformat(hFont, &cfHeaderCset);
  2466. if (FAILED(hr))
  2467. CopyMemory (&cfHeaderCset, &g_cfHeader, sizeof (CHARFORMAT));
  2468. }
  2469. else
  2470. CopyMemory (&cfHeaderCset, &g_cfHeader, sizeof (CHARFORMAT));
  2471. hFont = GetFont(FALSE);
  2472. }
  2473. // ~~~~ Do we need to be calling this with WrapW???
  2474. // Create a tooltip, if it doesn't already exist:
  2475. m_hwndTT=CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, 0,
  2476. CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT,
  2477. m_hwnd, (HMENU) NULL, g_hInst, NULL);
  2478. if (!m_hwndTT)
  2479. return FALSE;
  2480. ti.cbSize=sizeof(TOOLINFO);
  2481. ti.hwnd=m_hwnd;
  2482. ti.hinst=g_hLocRes;
  2483. ti.uFlags=TTF_IDISHWND|TTF_SUBCLASS;
  2484. m_lpAttMan = new CAttMan();
  2485. if (!m_lpAttMan)
  2486. return FALSE;
  2487. if (m_lpAttMan->HrInit(m_hwnd, m_ntNote==OENA_READ, m_ntNote==OENA_FORWARD, !DwGetOption(OPT_SECURITY_ATTACHMENT)))
  2488. return FALSE;
  2489. for (int iHC=0; iHC<(int)m_cHCI; iHC++)
  2490. {
  2491. phci=&m_rgHCI[iHC];
  2492. BOOL fIsCombo = (HCF_COMBO & phci->dwFlags);
  2493. BOOL fNeedsBorder = (phci->dwFlags & HCF_BORDER);
  2494. int cyCtrlSize;
  2495. // if header is optional, check setting
  2496. if ((phci->dwFlags & HCF_OPTIONAL) &&
  2497. !DwGetOption(phci->dwOpt))
  2498. continue;
  2499. if (phci->dwFlags & HCF_ATTACH)
  2500. {
  2501. // if we're not readonly, register ourselves as a drop target...
  2502. if (!(phci->dwFlags & HCF_READONLY))
  2503. {
  2504. hr = _RegisterAsDropTarget(TRUE);
  2505. if (FAILED(hr))
  2506. return FALSE;
  2507. }
  2508. continue;
  2509. }
  2510. phci->height = GetControlSize(fNeedsBorder, 1);
  2511. // Richedit
  2512. if (!fIsCombo)
  2513. {
  2514. pwszTitle = GetREClassStringW();
  2515. cyCtrlSize = phci->height;
  2516. lStyleFlags = WS_CHILD|WS_TABSTOP|WS_VISIBLE|ES_SAVESEL;
  2517. lMask=ENM_KEYEVENTS|ENM_CHANGE|ENM_SELCHANGE|ENM_REQUESTRESIZE;
  2518. if (phci->dwFlags & HCF_MULTILINE)
  2519. {
  2520. //lStyleFlags |= ES_MULTILINE|ES_WANTRETURN|WS_VSCROLL|ES_AUTOVSCROLL;
  2521. lStyleFlags |= ES_MULTILINE|WS_VSCROLL|ES_AUTOVSCROLL;
  2522. }
  2523. else
  2524. lStyleFlags |= ES_AUTOHSCROLL;
  2525. }
  2526. // Combo Box
  2527. else
  2528. {
  2529. pwszTitle = L"ComboBox";
  2530. cyCtrlSize = GetControlSize(fNeedsBorder, NUM_COMBO_LINES);
  2531. lStyleFlags = WS_CHILD|WS_TABSTOP|WS_VISIBLE|WS_VSCROLL|
  2532. CBS_DROPDOWNLIST|CBS_HASSTRINGS|CBS_SORT;
  2533. }
  2534. if (phci->dwFlags & HCF_READONLY)
  2535. lStyleFlags|=ES_READONLY;
  2536. GetClientRect(m_hwnd, &rc);
  2537. lExStyleFlags = fNeedsBorder ? WS_EX_NOPARENTNOTIFY|WS_EX_CLIENTEDGE : WS_EX_NOPARENTNOTIFY;
  2538. // @hack [dhaws] {55073} Do RTL mirroring only in special richedit versions.
  2539. fSubjectField = (idsSubjectField == phci->idsLabel);
  2540. RichEditRTLMirroring(m_hwnd, fSubjectField, &lExStyleFlags, TRUE);
  2541. // Regardless of mirroring, BiDi-Dates should be displayed RTL
  2542. if(((phci->idsLabel == idsDateField) && IsBiDiCalendar()))
  2543. lExStyleFlags |= WS_EX_RTLREADING;
  2544. hwnd = CreateWindowExWrapW(lExStyleFlags,
  2545. pwszTitle,
  2546. NULL,
  2547. lStyleFlags,
  2548. cx, cy, rc.right, cyCtrlSize,
  2549. m_hwnd,
  2550. (HMENU)IntToPtr(phci->idEdit),
  2551. g_hInst, 0 );
  2552. if (!hwnd)
  2553. return FALSE;
  2554. RichEditRTLMirroring(m_hwnd, fSubjectField, &lExStyleFlags, FALSE);
  2555. if (0 == (phci->dwFlags & HCF_BORDER))
  2556. {
  2557. SendMessage(hwnd, EM_SETBKGNDCOLOR, WPARAM(FALSE), LPARAM(GetSysColor(COLOR_BTNFACE)));
  2558. }
  2559. ti.uId = (UINT_PTR)hwnd;
  2560. ti.lpszText = (LPTSTR)IntToPtr(phci->idsTT);
  2561. SendMessage(m_hwndTT, TTM_ADDTOOL, 0, (LPARAM) &ti);
  2562. // hang a pointer into the phci off each control
  2563. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM)phci);
  2564. if (!fIsCombo)
  2565. {
  2566. LPRICHEDITOLE preole = NULL;
  2567. ITextDocument *pDoc = NULL;
  2568. SideAssert(SendMessage(hwnd, EM_GETOLEINTERFACE, NULL, (LPARAM)&preole));
  2569. phci->preole = preole;
  2570. Assert(preole);
  2571. if (SUCCEEDED(preole->QueryInterface(IID_ITextDocument, (LPVOID*)&pDoc)))
  2572. phci->pDoc = pDoc;
  2573. // This only happens with richedit 1.0
  2574. else
  2575. phci->pDoc = NULL;
  2576. // Set edit charformat
  2577. if (phci->dwFlags & HCF_USECHARSET)
  2578. SendMessage(hwnd, EM_SETCHARFORMAT, 0, (LPARAM)&cfHeaderCset);
  2579. else
  2580. SendMessage(hwnd, EM_SETCHARFORMAT, 0, (LPARAM)&g_cfHeader);
  2581. if ((pawcb = new CAddrWellCB(!(phci->dwFlags&HCF_READONLY), phci->dwFlags&HCF_ADDRWELL)))
  2582. {
  2583. if (pawcb->FInit(hwnd))
  2584. SendMessage(hwnd, EM_SETOLECALLBACK, 0, (LPARAM)(IRichEditOleCallback *)pawcb);
  2585. ReleaseObj(pawcb);
  2586. }
  2587. SendMessage(hwnd, EM_SETEVENTMASK, 0, lMask);
  2588. g_lpfnREWndProc=(WNDPROC)SetWindowLongPtrAthW(hwnd, GWLP_WNDPROC, (LPARAM)EditSubClassProc);
  2589. }
  2590. else
  2591. {
  2592. CHAR szAccount[CCHMAX_ACCOUNT_NAME];
  2593. CHAR szAcctID[CCHMAX_ACCOUNT_NAME];
  2594. CHAR szDefault[CCHMAX_ACCOUNT_NAME];
  2595. CHAR szEmailAddress[CCHMAX_EMAIL_ADDRESS];
  2596. CHAR szEntry[ACCT_ENTRY_SIZE];
  2597. CHAR szDefaultEntry[ACCT_ENTRY_SIZE];
  2598. IImnEnumAccounts *pEnum=NULL;
  2599. IImnAccount *pAccount=NULL;
  2600. int i = 0;
  2601. DWORD cAccounts = 0;
  2602. LPSTR *ppszAcctIDs;
  2603. *szDefault = 0;
  2604. *szDefaultEntry = 0;
  2605. // If default account isn't setup, this might fail, but doesn't matter.
  2606. g_pAcctMan->GetDefaultAccountName(m_fMail?ACCT_MAIL:ACCT_NEWS, szDefault, ARRAYSIZE(szDefault));
  2607. hr = g_pAcctMan->Enumerate(m_fMail?SRV_MAIL:SRV_NNTP, &pEnum);
  2608. if (SUCCEEDED(hr))
  2609. hr = pEnum->GetCount(&cAccounts);
  2610. if (SUCCEEDED(hr) && cAccounts)
  2611. {
  2612. if (!MemAlloc((void**)&m_ppAccountIDs, cAccounts*sizeof(LPSTR)))
  2613. hr = E_OUTOFMEMORY;
  2614. }
  2615. if (SUCCEEDED(hr))
  2616. {
  2617. *szDefaultEntry = 0;
  2618. ppszAcctIDs = m_ppAccountIDs;
  2619. while(SUCCEEDED(pEnum->GetNext(&pAccount)))
  2620. {
  2621. *szAccount = 0;
  2622. *szEmailAddress = 0;
  2623. pAccount->GetPropSz(AP_ACCOUNT_NAME, szAccount, ARRAYSIZE(szAccount));
  2624. if (m_fMail)
  2625. {
  2626. pAccount->GetPropSz(AP_SMTP_EMAIL_ADDRESS, szEmailAddress, ARRAYSIZE(szEmailAddress));
  2627. wnsprintf(szEntry, ARRAYSIZE(szEntry), "%s (%s)", szEmailAddress, szAccount);
  2628. }
  2629. else
  2630. {
  2631. StrCpyN(szEntry, szAccount, ARRAYSIZE(szEntry));
  2632. }
  2633. i = ComboBox_InsertString(hwnd, -1, szEntry);
  2634. if (i != CB_ERR)
  2635. {
  2636. if (0 == lstrcmpi(szDefault, szAccount))
  2637. {
  2638. StrCpyN(szDefaultEntry, szEntry, ARRAYSIZE(szDefaultEntry));
  2639. }
  2640. if (SUCCEEDED(pAccount->GetPropSz(AP_ACCOUNT_ID, szAcctID, ARRAYSIZE(szAcctID))))
  2641. {
  2642. DWORD cchSize = (lstrlen(szAcctID) + 1);
  2643. if (MemAlloc((void**)ppszAcctIDs, cchSize * sizeof(CHAR)))
  2644. {
  2645. StrCpyN(*ppszAcctIDs, szAcctID, cchSize);
  2646. }
  2647. else
  2648. {
  2649. *ppszAcctIDs = NULL;
  2650. }
  2651. }
  2652. else
  2653. *ppszAcctIDs = NULL;
  2654. SendMessage(hwnd, CB_SETITEMDATA, WPARAM(i), LPARAM(*ppszAcctIDs));
  2655. ppszAcctIDs++;
  2656. m_cAccountIDs++;
  2657. }
  2658. // Release Account
  2659. SafeRelease(pAccount);
  2660. }
  2661. AssertSz(m_cAccountIDs == cAccounts, "Why isn't num Ds = num accts?");
  2662. SafeRelease(pEnum);
  2663. AssertSz(!pAccount, "The last account didn't get freed.");
  2664. if (0 != *szDefaultEntry)
  2665. {
  2666. ComboBox_SelectString(hwnd, -1, szDefaultEntry);
  2667. m_iCurrComboIndex = ComboBox_GetCurSel(hwnd);
  2668. }
  2669. else
  2670. {
  2671. ComboBox_SetCurSel(hwnd, 0);
  2672. m_iCurrComboIndex = 0;
  2673. }
  2674. if (SUCCEEDED(HrGetAccountInHeader(&pAccount)))
  2675. {
  2676. ReplaceInterface(m_pAccount, pAccount);
  2677. ReleaseObj(pAccount);
  2678. }
  2679. SendMessage(hwnd, WM_SETFONT, WPARAM(hFont), MAKELONG(TRUE,0));
  2680. }
  2681. }
  2682. }
  2683. _RegisterWithFontCache(TRUE);
  2684. HrOnOffVCard();
  2685. ReLayout();
  2686. return PostWMCreate(); // allow subclass to setup the controls once created...
  2687. }
  2688. //
  2689. // HeaderWndProc
  2690. //
  2691. // Purpose: Main WNDPROC for header dialog
  2692. //
  2693. // Comments:
  2694. //
  2695. LRESULT CALLBACK CNoteHdr::ExtCNoteHdrWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  2696. {
  2697. CNoteHdr *pnh = NULL;
  2698. if (msg==WM_NCCREATE)
  2699. {
  2700. SetWndThisPtrOnCreate(hwnd, lParam);
  2701. pnh=(CNoteHdr *)GetWndThisPtr(hwnd);
  2702. if (!pnh)
  2703. return -1;
  2704. pnh->m_hwnd=hwnd;
  2705. return pnh->WMCreate();
  2706. }
  2707. pnh = (CNoteHdr *)GetWndThisPtr(hwnd);
  2708. if (pnh)
  2709. return pnh->CNoteHdrWndProc(hwnd, msg, wParam, lParam);
  2710. else
  2711. return DefWindowProcWrapW(hwnd, msg, wParam, lParam);
  2712. }
  2713. void CNoteHdr::RelayToolTip(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  2714. {
  2715. MSG Msg;
  2716. if (m_hwndTT != NULL)
  2717. {
  2718. Msg.lParam=lParam;
  2719. Msg.wParam=wParam;
  2720. Msg.message=msg;
  2721. Msg.hwnd=hwnd;
  2722. SendMessage(m_hwndTT, TTM_RELAYEVENT, 0, (LPARAM) (LPMSG) &Msg);
  2723. }
  2724. }
  2725. LRESULT CALLBACK CNoteHdr::CNoteHdrWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  2726. {
  2727. POINT pt;
  2728. int newWidth;
  2729. RECT rc;
  2730. HFONT hFont=NULL;
  2731. switch (msg)
  2732. {
  2733. case WM_HEADER_GETFONT:
  2734. // update cached fornt for addrobj's
  2735. if (g_lpIFontCache)
  2736. g_lpIFontCache->GetFont(wParam ? FNT_SYS_ICON_BOLD:FNT_SYS_ICON, m_hCharset, &hFont);
  2737. return (LRESULT)hFont;
  2738. case HDM_TESTQUERYPRI:
  2739. // hack for test team to query header's priority...
  2740. return m_pri;
  2741. case WM_DESTROY:
  2742. OnDestroy();
  2743. break;
  2744. case WM_NCDESTROY:
  2745. OnNCDestroy();
  2746. break;
  2747. case WM_CTLCOLORBTN:
  2748. // make sure the buttons backgrounds are window-color so the ownerdraw
  2749. // imagelists paint transparent OK
  2750. return (LPARAM)GetSysColorBrush(COLOR_WINDOWFRAME);
  2751. case WM_CONTEXTMENU:
  2752. if (m_lpAttMan && m_lpAttMan->WMContextMenu(hwnd, msg, wParam, lParam))
  2753. return 0;
  2754. break;
  2755. case WM_MOUSEMOVE:
  2756. {
  2757. DWORD newButton = GetButtonUnderMouse(LOWORD(lParam), HIWORD(lParam));
  2758. if ((HDRCB_NO_BUTTON == m_dwClickedBtn) ||
  2759. (HDRCB_NO_BUTTON == newButton) ||
  2760. (m_dwClickedBtn == newButton))
  2761. if (newButton != m_dwCurrentBtn)
  2762. {
  2763. DOUTL(PAINTING_DEBUG_LEVEL, "Old button: %d, New Button: %d", m_dwCurrentBtn, newButton);
  2764. if (HDRCB_NO_BUTTON == newButton)
  2765. {
  2766. DOUTL(PAINTING_DEBUG_LEVEL, "Leaving right button framing.");
  2767. // Need to clear old button.
  2768. InvalidateRect(m_hwnd, &m_rcCurrentBtn, FALSE);
  2769. HeaderRelease(FALSE);
  2770. }
  2771. else
  2772. {
  2773. DOUTL(PAINTING_DEBUG_LEVEL, "Framing button.");
  2774. if (HDRCB_NO_BUTTON == m_dwCurrentBtn)
  2775. HeaderCapture();
  2776. else
  2777. InvalidateRect(m_hwnd, &m_rcCurrentBtn, FALSE);
  2778. GetButtonRect(newButton, &m_rcCurrentBtn);
  2779. InvalidateRect(m_hwnd, &m_rcCurrentBtn, FALSE);
  2780. }
  2781. m_dwCurrentBtn = newButton;
  2782. }
  2783. RelayToolTip(hwnd, msg, wParam, lParam);
  2784. break;
  2785. }
  2786. case WM_LBUTTONDOWN:
  2787. case WM_RBUTTONDOWN:
  2788. {
  2789. RECT rc;
  2790. int x = LOWORD(lParam),
  2791. y = HIWORD(lParam);
  2792. HeaderCapture();
  2793. m_dwClickedBtn = GetButtonUnderMouse(x, y);
  2794. if (m_dwClickedBtn != HDRCB_NO_BUTTON)
  2795. {
  2796. GetButtonRect(m_dwClickedBtn, &rc);
  2797. InvalidateRect(m_hwnd, &rc, FALSE);
  2798. }
  2799. RelayToolTip(hwnd, msg, wParam, lParam);
  2800. break;
  2801. }
  2802. case WM_LBUTTONUP:
  2803. case WM_RBUTTONUP:
  2804. {
  2805. int x = LOWORD(lParam),
  2806. y = HIWORD(lParam);
  2807. DWORD iBtn = GetButtonUnderMouse(x, y);
  2808. RelayToolTip(hwnd, msg, wParam, lParam);
  2809. if (m_dwClickedBtn == iBtn)
  2810. HandleButtonClicks(x, y, iBtn);
  2811. m_dwClickedBtn = HDRCB_NO_BUTTON;
  2812. HeaderRelease(FALSE);
  2813. break;
  2814. }
  2815. case WM_PAINT:
  2816. WMPaint();
  2817. break;
  2818. case WM_SYSCOLORCHANGE:
  2819. if (m_himl)
  2820. {
  2821. // remap the toolbar bitmap into the new color scheme
  2822. ImageList_Destroy(m_himl);
  2823. SendMessage(m_hwndToolbar, TB_SETIMAGELIST, 0, NULL);
  2824. m_himl = LoadMappedToolbarBitmap(g_hLocRes, (fIsWhistler() ? ((GetCurColorRes() > 24) ? idb32SmBrowserHot : idbSmBrowserHot): idbNWSmBrowserHot), cxTBButton);
  2825. SendMessage(m_hwndToolbar, TB_SETIMAGELIST, 0, (LPARAM)m_himl);
  2826. }
  2827. UpdateRebarBandColors(m_hwndRebar);
  2828. // fall thro'
  2829. case WM_WININICHANGE:
  2830. case WM_DISPLAYCHANGE:
  2831. case WM_QUERYNEWPALETTE:
  2832. case WM_PALETTECHANGED:
  2833. SendMessage(m_hwndRebar, msg, wParam, lParam);
  2834. break;
  2835. case WM_ERASEBKGND:
  2836. return 1;
  2837. case WM_SIZE:
  2838. {
  2839. STACK("WM_SIZE (width, heigth)", LOWORD(lParam), HIWORD(lParam));
  2840. if (m_fResizing)
  2841. break;
  2842. m_fResizing = TRUE;
  2843. newWidth = LOWORD(lParam);
  2844. SetPosOfControls(newWidth, FALSE);
  2845. if (m_hwndRebar)
  2846. {
  2847. GetClientRect(m_hwndRebar, &rc);
  2848. // resize the width of the toolbar
  2849. if(rc.right != newWidth)
  2850. SetWindowPos(m_hwndRebar, NULL, 0, 0, newWidth, 30, SETWINPOS_DEF_FLAGS|SWP_NOMOVE);
  2851. }
  2852. AssertSz(m_fResizing, "Someone re-entered me!!! Why is m_fResizing already false??");
  2853. m_fResizing = FALSE;
  2854. break;
  2855. }
  2856. case WM_CLOSE:
  2857. //prevent alt-f4
  2858. return 0;
  2859. case WM_COMMAND:
  2860. WMCommand(GET_WM_COMMAND_HWND(wParam, lParam),
  2861. GET_WM_COMMAND_ID(wParam, lParam),
  2862. GET_WM_COMMAND_CMD(wParam, lParam));
  2863. break;
  2864. case WM_NOTIFY:
  2865. return WMNotify(wParam, lParam);
  2866. }
  2867. return DefWindowProcWrapW(hwnd, msg, wParam, lParam);
  2868. }
  2869. void CNoteHdr::HeaderCapture()
  2870. {
  2871. if (0 == m_cCapture)
  2872. m_hwndOldCapture = SetCapture(m_hwnd);
  2873. m_cCapture++;
  2874. }
  2875. void CNoteHdr::HeaderRelease(BOOL fForce)
  2876. {
  2877. if (0 == m_cCapture)
  2878. return;
  2879. if (fForce)
  2880. m_cCapture = 0;
  2881. else
  2882. m_cCapture--;
  2883. if (0 == m_cCapture)
  2884. {
  2885. ReleaseCapture();
  2886. if (NULL != m_hwndOldCapture)
  2887. {
  2888. DOUTL(PAINTING_DEBUG_LEVEL, "Restoring old mouse events capture.");
  2889. SetCapture(m_hwndOldCapture);
  2890. m_hwndOldCapture = NULL;
  2891. }
  2892. }
  2893. }
  2894. BOOL CNoteHdr::WMNotify(WPARAM wParam, LPARAM lParam)
  2895. {
  2896. HWND hwnd=m_hwnd;
  2897. int idCtl=(int)wParam;
  2898. LPNMHDR pnmh=(LPNMHDR)lParam;
  2899. TBNOTIFY *ptbn;
  2900. LPTOOLTIPTEXT lpttt;
  2901. int i;
  2902. if (m_lpAttMan->WMNotify((int) wParam, pnmh))
  2903. return TRUE;
  2904. switch (pnmh->code)
  2905. {
  2906. case RBN_CHEVRONPUSHED:
  2907. {
  2908. ITrackShellMenu* ptsm;
  2909. CoCreateInstance(CLSID_TrackShellMenu, NULL, CLSCTX_INPROC_SERVER, IID_ITrackShellMenu,
  2910. (LPVOID*)&ptsm);
  2911. if (!ptsm)
  2912. break;
  2913. ptsm->Initialize(0, 0, 0, SMINIT_TOPLEVEL|SMINIT_VERTICAL);
  2914. LPNMREBARCHEVRON pnmch = (LPNMREBARCHEVRON) pnmh;
  2915. ptsm->SetObscured(m_hwndToolbar, NULL, SMSET_TOP);
  2916. MapWindowPoints(m_hwndRebar, HWND_DESKTOP, (LPPOINT)&pnmch->rc, 2);
  2917. POINTL pt = {pnmch->rc.left, pnmch->rc.right};
  2918. ptsm->Popup(m_hwndRebar, &pt, (RECTL*)&pnmch->rc, MPPF_BOTTOM);
  2919. ptsm->Release();
  2920. break;
  2921. }
  2922. case EN_MSGFILTER:
  2923. {
  2924. // if we get a control-tab, then richedit snags this and inserts a
  2925. // tab char, we hook the wm_keydown and never pass to richedit
  2926. if (((MSGFILTER *)pnmh)->msg == WM_KEYDOWN &&
  2927. ((MSGFILTER *)pnmh)->wParam == VK_TAB &&
  2928. (GetKeyState(VK_CONTROL) & 0x8000))
  2929. return TRUE;
  2930. break;
  2931. }
  2932. case ATTN_RESIZEPARENT:
  2933. {
  2934. RECT rc;
  2935. GetClientRect(m_hwnd, &rc);
  2936. SetPosOfControls(rc.right, TRUE);
  2937. return TRUE;
  2938. }
  2939. case EN_REQUESTRESIZE:
  2940. {
  2941. REQRESIZE *presize=(REQRESIZE *)lParam;
  2942. HWND hwndEdit = presize->nmhdr.hwndFrom;
  2943. STACK("EN_REQUESTRESIZE (hwnd, width, heigth)", (DWORD_PTR)(presize->nmhdr.hwndFrom), presize->rc.right - presize->rc.left, presize->rc.bottom - presize->rc.top);
  2944. if (S_FALSE != HrUpdateCachedHeight(hwndEdit, &presize->rc) && !m_fResizing)
  2945. {
  2946. RECT rc;
  2947. DWORD dwMask = (DWORD) SendMessage(hwndEdit, EM_GETEVENTMASK, 0, 0);
  2948. SendMessage(hwndEdit, EM_SETEVENTMASK, 0, dwMask & (~ENM_REQUESTRESIZE));
  2949. STACK("EN_REQUESTRESIZE after GrowControls");
  2950. GetClientRect(m_hwnd, &rc);
  2951. SetPosOfControls(rc.right, FALSE);
  2952. SendMessage(hwndEdit, EM_SETEVENTMASK, 0, dwMask);
  2953. }
  2954. return TRUE;
  2955. }
  2956. case NM_SETFOCUS:
  2957. case NM_KILLFOCUS:
  2958. // UIActivate/Deactivate for attachment manager
  2959. if (m_lpAttMan && pnmh->hwndFrom == m_lpAttMan->Hwnd())
  2960. _UIActivate(pnmh->code == NM_SETFOCUS, pnmh->hwndFrom);
  2961. break;
  2962. case EN_SELCHANGE:
  2963. {
  2964. PHCI phci=(PHCI)GetWndThisPtr(pnmh->hwndFrom);
  2965. if (phci)
  2966. phci->dwACFlags &= ~AC_SELECTION;
  2967. // update office toolbars if running as envelope
  2968. if(m_pEnvelopeSite)
  2969. m_pEnvelopeSite->DirtyToolbars();
  2970. // on a sel change, forward a note updatetoolbar to update the
  2971. // cut|copy|paste buttons
  2972. if (m_pHeaderSite)
  2973. m_pHeaderSite->Update();
  2974. return TRUE;
  2975. }
  2976. case TTN_NEEDTEXT:
  2977. // we use TTN_NEEDTEXT to show toolbar tips as we have different tips than toolbar-labels
  2978. // because on the office-envelope toolbar only 2 buttons (send and bcc) have text next to the
  2979. // buttons
  2980. lpttt = (LPTOOLTIPTEXT) pnmh;
  2981. lpttt->hinst = NULL;
  2982. lpttt->lpszText = 0;
  2983. for (i=0; i< ARRAYSIZE(c_rgTipLookup); i++)
  2984. {
  2985. if (c_rgTipLookup[i].idm == (int)lpttt->hdr.idFrom)
  2986. {
  2987. lpttt->hinst = g_hLocRes;
  2988. lpttt->lpszText = MAKEINTRESOURCE(c_rgTipLookup[i].ids);
  2989. break;
  2990. }
  2991. }
  2992. break;
  2993. case TBN_DROPDOWN:
  2994. {
  2995. ptbn = (TBNOTIFY *)lParam;
  2996. if (ptbn->iItem == ID_SET_PRIORITY)
  2997. {
  2998. HMENU hMenuPopup;
  2999. UINT i;
  3000. hMenuPopup = LoadPopupMenu(IDR_PRIORITY_POPUP);
  3001. if (hMenuPopup != NULL)
  3002. {
  3003. for (i = 0; i < 3; i++)
  3004. CheckMenuItem(hMenuPopup, i, MF_UNCHECKED | MF_BYPOSITION);
  3005. GetPriority(&i);
  3006. Assert(i != priNone);
  3007. CheckMenuItem(hMenuPopup, 2 - i, MF_CHECKED | MF_BYPOSITION);
  3008. DoToolbarDropdown(hwnd, (LPNMHDR) lParam, hMenuPopup);
  3009. DestroyMenu(hMenuPopup);
  3010. }
  3011. }
  3012. break;
  3013. }
  3014. }
  3015. return FALSE;
  3016. }
  3017. HRESULT CNoteHdr::WMCommand(HWND hwndCmd, int id, WORD wCmd)
  3018. {
  3019. HWND hwnd=m_hwnd;
  3020. int i;
  3021. UINT pri;
  3022. if (m_lpAttMan && m_lpAttMan->WMCommand(hwndCmd, id, wCmd))
  3023. return S_OK;
  3024. for (i=0; i<(int)m_cHCI; i++)
  3025. if (m_rgHCI[i].idEdit==id)
  3026. {
  3027. switch (wCmd)
  3028. {
  3029. case EN_CHANGE:
  3030. {
  3031. if (m_fHandleChange)
  3032. {
  3033. BOOL fEmpty;
  3034. PHCI phci = (PHCI)GetWndThisPtr(hwndCmd);
  3035. char sz[cchHeaderMax+1];
  3036. DWORD dwMask = 0;
  3037. RichEditProtectENChange(hwndCmd, &dwMask, TRUE);
  3038. Assert(phci);
  3039. fEmpty = (0 == GetRichEditTextLen(hwndCmd));
  3040. // if it has no text, see if it has object...
  3041. if (fEmpty && phci->preole)
  3042. fEmpty = (fEmpty && (0 == phci->preole->GetObjectCount()));
  3043. if (phci->dwFlags & HCF_ADDRWELL)
  3044. m_fAddressesChanged = TRUE;
  3045. phci->fEmpty = fEmpty;
  3046. SetDirtyFlag();
  3047. if (m_fAutoComplete && (m_rgHCI[i].dwFlags & HCF_ADDRWELL) && !IsReadOnly())
  3048. {
  3049. if (NULL == m_pTable)
  3050. {
  3051. if (NULL == m_lpWab)
  3052. HrCreateWabObject(&m_lpWab);
  3053. if (m_lpWab)
  3054. m_lpWab->HrGetPABTable(&m_pTable);
  3055. }
  3056. if (m_pTable)
  3057. HrAutoComplete(hwndCmd, &m_rgHCI[i]);
  3058. }
  3059. RichEditProtectENChange(hwndCmd, &dwMask, FALSE);
  3060. }
  3061. }
  3062. return S_OK;
  3063. case CBN_SELCHANGE:
  3064. {
  3065. IImnAccount *pAcct = NULL;
  3066. if (!m_fMail)
  3067. {
  3068. int newIndex = ComboBox_GetCurSel(hwndCmd);
  3069. HWND hwndNews = GetDlgItem(m_hwnd, idADNewsgroups);
  3070. // Don't need to warn if going to same account, or if there are no newgroups listed.
  3071. if ((newIndex != m_iCurrComboIndex) && (0 < GetWindowTextLength(hwndNews)))
  3072. {
  3073. if (IDCANCEL == DoDontShowMeAgainDlg(m_hwnd, c_szDSChangeNewsServer, MAKEINTRESOURCE(idsAthena),
  3074. MAKEINTRESOURCE(idsChangeNewsServer), MB_OKCANCEL))
  3075. {
  3076. ComboBox_SetCurSel(hwndCmd, m_iCurrComboIndex);
  3077. return S_OK;
  3078. }
  3079. else
  3080. HdrSetRichEditText(hwndNews, c_wszEmpty, FALSE);
  3081. }
  3082. m_iCurrComboIndex = newIndex;
  3083. }
  3084. if (SUCCEEDED(HrGetAccountInHeader(&pAcct)))
  3085. ReplaceInterface(m_pAccount, pAcct);
  3086. ReleaseObj(pAcct);
  3087. return S_OK;
  3088. }
  3089. case CBN_SETFOCUS:
  3090. case EN_SETFOCUS:
  3091. _UIActivate(TRUE, hwndCmd);
  3092. return S_OK;
  3093. case CBN_KILLFOCUS:
  3094. case EN_KILLFOCUS:
  3095. _UIActivate(FALSE, hwndCmd);
  3096. return S_OK;
  3097. }
  3098. return S_FALSE;
  3099. }
  3100. switch (id)
  3101. {
  3102. case ID_PRIORITY_LOW:
  3103. SetPriority(priLow);
  3104. return S_OK;
  3105. case ID_PRIORITY_NORMAL:
  3106. SetPriority(priNorm);
  3107. return S_OK;
  3108. case ID_PRIORITY_HIGH:
  3109. SetPriority(priHigh);
  3110. return S_OK;
  3111. case ID_SET_PRIORITY:
  3112. GetPriority(&pri);
  3113. pri++;
  3114. if (pri > priHigh)
  3115. pri = priLow;
  3116. SetPriority(pri);
  3117. return S_OK;
  3118. case ID_SELECT_ALL:
  3119. {
  3120. HWND hwndFocus=GetFocus();
  3121. if (GetParent(hwndFocus)==m_hwnd)
  3122. {
  3123. // only if it's one of our kids..
  3124. Edit_SetSel(hwndFocus, 0, -1);
  3125. return S_OK;
  3126. }
  3127. }
  3128. break;
  3129. case ID_CUT:
  3130. if (FDoCutCopyPaste(WM_CUT))
  3131. return S_OK;
  3132. break;
  3133. case ID_NOTE_COPY:
  3134. case ID_COPY:
  3135. if (FDoCutCopyPaste(WM_COPY))
  3136. return S_OK;
  3137. break;
  3138. case ID_PASTE:
  3139. if (FDoCutCopyPaste(WM_PASTE))
  3140. return S_OK;
  3141. break;
  3142. case ID_DELETE_VCARD:
  3143. m_fVCard = FALSE;
  3144. SetDirtyFlag();
  3145. HrOnOffVCard();
  3146. return S_OK;
  3147. case ID_OPEN_VCARD:
  3148. HrShowVCardProperties(m_hwnd);
  3149. return S_OK;
  3150. case ID_DIGITALLY_SIGN:
  3151. case ID_ENCRYPT:
  3152. HrHandleSecurityIDMs(ID_DIGITALLY_SIGN == id);
  3153. return S_OK;
  3154. case ID_ADDRESS_BOOK:
  3155. HrViewContacts();
  3156. return S_OK;
  3157. //this is for office use only
  3158. case ID_CHECK_NAMES:
  3159. HrCheckNames(FALSE, TRUE);
  3160. return S_OK;
  3161. //this is for office use only
  3162. case ID_ENV_BCC:
  3163. if (m_pEnvelopeSite)
  3164. {
  3165. ShowAdvancedHeaders(!m_fAdvanced);
  3166. SetDwOption(OPT_MAILNOTEADVSEND, !!m_fAdvanced, NULL, NULL);
  3167. // ~~~~ m_pHeaderSite is mutually exclusive to m_pEnvelopeSite
  3168. //if (m_pHeaderSite)
  3169. // m_pHeaderSite->Update();
  3170. return S_OK;
  3171. }
  3172. break;
  3173. case ID_MESSAGE_OPTS:
  3174. ShowEnvOptions();
  3175. return S_OK;
  3176. case ID_SAVE_ATTACHMENTS:
  3177. case ID_NOTE_SAVE_ATTACHMENTS:
  3178. if (m_pHeaderSite)
  3179. m_pHeaderSite->SaveAttachment();
  3180. return S_OK;
  3181. // These next two should only be handled by the header if in the envelope
  3182. case ID_SEND_MESSAGE:
  3183. case ID_SEND_NOW:
  3184. if (m_pEnvelopeSite)
  3185. {
  3186. m_fShowedUnicodeDialog = FALSE;
  3187. m_iUnicodeDialogResult = 0;
  3188. HrSend();
  3189. return S_OK;
  3190. }
  3191. default:
  3192. if (id>=ID_ADDROBJ_OLE_FIRST && id <=ID_ADDROBJ_OLE_LAST)
  3193. {
  3194. DoNoteOleVerb(id-ID_ADDROBJ_OLE_FIRST);
  3195. return S_OK;
  3196. }
  3197. }
  3198. return S_FALSE;
  3199. }
  3200. HRESULT CNoteHdr::HrAutoComplete(HWND hwnd, PHCI pHCI)
  3201. {
  3202. CHARRANGE chrg, chrgCaret;
  3203. LPWSTR pszPartial, pszSemiColon, pszComma;
  3204. INT i, j, len, iTextLen;
  3205. LPWSTR pszBuf=0;
  3206. WCHAR szFound[cchMaxWab+1];
  3207. WCHAR sz;
  3208. HRESULT hr = NOERROR;
  3209. STACK("HrAutoComplete");
  3210. *szFound = 0;
  3211. // If the IME is open, bail out
  3212. if (0 < m_dwIMEStartCount)
  3213. return hr;
  3214. if (NULL==hwnd || NULL==m_pTable || NULL==pHCI)
  3215. return hr;
  3216. if (pHCI->dwACFlags&AC_IGNORE)
  3217. return hr;
  3218. SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&chrgCaret);
  3219. if (chrgCaret.cpMin != chrgCaret.cpMax)
  3220. return hr;
  3221. if (S_OK != HrGetFieldText(&pszBuf, hwnd))
  3222. return hr;
  3223. sz = pszBuf[chrgCaret.cpMin];
  3224. if (!(sz==0x0000 || sz==L' ' || sz==L';'|| sz==L',' || sz==L'\r'))
  3225. goto cleanup;
  3226. DOUTL(64, "HrAutoComplete- Didn't exit early");
  3227. pszBuf[chrgCaret.cpMin] = 0x0000;
  3228. pszSemiColon = StrRChrIW(pszBuf, &pszBuf[lstrlenW(pszBuf)], L';');
  3229. pszComma = StrRChrIW(pszBuf, &pszBuf[lstrlenW(pszBuf)], L',');
  3230. if (pszComma >= pszSemiColon)
  3231. pszPartial = pszComma;
  3232. else
  3233. pszPartial = pszSemiColon;
  3234. if (!pszPartial)
  3235. pszPartial = pszBuf;
  3236. else
  3237. pszPartial++;
  3238. //skip spaces and returns...
  3239. while (*pszPartial==L' ' || *pszPartial==L'\r' || *pszPartial==L'\n')
  3240. pszPartial++;
  3241. if (NULL == *pszPartial)
  3242. goto cleanup;
  3243. //Certain richedits put in 0xfffc for an object, if our text is only that, it's no good
  3244. if (*pszPartial==0xfffc && pszPartial[1]==0x0000)
  3245. goto cleanup;
  3246. len = lstrlenW(pszPartial);
  3247. m_lpWab->SearchPABTable(m_pTable, pszPartial, szFound, ARRAYSIZE(szFound));
  3248. if (*szFound != 0)
  3249. {
  3250. chrg.cpMin = chrgCaret.cpMin;
  3251. chrg.cpMax = chrg.cpMin + lstrlenW(szFound) - len;
  3252. if (chrg.cpMin < chrg.cpMax)
  3253. {
  3254. RichEditExSetSel(hwnd, &chrgCaret);
  3255. HdrSetRichEditText(hwnd, szFound + len, TRUE);
  3256. SendMessage(hwnd, EM_SETMODIFY, (WPARAM)(UINT)TRUE, 0);
  3257. RichEditExSetSel(hwnd, &chrg);
  3258. pHCI->dwACFlags |= AC_SELECTION;
  3259. }
  3260. }
  3261. cleanup:
  3262. MemFree(pszBuf);
  3263. return hr;
  3264. }
  3265. void CNoteHdr::WMPaint()
  3266. {
  3267. PAINTSTRUCT ps;
  3268. HDC hdc,
  3269. hdcMem;
  3270. RECT rc;
  3271. PHCI phci = m_rgHCI;
  3272. HBITMAP hbmMem;
  3273. int idc,
  3274. cxHeader,
  3275. cyHeader,
  3276. cxLabel = ControlXBufferSize(),
  3277. cyStatus,
  3278. cyLeftButtonOffset = BUTTON_BUFFER,
  3279. cxLabelWithBtn = cxLabel + CXOfButtonToLabel();
  3280. char sz[cchHeaderMax+1];
  3281. int cStatusBarLines = 0;
  3282. BOOL fBold;
  3283. HWND hwnd;
  3284. if (!m_hwnd)
  3285. return;
  3286. STACK("WMPaint");
  3287. if (m_fFlagged || (priLow == m_pri) || (priHigh == m_pri) || (MARK_MESSAGE_NORMALTHREAD != m_MarkType))
  3288. cStatusBarLines++;
  3289. if (m_lpAttMan->GetUnsafeAttachCount())
  3290. cStatusBarLines++;
  3291. hdc = BeginPaint(m_hwnd, &ps);
  3292. // **************** Init the background bitmap ****************
  3293. hdcMem = CreateCompatibleDC(hdc);
  3294. idc = SaveDC(hdcMem);
  3295. GetClientRect(m_hwnd, &rc);
  3296. cxHeader = rc.right;
  3297. cyHeader = rc.bottom;
  3298. hbmMem = CreateCompatibleBitmap(hdc, rc.right, rc.bottom);
  3299. SelectObject(hdcMem, (HGDIOBJ)hbmMem);
  3300. // **************** Clear the rect *****************
  3301. FillRect(hdcMem, &rc, GetSysColorBrush(COLOR_BTNFACE));
  3302. // **************** Setup the HDC ******************
  3303. fBold = IsReadOnly();
  3304. SetBkColor(hdcMem, GetSysColor(COLOR_BTNFACE)); // colour of header window
  3305. SetBkMode(hdcMem, TRANSPARENT);
  3306. SetTextColor(hdcMem, GetSysColor(COLOR_BTNTEXT));
  3307. SelectObject(hdcMem, GetFont(fBold));
  3308. // **************** Paint the left labels and buttons **************
  3309. // Center the buttons images
  3310. if (g_cyFont > cyBtn)
  3311. cyLeftButtonOffset += ((g_cyFont - cyBtn) / 2);
  3312. for (int i = 0; (ULONG)i < m_cHCI; i++, phci++)
  3313. {
  3314. if (S_OK == HrFShowHeader(phci))
  3315. {
  3316. if (HCF_HASBUTTON & phci->dwFlags)
  3317. {
  3318. TextOutW(hdcMem, cxLabelWithBtn, phci->cy + BUTTON_BUFFER, phci->sz, phci->strlen);
  3319. ImageList_Draw(g_himlBtns, (HCF_ADDRBOOK & phci->dwFlags)?0:1, hdcMem, cxLabel, phci->cy + cyLeftButtonOffset, ILD_NORMAL);
  3320. }
  3321. else
  3322. TextOutW(hdcMem, cxLabel, (HCF_BORDER & phci->dwFlags)? phci->cy + BUTTON_BUFFER: phci->cy, phci->sz, phci->strlen);
  3323. }
  3324. }
  3325. // **************** Paint the status bar as needed *******************
  3326. if (cStatusBarLines > 0)
  3327. {
  3328. int cxStatusBtn = ControlXBufferSize() + 1, // 1 added for the border
  3329. cyStatusBtn = m_dxTBOffset + cyBorder + 1, // 1 added for the border
  3330. cyStatusBmp = cyStatusBtn,
  3331. cNumButtons = 0;
  3332. LPTSTR pszTitles[3]={0};
  3333. // Center the buttons images
  3334. if (g_cyFont > cyBtn)
  3335. cyStatusBmp += ((g_cyFont - cyBtn) / 2);
  3336. // Fill the dark rect
  3337. rc.top = m_dxTBOffset;
  3338. rc.bottom = m_dxTBOffset + GetStatusHeight(cStatusBarLines);
  3339. FillRect(hdcMem, &rc, GetSysColorBrush(COLOR_BTNSHADOW));
  3340. InflateRect(&rc, -1, -1);
  3341. FillRect(hdcMem, &rc, GetSysColorBrush(COLOR_INFOBK));
  3342. // Set up the DC for the rest of the status bar
  3343. SetBkColor(hdcMem, GetSysColor(COLOR_INFOBK)); // colour of header window
  3344. SetTextColor(hdcMem, GetSysColor(COLOR_INFOTEXT));
  3345. SelectObject(hdcMem, GetFont(FALSE));
  3346. // Draw icons in status bar
  3347. if (priLow == m_pri)
  3348. {
  3349. ImageList_Draw(g_himlStatus, 1, hdcMem, cxStatusBtn, cyStatusBmp+2, ILD_NORMAL);
  3350. cxStatusBtn += cxFlagsDelta;
  3351. pszTitles[cNumButtons++] = g_szStatLowPri;
  3352. }
  3353. else if (priHigh == m_pri)
  3354. {
  3355. ImageList_Draw(g_himlStatus, 0, hdcMem, cxStatusBtn, cyStatusBmp+2, ILD_NORMAL);
  3356. cxStatusBtn += cxFlagsDelta;
  3357. pszTitles[cNumButtons++] = g_szStatHighPri;
  3358. }
  3359. if (MARK_MESSAGE_WATCH == m_MarkType)
  3360. {
  3361. ImageList_Draw(g_himlStatus, 4, hdcMem, cxStatusBtn, cyStatusBmp+2, ILD_NORMAL);
  3362. cxStatusBtn += cxFlagsDelta;
  3363. pszTitles[cNumButtons++] = g_szStatWatched;
  3364. }
  3365. else if (MARK_MESSAGE_IGNORE == m_MarkType)
  3366. {
  3367. ImageList_Draw(g_himlStatus, 5, hdcMem, cxStatusBtn, cyStatusBmp+2, ILD_NORMAL);
  3368. cxStatusBtn += cxFlagsDelta;
  3369. pszTitles[cNumButtons++] = g_szStatIgnored;
  3370. }
  3371. if (m_fFlagged)
  3372. {
  3373. ImageList_Draw(g_himlStatus, 2, hdcMem, cxStatusBtn, cyStatusBmp+2, ILD_NORMAL);
  3374. cxStatusBtn += cxFlagsDelta;
  3375. pszTitles[cNumButtons++] = g_szStatFlagged;
  3376. }
  3377. if (m_lpAttMan->GetUnsafeAttachCount())
  3378. {
  3379. ImageList_Draw(g_himlStatus, 6, hdcMem, cxStatusBtn, cyStatusBmp+2, ILD_NORMAL);
  3380. cxStatusBtn += cxFlagsDelta;
  3381. }
  3382. if (cNumButtons > 0)
  3383. {
  3384. char szHeaderString[cchHeaderMax*4+1];
  3385. // Add an additional pixel for the text.
  3386. cyStatusBtn++;
  3387. switch (cNumButtons)
  3388. {
  3389. case 1:
  3390. {
  3391. wnsprintf(szHeaderString, ARRAYSIZE(szHeaderString), g_szStatFormat1, pszTitles[0]);
  3392. TextOut(hdcMem, cxStatusBtn, cyStatusBtn, szHeaderString, lstrlen(szHeaderString));
  3393. break;
  3394. }
  3395. case 2:
  3396. {
  3397. wnsprintf(szHeaderString, ARRAYSIZE(szHeaderString), g_szStatFormat2, pszTitles[0], pszTitles[1]);
  3398. TextOut(hdcMem, cxStatusBtn, cyStatusBtn, szHeaderString, lstrlen(szHeaderString));
  3399. break;
  3400. }
  3401. case 3:
  3402. {
  3403. wnsprintf(szHeaderString, ARRAYSIZE(szHeaderString), g_szStatFormat3, pszTitles[0], pszTitles[1], pszTitles[2]);
  3404. TextOut(hdcMem, cxStatusBtn, cyStatusBtn, szHeaderString, lstrlen(szHeaderString));
  3405. break;
  3406. }
  3407. }
  3408. cyStatusBtn += CYOfStatusLine() - 1;
  3409. }
  3410. if (m_lpAttMan->GetUnsafeAttachCount())
  3411. {
  3412. char szHeaderString[cchHeaderMax*4+1];
  3413. // Add an additional pixel for the text.
  3414. cyStatusBtn++;
  3415. wnsprintf(szHeaderString, ARRAYSIZE(szHeaderString), g_szStatUnsafeAtt, m_lpAttMan->GetUnsafeAttachList());
  3416. TextOut(hdcMem, cxStatusBtn, cyStatusBtn, szHeaderString, lstrlen(szHeaderString));
  3417. }
  3418. }
  3419. // ************ Draw the right side buttons **************
  3420. if (m_fDigSigned || m_fEncrypted || m_fVCard)
  3421. {
  3422. int width = GetRightMargin(TRUE),
  3423. cx = cxHeader - (ControlXBufferSize() + cxBtn),
  3424. cy = BeginYPos() + BUTTON_BUFFER,
  3425. yDiff = cyBtn + ControlYBufferSize() + 2*BUTTON_BUFFER;
  3426. if (m_fDigSigned)
  3427. {
  3428. ImageList_Draw(g_himlSecurity, m_fSignTrusted?0:2, hdcMem, cx, cy, ILD_NORMAL);
  3429. cy += yDiff;
  3430. }
  3431. if (m_fEncrypted)
  3432. {
  3433. ImageList_Draw(g_himlSecurity, m_fEncryptionOK?1:3, hdcMem, cx, cy, ILD_NORMAL);
  3434. cy += yDiff;
  3435. }
  3436. if (m_fVCard)
  3437. {
  3438. ImageList_Draw(g_himlBtns, 2, hdcMem, cx, cy, ILD_NORMAL);
  3439. }
  3440. }
  3441. // Draw active button edge
  3442. if (HDRCB_NO_BUTTON != m_dwCurrentBtn)
  3443. {
  3444. DOUTL(PAINTING_DEBUG_LEVEL, "Framing button %d: (%d, %d) to (%d, %d)",
  3445. m_dwCurrentBtn, m_rcCurrentBtn.left, m_rcCurrentBtn.top, m_rcCurrentBtn.right, m_rcCurrentBtn.bottom);
  3446. if (HDRCB_NO_BUTTON == m_dwClickedBtn)
  3447. DrawEdge(hdcMem, &m_rcCurrentBtn, BDR_RAISEDINNER, BF_TOPRIGHT | BF_BOTTOMLEFT);
  3448. else
  3449. DrawEdge(hdcMem, &m_rcCurrentBtn, BDR_SUNKENINNER, BF_TOPRIGHT | BF_BOTTOMLEFT);
  3450. }
  3451. BitBlt(hdc, 0, 0, cxHeader, cyHeader, hdcMem, 0, 0, SRCCOPY);
  3452. RestoreDC(hdcMem, idc);
  3453. DeleteObject(hbmMem);
  3454. DeleteDC(hdcMem);
  3455. EndPaint(m_hwnd, &ps);
  3456. }
  3457. HRESULT CNoteHdr::HrFillToolbarColor(HDC hdc)
  3458. {
  3459. HRESULT hr = NOERROR;
  3460. RECT rc;
  3461. if (!m_hwndToolbar)
  3462. return hr;
  3463. GetRealClientRect(m_hwndToolbar, &rc);
  3464. FillRect(hdc, &rc, GetSysColorBrush(COLOR_3DFACE));
  3465. return hr;
  3466. }
  3467. HRESULT CNoteHdr::HrGetVCardName(LPTSTR pszName, DWORD cch)
  3468. {
  3469. HRESULT hr = E_FAIL;
  3470. if (pszName == NULL || cch==0)
  3471. goto error;
  3472. *pszName = 0;
  3473. if (m_fMail)
  3474. GetOption(OPT_MAIL_VCARDNAME, pszName, cch);
  3475. else
  3476. GetOption(OPT_NEWS_VCARDNAME, pszName, cch);
  3477. if (*pszName != 0)
  3478. hr = NOERROR;
  3479. error:
  3480. return hr;
  3481. }
  3482. // turn on or off the vcard stamp.
  3483. HRESULT CNoteHdr::HrOnOffVCard()
  3484. {
  3485. HRESULT hr = NOERROR;
  3486. RECT rc;
  3487. TOOLINFO ti = {0};
  3488. ti.cbSize = sizeof(TOOLINFO);
  3489. ti.uFlags = 0;
  3490. ti.uId = idVCardStamp;
  3491. ti.hinst=g_hLocRes;
  3492. ti.hwnd = m_hwnd;
  3493. if (m_fVCardSave == m_fVCard)
  3494. return hr;
  3495. else
  3496. m_fVCardSave = m_fVCard;
  3497. if (m_fVCard)
  3498. {
  3499. ti.lpszText = (LPTSTR)idsTTVCardStamp;
  3500. SendMessage(m_hwndTT, TTM_ADDTOOL, 0, (LPARAM) &ti);
  3501. }
  3502. else
  3503. SendMessage(m_hwndTT, TTM_DELTOOL, 0, (LPARAM) &ti);
  3504. InvalidateRightMargin(0);
  3505. ReLayout();
  3506. return hr;
  3507. }
  3508. HRESULT CNoteHdr::HrGetVCardState(ULONG* pCmdf)
  3509. {
  3510. TCHAR szBuf[MAX_PATH];
  3511. HRESULT hr;
  3512. // if OLECMDF_LATCHED is on, insert vcard menu should be checked.
  3513. if (m_fVCard)
  3514. *pCmdf |= OLECMDF_LATCHED;
  3515. hr = HrGetVCardName(szBuf, sizeof(szBuf));
  3516. if (FAILED(hr)) // no vcard name selected
  3517. {
  3518. *pCmdf &= ~OLECMDF_ENABLED;
  3519. *pCmdf &= ~OLECMDF_LATCHED;
  3520. }
  3521. else
  3522. *pCmdf |= OLECMDF_ENABLED;
  3523. return NOERROR;
  3524. }
  3525. HRESULT CNoteHdr::HrShowVCardCtxtMenu(int x, int y)
  3526. {
  3527. HMENU hPopup=0;
  3528. HRESULT hr = E_FAIL;
  3529. POINT pt;
  3530. if (!m_fVCard)
  3531. goto exit;
  3532. // Pop up the context menu.
  3533. hPopup = LoadPopupMenu(IDR_VCARD_POPUP);
  3534. if (!hPopup)
  3535. goto exit;
  3536. if (IsReadOnly())
  3537. EnableMenuItem(hPopup, ID_DELETE_VCARD, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
  3538. pt.x = x;
  3539. pt.y = y;
  3540. ClientToScreen(m_hwnd, &pt);
  3541. TrackPopupMenuEx( hPopup, TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON,
  3542. pt.x, pt.y, m_hwnd, NULL);
  3543. hr = NOERROR;
  3544. exit:
  3545. if (hPopup)
  3546. DestroyMenu(hPopup);
  3547. return hr;
  3548. }
  3549. HRESULT CNoteHdr::HrShowVCardProperties(HWND hwnd)
  3550. {
  3551. HRESULT hr = NOERROR;
  3552. LPWAB lpWab = NULL;
  3553. TCHAR szName[MAX_PATH] = {0};
  3554. UINT cb = 0;
  3555. if (IsReadOnly() && m_lpAttMan)
  3556. return m_lpAttMan->HrShowVCardProp();
  3557. //else
  3558. // return E_FAIL;
  3559. hr = HrGetVCardName(szName, sizeof(szName));
  3560. if (FAILED(hr))
  3561. goto error;
  3562. hr = HrCreateWabObject(&lpWab);
  3563. if (FAILED(hr))
  3564. goto error;
  3565. //load names into the combobox from personal address book
  3566. hr = lpWab->HrEditEntry(hwnd, szName, ARRAYSIZE(szName));
  3567. if (FAILED(hr))
  3568. goto error;
  3569. error:
  3570. if (FAILED(hr) && hr!=MAPI_E_USER_CANCEL)
  3571. AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrVCardProperties),
  3572. NULL, MB_OK | MB_ICONEXCLAMATION);
  3573. ReleaseObj(lpWab);
  3574. return hr;
  3575. }
  3576. LRESULT CALLBACK CNoteHdr::IMESubClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, PHCI phci)
  3577. {
  3578. CNoteHdr *pnh = NULL;
  3579. HWND hwndParent = GetParent(hwnd);
  3580. STACK("IMESubClassProc");
  3581. if (IsWindow(hwndParent))
  3582. {
  3583. // Get the header class of the header window
  3584. pnh = (CNoteHdr *)GetWndThisPtr(hwndParent);
  3585. switch (msg)
  3586. {
  3587. case WM_IME_STARTCOMPOSITION:
  3588. DOUTL(64, "WM_IME_STARTCOMPOSITION");
  3589. pnh->m_dwIMEStartCount++;
  3590. break;
  3591. case WM_IME_ENDCOMPOSITION:
  3592. DOUTL(64, "WM_IME_ENDCOMPOSITION");
  3593. // Make sure we don't go negative.
  3594. if (0 < pnh->m_dwIMEStartCount)
  3595. {
  3596. pnh->m_dwIMEStartCount--;
  3597. }
  3598. else
  3599. {
  3600. AssertSz(FALSE, "We just received an extra WM_IME_ENDCOMPOSITION");
  3601. DOUTL(64, "WM_IME_ENDCOMPOSITION, not expected");
  3602. }
  3603. break;
  3604. }
  3605. }
  3606. // Defer to the default window proc
  3607. return CallWindowProcWrapW(g_lpfnREWndProc, hwnd, msg, wParam, lParam);
  3608. }
  3609. // bug #28379
  3610. // this is a hack to work around RichEd32 4.0 above bug in which
  3611. // it did not syncronize the keyboard change in the child windows.
  3612. // we use these global variable to keep track which keyboard
  3613. // is using now.
  3614. static HKL g_hCurrentKeyboardHandle = NULL ;
  3615. static BOOL g_fBiDiSystem = (BOOL) GetSystemMetrics(SM_MIDEASTENABLED);
  3616. static TCHAR g_chLastPressed = 0;
  3617. LRESULT CALLBACK CNoteHdr::EditSubClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  3618. {
  3619. HDC hdc;
  3620. PAINTSTRUCT ps;
  3621. int idcKeep;
  3622. PHCI phci;
  3623. LRESULT lRet;
  3624. CHARRANGE chrg;
  3625. phci=(PHCI)GetWndThisPtr(hwnd);
  3626. Assert(phci);
  3627. Assert(g_lpfnREWndProc);
  3628. if (phci && (phci->dwFlags&HCF_ADDRWELL))
  3629. {
  3630. switch (msg)
  3631. {
  3632. case WM_IME_STARTCOMPOSITION:
  3633. case WM_IME_ENDCOMPOSITION:
  3634. return IMESubClassProc(hwnd, msg, wParam, lParam, phci);
  3635. case WM_CUT:
  3636. // if cutting a selection, make sure we don't autocomplete when we get the en_change
  3637. goto cut;
  3638. case WM_KEYDOWN:
  3639. if (VK_BACK==wParam ||
  3640. VK_DELETE==wParam ||
  3641. ((GetKeyState(VK_CONTROL)&0x8000) && ('x'==wParam || 'X'==wParam)))
  3642. {
  3643. // if deleting a selection, make sure we don't autocomplete when we get the en_change
  3644. cut:
  3645. phci->dwACFlags |= AC_IGNORE;
  3646. lRet = CallWindowProcWrapW(g_lpfnREWndProc, hwnd, msg, wParam, lParam);
  3647. phci->dwACFlags &= ~AC_IGNORE;
  3648. return lRet;
  3649. }
  3650. else if (phci->dwACFlags&AC_SELECTION && (VK_RETURN==wParam))
  3651. {
  3652. SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&chrg);
  3653. if (chrg.cpMin < chrg.cpMax)
  3654. {
  3655. chrg.cpMin = chrg.cpMax;
  3656. SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&chrg);
  3657. HdrSetRichEditText(hwnd, (',' == wParam) ? L", ": L"; ", TRUE);
  3658. return 0;
  3659. }
  3660. }
  3661. // bobn: brianv says we have to take this out...
  3662. /*if ((g_dwBrowserFlags == 3) && (GetKeyState(VK_CONTROL)&0x8000) && (GetKeyState(VK_SHIFT)&0x8000))
  3663. {
  3664. switch(wParam) {
  3665. case 'R':
  3666. g_chLastPressed = (g_chLastPressed == 0) ? 'R' : 0;
  3667. break;
  3668. case 'O':
  3669. g_chLastPressed = (g_chLastPressed == 'R') ? 'O' : 0;
  3670. break;
  3671. case 'C':
  3672. g_chLastPressed = (g_chLastPressed == 'O') ? 'C' : 0;
  3673. break;
  3674. case 'K':
  3675. if (g_chLastPressed == 'C')
  3676. g_dwBrowserFlags |= 4;
  3677. g_chLastPressed = 0;
  3678. break;
  3679. }
  3680. }*/
  3681. break;
  3682. case WM_CHAR:
  3683. // VK_RETURN is no longer sent as a WM_CHAR so we place it in the
  3684. // WM_KEYDOWN. RAID 75444
  3685. if (phci->dwACFlags&AC_SELECTION && (wParam==',' || wParam==';'))
  3686. {
  3687. SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&chrg);
  3688. if (chrg.cpMin < chrg.cpMax)
  3689. {
  3690. chrg.cpMin = chrg.cpMax;
  3691. SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&chrg);
  3692. HdrSetRichEditText(hwnd, (wParam==',') ? L", ": L"; ", TRUE);
  3693. return 0;
  3694. }
  3695. }
  3696. break;
  3697. case WM_SETFOCUS:
  3698. if(g_fBiDiSystem)
  3699. {
  3700. HKL hklUS = NULL;
  3701. GetUSKeyboardLayout(&hklUS);
  3702. ActivateKeyboardLayout(hklUS, 0);
  3703. }
  3704. break;
  3705. }
  3706. }
  3707. // bug #28379
  3708. // this is a hack to work around RichEd32 4.0 above bug in which
  3709. // it did not syncronize the keyboard change in the child windows.
  3710. // we use these global variable to keep track which keyboard
  3711. // is using now.
  3712. //a-msadek; bug# 45709
  3713. // BiDi richedit uses WM_INPUTLANGCHANGE to determine reading order
  3714. // This will make it confused causing Latin text displayed flipped
  3715. if(!g_fBiDiSystem)
  3716. {
  3717. if (msg == WM_INPUTLANGCHANGE )
  3718. {
  3719. if ( g_hCurrentKeyboardHandle &&
  3720. g_hCurrentKeyboardHandle != (HKL) lParam )
  3721. ActivateKeyboardLayout(g_hCurrentKeyboardHandle, 0 );
  3722. }
  3723. if (msg == WM_INPUTLANGCHANGEREQUEST )
  3724. g_hCurrentKeyboardHandle = (HKL) lParam ;
  3725. }
  3726. // dispatch subject off to regular edit wndproc, and to & cc off to the RE wnd proc.
  3727. return CallWindowProcWrapW(g_lpfnREWndProc, hwnd, msg, wParam, lParam);
  3728. }
  3729. void GetUSKeyboardLayout(HKL *phkl)
  3730. {
  3731. UINT cNumkeyboards = 0, i;
  3732. HKL* phKeyboadList = NULL;
  3733. HKL hKeyboardUS = NULL;
  3734. // Let's check how many keyboard the system has
  3735. cNumkeyboards = GetKeyboardLayoutList(0, phKeyboadList);
  3736. phKeyboadList = (HKL*)LocalAlloc(LPTR, cNumkeyboards * sizeof(HKL));
  3737. cNumkeyboards = GetKeyboardLayoutList(cNumkeyboards, phKeyboadList);
  3738. for (i = 0; i < cNumkeyboards; i++)
  3739. {
  3740. LANGID LangID = PRIMARYLANGID(LANGIDFROMLCID(LOWORD(phKeyboadList[i])));
  3741. if(LangID == LANG_ENGLISH)
  3742. {
  3743. *phkl = phKeyboadList[i];
  3744. break;
  3745. }
  3746. }
  3747. if(phKeyboadList)
  3748. {
  3749. LocalFree((HLOCAL)phKeyboadList);
  3750. }
  3751. }
  3752. HRESULT CNoteHdr::HrUpdateTooltipPos()
  3753. {
  3754. TOOLINFO ti;
  3755. if (m_hwndTT)
  3756. {
  3757. /* ti.cbSize = sizeof(TOOLINFO);
  3758. ti.hwnd = m_hwnd;
  3759. ti.uId = idStamp;
  3760. ::SetRect(&ti.rect, m_ptStamp.x, m_ptStamp.y, m_ptStamp.x + cxStamp, m_ptStamp.y + cyStamp);
  3761. SendMessage(m_hwndTT, TTM_NEWTOOLRECT, 0, (LPARAM) &ti);
  3762. if (m_fVCard)
  3763. {
  3764. ti.uFlags = 0;
  3765. ti.uId = idVCardStamp;
  3766. ti.lpszText = (LPTSTR) idsTTVCardStamp;
  3767. if (m_pri!=priNone) //mail
  3768. ::SetRect(&ti.rect, m_ptStamp.x, m_ptStamp.y*2+cyStamp, m_ptStamp.x + cxStamp, 2*(m_ptStamp.y+cyStamp));
  3769. else // news
  3770. ::SetRect(&ti.rect, m_ptStamp.x, m_ptStamp.y, m_ptStamp.x + cxStamp, m_ptStamp.y + cyStamp);
  3771. SendMessage(m_hwndTT, TTM_NEWTOOLRECT, 0, (LPARAM) &ti);
  3772. }*/
  3773. }
  3774. return NOERROR;
  3775. }
  3776. HRESULT CNoteHdr::HrInit(IMimeMessage *pMsg)
  3777. {
  3778. HWND hwnd;
  3779. HRESULT hr=S_OK;
  3780. if (m_hwnd) // already running
  3781. return S_OK;
  3782. if (!FInitRichEdit(TRUE))
  3783. return E_FAIL;
  3784. if (!m_pEnvelopeSite)
  3785. {
  3786. Assert(m_hwndParent);
  3787. hwnd=CreateWindowExWrapW( WS_EX_CONTROLPARENT|WS_EX_NOPARENTNOTIFY,
  3788. WC_ATHHEADER,
  3789. NULL,
  3790. WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_CHILD,
  3791. 0,0,0,0,
  3792. m_hwndParent,
  3793. (HMENU)idcNoteHdr,
  3794. g_hInst, (LPVOID)this );
  3795. }
  3796. else
  3797. {
  3798. Assert(!m_hwnd);
  3799. hr = HrOfficeInitialize(TRUE);
  3800. if (FAILED(hr))
  3801. goto error;
  3802. m_hwndParent = g_hwndInit;
  3803. hwnd=CreateWindowExWrapW(WS_EX_CONTROLPARENT|WS_EX_NOPARENTNOTIFY,
  3804. WC_ATHHEADER,
  3805. NULL,
  3806. WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_CHILD,
  3807. 0,0,0,0,
  3808. m_hwndParent,
  3809. (HMENU)idcNoteHdr,
  3810. g_hInst, (LPVOID)this);
  3811. if (!hwnd)
  3812. {
  3813. hr = E_FAIL;
  3814. goto error;
  3815. }
  3816. m_ntNote = OENA_COMPOSE;
  3817. m_fMail = TRUE;
  3818. if (pMsg)
  3819. hr = Load(pMsg);
  3820. else
  3821. hr = HrOfficeLoad();
  3822. if (FAILED(hr))
  3823. goto error;
  3824. }
  3825. if (!hwnd)
  3826. {
  3827. hr=E_OUTOFMEMORY;
  3828. goto error;
  3829. }
  3830. m_hwnd = hwnd;
  3831. m_fDirty=FALSE;
  3832. error:
  3833. return hr;
  3834. }
  3835. HRESULT CNoteHdr::HrOfficeInitialize(BOOL fInit)
  3836. {
  3837. HRESULT hr = E_FAIL;
  3838. if (fInit)
  3839. {
  3840. hr = CoIncrementInit("CNoteHdr::HrOfficeInitialize", MSOEAPI_START_COMOBJECT, NULL, &m_hInitRef);
  3841. if (FAILED(hr))
  3842. return hr;
  3843. if (!FHeader_Init(TRUE))
  3844. return E_FAIL;
  3845. m_fAutoComplete = TRUE;
  3846. m_fDirty=FALSE;
  3847. hr = _RegisterWithComponentMgr(TRUE);
  3848. if (FAILED(hr))
  3849. return E_FAIL;
  3850. m_fOfficeInit = TRUE;
  3851. }
  3852. else
  3853. {
  3854. if (m_hInitRef)
  3855. CoDecrementInit("CNoteHdr::HrOfficeInitialize", &m_hInitRef);
  3856. }
  3857. return NOERROR;
  3858. }
  3859. void CNoteHdr::OnNCDestroy()
  3860. {
  3861. if (m_rgHCI)
  3862. {
  3863. MemFree(m_rgHCI);
  3864. m_rgHCI = NULL;
  3865. m_cHCI = 0;
  3866. }
  3867. _RegisterAsDropTarget(FALSE);
  3868. _RegisterWithFontCache(FALSE);
  3869. SafeRelease(m_pHeaderSite);
  3870. SafeRelease(m_pEnvelopeSite);
  3871. m_hwnd = NULL;
  3872. }
  3873. void CNoteHdr::OnDestroy()
  3874. {
  3875. HrFreeFieldList();
  3876. if (m_lpAttMan)
  3877. m_lpAttMan->HrClose();
  3878. // release office interfaces if we get torn down
  3879. _RegisterWithComponentMgr(FALSE);
  3880. }
  3881. HRESULT CNoteHdr::ShowAdvancedHeaders(BOOL fShow)
  3882. {
  3883. if (!!m_fAdvanced != fShow)
  3884. {
  3885. m_fAdvanced=fShow;
  3886. ReLayout();
  3887. if (m_hwndToolbar)
  3888. SendMessage(m_hwndToolbar, TB_CHECKBUTTON, ID_ENV_BCC, MAKELONG(!!m_fAdvanced, 0));
  3889. }
  3890. return S_OK;
  3891. }
  3892. HRESULT CNoteHdr::HrFShowHeader(PHCI phci)
  3893. {
  3894. Assert(phci);
  3895. if (phci->dwFlags & HCF_COMBO)
  3896. {
  3897. if (m_cAccountIDs < 2)
  3898. return S_FALSE;
  3899. else
  3900. return S_OK;
  3901. }
  3902. if (phci->dwFlags & HCF_ATTACH)
  3903. {
  3904. if (!m_fStillLoading)
  3905. {
  3906. ULONG cAttMan = 0;
  3907. HrGetAttachCount(&cAttMan);
  3908. if (cAttMan)
  3909. return S_OK;
  3910. }
  3911. return S_FALSE;
  3912. }
  3913. if (phci->dwFlags & HCF_ADVANCED)
  3914. {
  3915. if (IsReadOnly())
  3916. {
  3917. // If it is a read note and CC is empty, don't show
  3918. if (phci->fEmpty)
  3919. return S_FALSE;
  3920. }
  3921. else
  3922. // If is a send note and not suppose to show adv headers, don't show
  3923. if (!m_fAdvanced)
  3924. return S_FALSE;
  3925. }
  3926. if ((phci->dwFlags & HCF_OPTIONAL) && !DwGetOption(phci->dwOpt))
  3927. return S_FALSE;
  3928. if (phci->dwFlags & HCF_HIDDEN)
  3929. return S_FALSE;
  3930. return S_OK;
  3931. }
  3932. // =================================================================================
  3933. // SzGetDisplaySec
  3934. // returns the security enhancements and state of such for this message
  3935. // Params:
  3936. // OUT pidsLabel - if non-NULL, will contain the ids for the field name
  3937. // Returns:
  3938. // a built string giving information about the signature and/or encryption
  3939. // =================================================================================
  3940. LPWSTR CNoteHdr::SzGetDisplaySec(LPMIMEMESSAGE pMsg, int *pidsLabel)
  3941. {
  3942. WCHAR szResource[CCHMAX_STRINGRES];
  3943. LPWSTR lpszLabel = NULL;
  3944. DWORD cchSecurityField = 0;
  3945. if (m_lpszSecurityField)
  3946. {
  3947. MemFree(m_lpszSecurityField);
  3948. m_lpszSecurityField = NULL;
  3949. }
  3950. // check label first.
  3951. if ((m_ntNote == OENA_READ) && pMsg)
  3952. {
  3953. HrGetLabelString(pMsg, &lpszLabel);
  3954. }
  3955. if (pidsLabel)
  3956. *pidsLabel=idsSecurityField;
  3957. UINT labelLen = 1;
  3958. if(lpszLabel)
  3959. {
  3960. //Bug #101350 - lstrlenW will AV (and handle it) if passed a NULL
  3961. labelLen += lstrlenW(lpszLabel);
  3962. }
  3963. // need to build string
  3964. cchSecurityField = (2 * CCHMAX_STRINGRES + labelLen);
  3965. if (!MemAlloc((LPVOID *)&m_lpszSecurityField, (cchSecurityField *sizeof(WCHAR))))
  3966. return NULL;
  3967. *m_lpszSecurityField = L'\0';
  3968. // Example: "Digitally signed - signature unverifiable; Encrypted - Certificate is trusted"
  3969. if (MST_SIGN_MASK & m_SecState.type)
  3970. {
  3971. AthLoadStringW(idsSecurityLineDigSign, szResource, ARRAYSIZE(szResource));
  3972. StrCpyNW(m_lpszSecurityField, szResource, cchSecurityField);
  3973. if (IsSignTrusted(&m_SecState))
  3974. AthLoadStringW(idsSecurityLineSignGood, szResource, ARRAYSIZE(szResource));
  3975. else if (MSV_BADSIGNATURE & m_SecState.ro_msg_validity)
  3976. AthLoadStringW(idsSecurityLineSignBad, szResource, ARRAYSIZE(szResource));
  3977. else if ((MSV_UNVERIFIABLE & m_SecState.ro_msg_validity) ||
  3978. (MSV_MALFORMEDSIG & m_SecState.ro_msg_validity))
  3979. AthLoadStringW(idsSecurityLineSignUnsure, szResource, ARRAYSIZE(szResource));
  3980. else if ((ATHSEC_NOTRUSTWRONGADDR & m_SecState.user_validity) &&
  3981. ((m_SecState.user_validity & ~ATHSEC_NOTRUSTWRONGADDR) == ATHSEC_TRUSTED) &&
  3982. (! m_SecState.ro_msg_validity))
  3983. {
  3984. AthLoadStringW(idsSecurityLineSignPreProblem, szResource, ARRAYSIZE(szResource));
  3985. StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
  3986. AthLoadStringW(idsSecurityLineSignMismatch, szResource, ARRAYSIZE(szResource));
  3987. }
  3988. else if (((ATHSEC_TRUSTED != m_SecState.user_validity) && m_SecState.fHaveCert) ||
  3989. (MSV_EXPIRED_SIGNINGCERT & m_SecState.ro_msg_validity))
  3990. {
  3991. AthLoadStringW(idsSecurityLineSignPreProblem, szResource, ARRAYSIZE(szResource));
  3992. if (ATHSEC_TRUSTED != m_SecState.user_validity)
  3993. {
  3994. int nNotTrust = 0;
  3995. StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
  3996. // ignore revokedness for now
  3997. if (ATHSEC_NOTRUSTUNKNOWN & m_SecState.user_validity)
  3998. {
  3999. AthLoadStringW(idsSecurityLineSignUntrusted, szResource, ARRAYSIZE(szResource));
  4000. }
  4001. else if(ATHSEC_NOTRUSTREVOKED & m_SecState.user_validity)
  4002. {
  4003. AthLoadStringW(idsSecurityLineSignRevoked, szResource, ARRAYSIZE(szResource));
  4004. nNotTrust = 1;
  4005. }
  4006. else if(ATHSEC_NOTRUSTOTHER & m_SecState.user_validity)
  4007. {
  4008. AthLoadStringW(idsSecurityLineSignOthers, szResource, ARRAYSIZE(szResource));
  4009. nNotTrust = 1;
  4010. }
  4011. else if(m_SecState.user_validity & ATHSEC_NOTRUSTWRONGADDR)
  4012. {
  4013. AthLoadStringW(idsSecurityLineSignMismatch, szResource, ARRAYSIZE(szResource));
  4014. nNotTrust = 1;
  4015. }
  4016. else // if(!(m_SecState.user_validity & ATHSEC_NOTRUSTNOTTRUSTED))
  4017. AthLoadStringW(idsSecurityLineSignDistrusted, szResource, ARRAYSIZE(szResource));
  4018. if((m_SecState.user_validity & ATHSEC_NOTRUSTNOTTRUSTED) && nNotTrust)
  4019. {
  4020. StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
  4021. AthLoadStringW(idsSecurityLineListStr, szResource, ARRAYSIZE(szResource));
  4022. StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
  4023. AthLoadStringW(idsSecurityLineSignDistrusted, szResource, ARRAYSIZE(szResource));
  4024. }
  4025. if (MSV_EXPIRED_SIGNINGCERT & m_SecState.ro_msg_validity)
  4026. {
  4027. StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
  4028. AthLoadStringW(idsSecurityLineListStr, szResource, ARRAYSIZE(szResource));
  4029. }
  4030. }
  4031. if (MSV_EXPIRED_SIGNINGCERT & m_SecState.ro_msg_validity)
  4032. {
  4033. StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
  4034. AthLoadStringW(idsSecurityLineSignExpired, szResource, ARRAYSIZE(szResource));
  4035. }
  4036. }
  4037. else
  4038. {
  4039. AthLoadStringW(idsSecurityLineSignUnsure, szResource, ARRAYSIZE(szResource));
  4040. }
  4041. StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
  4042. if (MST_ENCRYPT_MASK & m_SecState.type)
  4043. {
  4044. AthLoadStringW(idsSecurityLineBreakStr, szResource, ARRAYSIZE(szResource));
  4045. StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
  4046. }
  4047. }
  4048. if (MST_ENCRYPT_MASK & m_SecState.type)
  4049. {
  4050. AthLoadStringW(idsSecurityLineEncryption, szResource, ARRAYSIZE(szResource));
  4051. StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
  4052. if (MSV_OK == (m_SecState.ro_msg_validity & MSV_ENCRYPT_MASK))
  4053. AthLoadStringW(idsSecurityLineEncGood, szResource, ARRAYSIZE(szResource));
  4054. else if (MSV_CANTDECRYPT & m_SecState.ro_msg_validity)
  4055. AthLoadStringW(idsSecurityLineEncBad, szResource, ARRAYSIZE(szResource));
  4056. else if (MSV_ENC_FOR_EXPIREDCERT & m_SecState.ro_msg_validity)
  4057. AthLoadStringW(idsSecurityLineEncExpired, szResource, ARRAYSIZE(szResource));
  4058. else
  4059. {
  4060. DOUTL(DOUTL_CRYPT, "CRYPT: bad encrypt state in SzGetDisplaySec");
  4061. szResource[0] = _T('\000');
  4062. }
  4063. StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
  4064. }
  4065. if(lpszLabel != NULL)
  4066. {
  4067. AthLoadStringW(idsSecurityLineBreakStr, szResource, ARRAYSIZE(szResource));
  4068. StrCatBuffW(m_lpszSecurityField, szResource, cchSecurityField);
  4069. StrCatBuffW(m_lpszSecurityField, lpszLabel, cchSecurityField);
  4070. MemFree(lpszLabel);
  4071. }
  4072. return m_lpszSecurityField;
  4073. }
  4074. HRESULT CNoteHdr::HrClearUndoStack()
  4075. {
  4076. int iHC;
  4077. HWND hwndRE;
  4078. for (iHC=0; iHC<(int)m_cHCI; iHC++)
  4079. {
  4080. if (hwndRE = GetDlgItem(m_hwnd, m_rgHCI[iHC].idEdit))
  4081. SendMessage(hwndRE, EM_EMPTYUNDOBUFFER, 0, 0);
  4082. }
  4083. return S_OK;
  4084. }
  4085. // There are some cases where we don't wan't the resolve name to
  4086. // be skipped. For example, a resolve name during a save will set
  4087. // m_fAddressesChanged to be false. That is fine, except it doesn't
  4088. // underline the addresses. So when the user tries to resolve the name
  4089. // by doing the resolve name command, the name will appear not to
  4090. // be resolved. In this case, we don't want the next call to HrCheckNames
  4091. // to be skipped.
  4092. HRESULT CNoteHdr::HrCheckNames(BOOL fSilent, BOOL fSetCheckedFlag)
  4093. {
  4094. HRESULT hr;
  4095. if (!m_fAddressesChanged)
  4096. return S_OK;
  4097. if (m_fPoster && (OENA_READ != m_ntNote))
  4098. {
  4099. //We need to setmodify the cc field.
  4100. //We need to do this because this field is not typed in by the user.
  4101. Edit_SetModify(GetDlgItem(m_hwnd, idADCc), TRUE);
  4102. }
  4103. hr = m_pAddrWells->HrCheckNames(m_hwnd, fSilent ? CNF_DONTRESOLVE : 0);
  4104. if (SUCCEEDED(hr))
  4105. {
  4106. if (m_lpWabal == NULL)
  4107. hr = hrNoRecipients;
  4108. else
  4109. {
  4110. ADRINFO AdrInfo;
  4111. if (!m_lpWabal->FGetFirst(&AdrInfo))
  4112. hr = hrNoRecipients;
  4113. }
  4114. if (SUCCEEDED(hr) && fSetCheckedFlag)
  4115. m_fAddressesChanged = FALSE;
  4116. }
  4117. return hr;
  4118. }
  4119. HRESULT CNoteHdr::HrCheckGroups(BOOL fPosting)
  4120. {
  4121. HRESULT hr = S_OK;
  4122. BOOL fFailed = FALSE;
  4123. ULONG cReplyTo=0;
  4124. ADRINFO adrInfo;
  4125. BOOL fOneOrMoreNames = FALSE;
  4126. BOOL fMoreNames = FALSE;
  4127. TCHAR szAcctID[CCHMAX_ACCOUNT_NAME];
  4128. FOLDERID idServer = FOLDERID_INVALID;
  4129. if (!m_pAccount)
  4130. return E_FAIL;
  4131. m_pAccount->GetPropSz(AP_ACCOUNT_ID, szAcctID, sizeof(szAcctID));
  4132. // find the parent folder id of the account
  4133. hr = g_pStore->FindServerId(szAcctID, &idServer);
  4134. if (FAILED(hr))
  4135. return hr;
  4136. // check the group names...
  4137. hr = ResolveGroupNames(m_hwnd, idADNewsgroups, idServer, FALSE, &fMoreNames);
  4138. fOneOrMoreNames = fMoreNames;
  4139. fFailed = FAILED(hr);
  4140. // Check followup names
  4141. hr = ResolveGroupNames(m_hwnd, idTXTFollowupTo, idServer, TRUE, &fMoreNames);
  4142. fOneOrMoreNames = (fOneOrMoreNames || fMoreNames);
  4143. fFailed = fFailed || FAILED(hr);
  4144. if (!fOneOrMoreNames)
  4145. return hrNoRecipients;
  4146. if (fPosting)
  4147. {
  4148. // make sure there is only one reply-to person, in the wabal
  4149. if (m_lpWabal->FGetFirst(&adrInfo))
  4150. do
  4151. if (adrInfo.lRecipType == MAPI_REPLYTO)
  4152. cReplyTo++;
  4153. while (m_lpWabal->FGetNext(&adrInfo));
  4154. if (cReplyTo>1)
  4155. {
  4156. // this is not cool. Don't allow then to post...
  4157. AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaNews), MAKEINTRESOURCEW(idsErrOnlyOneReplyTo), NULL, MB_OK);
  4158. return hrTooManyReplyTo;
  4159. }
  4160. }
  4161. if (fPosting && fFailed)
  4162. {
  4163. if (IDYES == AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaNews), MAKEINTRESOURCEW(idsIgnoreResolveError), 0, MB_ICONEXCLAMATION |MB_YESNO))
  4164. hr = S_OK;
  4165. else
  4166. hr = MAPI_E_USER_CANCEL;
  4167. }
  4168. return hr;
  4169. }
  4170. HRESULT CNoteHdr::ResolveGroupNames(HWND hwnd, int idField, FOLDERID idServer, BOOL fPosterAllowed, BOOL *fOneOrMoreNames)
  4171. {
  4172. HRESULT hr = S_OK;
  4173. FOLDERINFO Folder;
  4174. int nResolvedNames = 0;
  4175. AssertSz((idServer != FOLDERID_INVALID), TEXT("ResolveGroupNames: [ARGS] No account folder"));
  4176. // Now loop through the group names and see if they all exist. First make
  4177. // a copy of the string since strtok is destructive.
  4178. LPWSTR pwszBuffer = NULL;
  4179. LPSTR pszBuffer = NULL;
  4180. DWORD dwType;
  4181. LONG lIndex,
  4182. cchBufLen,
  4183. lIter = 0;
  4184. TCHAR szPrompt[CCHMAX_STRINGRES];
  4185. LPTSTR psz = NULL,
  4186. pszTok = NULL,
  4187. pszToken = NULL;
  4188. // HrGetFieldText will return S_FALSE if no text
  4189. hr = HrGetFieldText(&pwszBuffer, idField);
  4190. if (S_OK != hr)
  4191. return hr;
  4192. IF_NULLEXIT(pszBuffer = PszToANSI(GetACP(), pwszBuffer));
  4193. psz = pszBuffer;
  4194. // Check group name
  4195. while (*psz && IsSpace(psz))
  4196. psz = CharNext(psz);
  4197. if(!(*psz))
  4198. {
  4199. hr = S_FALSE;
  4200. goto exit;
  4201. }
  4202. else
  4203. psz = NULL;
  4204. pszTok = pszBuffer;
  4205. pszToken = StrTokEx(&pszTok, GRP_DELIMITERS);
  4206. while (NULL != pszToken)
  4207. {
  4208. if (!fPosterAllowed ||
  4209. (fPosterAllowed && 0 != lstrcmpi(pszToken, c_szPosterKeyword)))
  4210. {
  4211. ZeroMemory(&Folder, sizeof(Folder));
  4212. // See if the Folder Already Exists
  4213. Folder.idParent = idServer;
  4214. Folder.pszName = (LPSTR)pszToken;
  4215. // Try to find in the index
  4216. if (DB_S_FOUND == g_pStore->FindRecord(IINDEX_ALL, COLUMNS_ALL, &Folder, NULL))
  4217. {
  4218. // Check to see if this newsgroup allows posting.
  4219. if (Folder.dwFlags & FOLDER_NOPOSTING)
  4220. {
  4221. psz = AthLoadString(idsErrNewsgroupNoPosting, 0, 0);
  4222. wnsprintf(szPrompt, ARRAYSIZE(szPrompt), psz, pszToken, pszToken);
  4223. AthFreeString(psz);
  4224. AthMessageBox(hwnd, MAKEINTRESOURCE(idsAthenaNews), szPrompt,
  4225. 0, MB_ICONSTOP | MB_OK);
  4226. hr = E_FAIL;
  4227. }
  4228. if (Folder.dwFlags & FOLDER_BLOCKED)
  4229. {
  4230. psz = AthLoadString(idsErrNewsgroupBlocked, 0, 0);
  4231. wnsprintf(szPrompt, ARRAYSIZE(szPrompt), psz, pszToken, pszToken);
  4232. AthFreeString(psz);
  4233. AthMessageBox(hwnd, MAKEINTRESOURCE(idsAthenaNews), szPrompt,
  4234. 0, MB_ICONSTOP | MB_OK);
  4235. hr = E_FAIL;
  4236. }
  4237. else
  4238. nResolvedNames++;
  4239. // Free
  4240. g_pStore->FreeRecord(&Folder);
  4241. }
  4242. else
  4243. {
  4244. psz = AthLoadString(idsErrCantResolveGroup, 0, 0);
  4245. wnsprintf(szPrompt, ARRAYSIZE(szPrompt), psz, pszToken);
  4246. AthFreeString(psz);
  4247. AthMessageBox(hwnd, MAKEINTRESOURCE(idsAthenaNews), szPrompt, 0,
  4248. MB_ICONSTOP | MB_OK);
  4249. hr = E_FAIL;
  4250. }
  4251. }
  4252. pszToken = StrTokEx(&pszTok, GRP_DELIMITERS);
  4253. }
  4254. exit:
  4255. MemFree(pszBuffer);
  4256. MemFree(pwszBuffer);
  4257. *fOneOrMoreNames = ((nResolvedNames > 0) ? TRUE : FALSE);
  4258. return (hr);
  4259. }
  4260. HRESULT CNoteHdr::HrGetFieldText(LPWSTR* ppszText, int idHdrCtrl)
  4261. {
  4262. HWND hwnd = GetDlgItem(m_hwnd, idHdrCtrl);
  4263. return HrGetFieldText(ppszText, hwnd);
  4264. }
  4265. HRESULT CNoteHdr::HrGetFieldText(LPWSTR* ppszText, HWND hwnd)
  4266. {
  4267. DWORD cch;
  4268. cch = GetRichEditTextLen(hwnd) + 1;
  4269. if (1 == cch)
  4270. return (S_FALSE);
  4271. if (!MemAlloc((LPVOID*) ppszText, cch * sizeof(WCHAR)))
  4272. return (E_OUTOFMEMORY);
  4273. HdrGetRichEditText(hwnd, *ppszText, cch, FALSE);
  4274. return (S_OK);
  4275. }
  4276. HRESULT CNoteHdr::HrAddSender()
  4277. {
  4278. ULONG uPos=0;
  4279. ADRINFO adrInfo;
  4280. LPADRINFO lpAdrInfo=0;
  4281. LPWAB lpWab;
  4282. HRESULT hr=E_FAIL;
  4283. if (m_lpWabal->FGetFirst(&adrInfo))
  4284. do
  4285. if (adrInfo.lRecipType==MAPI_ORIG)
  4286. {
  4287. lpAdrInfo=&adrInfo;
  4288. break;
  4289. }
  4290. while (m_lpWabal->FGetNext(&adrInfo));
  4291. if (lpAdrInfo &&
  4292. !FAILED (HrCreateWabObject (&lpWab)))
  4293. {
  4294. hr=lpWab->HrAddToWAB(m_hwnd, lpAdrInfo);
  4295. lpWab->Release ();
  4296. }
  4297. if (FAILED(hr) && hr!=MAPI_E_USER_CANCEL)
  4298. {
  4299. if (hr==MAPI_E_COLLISION)
  4300. AthMessageBoxW (m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrAddrDupe), NULL, MB_OK);
  4301. else
  4302. AthMessageBoxW (m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrAddToWAB), NULL, MB_OK);
  4303. }
  4304. return NOERROR;
  4305. }
  4306. HRESULT CNoteHdr::HrAddAllOnToList()
  4307. {
  4308. ADRINFO adrInfo;
  4309. LPWAB lpWab;
  4310. HRESULT hr = S_OK;
  4311. if (m_lpWabal->FGetFirst(&adrInfo))
  4312. {
  4313. hr = HrCreateWabObject(&lpWab);
  4314. if (SUCCEEDED(hr))
  4315. {
  4316. do
  4317. {
  4318. if (MAPI_TO == adrInfo.lRecipType)
  4319. {
  4320. hr = lpWab->HrAddToWAB(m_hwnd, &adrInfo);
  4321. if (MAPI_E_COLLISION == hr)
  4322. {
  4323. hr = S_OK;
  4324. AthMessageBoxW (m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrAddrDupe), NULL, MB_OK);
  4325. }
  4326. }
  4327. } while (SUCCEEDED(hr) && m_lpWabal->FGetNext(&adrInfo));
  4328. }
  4329. lpWab->Release();
  4330. }
  4331. if (FAILED(hr) && (MAPI_E_USER_CANCEL != hr))
  4332. AthMessageBoxW (m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrAddToWAB), NULL, MB_OK);
  4333. return hr;
  4334. }
  4335. HRESULT CNoteHdr::HrInitFieldList()
  4336. {
  4337. PHCI pHCI, pLoopHCI;
  4338. INT size;
  4339. BOOL fReadOnly = IsReadOnly();
  4340. if (m_fMail)
  4341. {
  4342. if (fReadOnly)
  4343. {
  4344. pHCI = rgMailHeaderRead;
  4345. size = sizeof(rgMailHeaderRead);
  4346. }
  4347. else
  4348. {
  4349. pHCI = rgMailHeaderSend;
  4350. size = sizeof(rgMailHeaderSend);
  4351. }
  4352. }
  4353. else
  4354. {
  4355. if (fReadOnly)
  4356. {
  4357. pHCI = rgNewsHeaderRead;
  4358. size = sizeof(rgNewsHeaderRead);
  4359. }
  4360. else
  4361. {
  4362. pHCI = rgNewsHeaderSend;
  4363. size = sizeof(rgNewsHeaderSend);
  4364. }
  4365. }
  4366. // Setup the labels
  4367. pLoopHCI = pHCI;
  4368. m_cHCI = size/sizeof(HCI);
  4369. for (ULONG i = 0; i < m_cHCI; i++, pLoopHCI++)
  4370. {
  4371. if (0 == pLoopHCI->strlen)
  4372. {
  4373. AthLoadStringW(pLoopHCI->idsLabel, pLoopHCI->sz, cchHeaderMax+1);
  4374. pLoopHCI->strlen = lstrlenW(pLoopHCI->sz);
  4375. }
  4376. if ((0 == pLoopHCI->strlenEmpty) && (0 != pLoopHCI->idsEmpty))
  4377. {
  4378. AthLoadStringW(pLoopHCI->idsEmpty, pLoopHCI->szEmpty, cchHeaderMax+1);
  4379. pLoopHCI->strlenEmpty = lstrlenW(pLoopHCI->szEmpty);
  4380. }
  4381. }
  4382. if (NULL != MemAlloc((LPVOID *)&m_rgHCI, size))
  4383. CopyMemory(m_rgHCI, pHCI, size);
  4384. else
  4385. return E_OUTOFMEMORY;
  4386. m_cxLeftMargin = _GetLeftMargin();
  4387. return S_OK;
  4388. }
  4389. int CNoteHdr::_GetLeftMargin()
  4390. {
  4391. PHCI pLoopHCI = m_rgHCI;
  4392. INT size;
  4393. int cxButtons = ControlXBufferSize();
  4394. HDC hdc = GetDC(m_hwnd);
  4395. HFONT hfontOld;
  4396. ULONG cxEditMarginCur = 0,
  4397. cxEditMaxMargin = 0;
  4398. SIZE rSize;
  4399. BOOL fReadOnly = IsReadOnly();
  4400. // Setup the labels
  4401. hfontOld=(HFONT)SelectObject(hdc, GetFont(fReadOnly));
  4402. for (ULONG i = 0; i < m_cHCI; i++, pLoopHCI++)
  4403. {
  4404. AssertSz(pLoopHCI->strlen, "Haven't set the strings yet.");
  4405. GetTextExtentPoint32AthW(hdc, pLoopHCI->sz, pLoopHCI->strlen, &rSize, NOFLAGS);
  4406. cxEditMarginCur = rSize.cx + PaddingOfLabels();
  4407. if (pLoopHCI->dwFlags & HCF_HASBUTTON)
  4408. cxEditMarginCur += CXOfButtonToLabel();
  4409. if (cxEditMarginCur > cxEditMaxMargin)
  4410. cxEditMaxMargin = cxEditMarginCur;
  4411. }
  4412. SelectObject(hdc, hfontOld);
  4413. ReleaseDC(m_hwnd, hdc);
  4414. return cxEditMaxMargin;
  4415. }
  4416. HRESULT CNoteHdr::HrFreeFieldList()
  4417. {
  4418. if (m_rgHCI)
  4419. {
  4420. for (int i=0; i<(int)m_cHCI; i++)
  4421. {
  4422. // You must free the pDoc before the preole or fault! (RICHED 2.0)
  4423. SafeRelease(m_rgHCI[i].pDoc);
  4424. SafeRelease(m_rgHCI[i].preole);
  4425. }
  4426. }
  4427. return NOERROR;
  4428. }
  4429. static WELLINIT rgWellInitMail[]=
  4430. {
  4431. {idADTo, MAPI_TO},
  4432. {idADCc, MAPI_CC},
  4433. {idADFrom, MAPI_ORIG},
  4434. {idADBCc, MAPI_BCC}
  4435. };
  4436. static WELLINIT rgWellInitNews[]=
  4437. {
  4438. {idADFrom, MAPI_ORIG},
  4439. {idADCc, MAPI_TO},
  4440. {idADReplyTo, MAPI_REPLYTO}
  4441. };
  4442. BOOL CNoteHdr::PostWMCreate()
  4443. {
  4444. HWND hwnd;
  4445. HWND hwndWells[4];
  4446. ULONG ulRecipType[4];
  4447. ULONG cWells=0;
  4448. PWELLINIT pWI;
  4449. INT size;
  4450. INT i;
  4451. if (hwnd=GetDlgItem(m_hwnd, idTXTSubject))
  4452. SendMessage(hwnd, EM_LIMITTEXT,cchMaxSubject,0);
  4453. if (m_fMail)
  4454. {
  4455. pWI = rgWellInitMail;
  4456. size = ARRAYSIZE(rgWellInitMail);
  4457. }
  4458. else
  4459. {
  4460. pWI = rgWellInitNews;
  4461. size = ARRAYSIZE(rgWellInitNews);
  4462. }
  4463. for (i=0; i<size; i++)
  4464. {
  4465. hwnd = GetDlgItem(m_hwnd, pWI[i].idField);
  4466. if (hwnd)
  4467. {
  4468. hwndWells[cWells] = hwnd;
  4469. ulRecipType[cWells++] = pWI[i].uMAPI;
  4470. }
  4471. }
  4472. AssertSz(!m_pAddrWells, "Who called PostWMCreate??????");
  4473. m_pAddrWells = new CAddrWells;
  4474. if (!m_pAddrWells || FAILED(m_pAddrWells->HrInit(cWells, hwndWells, ulRecipType)))
  4475. return FALSE;
  4476. return TRUE;
  4477. }
  4478. HRESULT CNoteHdr::HrSetMailRecipients(LPMIMEMESSAGE pMsg)
  4479. {
  4480. ADRINFO rAdrInfo;
  4481. HRESULT hr = NOERROR;
  4482. IImnEnumAccounts *pEnumAccounts = NULL;
  4483. LPWABAL lpWabal = NULL;
  4484. BOOL fAdvanced = FALSE;
  4485. AssertSz(OENA_REPLYTONEWSGROUP != m_ntNote, "Shouldn't get a REPLYTONEWSGROUP in a mail note.");
  4486. SafeRelease(m_lpWabal);
  4487. // Set initial state of wabals to use
  4488. switch (m_ntNote)
  4489. {
  4490. case OENA_READ:
  4491. case OENA_WEBPAGE:
  4492. case OENA_STATIONERY:
  4493. IF_FAILEXIT(hr = HrGetWabalFromMsg(pMsg, &m_lpWabal));
  4494. break;
  4495. case OENA_COMPOSE:
  4496. case OENA_REPLYTOAUTHOR:
  4497. case OENA_REPLYALL:
  4498. IF_FAILEXIT(hr = HrGetWabalFromMsg(pMsg, &lpWabal));
  4499. IF_FAILEXIT(hr = HrCreateWabalObject(&m_lpWabal));
  4500. break;
  4501. case OENA_FORWARD:
  4502. case OENA_FORWARDBYATTACH:
  4503. IF_FAILEXIT(hr = HrCreateWabalObject(&m_lpWabal));
  4504. break;
  4505. }
  4506. // Actually set recipients now.
  4507. switch (m_ntNote)
  4508. {
  4509. case OENA_COMPOSE:
  4510. {
  4511. #pragma prefast(suppress:11, "noise")
  4512. BOOL fMoreIterations = lpWabal->FGetFirst(&rAdrInfo);
  4513. while (fMoreIterations)
  4514. {
  4515. if (rAdrInfo.lRecipType != MAPI_ORIG)
  4516. {
  4517. hr = m_lpWabal->HrAddEntry(&rAdrInfo);
  4518. if (FAILED(hr))
  4519. break;
  4520. }
  4521. fMoreIterations = lpWabal->FGetNext(&rAdrInfo);
  4522. }
  4523. break;
  4524. }
  4525. case OENA_REPLYTOAUTHOR:
  4526. case OENA_REPLYALL:
  4527. {
  4528. BOOL fNeedOriginatorItems = TRUE;
  4529. BOOL fMoreIterations;
  4530. // Add items to To: line from the ReplyTo Field
  4531. fMoreIterations = lpWabal->FGetFirst (&rAdrInfo);
  4532. while (fMoreIterations)
  4533. {
  4534. if (rAdrInfo.lRecipType==MAPI_REPLYTO)
  4535. {
  4536. Assert (rAdrInfo.lpwszAddress);
  4537. fNeedOriginatorItems = FALSE;
  4538. rAdrInfo.lRecipType=MAPI_TO;
  4539. IF_FAILEXIT(hr = m_lpWabal->HrAddEntry(&rAdrInfo));
  4540. }
  4541. fMoreIterations = lpWabal->FGetNext (&rAdrInfo);
  4542. }
  4543. // If we don't need to add the MAPI_ORIG and we are not trying to reply to all, then we are done
  4544. if (!fNeedOriginatorItems && (OENA_REPLYALL != m_ntNote))
  4545. break;
  4546. // Raid-35976: Unable to open message window with no accounts configured
  4547. // Get an SMTP account enumerator
  4548. Assert(g_pAcctMan);
  4549. if (g_pAcctMan && (OENA_REPLYALL == m_ntNote))
  4550. g_pAcctMan->Enumerate(SRV_SMTP|SRV_HTTPMAIL, &pEnumAccounts);
  4551. // Add the following items to the To line
  4552. // 1) If there were no ReplyTo items, then fill from the Orig field
  4553. // 2) If is ReplyToAll, then fill from the To and CC line
  4554. fMoreIterations = lpWabal->FGetFirst (&rAdrInfo);
  4555. while (fMoreIterations)
  4556. {
  4557. // No replyto people were added, and this is a MAPI_ORIG
  4558. if (fNeedOriginatorItems && rAdrInfo.lRecipType == MAPI_ORIG)
  4559. {
  4560. rAdrInfo.lRecipType=MAPI_TO;
  4561. IF_FAILEXIT(hr = m_lpWabal->HrAddEntry(&rAdrInfo));
  4562. }
  4563. // pEnumAccounts will only be set if ReplyToAll
  4564. // If ReplyToAll, then add the CC and To line entries to the To field
  4565. else if (pEnumAccounts && (rAdrInfo.lRecipType == MAPI_TO || rAdrInfo.lRecipType == MAPI_CC))
  4566. {
  4567. BOOL fIsSendersAccount = FALSE;
  4568. TCHAR szEmailAddress[CCHMAX_EMAIL_ADDRESS];
  4569. Assert (rAdrInfo.lpwszAddress);
  4570. pEnumAccounts->Reset();
  4571. // See if rAdrInfo.lpszAddress exist as one of the user's Send Email Addresses
  4572. while (!fIsSendersAccount)
  4573. {
  4574. IImnAccount *pAccount = NULL;
  4575. hr = pEnumAccounts->GetNext(&pAccount);
  4576. if (hr == E_EnumFinished || FAILED(hr))
  4577. break;
  4578. if (SUCCEEDED(pAccount->GetPropSz(AP_SMTP_EMAIL_ADDRESS, szEmailAddress, ARRAYSIZE(szEmailAddress))))
  4579. {
  4580. LPWSTR pwszAddress = NULL;
  4581. IF_NULLEXIT(pwszAddress = PszToUnicode(CP_ACP, szEmailAddress));
  4582. if (0 == StrCmpIW(rAdrInfo.lpwszAddress, pwszAddress))
  4583. fIsSendersAccount = TRUE;
  4584. MemFree(pwszAddress);
  4585. }
  4586. pAccount->Release();
  4587. }
  4588. // Reset hr
  4589. hr = S_OK;
  4590. // Add the account if it isn't from the sender
  4591. if (!fIsSendersAccount)
  4592. {
  4593. if (0 != StrCmpW(rAdrInfo.lpwszAddress, L"Undisclosed Recipients"))
  4594. {
  4595. // only include recipient on ReplyAll if it's not the sender...
  4596. IF_FAILEXIT(hr = m_lpWabal->HrAddEntry(&rAdrInfo));
  4597. }
  4598. }
  4599. }
  4600. fMoreIterations = lpWabal->FGetNext(&rAdrInfo);
  4601. }
  4602. }
  4603. }
  4604. Assert (m_lpWabal);
  4605. // For the send note case, make sure that resolved addresses are valid.
  4606. // If display name and email address are the same, UnresolveOneOffs() will clear
  4607. // the email address to force a real resolve.
  4608. if (OENA_COMPOSE == m_ntNote || OENA_WEBPAGE == m_ntNote || OENA_STATIONERY == m_ntNote)
  4609. m_lpWabal->UnresolveOneOffs();
  4610. m_lpWabal->HrResolveNames(NULL, FALSE);
  4611. Assert(m_pAddrWells);
  4612. m_pAddrWells->HrSetWabal(m_lpWabal);
  4613. m_pAddrWells->HrDisplayWells(m_hwnd);
  4614. if (OENA_READ == m_ntNote)
  4615. fAdvanced = DwGetOption(OPT_MAILNOTEADVREAD);
  4616. else
  4617. {
  4618. fAdvanced = DwGetOption(OPT_MAILNOTEADVSEND);
  4619. // Need to make sure that if we are in a compose note, that we check to see
  4620. // if we added a bcc without setting the advanced headers. If this is the case,
  4621. // then show the advanced headers for this note.
  4622. if (!fAdvanced && (0 < GetRichEditTextLen(GetDlgItem(m_hwnd, idADBCc))))
  4623. fAdvanced = TRUE;
  4624. }
  4625. // BUG: 31217: showadvanced has to be the last thing we call after modifying the
  4626. // well contents
  4627. ShowAdvancedHeaders(fAdvanced);
  4628. exit:
  4629. // Cleanup
  4630. ReleaseObj(lpWabal);
  4631. ReleaseObj(pEnumAccounts);
  4632. return hr;
  4633. }
  4634. HRESULT CNoteHdr::HrSetupNote(LPMIMEMESSAGE pMsg)
  4635. {
  4636. HWND hwnd;
  4637. WCHAR wsz[cchMaxSubject+1];
  4638. LPWSTR psz = NULL;
  4639. PROPVARIANT rVariant;
  4640. HRESULT hr = NOERROR;
  4641. if (!pMsg)
  4642. return E_INVALIDARG;
  4643. MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_SUBJECT), NOFLAGS, &psz);
  4644. HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTSubject), psz, FALSE);
  4645. *wsz=0;
  4646. rVariant.vt = VT_FILETIME;
  4647. pMsg->GetProp(PIDTOSTR(PID_ATT_SENTTIME), 0, &rVariant);
  4648. AthFileTimeToDateTimeW(&rVariant.filetime, wsz, ARRAYSIZE(wsz), DTM_LONGDATE|DTM_NOSECONDS);
  4649. HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTDate), wsz, FALSE);
  4650. MemFree(psz);
  4651. return hr;
  4652. }
  4653. HRESULT CNoteHdr::HrSetPri(LPMIMEMESSAGE pMsg)
  4654. {
  4655. UINT pri=priNorm;
  4656. PROPVARIANT rVariant;
  4657. Assert(pMsg);
  4658. rVariant.vt = VT_UI4;
  4659. if (SUCCEEDED(pMsg->GetProp(PIDTOSTR(PID_ATT_PRIORITY), 0, &rVariant)))
  4660. {
  4661. if (rVariant.ulVal == IMSG_PRI_HIGH)
  4662. pri=priHigh;
  4663. else if (rVariant.ulVal == IMSG_PRI_LOW)
  4664. pri=priLow;
  4665. }
  4666. return SetPriority(pri);
  4667. }
  4668. HRESULT CNoteHdr::HrAutoAddToWAB()
  4669. {
  4670. LPWAB lpWab=0;
  4671. LPWABAL lpWabal=0;
  4672. HRESULT hr;
  4673. ADRINFO adrInfo;
  4674. if (!m_lpWabal)
  4675. return S_OK;
  4676. if (!DwGetOption(OPT_MAIL_AUTOADDTOWABONREPLY))
  4677. return S_OK;
  4678. IF_FAILEXIT(hr=HrCreateWabObject(&lpWab));
  4679. // when this is called, m_lpWabal contains everyone on the to: and cc: line
  4680. // for a reply/reply all. We will add all these people to the WAB, ignoring any
  4681. // clashes or failures
  4682. // Add Sender if email and displayname are not the same.
  4683. // if so then there's no username so little point in adding.
  4684. if (m_lpWabal->FGetFirst(&adrInfo))
  4685. do
  4686. {
  4687. // IE5.#2568: we now just add to the WAB regardless of
  4688. // email and dispname being the same.
  4689. // if (lstrcmp(adrInfo.lpszDisplay, adrInfo.lpszAddress)!=0)
  4690. lpWab->HrAddNewEntry(adrInfo.lpwszDisplay, adrInfo.lpwszAddress);
  4691. }
  4692. while (m_lpWabal->FGetNext(&adrInfo));
  4693. exit:
  4694. ReleaseObj(lpWab);
  4695. return hr;
  4696. }
  4697. HRESULT CNoteHdr::HrOfficeLoad()
  4698. {
  4699. HRESULT hr = NOERROR;
  4700. m_fSkipLayout = FALSE;
  4701. if (!m_hCharset)
  4702. {
  4703. if (g_hDefaultCharsetForMail==NULL)
  4704. ReadSendMailDefaultCharset();
  4705. m_hCharset = g_hDefaultCharsetForMail;
  4706. }
  4707. if (m_hCharset)
  4708. HrUpdateCharSetFonts(m_hCharset, FALSE);
  4709. SafeRelease(m_lpWabal);
  4710. hr = HrCreateWabalObject(&m_lpWabal);
  4711. if (SUCCEEDED(hr))
  4712. {
  4713. Assert(m_pAddrWells);
  4714. m_pAddrWells->HrSetWabal(m_lpWabal);
  4715. ShowAdvancedHeaders(DwGetOption(OPT_MAILNOTEADVSEND));
  4716. m_fStillLoading = FALSE;
  4717. }
  4718. return hr;
  4719. }
  4720. void CNoteHdr::SetReferences(LPMIMEMESSAGE pMsg)
  4721. {
  4722. LPWSTR lpszRefs = 0;
  4723. SafeMemFree(m_pszRefs);
  4724. MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_REFS), NOFLAGS, &lpszRefs);
  4725. switch (m_ntNote)
  4726. {
  4727. case OENA_REPLYALL:
  4728. case OENA_REPLYTOAUTHOR:
  4729. case OENA_REPLYTONEWSGROUP:
  4730. {
  4731. LPWSTR lpszMsgId = 0;
  4732. MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_MESSAGEID), NOFLAGS, &lpszMsgId);
  4733. if (lpszMsgId)
  4734. HrCreateReferences(lpszRefs, lpszMsgId, &m_pszRefs);
  4735. SafeMimeOleFree(lpszMsgId);
  4736. break;
  4737. }
  4738. case OENA_READ:
  4739. case OENA_WEBPAGE:
  4740. case OENA_STATIONERY:
  4741. case OENA_COMPOSE:
  4742. // hold on to the reference line for a send-note, so we can repersist if saving in drafts
  4743. if (lpszRefs)
  4744. m_pszRefs = PszDupW(lpszRefs);
  4745. break;
  4746. default:
  4747. break;
  4748. }
  4749. SafeMimeOleFree(lpszRefs);
  4750. }
  4751. HRESULT CNoteHdr::HrSetNewsRecipients(LPMIMEMESSAGE pMsg)
  4752. {
  4753. HRESULT hr = S_OK;
  4754. LPWSTR pwszNewsgroups = 0,
  4755. pwszCC = 0,
  4756. pwszSetNewsgroups = 0;
  4757. TCHAR szApproved[CCHMAX_EMAIL_ADDRESS];
  4758. HWND hwnd;
  4759. AssertSz(OENA_REPLYTOAUTHOR != m_ntNote, "Shouldn't get a REPLYTOAUTHOR in a news note.");
  4760. AssertSz(OENA_FORWARD != m_ntNote, "Shouldn't get a FORWARD in a news note.");
  4761. AssertSz(OENA_FORWARDBYATTACH != m_ntNote, "Shouldn't get a FORWARDBYATTACH in a news note.");
  4762. *szApproved = 0;
  4763. if (m_pAccount && DwGetOption(OPT_NEWSMODERATOR))
  4764. {
  4765. if (FAILED(m_pAccount->GetPropSz(AP_NNTP_REPLY_EMAIL_ADDRESS, szApproved, ARRAYSIZE(szApproved))) || (0 == *szApproved))
  4766. m_pAccount->GetPropSz(AP_NNTP_EMAIL_ADDRESS, szApproved, ARRAYSIZE(szApproved));
  4767. }
  4768. MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_NEWSGROUPS), NOFLAGS, &pwszNewsgroups);
  4769. switch (m_ntNote)
  4770. {
  4771. case OENA_READ:
  4772. {
  4773. LPWSTR lpszOrg = 0;
  4774. MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_ORG), NOFLAGS, &lpszOrg);
  4775. HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTOrg), lpszOrg, FALSE);
  4776. SafeMimeOleFree(lpszOrg);
  4777. }
  4778. // Fall through
  4779. case OENA_WEBPAGE:
  4780. case OENA_STATIONERY:
  4781. case OENA_COMPOSE:
  4782. {
  4783. LPWSTR lpszFollowup = 0,
  4784. lpszDist = 0,
  4785. lpszKeywords = 0;
  4786. MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_FOLLOWUPTO), NOFLAGS, &lpszFollowup);
  4787. MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_DISTRIB), NOFLAGS, &lpszDist);
  4788. MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_KEYWORDS), NOFLAGS, &lpszKeywords);
  4789. pwszSetNewsgroups = pwszNewsgroups;
  4790. HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTFollowupTo), lpszFollowup, FALSE);
  4791. HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTDistribution), lpszDist, FALSE);
  4792. HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTKeywords), lpszKeywords, FALSE);
  4793. MemFree(lpszFollowup);
  4794. MemFree(lpszDist);
  4795. MemFree(lpszKeywords);
  4796. break;
  4797. }
  4798. case OENA_REPLYALL:
  4799. case OENA_REPLYTONEWSGROUP:
  4800. {
  4801. LPSTR pszGroupsFree = 0;
  4802. if (SUCCEEDED(ParseFollowup(pMsg, &pszGroupsFree, &m_fPoster)))
  4803. {
  4804. if (pszGroupsFree)
  4805. {
  4806. SafeMemFree(pwszNewsgroups);
  4807. IF_NULLEXIT(pwszNewsgroups = PszToUnicode(CP_ACP, pszGroupsFree));
  4808. }
  4809. pwszSetNewsgroups = pwszNewsgroups;
  4810. }
  4811. else
  4812. pwszSetNewsgroups = pwszNewsgroups;
  4813. Assert(pwszSetNewsgroups);
  4814. if ((OENA_REPLYALL == m_ntNote) || m_fPoster)
  4815. {
  4816. MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_REPLYTO), NOFLAGS, &pwszCC);
  4817. if (!pwszCC)
  4818. MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_FROM), NOFLAGS, &pwszCC);
  4819. }
  4820. break;
  4821. }
  4822. }
  4823. // set common fields
  4824. HdrSetRichEditText(GetDlgItem(m_hwnd, idADNewsgroups), pwszSetNewsgroups, FALSE);
  4825. // set read note / send note specific fields
  4826. if (OENA_READ != m_ntNote)
  4827. SetDlgItemText(m_hwnd, idADApproved, szApproved);
  4828. // set up the recipients
  4829. hr = HrSetNewsWabal(pMsg, pwszCC);
  4830. // BUG: 31217: showadvanced has to be the last thing we call after modifying the
  4831. // well contents
  4832. ShowAdvancedHeaders(DwGetOption(m_ntNote == OENA_READ ? OPT_NEWSNOTEADVREAD : OPT_NEWSNOTEADVSEND));
  4833. exit:
  4834. MemFree(pwszNewsgroups);
  4835. MemFree(pwszCC);
  4836. return hr;
  4837. }
  4838. HRESULT CNoteHdr::FullHeadersShowing(void)
  4839. {
  4840. return m_fAdvanced ? S_OK : S_FALSE;
  4841. }
  4842. HRESULT CNoteHdr::HrNewsSave(LPMIMEMESSAGE pMsg, CODEPAGEID cpID, BOOL fCheckConflictOnly)
  4843. {
  4844. HRESULT hr = S_OK;
  4845. WCHAR wsz[256];
  4846. WCHAR *pwszTrim;
  4847. BOOL fSenderOk = FALSE,
  4848. fSetMessageAcct = TRUE;
  4849. PROPVARIANT rVariant;
  4850. SYSTEMTIME st;
  4851. HWND hwnd;
  4852. PROPVARIANT rUserData;
  4853. BOOL fConflict = FALSE;
  4854. if (fCheckConflictOnly)
  4855. {
  4856. HdrGetRichEditText(GetDlgItem(m_hwnd, idADNewsgroups), wsz, ARRAYSIZE(wsz), FALSE);
  4857. pwszTrim = strtrimW(wsz);
  4858. if (*pwszTrim)
  4859. {
  4860. IF_FAILEXIT(hr = HrSafeToEncodeToCP(pwszTrim, cpID));
  4861. if (MIME_S_CHARSET_CONFLICT == hr)
  4862. goto exit;
  4863. }
  4864. HdrGetRichEditText(GetDlgItem(m_hwnd, idTXTFollowupTo), wsz, ARRAYSIZE(wsz), FALSE);
  4865. pwszTrim = strtrimW(wsz);
  4866. if (*pwszTrim)
  4867. {
  4868. IF_FAILEXIT(hr = HrSafeToEncodeToCP(pwszTrim, cpID));
  4869. if (MIME_S_CHARSET_CONFLICT == hr)
  4870. goto exit;
  4871. }
  4872. HdrGetRichEditText(GetDlgItem(m_hwnd, idTXTDistribution), wsz, ARRAYSIZE(wsz), FALSE);
  4873. pwszTrim = strtrimW(wsz);
  4874. if (*pwszTrim)
  4875. {
  4876. IF_FAILEXIT(hr = HrSafeToEncodeToCP(pwszTrim, cpID));
  4877. if (MIME_S_CHARSET_CONFLICT == hr)
  4878. goto exit;
  4879. }
  4880. HdrGetRichEditText(GetDlgItem(m_hwnd, idTXTKeywords), wsz, ARRAYSIZE(wsz), FALSE);
  4881. pwszTrim = strtrimW(wsz);
  4882. if (*pwszTrim)
  4883. {
  4884. IF_FAILEXIT(hr = HrSafeToEncodeToCP(pwszTrim, cpID));
  4885. if (MIME_S_CHARSET_CONFLICT == hr)
  4886. goto exit;
  4887. }
  4888. if (hwnd = GetDlgItem(m_hwnd, idADApproved))
  4889. {
  4890. HdrGetRichEditText(hwnd, wsz, ARRAYSIZE(wsz), FALSE);
  4891. pwszTrim = strtrimW(wsz);
  4892. if (*pwszTrim)
  4893. {
  4894. IF_FAILEXIT(hr = HrSafeToEncodeToCP(pwszTrim, cpID));
  4895. if (MIME_S_CHARSET_CONFLICT == hr)
  4896. goto exit;
  4897. }
  4898. }
  4899. if (hwnd = GetDlgItem(m_hwnd, idTxtControl))
  4900. {
  4901. HdrGetRichEditText(hwnd, wsz, ARRAYSIZE(wsz), FALSE);
  4902. pwszTrim = strtrimW(wsz);
  4903. if (*pwszTrim)
  4904. {
  4905. IF_FAILEXIT(hr = HrSafeToEncodeToCP(pwszTrim, cpID));
  4906. if (MIME_S_CHARSET_CONFLICT == hr)
  4907. goto exit;
  4908. }
  4909. }
  4910. }
  4911. else
  4912. {
  4913. // ************************
  4914. // This portion only happens on save, so don't try to do for fCheckConflictOnly
  4915. // Anything not in this section had better be mirrored in the fCheckConflictOnly block above
  4916. // Place any ascii only stuff here.
  4917. // end of save only portion.
  4918. // *************************
  4919. HdrGetRichEditText(GetDlgItem(m_hwnd, idADNewsgroups), wsz, ARRAYSIZE(wsz), FALSE);
  4920. pwszTrim = strtrimW(wsz);
  4921. if (*pwszTrim)
  4922. {
  4923. // Bug #22455 - Make sure we strip spaces etc from between newsgroups
  4924. _ValidateNewsgroups(pwszTrim);
  4925. IF_FAILEXIT(hr = MimeOleSetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_NEWSGROUPS), NOFLAGS, pwszTrim));
  4926. }
  4927. HdrGetRichEditText(GetDlgItem(m_hwnd, idTXTFollowupTo), wsz, ARRAYSIZE(wsz), FALSE);
  4928. pwszTrim = strtrimW(wsz);
  4929. if (*pwszTrim)
  4930. {
  4931. IF_FAILEXIT(hr = MimeOleSetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_FOLLOWUPTO), NOFLAGS, pwszTrim));
  4932. }
  4933. HdrGetRichEditText(GetDlgItem(m_hwnd, idTXTDistribution), wsz, ARRAYSIZE(wsz), FALSE);
  4934. pwszTrim = strtrimW(wsz);
  4935. if (*pwszTrim)
  4936. {
  4937. IF_FAILEXIT(hr = MimeOleSetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_DISTRIB), NOFLAGS, pwszTrim));
  4938. }
  4939. HdrGetRichEditText(GetDlgItem(m_hwnd, idTXTKeywords), wsz, ARRAYSIZE(wsz), FALSE);
  4940. pwszTrim = strtrimW(wsz);
  4941. if (*pwszTrim)
  4942. {
  4943. IF_FAILEXIT(hr = MimeOleSetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_KEYWORDS), NOFLAGS, pwszTrim));
  4944. }
  4945. if (hwnd = GetDlgItem(m_hwnd, idADApproved))
  4946. {
  4947. HdrGetRichEditText(hwnd, wsz, ARRAYSIZE(wsz), FALSE);
  4948. pwszTrim = strtrimW(wsz);
  4949. if (*pwszTrim)
  4950. {
  4951. IF_FAILEXIT(hr = MimeOleSetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_APPROVED), NOFLAGS, pwszTrim));
  4952. }
  4953. }
  4954. if (hwnd = GetDlgItem(m_hwnd, idTxtControl))
  4955. {
  4956. HdrGetRichEditText(hwnd, wsz, ARRAYSIZE(wsz), FALSE);
  4957. pwszTrim = strtrimW(wsz);
  4958. if (*pwszTrim)
  4959. {
  4960. IF_FAILEXIT(hr = MimeOleSetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_CONTROL), NOFLAGS, pwszTrim));
  4961. }
  4962. }
  4963. }
  4964. exit:
  4965. return hr;
  4966. }
  4967. HRESULT CNoteHdr::HrSetNewsWabal(LPMIMEMESSAGE pMsg, LPWSTR pwszCC)
  4968. {
  4969. HRESULT hr = S_OK;
  4970. LPWABAL lpWabal = NULL;
  4971. ADDRESSLIST addrList = { 0 };
  4972. LPWSTR pwszEmail = NULL;
  4973. IMimeMessageW *pMsgW = NULL;
  4974. SafeRelease(m_lpWabal);
  4975. if (OENA_READ == m_ntNote)
  4976. {
  4977. // for a read note, just take the wabal from the message
  4978. IF_FAILEXIT(hr = HrGetWabalFromMsg(pMsg, &m_lpWabal));
  4979. }
  4980. else
  4981. {
  4982. TCHAR szReplyAddr[CCHMAX_EMAIL_ADDRESS];
  4983. TCHAR szEmailAddr[CCHMAX_EMAIL_ADDRESS];
  4984. // for a compose note, or a reply note we need to do some munging, so create a new wabal
  4985. IF_FAILEXIT(hr = HrCreateWabalObject(&m_lpWabal));
  4986. if (OENA_COMPOSE == m_ntNote)
  4987. {
  4988. ADRINFO rAdrInfo;
  4989. IF_FAILEXIT(hr = HrGetWabalFromMsg(pMsg, &lpWabal));
  4990. // just copy everything except From: and ReplyTo: because we'll add those later
  4991. if (lpWabal->FGetFirst(&rAdrInfo))
  4992. {
  4993. do
  4994. {
  4995. if (rAdrInfo.lRecipType != MAPI_ORIG && rAdrInfo.lRecipType != MAPI_REPLYTO)
  4996. IF_FAILEXIT(hr = m_lpWabal->HrAddEntry(&rAdrInfo));
  4997. }
  4998. while (lpWabal->FGetNext(&rAdrInfo));
  4999. }
  5000. }
  5001. // add replyto if necessary
  5002. if (m_pAccount)
  5003. {
  5004. if (SUCCEEDED(m_pAccount->GetPropSz(AP_NNTP_REPLY_EMAIL_ADDRESS, szReplyAddr, ARRAYSIZE(szReplyAddr))) &&
  5005. *szReplyAddr &&
  5006. SUCCEEDED(m_pAccount->GetPropSz(AP_NNTP_EMAIL_ADDRESS, szEmailAddr, ARRAYSIZE(szEmailAddr))) &&
  5007. lstrcmpi(szReplyAddr, szEmailAddr))
  5008. {
  5009. TCHAR szName[CCHMAX_DISPLAY_NAME];
  5010. if (SUCCEEDED(m_pAccount->GetPropSz(AP_NNTP_DISPLAY_NAME, szName, ARRAYSIZE(szName))))
  5011. IF_FAILEXIT(hr = m_lpWabal->HrAddEntryA(szName, szReplyAddr, MAPI_REPLYTO));
  5012. else
  5013. IF_FAILEXIT(hr = m_lpWabal->HrAddEntryA(szReplyAddr, szReplyAddr, MAPI_REPLYTO));
  5014. }
  5015. }
  5016. //Bug# 79066
  5017. if ((OENA_REPLYALL == m_ntNote) || m_fPoster)
  5018. {
  5019. if (FAILED(MimeOleParseRfc822AddressW(IAT_REPLYTO, pwszCC, &addrList)))
  5020. {
  5021. IF_FAILEXIT(hr = MimeOleParseRfc822AddressW(IAT_FROM, pwszCC, &addrList));
  5022. }
  5023. IF_NULLEXIT(pwszEmail = PszToUnicode(CP_ACP, addrList.prgAdr->pszEmail));
  5024. IF_FAILEXIT(hr = m_lpWabal->HrAddEntry(addrList.prgAdr->pszFriendlyW, pwszEmail, MAPI_TO));
  5025. }
  5026. }
  5027. // For the send note case, make sure that resolved addresses are valid.
  5028. // If display name and email address are the same, UnresolveOneOffs() will clear
  5029. // the email address to force a real resolve.
  5030. if ((OENA_COMPOSE == m_ntNote) || (OENA_WEBPAGE == m_ntNote) || OENA_STATIONERY == m_ntNote)
  5031. m_lpWabal->UnresolveOneOffs();
  5032. m_lpWabal->HrResolveNames(NULL, FALSE);
  5033. Assert(m_pAddrWells);
  5034. if (SUCCEEDED(hr = m_pAddrWells->HrSetWabal(m_lpWabal)))
  5035. hr = m_pAddrWells->HrDisplayWells(m_hwnd);
  5036. exit:
  5037. if (g_pMoleAlloc)
  5038. {
  5039. if (addrList.cAdrs)
  5040. g_pMoleAlloc->FreeAddressList(&addrList);
  5041. }
  5042. ReleaseObj(lpWabal);
  5043. MemFree(pwszEmail);
  5044. ReleaseObj(pMsgW);
  5045. return hr;
  5046. }
  5047. HRESULT CNoteHdr::HrSetReplySubject(LPMIMEMESSAGE pMsg, BOOL fReply)
  5048. {
  5049. WCHAR szNewSubject[cchMaxSubject+1];
  5050. LPWSTR pszNorm = NULL;
  5051. int cchPrefix;
  5052. LPCWSTR lpwReFwd = NULL;
  5053. MimeOleGetBodyPropW(pMsg, HBODY_ROOT, STR_ATT_NORMSUBJ, NOFLAGS, &pszNorm);
  5054. if (!!DwGetOption(OPT_HARDCODEDHDRS))
  5055. {
  5056. //Use english strings and not from resources
  5057. lpwReFwd = fReply ? c_wszRe : c_wszFwd;
  5058. StrCpyNW(szNewSubject, lpwReFwd, cchMaxSubject);
  5059. }
  5060. else
  5061. {
  5062. // pull in the new prefix from resource...
  5063. AthLoadStringW(fReply?idsPrefixReply:idsPrefixForward, szNewSubject, cchMaxSubject);
  5064. }
  5065. cchPrefix = lstrlenW(szNewSubject);
  5066. Assert(cchPrefix);
  5067. if (pszNorm)
  5068. {
  5069. StrCpyNW(szNewSubject+cchPrefix, pszNorm, min(lstrlenW(pszNorm), cchMaxSubject-cchPrefix)+1);
  5070. SafeMimeOleFree(pszNorm);
  5071. }
  5072. HdrSetRichEditText(GetDlgItem(m_hwnd, idTXTSubject), szNewSubject, FALSE);
  5073. return NOERROR;
  5074. }
  5075. #define FIsDelimiter(_ch) (_ch==L';' || _ch==L',' || _ch==L' ' || _ch==L'\r' || _ch==L'\n' || _ch == L'\t')
  5076. void _ValidateNewsgroups(LPWSTR pszGroups)
  5077. {
  5078. LPWSTR pszDst = pszGroups;
  5079. BOOL fInGroup = FALSE;
  5080. WCHAR ch;
  5081. Assert(pszGroups);
  5082. while (ch = *pszGroups++)
  5083. {
  5084. if (FIsDelimiter(ch))
  5085. {
  5086. if (fInGroup)
  5087. {
  5088. while ((ch = *pszGroups) && FIsDelimiter(ch))
  5089. pszGroups++;
  5090. if (ch)
  5091. *pszDst++ = L',';
  5092. fInGroup = FALSE;
  5093. }
  5094. }
  5095. else
  5096. {
  5097. *pszDst++ = ch;
  5098. fInGroup = TRUE;
  5099. }
  5100. }
  5101. *pszDst = 0;
  5102. }
  5103. HRESULT CNoteHdr::HrQueryToolbarButtons(DWORD dwFlags, const GUID *pguidCmdGroup, OLECMD* pOleCmd)
  5104. {
  5105. pOleCmd->cmdf = 0;
  5106. if (NULL == pguidCmdGroup)
  5107. {
  5108. switch (pOleCmd->cmdID)
  5109. {
  5110. case OLECMDID_CUT:
  5111. pOleCmd->cmdf = QS_ENABLED(dwFlags&edfEditHasSelAndIsRW);
  5112. break;
  5113. case OLECMDID_PASTE:
  5114. pOleCmd->cmdf = QS_ENABLED(dwFlags&edfPaste);
  5115. break;
  5116. case OLECMDID_SELECTALL:
  5117. pOleCmd->cmdf = QS_ENABLED(TRUE);
  5118. break;
  5119. case OLECMDID_COPY:
  5120. pOleCmd->cmdf = QS_ENABLED(dwFlags&edfEditHasSel);
  5121. break;
  5122. case OLECMDID_UNDO:
  5123. pOleCmd->cmdf = QS_ENABLED(dwFlags&edfUndo);
  5124. break;
  5125. }
  5126. }
  5127. else if (IsEqualGUID(CMDSETID_OutlookExpress, *pguidCmdGroup))
  5128. {
  5129. switch (pOleCmd->cmdID)
  5130. {
  5131. case ID_CUT:
  5132. pOleCmd->cmdf = QS_ENABLED(dwFlags&edfEditHasSelAndIsRW);
  5133. break;
  5134. case ID_PASTE:
  5135. pOleCmd->cmdf = QS_ENABLED(dwFlags&edfPaste);
  5136. break;
  5137. case ID_SELECT_ALL:
  5138. pOleCmd->cmdf = QS_ENABLED(TRUE);
  5139. break;
  5140. case ID_NOTE_COPY:
  5141. case ID_COPY:
  5142. pOleCmd->cmdf = QS_ENABLED(dwFlags&edfEditHasSel);
  5143. break;
  5144. case ID_UNDO:
  5145. pOleCmd->cmdf = QS_ENABLED(dwFlags&edfUndo);
  5146. break;
  5147. }
  5148. }
  5149. return NOERROR;
  5150. }
  5151. void CNoteHdr::OnButtonClick(int idBtn)
  5152. {
  5153. UINT cch;
  5154. LPTSTR pszGroups;
  5155. //CPickGroupDlg* ppgd;
  5156. switch (idBtn)
  5157. {
  5158. case idbtnTo:
  5159. if (m_fMail)
  5160. HrPickNames(0);
  5161. else
  5162. HrPickGroups(idADNewsgroups, FALSE);
  5163. break;
  5164. case idbtnFollowup:
  5165. HrPickGroups(idTXTFollowupTo, TRUE);
  5166. break;
  5167. case idbtnCc:
  5168. if (m_fMail)
  5169. HrPickNames(1);
  5170. else
  5171. HrPickNames(0);
  5172. break;
  5173. case idbtnBCc:
  5174. HrPickNames(2);
  5175. break;
  5176. case idbtnReplyTo:
  5177. HrPickNames(1);
  5178. break;
  5179. }
  5180. }
  5181. void CNoteHdr::HrPickGroups(int idWell, BOOL fFollowUpTo)
  5182. {
  5183. UINT cch;
  5184. DWORD cServer = 0;
  5185. HWND hwnd;
  5186. LPSTR pszGroups=NULL;
  5187. LPWSTR pwszGroups=NULL;
  5188. CPickGroupDlg *ppgd;
  5189. CHAR szAccount[CCHMAX_ACCOUNT_NAME];
  5190. g_pAcctMan->GetAccountCount(ACCT_NEWS, &cServer);
  5191. // BUGBUG Sometimes m_pAccount is an IMAP server, so we want to also
  5192. // test that we have at least one news server. This is a known problem
  5193. // that was punted a long time ago.
  5194. if (!m_pAccount || !cServer)
  5195. {
  5196. AthMessageBoxW (m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrConfigureServer), NULL, MB_OK);
  5197. return;
  5198. }
  5199. hwnd = GetDlgItem(m_hwnd, idWell);
  5200. if (S_OK == HrGetFieldText(&pwszGroups, hwnd))
  5201. {
  5202. // Since this function doesn't fail, just make sure that we
  5203. // don't do anything funky when PszToANSI and PszToUnicode fails.
  5204. pszGroups = PszToANSI(GetACP(), pwszGroups);
  5205. }
  5206. ppgd = new CPickGroupDlg;
  5207. if (ppgd)
  5208. {
  5209. FOLDERID idServer = FOLDERID_INVALID;
  5210. m_pAccount->GetPropSz(AP_ACCOUNT_ID, szAccount, sizeof(szAccount));
  5211. // find the parent folder id of the account
  5212. if (SUCCEEDED(g_pStore->FindServerId(szAccount, &idServer)) &&
  5213. ppgd->FCreate(m_hwnd, idServer, &pszGroups, fFollowUpTo) &&
  5214. pszGroups)
  5215. {
  5216. SafeMemFree(pwszGroups);
  5217. pwszGroups = PszToUnicode(CP_ACP, pszGroups);
  5218. HdrSetRichEditText(hwnd, pwszGroups != NULL ? pwszGroups : c_wszEmpty, FALSE);
  5219. }
  5220. ppgd->Release();
  5221. }
  5222. MemFree(pwszGroups);
  5223. MemFree(pszGroups);
  5224. }
  5225. HRESULT CNoteHdr::HrPickNames(int iwell)
  5226. {
  5227. HRESULT hr = NOERROR;
  5228. if (IsReadOnly())
  5229. return hr;
  5230. Assert(m_lpWabal);
  5231. Assert(m_pAddrWells);
  5232. //We need to setmodify so that it is marked as dirty. In a normal case,
  5233. //the user would have typed in and hence set modify would have happenned automatically
  5234. if (m_fPoster)
  5235. {
  5236. Edit_SetModify(GetDlgItem(m_hwnd, idADCc), TRUE);
  5237. }
  5238. hr=m_pAddrWells->HrSelectNames(m_hwnd, iwell, m_fMail?FALSE:TRUE);
  5239. if (SUCCEEDED(hr))
  5240. {
  5241. // Check to see if need to show advanced headers.
  5242. if (0 < GetRichEditTextLen(GetDlgItem(m_hwnd, idADBCc)))
  5243. ShowAdvancedHeaders(TRUE);
  5244. }
  5245. else if (hr!=MAPI_E_USER_CANCEL)
  5246. AthMessageBoxW (m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrPickNames), NULL, MB_OK);
  5247. return hr;
  5248. }
  5249. HRESULT CNoteHdr::HrGetAccountInHeader(IImnAccount **ppAcct)
  5250. {
  5251. HRESULT hr = E_FAIL;
  5252. IImnAccount *pAcct = NULL;
  5253. ULONG cAccount = 0;
  5254. HWND hwndCombo = GetDlgItem(m_hwnd, idFromCombo);
  5255. // If the combo box is being used then get the account info from it.
  5256. if (SUCCEEDED(g_pAcctMan->GetAccountCount(m_fMail?ACCT_MAIL:ACCT_NEWS, &cAccount)) &&
  5257. (cAccount > 1) && hwndCombo)
  5258. {
  5259. LPSTR szAcctID = NULL;
  5260. ULONG i = ComboBox_GetCurSel(hwndCombo);
  5261. szAcctID = (LPSTR)SendMessage(hwndCombo, CB_GETITEMDATA, WPARAM(i), 0);
  5262. hr = g_pAcctMan->FindAccount(AP_ACCOUNT_ID, szAcctID, &pAcct);
  5263. }
  5264. // Get default account from MsgSite
  5265. if (FAILED(hr) && m_pHeaderSite)
  5266. {
  5267. IOEMsgSite *pMsgSite = NULL;
  5268. IServiceProvider *pServ = NULL;
  5269. hr = m_pHeaderSite->QueryInterface(IID_IServiceProvider, (LPVOID*)&pServ);
  5270. if (SUCCEEDED(hr))
  5271. {
  5272. hr = pServ->QueryService(IID_IOEMsgSite, IID_IOEMsgSite, (LPVOID*)&pMsgSite);
  5273. pServ->Release();
  5274. }
  5275. if (SUCCEEDED(hr))
  5276. {
  5277. hr = pMsgSite->GetDefaultAccount(m_fMail?ACCT_MAIL:ACCT_NEWS, &pAcct);
  5278. pMsgSite->Release();
  5279. }
  5280. }
  5281. // Get global default. Used in failure case and in Envelope (WordMail, etc) case
  5282. if (FAILED(hr))
  5283. hr = g_pAcctMan->GetDefaultAccount(m_fMail?ACCT_MAIL:ACCT_NEWS, &pAcct);
  5284. if (SUCCEEDED(hr))
  5285. {
  5286. AssertSz(pAcct, "How is it that we succeeded, yet we don't have an account???");
  5287. ReplaceInterface((*ppAcct), pAcct);
  5288. }
  5289. else if (E_FAIL == hr)
  5290. hr = HR_E_COULDNOTFINDACCOUNT;
  5291. ReleaseObj(pAcct);
  5292. return hr;
  5293. }
  5294. HRESULT CNoteHdr::HrFillMessage(IMimeMessage *pMsg)
  5295. {
  5296. IUnknown *punk;
  5297. IPersistMime *pPM = NULL;
  5298. HRESULT hr;
  5299. if (m_pEnvelopeSite)
  5300. punk = m_pEnvelopeSite;
  5301. else
  5302. punk = m_pHeaderSite;
  5303. AssertSz(punk, "You need either a HeaderSite or an EnvelopeSite");
  5304. hr = punk->QueryInterface(IID_IPersistMime, (LPVOID*)&pPM);
  5305. if (SUCCEEDED(hr))
  5306. {
  5307. hr = pPM->Save(pMsg, 0);
  5308. ReleaseObj(pPM);
  5309. if (hr == MAPI_E_USER_CANCEL)
  5310. goto Exit;
  5311. }
  5312. else
  5313. // If can't get a IPersistMime, need to fake the save through the m_pEnvelopeSite
  5314. // The only time the QI for IPersistMime doesn't work is if you have an m_pEnvelopeSite
  5315. // that doesn't support IPersistMime. If you have a m_pHeaderSite, QI should always work.
  5316. {
  5317. LPSTREAM pstm;
  5318. HBODY hBodyHtml = 0;
  5319. AssertSz(m_pEnvelopeSite, "If the QI didn't work, then must be an envelope site.");
  5320. // We need to select the charset before we save the message
  5321. pMsg->SetCharset(m_hCharset, CSET_APPLY_ALL);
  5322. hr = Save(pMsg, 0);
  5323. if (FAILED(hr))
  5324. goto Exit;
  5325. // Word will call our GetAttach function during this call to GetBody so save m_pMsgSend
  5326. // so that we can inline attaches that Word sends to us.
  5327. m_pMsgSend = pMsg;
  5328. if (SUCCEEDED(_GetMsoBody(ENV_BODY_HTML, &pstm)))
  5329. {
  5330. pMsg->SetTextBody(TXT_HTML, IET_INETCSET, NULL, pstm, &hBodyHtml);
  5331. pstm->Release();
  5332. }
  5333. if (SUCCEEDED(_GetMsoBody(ENV_BODY_TEXT, &pstm)))
  5334. {
  5335. pMsg->SetTextBody(TXT_PLAIN, IET_INETCSET, hBodyHtml, pstm, NULL);
  5336. pstm->Release();
  5337. }
  5338. m_pMsgSend = NULL;
  5339. }
  5340. Exit:
  5341. return hr;
  5342. }
  5343. HRESULT CNoteHdr::_GetMsoBody(ULONG uBody, LPSTREAM *ppstm)
  5344. {
  5345. LPSTREAM pstm=NULL;
  5346. HRESULT hr;
  5347. *ppstm = NULL;
  5348. IF_FAILEXIT(hr = MimeOleCreateVirtualStream(&pstm));
  5349. IF_FAILEXIT(hr = m_pEnvelopeSite->GetBody(pstm, uCodePageFromCharset(m_hCharset), uBody));
  5350. *ppstm = pstm;
  5351. pstm = NULL;
  5352. exit:
  5353. ReleaseObj(pstm);
  5354. return hr;
  5355. }
  5356. #ifdef YST
  5357. // this check produced a 4 bugs in OE 5.01 and 5.5 and I disaable it (YST)
  5358. HRESULT CNoteHdr::_CheckMsoBodyCharsetConflict(CODEPAGEID cpID)
  5359. {
  5360. HRESULT hr = S_OK;
  5361. LPSTREAM pstm = NULL;
  5362. BSTR bstrText = NULL;
  5363. ULONG cbToRead = 0,
  5364. cbRead = 0;
  5365. IF_FAILEXIT(hr = MimeOleCreateVirtualStream(&pstm));
  5366. hr = m_pEnvelopeSite->GetBody(pstm, CP_UNICODE, ENV_BODY_TEXT);
  5367. // bobn; Raid 81900; 6/30/99
  5368. // Excel (and powerpoint?) don't have a text body.
  5369. // Check that there is an HTML body and we can have
  5370. // it in unicode.
  5371. if(FAILED(hr))
  5372. IF_FAILEXIT(hr = m_pEnvelopeSite->GetBody(pstm, CP_UNICODE, ENV_BODY_HTML));
  5373. IF_FAILEXIT(hr = HrIStreamToBSTR(CP_UNICODE, pstm, &bstrText));
  5374. hr = HrSafeToEncodeToCP((LPWSTR)bstrText, cpID);
  5375. exit:
  5376. SysFreeString(bstrText);
  5377. ReleaseObj(pstm);
  5378. return hr;
  5379. }
  5380. #endif //YST
  5381. HRESULT CNoteHdr::HrCheckSendInfo()
  5382. {
  5383. HRESULT hr;
  5384. BOOL fOneOrMoreGroups = FALSE,
  5385. fOneOrMoreNames = FALSE;
  5386. hr = HrCheckNames(FALSE, TRUE);
  5387. if (FAILED(hr))
  5388. {
  5389. if ((MAPI_E_USER_CANCEL != hr) && (hrNoRecipients != hr))
  5390. hr = hrBadRecipients;
  5391. if (hrNoRecipients != hr)
  5392. goto Exit;
  5393. }
  5394. else
  5395. fOneOrMoreNames = TRUE;
  5396. // If we didn't find any email recipients, don't need to check if valid.
  5397. if (SUCCEEDED(hr) && m_lpWabal)
  5398. hr = m_lpWabal->IsValidForSending();
  5399. // Only check groups if:
  5400. // 1- Have succeeded to this point or didn't have any email recipients
  5401. // 2- In a news header
  5402. if ((SUCCEEDED(hr) || (hrNoRecipients == hr)) && !m_fMail)
  5403. {
  5404. hr = HrCheckGroups(TRUE);
  5405. if (SUCCEEDED(hr))
  5406. fOneOrMoreGroups = TRUE;
  5407. }
  5408. if (FAILED(hr))
  5409. goto Exit;
  5410. hr = HrCheckSubject(!fOneOrMoreGroups);
  5411. if (FAILED(hr))
  5412. goto Exit;
  5413. // TODO:
  5414. if (m_pHeaderSite && m_pHeaderSite->IsHTML() == S_OK)
  5415. {
  5416. // if a HTML message, then let's make sure there's no plain-text recipients
  5417. if (fOneOrMoreNames)
  5418. {
  5419. hr = HrIsCoolToSendHTML();
  5420. if (hr == S_FALSE && m_pHeaderSite)
  5421. // send plain-text only...
  5422. m_pHeaderSite->SetHTML(FALSE);
  5423. }
  5424. if (fOneOrMoreGroups &&
  5425. (IDCANCEL == DoDontShowMeAgainDlg(m_hwnd, c_szDSHTMLNewsWarning, MAKEINTRESOURCE(idsAthena),
  5426. MAKEINTRESOURCE(idsErrHTMLInNewsIsBad), MB_OKCANCEL)))
  5427. hr = MAPI_E_USER_CANCEL;
  5428. }
  5429. Exit:
  5430. return hr;
  5431. }
  5432. HRESULT CNoteHdr::HrSend(void)
  5433. {
  5434. HRESULT hr;
  5435. IMimeMessage *pMsg = NULL;
  5436. IOEMsgSite *pMsgSite = NULL;
  5437. if (m_pEnvelopeSite)
  5438. {
  5439. // With the envelope site, must check to see if things set up at this point to use mail
  5440. hr = ProcessICW(m_hwnd, FOLDER_LOCAL, TRUE);
  5441. if (hr == S_FALSE)
  5442. // user cancelled out of config wizard so we can't continue
  5443. hr = MAPI_E_USER_CANCEL;
  5444. if (FAILED(hr))
  5445. goto error;
  5446. m_fSendImmediate = TRUE;
  5447. }
  5448. hr = HrCreateMessage(&pMsg);
  5449. if (FAILED(hr))
  5450. goto error;
  5451. // The only case where this will happen is if no accounts are configured. Just to make
  5452. // sure, call the ICW and then try to get the default account.
  5453. if (!m_pAccount)
  5454. {
  5455. hr = ProcessICW(m_hwnd, m_fMail ? FOLDER_LOCAL : FOLDER_NEWS, TRUE);
  5456. if (FAILED(hr))
  5457. goto error;
  5458. if (FAILED(g_pAcctMan->GetDefaultAccount(m_fMail?ACCT_MAIL:ACCT_NEWS, &m_pAccount)))
  5459. {
  5460. hr = HR_E_COULDNOTFINDACCOUNT;
  5461. goto error;
  5462. }
  5463. }
  5464. hr = HrCheckSendInfo();
  5465. if (FAILED(hr))
  5466. goto error;
  5467. // Does IPersistMime save stuff
  5468. hr = HrFillMessage(pMsg);
  5469. if (FAILED(hr))
  5470. goto error;
  5471. if (m_pHeaderSite)
  5472. {
  5473. IOEMsgSite *pMsgSite = NULL;
  5474. IServiceProvider *pServ = NULL;
  5475. hr = m_pHeaderSite->QueryInterface(IID_IServiceProvider, (LPVOID*)&pServ);
  5476. if (SUCCEEDED(hr))
  5477. {
  5478. hr = pServ->QueryService(IID_IOEMsgSite, IID_IOEMsgSite, (LPVOID*)&pMsgSite);
  5479. pServ->Release();
  5480. }
  5481. if (SUCCEEDED(hr))
  5482. {
  5483. if (!m_fMail && IsReplyNote() && !DwGetDontShowAgain(c_szDSReplyNews))
  5484. {
  5485. LRESULT id = DoDontShowMeAgainDlg(m_hwnd, c_szDSReplyNews,
  5486. MAKEINTRESOURCE(idsPostNews),
  5487. MAKEINTRESOURCE(idsReplyToNewsGroup),
  5488. MB_YESNO);
  5489. if (IDNO == id || IDCANCEL == id)
  5490. hr = hrUserCancel;
  5491. else
  5492. hr = pMsgSite->SendToOutbox(pMsg, m_fSendImmediate, m_pHeaderSite);
  5493. }
  5494. else
  5495. {
  5496. hr = pMsgSite->SendToOutbox(pMsg, m_fSendImmediate, m_pHeaderSite);
  5497. }
  5498. pMsgSite->Release();
  5499. }
  5500. }
  5501. // We are in office Envelope
  5502. else
  5503. {
  5504. COEMsgSite *pMsgSite = NULL;
  5505. CStoreCB *pCB = NULL;
  5506. pMsgSite = new COEMsgSite();
  5507. if (!pMsgSite)
  5508. hr = E_OUTOFMEMORY;
  5509. pCB = new CStoreCB;
  5510. if (!pCB)
  5511. hr = E_OUTOFMEMORY;
  5512. if (SUCCEEDED(hr))
  5513. hr = pCB->Initialize(m_hwndParent, MAKEINTRESOURCE(idsSendingToOutbox), TRUE);
  5514. if (SUCCEEDED(hr))
  5515. {
  5516. INIT_MSGSITE_STRUCT rInitStruct;
  5517. rInitStruct.dwInitType = OEMSIT_MSG;
  5518. rInitStruct.folderID = FOLDERID_INVALID;
  5519. rInitStruct.pMsg = pMsg;
  5520. hr = pMsgSite->Init(&rInitStruct);
  5521. }
  5522. if (SUCCEEDED(hr))
  5523. hr = pMsgSite->SetStoreCallback(pCB);
  5524. if (SUCCEEDED(hr))
  5525. {
  5526. hr = pMsgSite->SendToOutbox(pMsg, m_fSendImmediate, m_pHeaderSite);
  5527. if (E_PENDING == hr)
  5528. hr = pCB->Block();
  5529. pCB->Close();
  5530. }
  5531. if (SUCCEEDED(hr))
  5532. {
  5533. m_pEnvelopeSite->CloseNote(ENV_CLOSE_SEND);
  5534. ShowWindow(m_hwnd, SW_HIDE);
  5535. }
  5536. if (pMsgSite)
  5537. {
  5538. pMsgSite->Close();
  5539. pMsgSite->Release();
  5540. }
  5541. ReleaseObj(pCB);
  5542. }
  5543. error:
  5544. if (FAILED(hr))
  5545. {
  5546. int idsErr = -1;
  5547. m_fSecurityInited = FALSE;
  5548. switch (hr)
  5549. {
  5550. case hrNoRecipients:
  5551. if(!m_fMail)
  5552. hr = HR_E_POST_WITHOUT_NEWS; // idsErr = idsErrPostWithoutNewsgroup;
  5553. break;
  5554. case HR_E_COULDNOTFINDACCOUNT:
  5555. if(!m_fMail)
  5556. hr = HR_E_CONFIGURE_SERVER; //idsErr = idsErrConfigureServer;
  5557. break;
  5558. case HR_E_ATHSEC_FAILED:
  5559. case hrUserCancel:
  5560. case MAPI_E_USER_CANCEL:
  5561. idsErr = 0;
  5562. break;
  5563. case HR_E_ATHSEC_NOCERTTOSIGN:
  5564. case MIME_E_SECURITY_NOSIGNINGCERT:
  5565. idsErr = 0;
  5566. if(DialogBoxParam(g_hLocRes,
  5567. MAKEINTRESOURCE(iddErrSecurityNoSigningCert), m_hwnd,
  5568. ErrSecurityNoSigningCertDlgProc, NULL) == idGetDigitalIDs)
  5569. GetDigitalIDs(m_pAccount);
  5570. break;
  5571. default:
  5572. // idsErr = m_fMail?idsErrSendMail:NULL; // ~~~ Should we have a default for news?
  5573. break;
  5574. }
  5575. if (idsErr != 0)
  5576. {
  5577. AthErrorMessageW(m_hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrSendMail), hr);
  5578. if ((hr == hrNoRecipients) || (hr == HR_E_POST_WITHOUT_NEWS))
  5579. SetInitFocus(FALSE);
  5580. }
  5581. }
  5582. ReleaseObj(pMsg);
  5583. return hr;
  5584. }
  5585. HRESULT CNoteHdr::HrCheckSubject(BOOL fMail)
  5586. {
  5587. HWND hwnd;
  5588. if ((hwnd=GetDlgItem(m_hwnd, idTXTSubject)) && GetRichEditTextLen(hwnd)==0)
  5589. {
  5590. if (IDCANCEL == DoDontShowMeAgainDlg(m_hwnd, fMail?c_szRegMailEmptySubj:c_szRegNewsEmptySubj,
  5591. MAKEINTRESOURCE(idsAthena),
  5592. MAKEINTRESOURCE(fMail?idsWarnMailEmptySubj:idsWarnNewsEmptySubj),
  5593. MB_OKCANCEL))
  5594. {
  5595. ::SetFocus(hwnd);
  5596. return MAPI_E_USER_CANCEL;
  5597. }
  5598. }
  5599. return NOERROR;
  5600. }
  5601. HRESULT CNoteHdr::HrIsCoolToSendHTML()
  5602. {
  5603. HRESULT hr=S_OK;
  5604. ADRINFO adrInfo;
  5605. BOOL fPlainText=FALSE;
  5606. int id;
  5607. // check for plaintext people
  5608. if (m_lpWabal->FGetFirst(&adrInfo))
  5609. {
  5610. do
  5611. {
  5612. if (adrInfo.fPlainText)
  5613. {
  5614. fPlainText=TRUE;
  5615. break;
  5616. }
  5617. }
  5618. while (m_lpWabal->FGetNext(&adrInfo));
  5619. }
  5620. if (fPlainText)
  5621. {
  5622. id = (int) DialogBox(g_hLocRes, MAKEINTRESOURCE(iddPlainRecipWarning), m_hwnd, _PlainWarnDlgProc);
  5623. if (id == IDNO)
  5624. return S_FALSE;
  5625. else
  5626. if (id == IDCANCEL)
  5627. return MAPI_E_USER_CANCEL;
  5628. else
  5629. return S_OK;
  5630. }
  5631. return hr;
  5632. }
  5633. INT_PTR CALLBACK _PlainWarnDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  5634. {
  5635. int id;
  5636. switch (msg)
  5637. {
  5638. case WM_INITDIALOG:
  5639. CenterDialog(hwnd);
  5640. return TRUE;
  5641. case WM_COMMAND:
  5642. id = GET_WM_COMMAND_ID(wParam, lParam);
  5643. if (id == IDYES || id == IDNO || id == IDCANCEL)
  5644. {
  5645. EndDialog(hwnd, id);
  5646. break;
  5647. }
  5648. }
  5649. return FALSE;
  5650. }
  5651. static HACCEL g_hAccelMailSend=0;
  5652. // This should only get called from the envelope as a send note
  5653. HACCEL CNoteHdr::GetAcceleratorTable()
  5654. {
  5655. Assert(!IsReadOnly());
  5656. Assert(m_pEnvelopeSite);
  5657. if (!g_hAccelMailSend)
  5658. g_hAccelMailSend = LoadAccelerators(g_hLocRes, MAKEINTRESOURCE(IDA_SEND_HDR_ACCEL));
  5659. return g_hAccelMailSend;
  5660. }
  5661. HRESULT CNoteHdr::HrInitSecurityOptions(LPMIMEMESSAGE pMsg, ULONG ulSecurityType)
  5662. {
  5663. HRESULT hr;
  5664. if (!m_fSecurityInited)
  5665. {
  5666. if (SUCCEEDED(hr = ::HrInitSecurityOptions(pMsg, ulSecurityType)))
  5667. m_fSecurityInited = TRUE;
  5668. }
  5669. else
  5670. hr = S_OK;
  5671. return hr;
  5672. }
  5673. HRESULT CNoteHdr::HrHandleSecurityIDMs(BOOL fDigSign)
  5674. {
  5675. IMimeBody *pBody;
  5676. PROPVARIANT var;
  5677. HRESULT hr;
  5678. if (fDigSign)
  5679. m_fDigSigned = !m_fDigSigned;
  5680. else
  5681. m_fEncrypted = !m_fEncrypted;
  5682. if(m_fForceEncryption && m_fDigSigned)
  5683. m_fEncrypted = TRUE;
  5684. hr = HrUpdateSecurity();
  5685. return hr;
  5686. }
  5687. HRESULT CNoteHdr::HrInitSecurity()
  5688. {
  5689. HRESULT hr = S_OK;
  5690. // Constructor set these flags to false so don't need to handle else case
  5691. if (OENA_READ != m_ntNote && m_fMail)
  5692. {
  5693. m_fDigSigned = DwGetOption(OPT_MAIL_DIGSIGNMESSAGES);
  5694. m_fEncrypted = DwGetOption(OPT_MAIL_ENCRYPTMESSAGES);
  5695. }
  5696. return hr;
  5697. }
  5698. HRESULT CNoteHdr::HrUpdateSecurity(LPMIMEMESSAGE pMsg)
  5699. {
  5700. RECT rc;
  5701. HRESULT hr = NOERROR;
  5702. LPWSTR psz = NULL;
  5703. HWND hEdit;
  5704. switch (m_ntNote)
  5705. {
  5706. case OENA_READ:
  5707. case OENA_REPLYTOAUTHOR:
  5708. case OENA_REPLYTONEWSGROUP:
  5709. case OENA_REPLYALL:
  5710. case OENA_FORWARD:
  5711. case OENA_FORWARDBYATTACH:
  5712. if (pMsg)
  5713. {
  5714. CleanupSECSTATE(&m_SecState);
  5715. HrGetSecurityState(pMsg, &m_SecState, NULL);
  5716. m_fDigSigned = IsSigned(m_SecState.type);
  5717. m_fEncrypted = IsEncrypted(m_SecState.type);
  5718. // RAID 12243. Added these two flags for broken and untrusted messages
  5719. if(m_ntNote == OENA_READ)
  5720. {
  5721. m_fSignTrusted = IsSignTrusted(&m_SecState);
  5722. m_fEncryptionOK = IsEncryptionOK(&m_SecState);
  5723. }
  5724. }
  5725. break;
  5726. case OENA_COMPOSE:
  5727. if (pMsg)
  5728. {
  5729. // Make certain that the highest security of (current message, option defaults) is applied.
  5730. //
  5731. CleanupSECSTATE(&m_SecState);
  5732. HrGetSecurityState(pMsg, &m_SecState, NULL);
  5733. if (! m_fDigSigned)
  5734. {
  5735. m_fDigSigned = IsSigned(m_SecState.type);
  5736. }
  5737. if (! m_fEncrypted)
  5738. {
  5739. m_fEncrypted = IsEncrypted(m_SecState.type);
  5740. }
  5741. }
  5742. break;
  5743. default: // do nothing
  5744. break;
  5745. }
  5746. hEdit = GetDlgItem(m_hwnd, idSecurity);
  5747. if (hEdit)
  5748. {
  5749. PHCI phci = (HCI*)GetWindowLongPtr(hEdit, GWLP_USERDATA);
  5750. // BUG 17788: need to set the text even if it is null
  5751. // since that will delete old security line text.
  5752. psz = SzGetDisplaySec(pMsg, NULL);
  5753. HdrSetRichEditText(hEdit, psz, FALSE);
  5754. phci->fEmpty = (0 == *psz);
  5755. }
  5756. m_fThisHeadDigSigned = m_fDigSigned;
  5757. m_fThisHeadEncrypted = m_fEncrypted;
  5758. // if(!m_fDigSigned)
  5759. // m_fForceEncryption = FALSE;
  5760. InvalidateRightMargin(0);
  5761. ReLayout();
  5762. if (m_pHeaderSite)
  5763. m_pHeaderSite->Update();
  5764. if (m_hwndToolbar)
  5765. {
  5766. Assert(m_pEnvelopeSite);
  5767. if (m_fDigSigned)
  5768. SendMessage(m_hwndToolbar, TB_SETSTATE, ID_DIGITALLY_SIGN, MAKELONG(TBSTATE_ENABLED | TBSTATE_PRESSED, 0));
  5769. else
  5770. SendMessage(m_hwndToolbar, TB_SETSTATE, ID_DIGITALLY_SIGN, MAKELONG(TBSTATE_ENABLED, 0));
  5771. if(m_fForceEncryption && m_fDigSigned)
  5772. SendMessage(m_hwndToolbar, TB_SETSTATE, ID_ENCRYPT, MAKELONG(TBSTATE_PRESSED, 0));
  5773. else if (m_fEncrypted)
  5774. SendMessage(m_hwndToolbar, TB_SETSTATE, ID_ENCRYPT, MAKELONG(TBSTATE_ENABLED | TBSTATE_PRESSED, 0));
  5775. else
  5776. SendMessage(m_hwndToolbar, TB_SETSTATE, ID_ENCRYPT, MAKELONG(TBSTATE_ENABLED, 0));
  5777. }
  5778. return hr;
  5779. }
  5780. HRESULT CNoteHdr::HrSaveSecurity(LPMIMEMESSAGE pMsg)
  5781. {
  5782. HRESULT hr;
  5783. ULONG ulSecurityType = MST_CLASS_SMIME_V1;
  5784. if (m_fDigSigned)
  5785. ulSecurityType |= ((DwGetOption(OPT_OPAQUE_SIGN)) ? MST_THIS_BLOBSIGN : MST_THIS_SIGN);
  5786. else
  5787. ulSecurityType &= ~((DwGetOption(OPT_OPAQUE_SIGN)) ? MST_THIS_BLOBSIGN : MST_THIS_SIGN);
  5788. if (m_fEncrypted)
  5789. ulSecurityType |= MST_THIS_ENCRYPT;
  5790. else
  5791. ulSecurityType &= ~MST_THIS_ENCRYPT;
  5792. hr = HrInitSecurityOptions(pMsg, ulSecurityType);
  5793. return hr;
  5794. }
  5795. BOOL CNoteHdr::IsReadOnly()
  5796. {
  5797. if (m_ntNote==OENA_READ)
  5798. return TRUE;
  5799. else
  5800. return FALSE;
  5801. }
  5802. HRESULT CNoteHdr::HrViewContacts()
  5803. {
  5804. LPWAB lpWab;
  5805. if (!FAILED (HrCreateWabObject (&lpWab)))
  5806. {
  5807. // launch wab in modal-mode if a) container is modal or b) running as office envelope
  5808. lpWab->HrBrowse (m_hwnd, m_fOfficeInit ? TRUE : (m_pHeaderSite ? (m_pHeaderSite->IsModal() == S_OK) : FALSE));
  5809. lpWab->Release ();
  5810. }
  5811. else
  5812. AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsGeneralWabError), NULL, MB_OK);
  5813. return NOERROR;
  5814. }
  5815. BOOL CNoteHdr::FDoCutCopyPaste(int wmCmd)
  5816. {
  5817. HWND hwndFocus=GetFocus();
  5818. // only if it's one of our kids..
  5819. if (GetParent(hwndFocus)==m_hwnd)
  5820. {
  5821. SendMessage(hwndFocus, wmCmd, 0, 0);
  5822. return TRUE;
  5823. }
  5824. return FALSE;
  5825. }
  5826. HRESULT CNoteHdr::GetTabStopArray(HWND *rgTSArray, int *pcArrayCount)
  5827. {
  5828. Assert(rgTSArray);
  5829. Assert(pcArrayCount);
  5830. int *array;
  5831. int cCount;
  5832. if (m_fMail)
  5833. {
  5834. if (IsReadOnly())
  5835. {
  5836. array = rgIDTabOrderMailRead;
  5837. cCount = sizeof(rgIDTabOrderMailRead)/sizeof(int);
  5838. }
  5839. else
  5840. {
  5841. array = rgIDTabOrderMailSend;
  5842. cCount = sizeof(rgIDTabOrderMailSend)/sizeof(int);
  5843. }
  5844. }
  5845. else
  5846. {
  5847. if (IsReadOnly())
  5848. {
  5849. array = rgIDTabOrderNewsRead;
  5850. cCount = sizeof(rgIDTabOrderNewsRead)/sizeof(int);
  5851. }
  5852. else
  5853. {
  5854. array = rgIDTabOrderNewsSend;
  5855. cCount = sizeof(rgIDTabOrderNewsSend)/sizeof(int);
  5856. }
  5857. }
  5858. AssertSz(cCount <= *pcArrayCount, "Do you need to change MAX_HEADER_COMP in note.h?");
  5859. for (int i = 0; i < cCount; i++)
  5860. *rgTSArray++ = GetDlgItem(m_hwnd, *array++);
  5861. *pcArrayCount = cCount;
  5862. return S_OK;
  5863. }
  5864. HRESULT CNoteHdr::SetFlagState(MARK_TYPE markType)
  5865. {
  5866. BOOL fDoRelayout = FALSE;
  5867. switch (markType)
  5868. {
  5869. case MARK_MESSAGE_FLAGGED:
  5870. case MARK_MESSAGE_UNFLAGGED:
  5871. {
  5872. BOOL fFlagged = (MARK_MESSAGE_FLAGGED == markType);
  5873. if (m_fFlagged != fFlagged)
  5874. {
  5875. fDoRelayout = TRUE;
  5876. m_fFlagged = fFlagged;
  5877. }
  5878. break;
  5879. }
  5880. case MARK_MESSAGE_WATCH:
  5881. case MARK_MESSAGE_IGNORE:
  5882. case MARK_MESSAGE_NORMALTHREAD:
  5883. if (m_MarkType != markType)
  5884. {
  5885. fDoRelayout = TRUE;
  5886. m_MarkType = markType;
  5887. }
  5888. break;
  5889. }
  5890. if (fDoRelayout)
  5891. {
  5892. InvalidateStatus();
  5893. ReLayout();
  5894. if (m_pHeaderSite)
  5895. m_pHeaderSite->Update();
  5896. }
  5897. return S_OK;
  5898. }
  5899. HRESULT CNoteHdr::ShowEnvOptions()
  5900. {
  5901. nyi("Header options are not implemented yet.");
  5902. return S_OK;
  5903. }
  5904. void CNoteHdr::ReLayout()
  5905. {
  5906. RECT rc;
  5907. if (m_fSkipLayout)
  5908. return;
  5909. GetClientRect(m_hwnd, &rc);
  5910. SetPosOfControls(rc.right, TRUE);
  5911. InvalidateRect(m_hwnd, &rc, TRUE);
  5912. DOUTL(PAINTING_DEBUG_LEVEL, "STATE Invalidating:(%d,%d) for (%d,%d)", rc.left, rc.top, rc.right, rc.bottom);
  5913. }
  5914. //IDropTarget
  5915. HRESULT CNoteHdr::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  5916. {
  5917. LPENUMFORMATETC penum = NULL;
  5918. HRESULT hr;
  5919. FORMATETC fmt;
  5920. ULONG ulCount = 0;
  5921. if (m_lpAttMan->HrIsDragSource() == S_OK)
  5922. {
  5923. *pdwEffect=DROPEFFECT_NONE;
  5924. return S_OK;
  5925. }
  5926. if (!pdwEffect || !pDataObj)
  5927. return E_INVALIDARG;
  5928. m_dwEffect = DROPEFFECT_NONE;
  5929. // lets get the enumerator from the IDataObject, and see if the format we take is
  5930. // available
  5931. hr = pDataObj->EnumFormatEtc(DATADIR_GET, &penum);
  5932. if (SUCCEEDED(hr) && penum)
  5933. {
  5934. hr = penum->Reset();
  5935. while (SUCCEEDED(hr=penum->Next(1, &fmt, &ulCount)) && ulCount)
  5936. {
  5937. if ( fmt.cfFormat==CF_HDROP ||
  5938. fmt.cfFormat==CF_FILEDESCRIPTORA ||
  5939. fmt.cfFormat==CF_FILEDESCRIPTORW)
  5940. {
  5941. // we take either a CF_FILEDESCRIPTOR from the shell, or a CF_HDROP...
  5942. //by default, or a move if the shift key is down
  5943. if ( (*pdwEffect) & DROPEFFECT_COPY )
  5944. m_dwEffect = DROPEFFECT_COPY;
  5945. if ( ((*pdwEffect) & DROPEFFECT_MOVE) &&
  5946. (grfKeyState & MK_SHIFT))
  5947. m_dwEffect=DROPEFFECT_MOVE;
  5948. // IE3 gives us a link
  5949. // if ONLY link is specified, default to a copy
  5950. if (*pdwEffect == DROPEFFECT_LINK)
  5951. m_dwEffect=DROPEFFECT_LINK;
  5952. m_cfAccept=fmt.cfFormat;
  5953. if (m_cfAccept==CF_FILEDESCRIPTORW) // this is the richest format we take, if we find one of these, no point looking any
  5954. break; // further...
  5955. }
  5956. }
  5957. }
  5958. ReleaseObj(penum);
  5959. *pdwEffect = m_dwEffect;
  5960. m_grfKeyState = grfKeyState;
  5961. return S_OK;
  5962. }
  5963. HRESULT CNoteHdr::DragOver(DWORD grfKeyState,POINTL pt, DWORD *pdwEffect)
  5964. {
  5965. if (m_lpAttMan->HrIsDragSource() == S_OK)
  5966. {
  5967. *pdwEffect=DROPEFFECT_NONE;
  5968. return S_OK;
  5969. }
  5970. if ( m_dwEffect == DROPEFFECT_NONE) // we're not taking drops at all...
  5971. {
  5972. *pdwEffect = m_dwEffect;
  5973. return NOERROR;
  5974. }
  5975. // Cool, we've accepted the drag this far... now we
  5976. // have to watch to see if it turns into a copy or move...
  5977. // as before, take the copy as default or move if the
  5978. // shft key is down
  5979. if ((*pdwEffect)&DROPEFFECT_COPY)
  5980. m_dwEffect=DROPEFFECT_COPY;
  5981. if (((*pdwEffect)&DROPEFFECT_MOVE)&&
  5982. (grfKeyState&MK_SHIFT))
  5983. m_dwEffect=DROPEFFECT_MOVE;
  5984. if (*pdwEffect==DROPEFFECT_LINK) // if it's link ONLY, like IE3 gives, then fine...
  5985. m_dwEffect=DROPEFFECT_LINK;
  5986. *pdwEffect &= m_dwEffect;
  5987. m_grfKeyState=grfKeyState;
  5988. return NOERROR;
  5989. }
  5990. HRESULT CNoteHdr::DragLeave()
  5991. {
  5992. return NOERROR;
  5993. }
  5994. HRESULT CNoteHdr::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  5995. {
  5996. HRESULT hr = E_FAIL;
  5997. FORMATETC fmte = {m_cfAccept, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  5998. STGMEDIUM medium;
  5999. *pdwEffect = m_dwEffect;
  6000. if ( m_dwEffect != DROPEFFECT_NONE )
  6001. {
  6002. // If this is us sourcing the drag, just bail. We may want to save the
  6003. // points of the icons.
  6004. //
  6005. if (m_lpAttMan->HrIsDragSource() == S_OK)
  6006. {
  6007. *pdwEffect=DROPEFFECT_NONE;
  6008. return S_OK;
  6009. }
  6010. if ( (m_grfKeyState & MK_RBUTTON) &&
  6011. m_lpAttMan->HrGetRequiredAction(pdwEffect, pt))
  6012. return E_FAIL;
  6013. if (pDataObj &&
  6014. SUCCEEDED(pDataObj->GetData(&fmte, &medium)))
  6015. {
  6016. if (m_cfAccept==CF_HDROP)
  6017. {
  6018. HDROP hdrop=(HDROP)GlobalLock(medium.hGlobal);
  6019. hr=m_lpAttMan->HrDropFiles(hdrop, (*pdwEffect)&DROPEFFECT_LINK);
  6020. GlobalUnlock(medium.hGlobal);
  6021. }
  6022. else
  6023. if (m_cfAccept==CF_FILEDESCRIPTORA || m_cfAccept==CF_FILEDESCRIPTORW)
  6024. {
  6025. // all file descriptors are copy|more, link makes no sense, as they are are
  6026. // memory object, ie. non-existent in fat.
  6027. hr=m_lpAttMan->HrDropFileDescriptor(pDataObj, FALSE);
  6028. }
  6029. #ifdef DEBUG
  6030. else
  6031. AssertSz(0, "how did this clipformat get accepted??");
  6032. #endif
  6033. if (medium.pUnkForRelease)
  6034. medium.pUnkForRelease->Release();
  6035. else
  6036. GlobalFree(medium.hGlobal);
  6037. }
  6038. }
  6039. return hr;
  6040. }
  6041. HRESULT CNoteHdr::HrGetAttachCount(ULONG *pcAttach)
  6042. {
  6043. return m_lpAttMan->HrGetAttachCount(pcAttach);
  6044. }
  6045. HRESULT CNoteHdr::HrIsDragSource()
  6046. {
  6047. return m_lpAttMan->HrIsDragSource();
  6048. }
  6049. HRESULT CNoteHdr::UnloadAll()
  6050. {
  6051. if (m_lpAttMan)
  6052. {
  6053. m_lpAttMan->HrUnload();
  6054. m_lpAttMan->HrClearDirtyFlag();
  6055. }
  6056. for (int i=0; i<(int)m_cHCI; i++)
  6057. {
  6058. if (0 == (m_rgHCI[i].dwFlags & HCF_ATTACH))
  6059. {
  6060. if (0 == (m_rgHCI[i].dwFlags & HCF_COMBO))
  6061. HdrSetRichEditText(GetDlgItem(m_hwnd, m_rgHCI[i].idEdit), c_wszEmpty, FALSE);
  6062. else
  6063. SetWindowText(GetDlgItem(m_hwnd, m_rgHCI[i].idEdit), "");
  6064. }
  6065. }
  6066. m_fDirty = FALSE;
  6067. m_pri = priNorm;
  6068. return S_OK;
  6069. }
  6070. void CNoteHdr::SetDirtyFlag()
  6071. {
  6072. if (!m_fStillLoading)
  6073. {
  6074. m_fDirty = TRUE;
  6075. if (m_pEnvelopeSite)
  6076. m_pEnvelopeSite->OnPropChange(dispidSomething);
  6077. }
  6078. }
  6079. void CNoteHdr::SetPosOfControls(int headerWidth, BOOL fChangeVisibleStates)
  6080. {
  6081. int cx,
  6082. cy,
  6083. cyDirty,
  6084. cyLabelDirty,
  6085. oldWidth = 0,
  6086. windowPosFlags = SETWINPOS_DEF_FLAGS,
  6087. editWidth = headerWidth - m_cxLeftMargin - GetRightMargin(FALSE);
  6088. RECT rc;
  6089. HWND hwnd;
  6090. PHCI phci = m_rgHCI;
  6091. BOOL fRePosition = FALSE;
  6092. if ((headerWidth < 5) || (m_fSkipLayout))
  6093. return;
  6094. STACK("SetPosOfControls (header width, edit width)", headerWidth, editWidth);
  6095. // size the dialog
  6096. GetClientRect(m_hwnd, &rc);
  6097. cyDirty = rc.bottom;
  6098. cyLabelDirty = rc.bottom;
  6099. if (fChangeVisibleStates)
  6100. windowPosFlags |= SWP_SHOWWINDOW;
  6101. cy = BeginYPos();
  6102. for (int i=0; i<(int)m_cHCI; i++, phci++)
  6103. {
  6104. hwnd = GetDlgItem(m_hwnd, phci->idEdit);
  6105. if (hwnd)
  6106. {
  6107. if (S_OK == HrFShowHeader(phci))
  6108. {
  6109. int newLabelCY = (phci->dwFlags & HCF_BORDER) ? cy + 2*cyBorder : cy;
  6110. BOOL fLabelMoved = FALSE;
  6111. if (phci->cy != cy)
  6112. {
  6113. int smcy = ((INVALID_PHCI_Y != phci->cy) && (phci->cy < cy)) ? phci->cy : cy;
  6114. if (cyLabelDirty > smcy)
  6115. cyLabelDirty = smcy;
  6116. phci->cy = cy;
  6117. fLabelMoved = TRUE;
  6118. }
  6119. // Is an attachment
  6120. if (HCF_ATTACH & phci->dwFlags)
  6121. {
  6122. DWORD cyAttMan = 0;
  6123. RECT rc;
  6124. m_lpAttMan->HrGetHeight(editWidth, &cyAttMan);
  6125. if (cyAttMan > MAX_ATTACH_PIXEL_HEIGHT)
  6126. cyAttMan = MAX_ATTACH_PIXEL_HEIGHT;
  6127. cyAttMan += 4*cyBorder;
  6128. cyDirty = cy;
  6129. rc.left = m_cxLeftMargin;
  6130. rc.right = m_cxLeftMargin + editWidth;
  6131. rc.top = cy;
  6132. rc.bottom = cy + cyAttMan;
  6133. m_lpAttMan->HrSetSize(&rc);
  6134. if ((cyAttMan != (DWORD)phci->height) && (cyDirty > cy))
  6135. cyDirty = cy;
  6136. AssertSz(cyAttMan != 0, "Setting this to zero would be a bummer...");
  6137. phci->height = cyAttMan;
  6138. cy += cyAttMan + ControlYBufferSize();
  6139. }
  6140. // Is either an edit or combo
  6141. else
  6142. {
  6143. int newHeight = phci->height,
  6144. ctrlHeight = GetCtrlHeight(hwnd);
  6145. oldWidth = GetCtrlWidth(hwnd);
  6146. if (HCF_COMBO & phci->dwFlags)
  6147. {
  6148. if (ctrlHeight != newHeight)
  6149. {
  6150. fRePosition = TRUE;
  6151. phci->height = ctrlHeight;
  6152. newHeight = GetControlSize(TRUE, NUM_COMBO_LINES);
  6153. }
  6154. else
  6155. {
  6156. fRePosition = fRePosition || fLabelMoved || (oldWidth != editWidth);
  6157. if (fRePosition)
  6158. newHeight = GetControlSize(TRUE, NUM_COMBO_LINES);
  6159. }
  6160. }
  6161. else
  6162. {
  6163. fRePosition = fRePosition || fLabelMoved || (oldWidth != editWidth) || (ctrlHeight != newHeight);
  6164. }
  6165. if (fRePosition)
  6166. {
  6167. SetWindowPos(hwnd, NULL, m_cxLeftMargin, cy, editWidth, newHeight, windowPosFlags);
  6168. // RAID 81136: The above SetWindowPos might change the width in such a way
  6169. // that the height now needs to change. We detect this condition below and
  6170. // cause another resize to handle the needed height change. This, of course,
  6171. // is only valid with the richedits.
  6172. if ((newHeight != phci->height) && (0 == (HCF_COMBO & phci->dwFlags)))
  6173. {
  6174. SetWindowPos(hwnd, NULL, m_cxLeftMargin, cy, editWidth, phci->height, windowPosFlags);
  6175. }
  6176. if (cyDirty > cy)
  6177. cyDirty = cy;
  6178. if (fLabelMoved)
  6179. InvalidateRect(hwnd, NULL, FALSE);
  6180. }
  6181. cy += phci->height + ControlYBufferSize();
  6182. }
  6183. }
  6184. else
  6185. {
  6186. phci->cy = INVALID_PHCI_Y;
  6187. if (fChangeVisibleStates)
  6188. SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_HIDEWINDOW);
  6189. }
  6190. }
  6191. }
  6192. DOUTL(RESIZING_DEBUG_LEVEL, "STATE resizing header (headerwidth=%d, cy=%d)", headerWidth, cy);
  6193. // don't send a poschanging, as we did all the work here, plus invalidation...
  6194. SetWindowPos(m_hwnd, NULL, NULL, NULL, headerWidth, cy,
  6195. SETWINPOS_DEF_FLAGS|SWP_NOMOVE|SWP_DRAWFRAME|SWP_FRAMECHANGED);
  6196. // notify the parent to resize the note...
  6197. if (m_pHeaderSite)
  6198. m_pHeaderSite->Resize();
  6199. if (m_pEnvelopeSite)
  6200. {
  6201. m_pEnvelopeSite->RequestResize(&cy);
  6202. }
  6203. GetRealClientRect(m_hwnd, &rc);
  6204. // Dirty the labels region
  6205. if (rc.bottom != cyLabelDirty)
  6206. {
  6207. rc.top = cyLabelDirty;
  6208. rc.right = m_cxLeftMargin;
  6209. rc.left = 0;
  6210. InvalidateRect(m_hwnd, &rc, TRUE);
  6211. DOUTL(PAINTING_DEBUG_LEVEL, "STATE Invalidating:(%d,%d) for (%d,%d)", rc.left, rc.top, rc.right, rc.bottom);
  6212. }
  6213. // Dirty the right margin if needed.
  6214. if (editWidth != oldWidth)
  6215. {
  6216. int rightMargin = (editWidth > oldWidth) ? editWidth - oldWidth : 0;
  6217. InvalidateRightMargin(rightMargin);
  6218. }
  6219. #ifdef DEBUG
  6220. DEBUGDumpHdr(m_hwnd, m_cHCI, m_rgHCI);
  6221. #endif
  6222. }
  6223. void CNoteHdr::InvalidateRightMargin(int additionalWidth)
  6224. {
  6225. RECT rc;
  6226. GetClientRect(m_hwnd, &rc);
  6227. rc.left = rc.right - GetRightMargin(TRUE) - additionalWidth;
  6228. InvalidateRect(m_hwnd, &rc, TRUE);
  6229. DOUTL(PAINTING_DEBUG_LEVEL, "STATE Invalidating:(%d,%d) for (%d,%d)", rc.left, rc.top, rc.right, rc.bottom);
  6230. }
  6231. HRESULT CNoteHdr::HrUpdateCachedHeight(HWND hwndEdit, RECT *prc)
  6232. {
  6233. int cyGrow,
  6234. cLines = (int) SendMessage(hwndEdit, EM_GETLINECOUNT, 0, 0);
  6235. BOOL fIncludeEdges = WS_EX_CLIENTEDGE & GetWindowLong(hwndEdit, GWL_EXSTYLE);
  6236. PHCI phci = (HCI*)GetWindowLongPtr(hwndEdit, GWLP_USERDATA);
  6237. if (prc->bottom < 0 || prc->top < 0)
  6238. return S_FALSE;
  6239. STACK("HrUpdateCachedHeight. Desired lines", cLines);
  6240. // Only allow between 1 and MAX_RICHEDIT_LINES lines
  6241. if (cLines < 1)
  6242. cLines = 1;
  6243. else if (cLines > MAX_RICHEDIT_LINES)
  6244. cLines = MAX_RICHEDIT_LINES;
  6245. DOUTL(RESIZING_DEBUG_LEVEL, "STATE Actual lines=%d", cLines);
  6246. // Figure out how many pixels cLines lines is
  6247. cyGrow = GetControlSize(fIncludeEdges, cLines);
  6248. // If these are different, then change is needed
  6249. if (cyGrow != GetCtrlHeight(hwndEdit))
  6250. phci->height = cyGrow;
  6251. else
  6252. return S_FALSE;
  6253. return S_OK;
  6254. }
  6255. void CNoteHdr::ShowControls()
  6256. {
  6257. PHCI phci = m_rgHCI;
  6258. STACK("ShowControls");
  6259. for (int i=0; i<(int)m_cHCI; i++, phci++)
  6260. {
  6261. HWND hwnd;
  6262. BOOL fHide;
  6263. fHide = (S_FALSE == HrFShowHeader(phci));
  6264. hwnd = GetDlgItem(m_hwnd, phci->idEdit);
  6265. if (hwnd)
  6266. ShowWindow(hwnd, fHide?SW_HIDE:SW_SHOW);
  6267. }
  6268. }
  6269. int CNoteHdr::GetRightMargin(BOOL fMax)
  6270. {
  6271. int margin = ControlXBufferSize();
  6272. if (fMax || m_fDigSigned || m_fEncrypted || m_fVCard)
  6273. margin += margin + cxBtn;
  6274. return margin;
  6275. }
  6276. // prc is in and out
  6277. DWORD CNoteHdr::GetButtonUnderMouse(int x, int y)
  6278. {
  6279. int resultButton = HDRCB_NO_BUTTON;
  6280. PHCI phci = m_rgHCI;
  6281. // Is it in the labels?
  6282. if ((x > int(ControlXBufferSize() - BUTTON_BUFFER)) && (x < int(m_cxLeftMargin - ControlXBufferSize() + BUTTON_BUFFER)))
  6283. {
  6284. for (int i=0; i<(int)m_cHCI; i++, phci++)
  6285. {
  6286. // Only check labels that have buttons that are showing
  6287. if ((0 != (phci->dwFlags & HCF_HASBUTTON)) && (INVALID_PHCI_Y != phci->cy))
  6288. {
  6289. if (y < (phci->cy))
  6290. break;
  6291. if (y < (phci->cy + 2*BUTTON_BUFFER + g_cyLabelHeight))
  6292. {
  6293. resultButton = i;
  6294. break;
  6295. }
  6296. }
  6297. }
  6298. }
  6299. else
  6300. // Is one of the right side buttons?
  6301. {
  6302. int width = GetCtrlWidth(m_hwnd),
  6303. xBuffSize = ControlXBufferSize(),
  6304. yBuffSize = ControlYBufferSize();
  6305. // Are we in the correct x range?
  6306. if ((x > (width - (xBuffSize + cxBtn + BUTTON_BUFFER))) && (x < width - xBuffSize + BUTTON_BUFFER))
  6307. {
  6308. BOOL rgBtnStates[] = {BUTTON_STATES};
  6309. BOOL rgUseButton[] = {BUTTON_USE_IN_COMPOSE};
  6310. BOOL fReadOnly = IsReadOnly();
  6311. int cy = BeginYPos();
  6312. for (int i = 0; i < ARRAYSIZE(rgBtnStates); i++)
  6313. {
  6314. if (rgBtnStates[i])
  6315. {
  6316. if (y < cy)
  6317. break;
  6318. if (y < (cy + cyBtn + 2*BUTTON_BUFFER))
  6319. {
  6320. if (fReadOnly || rgUseButton[i])
  6321. resultButton = g_rgBtnInd[i];
  6322. break;
  6323. }
  6324. cy += cyBtn + 2*BUTTON_BUFFER + yBuffSize;
  6325. }
  6326. }
  6327. }
  6328. }
  6329. return resultButton;
  6330. }
  6331. void CNoteHdr::GetButtonRect(DWORD iBtn, RECT *prc)
  6332. {
  6333. // Do we already have the rect?
  6334. if (iBtn == m_dwCurrentBtn)
  6335. {
  6336. CopyRect(prc, &m_rcCurrentBtn);
  6337. return;
  6338. }
  6339. // Buttons on the left hand side of the header
  6340. if (ButtonInLabels(iBtn))
  6341. {
  6342. AssertSz(iBtn < m_cHCI, "We are about to access an invalid element...");
  6343. int cyBegin = BeginYPos();
  6344. prc->top = m_rgHCI[iBtn].cy;
  6345. prc->bottom = m_rgHCI[iBtn].cy + g_cyLabelHeight + 2*BUTTON_BUFFER;
  6346. prc->left = ControlXBufferSize() - BUTTON_BUFFER;
  6347. prc->right = (m_cxLeftMargin - ControlXBufferSize()) + BUTTON_BUFFER;
  6348. DOUTL(PAINTING_DEBUG_LEVEL, "STATE Set New Button Frame for button (btn:%d):(%d,%d) to (%d,%d)",
  6349. iBtn, prc->left, prc->top, prc->right, prc->bottom);
  6350. }
  6351. // Buttons on the right hand side.
  6352. else
  6353. {
  6354. RECT rc;
  6355. int cx = GetCtrlWidth(m_hwnd) - (ControlXBufferSize() + cxBtn),
  6356. cy = BeginYPos(),
  6357. yBuffSize = cyBtn + ControlYBufferSize() + 2*BUTTON_BUFFER;
  6358. BOOL rgBtnStates[] = {BUTTON_STATES};
  6359. prc->left = cx - BUTTON_BUFFER;
  6360. prc->right = cx + cxBtn + BUTTON_BUFFER;
  6361. for (int i = 0; i < ARRAYSIZE(rgBtnStates); i++)
  6362. {
  6363. if (g_rgBtnInd[i] == iBtn)
  6364. {
  6365. prc->top = cy;
  6366. prc->bottom = cy + cyBtn + 2*BUTTON_BUFFER;
  6367. DOUTL(PAINTING_DEBUG_LEVEL, "STATE Set New Button Frame for button (btn:%d):(%d,%d) to (%d,%d)",
  6368. iBtn, prc->left, prc->top, prc->right, prc->bottom);
  6369. return;
  6370. }
  6371. else if (rgBtnStates[i])
  6372. cy += yBuffSize;
  6373. }
  6374. }
  6375. }
  6376. int CNoteHdr::BeginYPos()
  6377. {
  6378. int beginBuffer = m_dxTBOffset;
  6379. int cLines = 0;
  6380. if (m_fFlagged || (priLow == m_pri) || (priHigh == m_pri) || (MARK_MESSAGE_NORMALTHREAD != m_MarkType))
  6381. cLines++;
  6382. if (m_lpAttMan->GetUnsafeAttachCount())
  6383. cLines++;
  6384. if (cLines)
  6385. beginBuffer += GetStatusHeight(cLines) + g_cyFont/2;
  6386. return beginBuffer;
  6387. }
  6388. void CNoteHdr::HandleButtonClicks(int x, int y, int iBtn)
  6389. {
  6390. m_dwCurrentBtn = HDRCB_NO_BUTTON;
  6391. m_dwClickedBtn = HDRCB_NO_BUTTON;
  6392. HeaderRelease(TRUE);
  6393. InvalidateRect(m_hwnd, &m_rcCurrentBtn, FALSE);
  6394. if (HDRCB_NO_BUTTON == iBtn)
  6395. return;
  6396. switch (iBtn)
  6397. {
  6398. case HDRCB_VCARD:
  6399. HrShowVCardCtxtMenu(x, y);
  6400. break;
  6401. case HDRCB_SIGNED:
  6402. case HDRCB_ENCRYPT:
  6403. {
  6404. HrShowSecurityProperty(m_hwnd, m_pMsg);
  6405. break;
  6406. }
  6407. // This is an index into the labels
  6408. default:
  6409. OnButtonClick(m_rgHCI[iBtn].idBtn);
  6410. break;
  6411. }
  6412. }
  6413. void CNoteHdr::InvalidateStatus()
  6414. {
  6415. RECT rc;
  6416. GetClientRect(m_hwnd, &rc);
  6417. rc.bottom = BeginYPos();
  6418. InvalidateRect(m_hwnd, &rc, TRUE);
  6419. DOUTL(PAINTING_DEBUG_LEVEL, "STATE Invalidating:(%d,%d) for (%d,%d)", rc.left, rc.top, rc.right, rc.bottom);
  6420. }
  6421. HRESULT CNoteHdr::_CreateEnvToolbar()
  6422. {
  6423. UINT i;
  6424. RECT rc;
  6425. TCHAR szRes[CCHMAX_STRINGRES];
  6426. REBARBANDINFO rbbi;
  6427. POINT ptIdeal = {0};
  6428. // ~~~~ Do we need to do a WrapW here????
  6429. // create REBAR so we can show toolbar chevrons
  6430. m_hwndRebar = CreateWindowEx(0, REBARCLASSNAME, NULL,
  6431. WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN |
  6432. WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NOPARENTALIGN,
  6433. 0, 0, 100, 136, m_hwnd, NULL, g_hInst, NULL);
  6434. if (!m_hwndRebar)
  6435. return E_OUTOFMEMORY;
  6436. SendMessage(m_hwndRebar, RB_SETTEXTCOLOR, 0, (LPARAM)GetSysColor(COLOR_BTNTEXT));
  6437. SendMessage(m_hwndRebar, RB_SETBKCOLOR, 0, (LPARAM)GetSysColor(COLOR_BTNFACE));
  6438. //SendMessage(m_hwndRebar, RB_SETEXTENDEDSTYLE, RBS_EX_OFFICE9, RBS_EX_OFFICE9);
  6439. SendMessage(m_hwndRebar, CCM_SETVERSION, COMCTL32_VERSION, 0);
  6440. // ~~~~ Do we need to do a WrapW here????
  6441. m_hwndToolbar = CreateWindowEx(WS_EX_TOOLWINDOW, TOOLBARCLASSNAME, NULL,
  6442. WS_CHILD|WS_CLIPCHILDREN|WS_VISIBLE|CCS_NOPARENTALIGN|CCS_NODIVIDER|
  6443. TBSTYLE_TOOLTIPS|TBSTYLE_FLAT|TBSTYLE_LIST,
  6444. 0, 0, 0, 0, m_hwndRebar, NULL,
  6445. g_hInst, NULL);
  6446. if (!m_hwndToolbar)
  6447. return E_OUTOFMEMORY;
  6448. // set style on toolbar
  6449. SendMessage(m_hwndToolbar, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS);
  6450. SendMessage(m_hwndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
  6451. SendMessage(m_hwndToolbar, TB_ADDBUTTONS, (WPARAM)ARRAYSIZE(c_btnsOfficeEnvelope), (LPARAM)c_btnsOfficeEnvelope);
  6452. // set the normal imagelist, office toolbar has ONE only as it's always in Color
  6453. m_himl = LoadMappedToolbarBitmap(g_hLocRes, (fIsWhistler() ? ((GetCurColorRes() > 24) ? idb32SmBrowserHot : idbSmBrowserHot): idbNWSmBrowserHot), cxTBButton);
  6454. if (!m_himl)
  6455. return E_OUTOFMEMORY;
  6456. SendMessage(m_hwndToolbar, TB_SETIMAGELIST, 0, (LPARAM)m_himl);
  6457. SendMessage(m_hwndToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(cxTBButton, cxTBButton));
  6458. // Add text to the Bcc btn. The Send btn is taken care of in the Init
  6459. _SetButtonText(ID_ENV_BCC, MAKEINTRESOURCE(idsEnvBcc));
  6460. GetClientRect(m_hwndToolbar, &rc);
  6461. // get the IDEALSIZE of the toolbar
  6462. SendMessage(m_hwndToolbar, TB_GETIDEALSIZE, FALSE, (LPARAM)&ptIdeal);
  6463. // insert a band
  6464. ZeroMemory(&rbbi, sizeof(rbbi));
  6465. rbbi.cbSize = sizeof(REBARBANDINFO);
  6466. rbbi.fMask = RBBIM_SIZE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_STYLE;
  6467. rbbi.fStyle = RBBS_USECHEVRON;
  6468. rbbi.cx = 0;
  6469. rbbi.hwndChild = m_hwndToolbar;
  6470. rbbi.cxMinChild = 0;
  6471. rbbi.cyMinChild = rc.bottom;
  6472. rbbi.cxIdeal = ptIdeal.x;
  6473. SendMessage(m_hwndRebar, RB_INSERTBAND, (UINT)-1, (LPARAM)(LPREBARBANDINFO)&rbbi);
  6474. // set the toolbar offset
  6475. m_dxTBOffset = rc.bottom;
  6476. return S_OK;
  6477. }
  6478. HRESULT CNoteHdr::_LoadFromStream(IStream *pstm)
  6479. {
  6480. HRESULT hr;
  6481. IMimeMessage *pMsg;
  6482. IStream *pstmTmp,
  6483. *pstmMsg;
  6484. PERSISTHEADER rPersist;
  6485. ULONG cbRead;
  6486. CLSID clsid;
  6487. if (pstm == NULL)
  6488. return E_INVALIDARG;
  6489. HrRewindStream(pstm);
  6490. // make sure it's our GUID
  6491. if (ReadClassStm(pstm, &clsid)!=S_OK ||
  6492. !IsEqualCLSID(clsid, CLSID_OEEnvelope))
  6493. return E_FAIL;
  6494. // make sure the persistent header is the correct version
  6495. hr = pstm->Read(&rPersist, sizeof(PERSISTHEADER), &cbRead);
  6496. if (hr != S_OK || cbRead != sizeof(PERSISTHEADER) || rPersist.cbSize != sizeof(PERSISTHEADER))
  6497. return E_FAIL;
  6498. // read the message
  6499. hr = HrCreateMessage(&pMsg);
  6500. if (!FAILED(hr))
  6501. {
  6502. hr = MimeOleCreateVirtualStream(&pstmMsg);
  6503. if (!FAILED(hr))
  6504. {
  6505. // MimeOle always rewinds the stream we give it, so we have to copy the
  6506. // message from our persistent stream into another stream
  6507. hr = HrCopyStream(pstm, pstmMsg, NULL);
  6508. if (!FAILED(hr))
  6509. {
  6510. hr = pMsg->Load(pstmMsg);
  6511. if (!FAILED(hr))
  6512. {
  6513. hr = Load(pMsg);
  6514. if (!FAILED(hr))
  6515. {
  6516. // BUG: as we use an empty message to persist data for office envelope and empty mime-body can be
  6517. // considers a text/plain body part. We need to make sure we mark this as RENDERED before loading
  6518. // any attachments
  6519. if (pMsg->GetTextBody(TXT_PLAIN, IET_DECODED, &pstmTmp, NULL)==S_OK)
  6520. pstmTmp->Release();
  6521. hr = OnDocumentReady(pMsg);
  6522. }
  6523. }
  6524. }
  6525. pstmMsg->Release();
  6526. }
  6527. pMsg->Release();
  6528. }
  6529. return hr;
  6530. }
  6531. HRESULT CNoteHdr::_SetButtonText(int idmCmd, LPSTR pszText)
  6532. {
  6533. TBBUTTONINFO tbi;
  6534. TCHAR szRes[CCHMAX_STRINGRES];
  6535. ZeroMemory(&tbi, sizeof(TBBUTTONINFO));
  6536. tbi.cbSize = sizeof(TBBUTTONINFO);
  6537. tbi.dwMask = TBIF_TEXT | TBIF_STYLE;
  6538. tbi.fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE;
  6539. if (IS_INTRESOURCE(pszText))
  6540. {
  6541. // its a string resource id
  6542. LoadString(g_hLocRes, PtrToUlong(pszText), szRes, sizeof(szRes));
  6543. pszText = szRes;
  6544. }
  6545. tbi.pszText = pszText;
  6546. tbi.cchText = lstrlen(pszText);
  6547. SendMessage(m_hwndToolbar, TB_SETBUTTONINFO, idmCmd, (LPARAM) &tbi);
  6548. return S_OK;
  6549. }
  6550. HRESULT CNoteHdr::_ConvertOfficeCmdIDToOE(LPDWORD pdwCmdId)
  6551. {
  6552. static const CMDMAPING rgCmdMap[] =
  6553. { {cmdidSend, MSOEENVCMDID_SEND},
  6554. {cmdidCheckNames, MSOEENVCMDID_CHECKNAMES},
  6555. {cmdidAttach, MSOEENVCMDID_ATTACHFILE},
  6556. {cmdidSelectNames, MSOEENVCMDID_SELECTRECIPIENTS},
  6557. {cmdidFocusTo, MSOEENVCMDID_FOCUSTO},
  6558. {cmdidFocusCc, MSOEENVCMDID_FOCUSCC},
  6559. {cmdidFocusSubject, MSOEENVCMDID_FOCUSSUBJ}
  6560. };
  6561. for (int i=0; i<ARRAYSIZE(rgCmdMap); i++)
  6562. if (rgCmdMap[i].cmdIdOffice == *pdwCmdId)
  6563. {
  6564. *pdwCmdId = rgCmdMap[i].cmdIdOE;
  6565. return S_OK;
  6566. }
  6567. return E_FAIL;
  6568. }
  6569. HRESULT CNoteHdr::_UIActivate(BOOL fActive, HWND hwndFocus)
  6570. {
  6571. m_fUIActive = fActive;
  6572. if (fActive)
  6573. {
  6574. if (m_pHeaderSite)
  6575. m_pHeaderSite->OnUIActivate();
  6576. if (m_pMsoComponentMgr)
  6577. m_pMsoComponentMgr->FOnComponentActivate(m_dwComponentMgrID);
  6578. if (m_pEnvelopeSite)
  6579. {
  6580. m_pEnvelopeSite->OnEnvSetFocus();
  6581. m_pEnvelopeSite->DirtyToolbars();
  6582. }
  6583. }
  6584. else
  6585. {
  6586. // store focus if decativating
  6587. m_hwndLastFocus = hwndFocus;
  6588. if (m_pHeaderSite)
  6589. m_pHeaderSite->OnUIDeactivate(FALSE);
  6590. }
  6591. return S_OK;
  6592. }
  6593. HWND CNoteHdr::_GetNextDlgTabItem(HWND hwndDlg, HWND hwndFocus, BOOL fShift)
  6594. {
  6595. int i,
  6596. j,
  6597. idFocus = GetDlgCtrlID(hwndFocus),
  6598. iFocus;
  6599. LONG lStyle;
  6600. HWND hwnd;
  6601. // find current pos
  6602. for (i=0; i<ARRAYSIZE(rgIDTabOrderMailSend); i++)
  6603. {
  6604. if (rgIDTabOrderMailSend[i] == idFocus)
  6605. break;
  6606. }
  6607. // i now points to the current control's index
  6608. if (fShift)
  6609. {
  6610. // backwards
  6611. for (j=i-1; j>=0; j--)
  6612. {
  6613. hwnd = GetDlgItem(hwndDlg, rgIDTabOrderMailSend[j]);
  6614. AssertSz(hwnd, "something broke");
  6615. if (hwnd)
  6616. {
  6617. lStyle = GetWindowLong(hwnd, GWL_STYLE);
  6618. if ((lStyle & WS_VISIBLE) &&
  6619. (lStyle & WS_TABSTOP) &&
  6620. !(lStyle & WS_DISABLED))
  6621. return GetDlgItem(hwndDlg, rgIDTabOrderMailSend[j]);
  6622. }
  6623. }
  6624. }
  6625. else
  6626. {
  6627. // forwards tab
  6628. for (j=i+1; j<ARRAYSIZE(rgIDTabOrderMailSend); j++)
  6629. {
  6630. hwnd = GetDlgItem(hwndDlg, rgIDTabOrderMailSend[j]);
  6631. AssertSz(hwnd, "something broke");
  6632. if (hwnd)
  6633. {
  6634. lStyle = GetWindowLong(hwnd, GWL_STYLE);
  6635. if ((lStyle & WS_VISIBLE) &&
  6636. (lStyle & WS_TABSTOP) &&
  6637. !(lStyle & WS_DISABLED))
  6638. return GetDlgItem(hwndDlg, rgIDTabOrderMailSend[j]);
  6639. }
  6640. }
  6641. }
  6642. // not found
  6643. return NULL;
  6644. }
  6645. HRESULT CNoteHdr::_ClearDirtyFlag()
  6646. {
  6647. m_fDirty = FALSE;
  6648. if (m_lpAttMan)
  6649. m_lpAttMan->HrClearDirtyFlag();
  6650. return S_OK;
  6651. }
  6652. HRESULT CNoteHdr::_RegisterAsDropTarget(BOOL fOn)
  6653. {
  6654. HRESULT hr=S_OK;
  6655. if (fOn)
  6656. {
  6657. // already registered
  6658. if (!m_fDropTargetRegister)
  6659. {
  6660. hr = CoLockObjectExternal((LPDROPTARGET)this, TRUE, FALSE);
  6661. if (FAILED(hr))
  6662. goto error;
  6663. hr = RegisterDragDrop(m_hwnd, (LPDROPTARGET)this);
  6664. if (FAILED(hr))
  6665. goto error;
  6666. m_fDropTargetRegister=TRUE;
  6667. }
  6668. }
  6669. else
  6670. {
  6671. // nothing to do
  6672. if (m_fDropTargetRegister)
  6673. {
  6674. RevokeDragDrop(m_hwnd);
  6675. CoLockObjectExternal((LPUNKNOWN)(LPDROPTARGET)this, FALSE, TRUE);
  6676. m_fDropTargetRegister = FALSE;
  6677. }
  6678. }
  6679. error:
  6680. return hr;
  6681. }
  6682. HRESULT CNoteHdr::_RegisterWithFontCache(BOOL fOn)
  6683. {
  6684. Assert(g_pFieldSizeMgr);
  6685. if (fOn)
  6686. {
  6687. if (0 == m_dwFontNotify)
  6688. g_pFieldSizeMgr->Advise((IUnknown*)(IFontCacheNotify*)this, &m_dwFontNotify);
  6689. }
  6690. else
  6691. {
  6692. if (m_dwFontNotify)
  6693. {
  6694. g_pFieldSizeMgr->Unadvise(m_dwFontNotify);
  6695. m_dwFontNotify = NULL;
  6696. }
  6697. }
  6698. return S_OK;
  6699. }
  6700. HRESULT CNoteHdr::_RegisterWithComponentMgr(BOOL fOn)
  6701. {
  6702. MSOCRINFO crinfo;
  6703. IServiceProvider *pSP;
  6704. if (fOn)
  6705. {
  6706. // not registered, so get a component msgr interface and register ourselves
  6707. if (m_pMsoComponentMgr == NULL)
  6708. {
  6709. // negotiate an component msgr from the host
  6710. if (m_pEnvelopeSite &&
  6711. m_pEnvelopeSite->QueryInterface(IID_IServiceProvider, (LPVOID *)&pSP)==S_OK)
  6712. {
  6713. pSP->QueryService(IID_IMsoComponentManager, IID_IMsoComponentManager, (LPVOID *)&m_pMsoComponentMgr);
  6714. pSP->Release();
  6715. }
  6716. // if not host-provided, try and obtain from LoadLibrary on office dll
  6717. if (!m_pMsoComponentMgr &&
  6718. FAILED(MsoFGetComponentManager(&m_pMsoComponentMgr)))
  6719. return E_FAIL;
  6720. Assert (m_pMsoComponentMgr);
  6721. crinfo.cbSize = sizeof(MSOCRINFO);
  6722. crinfo.uIdleTimeInterval = 3000;
  6723. crinfo.grfcrf = msocrfPreTranslateAll;
  6724. crinfo.grfcadvf = msocadvfRedrawOff;
  6725. if (!m_pMsoComponentMgr->FRegisterComponent((IMsoComponent*) this, &crinfo, &m_dwComponentMgrID))
  6726. return E_FAIL;
  6727. }
  6728. }
  6729. else
  6730. {
  6731. if (m_pMsoComponentMgr)
  6732. {
  6733. m_pMsoComponentMgr->FRevokeComponent(m_dwComponentMgrID);
  6734. m_pMsoComponentMgr->Release();
  6735. m_pMsoComponentMgr = NULL;
  6736. m_dwComponentMgrID = 0;
  6737. }
  6738. }
  6739. return S_OK;
  6740. }
  6741. HRESULT ParseFollowup(LPMIMEMESSAGE pMsg, LPTSTR* ppszGroups, BOOL* pfPoster)
  6742. {
  6743. LPTSTR pszToken, pszTok;
  6744. BOOL fFirst = TRUE,
  6745. fPoster = FALSE;
  6746. int cchFollowup;
  6747. LPSTR lpszFollowup=0;
  6748. ADDRESSLIST addrList={0};
  6749. HRESULT hr = S_OK;
  6750. *ppszGroups = NULL;
  6751. if (!pMsg)
  6752. return E_INVALIDARG;
  6753. if (FAILED(MimeOleGetBodyPropA(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_FOLLOWUPTO), NOFLAGS, &lpszFollowup)))
  6754. return E_FAIL;
  6755. cchFollowup = lstrlen(lpszFollowup) + 1;
  6756. if (!MemAlloc((LPVOID*) ppszGroups, sizeof(TCHAR) * cchFollowup))
  6757. {
  6758. hr = E_OUTOFMEMORY;
  6759. goto exit;
  6760. }
  6761. **ppszGroups = 0;
  6762. // WARNING: we about to trash lpszFollowup with strtok...
  6763. // Walk through the string parsing out the tokens
  6764. pszTok = lpszFollowup;
  6765. pszToken = StrTokEx(&pszTok, GRP_DELIMITERS);
  6766. while (NULL != pszToken)
  6767. {
  6768. // Want to add all items except Poster (c_szPosterKeyword)
  6769. if (0 == lstrcmpi(pszToken, c_szPosterKeyword))
  6770. fPoster = TRUE;
  6771. else
  6772. {
  6773. if (!fFirst)
  6774. {
  6775. StrCatBuff(*ppszGroups, g_szComma, cchFollowup);
  6776. }
  6777. else
  6778. fFirst = FALSE;
  6779. StrCatBuff(*ppszGroups, pszToken, cchFollowup);
  6780. }
  6781. pszToken = StrTokEx(&pszTok, GRP_DELIMITERS);
  6782. }
  6783. *pfPoster = fPoster;
  6784. exit:
  6785. SafeMimeOleFree(lpszFollowup);
  6786. if (**ppszGroups == 0)
  6787. {
  6788. MemFree(*ppszGroups);
  6789. *ppszGroups = NULL;
  6790. }
  6791. return hr;
  6792. }
  6793. //***************************************************
  6794. CFieldSizeMgr::CFieldSizeMgr(IUnknown *pUnkOuter) : CPrivateUnknown(pUnkOuter)
  6795. {
  6796. TraceCall("CFieldSizeMgr::CFieldSizeMgr");
  6797. m_pAdviseRegistry = NULL;
  6798. m_fFontsChanged = FALSE;
  6799. m_dwFontNotify = 0;
  6800. InitializeCriticalSection(&m_rAdviseCritSect);
  6801. }
  6802. //***************************************************
  6803. CFieldSizeMgr::~CFieldSizeMgr()
  6804. {
  6805. IConnectionPoint *pCP = NULL;
  6806. TraceCall("CFieldSizeMgr::~CFieldSizeMgr");
  6807. EnterCriticalSection(&m_rAdviseCritSect);
  6808. if (m_pAdviseRegistry)
  6809. m_pAdviseRegistry->Release();
  6810. LeaveCriticalSection(&m_rAdviseCritSect);
  6811. if (g_lpIFontCache)
  6812. {
  6813. if (SUCCEEDED(g_lpIFontCache->QueryInterface(IID_IConnectionPoint, (LPVOID*)&pCP)))
  6814. {
  6815. pCP->Unadvise(m_dwFontNotify);
  6816. pCP->Release();
  6817. }
  6818. }
  6819. DeleteCriticalSection(&m_rAdviseCritSect);
  6820. }
  6821. //***************************************************
  6822. HRESULT CFieldSizeMgr::OnPreFontChange(void)
  6823. {
  6824. DWORD cookie = 0;
  6825. IFontCacheNotify* pCurr;
  6826. IUnknown* pTempCurr;
  6827. TraceCall("CFieldSizeMgr::OnPreFontChange");
  6828. EnterCriticalSection(&m_rAdviseCritSect);
  6829. while(SUCCEEDED(m_pAdviseRegistry->GetNext(LD_FORWARD, &pTempCurr, &cookie)))
  6830. {
  6831. if (SUCCEEDED(pTempCurr->QueryInterface(IID_IFontCacheNotify, (LPVOID *)&pCurr)))
  6832. {
  6833. pCurr->OnPreFontChange();
  6834. pCurr->Release();
  6835. }
  6836. pTempCurr->Release();
  6837. }
  6838. LeaveCriticalSection(&m_rAdviseCritSect);
  6839. return S_OK;
  6840. }
  6841. //***************************************************
  6842. HRESULT CFieldSizeMgr::OnPostFontChange(void)
  6843. {
  6844. DWORD cookie = 0;
  6845. IFontCacheNotify* pCurr;
  6846. IUnknown* pTempCurr;
  6847. TraceCall("CFieldSizeMgr::OnPostFontChange");
  6848. ResetGlobalSizes();
  6849. EnterCriticalSection(&m_rAdviseCritSect);
  6850. while(SUCCEEDED(m_pAdviseRegistry->GetNext(LD_FORWARD, &pTempCurr, &cookie)))
  6851. {
  6852. if (SUCCEEDED(pTempCurr->QueryInterface(IID_IFontCacheNotify, (LPVOID *)&pCurr)))
  6853. {
  6854. pCurr->OnPostFontChange();
  6855. pCurr->Release();
  6856. }
  6857. pTempCurr->Release();
  6858. }
  6859. LeaveCriticalSection(&m_rAdviseCritSect);
  6860. return S_OK;
  6861. }
  6862. //***************************************************
  6863. HRESULT CFieldSizeMgr::GetConnectionInterface(IID *pIID)
  6864. {
  6865. return E_NOTIMPL;
  6866. }
  6867. //***************************************************
  6868. HRESULT CFieldSizeMgr::GetConnectionPointContainer(IConnectionPointContainer **ppCPC)
  6869. {
  6870. *ppCPC = NULL;
  6871. return E_NOTIMPL;
  6872. }
  6873. //***************************************************
  6874. HRESULT CFieldSizeMgr::EnumConnections(IEnumConnections **ppEnum)
  6875. {
  6876. *ppEnum = NULL;
  6877. return E_NOTIMPL;
  6878. }
  6879. //***************************************************
  6880. HRESULT CFieldSizeMgr::Advise(IUnknown *pUnkSink, DWORD *pdwCookie)
  6881. {
  6882. TraceCall("CFieldSizeMgr::Advise");
  6883. EnterCriticalSection(&m_rAdviseCritSect);
  6884. HRESULT hr = m_pAdviseRegistry->AddItem(pUnkSink, pdwCookie);
  6885. LeaveCriticalSection(&m_rAdviseCritSect);
  6886. return hr;
  6887. }
  6888. //***************************************************
  6889. HRESULT CFieldSizeMgr::Unadvise(DWORD dwCookie)
  6890. {
  6891. TraceCall("CFieldSizeMgr::Unadvise");
  6892. EnterCriticalSection(&m_rAdviseCritSect);
  6893. HRESULT hr = m_pAdviseRegistry->RemoveItem(dwCookie);
  6894. LeaveCriticalSection(&m_rAdviseCritSect);
  6895. return hr;
  6896. }
  6897. //***************************************************
  6898. int CFieldSizeMgr::GetScalingFactor(void)
  6899. {
  6900. int iScaling = 100;
  6901. UINT cp;
  6902. cp = GetACP();
  6903. if((932 == cp) || (936 == cp) || (950 == cp) || (949 == cp) || (((1255 == cp) || (1256 == cp)) && (VER_PLATFORM_WIN32_NT != g_OSInfo.dwPlatformId)))
  6904. iScaling = 115;
  6905. return iScaling;
  6906. }
  6907. //***************************************************
  6908. void CFieldSizeMgr::ResetGlobalSizes(void)
  6909. {
  6910. HDC hdc;
  6911. HFONT hfontOld,
  6912. hfont;
  6913. TEXTMETRIC tm;
  6914. int oldcyFont = g_cyFont,
  6915. oldLabelHeight = g_cyLabelHeight,
  6916. cyScaledFont;
  6917. TraceCall("CFieldSizeMgr::ResetGlobalSizes");
  6918. // calc height of edit, based on font we're going to put in it...
  6919. hdc=GetDC(NULL);
  6920. hfont = GetFont(FALSE);
  6921. hfontOld=(HFONT)SelectObject(hdc, hfont); // Hopefully charset fonts are about the same size ???!!!
  6922. g_cfHeader.cbSize = sizeof(CHARFORMAT);
  6923. FontToCharformat(hfont, &g_cfHeader);
  6924. GetTextMetrics(hdc, &tm);
  6925. DOUTL(16, "tmHeight=%d tmAscent=%d tmDescent=%d tmInternalLeading=%d tmExternalLeading=%d\n",
  6926. tm.tmHeight, tm.tmAscent, tm.tmDescent, tm.tmInternalLeading, tm.tmExternalLeading);
  6927. SelectObject(hdc, hfontOld);
  6928. cyScaledFont = (tm.tmHeight + tm.tmExternalLeading) * GetScalingFactor();
  6929. if((cyScaledFont%100) >= 50)
  6930. cyScaledFont += 100;
  6931. g_cyFont = (cyScaledFont / 100);
  6932. g_cyLabelHeight = (g_cyFont < cyBtn) ? cyBtn : g_cyFont;
  6933. DOUTL(GEN_HEADER_DEBUG_LEVEL,"cyFont=%d", g_cyFont);
  6934. ReleaseDC(NULL, hdc);
  6935. m_fFontsChanged = ((oldcyFont != g_cyFont) || (oldLabelHeight != g_cyLabelHeight));
  6936. }
  6937. //***************************************************
  6938. HRESULT CFieldSizeMgr::Init(void)
  6939. {
  6940. HRESULT hr = S_OK;
  6941. IConnectionPoint *pCP = NULL;
  6942. TraceCall("CFieldSizeMgr::Init");
  6943. ResetGlobalSizes();
  6944. EnterCriticalSection(&m_rAdviseCritSect);
  6945. IF_FAILEXIT(hr = IUnknownList_CreateInstance(&m_pAdviseRegistry));
  6946. IF_FAILEXIT(hr = m_pAdviseRegistry->Init(NULL, 0, 0));
  6947. // We don't want to fail if the font cache is not created. That just means
  6948. // that the fonts won't be changed.
  6949. if (g_lpIFontCache)
  6950. {
  6951. IF_FAILEXIT(hr = g_lpIFontCache->QueryInterface(IID_IConnectionPoint, (LPVOID*)&pCP));
  6952. IF_FAILEXIT(hr = pCP->Advise((IUnknown*)(IFontCacheNotify*)this, &m_dwFontNotify));
  6953. }
  6954. exit:
  6955. ReleaseObj(pCP);
  6956. LeaveCriticalSection(&m_rAdviseCritSect);
  6957. return hr;
  6958. }
  6959. //***************************************************
  6960. HRESULT CFieldSizeMgr::PrivateQueryInterface(REFIID riid, LPVOID *lplpObj)
  6961. {
  6962. TraceCall("CFieldSizeMgr::PrivateQueryInterface");
  6963. if(!lplpObj)
  6964. return E_INVALIDARG;
  6965. *lplpObj = NULL;
  6966. if (IsEqualIID(riid, IID_IFontCacheNotify))
  6967. *lplpObj = (LPVOID)(IFontCacheNotify *)this;
  6968. else if (IsEqualIID(riid, IID_IConnectionPoint))
  6969. *lplpObj = (LPVOID)(IConnectionPoint *)this;
  6970. else
  6971. {
  6972. return E_NOINTERFACE;
  6973. }
  6974. AddRef();
  6975. return S_OK;
  6976. }