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
1352 lines
43 KiB
/*
|
|
* m s g p r o p . c p p
|
|
*
|
|
* Purpose:
|
|
* Implements propsheet for a msg
|
|
*
|
|
* Owner:
|
|
* brettm.
|
|
*
|
|
* History:
|
|
* Feb '95: Stolen from Capone Sources - brettm
|
|
*
|
|
* Copyright (C) Microsoft Corp. 1993, 1994.
|
|
*/
|
|
|
|
#include <pch.hxx>
|
|
#ifdef WIN16
|
|
#include "mapi.h"
|
|
#endif
|
|
#include <resource.h>
|
|
#include <richedit.h>
|
|
#include "goptions.h"
|
|
#include "mimeole.h"
|
|
#include "mimeutil.h"
|
|
#include "msgprop.h"
|
|
#include "addrobj.h"
|
|
#include "mpropdlg.h"
|
|
#ifndef WIN16
|
|
#include "mapi.h"
|
|
#endif
|
|
#include "ipab.h"
|
|
#include <secutil.h>
|
|
#include <seclabel.h>
|
|
#include <certs.h>
|
|
#include <demand.h>
|
|
#include <strconst.h>
|
|
#include <shlwapi.h>
|
|
#include <shlwapip.h>
|
|
#include "instance.h"
|
|
#include "conman.h"
|
|
#include "shared.h"
|
|
#include "htmlhelp.h"
|
|
|
|
|
|
/*
|
|
* m a c r o s and c o n s t a n t s
|
|
*
|
|
*/
|
|
#define KILOBYTE 1024L
|
|
|
|
#define PROP_ERROR(prop) (PROP_TYPE(prop.ulPropTag) == PT_ERROR)
|
|
|
|
#ifdef WIN16
|
|
#ifndef GetLastError
|
|
#define GetLastError() ((DWORD)-1)
|
|
#endif
|
|
#endif //!WIN16
|
|
|
|
|
|
#ifdef WIN16
|
|
#define SET_DIALOG_SECURITY(hwnd, value) SetProp32(hwnd, s_cszDlgSec, (LPVOID)value)
|
|
#define GET_DIALOG_SECURITY(hwnd) GetProp32(hwnd, s_cszDlgSec)
|
|
#define CLEAR_DIALOG_SECURITY(hwnd) RemoveProp32(hwnd, s_cszDlgSec);
|
|
#else
|
|
#define SET_DIALOG_SECURITY(hwnd, value) SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM)value)
|
|
#define GET_DIALOG_SECURITY(hwnd) GetWindowLongPtr(hwnd, DWLP_USER);
|
|
#define CLEAR_DIALOG_SECURITY(hwnd) SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM)NULL)
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
* s t r u c t u r e s
|
|
*
|
|
*/
|
|
|
|
struct DLGSECURITYtag
|
|
{
|
|
PCX509CERT pSenderCert;
|
|
PCCERT_CONTEXT pEncSenderCert;
|
|
PCCERT_CONTEXT pEncryptionCert;
|
|
THUMBBLOB tbSenderThumbprint;
|
|
BLOB blSymCaps;
|
|
FILETIME ftSigningTime;
|
|
HCERTSTORE hcMsg;
|
|
};
|
|
typedef struct DLGSECURITYtag DLGSECURITY;
|
|
typedef DLGSECURITY *PDLGSECURITY;
|
|
typedef const DLGSECURITY *PCDLGSECURITY;
|
|
|
|
/*
|
|
* c l a s s e s
|
|
*
|
|
*/
|
|
|
|
|
|
class CMsgProps
|
|
{
|
|
public:
|
|
CMsgProps();
|
|
~CMsgProps();
|
|
|
|
HRESULT HrDoProps(PMSGPROP pmp);
|
|
|
|
static INT_PTR CALLBACK GeneralPageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
|
static INT_PTR CALLBACK DetailsPageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
|
static INT_PTR CALLBACK SecurityPageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
|
static INT_PTR CALLBACK EncryptionPageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
|
|
|
void InitGeneralPage();
|
|
void InitDetailsPage(HWND hwnd);
|
|
void InitSecurityPage(HWND hwnd);
|
|
|
|
private:
|
|
HIMAGELIST m_himl;
|
|
HWND m_hwndGen;
|
|
HWND m_hwndGenSource;
|
|
PMSGPROP m_pmp;
|
|
};
|
|
|
|
|
|
|
|
// Function declarations ////////////////////////////////////////
|
|
// msg source dialog is modeless, so it can't be in the CProps dialog.
|
|
|
|
/*
|
|
* p r o t o t y p e s
|
|
*
|
|
*/
|
|
void SecurityOnWMCreate(HWND hwnd, LPARAM lParam);
|
|
INT_PTR CALLBACK ViewSecCertDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
|
|
|
|
/*
|
|
* f u n c t i o n s
|
|
*
|
|
*/
|
|
|
|
|
|
//
|
|
// FUNCTION: HrMsgProperties()
|
|
//
|
|
// PURPOSE: Displays the property sheet for the specified message.
|
|
//
|
|
// PARAMETERS:
|
|
// [in] pmp - Information needed to identify the message.
|
|
//
|
|
HRESULT HrMsgProperties(PMSGPROP pmp)
|
|
{
|
|
CMsgProps *pMsgProp = 0;
|
|
HRESULT hr;
|
|
|
|
TraceCall("HrMsgProperties");
|
|
|
|
// Create the property sheet object
|
|
pMsgProp = new CMsgProps();
|
|
if (!pMsgProp)
|
|
return E_OUTOFMEMORY;
|
|
|
|
// Tell the object to do it's thing. This won't go away until the
|
|
// property sheet is dismissed.
|
|
hr = pMsgProp->HrDoProps(pmp);
|
|
|
|
// Free the object
|
|
if (pMsgProp)
|
|
delete pMsgProp;
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
CMsgProps::CMsgProps()
|
|
{
|
|
m_himl = 0;
|
|
m_hwndGen = 0;
|
|
m_hwndGenSource = 0;
|
|
m_pmp = NULL;
|
|
}
|
|
|
|
CMsgProps::~CMsgProps()
|
|
{
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// FUNCTION: CMsgProps::HrDoProps()
|
|
//
|
|
// PURPOSE: Initializes the structures used to create the prop sheet
|
|
// and then displays the sheet.
|
|
//
|
|
// PARAMETERS:
|
|
// [in] pmp - Information needed to identify the message.
|
|
//
|
|
// RETURN VALUE:
|
|
// HRESULT
|
|
//
|
|
HRESULT CMsgProps::HrDoProps(PMSGPROP pmp)
|
|
{
|
|
PROPSHEETHEADER psh;
|
|
PROPSHEETPAGE psp[3];
|
|
BOOL fApply = FALSE;
|
|
HRESULT hr;
|
|
LPTSTR pszSubject = NULL;
|
|
LPTSTR pszFree = NULL;
|
|
TCHAR rgch[256] = "";
|
|
|
|
TraceCall("CMsgProps::HrDoProps");
|
|
|
|
// Zero init the prop sheet structures
|
|
ZeroMemory(&psh, sizeof(psh));
|
|
ZeroMemory(&psp, sizeof(psp));
|
|
|
|
// Double check that we have the information we need to do this.
|
|
if (pmp == NULL || (pmp->pMsg == NULL && pmp->pNoMsgData == NULL))
|
|
return E_INVALIDARG;
|
|
|
|
Assert(pmp->hwndParent);
|
|
|
|
// Stash this pointer
|
|
m_pmp = pmp;
|
|
|
|
// Page zero is the general tab
|
|
psp[0].dwSize = sizeof(PROPSHEETPAGE);
|
|
psp[0].dwFlags = PSP_USETITLE;
|
|
psp[0].hInstance = g_hLocRes;
|
|
psp[0].pszTemplate = MAKEINTRESOURCE(iddMsgProp_General);
|
|
psp[0].pfnDlgProc = GeneralPageProc;
|
|
psp[0].pszTitle = MAKEINTRESOURCE(idsPropPageGeneral);
|
|
psp[0].lParam = (LPARAM) this;
|
|
|
|
// Increment the number of pages
|
|
psh.nPages++;
|
|
|
|
// If the message is not unsent, then we also display the "Details" tab.
|
|
if (!(pmp->dwFlags & ARF_UNSENT) || (pmp->dwFlags & ARF_SUBMITTED))
|
|
{
|
|
psp[psh.nPages].dwSize = sizeof(PROPSHEETPAGE);
|
|
psp[psh.nPages].dwFlags = PSP_USETITLE;
|
|
psp[psh.nPages].hInstance = g_hLocRes;
|
|
psp[psh.nPages].pszTemplate = MAKEINTRESOURCE(iddMsgProp_Details);
|
|
psp[psh.nPages].pfnDlgProc = DetailsPageProc;
|
|
psp[psh.nPages].pszTitle = MAKEINTRESOURCE(idsPropPageDetails);
|
|
psp[psh.nPages].lParam = (LPARAM) this;
|
|
|
|
// If the caller wanted this to be the first page the user
|
|
// sees, set it to be the start page.
|
|
if (MP_DETAILS == pmp->mpStartPage)
|
|
psh.nStartPage = psh.nPages;
|
|
|
|
// Increment the number of pages
|
|
psh.nPages++;
|
|
}
|
|
|
|
// If the message is secure, add the security pages
|
|
if (pmp->fSecure && (!(pmp->dwFlags & ARF_UNSENT) || (pmp->dwFlags & ARF_SUBMITTED)))
|
|
{
|
|
psp[psh.nPages].dwSize = sizeof(PROPSHEETPAGE);
|
|
psp[psh.nPages].dwFlags = PSP_USETITLE;
|
|
psp[psh.nPages].hInstance = g_hLocRes;
|
|
psp[psh.nPages].pszTemplate = MAKEINTRESOURCE(iddMsgProp_Security_Msg);
|
|
psp[psh.nPages].pfnDlgProc = SecurityPageProc;
|
|
psp[psh.nPages].pszTitle = MAKEINTRESOURCE(idsPropPageSecurity);
|
|
psp[psh.nPages].lParam = (LPARAM) this;
|
|
|
|
// If the caller wanted this to be the first page the user
|
|
// sees, set it to be the start page.
|
|
if (MP_SECURITY == pmp->mpStartPage)
|
|
psh.nStartPage = psh.nPages;
|
|
|
|
// Increment the number of pages
|
|
psh.nPages++;
|
|
}
|
|
|
|
// Property sheet header information
|
|
psh.dwSize = sizeof(PROPSHEETHEADER);
|
|
psh.dwFlags = PSH_PROPSHEETPAGE | PSH_USEPAGELANG | ((fApply) ? 0 : PSH_NOAPPLYNOW);
|
|
psh.hwndParent = pmp->hwndParent;
|
|
psh.hInstance = g_hLocRes;
|
|
|
|
// The title of the property sheet is the same as the subject. So now we
|
|
// need to get the subject from either the message or message info.
|
|
if (pmp->pMsg)
|
|
{
|
|
// Get the subject from the message
|
|
if (SUCCEEDED(MimeOleGetBodyPropA(pmp->pMsg, HBODY_ROOT,
|
|
PIDTOSTR(PID_HDR_SUBJECT), NOFLAGS,
|
|
&pszSubject)))
|
|
{
|
|
// We'll need to free this string later
|
|
pszFree = pszSubject;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AssertSz(pmp->pNoMsgData, "CMsgProp::HrDoProps() - Need to provide either a Message or Message Info");
|
|
pszSubject = (LPTSTR) pmp->pNoMsgData->pszSubject;
|
|
}
|
|
|
|
// If there was no subject on the message, set the title to be "No Subject"
|
|
if (!pszSubject || !*pszSubject)
|
|
{
|
|
LoadString(g_hLocRes, idsNoSubject, rgch, sizeof(rgch));
|
|
pszSubject = rgch;
|
|
}
|
|
|
|
// Clean up the subject string before we use it. Tabs look like pretty bad.
|
|
ConvertTabsToSpaces(pszSubject);
|
|
|
|
// Set the subject as the property sheet title.
|
|
psh.pszCaption = pszSubject;
|
|
|
|
// Provide the array of pages. The number was set along the way.
|
|
psh.ppsp = (LPCPROPSHEETPAGE) &psp;
|
|
|
|
// Invoke the property sheet.
|
|
PropertySheet(&psh);
|
|
|
|
// If this is valid, then we need to free the string.
|
|
SafeMemFree(pszFree);
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: CMsgProps::GeneralPageProc()
|
|
//
|
|
// PURPOSE: Callback for the General tab dialog.
|
|
//
|
|
INT_PTR CALLBACK CMsgProps::GeneralPageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CMsgProps *pThis = 0;
|
|
|
|
switch(msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
// Grab the object's this pointer from the init info
|
|
pThis = (CMsgProps *) ((PROPSHEETPAGE *)lParam)->lParam;
|
|
|
|
// Stash the window handle for this dialog in the class
|
|
pThis->m_hwndGen = hwnd;
|
|
|
|
// Initialize the page
|
|
pThis->InitGeneralPage();
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_NOTIFY:
|
|
{
|
|
switch(((NMHDR FAR *)lParam)->code)
|
|
{
|
|
// We're going to do the default thing for all of these notifications
|
|
case PSN_APPLY:
|
|
case PSN_KILLACTIVE:
|
|
case PSN_SETACTIVE:
|
|
{
|
|
SetDlgMsgResult(hwnd, WM_NOTIFY, FALSE);
|
|
return TRUE;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
enum
|
|
{
|
|
freeSubject = 0,
|
|
freeFrom,
|
|
freeMax
|
|
};
|
|
|
|
|
|
//
|
|
// FUNCTION: CMsgProps::InitGeneralPage()
|
|
//
|
|
// PURPOSE: Set's the values for the "General" tab in the message
|
|
// property sheet.
|
|
//
|
|
void CMsgProps::InitGeneralPage()
|
|
{
|
|
HWND hwnd;
|
|
char rgch[256],
|
|
rgchFmt[256];
|
|
char *psz = NULL;
|
|
PROPVARIANT rVariant;
|
|
LPMIMEMESSAGE pMsg = m_pmp->pMsg;
|
|
IMSGPRIORITY Pri = IMSG_PRI_NORMAL;
|
|
int ids;
|
|
BOOL fMime;
|
|
LPSTR rgszFree[freeMax]={0};
|
|
WCHAR wszDate[CCHMAX_STRINGRES];
|
|
|
|
TraceCall("CMsgProps::InitGeneralPage");
|
|
|
|
// [SBAILEY]: Raid-2440: ATTACH: Attachments field in Properties dialog innacurate when looked at from the listview.
|
|
if (m_pmp->fFromListView)
|
|
{
|
|
// Too hard to get these counts write from the listview because to really compute the attachment
|
|
// counts correctly, we have to render the message in trident. Since we are time contrained,
|
|
// we are going to simply remove the attachement count from the listview message properties. But
|
|
// since the counts are correct from message note properties, we will show the attachment counts from there.
|
|
ShowWindow(GetDlgItem(m_hwndGen, IDC_ATTACHMENTS_STATIC), SW_HIDE);
|
|
ShowWindow(GetDlgItem(m_hwndGen, IDC_ATTACHMENTS), SW_HIDE);
|
|
}
|
|
|
|
// If this is a news message, we hide the "Recieved:" and "Priority" fields
|
|
if (m_pmp->type == MSGPROPTYPE_NEWS)
|
|
{
|
|
RECT rc, rcLabel;
|
|
|
|
// Get the position of the priority field
|
|
GetWindowRect(GetDlgItem(m_hwndGen, IDC_PRIORITY), &rc);
|
|
MapWindowPoints(NULL, m_hwndGen, (LPPOINT) &rc, 2);
|
|
|
|
// Get the position of the priority label
|
|
GetWindowRect(GetDlgItem(m_hwndGen, IDC_PRIORITY_STATIC), &rcLabel);
|
|
MapWindowPoints(NULL, m_hwndGen, (LPPOINT) &rcLabel, 2);
|
|
|
|
// Hide the unused fields
|
|
ShowWindow(GetDlgItem(m_hwndGen, IDC_PRIORITY_STATIC), SW_HIDE);
|
|
ShowWindow(GetDlgItem(m_hwndGen, IDC_PRIORITY), SW_HIDE);
|
|
ShowWindow(GetDlgItem(m_hwndGen, idcStatic1), SW_HIDE);
|
|
ShowWindow(GetDlgItem(m_hwndGen, IDC_RECEIVED_STATIC), SW_HIDE);
|
|
ShowWindow(GetDlgItem(m_hwndGen, IDC_RECEIVED), SW_HIDE);
|
|
|
|
// Move the sent fields up to where the priority fields were
|
|
SetWindowPos(GetDlgItem(m_hwndGen, IDC_SENT_STATIC), NULL, rcLabel.left,
|
|
rcLabel.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
SetWindowPos(GetDlgItem(m_hwndGen, IDC_SENT), NULL, rc.left, rc.top, 0, 0,
|
|
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
}
|
|
|
|
// Figure out the correct image for this message
|
|
int idIcon;
|
|
if (m_pmp->type == MSGPROPTYPE_MAIL)
|
|
{
|
|
if (m_pmp->dwFlags & ARF_UNSENT)
|
|
idIcon = idiMsgPropUnSent;
|
|
else
|
|
idIcon = idiMsgPropSent;
|
|
}
|
|
else
|
|
{
|
|
if (m_pmp->dwFlags & ARF_UNSENT)
|
|
idIcon = idiArtPropUnpost;
|
|
else
|
|
idIcon = idiArtPropPost;
|
|
}
|
|
|
|
// Set the image on the property sheet
|
|
HICON hIcon = LoadIcon(g_hLocRes, MAKEINTRESOURCE(idIcon));
|
|
SendDlgItemMessage(m_hwndGen, IDC_FOLDER_IMAGE, STM_SETIMAGE, IMAGE_ICON, (LPARAM) hIcon);
|
|
|
|
// Subject
|
|
if (pMsg)
|
|
{
|
|
// If we have a message object, then we need to get the subject from the message
|
|
if (SUCCEEDED(MimeOleGetBodyPropA(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_SUBJECT),
|
|
NOFLAGS, &psz)))
|
|
{
|
|
// Make sure we free this later, eh?
|
|
rgszFree[freeSubject] = psz;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Assert(m_pmp->pNoMsgData);
|
|
psz = (LPTSTR) m_pmp->pNoMsgData->pszSubject;
|
|
}
|
|
|
|
// If the message doesn't have a subject, then substitute "(No Subject)"
|
|
if (!psz || !*psz)
|
|
{
|
|
LoadString(g_hLocRes, idsNoSubject, rgch, sizeof(rgch));
|
|
psz = rgch;
|
|
}
|
|
|
|
// Set the subject on the dialog
|
|
SetDlgItemText(m_hwndGen, IDC_MSGSUBJECT, psz);
|
|
|
|
// From
|
|
if (pMsg)
|
|
{
|
|
// Get the "From" line
|
|
if (S_OK == pMsg->GetAddressFormat(IAT_FROM, AFT_DISPLAY_BOTH, &psz))
|
|
{
|
|
// We'll need to free this later
|
|
rgszFree[freeFrom] = psz;
|
|
|
|
// Set the name on the control
|
|
SetDlgItemText(m_hwndGen, IDC_MSGFROM, psz);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Check to see if the caller provided this information
|
|
if (m_pmp->pNoMsgData && m_pmp->pNoMsgData->pszFrom)
|
|
{
|
|
SetDlgItemText(m_hwndGen, IDC_MSGFROM, m_pmp->pNoMsgData->pszFrom);
|
|
}
|
|
}
|
|
|
|
// Type (News or Mail)
|
|
if (m_pmp->type == MSGPROPTYPE_MAIL)
|
|
LoadString(g_hLocRes, idsMailMessage, rgch, ARRAYSIZE(rgch));
|
|
else
|
|
LoadString(g_hLocRes, idsNewsMessage, rgch, ARRAYSIZE(rgch));
|
|
|
|
SetDlgItemText(m_hwndGen, IDC_TYPE, rgch);
|
|
|
|
// Location
|
|
if (m_pmp->dwFlags & ARF_UNSENT)
|
|
{
|
|
LoadString(g_hLocRes, idsUnderComp, rgch, ARRAYSIZE(rgchFmt));
|
|
SetDlgItemText(m_hwndGen, IDC_MSGFOLDER, rgch);
|
|
}
|
|
else
|
|
SetDlgItemText(m_hwndGen, IDC_MSGFOLDER, m_pmp->szFolderName);
|
|
|
|
// Size
|
|
ULONG ulSize;
|
|
if (pMsg)
|
|
{
|
|
pMsg->GetMessageSize(&ulSize, 0);
|
|
if (0 == ulSize)
|
|
{
|
|
// see if the message has the userprop for uncached size
|
|
rVariant.vt = VT_UI4;
|
|
if (SUCCEEDED(pMsg->GetProp(PIDTOSTR(PID_ATT_UNCACHEDSIZE), 0, &rVariant)))
|
|
ulSize = rVariant.ulVal;
|
|
}
|
|
AthFormatSizeK(ulSize, rgch, ARRAYSIZE(rgch));
|
|
}
|
|
else if (m_pmp->pNoMsgData && m_pmp->pNoMsgData->ulSize)
|
|
{
|
|
AthFormatSizeK(m_pmp->pNoMsgData->ulSize, rgch, ARRAYSIZE(rgch));
|
|
}
|
|
else
|
|
{
|
|
LoadString(g_hLocRes, idsUnderComp, rgch, ARRAYSIZE(rgchFmt));
|
|
}
|
|
|
|
SetDlgItemText(m_hwndGen, IDC_MSGSIZE, rgch);
|
|
|
|
// Attachments
|
|
ULONG cAttachments = 0;
|
|
if (pMsg)
|
|
{
|
|
GetAttachmentCount(pMsg, &cAttachments);
|
|
}
|
|
else if (m_pmp->pNoMsgData)
|
|
{
|
|
cAttachments = m_pmp->pNoMsgData->cAttachments;
|
|
SetDlgItemInt(m_hwndGen, IDC_ATTACHMENTS, cAttachments, FALSE);
|
|
}
|
|
|
|
if (cAttachments)
|
|
{
|
|
SetDlgItemInt(m_hwndGen, IDC_ATTACHMENTS, cAttachments, FALSE);
|
|
}
|
|
else
|
|
{
|
|
LoadString(g_hLocRes, idsPropAttachNone, rgch, sizeof(rgch));
|
|
SetDlgItemText(m_hwndGen, IDC_ATTACHMENTS, rgch);
|
|
}
|
|
|
|
// Priority
|
|
// Get the priority from the message
|
|
rVariant.vt = VT_UI4;
|
|
Pri = IMSG_PRI_NORMAL;
|
|
if (pMsg && SUCCEEDED(pMsg->GetProp(PIDTOSTR(PID_ATT_PRIORITY), 0, &rVariant)))
|
|
Pri = (IMSGPRIORITY) rVariant.ulVal;
|
|
else
|
|
{
|
|
Assert(m_pmp->pNoMsgData);
|
|
Pri = m_pmp->pNoMsgData->Pri;
|
|
}
|
|
|
|
// Map the priority to a string
|
|
switch (Pri)
|
|
{
|
|
case IMSG_PRI_LOW:
|
|
ids = idsPriLow;
|
|
break;
|
|
case IMSG_PRI_HIGH:
|
|
ids = idsPriHigh;
|
|
break;
|
|
default:
|
|
ids = idsPriNormal;
|
|
}
|
|
|
|
// Set the string on the dialog
|
|
LoadString(g_hLocRes, ids, rgch, ARRAYSIZE(rgch));
|
|
SetDlgItemText(m_hwndGen, IDC_PRIORITY, rgch);
|
|
|
|
// Sent
|
|
if (pMsg)
|
|
{
|
|
*wszDate = 0;
|
|
rVariant.vt = VT_FILETIME;
|
|
pMsg->GetProp(PIDTOSTR(PID_ATT_SENTTIME), 0, &rVariant);
|
|
AthFileTimeToDateTimeW(&rVariant.filetime, wszDate, ARRAYSIZE(wszDate), DTM_NOSECONDS);
|
|
SetDlgItemTextWrapW(m_hwndGen, IDC_SENT, wszDate);
|
|
}
|
|
else if (m_pmp->dwFlags & ARF_UNSENT)
|
|
{
|
|
LoadString(g_hLocRes, idsUnderComp, rgch, ARRAYSIZE(rgchFmt));
|
|
SetDlgItemText(m_hwndGen, IDC_SENT, rgch);
|
|
}
|
|
else
|
|
{
|
|
SetDlgItemText(m_hwndGen, IDC_SENT, m_pmp->pNoMsgData->pszSent);
|
|
}
|
|
|
|
// Recieved
|
|
if (pMsg)
|
|
{
|
|
*wszDate = 0;
|
|
rVariant.vt = VT_FILETIME;
|
|
pMsg->GetProp(PIDTOSTR(PID_ATT_RECVTIME), 0, &rVariant);
|
|
AthFileTimeToDateTimeW(&rVariant.filetime, wszDate, ARRAYSIZE(wszDate), DTM_NOSECONDS);
|
|
SetDlgItemTextWrapW(m_hwndGen, IDC_RECEIVED, wszDate);
|
|
}
|
|
else if (m_pmp->dwFlags & ARF_UNSENT)
|
|
{
|
|
LoadString(g_hLocRes, idsUnderComp, rgch, ARRAYSIZE(rgchFmt));
|
|
SetDlgItemText(m_hwndGen, IDC_RECEIVED, rgch);
|
|
}
|
|
|
|
// Free the string table
|
|
for (register int i=0; i < freeMax; i++)
|
|
if (rgszFree[i])
|
|
MemFree(rgszFree[i]);
|
|
}
|
|
|
|
|
|
|
|
void CMsgProps::InitDetailsPage(HWND hwnd)
|
|
{
|
|
LPSTREAM pstm;
|
|
BODYOFFSETS rOffset;
|
|
char *psz;
|
|
int cch;
|
|
|
|
Assert(m_pmp);
|
|
Assert(m_pmp->pMsg);
|
|
|
|
// fill in the headers...
|
|
if(m_pmp->pMsg->GetMessageSource(&pstm, 0)==S_OK)
|
|
{
|
|
HrRewindStream(pstm);
|
|
|
|
m_pmp->pMsg->GetBodyOffsets(HBODY_ROOT, &rOffset);
|
|
|
|
cch=rOffset.cbBodyStart;
|
|
if(MemAlloc((LPVOID *)&psz, cch+1))
|
|
{
|
|
if(!pstm->Read(psz, cch, NULL))
|
|
{
|
|
psz[cch]=0; // null term this
|
|
SetDlgItemText(hwnd, idcTxtHeaders, psz);
|
|
}
|
|
MemFree(psz);
|
|
}
|
|
ReleaseObj(pstm);
|
|
}
|
|
else
|
|
EnableWindow(GetDlgItem(hwnd, idbMsgSource), FALSE);
|
|
|
|
if (!m_pmp->fSecure || !m_pmp->pSecureMsg)
|
|
ShowWindow(GetDlgItem(hwnd, idbSecMsgSource), SW_HIDE);
|
|
}
|
|
|
|
INT_PTR CALLBACK CMsgProps::DetailsPageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CMsgProps *pmprop=0;
|
|
|
|
switch(msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
pmprop=(CMsgProps *) ((PROPSHEETPAGE *)lParam)->lParam;
|
|
SetDlgThisPtr(hwnd, (LPARAM)pmprop);
|
|
|
|
Assert(pmprop);
|
|
pmprop->InitDetailsPage(hwnd);
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
pmprop=(CMsgProps *)GetDlgThisPtr(hwnd);
|
|
if(GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED)
|
|
{
|
|
if (GET_WM_COMMAND_ID(wParam, lParam)==idbMsgSource)
|
|
{
|
|
MimeEditViewSource(pmprop->m_pmp->hwndParent, pmprop->m_pmp->pMsg);
|
|
return(FALSE);
|
|
}
|
|
else if (GET_WM_COMMAND_ID(wParam, lParam)==idbSecMsgSource)
|
|
{
|
|
MimeEditViewSource(pmprop->m_pmp->hwndParent, pmprop->m_pmp->pSecureMsg);
|
|
return(FALSE);
|
|
}
|
|
}
|
|
else if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_SETFOCUS) {
|
|
if (GET_WM_COMMAND_ID(wParam, lParam) == idcTxtHeaders) {
|
|
// Remove the selection!
|
|
SendDlgItemMessage(hwnd, idcTxtHeaders, EM_SETSEL, -1, -1);
|
|
// fall through to default processing.
|
|
}
|
|
}
|
|
return TRUE;
|
|
|
|
case WM_NOTIFY:
|
|
switch(((NMHDR FAR *)lParam)->code)
|
|
{
|
|
pmprop=(CMsgProps *)GetDlgThisPtr(hwnd);
|
|
case PSN_APPLY:
|
|
case PSN_KILLACTIVE:
|
|
case PSN_SETACTIVE:
|
|
return TRUE;
|
|
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
{
|
|
PostMessage(GetParent(hwnd), WM_CLOSE, 0, 0);
|
|
break;
|
|
}
|
|
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
#ifdef WIN16
|
|
static const char s_cszDlgSec[] = "PDLGSECUTIRY";
|
|
#endif
|
|
|
|
INT_PTR CALLBACK CMsgProps::SecurityPageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
PMSGPROP pMsgProp = (PMSGPROP)0;
|
|
DLGSECURITY *pDlgSec;
|
|
|
|
switch(msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
CMsgProps *pmprop;
|
|
pmprop=(CMsgProps *) ((PROPSHEETPAGE *)lParam)->lParam;
|
|
SetWndThisPtr(hwnd, (LPARAM)pmprop->m_pmp);
|
|
if (pmprop)
|
|
pmprop->InitSecurityPage(hwnd);
|
|
}
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
|
|
if (GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED)
|
|
{
|
|
switch(GET_WM_COMMAND_ID(wParam, lParam))
|
|
{
|
|
case idcAddCert:
|
|
pDlgSec = (PDLGSECURITY)GET_DIALOG_SECURITY(hwnd);
|
|
pMsgProp = (PMSGPROP)GetWndThisPtr(hwnd);
|
|
|
|
// Get thumbprint into WAB and cert into AddressBook CAPI store
|
|
// cert goes to store first so CAPI details page can find it
|
|
if (pDlgSec && pMsgProp)
|
|
{
|
|
if (SUCCEEDED(HrAddSenderCertToWab(hwnd,
|
|
pMsgProp->pMsg,
|
|
pMsgProp->lpWabal,
|
|
&pDlgSec->tbSenderThumbprint,
|
|
&pDlgSec->blSymCaps,
|
|
pDlgSec->ftSigningTime,
|
|
WFF_CREATE | WFF_SHOWUI)))
|
|
{
|
|
AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthenaMail),
|
|
MAKEINTRESOURCEW(idsSenderCertAdded), NULL, MB_ICONINFORMATION | MB_OK);
|
|
}
|
|
}
|
|
return(FALSE);
|
|
|
|
case idcVerifySig:
|
|
pDlgSec = (PDLGSECURITY)GET_DIALOG_SECURITY(hwnd);
|
|
|
|
if (CommonUI_ViewSigningCertificate(hwnd, pDlgSec->pSenderCert, pDlgSec->hcMsg))
|
|
MessageBeep(MB_OK);
|
|
return(FALSE);
|
|
|
|
case idcViewCerts:
|
|
pMsgProp = (PMSGPROP)GetWndThisPtr(hwnd);
|
|
|
|
return (DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddMsgProp_Sec_ViewCert),
|
|
hwnd, ViewSecCertDlgProc, (LPARAM) (pMsgProp)) == IDOK);
|
|
|
|
case idcCertHelp:
|
|
OEHtmlHelp(hwnd, c_szCtxHelpFileHTMLCtx, HH_DISPLAY_TOPIC, (DWORD_PTR)(LPCSTR)"mail_overview_send_secure_messages.htm");
|
|
return(FALSE);
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return TRUE;
|
|
|
|
case WM_DESTROY:
|
|
pDlgSec = (PDLGSECURITY)GET_DIALOG_SECURITY(hwnd);
|
|
if (pDlgSec)
|
|
{
|
|
if (pDlgSec->pSenderCert)
|
|
CertFreeCertificateContext(pDlgSec->pSenderCert);
|
|
if (pDlgSec->pEncSenderCert)
|
|
CertFreeCertificateContext(pDlgSec->pEncSenderCert);
|
|
if (pDlgSec->pEncryptionCert)
|
|
CertFreeCertificateContext(pDlgSec->pEncryptionCert);
|
|
if (pDlgSec->tbSenderThumbprint.pBlobData)
|
|
MemFree(pDlgSec->tbSenderThumbprint.pBlobData);
|
|
if (pDlgSec->hcMsg) {
|
|
if (! CertCloseStore(pDlgSec->hcMsg, 0)) {
|
|
DOUTL(DOUTL_CRYPT, "CertCloseStore (message store) failed");
|
|
}
|
|
pDlgSec->hcMsg = NULL;
|
|
}
|
|
|
|
MemFree(pDlgSec);
|
|
|
|
CLEAR_DIALOG_SECURITY(hwnd);
|
|
}
|
|
return NULL;
|
|
|
|
case WM_NOTIFY:
|
|
switch(((NMHDR FAR *)lParam)->code)
|
|
{
|
|
case PSN_APPLY:
|
|
case PSN_KILLACTIVE:
|
|
case PSN_SETACTIVE:
|
|
return TRUE;
|
|
|
|
}
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
void CMsgProps::InitSecurityPage(HWND hwnd)
|
|
{
|
|
DWORD cb;
|
|
DWORD i;
|
|
HRESULT hr;
|
|
TCHAR szYes[CCHMAX_STRINGRES/4],
|
|
szNo[CCHMAX_STRINGRES/4],
|
|
szMaybe[CCHMAX_STRINGRES/4],
|
|
szNA[CCHMAX_STRINGRES/4];
|
|
HWND hwndCtrl;
|
|
DLGSECURITY *pDlgSec;
|
|
IMimeBody *pBody;
|
|
PROPVARIANT var;
|
|
ULONG secType, ulROVal;
|
|
BOOL fNoEncAlg = TRUE;
|
|
LPTSTR sz;
|
|
LPMIMEMESSAGE pMsg = m_pmp->pMsg;
|
|
PCCERT_CONTEXT pccert = NULL;
|
|
TCHAR szTmp[CCHMAX_STRINGRES];
|
|
|
|
HBODY hBody = NULL;
|
|
SECSTATE SecState ={0};
|
|
|
|
// We need these to set the statics
|
|
LoadString(g_hLocRes, idsOui, szYes, ARRAYSIZE(szYes));
|
|
LoadString(g_hLocRes, idsNon, szNo, ARRAYSIZE(szNo));
|
|
LoadString(g_hLocRes, idsMaybe, szMaybe, ARRAYSIZE(szMaybe));
|
|
LoadString(g_hLocRes, idsNotApplicable, szNA, ARRAYSIZE(szNA));
|
|
|
|
if(FAILED(HrGetSecurityState(m_pmp->pMsg, &SecState, &hBody)))
|
|
return;
|
|
|
|
CleanupSECSTATE(&SecState);
|
|
if (FAILED(m_pmp->pMsg->BindToObject(hBody ? hBody : HBODY_ROOT, IID_IMimeBody, (void **)&pBody)))
|
|
return;
|
|
|
|
if (SUCCEEDED(pBody->GetOption(OID_SECURITY_TYPE, &var)))
|
|
secType = var.ulVal;
|
|
|
|
// Set up storage for the other security info that
|
|
// we care about
|
|
if (MemAlloc((LPVOID *)&pDlgSec, sizeof(*pDlgSec)))
|
|
{
|
|
memset(pDlgSec, 0, sizeof(*pDlgSec));
|
|
#ifdef _WIN64
|
|
if (SUCCEEDED(pBody->GetOption(OID_SECURITY_HCERTSTORE_64, &var)))
|
|
{
|
|
pDlgSec->hcMsg = (HCERTSTORE)(var.pulVal); // Closed in WM_DESTROY
|
|
}
|
|
|
|
if (SUCCEEDED(pBody->GetOption(OID_SECURITY_CERT_SIGNING_64, &var)))
|
|
{
|
|
// we don't have to dupe the pDlgSec cert because we won't free
|
|
// the var's.
|
|
pDlgSec->pSenderCert = (PCCERT_CONTEXT)(var.pulVal);
|
|
}
|
|
#else // !_WIN64
|
|
if (SUCCEEDED(pBody->GetOption(OID_SECURITY_HCERTSTORE, &var)))
|
|
{
|
|
pDlgSec->hcMsg = (HCERTSTORE) var.ulVal; // Closed in WM_DESTROY
|
|
}
|
|
|
|
if (SUCCEEDED(pBody->GetOption(OID_SECURITY_CERT_SIGNING, &var)))
|
|
{
|
|
// we don't have to dupe the pDlgSec cert because we won't free
|
|
// the var's.
|
|
pDlgSec->pSenderCert = (PCCERT_CONTEXT) var.ulVal;
|
|
}
|
|
#endif // _WIN64
|
|
hr = GetSigningCert(m_pmp->pMsg, &pccert,
|
|
&pDlgSec->tbSenderThumbprint, &pDlgSec->blSymCaps,
|
|
&pDlgSec->ftSigningTime);
|
|
if (FAILED(hr) && (hr != MIME_E_SECURITY_NOCERT))
|
|
{
|
|
SUCCEEDED(hr);
|
|
}
|
|
}
|
|
|
|
SET_DIALOG_SECURITY(hwnd, (LPARAM)pDlgSec);
|
|
|
|
// we use the same dlgproc for sent items and recd items
|
|
// so use if statements to check for existance of all
|
|
// non-common controls
|
|
|
|
// set up the statics based on the message's info
|
|
|
|
if(IsSigned(secType))
|
|
{
|
|
LPSTR szCertEmail = SzGetCertificateEmailAddress(pccert);
|
|
SetDlgItemText(hwnd, idcStaticDigSign, szCertEmail);
|
|
MemFree(szCertEmail);
|
|
SetDlgItemText(hwnd, idcStaticRevoked,
|
|
(LPCTSTR)(((DwGetOption(OPT_REVOKE_CHECK) != 0) && !g_pConMan->IsGlobalOffline() && CheckCDPinCert(pMsg))
|
|
? szYes
|
|
: szNo));
|
|
}
|
|
else
|
|
{
|
|
SetDlgItemText(hwnd, idcStaticDigSign, szNA);
|
|
SetDlgItemText(hwnd, idcStaticRevoked, szNA);
|
|
}
|
|
|
|
|
|
SetDlgItemText(hwnd, idcStaticEncrypt,
|
|
(LPCTSTR)(IsEncrypted(secType)
|
|
? szYes
|
|
: szNo));
|
|
|
|
if (SUCCEEDED(pBody->GetOption(OID_SECURITY_RO_MSG_VALIDITY, &var)))
|
|
ulROVal = var.ulVal;
|
|
else
|
|
ulROVal = MSV_INVALID|MSV_UNVERIFIABLE;
|
|
|
|
#ifdef SMIME_V3
|
|
if(!IsSMIME3Supported())
|
|
{
|
|
LoadString(g_hLocRes, idsRecUnknown, szTmp, ARRAYSIZE(szTmp));
|
|
SendMessage(GetDlgItem(hwnd, idcRetRecReq), WM_SETTEXT, 0, LPARAM(LPCTSTR(szTmp)));
|
|
}
|
|
else
|
|
{
|
|
if(FPresentPolicyRegInfo())
|
|
{
|
|
if ((hwndCtrl = GetDlgItem(hwnd, idcSecLabelText)) && IsSigned(secType))
|
|
{
|
|
LPWSTR pwStr = NULL;
|
|
// Set Label text
|
|
if((hr = HrGetLabelString(m_pmp->pMsg, &pwStr)) == S_OK)
|
|
{
|
|
SetWindowTextWrapW(hwndCtrl, pwStr);
|
|
SafeMemFree(pwStr);
|
|
}
|
|
else
|
|
SendMessage(hwndCtrl, WM_SETTEXT, 0, LPARAM(LPCTSTR(SUCCEEDED(hr) ? szYes : szNo)));
|
|
}
|
|
}
|
|
// Check receipt request
|
|
if ((hwndCtrl = GetDlgItem(hwnd, idcRetRecReq)))
|
|
{
|
|
if (!IsSigned(secType))
|
|
sz = szNA;
|
|
else
|
|
{
|
|
PSMIME_RECEIPT pSecReceipt = NULL;
|
|
if(CheckDecodedForReceipt(m_pmp->pMsg, &pSecReceipt) == S_OK)
|
|
sz = szNA;
|
|
else
|
|
sz = (secType & MST_RECEIPT_REQUEST) ? szYes : szNo;
|
|
SafeMemFree(pSecReceipt);
|
|
}
|
|
SendMessage(hwndCtrl, WM_SETTEXT, 0, LPARAM(LPCTSTR(sz)));
|
|
}
|
|
}
|
|
|
|
#endif // SMIME_V3
|
|
////////
|
|
// begin sign dependent block
|
|
|
|
if (!IsSigned(secType))
|
|
sz = szNA;
|
|
|
|
if ((hwndCtrl = GetDlgItem(hwnd, idcStaticAlter)))
|
|
{
|
|
if (IsSigned(secType))
|
|
{
|
|
sz = (MSV_SIGNATURE_MASK & ulROVal)
|
|
? (MSV_BADSIGNATURE & ulROVal)
|
|
? szNo
|
|
: szMaybe
|
|
: ((pccert != NULL) ? szYes : szMaybe);
|
|
}
|
|
SendMessage(hwndCtrl, WM_SETTEXT, 0, LPARAM(LPCTSTR(sz)));
|
|
}
|
|
|
|
if ((hwndCtrl = GetDlgItem(hwnd, idcStaticTrust)) &&
|
|
SUCCEEDED(pBody->GetOption(OID_SECURITY_USER_VALIDITY, &var)))
|
|
{
|
|
if (IsSigned(secType))
|
|
{
|
|
sz = (ATHSEC_TRUSTSTATEMASK & var.ulVal)
|
|
? ((ATHSEC_NOTRUSTNOTTRUSTED & var.ulVal) || (ulROVal & MSV_EXPIRED_SIGNINGCERT))
|
|
? szNo
|
|
: szMaybe
|
|
: szYes;
|
|
}
|
|
SendMessage(hwndCtrl, WM_SETTEXT, 0, LPARAM(LPCTSTR(sz)));
|
|
|
|
}
|
|
|
|
if((hwndCtrl = GetDlgItem(hwnd, idcStaticRevStatus)) && IsSigned(secType))
|
|
{
|
|
if((DwGetOption(OPT_REVOKE_CHECK) != 0) && !g_pConMan->IsGlobalOffline() && CheckCDPinCert(pMsg))
|
|
{
|
|
if(var.ulVal & ATHSEC_NOTRUSTREVOKED)
|
|
LoadString(g_hLocRes, idsWrnSecurityCertRevoked, szTmp, ARRAYSIZE(szTmp));
|
|
else if(var.ulVal & ATHSEC_NOTRUSTREVFAIL)
|
|
LoadString(g_hLocRes, idsWrnSecurityRevFail, szTmp, ARRAYSIZE(szTmp));
|
|
else
|
|
LoadString(g_hLocRes, idsOkSecurityCertRevoked, szTmp, ARRAYSIZE(szTmp));
|
|
}
|
|
else if((DwGetOption(OPT_REVOKE_CHECK) != 0) && !g_pConMan->IsGlobalOffline() && !CheckCDPinCert(pMsg))
|
|
LoadString(g_hLocRes, idsWrnSecurityNoCDP, szTmp, ARRAYSIZE(szTmp));
|
|
|
|
else if((DwGetOption(OPT_REVOKE_CHECK) != 0) && g_pConMan->IsGlobalOffline())
|
|
LoadString(g_hLocRes, idsRevokationOffline, szTmp, ARRAYSIZE(szTmp));
|
|
|
|
else if(DwGetOption(OPT_REVOKE_CHECK) == 0)
|
|
LoadString(g_hLocRes, idsRevokationTurnedOff, szTmp, ARRAYSIZE(szTmp));
|
|
|
|
SendMessage(hwndCtrl, WM_SETTEXT, 0, LPARAM(LPCTSTR(szTmp)));
|
|
}
|
|
|
|
if (SUCCEEDED(pBody->GetOption(OID_SECURITY_CERT_INCLUDED, &var)))
|
|
{
|
|
if (IsSigned(secType))
|
|
sz = (var.boolVal == TRUE) ? szYes : szNo;
|
|
SetDlgItemText(hwnd, idcStaticCertInc, LPCTSTR(sz));
|
|
}
|
|
|
|
// end signing dependent block
|
|
////////
|
|
|
|
|
|
if (IsEncrypted(secType) && SUCCEEDED(pBody->GetOption(OID_SECURITY_ALG_BULK, &var)))
|
|
{
|
|
Assert(var.vt == VT_BLOB);
|
|
if (var.vt == VT_BLOB && var.blob.cbSize && var.blob.pBlobData)
|
|
{
|
|
LPCTSTR pszProtocol = NULL;
|
|
|
|
// Convert the SYMCAPS blob to an "encrypted using" string
|
|
if (SUCCEEDED(MimeOleAlgNameFromSMimeCap(var.blob.pBlobData, var.blob.cbSize,
|
|
&pszProtocol)))
|
|
{ // Note: returns a static string. Don't free it.
|
|
if (pszProtocol)
|
|
{
|
|
SendMessage(GetDlgItem(hwnd, idcStaticEncAlg), WM_SETTEXT, 0, (LPARAM)pszProtocol);
|
|
fNoEncAlg = FALSE;
|
|
}
|
|
}
|
|
// Free the data
|
|
MemFree(var.blob.pBlobData);
|
|
}
|
|
}
|
|
if (fNoEncAlg)
|
|
{
|
|
SendMessage(GetDlgItem(hwnd, idcStaticEncAlg), WM_SETTEXT, 0,
|
|
LPARAM(LPCTSTR(szNA)));
|
|
}
|
|
|
|
if (pccert != NULL)
|
|
CertFreeCertificateContext(pccert);
|
|
ReleaseObj(pBody);
|
|
return;
|
|
}
|
|
|
|
INT_PTR CALLBACK ViewSecCertDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LPMIMEMESSAGE pMsg = NULL;
|
|
IMimeBody *pBody;
|
|
PROPVARIANT var;
|
|
DLGSECURITY *pDlgSec;
|
|
ULONG secType, ulROVal;
|
|
HWND hwndCtrl = NULL;
|
|
PMSGPROP pMsgProp = (PMSGPROP)0;
|
|
HRESULT hr = S_OK;
|
|
TCHAR szTmp[CCHMAX_STRINGRES];
|
|
HBODY hBody = NULL;
|
|
HBODY hInerBody = NULL;
|
|
SECSTATE SecState ={0};
|
|
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
TCHAR szNA[CCHMAX_STRINGRES/4];
|
|
|
|
SetWndThisPtr(hwnd, lParam);
|
|
CenterDialog(hwnd);
|
|
pMsgProp = (PMSGPROP) lParam;
|
|
pMsg = pMsgProp->pMsg;
|
|
|
|
LoadString(g_hLocRes, idsNotApplicable, szNA, ARRAYSIZE(szNA));
|
|
|
|
if(FAILED(HrGetSecurityState(pMsgProp->pMsg, &SecState, &hBody)))
|
|
return FALSE;
|
|
|
|
if(FAILED(HrGetInnerLayer(pMsgProp->pMsg, &hInerBody)))
|
|
return FALSE;
|
|
|
|
if((!IsSignTrusted(&SecState) || !IsEncryptionOK(&SecState)) && (hBody != hInerBody))
|
|
EnableWindow(GetDlgItem(hwnd, idcAddCert), FALSE);
|
|
|
|
CleanupSECSTATE(&SecState);
|
|
|
|
if (FAILED(pMsgProp->pMsg->BindToObject(hBody ? hBody : HBODY_ROOT, IID_IMimeBody, (void **)&pBody)))
|
|
return FALSE;
|
|
|
|
if (SUCCEEDED(pBody->GetOption(OID_SECURITY_TYPE, &var)))
|
|
secType = var.ulVal;
|
|
|
|
// Set up storage for the other security info that
|
|
// we care about
|
|
if (MemAlloc((LPVOID *)&pDlgSec, sizeof(*pDlgSec)))
|
|
{
|
|
memset(pDlgSec, 0, sizeof(*pDlgSec));
|
|
#ifdef _WIN64
|
|
if (SUCCEEDED(pBody->GetOption(OID_SECURITY_HCERTSTORE_64, &var)))
|
|
{
|
|
pDlgSec->hcMsg = (HCERTSTORE)(var.pulVal); // Closed in WM_DESTROY
|
|
}
|
|
|
|
if (SUCCEEDED(pBody->GetOption(OID_SECURITY_CERT_SIGNING_64, &var)))
|
|
{
|
|
// we don't have to dupe the pDlgSec cert because we won't free
|
|
// the var's.
|
|
pDlgSec->pSenderCert = (PCCERT_CONTEXT)(var.pulVal);
|
|
}
|
|
#else // !_WIN64
|
|
if (SUCCEEDED(pBody->GetOption(OID_SECURITY_HCERTSTORE, &var)))
|
|
{
|
|
pDlgSec->hcMsg = (HCERTSTORE) var.ulVal; // Closed in WM_DESTROY
|
|
}
|
|
|
|
if (SUCCEEDED(pBody->GetOption(OID_SECURITY_CERT_SIGNING, &var)))
|
|
{
|
|
// we don't have to dupe the pDlgSec cert because we won't free
|
|
// the var's.
|
|
pDlgSec->pSenderCert = (PCCERT_CONTEXT) var.ulVal;
|
|
}
|
|
#endif // _WIN64
|
|
hr = GetSignerEncryptionCert(pMsgProp->pMsg, &pDlgSec->pEncSenderCert,
|
|
&pDlgSec->tbSenderThumbprint, &pDlgSec->blSymCaps,
|
|
&pDlgSec->ftSigningTime);
|
|
if (FAILED(hr) && (hr != MIME_E_SECURITY_NOCERT))
|
|
{
|
|
SUCCEEDED(hr);
|
|
}
|
|
}
|
|
if(IsEncrypted(secType))
|
|
{
|
|
#ifdef _WIN64
|
|
if (SUCCEEDED(hr = pBody->GetOption(OID_SECURITY_CERT_DECRYPTION_64, &var)))
|
|
{
|
|
Assert(VT_UI8 == var.vt);
|
|
if ((PCCERT_CONTEXT)(var.pulVal))
|
|
pDlgSec->pEncryptionCert = (PCCERT_CONTEXT)(var.pulVal);
|
|
}
|
|
|
|
#else // !_WIN64
|
|
|
|
if (SUCCEEDED(hr = pBody->GetOption(OID_SECURITY_CERT_DECRYPTION, &var)))
|
|
{
|
|
Assert(VT_UI4 == var.vt);
|
|
if (*(PCCERT_CONTEXT *)(&(var.uhVal)))
|
|
pDlgSec->pEncryptionCert = *(PCCERT_CONTEXT *)(&(var.uhVal));
|
|
}
|
|
#endif // _WIN64
|
|
}
|
|
else
|
|
pDlgSec->pEncryptionCert = NULL;
|
|
|
|
SET_DIALOG_SECURITY(hwnd, (LPARAM)pDlgSec);
|
|
|
|
if (pDlgSec->pEncSenderCert == NULL)
|
|
{
|
|
// Disable Add to Address Book button
|
|
if ((hwndCtrl = GetDlgItem(hwnd, idcAddCert)))
|
|
EnableWindow(hwndCtrl, FALSE);
|
|
|
|
// Disable View sender's encrypt cert.
|
|
if ((hwndCtrl = GetDlgItem(hwnd, idcSendersEncryptionCert)))
|
|
EnableWindow(hwndCtrl, FALSE);
|
|
|
|
LoadString(g_hLocRes, idsEncrCertNotIncluded, szTmp, ARRAYSIZE(szTmp));
|
|
SetDlgItemText(hwnd, idcStaticSendersCert, LPCTSTR(szTmp));
|
|
}
|
|
//
|
|
if (pDlgSec->pSenderCert == NULL)
|
|
{
|
|
if ((hwndCtrl = GetDlgItem(hwnd, idcVerifySig)))
|
|
EnableWindow(hwndCtrl, FALSE);
|
|
|
|
LoadString(g_hLocRes, idsSignCertNotIncl, szTmp, ARRAYSIZE(szTmp));
|
|
SetDlgItemText(hwnd, idcStaticSigningCert, LPCTSTR(szTmp));
|
|
}
|
|
|
|
if(pDlgSec->pEncryptionCert == NULL)
|
|
{
|
|
if ((hwndCtrl = GetDlgItem(hwnd, idcViewEncrytionCert)))
|
|
EnableWindow(hwndCtrl, FALSE);
|
|
|
|
if(IsEncrypted(secType))
|
|
LoadString(g_hLocRes, idsEncrCertNotFoundOnPC, szTmp, ARRAYSIZE(szTmp));
|
|
else
|
|
LoadString(g_hLocRes, idsMsgWasNotEncrypted, szTmp, ARRAYSIZE(szTmp));
|
|
SetDlgItemText(hwnd, idcStaticEncryptionCert, LPCTSTR(szTmp));
|
|
}
|
|
|
|
if(pDlgSec->blSymCaps.cbSize > 0)
|
|
{
|
|
// Convert the SYMCAPS blob to an "encrypted using" string
|
|
LPCTSTR pszProtocol = NULL;
|
|
if (SUCCEEDED(MimeOleAlgNameFromSMimeCap(pDlgSec->blSymCaps.pBlobData, pDlgSec->blSymCaps.cbSize,
|
|
&pszProtocol)))
|
|
{ // Note: returns a static string. Don't free it.
|
|
if (pszProtocol)
|
|
SetDlgItemText(hwnd, idcStaticEncryptAlgorithm, LPCTSTR(pszProtocol));
|
|
}
|
|
|
|
}
|
|
else
|
|
SetDlgItemText(hwnd, idcStaticEncryptAlgorithm, LPCTSTR(szNA));
|
|
|
|
|
|
if(pBody)
|
|
ReleaseObj(pBody);
|
|
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
|
|
pDlgSec = (PDLGSECURITY)GET_DIALOG_SECURITY(hwnd);
|
|
pMsgProp = (PMSGPROP)GetWndThisPtr(hwnd);
|
|
pMsg = pMsgProp->pMsg;
|
|
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case idcAddCert:
|
|
|
|
// Get thumbprint into WAB and cert into AddressBook CAPI store
|
|
// cert goes to store first so CAPI details page can find it
|
|
if (pDlgSec && pMsgProp)
|
|
{
|
|
if (SUCCEEDED(HrAddSenderCertToWab(hwnd,
|
|
pMsgProp->pMsg,
|
|
pMsgProp->lpWabal,
|
|
&pDlgSec->tbSenderThumbprint,
|
|
&pDlgSec->blSymCaps,
|
|
pDlgSec->ftSigningTime,
|
|
WFF_CREATE | WFF_SHOWUI)))
|
|
{
|
|
AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthenaMail),
|
|
MAKEINTRESOURCEW(idsSenderCertAdded), NULL, MB_ICONINFORMATION | MB_OK);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case idcVerifySig:
|
|
if (CommonUI_ViewSigningCertificate(hwnd, pDlgSec->pSenderCert, pDlgSec->hcMsg))
|
|
MessageBeep(MB_OK);
|
|
return(FALSE);
|
|
|
|
case idcViewEncrytionCert:
|
|
if (CommonUI_ViewSigningCertificate(hwnd, pDlgSec->pEncryptionCert, pDlgSec->hcMsg))
|
|
MessageBeep(MB_OK);
|
|
return(FALSE);
|
|
|
|
case idcSendersEncryptionCert:
|
|
if (CommonUI_ViewSigningCertificate(hwnd, pDlgSec->pEncSenderCert, pDlgSec->hcMsg))
|
|
MessageBeep(MB_OK);
|
|
return(FALSE);
|
|
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
EndDialog(hwnd, LOWORD(wParam));
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
break; // wm_command
|
|
case WM_CLOSE:
|
|
SendMessage(hwnd, WM_COMMAND, IDCANCEL, 0L);
|
|
return (TRUE);
|
|
|
|
case WM_DESTROY:
|
|
pDlgSec = (PDLGSECURITY)GET_DIALOG_SECURITY(hwnd);
|
|
if (pDlgSec)
|
|
{
|
|
if (pDlgSec->pSenderCert)
|
|
CertFreeCertificateContext(pDlgSec->pSenderCert);
|
|
if (pDlgSec->pEncSenderCert)
|
|
CertFreeCertificateContext(pDlgSec->pEncSenderCert);
|
|
if (pDlgSec->pEncryptionCert)
|
|
CertFreeCertificateContext(pDlgSec->pEncryptionCert);
|
|
if (pDlgSec->tbSenderThumbprint.pBlobData)
|
|
MemFree(pDlgSec->tbSenderThumbprint.pBlobData);
|
|
if (pDlgSec->hcMsg)
|
|
{
|
|
if (! CertCloseStore(pDlgSec->hcMsg, 0))
|
|
{
|
|
DOUTL(DOUTL_CRYPT, "CertCloseStore (message store) failed");
|
|
}
|
|
pDlgSec->hcMsg = NULL;
|
|
}
|
|
|
|
MemFree(pDlgSec);
|
|
|
|
CLEAR_DIALOG_SECURITY(hwnd);
|
|
}
|
|
|
|
} // message switch
|
|
return(FALSE);
|
|
}
|