817 lines
15 KiB
C++
817 lines
15 KiB
C++
/*++
|
|
|
|
Copyright (c) 1994-1998 Microsoft Corporation
|
|
|
|
Module Name :
|
|
|
|
security.cpp
|
|
|
|
Abstract:
|
|
|
|
WWW Security Property Page
|
|
|
|
Author:
|
|
|
|
Ronald Meijer (ronaldm)
|
|
|
|
Project:
|
|
|
|
Internet Services Manager
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
//
|
|
// Include Files
|
|
//
|
|
#include "stdafx.h"
|
|
#include "wincrypt.h"
|
|
|
|
#include "w3scfg.h"
|
|
#include "security.h"
|
|
#include "authent.h"
|
|
#include "seccom.h"
|
|
#include "ipdomdlg.h"
|
|
|
|
#include "cryptui.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
//
|
|
// CW3SecurityPage property page
|
|
//
|
|
IMPLEMENT_DYNCREATE(CW3SecurityPage, CInetPropertyPage)
|
|
|
|
|
|
|
|
CW3SecurityPage::CW3SecurityPage(
|
|
IN CInetPropertySheet * pSheet,
|
|
IN BOOL fHome,
|
|
IN DWORD dwAttributes
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor
|
|
|
|
Arguments:
|
|
|
|
CInetPropertySheet * pSheet : Sheet object
|
|
BOOL fHome : TRUE if this is a home directory
|
|
DWORD dwAttributes : Attributes
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
: CInetPropertyPage(CW3SecurityPage::IDD, pSheet,
|
|
IS_FILE(dwAttributes)
|
|
? IDS_TAB_FILE_SECURITY
|
|
: IDS_TAB_DIR_SECURITY
|
|
),
|
|
m_oblAccessList(),
|
|
m_fU2Installed(FALSE),
|
|
m_fIpDirty(FALSE),
|
|
m_fHome(fHome),
|
|
//
|
|
// By default, we grant access
|
|
//
|
|
m_fOldDefaultGranted(TRUE),
|
|
m_fDefaultGranted(TRUE)
|
|
{
|
|
|
|
#if 0 // Keep class wizard happy
|
|
|
|
//{{AFX_DATA_INIT(CW3SecurityPage)
|
|
m_fUseNTMapper = FALSE;
|
|
//}}AFX_DATA_INIT
|
|
|
|
#endif // 0
|
|
|
|
}
|
|
|
|
|
|
CW3SecurityPage::~CW3SecurityPage()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor
|
|
|
|
Arguments:
|
|
|
|
N/A
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
{
|
|
}
|
|
|
|
|
|
|
|
void
|
|
CW3SecurityPage::DoDataExchange(
|
|
IN CDataExchange * pDX
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialise/Store control data
|
|
|
|
Arguments:
|
|
|
|
CDataExchange * pDX - DDX/DDV control structure
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
CInetPropertyPage::DoDataExchange(pDX);
|
|
|
|
//{{AFX_DATA_MAP(CW3SecurityPage)
|
|
DDX_Check(pDX, IDC_CHECK_ENABLE_DS, m_fUseNTMapper);
|
|
DDX_Control(pDX, IDC_ICON_SECURE, m_icon_Secure);
|
|
DDX_Control(pDX, IDC_STATIC_SSL_PROMPT, m_static_SSLPrompt);
|
|
DDX_Control(pDX, IDC_CHECK_ENABLE_DS, m_check_EnableDS);
|
|
DDX_Control(pDX, IDC_BUTTON_GET_CERTIFICATES, m_button_GetCertificates);
|
|
DDX_Control(pDX, IDC_VIEW_CERTIFICATE, m_button_ViewCertificates);
|
|
DDX_Control(pDX, IDC_BUTTON_COMMUNICATIONS, m_button_Communications);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Message Map
|
|
//
|
|
BEGIN_MESSAGE_MAP(CW3SecurityPage, CInetPropertyPage)
|
|
//{{AFX_MSG_MAP(CW3SecurityPage)
|
|
ON_BN_CLICKED(IDC_BUTTON_AUTHENTICATION, OnButtonAuthentication)
|
|
ON_BN_CLICKED(IDC_BUTTON_COMMUNICATIONS, OnButtonCommunications)
|
|
ON_BN_CLICKED(IDC_BUTTON_IP_SECURITY, OnButtonIpSecurity)
|
|
ON_BN_CLICKED(IDC_BUTTON_GET_CERTIFICATES, OnButtonGetCertificates)
|
|
ON_BN_CLICKED(IDC_VIEW_CERTIFICATE, OnButtonViewCertificates)
|
|
//}}AFX_MSG_MAP
|
|
|
|
ON_BN_CLICKED(IDC_CHECK_ENABLE_DS, OnItemChanged)
|
|
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CW3SecurityPage::FetchLoadedValues()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Move configuration data from sheet to dialog controls
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
CError err;
|
|
|
|
BEGIN_META_DIR_READ(CW3Sheet)
|
|
FETCH_DIR_DATA_FROM_SHEET(m_dwAuthFlags);
|
|
FETCH_DIR_DATA_FROM_SHEET(m_dwSSLAccessPermissions);
|
|
FETCH_DIR_DATA_FROM_SHEET(m_strBasicDomain);
|
|
FETCH_DIR_DATA_FROM_SHEET(m_strAnonUserName);
|
|
FETCH_DIR_DATA_FROM_SHEET(m_strAnonPassword);
|
|
FETCH_DIR_DATA_FROM_SHEET(m_fPasswordSync);
|
|
FETCH_DIR_DATA_FROM_SHEET(m_fU2Installed);
|
|
FETCH_DIR_DATA_FROM_SHEET(m_fUseNTMapper);
|
|
END_META_DIR_READ(err)
|
|
|
|
//
|
|
// First we need to read in the hash and the name of the store. If either
|
|
// is not there then there is no certificate.
|
|
//
|
|
BEGIN_META_INST_READ(CW3Sheet)
|
|
FETCH_INST_DATA_FROM_SHEET(m_strCertStoreName);
|
|
FETCH_INST_DATA_FROM_SHEET(m_strCTLIdentifier);
|
|
FETCH_INST_DATA_FROM_SHEET(m_strCTLStoreName);
|
|
END_META_INST_READ(err)
|
|
|
|
//
|
|
// Build the IPL list
|
|
//
|
|
err = BuildIplOblistFromBlob(
|
|
GetIPL(),
|
|
m_oblAccessList,
|
|
m_fDefaultGranted
|
|
);
|
|
|
|
m_fOldDefaultGranted = m_fDefaultGranted;
|
|
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CW3SecurityPage::SaveInfo()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Save the information on this property page
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Error return code
|
|
|
|
--*/
|
|
{
|
|
ASSERT(IsDirty());
|
|
|
|
TRACEEOLID("Saving W3 security page now...");
|
|
|
|
CError err;
|
|
|
|
//
|
|
// Check to see if the ip access list needs saving.
|
|
//
|
|
BOOL fIplDirty = m_fIpDirty || (m_fOldDefaultGranted != m_fDefaultGranted);
|
|
|
|
//
|
|
// Use m_ notation because the message crackers require it
|
|
//
|
|
CBlob m_ipl;
|
|
|
|
if (fIplDirty)
|
|
{
|
|
BuildIplBlob(m_oblAccessList, m_fDefaultGranted, m_ipl);
|
|
}
|
|
|
|
BeginWaitCursor();
|
|
|
|
BEGIN_META_DIR_WRITE(CW3Sheet)
|
|
STORE_DIR_DATA_ON_SHEET(m_dwSSLAccessPermissions)
|
|
STORE_DIR_DATA_ON_SHEET(m_dwAuthFlags)
|
|
STORE_DIR_DATA_ON_SHEET(m_strBasicDomain)
|
|
|
|
if (fIplDirty)
|
|
{
|
|
STORE_DIR_DATA_ON_SHEET(m_ipl)
|
|
}
|
|
STORE_DIR_DATA_ON_SHEET(m_strAnonUserName)
|
|
STORE_DIR_DATA_ON_SHEET(m_fPasswordSync)
|
|
STORE_DIR_DATA_ON_SHEET(m_fUseNTMapper)
|
|
if (m_fPasswordSync)
|
|
{
|
|
//
|
|
// Delete password
|
|
//
|
|
// CODEWORK: Shouldn't need to know ID number.
|
|
// Implement m_fDelete flag in CMP template maybe?
|
|
//
|
|
FLAG_DIR_DATA_FOR_DELETION(MD_ANONYMOUS_PWD);
|
|
}
|
|
else
|
|
{
|
|
STORE_DIR_DATA_ON_SHEET(m_strAnonPassword);
|
|
}
|
|
END_META_DIR_WRITE(err)
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
BEGIN_META_INST_WRITE(CW3Sheet)
|
|
if ( m_strCTLIdentifier.IsEmpty() )
|
|
{
|
|
FLAG_INST_DATA_FOR_DELETION( MD_SSL_CTL_IDENTIFIER )
|
|
}
|
|
else
|
|
{
|
|
STORE_INST_DATA_ON_SHEET(m_strCTLIdentifier)
|
|
}
|
|
|
|
if ( m_strCTLStoreName.IsEmpty() )
|
|
{
|
|
FLAG_INST_DATA_FOR_DELETION( MD_SSL_CTL_STORE_NAME )
|
|
}
|
|
else
|
|
{
|
|
STORE_INST_DATA_ON_SHEET(m_strCTLStoreName)
|
|
}
|
|
END_META_INST_WRITE(err)
|
|
}
|
|
|
|
EndWaitCursor();
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
m_fIpDirty = FALSE;
|
|
m_fOldDefaultGranted = m_fDefaultGranted;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
CW3SecurityPage::FetchSSLState()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Obtain the state of the dialog depending on whether certificates
|
|
are installed or not.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
TRUE if certificates are installed, FALSE otherwise
|
|
|
|
--*/
|
|
{
|
|
BeginWaitCursor();
|
|
m_fCertInstalled = ::IsCertInstalledOnServer(
|
|
GetServerName(),
|
|
QueryInstance()
|
|
);
|
|
EndWaitCursor();
|
|
|
|
return m_fCertInstalled;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
CW3SecurityPage::SetSSLControlState()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enable/disable supported controls depending on what's installed.
|
|
Only available on non-master instance nodes.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
m_static_SSLPrompt.EnableWindow(!IsMasterInstance());
|
|
m_button_GetCertificates.EnableWindow(
|
|
!IsMasterInstance()
|
|
&& m_fHome
|
|
&& IsLocal()
|
|
);
|
|
m_button_Communications.EnableWindow(
|
|
!IsMasterInstance()
|
|
&& IsSSLSupported()
|
|
&& FetchSSLState()
|
|
);
|
|
m_button_ViewCertificates.EnableWindow(m_fCertInstalled);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Message Handlers
|
|
//
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
BOOL
|
|
CW3SecurityPage::OnSetActive()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Page got activated -- set the SSL state depending on whether a
|
|
certificate is installed or not.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
TRUE to activate the page, FALSE otherwise.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Enable/disable ssl controls
|
|
//
|
|
SetSSLControlState();
|
|
|
|
return CInetPropertyPage::OnSetActive();
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
CW3SecurityPage::OnInitDialog()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
WM_INITDIALOG handler. Initialize the dialog.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TRUE if no focus is to be set automatically, FALSE if the focus
|
|
is already set.
|
|
|
|
--*/
|
|
{
|
|
CInetPropertyPage::OnInitDialog();
|
|
|
|
//
|
|
// Initialize certificate authorities ocx
|
|
//
|
|
CRect rc(0, 0, 0, 0);
|
|
m_ocx_CertificateAuthorities.Create(
|
|
_T("CertWiz"),
|
|
WS_BORDER,
|
|
rc,
|
|
this,
|
|
IDC_APPSCTRL
|
|
);
|
|
|
|
GetDlgItem(IDC_GROUP_IP)->EnableWindow(HasIPAccessCheck());
|
|
GetDlgItem(IDC_ICON_IP)->EnableWindow(HasIPAccessCheck());
|
|
GetDlgItem(IDC_STATIC_IP)->EnableWindow(HasIPAccessCheck());
|
|
GetDlgItem(IDC_BUTTON_IP_SECURITY)->EnableWindow(HasIPAccessCheck());
|
|
GetDlgItem(IDC_BUTTON_AUTHENTICATION)->EnableWindow(!m_fU2Installed);
|
|
|
|
//
|
|
// Configure for either master or non-master display.
|
|
//
|
|
m_check_EnableDS.ShowWindow(IsMasterInstance() ? SW_SHOW : SW_HIDE);
|
|
m_check_EnableDS.EnableWindow(
|
|
HasAdminAccess()
|
|
&& IsMasterInstance()
|
|
&& HasNTCertMapper()
|
|
);
|
|
|
|
#define SHOW_NON_MASTER(x)\
|
|
(x).ShowWindow(IsMasterInstance() ? SW_HIDE : SW_SHOW)
|
|
|
|
SHOW_NON_MASTER(m_static_SSLPrompt);
|
|
SHOW_NON_MASTER(m_icon_Secure);
|
|
SHOW_NON_MASTER(m_button_GetCertificates);
|
|
SHOW_NON_MASTER(m_button_Communications);
|
|
SHOW_NON_MASTER(m_button_ViewCertificates);
|
|
|
|
#undef SHOW_NON_MASTER
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
CW3SecurityPage::OnButtonAuthentication()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
'Authentication' button hander
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
CAuthenticationDlg dlg(
|
|
GetServerName(),
|
|
QueryInstance(),
|
|
m_strBasicDomain,
|
|
m_dwAuthFlags,
|
|
m_dwSSLAccessPermissions,
|
|
m_strAnonUserName,
|
|
m_strAnonPassword,
|
|
m_fPasswordSync,
|
|
HasAdminAccess(),
|
|
HasDigest(),
|
|
this
|
|
);
|
|
|
|
DWORD dwOldAccess = m_dwSSLAccessPermissions;
|
|
DWORD dwOldAuth = m_dwAuthFlags;
|
|
CString strOldDomain = m_strBasicDomain;
|
|
CString strOldUserName = m_strAnonUserName;
|
|
CString strOldPassword = m_strAnonPassword;
|
|
BOOL fOldPasswordSync = m_fPasswordSync;
|
|
|
|
if (dlg.DoModal() == IDOK)
|
|
{
|
|
//
|
|
// See if anything has changed
|
|
//
|
|
if (dwOldAccess != m_dwSSLAccessPermissions
|
|
|| dwOldAuth != m_dwAuthFlags
|
|
|| m_strBasicDomain != strOldDomain
|
|
|| m_strAnonUserName != strOldUserName
|
|
|| m_strAnonPassword != strOldPassword
|
|
|| m_fPasswordSync != fOldPasswordSync
|
|
)
|
|
{
|
|
//
|
|
// Mark as dirty
|
|
//
|
|
OnItemChanged();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
CW3SecurityPage::OnButtonCommunications()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
'Communications' button handler
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Prep the flag for if we can edit CTLs or not
|
|
//
|
|
BOOL fEditCTLs = IsMasterInstance() || m_fHome;
|
|
|
|
//
|
|
// Prep the communications dialog
|
|
//
|
|
CSecCommDlg dlg(
|
|
GetServerName(),
|
|
QueryInstanceMetaPath(),
|
|
m_strBasicDomain,
|
|
m_dwAuthFlags,
|
|
m_dwSSLAccessPermissions,
|
|
IsMasterInstance(),
|
|
IsSSLSupported(),
|
|
IsSSL128Supported(),
|
|
m_fU2Installed,
|
|
m_strCTLIdentifier,
|
|
m_strCTLStoreName,
|
|
fEditCTLs,
|
|
IsLocal(),
|
|
this
|
|
);
|
|
|
|
DWORD dwOldAccess = m_dwSSLAccessPermissions;
|
|
DWORD dwOldAuth = m_dwAuthFlags;
|
|
|
|
if (dlg.DoModal() == IDOK)
|
|
{
|
|
//
|
|
// See if anything has changed
|
|
//
|
|
if (dwOldAccess != m_dwSSLAccessPermissions
|
|
|| dwOldAuth != m_dwAuthFlags
|
|
)
|
|
{
|
|
//
|
|
// Mark as dirty
|
|
//
|
|
OnItemChanged();
|
|
}
|
|
|
|
//
|
|
// See if the CTL information has changed
|
|
//
|
|
if (dlg.m_bCTLDirty)
|
|
{
|
|
m_strCTLIdentifier = dlg.m_strCTLIdentifier;
|
|
m_strCTLStoreName = dlg.m_strCTLStoreName;
|
|
OnItemChanged();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
CW3SecurityPage::OnButtonIpSecurity()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
'tcpip' button handler
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
CIPDomainDlg dlg(
|
|
m_fIpDirty,
|
|
m_fDefaultGranted,
|
|
m_fOldDefaultGranted,
|
|
m_oblAccessList,
|
|
this
|
|
);
|
|
|
|
if (dlg.DoModal() == IDOK)
|
|
{
|
|
//
|
|
// Rebuild the list. Temporarily reset ownership, otherwise
|
|
// RemoveAll() will destroy the pointers which are shared with the
|
|
// new list.
|
|
//
|
|
BOOL fOwn = m_oblAccessList.SetOwnership(FALSE);
|
|
m_oblAccessList.RemoveAll();
|
|
m_oblAccessList.AddTail(&dlg.GetAccessList());
|
|
m_oblAccessList.SetOwnership(fOwn);
|
|
|
|
if (m_fIpDirty || m_fOldDefaultGranted != m_fDefaultGranted)
|
|
{
|
|
OnItemChanged();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
CW3SecurityPage::OnButtonGetCertificates()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
"get certicate" button handler
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
m_ocx_CertificateAuthorities.SetMachineName(GetServerName());
|
|
m_ocx_CertificateAuthorities.SetServerInstance(QueryInstanceMetaPath());
|
|
m_ocx_CertificateAuthorities.DoClick();
|
|
|
|
//
|
|
// There may now be a certificate. See if we should enable the edit button.
|
|
//
|
|
SetSSLControlState();
|
|
}
|
|
|
|
|
|
void
|
|
CW3SecurityPage::OnButtonViewCertificates()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
"view certicate" button handler
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
HCERTSTORE hStore = NULL;
|
|
PCCERT_CONTEXT pCert = NULL;
|
|
CMetaKey key(GetServerName(),
|
|
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
|
|
METADATA_MASTER_ROOT_HANDLE,
|
|
QueryInstanceMetaPath());
|
|
if (key.Succeeded())
|
|
{
|
|
CString store_name;
|
|
CBlob hash;
|
|
if ( SUCCEEDED(key.QueryValue(MD_SSL_CERT_STORE_NAME, store_name))
|
|
&& SUCCEEDED(key.QueryValue(MD_SSL_CERT_HASH, hash))
|
|
)
|
|
{
|
|
hStore = CertOpenStore(
|
|
CERT_STORE_PROV_SYSTEM,
|
|
PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
|
|
NULL,
|
|
CERT_SYSTEM_STORE_LOCAL_MACHINE,
|
|
store_name
|
|
);
|
|
if (hStore != NULL)
|
|
{
|
|
// Now we need to find cert by hash
|
|
CRYPT_HASH_BLOB crypt_hash;
|
|
crypt_hash.cbData = hash.GetSize();
|
|
crypt_hash.pbData = hash.GetData();
|
|
pCert = CertFindCertificateInStore(
|
|
hStore,
|
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
|
0, CERT_FIND_HASH, (LPVOID)&crypt_hash, NULL);
|
|
}
|
|
}
|
|
}
|
|
if (pCert)
|
|
{
|
|
BOOL fPropertiesChanged;
|
|
CRYPTUI_VIEWCERTIFICATE_STRUCT vcs;
|
|
HCERTSTORE hCertStore = ::CertDuplicateStore(hStore);
|
|
::ZeroMemory (&vcs, sizeof (vcs));
|
|
vcs.dwSize = sizeof (vcs);
|
|
vcs.hwndParent = GetParent()->GetSafeHwnd();
|
|
vcs.dwFlags = 0;
|
|
vcs.cStores = 1;
|
|
vcs.rghStores = &hCertStore;
|
|
vcs.pCertContext = pCert;
|
|
::CryptUIDlgViewCertificate(&vcs, &fPropertiesChanged);
|
|
::CertCloseStore (hCertStore, 0);
|
|
}
|
|
else
|
|
{
|
|
}
|
|
if (pCert != NULL)
|
|
::CertFreeCertificateContext(pCert);
|
|
if (hStore != NULL)
|
|
::CertCloseStore(hStore, 0);
|
|
}
|
|
|
|
void
|
|
CW3SecurityPage::OnItemChanged()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
All EN_CHANGE messages map to this function
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
SetModified(TRUE);
|
|
}
|
|
|
|
|
|
|