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.

711 lines
20 KiB

  1. /*
  2. * a t t m e n u. c p p
  3. *
  4. * Purpose:
  5. * Attachment menu
  6. *
  7. * History
  8. *
  9. * Copyright (C) Microsoft Corp. 1995, 1996.
  10. */
  11. #include <pch.hxx>
  12. #include "dllmain.h"
  13. #include "docobj.h"
  14. #include "resource.h"
  15. #include "shlwapi.h"
  16. #include "shlwapip.h"
  17. #include "mimeole.h"
  18. #include "mimeolep.h"
  19. #include "attmenu.h"
  20. #include "saveatt.h"
  21. #include <icutil.h>
  22. #include "demand.h"
  23. ASSERTDATA
  24. /*
  25. * e x t e r n s
  26. */
  27. /*
  28. * t y p e d e f s
  29. */
  30. /*
  31. * m a c r o s
  32. */
  33. /*
  34. * c o n s t a n t s
  35. */
  36. /*
  37. * g l o b a l s
  38. */
  39. static const TCHAR c_szSubThisPtr[]="AttMenu_SubThisPtr";
  40. /*
  41. * p r o t o t y p e s
  42. */
  43. CAttMenu::CAttMenu()
  44. {
  45. m_hMenu=NULL;
  46. m_cRef=1;
  47. m_hCharset=NULL;
  48. m_pFntCache=NULL;
  49. m_pFrame=NULL;
  50. m_pMsg=NULL;
  51. m_pfnWndProc=NULL;
  52. m_fShowingMenu=FALSE;
  53. m_pAttachVCard=NULL;
  54. m_pHostCmdTarget=NULL;
  55. m_cAttach = 0;
  56. m_cVisibleAttach = 0;
  57. m_cEnabledAttach = 0;
  58. m_fAllowUnsafe = FALSE;
  59. m_hVCard = NULL;
  60. m_rghAttach = NULL;
  61. }
  62. CAttMenu::~CAttMenu()
  63. {
  64. if (m_hMenu)
  65. DestroyMenu(m_hMenu);
  66. HrFreeAttachData(m_pAttachVCard);
  67. ReleaseObj(m_pFntCache);
  68. ReleaseObj(m_pFrame);
  69. ReleaseObj(m_pMsg);
  70. ReleaseObj(m_pHostCmdTarget);
  71. SafeMemFree(m_rghAttach);
  72. }
  73. ULONG CAttMenu::AddRef()
  74. {
  75. return ++m_cRef;
  76. }
  77. ULONG CAttMenu::Release()
  78. {
  79. m_cRef--;
  80. if (m_cRef==0)
  81. {
  82. delete this;
  83. return 0;
  84. }
  85. return m_cRef;
  86. }
  87. HRESULT CAttMenu::Init(IMimeMessage *pMsg, IFontCache *pFntCache, IOleInPlaceFrame *pFrame, IOleCommandTarget *pHostCmdTarget)
  88. {
  89. if (pMsg==NULL || pFntCache==NULL)
  90. return E_INVALIDARG;
  91. ReplaceInterface(m_pFntCache, pFntCache);
  92. ReplaceInterface(m_pFrame, pFrame);
  93. ReplaceInterface(m_pMsg, pMsg);
  94. ReplaceInterface(m_pHostCmdTarget, pHostCmdTarget);
  95. pMsg->GetCharset(&m_hCharset);
  96. return ScanForAttachmentCount();
  97. }
  98. HRESULT CAttMenu::Show(HWND hwnd, LPPOINT ppt, BOOL fRightClick)
  99. {
  100. ULONG iCmd;
  101. LPATTACHDATA lpAttach;
  102. HRESULT hr=S_OK;
  103. // Check Params
  104. AssertSz (hwnd && ppt, "Null Parameter");
  105. if (m_fShowingMenu)
  106. return S_OK;
  107. if (m_hMenu == NULL)
  108. {
  109. hr = BuildMenu();
  110. if (FAILED(hr))
  111. goto error;
  112. }
  113. Assert (m_hMenu);
  114. // BUG: If the right edge is off the screen, TrackPopupMenu picks a random point
  115. // ppt->x = min(GetSystemMetrics(SM_CXSCREEN), ppt->x);
  116. // set m_uVerb so we can show correct context menu help for Open or Save.
  117. m_uVerb = fRightClick || (GetAsyncKeyState(VK_CONTROL)&0x8000) ? AV_SAVEAS : AV_OPEN;
  118. m_fShowingMenu=TRUE;
  119. SubClassWindow(hwnd, TRUE);
  120. // sheer brillance. We subclass the parent window during the context menu loop so we can steal the
  121. // owndraw messages and also steal the menu select messages.
  122. iCmd = (ULONG)TrackPopupMenu (m_hMenu, TPM_RIGHTALIGN | TPM_LEFTBUTTON | TPM_RETURNCMD, ppt->x, ppt->y, 0, hwnd, NULL);
  123. SubClassWindow(hwnd, FALSE);
  124. m_fShowingMenu=FALSE;
  125. if (iCmd<=0) // nothing selected, bail
  126. goto error;
  127. if (iCmd == idmSaveAllAttach)
  128. return HrSaveAll(hwnd);
  129. hr = FindItem(iCmd, FALSE, &lpAttach);
  130. if (FAILED(hr))
  131. goto error;
  132. hr = HrDoAttachmentVerb(hwnd, m_uVerb, m_pMsg, lpAttach);
  133. error:
  134. return hr;
  135. }
  136. /*
  137. * note, we build the attachment menu we hang the lpAttach data off the context menu
  138. * which contains all the temp file to delete etc.
  139. */
  140. HRESULT CAttMenu::BuildMenu()
  141. {
  142. HRESULT hr = S_OK;
  143. MENUITEMINFO mii={0};
  144. INT iMenu = 0;
  145. int cyMenu, cyMenuMax, cyItem;
  146. SIZE size;
  147. ULONG uAttach;
  148. LPATTACHDATA pAttach;
  149. int cSafeFiles = 0;
  150. Assert (!m_hMenu);
  151. // Create the menu
  152. m_hMenu = CreatePopupMenu();
  153. if (!m_hMenu)
  154. return E_OUTOFMEMORY;
  155. // figure out where to put menu breaks
  156. cyMenu = 0;
  157. cyMenuMax = GetSystemMetrics(SM_CYSCREEN);
  158. // calculate the rough height of each item, and the maximum width
  159. // for the attachment name
  160. GetItemTextExtent(NULL, L"BIGGERMAXATTACHMENTNAME.TXT", &size);
  161. m_cxMaxText = size.cx;
  162. cyItem = max(size.cy, GetSystemMetrics(SM_CYSMICON)) + 8;
  163. mii.cbSize = sizeof(mii);
  164. mii.fMask = MIIM_DATA|MIIM_ID|MIIM_TYPE;
  165. mii.fType = MFT_OWNERDRAW;
  166. mii.wID = 1;
  167. /*
  168. * This is weird, but cool. So we assign menu items idms based on idmSaveAttachLast + i
  169. * where i is the item added. If we're a popup on a menubar, then we ensure that we don't go
  170. * over the reserved limit. If we're not then we are a context menu. The context menu is called with
  171. * TPM_RETURNCMD, so the commands are not sent to the owners WM_COMMAND. Therefore over-running this range
  172. * and going into someone elses idm-space is not an issue.
  173. */
  174. for (uAttach=0; uAttach<m_cAttach; uAttach++)
  175. {
  176. if (m_rghAttach[uAttach] != m_hVCard)
  177. {
  178. hr = HrAttachDataFromBodyPart(m_pMsg, m_rghAttach[uAttach], &pAttach);
  179. if (!FAILED(hr))
  180. {
  181. // for the ownerdraw menus, we simply hang off the attachment pointers, we are guaranteed
  182. // these to be valid during the lifetime of the menu
  183. mii.dwItemData = (DWORD_PTR)pAttach;
  184. mii.fType = MFT_OWNERDRAW;
  185. // insert menu breaks as appropriate
  186. cyMenu += cyItem;
  187. if (cyMenu >= cyMenuMax)
  188. {
  189. mii.fType |= MFT_MENUBARBREAK;
  190. cyMenu = cyItem;
  191. }
  192. if (pAttach && !pAttach->fSafe && !m_fAllowUnsafe)
  193. {
  194. mii.fMask |= MIIM_STATE;
  195. mii.fState = MFS_DISABLED;
  196. }
  197. else
  198. cSafeFiles++;
  199. if (!InsertMenuItem (m_hMenu, iMenu++, TRUE, &mii))
  200. {
  201. MemFree(pAttach);
  202. hr = E_FAIL;
  203. goto error;
  204. }
  205. mii.fMask &= ~MIIM_STATE;
  206. mii.fState = 0;
  207. mii.wID++;
  208. }
  209. }
  210. }
  211. mii.fType = MFT_SEPARATOR;
  212. mii.dwItemData=0;
  213. InsertMenuItem (m_hMenu, iMenu++, TRUE, &mii);
  214. // we have to owner-draw this menu item as we draw the entire menu in a different font
  215. // based on the message locale
  216. mii.fType = MFT_OWNERDRAW;
  217. mii.dwTypeData = NULL;
  218. mii.dwItemData = NULL;
  219. mii.wID = idmSaveAllAttach;
  220. if (!m_fAllowUnsafe)
  221. {
  222. if (!cSafeFiles)
  223. {
  224. mii.fMask |= MIIM_STATE;
  225. mii.fState = MFS_DISABLED;
  226. }
  227. m_cEnabledAttach = cSafeFiles;
  228. }
  229. InsertMenuItem (m_hMenu, iMenu++, TRUE, &mii);
  230. error:
  231. // Failed cond
  232. if (FAILED (hr) && m_hMenu)
  233. DestroyMenu(m_hMenu);
  234. // Done
  235. return hr;
  236. }
  237. HRESULT CAttMenu::DestroyMenu(HMENU hMenu)
  238. {
  239. ULONG uItem,
  240. cItems;
  241. LPATTACHDATA pAttach;
  242. cItems = GetMenuItemCount(hMenu);
  243. for (uItem = 0; uItem < cItems; uItem++)
  244. {
  245. // free the lpAttach hanging off the menu
  246. if (FindItem(uItem, TRUE, &pAttach)==S_OK)
  247. HrFreeAttachData(pAttach);
  248. }
  249. ::DestroyMenu(hMenu);
  250. return S_OK;
  251. }
  252. HRESULT CAttMenu::OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis)
  253. {
  254. WORD cxIcon=(WORD)GetSystemMetrics (SM_CXSMICON),
  255. cyIcon=(WORD)GetSystemMetrics (SM_CYSMICON);
  256. SIZE rSize;
  257. LPATTACHDATA lpAttach;
  258. WCHAR rgch[CCHMAX_STRINGRES];
  259. Assert(lpmis && hwnd);
  260. if (lpmis->CtlType == ODT_MENU)
  261. {
  262. // Default width and height
  263. lpmis->itemHeight = cyIcon + 8;
  264. lpmis->itemWidth = cxIcon + 9;
  265. lpAttach = (LPATTACHDATA)lpmis->itemData;
  266. if (lpAttach)
  267. {
  268. if (FAILED(GetItemTextExtent(hwnd, lpAttach->szDisplay, &rSize)))
  269. return E_FAIL;
  270. lpmis->itemWidth += min(rSize.cx, m_cxMaxText);
  271. lpmis->itemHeight = max (rSize.cy, cyIcon) + 8;
  272. return S_OK;
  273. }
  274. if (lpmis->itemID == idmSaveAllAttach)
  275. {
  276. LoadStringWrapW(g_hLocRes, idsSaveAllAttach, rgch, ARRAYSIZE(rgch));
  277. if (FAILED(GetItemTextExtent(hwnd, rgch, &rSize)))
  278. return E_FAIL;
  279. lpmis->itemWidth = min(rSize.cx, m_cxMaxText) + 9;
  280. lpmis->itemHeight = max (rSize.cy, cyIcon) + 8;
  281. return S_OK;
  282. }
  283. }
  284. return E_FAIL;
  285. }
  286. HRESULT CAttMenu::GetItemTextExtent(HWND hwnd, LPWSTR szDisp, LPSIZE pSize)
  287. {
  288. HDC hdc;
  289. HFONT hFont=0,
  290. hFontOld;
  291. HRESULT hr=E_FAIL;
  292. // I need a DC to measure the size of the menu font
  293. hdc = GetDC (hwnd);
  294. if (hdc)
  295. {
  296. Assert (m_hCharset!=NULL);
  297. Assert (m_pFntCache);
  298. // Create the menu font
  299. m_pFntCache->GetFont(FNT_SYS_MENU, m_hCharset, &hFont);
  300. if (hFont)
  301. hFontOld = SelectFont (hdc, hFont);
  302. // Get the size of the text
  303. hr = GetTextExtentPoint32AthW(hdc, szDisp, lstrlenW(szDisp), pSize, DT_NOPREFIX)?S_OK:S_FALSE;
  304. if (hFont)
  305. SelectObject (hdc, hFontOld);
  306. ReleaseDC (hwnd, hdc);
  307. }
  308. return S_OK;
  309. }
  310. HRESULT CAttMenu::OnDrawItem(HWND hwnd, LPDRAWITEMSTRUCT lpdis)
  311. {
  312. DWORD rgbBack, rgbText;
  313. WORD dx, x, y,
  314. cxIcon=(WORD) GetSystemMetrics (SM_CXSMICON),
  315. cyIcon=(WORD) GetSystemMetrics (SM_CYSMICON);
  316. HFONT hFont = NULL,
  317. hFontOld = NULL;
  318. LPATTACHDATA lpAttach;
  319. RECT rc;
  320. LPWSTR pszDisplay;
  321. WCHAR rgch[CCHMAX_STRINGRES];
  322. HICON hIcon;
  323. HCHARSET hCharset;
  324. AssertSz (lpdis, "Null Parameter");
  325. // not a menu
  326. if (lpdis->CtlType != ODT_MENU)
  327. return E_FAIL;
  328. if (lpdis->itemID == idmSaveAllAttach)
  329. {
  330. if (!LoadStringWrapW(g_hLocRes, idsSaveAllAttach, rgch, ARRAYSIZE(rgch)))
  331. return E_FAIL;
  332. pszDisplay = rgch;
  333. hIcon=NULL;
  334. hCharset = NULL; // always draw in system font
  335. }
  336. else
  337. {
  338. lpAttach = (LPATTACHDATA)lpdis->itemData;
  339. if (!lpAttach)
  340. return E_FAIL;
  341. hIcon = lpAttach->hIcon;
  342. pszDisplay = lpAttach->szDisplay;
  343. hCharset = m_hCharset; // always draw in localised font
  344. }
  345. // Determine Colors
  346. if (lpdis->itemState & ODS_SELECTED)
  347. {
  348. rgbBack = SetBkColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
  349. if (lpdis->itemState & ODS_DISABLED)
  350. rgbText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_GRAYTEXT));
  351. else
  352. rgbText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
  353. }
  354. else
  355. {
  356. rgbBack = SetBkColor (lpdis->hDC, GetSysColor(COLOR_MENU));
  357. if (lpdis->itemState & ODS_DISABLED)
  358. rgbText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_GRAYTEXT));
  359. else
  360. rgbText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_WINDOWTEXT));
  361. }
  362. // Clear the item
  363. ExtTextOutWrapW(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, ETO_OPAQUE, &lpdis->rcItem, NULL, 0, NULL);
  364. dx = 4;
  365. if (hIcon)
  366. {
  367. x = (WORD) lpdis->rcItem.left + dx;
  368. y = (WORD) lpdis->rcItem.top + (INT)(((lpdis->rcItem.bottom - lpdis->rcItem.top) / 2) - (INT)(cyIcon / 2));
  369. DrawIconEx(lpdis->hDC, x, y, lpAttach->hIcon, cxIcon, cyIcon, NULL, NULL, DI_NORMAL);
  370. }
  371. // Create the menu font
  372. m_pFntCache->GetFont(FNT_SYS_MENU, hCharset, &hFont);
  373. if (hFont)
  374. hFontOld = (HFONT)SelectObject (lpdis->hDC, hFont);
  375. rc = lpdis->rcItem;
  376. rc.left += (cxIcon + (2*dx));
  377. rc.right -= 2*dx;
  378. DrawTextExWrapW(lpdis->hDC, pszDisplay, lstrlenW(pszDisplay), &rc, DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER|DT_WORDBREAK|DT_NOPREFIX, NULL);
  379. if (hFont)
  380. SelectObject (lpdis->hDC, hFontOld);
  381. // Reset Text Colors
  382. SetTextColor (lpdis->hDC, rgbText);
  383. SetBkColor (lpdis->hDC, rgbBack);
  384. return S_OK;
  385. }
  386. HRESULT CAttMenu::OnMenuSelect(HWND hwnd, WPARAM wParam, LPARAM lParam)
  387. {
  388. LPATTACHDATA pAttach;
  389. WCHAR wszRes[CCHMAX_STRINGRES],
  390. wsz[CCHMAX_STRINGRES + ARRAYSIZE(pAttach->szDisplay)];
  391. if (!m_pFrame)
  392. return E_FAIL;
  393. if (HIWORD(wParam)&MF_OWNERDRAW)
  394. {
  395. if (LOWORD(wParam) == idmSaveAllAttach)
  396. {
  397. SideAssert(LoadStringWrapW(g_hLocRes, idsSaveAllAttachMH, wszRes, ARRAYSIZE(wszRes)));
  398. m_pFrame->SetStatusText(wszRes);
  399. return S_OK;
  400. }
  401. if (FindItem(LOWORD(wParam), FALSE, &pAttach)==S_OK)
  402. {
  403. // if we're showing the context menu, rather than the save-attachment menu then we offer menuhelp
  404. // in the Form of 'Opens the attachment'. If a right-click context, do a save
  405. LoadStringWrapW(g_hLocRes,
  406. (m_uVerb == AV_OPEN) ? idsOpenAttachControl : idsSaveAttachControl,
  407. wszRes,
  408. ARRAYSIZE(wszRes));
  409. wnsprintfW(wsz, ARRAYSIZE(wsz), wszRes, pAttach->szDisplay);
  410. m_pFrame->SetStatusText(wsz);
  411. return S_OK;
  412. }
  413. }
  414. return S_FALSE;
  415. }
  416. HRESULT CAttMenu::SubClassWindow(HWND hwnd, BOOL fOn)
  417. {
  418. if (fOn)
  419. {
  420. Assert (!m_pfnWndProc);
  421. SetProp(hwnd, c_szSubThisPtr, (HANDLE)this);
  422. m_pfnWndProc = (WNDPROC)SetWindowLongPtrAthW(hwnd, GWLP_WNDPROC, (LONG_PTR)ExtSubClassProc);
  423. }
  424. else
  425. {
  426. Assert (m_pfnWndProc);
  427. SetWindowLongPtrAthW(hwnd, GWLP_WNDPROC, (LONG_PTR)m_pfnWndProc);
  428. RemoveProp(hwnd, c_szSubThisPtr);
  429. m_pfnWndProc=NULL;
  430. }
  431. return S_OK;
  432. }
  433. LRESULT CAttMenu::ExtSubClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  434. {
  435. CAttMenu *pAttMenu = (CAttMenu *)GetProp(hwnd, c_szSubThisPtr);
  436. Assert (pAttMenu);
  437. switch (msg)
  438. {
  439. case WM_MEASUREITEM:
  440. pAttMenu->OnMeasureItem(hwnd, (LPMEASUREITEMSTRUCT)lParam);
  441. break;
  442. case WM_DRAWITEM:
  443. pAttMenu->OnDrawItem(hwnd, (LPDRAWITEMSTRUCT)lParam);
  444. break;
  445. case WM_MENUSELECT:
  446. pAttMenu->OnMenuSelect(hwnd, wParam, lParam);
  447. break;
  448. }
  449. return CallWindowProcWrapW(pAttMenu->m_pfnWndProc, hwnd, msg, wParam, lParam);
  450. }
  451. HRESULT CAttMenu::FindItem(int idm, BOOL fByPos, LPATTACHDATA *ppAttach)
  452. {
  453. MENUITEMINFO mii;
  454. mii.cbSize = sizeof(MENUITEMINFO);
  455. mii.fMask = MIIM_DATA;
  456. Assert (ppAttach);
  457. if (GetMenuItemInfo(m_hMenu, idm, fByPos, &mii) && mii.dwItemData)
  458. {
  459. *ppAttach = (LPATTACHDATA)mii.dwItemData;
  460. return S_OK;
  461. }
  462. return E_FAIL;
  463. }
  464. HRESULT CAttMenu::HasAttach()
  465. {
  466. return m_cVisibleAttach ? S_OK:S_FALSE;
  467. }
  468. HRESULT CAttMenu::HasEnabledAttach()
  469. {
  470. return m_cEnabledAttach ? S_OK:S_FALSE;
  471. }
  472. HRESULT CAttMenu::HasVCard()
  473. {
  474. return m_hVCard ? S_OK:S_FALSE;
  475. }
  476. HRESULT CAttMenu::LaunchVCard(HWND hwnd)
  477. {
  478. if (!m_hVCard)
  479. return E_FAIL;
  480. if (m_pAttachVCard==NULL &&
  481. HrAttachDataFromBodyPart(m_pMsg, m_hVCard, &m_pAttachVCard)!=S_OK)
  482. return E_FAIL;
  483. return HrDoAttachmentVerb(hwnd, AV_OPEN, m_pMsg, m_pAttachVCard);
  484. }
  485. HRESULT CAttMenu::HrSaveAll(HWND hwnd)
  486. {
  487. return SaveAttachmentsWithPath(hwnd, m_pHostCmdTarget, m_pMsg);
  488. }
  489. HRESULT SaveAttachmentsWithPath(HWND hwnd, IOleCommandTarget *pCmdTarget, IMimeMessage *pMsg)
  490. {
  491. VARIANTARG va;
  492. WCHAR rgchPath[MAX_PATH];
  493. HRESULT hr;
  494. BOOL fAllowUnsafe = FALSE;
  495. *rgchPath = 0;
  496. if (pCmdTarget &&
  497. pCmdTarget->Exec(&CMDSETID_MimeEditHost, MEHOSTCMDID_SAVEATTACH_PATH, 0, NULL, &va)==S_OK &&
  498. va.vt == VT_BSTR &&
  499. va.bstrVal)
  500. {
  501. StrCpyNW(rgchPath, va.bstrVal, ARRAYSIZE(rgchPath));
  502. SysFreeString(va.bstrVal);
  503. }
  504. if (pCmdTarget &&
  505. pCmdTarget->Exec(&CMDSETID_MimeEditHost, MEHOSTCMDID_UNSAFEATTACHMENTS, 0, NULL, &va)==S_OK &&
  506. va.vt == VT_I4 && va.lVal == 0)
  507. fAllowUnsafe = TRUE;
  508. hr = HrSaveAttachments(hwnd, pMsg, rgchPath, ARRAYSIZE(rgchPath), fAllowUnsafe);
  509. if (hr == S_OK)
  510. {
  511. // if successful, then set the save attachment path
  512. if (pCmdTarget)
  513. {
  514. DWORD cchPath = lstrlenW(rgchPath);
  515. va.bstrVal = SysAllocStringLen(NULL, cchPath);
  516. if (va.bstrVal)
  517. {
  518. StrCpyNW(va.bstrVal, rgchPath, cchPath);
  519. va.vt = VT_BSTR;
  520. pCmdTarget->Exec(&CMDSETID_MimeEditHost, MEHOSTCMDID_SAVEATTACH_PATH, 0, &va, NULL);
  521. SysFreeString(va.bstrVal);
  522. }
  523. else
  524. TraceResult(hr = E_OUTOFMEMORY);
  525. }
  526. }
  527. return hr;
  528. }
  529. HRESULT CAttMenu::ScanForAttachmentCount()
  530. {
  531. ULONG uAttach,
  532. cAttach=0;
  533. LPSTR psz;
  534. PROPVARIANT pv;
  535. VARIANTARG va;
  536. // we quickly need to determine if there's a Vcard and or/attachments
  537. // so the preview pane can update the icons. When clicked on, we then defer-load the
  538. // actual info.
  539. Assert(m_rghAttach == NULL);
  540. Assert(m_cVisibleAttach == 0);
  541. Assert(m_cEnabledAttach == 0);
  542. Assert(m_cAttach == 0);
  543. if (m_pHostCmdTarget &&
  544. m_pHostCmdTarget->Exec(&CMDSETID_MimeEditHost, MEHOSTCMDID_UNSAFEATTACHMENTS, 0, NULL, &va)==S_OK &&
  545. va.vt == VT_I4 && va.lVal == 0)
  546. m_fAllowUnsafe = TRUE;
  547. if (m_pMsg &&
  548. m_pMsg->GetAttachments(&cAttach, &m_rghAttach)==S_OK)
  549. {
  550. for (uAttach=0; uAttach<cAttach; uAttach++)
  551. {
  552. BOOL fSafe = FALSE;
  553. if (m_hVCard == NULL &&
  554. MimeOleGetBodyPropA(m_pMsg, m_rghAttach[uAttach], PIDTOSTR(PID_HDR_CNTTYPE), NOFLAGS, &psz)==S_OK)
  555. {
  556. // hang onto first v-card
  557. if (lstrcmpi(psz, "text/x-vcard")==0)
  558. m_hVCard = m_rghAttach[uAttach];
  559. MemFree(psz);
  560. }
  561. if (!m_fAllowUnsafe && SUCCEEDED(HrAttachSafetyFromBodyPart(m_pMsg, m_rghAttach[uAttach], &fSafe)) && fSafe)
  562. m_cEnabledAttach++;
  563. }
  564. }
  565. // we keep the actual attachment count (tells the size of m_rghAttach) and also the
  566. // count of 'visible' attachment we want to show
  567. m_cVisibleAttach = m_cAttach = cAttach;
  568. if (m_hVCard)
  569. {
  570. Assert (cAttach>0);
  571. m_cVisibleAttach--;
  572. m_cEnabledAttach--;
  573. }
  574. if (m_fAllowUnsafe) // all visible attachments are enabled if we allow all files
  575. m_cEnabledAttach = m_cVisibleAttach;
  576. return S_OK;
  577. }