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.

1352 lines
43 KiB

  1. /*
  2. * m s g p r o p . c p p
  3. *
  4. * Purpose:
  5. * Implements propsheet for a msg
  6. *
  7. * Owner:
  8. * brettm.
  9. *
  10. * History:
  11. * Feb '95: Stolen from Capone Sources - brettm
  12. *
  13. * Copyright (C) Microsoft Corp. 1993, 1994.
  14. */
  15. #include <pch.hxx>
  16. #ifdef WIN16
  17. #include "mapi.h"
  18. #endif
  19. #include <resource.h>
  20. #include <richedit.h>
  21. #include "goptions.h"
  22. #include "mimeole.h"
  23. #include "mimeutil.h"
  24. #include "msgprop.h"
  25. #include "addrobj.h"
  26. #include "mpropdlg.h"
  27. #ifndef WIN16
  28. #include "mapi.h"
  29. #endif
  30. #include "ipab.h"
  31. #include <secutil.h>
  32. #include <seclabel.h>
  33. #include <certs.h>
  34. #include <demand.h>
  35. #include <strconst.h>
  36. #include <shlwapi.h>
  37. #include <shlwapip.h>
  38. #include "instance.h"
  39. #include "conman.h"
  40. #include "shared.h"
  41. #include "htmlhelp.h"
  42. /*
  43. * m a c r o s and c o n s t a n t s
  44. *
  45. */
  46. #define KILOBYTE 1024L
  47. #define PROP_ERROR(prop) (PROP_TYPE(prop.ulPropTag) == PT_ERROR)
  48. #ifdef WIN16
  49. #ifndef GetLastError
  50. #define GetLastError() ((DWORD)-1)
  51. #endif
  52. #endif //!WIN16
  53. #ifdef WIN16
  54. #define SET_DIALOG_SECURITY(hwnd, value) SetProp32(hwnd, s_cszDlgSec, (LPVOID)value)
  55. #define GET_DIALOG_SECURITY(hwnd) GetProp32(hwnd, s_cszDlgSec)
  56. #define CLEAR_DIALOG_SECURITY(hwnd) RemoveProp32(hwnd, s_cszDlgSec);
  57. #else
  58. #define SET_DIALOG_SECURITY(hwnd, value) SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM)value)
  59. #define GET_DIALOG_SECURITY(hwnd) GetWindowLongPtr(hwnd, DWLP_USER);
  60. #define CLEAR_DIALOG_SECURITY(hwnd) SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM)NULL)
  61. #endif
  62. /*
  63. * s t r u c t u r e s
  64. *
  65. */
  66. struct DLGSECURITYtag
  67. {
  68. PCX509CERT pSenderCert;
  69. PCCERT_CONTEXT pEncSenderCert;
  70. PCCERT_CONTEXT pEncryptionCert;
  71. THUMBBLOB tbSenderThumbprint;
  72. BLOB blSymCaps;
  73. FILETIME ftSigningTime;
  74. HCERTSTORE hcMsg;
  75. };
  76. typedef struct DLGSECURITYtag DLGSECURITY;
  77. typedef DLGSECURITY *PDLGSECURITY;
  78. typedef const DLGSECURITY *PCDLGSECURITY;
  79. /*
  80. * c l a s s e s
  81. *
  82. */
  83. class CMsgProps
  84. {
  85. public:
  86. CMsgProps();
  87. ~CMsgProps();
  88. HRESULT HrDoProps(PMSGPROP pmp);
  89. static INT_PTR CALLBACK GeneralPageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  90. static INT_PTR CALLBACK DetailsPageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  91. static INT_PTR CALLBACK SecurityPageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  92. static INT_PTR CALLBACK EncryptionPageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  93. void InitGeneralPage();
  94. void InitDetailsPage(HWND hwnd);
  95. void InitSecurityPage(HWND hwnd);
  96. private:
  97. HIMAGELIST m_himl;
  98. HWND m_hwndGen;
  99. HWND m_hwndGenSource;
  100. PMSGPROP m_pmp;
  101. };
  102. // Function declarations ////////////////////////////////////////
  103. // msg source dialog is modeless, so it can't be in the CProps dialog.
  104. /*
  105. * p r o t o t y p e s
  106. *
  107. */
  108. void SecurityOnWMCreate(HWND hwnd, LPARAM lParam);
  109. INT_PTR CALLBACK ViewSecCertDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  110. /*
  111. * f u n c t i o n s
  112. *
  113. */
  114. //
  115. // FUNCTION: HrMsgProperties()
  116. //
  117. // PURPOSE: Displays the property sheet for the specified message.
  118. //
  119. // PARAMETERS:
  120. // [in] pmp - Information needed to identify the message.
  121. //
  122. HRESULT HrMsgProperties(PMSGPROP pmp)
  123. {
  124. CMsgProps *pMsgProp = 0;
  125. HRESULT hr;
  126. TraceCall("HrMsgProperties");
  127. // Create the property sheet object
  128. pMsgProp = new CMsgProps();
  129. if (!pMsgProp)
  130. return E_OUTOFMEMORY;
  131. // Tell the object to do it's thing. This won't go away until the
  132. // property sheet is dismissed.
  133. hr = pMsgProp->HrDoProps(pmp);
  134. // Free the object
  135. if (pMsgProp)
  136. delete pMsgProp;
  137. return hr;
  138. }
  139. CMsgProps::CMsgProps()
  140. {
  141. m_himl = 0;
  142. m_hwndGen = 0;
  143. m_hwndGenSource = 0;
  144. m_pmp = NULL;
  145. }
  146. CMsgProps::~CMsgProps()
  147. {
  148. }
  149. //
  150. // FUNCTION: CMsgProps::HrDoProps()
  151. //
  152. // PURPOSE: Initializes the structures used to create the prop sheet
  153. // and then displays the sheet.
  154. //
  155. // PARAMETERS:
  156. // [in] pmp - Information needed to identify the message.
  157. //
  158. // RETURN VALUE:
  159. // HRESULT
  160. //
  161. HRESULT CMsgProps::HrDoProps(PMSGPROP pmp)
  162. {
  163. PROPSHEETHEADER psh;
  164. PROPSHEETPAGE psp[3];
  165. BOOL fApply = FALSE;
  166. HRESULT hr;
  167. LPTSTR pszSubject = NULL;
  168. LPTSTR pszFree = NULL;
  169. TCHAR rgch[256] = "";
  170. TraceCall("CMsgProps::HrDoProps");
  171. // Zero init the prop sheet structures
  172. ZeroMemory(&psh, sizeof(psh));
  173. ZeroMemory(&psp, sizeof(psp));
  174. // Double check that we have the information we need to do this.
  175. if (pmp == NULL || (pmp->pMsg == NULL && pmp->pNoMsgData == NULL))
  176. return E_INVALIDARG;
  177. Assert(pmp->hwndParent);
  178. // Stash this pointer
  179. m_pmp = pmp;
  180. // Page zero is the general tab
  181. psp[0].dwSize = sizeof(PROPSHEETPAGE);
  182. psp[0].dwFlags = PSP_USETITLE;
  183. psp[0].hInstance = g_hLocRes;
  184. psp[0].pszTemplate = MAKEINTRESOURCE(iddMsgProp_General);
  185. psp[0].pfnDlgProc = GeneralPageProc;
  186. psp[0].pszTitle = MAKEINTRESOURCE(idsPropPageGeneral);
  187. psp[0].lParam = (LPARAM) this;
  188. // Increment the number of pages
  189. psh.nPages++;
  190. // If the message is not unsent, then we also display the "Details" tab.
  191. if (!(pmp->dwFlags & ARF_UNSENT) || (pmp->dwFlags & ARF_SUBMITTED))
  192. {
  193. psp[psh.nPages].dwSize = sizeof(PROPSHEETPAGE);
  194. psp[psh.nPages].dwFlags = PSP_USETITLE;
  195. psp[psh.nPages].hInstance = g_hLocRes;
  196. psp[psh.nPages].pszTemplate = MAKEINTRESOURCE(iddMsgProp_Details);
  197. psp[psh.nPages].pfnDlgProc = DetailsPageProc;
  198. psp[psh.nPages].pszTitle = MAKEINTRESOURCE(idsPropPageDetails);
  199. psp[psh.nPages].lParam = (LPARAM) this;
  200. // If the caller wanted this to be the first page the user
  201. // sees, set it to be the start page.
  202. if (MP_DETAILS == pmp->mpStartPage)
  203. psh.nStartPage = psh.nPages;
  204. // Increment the number of pages
  205. psh.nPages++;
  206. }
  207. // If the message is secure, add the security pages
  208. if (pmp->fSecure && (!(pmp->dwFlags & ARF_UNSENT) || (pmp->dwFlags & ARF_SUBMITTED)))
  209. {
  210. psp[psh.nPages].dwSize = sizeof(PROPSHEETPAGE);
  211. psp[psh.nPages].dwFlags = PSP_USETITLE;
  212. psp[psh.nPages].hInstance = g_hLocRes;
  213. psp[psh.nPages].pszTemplate = MAKEINTRESOURCE(iddMsgProp_Security_Msg);
  214. psp[psh.nPages].pfnDlgProc = SecurityPageProc;
  215. psp[psh.nPages].pszTitle = MAKEINTRESOURCE(idsPropPageSecurity);
  216. psp[psh.nPages].lParam = (LPARAM) this;
  217. // If the caller wanted this to be the first page the user
  218. // sees, set it to be the start page.
  219. if (MP_SECURITY == pmp->mpStartPage)
  220. psh.nStartPage = psh.nPages;
  221. // Increment the number of pages
  222. psh.nPages++;
  223. }
  224. // Property sheet header information
  225. psh.dwSize = sizeof(PROPSHEETHEADER);
  226. psh.dwFlags = PSH_PROPSHEETPAGE | PSH_USEPAGELANG | ((fApply) ? 0 : PSH_NOAPPLYNOW);
  227. psh.hwndParent = pmp->hwndParent;
  228. psh.hInstance = g_hLocRes;
  229. // The title of the property sheet is the same as the subject. So now we
  230. // need to get the subject from either the message or message info.
  231. if (pmp->pMsg)
  232. {
  233. // Get the subject from the message
  234. if (SUCCEEDED(MimeOleGetBodyPropA(pmp->pMsg, HBODY_ROOT,
  235. PIDTOSTR(PID_HDR_SUBJECT), NOFLAGS,
  236. &pszSubject)))
  237. {
  238. // We'll need to free this string later
  239. pszFree = pszSubject;
  240. }
  241. }
  242. else
  243. {
  244. AssertSz(pmp->pNoMsgData, "CMsgProp::HrDoProps() - Need to provide either a Message or Message Info");
  245. pszSubject = (LPTSTR) pmp->pNoMsgData->pszSubject;
  246. }
  247. // If there was no subject on the message, set the title to be "No Subject"
  248. if (!pszSubject || !*pszSubject)
  249. {
  250. LoadString(g_hLocRes, idsNoSubject, rgch, sizeof(rgch));
  251. pszSubject = rgch;
  252. }
  253. // Clean up the subject string before we use it. Tabs look like pretty bad.
  254. ConvertTabsToSpaces(pszSubject);
  255. // Set the subject as the property sheet title.
  256. psh.pszCaption = pszSubject;
  257. // Provide the array of pages. The number was set along the way.
  258. psh.ppsp = (LPCPROPSHEETPAGE) &psp;
  259. // Invoke the property sheet.
  260. PropertySheet(&psh);
  261. // If this is valid, then we need to free the string.
  262. SafeMemFree(pszFree);
  263. return (S_OK);
  264. }
  265. //
  266. // FUNCTION: CMsgProps::GeneralPageProc()
  267. //
  268. // PURPOSE: Callback for the General tab dialog.
  269. //
  270. INT_PTR CALLBACK CMsgProps::GeneralPageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  271. {
  272. CMsgProps *pThis = 0;
  273. switch(msg)
  274. {
  275. case WM_INITDIALOG:
  276. {
  277. // Grab the object's this pointer from the init info
  278. pThis = (CMsgProps *) ((PROPSHEETPAGE *)lParam)->lParam;
  279. // Stash the window handle for this dialog in the class
  280. pThis->m_hwndGen = hwnd;
  281. // Initialize the page
  282. pThis->InitGeneralPage();
  283. return TRUE;
  284. }
  285. case WM_NOTIFY:
  286. {
  287. switch(((NMHDR FAR *)lParam)->code)
  288. {
  289. // We're going to do the default thing for all of these notifications
  290. case PSN_APPLY:
  291. case PSN_KILLACTIVE:
  292. case PSN_SETACTIVE:
  293. {
  294. SetDlgMsgResult(hwnd, WM_NOTIFY, FALSE);
  295. return TRUE;
  296. }
  297. }
  298. break;
  299. }
  300. }
  301. return FALSE;
  302. }
  303. enum
  304. {
  305. freeSubject = 0,
  306. freeFrom,
  307. freeMax
  308. };
  309. //
  310. // FUNCTION: CMsgProps::InitGeneralPage()
  311. //
  312. // PURPOSE: Set's the values for the "General" tab in the message
  313. // property sheet.
  314. //
  315. void CMsgProps::InitGeneralPage()
  316. {
  317. HWND hwnd;
  318. char rgch[256],
  319. rgchFmt[256];
  320. char *psz = NULL;
  321. PROPVARIANT rVariant;
  322. LPMIMEMESSAGE pMsg = m_pmp->pMsg;
  323. IMSGPRIORITY Pri = IMSG_PRI_NORMAL;
  324. int ids;
  325. BOOL fMime;
  326. LPSTR rgszFree[freeMax]={0};
  327. WCHAR wszDate[CCHMAX_STRINGRES];
  328. TraceCall("CMsgProps::InitGeneralPage");
  329. // [SBAILEY]: Raid-2440: ATTACH: Attachments field in Properties dialog innacurate when looked at from the listview.
  330. if (m_pmp->fFromListView)
  331. {
  332. // Too hard to get these counts write from the listview because to really compute the attachment
  333. // counts correctly, we have to render the message in trident. Since we are time contrained,
  334. // we are going to simply remove the attachement count from the listview message properties. But
  335. // since the counts are correct from message note properties, we will show the attachment counts from there.
  336. ShowWindow(GetDlgItem(m_hwndGen, IDC_ATTACHMENTS_STATIC), SW_HIDE);
  337. ShowWindow(GetDlgItem(m_hwndGen, IDC_ATTACHMENTS), SW_HIDE);
  338. }
  339. // If this is a news message, we hide the "Recieved:" and "Priority" fields
  340. if (m_pmp->type == MSGPROPTYPE_NEWS)
  341. {
  342. RECT rc, rcLabel;
  343. // Get the position of the priority field
  344. GetWindowRect(GetDlgItem(m_hwndGen, IDC_PRIORITY), &rc);
  345. MapWindowPoints(NULL, m_hwndGen, (LPPOINT) &rc, 2);
  346. // Get the position of the priority label
  347. GetWindowRect(GetDlgItem(m_hwndGen, IDC_PRIORITY_STATIC), &rcLabel);
  348. MapWindowPoints(NULL, m_hwndGen, (LPPOINT) &rcLabel, 2);
  349. // Hide the unused fields
  350. ShowWindow(GetDlgItem(m_hwndGen, IDC_PRIORITY_STATIC), SW_HIDE);
  351. ShowWindow(GetDlgItem(m_hwndGen, IDC_PRIORITY), SW_HIDE);
  352. ShowWindow(GetDlgItem(m_hwndGen, idcStatic1), SW_HIDE);
  353. ShowWindow(GetDlgItem(m_hwndGen, IDC_RECEIVED_STATIC), SW_HIDE);
  354. ShowWindow(GetDlgItem(m_hwndGen, IDC_RECEIVED), SW_HIDE);
  355. // Move the sent fields up to where the priority fields were
  356. SetWindowPos(GetDlgItem(m_hwndGen, IDC_SENT_STATIC), NULL, rcLabel.left,
  357. rcLabel.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  358. SetWindowPos(GetDlgItem(m_hwndGen, IDC_SENT), NULL, rc.left, rc.top, 0, 0,
  359. SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  360. }
  361. // Figure out the correct image for this message
  362. int idIcon;
  363. if (m_pmp->type == MSGPROPTYPE_MAIL)
  364. {
  365. if (m_pmp->dwFlags & ARF_UNSENT)
  366. idIcon = idiMsgPropUnSent;
  367. else
  368. idIcon = idiMsgPropSent;
  369. }
  370. else
  371. {
  372. if (m_pmp->dwFlags & ARF_UNSENT)
  373. idIcon = idiArtPropUnpost;
  374. else
  375. idIcon = idiArtPropPost;
  376. }
  377. // Set the image on the property sheet
  378. HICON hIcon = LoadIcon(g_hLocRes, MAKEINTRESOURCE(idIcon));
  379. SendDlgItemMessage(m_hwndGen, IDC_FOLDER_IMAGE, STM_SETIMAGE, IMAGE_ICON, (LPARAM) hIcon);
  380. // Subject
  381. if (pMsg)
  382. {
  383. // If we have a message object, then we need to get the subject from the message
  384. if (SUCCEEDED(MimeOleGetBodyPropA(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_SUBJECT),
  385. NOFLAGS, &psz)))
  386. {
  387. // Make sure we free this later, eh?
  388. rgszFree[freeSubject] = psz;
  389. }
  390. }
  391. else
  392. {
  393. Assert(m_pmp->pNoMsgData);
  394. psz = (LPTSTR) m_pmp->pNoMsgData->pszSubject;
  395. }
  396. // If the message doesn't have a subject, then substitute "(No Subject)"
  397. if (!psz || !*psz)
  398. {
  399. LoadString(g_hLocRes, idsNoSubject, rgch, sizeof(rgch));
  400. psz = rgch;
  401. }
  402. // Set the subject on the dialog
  403. SetDlgItemText(m_hwndGen, IDC_MSGSUBJECT, psz);
  404. // From
  405. if (pMsg)
  406. {
  407. // Get the "From" line
  408. if (S_OK == pMsg->GetAddressFormat(IAT_FROM, AFT_DISPLAY_BOTH, &psz))
  409. {
  410. // We'll need to free this later
  411. rgszFree[freeFrom] = psz;
  412. // Set the name on the control
  413. SetDlgItemText(m_hwndGen, IDC_MSGFROM, psz);
  414. }
  415. }
  416. else
  417. {
  418. // Check to see if the caller provided this information
  419. if (m_pmp->pNoMsgData && m_pmp->pNoMsgData->pszFrom)
  420. {
  421. SetDlgItemText(m_hwndGen, IDC_MSGFROM, m_pmp->pNoMsgData->pszFrom);
  422. }
  423. }
  424. // Type (News or Mail)
  425. if (m_pmp->type == MSGPROPTYPE_MAIL)
  426. LoadString(g_hLocRes, idsMailMessage, rgch, ARRAYSIZE(rgch));
  427. else
  428. LoadString(g_hLocRes, idsNewsMessage, rgch, ARRAYSIZE(rgch));
  429. SetDlgItemText(m_hwndGen, IDC_TYPE, rgch);
  430. // Location
  431. if (m_pmp->dwFlags & ARF_UNSENT)
  432. {
  433. LoadString(g_hLocRes, idsUnderComp, rgch, ARRAYSIZE(rgchFmt));
  434. SetDlgItemText(m_hwndGen, IDC_MSGFOLDER, rgch);
  435. }
  436. else
  437. SetDlgItemText(m_hwndGen, IDC_MSGFOLDER, m_pmp->szFolderName);
  438. // Size
  439. ULONG ulSize;
  440. if (pMsg)
  441. {
  442. pMsg->GetMessageSize(&ulSize, 0);
  443. if (0 == ulSize)
  444. {
  445. // see if the message has the userprop for uncached size
  446. rVariant.vt = VT_UI4;
  447. if (SUCCEEDED(pMsg->GetProp(PIDTOSTR(PID_ATT_UNCACHEDSIZE), 0, &rVariant)))
  448. ulSize = rVariant.ulVal;
  449. }
  450. AthFormatSizeK(ulSize, rgch, ARRAYSIZE(rgch));
  451. }
  452. else if (m_pmp->pNoMsgData && m_pmp->pNoMsgData->ulSize)
  453. {
  454. AthFormatSizeK(m_pmp->pNoMsgData->ulSize, rgch, ARRAYSIZE(rgch));
  455. }
  456. else
  457. {
  458. LoadString(g_hLocRes, idsUnderComp, rgch, ARRAYSIZE(rgchFmt));
  459. }
  460. SetDlgItemText(m_hwndGen, IDC_MSGSIZE, rgch);
  461. // Attachments
  462. ULONG cAttachments = 0;
  463. if (pMsg)
  464. {
  465. GetAttachmentCount(pMsg, &cAttachments);
  466. }
  467. else if (m_pmp->pNoMsgData)
  468. {
  469. cAttachments = m_pmp->pNoMsgData->cAttachments;
  470. SetDlgItemInt(m_hwndGen, IDC_ATTACHMENTS, cAttachments, FALSE);
  471. }
  472. if (cAttachments)
  473. {
  474. SetDlgItemInt(m_hwndGen, IDC_ATTACHMENTS, cAttachments, FALSE);
  475. }
  476. else
  477. {
  478. LoadString(g_hLocRes, idsPropAttachNone, rgch, sizeof(rgch));
  479. SetDlgItemText(m_hwndGen, IDC_ATTACHMENTS, rgch);
  480. }
  481. // Priority
  482. // Get the priority from the message
  483. rVariant.vt = VT_UI4;
  484. Pri = IMSG_PRI_NORMAL;
  485. if (pMsg && SUCCEEDED(pMsg->GetProp(PIDTOSTR(PID_ATT_PRIORITY), 0, &rVariant)))
  486. Pri = (IMSGPRIORITY) rVariant.ulVal;
  487. else
  488. {
  489. Assert(m_pmp->pNoMsgData);
  490. Pri = m_pmp->pNoMsgData->Pri;
  491. }
  492. // Map the priority to a string
  493. switch (Pri)
  494. {
  495. case IMSG_PRI_LOW:
  496. ids = idsPriLow;
  497. break;
  498. case IMSG_PRI_HIGH:
  499. ids = idsPriHigh;
  500. break;
  501. default:
  502. ids = idsPriNormal;
  503. }
  504. // Set the string on the dialog
  505. LoadString(g_hLocRes, ids, rgch, ARRAYSIZE(rgch));
  506. SetDlgItemText(m_hwndGen, IDC_PRIORITY, rgch);
  507. // Sent
  508. if (pMsg)
  509. {
  510. *wszDate = 0;
  511. rVariant.vt = VT_FILETIME;
  512. pMsg->GetProp(PIDTOSTR(PID_ATT_SENTTIME), 0, &rVariant);
  513. AthFileTimeToDateTimeW(&rVariant.filetime, wszDate, ARRAYSIZE(wszDate), DTM_NOSECONDS);
  514. SetDlgItemTextWrapW(m_hwndGen, IDC_SENT, wszDate);
  515. }
  516. else if (m_pmp->dwFlags & ARF_UNSENT)
  517. {
  518. LoadString(g_hLocRes, idsUnderComp, rgch, ARRAYSIZE(rgchFmt));
  519. SetDlgItemText(m_hwndGen, IDC_SENT, rgch);
  520. }
  521. else
  522. {
  523. SetDlgItemText(m_hwndGen, IDC_SENT, m_pmp->pNoMsgData->pszSent);
  524. }
  525. // Recieved
  526. if (pMsg)
  527. {
  528. *wszDate = 0;
  529. rVariant.vt = VT_FILETIME;
  530. pMsg->GetProp(PIDTOSTR(PID_ATT_RECVTIME), 0, &rVariant);
  531. AthFileTimeToDateTimeW(&rVariant.filetime, wszDate, ARRAYSIZE(wszDate), DTM_NOSECONDS);
  532. SetDlgItemTextWrapW(m_hwndGen, IDC_RECEIVED, wszDate);
  533. }
  534. else if (m_pmp->dwFlags & ARF_UNSENT)
  535. {
  536. LoadString(g_hLocRes, idsUnderComp, rgch, ARRAYSIZE(rgchFmt));
  537. SetDlgItemText(m_hwndGen, IDC_RECEIVED, rgch);
  538. }
  539. // Free the string table
  540. for (register int i=0; i < freeMax; i++)
  541. if (rgszFree[i])
  542. MemFree(rgszFree[i]);
  543. }
  544. void CMsgProps::InitDetailsPage(HWND hwnd)
  545. {
  546. LPSTREAM pstm;
  547. BODYOFFSETS rOffset;
  548. char *psz;
  549. int cch;
  550. Assert(m_pmp);
  551. Assert(m_pmp->pMsg);
  552. // fill in the headers...
  553. if(m_pmp->pMsg->GetMessageSource(&pstm, 0)==S_OK)
  554. {
  555. HrRewindStream(pstm);
  556. m_pmp->pMsg->GetBodyOffsets(HBODY_ROOT, &rOffset);
  557. cch=rOffset.cbBodyStart;
  558. if(MemAlloc((LPVOID *)&psz, cch+1))
  559. {
  560. if(!pstm->Read(psz, cch, NULL))
  561. {
  562. psz[cch]=0; // null term this
  563. SetDlgItemText(hwnd, idcTxtHeaders, psz);
  564. }
  565. MemFree(psz);
  566. }
  567. ReleaseObj(pstm);
  568. }
  569. else
  570. EnableWindow(GetDlgItem(hwnd, idbMsgSource), FALSE);
  571. if (!m_pmp->fSecure || !m_pmp->pSecureMsg)
  572. ShowWindow(GetDlgItem(hwnd, idbSecMsgSource), SW_HIDE);
  573. }
  574. INT_PTR CALLBACK CMsgProps::DetailsPageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  575. {
  576. CMsgProps *pmprop=0;
  577. switch(msg)
  578. {
  579. case WM_INITDIALOG:
  580. pmprop=(CMsgProps *) ((PROPSHEETPAGE *)lParam)->lParam;
  581. SetDlgThisPtr(hwnd, (LPARAM)pmprop);
  582. Assert(pmprop);
  583. pmprop->InitDetailsPage(hwnd);
  584. return TRUE;
  585. case WM_COMMAND:
  586. pmprop=(CMsgProps *)GetDlgThisPtr(hwnd);
  587. if(GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED)
  588. {
  589. if (GET_WM_COMMAND_ID(wParam, lParam)==idbMsgSource)
  590. {
  591. MimeEditViewSource(pmprop->m_pmp->hwndParent, pmprop->m_pmp->pMsg);
  592. return(FALSE);
  593. }
  594. else if (GET_WM_COMMAND_ID(wParam, lParam)==idbSecMsgSource)
  595. {
  596. MimeEditViewSource(pmprop->m_pmp->hwndParent, pmprop->m_pmp->pSecureMsg);
  597. return(FALSE);
  598. }
  599. }
  600. else if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_SETFOCUS) {
  601. if (GET_WM_COMMAND_ID(wParam, lParam) == idcTxtHeaders) {
  602. // Remove the selection!
  603. SendDlgItemMessage(hwnd, idcTxtHeaders, EM_SETSEL, -1, -1);
  604. // fall through to default processing.
  605. }
  606. }
  607. return TRUE;
  608. case WM_NOTIFY:
  609. switch(((NMHDR FAR *)lParam)->code)
  610. {
  611. pmprop=(CMsgProps *)GetDlgThisPtr(hwnd);
  612. case PSN_APPLY:
  613. case PSN_KILLACTIVE:
  614. case PSN_SETACTIVE:
  615. return TRUE;
  616. }
  617. break;
  618. case WM_CLOSE:
  619. {
  620. PostMessage(GetParent(hwnd), WM_CLOSE, 0, 0);
  621. break;
  622. }
  623. }
  624. return FALSE;
  625. }
  626. #ifdef WIN16
  627. static const char s_cszDlgSec[] = "PDLGSECUTIRY";
  628. #endif
  629. INT_PTR CALLBACK CMsgProps::SecurityPageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  630. {
  631. PMSGPROP pMsgProp = (PMSGPROP)0;
  632. DLGSECURITY *pDlgSec;
  633. switch(msg)
  634. {
  635. case WM_INITDIALOG:
  636. {
  637. CMsgProps *pmprop;
  638. pmprop=(CMsgProps *) ((PROPSHEETPAGE *)lParam)->lParam;
  639. SetWndThisPtr(hwnd, (LPARAM)pmprop->m_pmp);
  640. if (pmprop)
  641. pmprop->InitSecurityPage(hwnd);
  642. }
  643. return TRUE;
  644. case WM_COMMAND:
  645. if (GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED)
  646. {
  647. switch(GET_WM_COMMAND_ID(wParam, lParam))
  648. {
  649. case idcAddCert:
  650. pDlgSec = (PDLGSECURITY)GET_DIALOG_SECURITY(hwnd);
  651. pMsgProp = (PMSGPROP)GetWndThisPtr(hwnd);
  652. // Get thumbprint into WAB and cert into AddressBook CAPI store
  653. // cert goes to store first so CAPI details page can find it
  654. if (pDlgSec && pMsgProp)
  655. {
  656. if (SUCCEEDED(HrAddSenderCertToWab(hwnd,
  657. pMsgProp->pMsg,
  658. pMsgProp->lpWabal,
  659. &pDlgSec->tbSenderThumbprint,
  660. &pDlgSec->blSymCaps,
  661. pDlgSec->ftSigningTime,
  662. WFF_CREATE | WFF_SHOWUI)))
  663. {
  664. AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthenaMail),
  665. MAKEINTRESOURCEW(idsSenderCertAdded), NULL, MB_ICONINFORMATION | MB_OK);
  666. }
  667. }
  668. return(FALSE);
  669. case idcVerifySig:
  670. pDlgSec = (PDLGSECURITY)GET_DIALOG_SECURITY(hwnd);
  671. if (CommonUI_ViewSigningCertificate(hwnd, pDlgSec->pSenderCert, pDlgSec->hcMsg))
  672. MessageBeep(MB_OK);
  673. return(FALSE);
  674. case idcViewCerts:
  675. pMsgProp = (PMSGPROP)GetWndThisPtr(hwnd);
  676. return (DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddMsgProp_Sec_ViewCert),
  677. hwnd, ViewSecCertDlgProc, (LPARAM) (pMsgProp)) == IDOK);
  678. case idcCertHelp:
  679. OEHtmlHelp(hwnd, c_szCtxHelpFileHTMLCtx, HH_DISPLAY_TOPIC, (DWORD_PTR)(LPCSTR)"mail_overview_send_secure_messages.htm");
  680. return(FALSE);
  681. default:
  682. break;
  683. }
  684. }
  685. return TRUE;
  686. case WM_DESTROY:
  687. pDlgSec = (PDLGSECURITY)GET_DIALOG_SECURITY(hwnd);
  688. if (pDlgSec)
  689. {
  690. if (pDlgSec->pSenderCert)
  691. CertFreeCertificateContext(pDlgSec->pSenderCert);
  692. if (pDlgSec->pEncSenderCert)
  693. CertFreeCertificateContext(pDlgSec->pEncSenderCert);
  694. if (pDlgSec->pEncryptionCert)
  695. CertFreeCertificateContext(pDlgSec->pEncryptionCert);
  696. if (pDlgSec->tbSenderThumbprint.pBlobData)
  697. MemFree(pDlgSec->tbSenderThumbprint.pBlobData);
  698. if (pDlgSec->hcMsg) {
  699. if (! CertCloseStore(pDlgSec->hcMsg, 0)) {
  700. DOUTL(DOUTL_CRYPT, "CertCloseStore (message store) failed");
  701. }
  702. pDlgSec->hcMsg = NULL;
  703. }
  704. MemFree(pDlgSec);
  705. CLEAR_DIALOG_SECURITY(hwnd);
  706. }
  707. return NULL;
  708. case WM_NOTIFY:
  709. switch(((NMHDR FAR *)lParam)->code)
  710. {
  711. case PSN_APPLY:
  712. case PSN_KILLACTIVE:
  713. case PSN_SETACTIVE:
  714. return TRUE;
  715. }
  716. break;
  717. }
  718. return FALSE;
  719. }
  720. void CMsgProps::InitSecurityPage(HWND hwnd)
  721. {
  722. DWORD cb;
  723. DWORD i;
  724. HRESULT hr;
  725. TCHAR szYes[CCHMAX_STRINGRES/4],
  726. szNo[CCHMAX_STRINGRES/4],
  727. szMaybe[CCHMAX_STRINGRES/4],
  728. szNA[CCHMAX_STRINGRES/4];
  729. HWND hwndCtrl;
  730. DLGSECURITY *pDlgSec;
  731. IMimeBody *pBody;
  732. PROPVARIANT var;
  733. ULONG secType, ulROVal;
  734. BOOL fNoEncAlg = TRUE;
  735. LPTSTR sz;
  736. LPMIMEMESSAGE pMsg = m_pmp->pMsg;
  737. PCCERT_CONTEXT pccert = NULL;
  738. TCHAR szTmp[CCHMAX_STRINGRES];
  739. HBODY hBody = NULL;
  740. SECSTATE SecState ={0};
  741. // We need these to set the statics
  742. LoadString(g_hLocRes, idsOui, szYes, ARRAYSIZE(szYes));
  743. LoadString(g_hLocRes, idsNon, szNo, ARRAYSIZE(szNo));
  744. LoadString(g_hLocRes, idsMaybe, szMaybe, ARRAYSIZE(szMaybe));
  745. LoadString(g_hLocRes, idsNotApplicable, szNA, ARRAYSIZE(szNA));
  746. if(FAILED(HrGetSecurityState(m_pmp->pMsg, &SecState, &hBody)))
  747. return;
  748. CleanupSECSTATE(&SecState);
  749. if (FAILED(m_pmp->pMsg->BindToObject(hBody ? hBody : HBODY_ROOT, IID_IMimeBody, (void **)&pBody)))
  750. return;
  751. if (SUCCEEDED(pBody->GetOption(OID_SECURITY_TYPE, &var)))
  752. secType = var.ulVal;
  753. // Set up storage for the other security info that
  754. // we care about
  755. if (MemAlloc((LPVOID *)&pDlgSec, sizeof(*pDlgSec)))
  756. {
  757. memset(pDlgSec, 0, sizeof(*pDlgSec));
  758. #ifdef _WIN64
  759. if (SUCCEEDED(pBody->GetOption(OID_SECURITY_HCERTSTORE_64, &var)))
  760. {
  761. pDlgSec->hcMsg = (HCERTSTORE)(var.pulVal); // Closed in WM_DESTROY
  762. }
  763. if (SUCCEEDED(pBody->GetOption(OID_SECURITY_CERT_SIGNING_64, &var)))
  764. {
  765. // we don't have to dupe the pDlgSec cert because we won't free
  766. // the var's.
  767. pDlgSec->pSenderCert = (PCCERT_CONTEXT)(var.pulVal);
  768. }
  769. #else // !_WIN64
  770. if (SUCCEEDED(pBody->GetOption(OID_SECURITY_HCERTSTORE, &var)))
  771. {
  772. pDlgSec->hcMsg = (HCERTSTORE) var.ulVal; // Closed in WM_DESTROY
  773. }
  774. if (SUCCEEDED(pBody->GetOption(OID_SECURITY_CERT_SIGNING, &var)))
  775. {
  776. // we don't have to dupe the pDlgSec cert because we won't free
  777. // the var's.
  778. pDlgSec->pSenderCert = (PCCERT_CONTEXT) var.ulVal;
  779. }
  780. #endif // _WIN64
  781. hr = GetSigningCert(m_pmp->pMsg, &pccert,
  782. &pDlgSec->tbSenderThumbprint, &pDlgSec->blSymCaps,
  783. &pDlgSec->ftSigningTime);
  784. if (FAILED(hr) && (hr != MIME_E_SECURITY_NOCERT))
  785. {
  786. SUCCEEDED(hr);
  787. }
  788. }
  789. SET_DIALOG_SECURITY(hwnd, (LPARAM)pDlgSec);
  790. // we use the same dlgproc for sent items and recd items
  791. // so use if statements to check for existance of all
  792. // non-common controls
  793. // set up the statics based on the message's info
  794. if(IsSigned(secType))
  795. {
  796. LPSTR szCertEmail = SzGetCertificateEmailAddress(pccert);
  797. SetDlgItemText(hwnd, idcStaticDigSign, szCertEmail);
  798. MemFree(szCertEmail);
  799. SetDlgItemText(hwnd, idcStaticRevoked,
  800. (LPCTSTR)(((DwGetOption(OPT_REVOKE_CHECK) != 0) && !g_pConMan->IsGlobalOffline() && CheckCDPinCert(pMsg))
  801. ? szYes
  802. : szNo));
  803. }
  804. else
  805. {
  806. SetDlgItemText(hwnd, idcStaticDigSign, szNA);
  807. SetDlgItemText(hwnd, idcStaticRevoked, szNA);
  808. }
  809. SetDlgItemText(hwnd, idcStaticEncrypt,
  810. (LPCTSTR)(IsEncrypted(secType)
  811. ? szYes
  812. : szNo));
  813. if (SUCCEEDED(pBody->GetOption(OID_SECURITY_RO_MSG_VALIDITY, &var)))
  814. ulROVal = var.ulVal;
  815. else
  816. ulROVal = MSV_INVALID|MSV_UNVERIFIABLE;
  817. #ifdef SMIME_V3
  818. if(!IsSMIME3Supported())
  819. {
  820. LoadString(g_hLocRes, idsRecUnknown, szTmp, ARRAYSIZE(szTmp));
  821. SendMessage(GetDlgItem(hwnd, idcRetRecReq), WM_SETTEXT, 0, LPARAM(LPCTSTR(szTmp)));
  822. }
  823. else
  824. {
  825. if(FPresentPolicyRegInfo())
  826. {
  827. if ((hwndCtrl = GetDlgItem(hwnd, idcSecLabelText)) && IsSigned(secType))
  828. {
  829. LPWSTR pwStr = NULL;
  830. // Set Label text
  831. if((hr = HrGetLabelString(m_pmp->pMsg, &pwStr)) == S_OK)
  832. {
  833. SetWindowTextWrapW(hwndCtrl, pwStr);
  834. SafeMemFree(pwStr);
  835. }
  836. else
  837. SendMessage(hwndCtrl, WM_SETTEXT, 0, LPARAM(LPCTSTR(SUCCEEDED(hr) ? szYes : szNo)));
  838. }
  839. }
  840. // Check receipt request
  841. if ((hwndCtrl = GetDlgItem(hwnd, idcRetRecReq)))
  842. {
  843. if (!IsSigned(secType))
  844. sz = szNA;
  845. else
  846. {
  847. PSMIME_RECEIPT pSecReceipt = NULL;
  848. if(CheckDecodedForReceipt(m_pmp->pMsg, &pSecReceipt) == S_OK)
  849. sz = szNA;
  850. else
  851. sz = (secType & MST_RECEIPT_REQUEST) ? szYes : szNo;
  852. SafeMemFree(pSecReceipt);
  853. }
  854. SendMessage(hwndCtrl, WM_SETTEXT, 0, LPARAM(LPCTSTR(sz)));
  855. }
  856. }
  857. #endif // SMIME_V3
  858. ////////
  859. // begin sign dependent block
  860. if (!IsSigned(secType))
  861. sz = szNA;
  862. if ((hwndCtrl = GetDlgItem(hwnd, idcStaticAlter)))
  863. {
  864. if (IsSigned(secType))
  865. {
  866. sz = (MSV_SIGNATURE_MASK & ulROVal)
  867. ? (MSV_BADSIGNATURE & ulROVal)
  868. ? szNo
  869. : szMaybe
  870. : ((pccert != NULL) ? szYes : szMaybe);
  871. }
  872. SendMessage(hwndCtrl, WM_SETTEXT, 0, LPARAM(LPCTSTR(sz)));
  873. }
  874. if ((hwndCtrl = GetDlgItem(hwnd, idcStaticTrust)) &&
  875. SUCCEEDED(pBody->GetOption(OID_SECURITY_USER_VALIDITY, &var)))
  876. {
  877. if (IsSigned(secType))
  878. {
  879. sz = (ATHSEC_TRUSTSTATEMASK & var.ulVal)
  880. ? ((ATHSEC_NOTRUSTNOTTRUSTED & var.ulVal) || (ulROVal & MSV_EXPIRED_SIGNINGCERT))
  881. ? szNo
  882. : szMaybe
  883. : szYes;
  884. }
  885. SendMessage(hwndCtrl, WM_SETTEXT, 0, LPARAM(LPCTSTR(sz)));
  886. }
  887. if((hwndCtrl = GetDlgItem(hwnd, idcStaticRevStatus)) && IsSigned(secType))
  888. {
  889. if((DwGetOption(OPT_REVOKE_CHECK) != 0) && !g_pConMan->IsGlobalOffline() && CheckCDPinCert(pMsg))
  890. {
  891. if(var.ulVal & ATHSEC_NOTRUSTREVOKED)
  892. LoadString(g_hLocRes, idsWrnSecurityCertRevoked, szTmp, ARRAYSIZE(szTmp));
  893. else if(var.ulVal & ATHSEC_NOTRUSTREVFAIL)
  894. LoadString(g_hLocRes, idsWrnSecurityRevFail, szTmp, ARRAYSIZE(szTmp));
  895. else
  896. LoadString(g_hLocRes, idsOkSecurityCertRevoked, szTmp, ARRAYSIZE(szTmp));
  897. }
  898. else if((DwGetOption(OPT_REVOKE_CHECK) != 0) && !g_pConMan->IsGlobalOffline() && !CheckCDPinCert(pMsg))
  899. LoadString(g_hLocRes, idsWrnSecurityNoCDP, szTmp, ARRAYSIZE(szTmp));
  900. else if((DwGetOption(OPT_REVOKE_CHECK) != 0) && g_pConMan->IsGlobalOffline())
  901. LoadString(g_hLocRes, idsRevokationOffline, szTmp, ARRAYSIZE(szTmp));
  902. else if(DwGetOption(OPT_REVOKE_CHECK) == 0)
  903. LoadString(g_hLocRes, idsRevokationTurnedOff, szTmp, ARRAYSIZE(szTmp));
  904. SendMessage(hwndCtrl, WM_SETTEXT, 0, LPARAM(LPCTSTR(szTmp)));
  905. }
  906. if (SUCCEEDED(pBody->GetOption(OID_SECURITY_CERT_INCLUDED, &var)))
  907. {
  908. if (IsSigned(secType))
  909. sz = (var.boolVal == TRUE) ? szYes : szNo;
  910. SetDlgItemText(hwnd, idcStaticCertInc, LPCTSTR(sz));
  911. }
  912. // end signing dependent block
  913. ////////
  914. if (IsEncrypted(secType) && SUCCEEDED(pBody->GetOption(OID_SECURITY_ALG_BULK, &var)))
  915. {
  916. Assert(var.vt == VT_BLOB);
  917. if (var.vt == VT_BLOB && var.blob.cbSize && var.blob.pBlobData)
  918. {
  919. LPCTSTR pszProtocol = NULL;
  920. // Convert the SYMCAPS blob to an "encrypted using" string
  921. if (SUCCEEDED(MimeOleAlgNameFromSMimeCap(var.blob.pBlobData, var.blob.cbSize,
  922. &pszProtocol)))
  923. { // Note: returns a static string. Don't free it.
  924. if (pszProtocol)
  925. {
  926. SendMessage(GetDlgItem(hwnd, idcStaticEncAlg), WM_SETTEXT, 0, (LPARAM)pszProtocol);
  927. fNoEncAlg = FALSE;
  928. }
  929. }
  930. // Free the data
  931. MemFree(var.blob.pBlobData);
  932. }
  933. }
  934. if (fNoEncAlg)
  935. {
  936. SendMessage(GetDlgItem(hwnd, idcStaticEncAlg), WM_SETTEXT, 0,
  937. LPARAM(LPCTSTR(szNA)));
  938. }
  939. if (pccert != NULL)
  940. CertFreeCertificateContext(pccert);
  941. ReleaseObj(pBody);
  942. return;
  943. }
  944. INT_PTR CALLBACK ViewSecCertDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  945. {
  946. LPMIMEMESSAGE pMsg = NULL;
  947. IMimeBody *pBody;
  948. PROPVARIANT var;
  949. DLGSECURITY *pDlgSec;
  950. ULONG secType, ulROVal;
  951. HWND hwndCtrl = NULL;
  952. PMSGPROP pMsgProp = (PMSGPROP)0;
  953. HRESULT hr = S_OK;
  954. TCHAR szTmp[CCHMAX_STRINGRES];
  955. HBODY hBody = NULL;
  956. HBODY hInerBody = NULL;
  957. SECSTATE SecState ={0};
  958. switch (message)
  959. {
  960. case WM_INITDIALOG:
  961. TCHAR szNA[CCHMAX_STRINGRES/4];
  962. SetWndThisPtr(hwnd, lParam);
  963. CenterDialog(hwnd);
  964. pMsgProp = (PMSGPROP) lParam;
  965. pMsg = pMsgProp->pMsg;
  966. LoadString(g_hLocRes, idsNotApplicable, szNA, ARRAYSIZE(szNA));
  967. if(FAILED(HrGetSecurityState(pMsgProp->pMsg, &SecState, &hBody)))
  968. return FALSE;
  969. if(FAILED(HrGetInnerLayer(pMsgProp->pMsg, &hInerBody)))
  970. return FALSE;
  971. if((!IsSignTrusted(&SecState) || !IsEncryptionOK(&SecState)) && (hBody != hInerBody))
  972. EnableWindow(GetDlgItem(hwnd, idcAddCert), FALSE);
  973. CleanupSECSTATE(&SecState);
  974. if (FAILED(pMsgProp->pMsg->BindToObject(hBody ? hBody : HBODY_ROOT, IID_IMimeBody, (void **)&pBody)))
  975. return FALSE;
  976. if (SUCCEEDED(pBody->GetOption(OID_SECURITY_TYPE, &var)))
  977. secType = var.ulVal;
  978. // Set up storage for the other security info that
  979. // we care about
  980. if (MemAlloc((LPVOID *)&pDlgSec, sizeof(*pDlgSec)))
  981. {
  982. memset(pDlgSec, 0, sizeof(*pDlgSec));
  983. #ifdef _WIN64
  984. if (SUCCEEDED(pBody->GetOption(OID_SECURITY_HCERTSTORE_64, &var)))
  985. {
  986. pDlgSec->hcMsg = (HCERTSTORE)(var.pulVal); // Closed in WM_DESTROY
  987. }
  988. if (SUCCEEDED(pBody->GetOption(OID_SECURITY_CERT_SIGNING_64, &var)))
  989. {
  990. // we don't have to dupe the pDlgSec cert because we won't free
  991. // the var's.
  992. pDlgSec->pSenderCert = (PCCERT_CONTEXT)(var.pulVal);
  993. }
  994. #else // !_WIN64
  995. if (SUCCEEDED(pBody->GetOption(OID_SECURITY_HCERTSTORE, &var)))
  996. {
  997. pDlgSec->hcMsg = (HCERTSTORE) var.ulVal; // Closed in WM_DESTROY
  998. }
  999. if (SUCCEEDED(pBody->GetOption(OID_SECURITY_CERT_SIGNING, &var)))
  1000. {
  1001. // we don't have to dupe the pDlgSec cert because we won't free
  1002. // the var's.
  1003. pDlgSec->pSenderCert = (PCCERT_CONTEXT) var.ulVal;
  1004. }
  1005. #endif // _WIN64
  1006. hr = GetSignerEncryptionCert(pMsgProp->pMsg, &pDlgSec->pEncSenderCert,
  1007. &pDlgSec->tbSenderThumbprint, &pDlgSec->blSymCaps,
  1008. &pDlgSec->ftSigningTime);
  1009. if (FAILED(hr) && (hr != MIME_E_SECURITY_NOCERT))
  1010. {
  1011. SUCCEEDED(hr);
  1012. }
  1013. }
  1014. if(IsEncrypted(secType))
  1015. {
  1016. #ifdef _WIN64
  1017. if (SUCCEEDED(hr = pBody->GetOption(OID_SECURITY_CERT_DECRYPTION_64, &var)))
  1018. {
  1019. Assert(VT_UI8 == var.vt);
  1020. if ((PCCERT_CONTEXT)(var.pulVal))
  1021. pDlgSec->pEncryptionCert = (PCCERT_CONTEXT)(var.pulVal);
  1022. }
  1023. #else // !_WIN64
  1024. if (SUCCEEDED(hr = pBody->GetOption(OID_SECURITY_CERT_DECRYPTION, &var)))
  1025. {
  1026. Assert(VT_UI4 == var.vt);
  1027. if (*(PCCERT_CONTEXT *)(&(var.uhVal)))
  1028. pDlgSec->pEncryptionCert = *(PCCERT_CONTEXT *)(&(var.uhVal));
  1029. }
  1030. #endif // _WIN64
  1031. }
  1032. else
  1033. pDlgSec->pEncryptionCert = NULL;
  1034. SET_DIALOG_SECURITY(hwnd, (LPARAM)pDlgSec);
  1035. if (pDlgSec->pEncSenderCert == NULL)
  1036. {
  1037. // Disable Add to Address Book button
  1038. if ((hwndCtrl = GetDlgItem(hwnd, idcAddCert)))
  1039. EnableWindow(hwndCtrl, FALSE);
  1040. // Disable View sender's encrypt cert.
  1041. if ((hwndCtrl = GetDlgItem(hwnd, idcSendersEncryptionCert)))
  1042. EnableWindow(hwndCtrl, FALSE);
  1043. LoadString(g_hLocRes, idsEncrCertNotIncluded, szTmp, ARRAYSIZE(szTmp));
  1044. SetDlgItemText(hwnd, idcStaticSendersCert, LPCTSTR(szTmp));
  1045. }
  1046. //
  1047. if (pDlgSec->pSenderCert == NULL)
  1048. {
  1049. if ((hwndCtrl = GetDlgItem(hwnd, idcVerifySig)))
  1050. EnableWindow(hwndCtrl, FALSE);
  1051. LoadString(g_hLocRes, idsSignCertNotIncl, szTmp, ARRAYSIZE(szTmp));
  1052. SetDlgItemText(hwnd, idcStaticSigningCert, LPCTSTR(szTmp));
  1053. }
  1054. if(pDlgSec->pEncryptionCert == NULL)
  1055. {
  1056. if ((hwndCtrl = GetDlgItem(hwnd, idcViewEncrytionCert)))
  1057. EnableWindow(hwndCtrl, FALSE);
  1058. if(IsEncrypted(secType))
  1059. LoadString(g_hLocRes, idsEncrCertNotFoundOnPC, szTmp, ARRAYSIZE(szTmp));
  1060. else
  1061. LoadString(g_hLocRes, idsMsgWasNotEncrypted, szTmp, ARRAYSIZE(szTmp));
  1062. SetDlgItemText(hwnd, idcStaticEncryptionCert, LPCTSTR(szTmp));
  1063. }
  1064. if(pDlgSec->blSymCaps.cbSize > 0)
  1065. {
  1066. // Convert the SYMCAPS blob to an "encrypted using" string
  1067. LPCTSTR pszProtocol = NULL;
  1068. if (SUCCEEDED(MimeOleAlgNameFromSMimeCap(pDlgSec->blSymCaps.pBlobData, pDlgSec->blSymCaps.cbSize,
  1069. &pszProtocol)))
  1070. { // Note: returns a static string. Don't free it.
  1071. if (pszProtocol)
  1072. SetDlgItemText(hwnd, idcStaticEncryptAlgorithm, LPCTSTR(pszProtocol));
  1073. }
  1074. }
  1075. else
  1076. SetDlgItemText(hwnd, idcStaticEncryptAlgorithm, LPCTSTR(szNA));
  1077. if(pBody)
  1078. ReleaseObj(pBody);
  1079. break;
  1080. case WM_COMMAND:
  1081. pDlgSec = (PDLGSECURITY)GET_DIALOG_SECURITY(hwnd);
  1082. pMsgProp = (PMSGPROP)GetWndThisPtr(hwnd);
  1083. pMsg = pMsgProp->pMsg;
  1084. switch (LOWORD(wParam))
  1085. {
  1086. case idcAddCert:
  1087. // Get thumbprint into WAB and cert into AddressBook CAPI store
  1088. // cert goes to store first so CAPI details page can find it
  1089. if (pDlgSec && pMsgProp)
  1090. {
  1091. if (SUCCEEDED(HrAddSenderCertToWab(hwnd,
  1092. pMsgProp->pMsg,
  1093. pMsgProp->lpWabal,
  1094. &pDlgSec->tbSenderThumbprint,
  1095. &pDlgSec->blSymCaps,
  1096. pDlgSec->ftSigningTime,
  1097. WFF_CREATE | WFF_SHOWUI)))
  1098. {
  1099. AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthenaMail),
  1100. MAKEINTRESOURCEW(idsSenderCertAdded), NULL, MB_ICONINFORMATION | MB_OK);
  1101. }
  1102. }
  1103. break;
  1104. case idcVerifySig:
  1105. if (CommonUI_ViewSigningCertificate(hwnd, pDlgSec->pSenderCert, pDlgSec->hcMsg))
  1106. MessageBeep(MB_OK);
  1107. return(FALSE);
  1108. case idcViewEncrytionCert:
  1109. if (CommonUI_ViewSigningCertificate(hwnd, pDlgSec->pEncryptionCert, pDlgSec->hcMsg))
  1110. MessageBeep(MB_OK);
  1111. return(FALSE);
  1112. case idcSendersEncryptionCert:
  1113. if (CommonUI_ViewSigningCertificate(hwnd, pDlgSec->pEncSenderCert, pDlgSec->hcMsg))
  1114. MessageBeep(MB_OK);
  1115. return(FALSE);
  1116. case IDOK:
  1117. case IDCANCEL:
  1118. EndDialog(hwnd, LOWORD(wParam));
  1119. return(TRUE);
  1120. }
  1121. break; // wm_command
  1122. case WM_CLOSE:
  1123. SendMessage(hwnd, WM_COMMAND, IDCANCEL, 0L);
  1124. return (TRUE);
  1125. case WM_DESTROY:
  1126. pDlgSec = (PDLGSECURITY)GET_DIALOG_SECURITY(hwnd);
  1127. if (pDlgSec)
  1128. {
  1129. if (pDlgSec->pSenderCert)
  1130. CertFreeCertificateContext(pDlgSec->pSenderCert);
  1131. if (pDlgSec->pEncSenderCert)
  1132. CertFreeCertificateContext(pDlgSec->pEncSenderCert);
  1133. if (pDlgSec->pEncryptionCert)
  1134. CertFreeCertificateContext(pDlgSec->pEncryptionCert);
  1135. if (pDlgSec->tbSenderThumbprint.pBlobData)
  1136. MemFree(pDlgSec->tbSenderThumbprint.pBlobData);
  1137. if (pDlgSec->hcMsg)
  1138. {
  1139. if (! CertCloseStore(pDlgSec->hcMsg, 0))
  1140. {
  1141. DOUTL(DOUTL_CRYPT, "CertCloseStore (message store) failed");
  1142. }
  1143. pDlgSec->hcMsg = NULL;
  1144. }
  1145. MemFree(pDlgSec);
  1146. CLEAR_DIALOG_SECURITY(hwnd);
  1147. }
  1148. } // message switch
  1149. return(FALSE);
  1150. }