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.
1801 lines
66 KiB
1801 lines
66 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1997-2002.
|
|
//
|
|
// File: CertMgr.cpp
|
|
//
|
|
// Contents: Implementation of DLL Exports
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "stdafx.h"
|
|
#include <initguid.h>
|
|
#include <gpedit.h>
|
|
#include "CertMgr_i.c"
|
|
#include "about.h" // CCertMgrAbout
|
|
#include "compdata.h" // CCertMgrSnapin, CCertMgrExtension
|
|
#pragma warning(push, 3)
|
|
#include <compuuid.h> // UUIDs for Computer Management
|
|
#include "uuids.h"
|
|
#include <efsstruc.h>
|
|
#include <sceattch.h> // For Security Configuratino Editor snapin
|
|
#include <ntverp.h> // VER_PRODUCTVERSION_STR, VERS_COMPANYNAME_STR
|
|
#include <typeinfo.h>
|
|
#pragma warning(pop)
|
|
|
|
#include <dsadminp.h>
|
|
#include <ntdsapi.h>
|
|
|
|
#ifdef _DEBUG
|
|
#ifndef ALPHA
|
|
#define new DEBUG_NEW
|
|
#endif
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
bool g_bSchemaIsW2K = false;
|
|
|
|
USE_HANDLE_MACROS ("CERTMGR (CertMgr.cpp)")
|
|
|
|
LPCWSTR CM_HELP_TOPIC = L"sag_CMtopNode.htm";
|
|
LPCWSTR CM_HELP_FILE = L"certmgr.chm";
|
|
LPCWSTR CM_LINKED_HELP_FILE = L"CMconcepts.chm";
|
|
LPCWSTR PKP_LINKED_HELP_FILE = L"SecSetConcepts.chm";
|
|
LPCWSTR PKP_HELP_FILE = L"secsettings.chm";
|
|
LPCWSTR PKP_HELP_TOPIC = L"sag_secsettopnode.htm";
|
|
LPCWSTR SAFER_WINDOWS_HELP_FILE = L"SAFER.chm";
|
|
LPCWSTR SAFER_WINDOWS_LINKED_HELP_FILE = L"SAFERconcepts.chm";
|
|
LPCWSTR SAFER_HELP_TOPIC = L"SAFER_topnode.htm";
|
|
LPCWSTR CM_CONTEXT_HELP = L"\\help\\certmgr.hlp";
|
|
LPCWSTR WINDOWS_HELP = L"windows.hlp";
|
|
LPCWSTR EFS_LINKED_HELP_FILE = L"encrypt.chm";
|
|
LPCWSTR EFS_HELP_TOPIC = L"sag_SEProcsOndisk.htm";
|
|
|
|
//
|
|
// This is used by the nodetype utility routines in stdutils.cpp
|
|
//
|
|
|
|
const struct NODETYPE_GUID_ARRAYSTRUCT g_NodetypeGuids[CERTMGR_NUMTYPES] =
|
|
{
|
|
{ // CERTMGR_SNAPIN
|
|
structuuidNodetypeSnapin,
|
|
lstruuidNodetypeSnapin },
|
|
{ // CERTMGR_CERTIFICATE
|
|
structuuidNodetypeCertificate,
|
|
lstruuidNodetypeCertificate },
|
|
{ // CERTMGR_LOG_STORE
|
|
structuuidNodetypeLogStore,
|
|
lstruuidNodetypeLogStore },
|
|
{ // CERTMGR_PHYS_STORE
|
|
structuuidNodetypePhysStore,
|
|
lstruuidNodetypePhysStore },
|
|
{ // CERTMGR_USAGE
|
|
structuuidNodetypeUsage,
|
|
lstruuidNodetypeUsage },
|
|
{ // CERTMGR_CRL_CONTAINER
|
|
structuuidNodetypeCRLContainer,
|
|
lstruuidNodetypeCRLContainer },
|
|
{ // CERTMGR_CTL_CONTAINER
|
|
structuuidNodetypeCTLContainer,
|
|
lstruuidNodetypeCTLContainer },
|
|
{ // CERTMGR_CERT_CONTAINER
|
|
structuuidNodetypeCertContainer,
|
|
lstruuidNodetypeCertContainer },
|
|
{ // CERTMGR_CRL
|
|
structuuidNodetypeCRL,
|
|
lstruuidNodetypeCRL },
|
|
{ // CERTMGR_CTL
|
|
structuuidNodetypeCTL,
|
|
lstruuidNodetypeCTL },
|
|
{ // CERTMGR_AUTO_CERT_REQUEST
|
|
structuuidNodetypeAutoCertRequest,
|
|
lstruuidNodetypeAutoCertRequest },
|
|
{ // CERTMGR_CERT_POLICIES_USER,
|
|
structuuidNodetypeCertPoliciesUser,
|
|
lstruiidNodetypeCertPoliciesUser },
|
|
{ // CERTMGR_CERT_POLICIES_COMPUTER,
|
|
structuuidNodetypeCertPoliciesComputer,
|
|
lstruiidNodetypeCertPoliciesComputer },
|
|
{ // CERTMGR_LOG_STORE_GPE
|
|
structuuidNodetypeLogStore,
|
|
lstruuidNodetypeLogStore },
|
|
{ // CERTMGR_LOG_STORE_RSOP
|
|
structuuidNodetypeLogStore,
|
|
lstruuidNodetypeLogStore },
|
|
{ // CERTMGR_PKP_AUTOENROLLMENT_COMPUTER_SETTINGS
|
|
structuuidNodetypePKPAutoenrollmentSettings,
|
|
lstruiidNodetypePKPAutoenrollmentSettings },
|
|
{ // CERTMGR_PKP_AUTOENROLLMENT_USER_SETTINGS
|
|
0,
|
|
0 },
|
|
{ // CERTMGR_SAFER_COMPUTER_ROOT
|
|
structuuidNodetypeSaferComputerRoot,
|
|
lstruiidNodetypeSaferComputerRoot },
|
|
{ // CERTMGR_SAFER_COMPUTER_LEVELS
|
|
structuuidNodetypeSaferComputerLevels,
|
|
lstruiidNodetypeSaferComputerLevels },
|
|
{ // CERTMGR_SAFER_COMPUTER_ENTRIES
|
|
structuuidNodetypeSaferComputerEntries,
|
|
lstruiidNodetypeSaferComputerEntries },
|
|
{ // CERTMGR_SAFER_USER_ROOT
|
|
structuuidNodetypeSaferUserRoot,
|
|
lstruiidNodetypeSaferUserRoot },
|
|
{ // CERTMGR_SAFER_USER_ENTRIES
|
|
structuuidNodetypeSaferUserEntries,
|
|
lstruiidNodetypeSaferUserEntries },
|
|
{ // CERTMGR_SAFER_USER_LEVELS
|
|
structuuidNodetypeSaferUserLevels,
|
|
lstruiidNodetypeSaferUserLevels },
|
|
{ // CERTMGR_SAFER_COMPUTER_LEVEL
|
|
structuuidNodetypeSaferComputerLevel,
|
|
lstruiidNodetypeSaferComputerLevel },
|
|
{ // CERTMGR_SAFER_USER_LEVEL
|
|
structuuidNodetypeSaferUserLevel,
|
|
lstruiidNodetypeSaferUserLevel },
|
|
{ // CERTMGR_SAFER_COMPUTER_ENTRY
|
|
structuuidNodetypeSaferComputerEntry,
|
|
lstruiidNodetypeSaferComputerEntry },
|
|
{ // CERTMGR_SAFER_USER_ENTRY
|
|
structuuidNodetypeSaferUserEntry,
|
|
lstruiidNodetypeSaferUserEntry },
|
|
{ // CERTMGR_SAFER_COMPUTER_TRUSTED_PUBLISHERS
|
|
structuuidNodetypeSaferTrustedPublishers,
|
|
lstruiidNodetypeSaferTrustedPublisher },
|
|
{ // CERTMGR_SAFER_USER_TRUSTED_PUBLISHERS
|
|
0,
|
|
0 },
|
|
{ // CERTMGR_SAFER_COMPUTER_DEFINED_FILE_TYPES
|
|
structuuidNodetypeSaferDefinedFileTypes,
|
|
lstruiidNodetypeSaferDefinedFileTypes },
|
|
{ // CERTMGR_SAFER_USER_DEFINED_FILE_TYPES
|
|
0,
|
|
0 },
|
|
{ // CERTMGR_SAFER_USER_ENFORCEMENT
|
|
structuuidNodetypeSaferEnforcement,
|
|
lstruiidNodetypeSaferEnforcement },
|
|
{ // CERTMGR_SAFER_COMPUTER_ENFORCEMENT
|
|
0,
|
|
0 }
|
|
};
|
|
|
|
const struct NODETYPE_GUID_ARRAYSTRUCT* g_aNodetypeGuids = g_NodetypeGuids;
|
|
|
|
const int g_cNumNodetypeGuids = CERTMGR_NUMTYPES;
|
|
|
|
|
|
HINSTANCE g_hInstance = 0;
|
|
CString g_szFileName;
|
|
CComModule _Module;
|
|
|
|
BEGIN_OBJECT_MAP (ObjectMap)
|
|
OBJECT_ENTRY (CLSID_CertificateManager, CCertMgrSnapin)
|
|
OBJECT_ENTRY (CLSID_CertificateManagerPKPOLExt, CCertMgrPKPolExtension)
|
|
OBJECT_ENTRY (CLSID_CertificateManagerAbout, CCertMgrAbout)
|
|
OBJECT_ENTRY (CLSID_PublicKeyPoliciesAbout, CPublicKeyPoliciesAbout)
|
|
OBJECT_ENTRY (CLSID_SaferWindowsExtension, CSaferWindowsExtension)
|
|
OBJECT_ENTRY (CLSID_SaferWindowsAbout, CSaferWindowsAbout)
|
|
END_OBJECT_MAP ()
|
|
|
|
class CCertMgrApp : public CWinApp
|
|
{
|
|
public:
|
|
CCertMgrApp ();
|
|
virtual BOOL InitInstance ();
|
|
virtual int ExitInstance ();
|
|
private:
|
|
};
|
|
|
|
CCertMgrApp theApp;
|
|
|
|
CCertMgrApp::CCertMgrApp ()
|
|
{
|
|
// security review 2/26/2002 BryanWal ok
|
|
LPWSTR pszCommandLine = _wcsupr (::GetCommandLine ());
|
|
LPWSTR pszParam = L"/CERTMGR:FILENAME=";
|
|
// security review 2/26/2002 BryanWal ok
|
|
size_t len = wcslen (pszParam);
|
|
|
|
// security review 2/26/2002 BryanWal ok
|
|
// NOTICE: handles very long strings - the Windows commandline parser will
|
|
// return an error if the commandline is too long
|
|
LPWSTR pszArg = wcsstr (pszCommandLine, pszParam);
|
|
if ( !pszArg )
|
|
{
|
|
pszParam = L"-CERTMGR:FILENAME=";
|
|
// security review 2/26/2002 BryanWal ok
|
|
pszArg = wcsstr (pszCommandLine, pszParam);
|
|
}
|
|
if ( pszArg )
|
|
{
|
|
LPWSTR pszDelimiters = 0;
|
|
|
|
// jump past the name of the arg to get the value
|
|
pszArg += len;
|
|
// Is the file name delimited by double quotes? This could indicate
|
|
// the presence of spaces in the name. If so, skip the quote
|
|
// and look for the closing quote. Otherwise, look for the next
|
|
// space, tab or NULL terminator.
|
|
if ( L'\"' == pszArg[0] )
|
|
{
|
|
pszDelimiters = L"\"";
|
|
pszArg++;
|
|
}
|
|
else
|
|
pszDelimiters = L" \t\0";
|
|
|
|
// security review 2/26/2002 BryanWal ok
|
|
len = wcscspn (pszArg, pszDelimiters);
|
|
* (pszArg + len) = 0;
|
|
g_szFileName = pszArg;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL CCertMgrApp::InitInstance ()
|
|
{
|
|
#ifdef _MERGE_PROXYSTUB
|
|
hProxyDll = m_hInstance;
|
|
|
|
#endif
|
|
g_hInstance = m_hInstance;
|
|
AfxSetResourceHandle (m_hInstance);
|
|
_Module.Init (ObjectMap, m_hInstance);
|
|
|
|
#if DBG == 1
|
|
CheckDebugOutputLevel ();
|
|
#endif
|
|
|
|
SHFusionInitializeFromModuleID (m_hInstance, 2);
|
|
|
|
return CWinApp::InitInstance ();
|
|
}
|
|
|
|
int CCertMgrApp::ExitInstance ()
|
|
{
|
|
SHFusionUninitialize();
|
|
|
|
SetRegistryScope (0, false);
|
|
_Module.Term ();
|
|
|
|
return CWinApp::ExitInstance ();
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Used to determine whether the DLL can be unloaded by OLE
|
|
|
|
STDAPI DllCanUnloadNow (void)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetStaticModuleState ());
|
|
return (AfxDllCanUnloadNow ()==S_OK && _Module.GetLockCount ()==0) ? S_OK : S_FALSE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Returns a class factory to create an object of the requested type
|
|
|
|
STDAPI DllGetClassObject (REFCLSID rclsid, REFIID riid, LPVOID* ppv)
|
|
{
|
|
return _Module.GetClassObject (rclsid, riid, ppv);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// DllRegisterServer - Adds entries to the system registry
|
|
//const WCHAR g_szNameString[] = TEXT ("NameString");
|
|
//const WCHAR g_szNodeType[] = TEXT ("NodeType");
|
|
|
|
|
|
STDAPI DllRegisterServer (void)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
// NTRAID# 88502 intlext: mui: me common: crypto: certificate 's
|
|
// intended purpose string unlocalized
|
|
// Unregister szOID_EFS_RECOVERY
|
|
CRYPT_OID_INFO oid;
|
|
// security review 2/26/2002 BryanWal ok
|
|
::ZeroMemory (&oid, sizeof (oid));
|
|
oid.cbSize = sizeof (CRYPT_OID_INFO);
|
|
oid.pszOID = szOID_EFS_RECOVERY;
|
|
oid.dwGroupId = CRYPT_ENHKEY_USAGE_OID_GROUP_ID;
|
|
|
|
CryptUnregisterOIDInfo (&oid);
|
|
|
|
// registers object, typelib and all interfaces in typelib
|
|
HRESULT hr = _Module.RegisterServer (TRUE);
|
|
ASSERT (SUCCEEDED (hr));
|
|
if ( E_ACCESSDENIED == hr )
|
|
{
|
|
CString caption;
|
|
CString text;
|
|
CThemeContextActivator activator;
|
|
|
|
VERIFY (caption.LoadString (IDS_REGISTER_CERTMGR));
|
|
VERIFY (text.LoadString (IDS_INSUFFICIENT_RIGHTS_TO_REGISTER_CERTMGR));
|
|
|
|
MessageBox (NULL, text, caption, MB_OK);
|
|
return hr;
|
|
}
|
|
|
|
try
|
|
{
|
|
CString strGUID;
|
|
CString snapinName;
|
|
CString verProviderStr, verVersionStr;
|
|
AMC::CRegKey rkSnapins;
|
|
BOOL fFound = rkSnapins.OpenKeyEx (HKEY_LOCAL_MACHINE, SNAPINS_KEY);
|
|
ASSERT (fFound);
|
|
if ( fFound )
|
|
{
|
|
{
|
|
AMC::CRegKey rkCertMgrSnapin;
|
|
hr = GuidToCString (&strGUID, CLSID_CertificateManager);
|
|
if ( FAILED (hr) )
|
|
{
|
|
ASSERT (FALSE);
|
|
return SELFREG_E_CLASS;
|
|
}
|
|
rkCertMgrSnapin.CreateKeyEx (rkSnapins, strGUID);
|
|
ASSERT (rkCertMgrSnapin.GetLastError () == ERROR_SUCCESS);
|
|
rkCertMgrSnapin.SetString (g_szNodeType, g_aNodetypeGuids[CERTMGR_SNAPIN].bstr);
|
|
VERIFY (snapinName.LoadString (IDS_CERTIFICATE_MANAGER_REGISTRY));
|
|
rkCertMgrSnapin.SetString (g_szNameString, (LPCWSTR) snapinName);
|
|
hr = GuidToCString (&strGUID, CLSID_CertificateManagerAbout);
|
|
if ( FAILED (hr) )
|
|
{
|
|
ASSERT (FALSE);
|
|
return SELFREG_E_CLASS;
|
|
}
|
|
rkCertMgrSnapin.SetString (L"About", strGUID);
|
|
|
|
// security review 2/26/2002 BryanWal ok
|
|
size_t len = strlen (VER_COMPANYNAME_STR);
|
|
// last arg includes null-terminator. If the last arg doesn't
|
|
// include the null terminator, the '/0' will not get converted.
|
|
len = mbstowcs (verProviderStr.GetBufferSetLength ((int) len),
|
|
VER_COMPANYNAME_STR, len+1);
|
|
rkCertMgrSnapin.SetString (L"Provider", verProviderStr);
|
|
|
|
// security review 2/26/2002 BryanWal ok
|
|
len = strlen (VER_PRODUCTVERSION_STR);
|
|
// security review 2/26/2002 BryanWal ok
|
|
len = mbstowcs (verVersionStr.GetBufferSetLength ((int)len),
|
|
VER_PRODUCTVERSION_STR, len+1); // last arg includes null-terminator
|
|
rkCertMgrSnapin.SetString (L"Version", verVersionStr);
|
|
|
|
AMC::CRegKey rkCertMgrStandalone;
|
|
rkCertMgrStandalone.CreateKeyEx (rkCertMgrSnapin, g_szStandAlone);
|
|
ASSERT (rkCertMgrStandalone.GetLastError () == ERROR_SUCCESS);
|
|
|
|
|
|
AMC::CRegKey rkMyNodeTypes;
|
|
rkMyNodeTypes.CreateKeyEx (rkCertMgrSnapin, g_szNodeTypes);
|
|
ASSERT (rkMyNodeTypes.GetLastError () == ERROR_SUCCESS);
|
|
AMC::CRegKey rkMyNodeType;
|
|
|
|
for (int i = CERTMGR_SNAPIN; i < CERTMGR_NUMTYPES; i++)
|
|
{
|
|
switch (i)
|
|
{
|
|
case CERTMGR_LOG_STORE_GPE:
|
|
case CERTMGR_LOG_STORE_RSOP:
|
|
case CERTMGR_AUTO_CERT_REQUEST:
|
|
case CERTMGR_CERT_POLICIES_USER:
|
|
case CERTMGR_CERT_POLICIES_COMPUTER:
|
|
case CERTMGR_PKP_AUTOENROLLMENT_USER_SETTINGS: // not necessary - just another kind of the same node
|
|
break;
|
|
|
|
// TODO: What to do with these?
|
|
case CERTMGR_SAFER_COMPUTER_ROOT:
|
|
case CERTMGR_SAFER_USER_ROOT:
|
|
case CERTMGR_SAFER_COMPUTER_LEVELS:
|
|
case CERTMGR_SAFER_USER_LEVELS:
|
|
case CERTMGR_SAFER_COMPUTER_ENTRIES:
|
|
case CERTMGR_SAFER_USER_ENTRIES:
|
|
case CERTMGR_SAFER_COMPUTER_LEVEL:
|
|
case CERTMGR_SAFER_USER_LEVEL:
|
|
case CERTMGR_SAFER_COMPUTER_ENTRY:
|
|
case CERTMGR_SAFER_USER_ENTRY:
|
|
case CERTMGR_SAFER_COMPUTER_TRUSTED_PUBLISHERS:
|
|
case CERTMGR_SAFER_USER_TRUSTED_PUBLISHERS:
|
|
case CERTMGR_SAFER_COMPUTER_DEFINED_FILE_TYPES:
|
|
case CERTMGR_SAFER_USER_DEFINED_FILE_TYPES:
|
|
case CERTMGR_SAFER_USER_ENFORCEMENT:
|
|
case CERTMGR_SAFER_COMPUTER_ENFORCEMENT:
|
|
break;
|
|
|
|
case CERTMGR_PKP_AUTOENROLLMENT_COMPUTER_SETTINGS:
|
|
default:
|
|
// security review 2/26/2002 BryanWal ok
|
|
if ( wcslen (g_aNodetypeGuids[i].bstr) )
|
|
{
|
|
rkMyNodeType.CreateKeyEx (rkMyNodeTypes, g_aNodetypeGuids[i].bstr);
|
|
ASSERT (rkMyNodeType.GetLastError () == ERROR_SUCCESS);
|
|
rkMyNodeType.CloseKey ();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// BryanWal 5/18/00
|
|
// 94793: MUI: MMC: Certificates snap-in stores its display
|
|
// information in the registry
|
|
//
|
|
// MMC now supports NameStringIndirect
|
|
//
|
|
WCHAR achModuleFileName[MAX_PATH+20];
|
|
if (0 < ::GetModuleFileName(
|
|
AfxGetInstanceHandle(),
|
|
achModuleFileName,
|
|
sizeof(achModuleFileName)/sizeof(WCHAR) )) // size of buffer in TCHARS
|
|
{
|
|
CString strNameIndirect;
|
|
strNameIndirect.Format(L"@%s,-%d",
|
|
achModuleFileName,
|
|
IDS_CERTIFICATE_MANAGER_REGISTRY );
|
|
rkCertMgrSnapin.SetString(L"NameStringIndirect",
|
|
strNameIndirect );
|
|
}
|
|
|
|
rkCertMgrSnapin.CloseKey ();
|
|
}
|
|
|
|
AMC::CRegKey rkNodeTypes;
|
|
fFound = rkNodeTypes.OpenKeyEx (HKEY_LOCAL_MACHINE, NODE_TYPES_KEY);
|
|
ASSERT (fFound);
|
|
if ( fFound )
|
|
{
|
|
AMC::CRegKey rkNodeType;
|
|
|
|
for (int i = CERTMGR_SNAPIN; i < CERTMGR_NUMTYPES; i++)
|
|
{
|
|
switch (i)
|
|
{
|
|
// these types are not used in the primary snapin
|
|
case CERTMGR_LOG_STORE_GPE:
|
|
case CERTMGR_LOG_STORE_RSOP:
|
|
case CERTMGR_AUTO_CERT_REQUEST:
|
|
case CERTMGR_CERT_POLICIES_USER:
|
|
case CERTMGR_CERT_POLICIES_COMPUTER:
|
|
case CERTMGR_PKP_AUTOENROLLMENT_COMPUTER_SETTINGS:
|
|
case CERTMGR_PKP_AUTOENROLLMENT_USER_SETTINGS:
|
|
case CERTMGR_SAFER_COMPUTER_ROOT:
|
|
case CERTMGR_SAFER_USER_ROOT:
|
|
case CERTMGR_SAFER_COMPUTER_LEVELS:
|
|
case CERTMGR_SAFER_USER_LEVELS:
|
|
case CERTMGR_SAFER_COMPUTER_ENTRIES:
|
|
case CERTMGR_SAFER_USER_ENTRIES:
|
|
case CERTMGR_SAFER_COMPUTER_LEVEL:
|
|
case CERTMGR_SAFER_USER_LEVEL:
|
|
case CERTMGR_SAFER_COMPUTER_ENTRY:
|
|
case CERTMGR_SAFER_USER_ENTRY:
|
|
case CERTMGR_SAFER_COMPUTER_TRUSTED_PUBLISHERS:
|
|
case CERTMGR_SAFER_USER_TRUSTED_PUBLISHERS:
|
|
case CERTMGR_SAFER_COMPUTER_DEFINED_FILE_TYPES:
|
|
case CERTMGR_SAFER_USER_DEFINED_FILE_TYPES:
|
|
case CERTMGR_SAFER_USER_ENFORCEMENT:
|
|
case CERTMGR_SAFER_COMPUTER_ENFORCEMENT:
|
|
break;
|
|
|
|
default:
|
|
// security review 2/26/2002 BryanWal ok
|
|
if ( wcslen (g_aNodetypeGuids[i].bstr) )
|
|
{
|
|
rkNodeType.CreateKeyEx (rkNodeTypes, g_aNodetypeGuids[i].bstr);
|
|
ASSERT (rkNodeType.GetLastError () == ERROR_SUCCESS);
|
|
rkNodeType.CloseKey ();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
if ( IsWindowsNT () )
|
|
{
|
|
{
|
|
// Public Key PoliciesSnap-in under Security Configuration Editor (SCE)
|
|
// Certificate Manager extends "Computer Settings" and
|
|
// "User Settings" node
|
|
CString strCertMgrExtPKPolGUID;
|
|
hr = GuidToCString (&strCertMgrExtPKPolGUID,
|
|
CLSID_CertificateManagerPKPOLExt);
|
|
if ( FAILED (hr) )
|
|
{
|
|
ASSERT (FALSE);
|
|
return SELFREG_E_CLASS;
|
|
}
|
|
|
|
VERIFY (snapinName.LoadString (IDS_CERT_MGR_SCE_EXTENSION_REGISTRY));
|
|
{
|
|
AMC::CRegKey rkCertMgrExtension;
|
|
rkCertMgrExtension.CreateKeyEx (rkSnapins, strCertMgrExtPKPolGUID);
|
|
ASSERT (rkCertMgrExtension.GetLastError () == ERROR_SUCCESS);
|
|
rkCertMgrExtension.SetString (g_szNameString, (LPCWSTR) snapinName);
|
|
hr = GuidToCString (&strGUID, CLSID_PublicKeyPoliciesAbout);
|
|
if ( FAILED (hr) )
|
|
{
|
|
ASSERT (FALSE);
|
|
return SELFREG_E_CLASS;
|
|
}
|
|
rkCertMgrExtension.SetString (L"About", strGUID);
|
|
rkCertMgrExtension.SetString (L"Provider", verProviderStr);
|
|
rkCertMgrExtension.SetString (L"Version", verVersionStr);
|
|
|
|
|
|
// Register the node types of the extension
|
|
AMC::CRegKey rkMyNodeTypes;
|
|
rkMyNodeTypes.CreateKeyEx (rkCertMgrExtension, g_szNodeTypes);
|
|
ASSERT (rkMyNodeTypes.GetLastError () == ERROR_SUCCESS);
|
|
AMC::CRegKey rkMyNodeType;
|
|
for (int i = CERTMGR_SNAPIN; i < CERTMGR_NUMTYPES; i++)
|
|
{
|
|
switch (i)
|
|
{
|
|
// None of these are used in the Public Key Policy extension
|
|
case CERTMGR_USAGE:
|
|
case CERTMGR_PHYS_STORE:
|
|
case CERTMGR_LOG_STORE:
|
|
case CERTMGR_CRL_CONTAINER:
|
|
case CERTMGR_CTL_CONTAINER:
|
|
case CERTMGR_CERT_CONTAINER:
|
|
case CERTMGR_CRL:
|
|
case CERTMGR_SAFER_COMPUTER_ROOT:
|
|
case CERTMGR_SAFER_USER_ROOT:
|
|
case CERTMGR_SAFER_COMPUTER_LEVELS:
|
|
case CERTMGR_SAFER_USER_LEVELS:
|
|
case CERTMGR_SAFER_COMPUTER_ENTRIES:
|
|
case CERTMGR_SAFER_USER_ENTRIES:
|
|
case CERTMGR_SAFER_COMPUTER_LEVEL:
|
|
case CERTMGR_SAFER_USER_LEVEL:
|
|
case CERTMGR_SAFER_COMPUTER_ENTRY:
|
|
case CERTMGR_SAFER_USER_ENTRY:
|
|
case CERTMGR_SAFER_COMPUTER_TRUSTED_PUBLISHERS:
|
|
case CERTMGR_SAFER_USER_TRUSTED_PUBLISHERS:
|
|
case CERTMGR_SAFER_COMPUTER_DEFINED_FILE_TYPES:
|
|
case CERTMGR_SAFER_USER_DEFINED_FILE_TYPES:
|
|
case CERTMGR_SAFER_USER_ENFORCEMENT:
|
|
case CERTMGR_SAFER_COMPUTER_ENFORCEMENT:
|
|
|
|
// not necessary - just another kind of the same node
|
|
case CERTMGR_PKP_AUTOENROLLMENT_USER_SETTINGS:
|
|
break;
|
|
|
|
default:
|
|
// security review 2/26/2002 BryanWal ok
|
|
if ( wcslen (g_aNodetypeGuids[i].bstr) )
|
|
{
|
|
rkMyNodeType.CreateKeyEx (rkMyNodeTypes, g_aNodetypeGuids[i].bstr);
|
|
ASSERT (rkMyNodeType.GetLastError () == ERROR_SUCCESS);
|
|
rkMyNodeType.CloseKey ();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// BryanWal 5/18/00
|
|
// 94793: MUI: MMC: Certificates snap-in stores its display
|
|
// information in the registry
|
|
//
|
|
// MMC now supports NameStringIndirect
|
|
//
|
|
WCHAR achModuleFileName[MAX_PATH+20];
|
|
if (0 < ::GetModuleFileName(
|
|
AfxGetInstanceHandle(),
|
|
achModuleFileName,
|
|
sizeof(achModuleFileName)/sizeof(WCHAR) )) // size of buffer in TCHARS
|
|
{
|
|
CString strNameIndirect;
|
|
strNameIndirect.Format(L"@%s,-%d",
|
|
achModuleFileName,
|
|
IDS_CERT_MGR_SCE_EXTENSION_REGISTRY );
|
|
rkCertMgrExtension.SetString( L"NameStringIndirect",
|
|
strNameIndirect );
|
|
}
|
|
rkCertMgrExtension.CloseKey ();
|
|
}
|
|
|
|
hr = GuidToCString (&strGUID, cNodetypeSceTemplate);
|
|
if ( FAILED (hr) )
|
|
{
|
|
ASSERT (FALSE);
|
|
return SELFREG_E_CLASS;
|
|
}
|
|
rkNodeType.CreateKeyEx (rkNodeTypes, strGUID);
|
|
ASSERT (rkNodeType.GetLastError () == ERROR_SUCCESS);
|
|
if ( rkNodeType.GetLastError () == ERROR_SUCCESS )
|
|
{
|
|
AMC::CRegKey rkExtensions;
|
|
ASSERT (rkExtensions.GetLastError () == ERROR_SUCCESS);
|
|
rkExtensions.CreateKeyEx (rkNodeType, g_szExtensions);
|
|
AMC::CRegKey rkNameSpace;
|
|
rkNameSpace.CreateKeyEx (rkExtensions, g_szNameSpace);
|
|
ASSERT (rkNameSpace.GetLastError () == ERROR_SUCCESS);
|
|
rkNameSpace.SetString (strCertMgrExtPKPolGUID, (LPCWSTR) snapinName);
|
|
rkNodeType.CloseKey ();
|
|
}
|
|
else
|
|
return SELFREG_E_CLASS;
|
|
}
|
|
|
|
|
|
{
|
|
// SAFER Windows Snap-in under Security Configuration Editor (SCE)
|
|
// Certificate Manager extends "Computer Settings" and
|
|
// "User Settings" node
|
|
CString strSaferWindowsExtensionGUID;
|
|
hr = GuidToCString (&strSaferWindowsExtensionGUID,
|
|
CLSID_SaferWindowsExtension);
|
|
if ( FAILED (hr) )
|
|
{
|
|
ASSERT (FALSE);
|
|
return SELFREG_E_CLASS;
|
|
}
|
|
|
|
VERIFY (snapinName.LoadString (IDS_SAFER_WINDOWS_EXTENSION_REGISTRY));
|
|
{
|
|
AMC::CRegKey rkCertMgrExtension;
|
|
rkCertMgrExtension.CreateKeyEx (rkSnapins, strSaferWindowsExtensionGUID);
|
|
ASSERT (rkCertMgrExtension.GetLastError () == ERROR_SUCCESS);
|
|
rkCertMgrExtension.SetString (g_szNameString, (LPCWSTR) snapinName);
|
|
hr = GuidToCString (&strGUID, CLSID_SaferWindowsAbout);
|
|
if ( FAILED (hr) )
|
|
{
|
|
ASSERT (FALSE);
|
|
return SELFREG_E_CLASS;
|
|
}
|
|
rkCertMgrExtension.SetString (L"About", strGUID);
|
|
rkCertMgrExtension.SetString (L"Provider", verProviderStr);
|
|
rkCertMgrExtension.SetString (L"Version", verVersionStr);
|
|
|
|
|
|
// Register the node types of the extension
|
|
AMC::CRegKey rkMyNodeTypes;
|
|
rkMyNodeTypes.CreateKeyEx (rkCertMgrExtension, g_szNodeTypes);
|
|
ASSERT (rkMyNodeTypes.GetLastError () == ERROR_SUCCESS);
|
|
AMC::CRegKey rkMyNodeType;
|
|
for (int i = CERTMGR_SNAPIN; i < CERTMGR_NUMTYPES; i++)
|
|
{
|
|
switch (i)
|
|
{
|
|
case CERTMGR_CERTIFICATE:
|
|
case CERTMGR_LOG_STORE:
|
|
case CERTMGR_PHYS_STORE:
|
|
case CERTMGR_USAGE:
|
|
case CERTMGR_CRL_CONTAINER:
|
|
case CERTMGR_CTL_CONTAINER:
|
|
case CERTMGR_CERT_CONTAINER:
|
|
case CERTMGR_CRL:
|
|
case CERTMGR_CTL:
|
|
case CERTMGR_AUTO_CERT_REQUEST:
|
|
case CERTMGR_CERT_POLICIES_USER:
|
|
case CERTMGR_CERT_POLICIES_COMPUTER:
|
|
case CERTMGR_LOG_STORE_GPE:
|
|
case CERTMGR_LOG_STORE_RSOP:
|
|
case CERTMGR_PKP_AUTOENROLLMENT_USER_SETTINGS:
|
|
case CERTMGR_PKP_AUTOENROLLMENT_COMPUTER_SETTINGS:
|
|
// None of these are used in the Software Restriction Policies extension
|
|
break;
|
|
|
|
case CERTMGR_SAFER_COMPUTER_ROOT:
|
|
case CERTMGR_SAFER_USER_ROOT:
|
|
case CERTMGR_SAFER_COMPUTER_LEVELS:
|
|
case CERTMGR_SAFER_USER_LEVELS:
|
|
case CERTMGR_SAFER_COMPUTER_ENTRIES:
|
|
case CERTMGR_SAFER_USER_ENTRIES:
|
|
case CERTMGR_SAFER_COMPUTER_LEVEL:
|
|
case CERTMGR_SAFER_USER_LEVEL:
|
|
case CERTMGR_SAFER_COMPUTER_ENTRY:
|
|
case CERTMGR_SAFER_USER_ENTRY:
|
|
case CERTMGR_SAFER_COMPUTER_TRUSTED_PUBLISHERS:
|
|
case CERTMGR_SAFER_USER_TRUSTED_PUBLISHERS:
|
|
case CERTMGR_SAFER_COMPUTER_DEFINED_FILE_TYPES:
|
|
case CERTMGR_SAFER_USER_DEFINED_FILE_TYPES:
|
|
case CERTMGR_SAFER_USER_ENFORCEMENT:
|
|
case CERTMGR_SAFER_COMPUTER_ENFORCEMENT:
|
|
default:
|
|
// security review 2/26/2002 BryanWal ok
|
|
if ( g_aNodetypeGuids[i].bstr && wcslen (g_aNodetypeGuids[i].bstr) )
|
|
{
|
|
rkMyNodeType.CreateKeyEx (rkMyNodeTypes, g_aNodetypeGuids[i].bstr);
|
|
ASSERT (rkMyNodeType.GetLastError () == ERROR_SUCCESS);
|
|
rkMyNodeType.CloseKey ();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
WCHAR achModuleFileName[MAX_PATH+20];
|
|
if (0 < ::GetModuleFileName(
|
|
AfxGetInstanceHandle(),
|
|
achModuleFileName,
|
|
sizeof(achModuleFileName)/sizeof(WCHAR) )) // size of buffer in TCHARS
|
|
{
|
|
CString strNameIndirect;
|
|
strNameIndirect.Format( L"@%s,-%d",
|
|
achModuleFileName,
|
|
IDS_SAFER_WINDOWS_EXTENSION_REGISTRY );
|
|
rkCertMgrExtension.SetString( L"NameStringIndirect",
|
|
strNameIndirect );
|
|
}
|
|
rkCertMgrExtension.CloseKey ();
|
|
}
|
|
|
|
hr = GuidToCString (&strGUID, cNodetypeSceTemplate);
|
|
if ( FAILED (hr) )
|
|
{
|
|
ASSERT (FALSE);
|
|
return SELFREG_E_CLASS;
|
|
}
|
|
rkNodeType.CreateKeyEx (rkNodeTypes, strGUID);
|
|
ASSERT (rkNodeType.GetLastError () == ERROR_SUCCESS);
|
|
if ( rkNodeType.GetLastError () == ERROR_SUCCESS )
|
|
{
|
|
AMC::CRegKey rkExtensions;
|
|
ASSERT (rkExtensions.GetLastError () == ERROR_SUCCESS);
|
|
rkExtensions.CreateKeyEx (rkNodeType, g_szExtensions);
|
|
AMC::CRegKey rkNameSpace;
|
|
rkNameSpace.CreateKeyEx (rkExtensions, g_szNameSpace);
|
|
ASSERT (rkNameSpace.GetLastError () == ERROR_SUCCESS);
|
|
rkNameSpace.SetString (strSaferWindowsExtensionGUID,
|
|
(LPCWSTR) snapinName);
|
|
rkNodeType.CloseKey ();
|
|
}
|
|
else
|
|
return SELFREG_E_CLASS;
|
|
}
|
|
|
|
// Deregister as extension to My Computer System Tools node
|
|
// CODEWORK It would be good if we deregistered the server too
|
|
// JonN 12/14/98
|
|
try
|
|
{
|
|
fFound = rkNodeType.OpenKeyEx (rkNodeTypes, TEXT(struuidNodetypeSystemTools));
|
|
// if this fails just carry on
|
|
if ( fFound )
|
|
{
|
|
AMC::CRegKey rkExtensions;
|
|
ASSERT (rkExtensions.GetLastError () == ERROR_SUCCESS);
|
|
fFound = rkExtensions.OpenKeyEx (rkNodeType, g_szExtensions);
|
|
// if this fails just carry on
|
|
if ( fFound )
|
|
{
|
|
AMC::CRegKey rkNameSpace;
|
|
ASSERT (rkNameSpace.GetLastError () == ERROR_SUCCESS);
|
|
fFound = rkNameSpace.OpenKeyEx (rkExtensions, g_szNameSpace);
|
|
// if this fails just carry on
|
|
if ( fFound )
|
|
{
|
|
rkNameSpace.DeleteValue( L"{9C7910D2-4C01-11D1-856B-00C04FB94F17}" );
|
|
}
|
|
}
|
|
}
|
|
} catch (COleException* /*e*/)
|
|
{
|
|
// don't do anything
|
|
}
|
|
|
|
} // endif IsWindowsNT ()
|
|
rkNodeTypes.CloseKey ();
|
|
}
|
|
else
|
|
return SELFREG_E_CLASS;
|
|
}
|
|
else
|
|
return SELFREG_E_CLASS;
|
|
}
|
|
catch (COleException* e)
|
|
{
|
|
ASSERT (FALSE);
|
|
e->Delete ();
|
|
return SELFREG_E_CLASS;
|
|
}
|
|
|
|
ASSERT (SUCCEEDED (hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// DllUnregisterServer - Removes entries from the system registry
|
|
|
|
STDAPI DllUnregisterServer (void)
|
|
{
|
|
|
|
_Module.UnregisterServer ();
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
STDAPI DllInstall(BOOL /*bInstall*/, LPCWSTR pszCmdLine)
|
|
{
|
|
LPCWSTR wszCurrentCmd = pszCmdLine;
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
|
|
// parse the cmd line
|
|
while(wszCurrentCmd && *wszCurrentCmd)
|
|
{
|
|
while(*wszCurrentCmd == L' ')
|
|
wszCurrentCmd++;
|
|
if(*wszCurrentCmd == 0)
|
|
break;
|
|
|
|
switch(*wszCurrentCmd++)
|
|
{
|
|
case L'?':
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// ConvertNameBlobToString ()
|
|
//
|
|
// nameBlob (IN) - Contains a CERT_NAME_BLOB to be decoded
|
|
// pszName (OUT) - The decoded contents of the name blob
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
HRESULT ConvertNameBlobToString (CERT_NAME_BLOB nameBlob, CString & pszName)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dwSize = 0;
|
|
|
|
// Call CertNameToStr to get returned the string length.
|
|
dwSize = CertNameToStr (
|
|
MY_ENCODING_TYPE, // Encoding type
|
|
&nameBlob, // CERT_NAME_BLOB
|
|
CERT_SIMPLE_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, // Type
|
|
NULL, // Place to return string
|
|
dwSize); // Size of string (chars),
|
|
// including zero terminator.
|
|
|
|
ASSERT (dwSize > 1);
|
|
if ( dwSize > 1 ) // This function always returns a null char
|
|
// (0), so the minimum count returned will
|
|
// be 1, even if nothing got converted.
|
|
{
|
|
// Call CertNameToStr to get the string.
|
|
dwSize = CertNameToStr (
|
|
MY_ENCODING_TYPE, // Encoding type
|
|
&nameBlob, // CERT_NAME_BLOB
|
|
CERT_SIMPLE_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, // Type
|
|
pszName.GetBufferSetLength (dwSize), // Place to return string
|
|
dwSize); // Size of string (chars)
|
|
ASSERT (dwSize > 1);
|
|
pszName.ReleaseBuffer ();
|
|
if ( dwSize <= 1 )
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// FormatDate ()
|
|
//
|
|
// utcDateTime (IN) - A FILETIME in UTC format.
|
|
// pszDateTime (OUT) - A string containing the local date and time
|
|
// formatted by locale and user preference
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT FormatDate (FILETIME utcDateTime, CString & pszDateTime, DWORD dwDateFlags, bool bGetTime)
|
|
{
|
|
// Time is returned as UTC, will be displayed as local.
|
|
// Use FileTimeToLocalFileTime () to make it local,
|
|
// then call FileTimeToSystemTime () to convert to system time, then
|
|
// format with GetDateFormat () and GetTimeFormat () to display
|
|
// according to user and locale preferences
|
|
HRESULT hr = S_OK;
|
|
FILETIME localDateTime;
|
|
|
|
BOOL bResult = FileTimeToLocalFileTime (&utcDateTime, // pointer to UTC file time to convert
|
|
&localDateTime); // pointer to converted file time
|
|
ASSERT (bResult);
|
|
if ( bResult )
|
|
{
|
|
SYSTEMTIME sysTime;
|
|
|
|
bResult = FileTimeToSystemTime (
|
|
&localDateTime, // pointer to file time to convert
|
|
&sysTime); // pointer to structure to receive system time
|
|
if ( bResult )
|
|
{
|
|
CString date;
|
|
CString time;
|
|
|
|
// Get date
|
|
// Get length to allocate buffer of sufficient size
|
|
int iLen = GetDateFormat (
|
|
LOCALE_USER_DEFAULT, // locale for which date is to be formatted
|
|
dwDateFlags, // flags specifying function options
|
|
&sysTime, // date to be formatted
|
|
0, // date format string
|
|
0, // buffer for storing formatted string
|
|
0); // size of buffer
|
|
ASSERT (iLen > 0);
|
|
if ( iLen > 0 )
|
|
{
|
|
int iResult = GetDateFormat (
|
|
LOCALE_USER_DEFAULT, // locale for which date is to be formatted
|
|
dwDateFlags, // flags specifying function options
|
|
&sysTime, // date to be formatted
|
|
0, // date format string
|
|
date.GetBufferSetLength (iLen), // buffer for storing formatted string
|
|
iLen); // size of buffer
|
|
ASSERT (iResult);
|
|
date.ReleaseBuffer ();
|
|
if ( iResult )
|
|
pszDateTime = date;
|
|
else
|
|
hr = HRESULT_FROM_WIN32 (GetLastError ());
|
|
|
|
if ( iResult && bGetTime )
|
|
{
|
|
// Get time
|
|
// Get length to allocate buffer of sufficient size
|
|
iLen = GetTimeFormat (
|
|
LOCALE_USER_DEFAULT, // locale for which date is to be formatted
|
|
0, // flags specifying function options
|
|
&sysTime, // date to be formatted
|
|
0, // date format string
|
|
0, // buffer for storing formatted string
|
|
0); // size of buffer
|
|
ASSERT (iLen > 0);
|
|
if ( iLen > 0 )
|
|
{
|
|
iResult = GetTimeFormat (
|
|
LOCALE_USER_DEFAULT, // locale for which date is to be formatted
|
|
0, // flags specifying function options
|
|
&sysTime, // date to be formatted
|
|
0, // date format string
|
|
time.GetBufferSetLength (iLen), // buffer for storing formatted string
|
|
iLen); // size of buffer
|
|
ASSERT (iResult);
|
|
time.ReleaseBuffer ();
|
|
if ( iResult )
|
|
{
|
|
pszDateTime = date + L" " + time;
|
|
}
|
|
else
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
else
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32 (GetLastError ());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32 (GetLastError ());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32 (GetLastError ());
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
void DisplaySystemError (HWND hParent, DWORD dwErr)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetStaticModuleState ());
|
|
LPVOID lpMsgBuf;
|
|
|
|
// security review 2/26/2002 BryanWal ok - message is from system
|
|
::FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
|
NULL,
|
|
dwErr,
|
|
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
|
(LPWSTR) &lpMsgBuf, 0, NULL);
|
|
|
|
// Display the string.
|
|
CString caption;
|
|
VERIFY (caption.LoadString (IDS_CERTIFICATE_MANAGER));
|
|
CThemeContextActivator activator;
|
|
::MessageBox (hParent, (LPWSTR) lpMsgBuf, (LPCWSTR) caption, MB_OK);
|
|
// Free the buffer.
|
|
LocalFree (lpMsgBuf);
|
|
}
|
|
|
|
|
|
CString GetSystemMessage (DWORD dwErr)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetStaticModuleState ());
|
|
CString message;
|
|
|
|
LPVOID lpMsgBuf;
|
|
|
|
// security review 2/26/2002 BryanWal ok - message is from system
|
|
::FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
|
NULL,
|
|
dwErr,
|
|
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
|
(LPWSTR) &lpMsgBuf, 0, NULL );
|
|
message = (LPWSTR) lpMsgBuf;
|
|
|
|
// Free the buffer.
|
|
LocalFree (lpMsgBuf);
|
|
|
|
return message;
|
|
}
|
|
|
|
|
|
bool MyGetOIDInfo (CString & string, LPCSTR pszObjId)
|
|
{
|
|
ASSERT (pszObjId);
|
|
PCCRYPT_OID_INFO pOIDInfo; // This points to a constant data structure and must not be freed.
|
|
bool bResult = true;
|
|
|
|
pOIDInfo = ::CryptFindOIDInfo (CRYPT_OID_INFO_OID_KEY, (void *) pszObjId, 0);
|
|
|
|
if ( pOIDInfo )
|
|
{
|
|
string = pOIDInfo->pwszName;
|
|
string.TrimLeft ();
|
|
string.TrimRight ();
|
|
}
|
|
else
|
|
{
|
|
// security review 2/26/2002 BryanWal ok
|
|
// NOTICE: API returns required char count including null terminator if
|
|
// last arg is 0
|
|
int nLen = ::MultiByteToWideChar (CP_ACP, 0, pszObjId, -1, NULL, 0);
|
|
ASSERT (nLen);
|
|
if ( nLen )
|
|
{
|
|
// security review 2/26/2002 BryanWal ok
|
|
nLen = ::MultiByteToWideChar (CP_ACP, 0, pszObjId, -1,
|
|
string.GetBufferSetLength (nLen), nLen);
|
|
ASSERT (nLen);
|
|
string.ReleaseBuffer ();
|
|
}
|
|
bResult = (nLen > 0) ? true : false;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
|
|
bool IsWindowsNT()
|
|
{
|
|
OSVERSIONINFO versionInfo;
|
|
|
|
// security review 2/26/2002 BryanWal ok
|
|
::ZeroMemory (&versionInfo, sizeof (versionInfo));
|
|
versionInfo.dwOSVersionInfoSize = sizeof (versionInfo);
|
|
BOOL bResult = ::GetVersionEx (&versionInfo);
|
|
ASSERT (bResult);
|
|
if ( bResult )
|
|
{
|
|
if ( VER_PLATFORM_WIN32_NT == versionInfo.dwPlatformId )
|
|
bResult = TRUE;
|
|
}
|
|
|
|
return bResult ? true : false;
|
|
}
|
|
|
|
bool GetNameStringByType (
|
|
PCCERT_CONTEXT pCertContext,
|
|
DWORD dwFlag,
|
|
DWORD dwType,
|
|
CString& szNameString)
|
|
{
|
|
bool bResult = false;
|
|
DWORD dwTypePara = CERT_SIMPLE_NAME_STR | CERT_NAME_STR_REVERSE_FLAG;
|
|
DWORD cchNameString = 0;
|
|
DWORD dwResult = ::CertGetNameString (pCertContext,
|
|
dwType,
|
|
dwFlag,
|
|
&dwTypePara,
|
|
NULL,
|
|
cchNameString);
|
|
if ( dwResult > 1 )
|
|
{
|
|
cchNameString = dwResult;
|
|
LPWSTR pszNameString = new WCHAR[cchNameString];
|
|
if ( pszNameString )
|
|
{
|
|
// security review 2/26/2002 BryanWal ok
|
|
::ZeroMemory (pszNameString, cchNameString*sizeof (WCHAR));
|
|
dwResult = ::CertGetNameString (pCertContext,
|
|
dwType,
|
|
dwFlag,
|
|
&dwTypePara,
|
|
pszNameString,
|
|
cchNameString);
|
|
ASSERT (dwResult > 1);
|
|
if ( dwResult > 1 )
|
|
{
|
|
szNameString = pszNameString;
|
|
bResult = true;
|
|
}
|
|
delete [] pszNameString;
|
|
}
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
CString GetNameString (PCCERT_CONTEXT pCertContext, DWORD dwFlag)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
CString szNameString;
|
|
DWORD dwTypes[] = {CERT_NAME_SIMPLE_DISPLAY_TYPE,
|
|
CERT_NAME_EMAIL_TYPE,
|
|
CERT_NAME_UPN_TYPE,
|
|
CERT_NAME_DNS_TYPE,
|
|
CERT_NAME_URL_TYPE,
|
|
(DWORD) -1};
|
|
int nIndex = 0;
|
|
while ( -1 != dwTypes[nIndex])
|
|
{
|
|
if ( GetNameStringByType (
|
|
pCertContext,
|
|
dwFlag,
|
|
dwTypes[nIndex],
|
|
szNameString) )
|
|
{
|
|
break;
|
|
}
|
|
nIndex++;
|
|
}
|
|
|
|
if ( szNameString.IsEmpty () )
|
|
szNameString.FormatMessage (IDS_NOT_AVAILABLE);
|
|
|
|
return szNameString;
|
|
}
|
|
|
|
|
|
bool CertHasEFSKeyUsage(PCCERT_CONTEXT pCertContext)
|
|
{
|
|
bool bFound = false;
|
|
BOOL bResult = FALSE;
|
|
DWORD cbUsage = 0;
|
|
|
|
|
|
|
|
bResult = ::CertGetEnhancedKeyUsage (pCertContext,
|
|
0, // get extension and property
|
|
NULL, &cbUsage);
|
|
if ( bResult )
|
|
{
|
|
PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE) new BYTE[cbUsage];
|
|
if ( pUsage )
|
|
{
|
|
bResult = ::CertGetEnhancedKeyUsage (pCertContext,
|
|
0, // get extension and property
|
|
pUsage, &cbUsage);
|
|
if ( bResult )
|
|
{
|
|
for (DWORD dwIndex = 0; dwIndex < pUsage->cUsageIdentifier; dwIndex++)
|
|
{
|
|
// security review 2/26/2002 BryanWal ok
|
|
if ( !_stricmp (szOID_EFS_RECOVERY,
|
|
pUsage->rgpszUsageIdentifier[dwIndex]) )
|
|
{
|
|
bFound = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT (GetLastError () == CRYPT_E_NOT_FOUND);
|
|
}
|
|
|
|
delete [] pUsage;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT (GetLastError () == CRYPT_E_NOT_FOUND);
|
|
}
|
|
return bFound;
|
|
}
|
|
|
|
|
|
////// This stuff was stolen from windows\gina\snapins\gpedit (eric flo's stuff) //////
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// RegDelnodeRecurse()
|
|
//
|
|
// Purpose: Deletes a registry key and all it's subkeys / values.
|
|
// Called by RegDelnode
|
|
//
|
|
// Parameters: hKeyRoot - Root key
|
|
// pwszSubKey - SubKey to delete
|
|
//
|
|
// Return: ERROR_SUCCESS if successful
|
|
// something else if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 10/3/95 ericflo Created
|
|
// 5/13/98 BryanWal Modified to return LRESULT
|
|
//
|
|
//*************************************************************
|
|
|
|
LRESULT RegDelnodeRecurse (HKEY hKeyRoot, CString szSubKey)
|
|
{
|
|
ASSERT (hKeyRoot && !szSubKey.IsEmpty ());
|
|
if ( !hKeyRoot || szSubKey.IsEmpty () )
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
//
|
|
// First, see if we can delete the key without having
|
|
// to recurse.
|
|
//
|
|
|
|
|
|
LONG lResult = ::RegDeleteKey(hKeyRoot, szSubKey);
|
|
if (lResult == ERROR_SUCCESS)
|
|
{
|
|
return lResult;
|
|
}
|
|
|
|
|
|
HKEY hKey = 0;
|
|
lResult = ::RegOpenKeyEx (hKeyRoot, szSubKey, 0, KEY_READ, &hKey);
|
|
if (lResult == ERROR_SUCCESS)
|
|
{
|
|
// ensure szSubKey ends with a slash
|
|
if ( L'\\' != szSubKey.GetAt (szSubKey.GetLength () - 1) )
|
|
{
|
|
szSubKey += L"\\";
|
|
}
|
|
|
|
//
|
|
// Enumerate the keys
|
|
//
|
|
|
|
DWORD dwSize = MAX_PATH;
|
|
FILETIME ftWrite;
|
|
WCHAR szName[MAX_PATH];
|
|
lResult = ::RegEnumKeyEx(hKey, 0,
|
|
szName,
|
|
&dwSize, // size in TCHARS of szName, including terminating NULL (on input)
|
|
NULL,
|
|
NULL, NULL, &ftWrite);
|
|
if (lResult == ERROR_SUCCESS)
|
|
{
|
|
do {
|
|
if ( ERROR_SUCCESS != RegDelnodeRecurse (hKeyRoot, szSubKey + szName) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Enumerate again
|
|
//
|
|
|
|
dwSize = MAX_PATH;
|
|
|
|
lResult = ::RegEnumKeyEx(hKey, 0,
|
|
szName,
|
|
&dwSize, // size in TCHARS of szName, including terminating NULL (on input)
|
|
NULL,
|
|
NULL, NULL, &ftWrite);
|
|
|
|
|
|
} while (lResult == ERROR_SUCCESS);
|
|
}
|
|
|
|
|
|
::RegCloseKey (hKey);
|
|
}
|
|
|
|
// remove slash from szSubKey
|
|
szSubKey.Delete (szSubKey.GetLength () - 1, 1);
|
|
|
|
//
|
|
// Try again to delete the key
|
|
//
|
|
|
|
lResult = ::RegDeleteKey(hKeyRoot, szSubKey);
|
|
if (lResult == ERROR_SUCCESS)
|
|
{
|
|
return lResult;
|
|
}
|
|
|
|
return lResult;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// RegDelnode()
|
|
//
|
|
// Purpose: Deletes a registry key and all it's subkeys / values
|
|
//
|
|
// Parameters: hKeyRoot - Root key
|
|
// pwszSubKey - SubKey to delete
|
|
//
|
|
// Return: ERROR_SUCCESS if successful
|
|
// something else if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 10/3/95 ericflo Created
|
|
// 5/13/98 BryanWal Modified to return LRESULT
|
|
//
|
|
//*************************************************************
|
|
|
|
LRESULT RegDelnode (HKEY hKeyRoot, CString szSubKey)
|
|
{
|
|
ASSERT (hKeyRoot && !szSubKey.IsEmpty ());
|
|
if ( !hKeyRoot || szSubKey.IsEmpty () )
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
return RegDelnodeRecurse (hKeyRoot, szSubKey);
|
|
}
|
|
|
|
|
|
HRESULT DisplayCertificateCountByStore(LPCONSOLE pConsole, CCertStore* pCertStore, bool bIsGPE)
|
|
{
|
|
if ( !pConsole || !pCertStore )
|
|
return E_POINTER;
|
|
|
|
_TRACE (1, L"Entering DisplayCertificateCountByStore- %s \n",
|
|
(LPCWSTR) pCertStore->GetStoreName ());
|
|
AFX_MANAGE_STATE (AfxGetStaticModuleState ( ));
|
|
IConsole2* pConsole2 = 0;
|
|
HRESULT hr = pConsole->QueryInterface (IID_PPV_ARG (IConsole2, &pConsole2));
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
CString statusText;
|
|
int nCertCount = 0;
|
|
|
|
switch (pCertStore->GetStoreType ())
|
|
{
|
|
case ACRS_STORE:
|
|
nCertCount = pCertStore->GetCTLCount ();
|
|
break;
|
|
|
|
case TRUST_STORE:
|
|
if ( bIsGPE )
|
|
{
|
|
nCertCount = pCertStore->GetCTLCount ();
|
|
}
|
|
else
|
|
nCertCount = pCertStore->GetCertCount ();
|
|
break;
|
|
|
|
default:
|
|
nCertCount = pCertStore->GetCertCount ();
|
|
break;
|
|
}
|
|
|
|
|
|
switch (nCertCount)
|
|
{
|
|
case 0:
|
|
{
|
|
UINT formatID = 0;
|
|
switch (pCertStore->GetStoreType ())
|
|
{
|
|
case ACRS_STORE:
|
|
formatID = IDS_STATUS_NO_AUTOENROLLMENT_OBJECTS;
|
|
break;
|
|
|
|
case TRUST_STORE:
|
|
if ( bIsGPE )
|
|
{
|
|
formatID = IDS_STATUS_NO_CTLS;
|
|
}
|
|
else
|
|
formatID = IDS_STATUS_NO_CERTS;
|
|
break;
|
|
|
|
default:
|
|
formatID = IDS_STATUS_NO_CERTS;
|
|
break;
|
|
}
|
|
statusText.FormatMessage (formatID, pCertStore->GetLocalizedName ());
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
{
|
|
UINT formatID = 0;
|
|
switch (pCertStore->GetStoreType ())
|
|
{
|
|
case ACRS_STORE:
|
|
formatID = IDS_STATUS_ONE_AUTOENROLLMENT_OBJECT;
|
|
break;
|
|
|
|
case TRUST_STORE:
|
|
if ( bIsGPE )
|
|
{
|
|
formatID = IDS_STATUS_ONE_CTL;
|
|
}
|
|
else
|
|
formatID = IDS_STATUS_ONE_CERT;
|
|
break;
|
|
|
|
default:
|
|
formatID = IDS_STATUS_ONE_CERT;
|
|
break;
|
|
}
|
|
statusText.FormatMessage (formatID, pCertStore->GetLocalizedName ());
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
UINT formatID = 0;
|
|
switch (pCertStore->GetStoreType ())
|
|
{
|
|
case ACRS_STORE:
|
|
formatID = IDS_STATUS_X_AUTOENROLLMENT_OBJECTS;
|
|
break;
|
|
|
|
case TRUST_STORE:
|
|
if ( bIsGPE )
|
|
{
|
|
formatID = IDS_STATUS_X_CTLS;
|
|
}
|
|
else
|
|
formatID = IDS_STATUS_X_CERTS;
|
|
break;
|
|
|
|
default:
|
|
formatID = IDS_STATUS_X_CERTS;
|
|
break;
|
|
}
|
|
|
|
statusText.FormatMessage (formatID,
|
|
(LPCWSTR) pCertStore->GetLocalizedName (), nCertCount);
|
|
}
|
|
break;
|
|
}
|
|
|
|
hr = pConsole2->SetStatusText ((LPWSTR)(LPCWSTR) statusText);
|
|
|
|
pConsole2->Release ();
|
|
}
|
|
|
|
_TRACE (-1, L"Leaving DisplayCertificateCountByStore- %s \n",
|
|
(LPCWSTR) pCertStore->GetStoreName ());
|
|
return hr;
|
|
}
|
|
|
|
|
|
CString GetF1HelpFilename()
|
|
{
|
|
static CString helpFileName;
|
|
|
|
if ( helpFileName.IsEmpty () )
|
|
{
|
|
UINT result = ::GetSystemWindowsDirectory (
|
|
helpFileName.GetBufferSetLength (MAX_PATH+1), MAX_PATH);
|
|
ASSERT(result != 0 && result <= MAX_PATH);
|
|
helpFileName.ReleaseBuffer ();
|
|
if ( result != 0 && result <= MAX_PATH )
|
|
helpFileName += CM_CONTEXT_HELP;
|
|
}
|
|
|
|
return helpFileName;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: LocaleStrCmp
|
|
//
|
|
// Synopsis: Do a case insensitive string compare that is safe for any
|
|
// locale.
|
|
//
|
|
// Arguments: [ptsz1] - strings to compare
|
|
// [ptsz2]
|
|
//
|
|
// Returns: -1, 0, or 1 just like lstrcmpi
|
|
//
|
|
// History: 10-28-96 DavidMun Created
|
|
//
|
|
// Notes: This is slower than lstrcmpi, but will work when sorting
|
|
// strings even in Japanese.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
int LocaleStrCmp(LPCWSTR ptsz1, LPCWSTR ptsz2)
|
|
{
|
|
ASSERT (ptsz1 && ptsz2);
|
|
if ( !ptsz1 || !ptsz2 )
|
|
return 0;
|
|
|
|
int iRet = 0;
|
|
|
|
iRet = CompareString(LOCALE_USER_DEFAULT,
|
|
NORM_IGNORECASE |
|
|
NORM_IGNOREKANATYPE |
|
|
NORM_IGNOREWIDTH,
|
|
ptsz1,
|
|
-1,
|
|
ptsz2,
|
|
-1);
|
|
|
|
if (iRet)
|
|
{
|
|
iRet -= 2; // convert to lstrcmpi-style return -1, 0, or 1
|
|
|
|
if ( 0 == iRet )
|
|
{
|
|
UNICODE_STRING unistr1;
|
|
|
|
// security review 2/26/2002 BryanWal ok
|
|
::RtlInitUnicodeString (&unistr1, ptsz1);
|
|
|
|
UNICODE_STRING unistr2;
|
|
// security review 2/26/2002 BryanWal ok
|
|
::RtlInitUnicodeString (&unistr2, ptsz2);
|
|
|
|
iRet = ::RtlCompareUnicodeString(
|
|
&unistr1,
|
|
&unistr2,
|
|
FALSE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_TRACE (0, L"CompareString (%s, %s) failed: 0x%x\n", ptsz1, ptsz2, GetLastError ());
|
|
}
|
|
return iRet;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
HPROPSHEETPAGE MyCreatePropertySheetPage(AFX_OLDPROPSHEETPAGE* psp)
|
|
{
|
|
ASSERT (psp);
|
|
if ( !psp )
|
|
return 0;
|
|
|
|
PROPSHEETPAGE_V3 sp_v3 = {0};
|
|
// security review 2/26/2002 BryanWal ok
|
|
::CopyMemory (&sp_v3, psp, psp->dwSize);
|
|
sp_v3.dwSize = sizeof(sp_v3);
|
|
|
|
return (::CreatePropertySheetPage (&sp_v3));
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#include <winldap.h>
|
|
#include <ntldap.h>
|
|
#include <dsrole.h>
|
|
#include <dsgetdc.h>
|
|
#include <accctrl.h>
|
|
|
|
#include <lmaccess.h>
|
|
#include <lmapibuf.h>
|
|
#include <lmerr.h>
|
|
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
// Defines
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
#define DS_RETEST_SECONDS 3
|
|
#define CVT_BASE (1000 * 1000 * 10)
|
|
#define CVT_SECONDS (1)
|
|
#define CERTTYPE_SECURITY_DESCRIPTOR_NAME L"NTSecurityDescriptor"
|
|
#define TEMPLATE_CONTAINER_NAME L"CN=Certificate Templates,CN=Public Key Services,CN=Services,"
|
|
#define SCHEMA_CONTAINER_NAME L"CN=Schema,"
|
|
|
|
HRESULT myHError(HRESULT hr)
|
|
{
|
|
|
|
if (S_OK != hr && S_FALSE != hr && !FAILED(hr))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
if ( SUCCEEDED (hr) )
|
|
{
|
|
// A call failed without properly setting an error condition!
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
void CheckDomainVersion ()
|
|
{
|
|
_TRACE (1, L"Entering CheckDomainVersion()\n");
|
|
|
|
bool bMachineIsStandAlone = false;
|
|
|
|
// Find out if we're joined to a domain.
|
|
PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pInfo = 0;
|
|
DWORD dwErr = ::DsRoleGetPrimaryDomainInformation (
|
|
0,
|
|
DsRolePrimaryDomainInfoBasic,
|
|
(PBYTE*) &pInfo);
|
|
if ( ERROR_SUCCESS == dwErr )
|
|
{
|
|
switch (pInfo->MachineRole)
|
|
{
|
|
case DsRole_RoleStandaloneWorkstation:
|
|
case DsRole_RoleStandaloneServer:
|
|
bMachineIsStandAlone = true;
|
|
break;
|
|
|
|
case DsRole_RoleMemberWorkstation:
|
|
case DsRole_RoleMemberServer:
|
|
case DsRole_RoleBackupDomainController:
|
|
case DsRole_RolePrimaryDomainController:
|
|
bMachineIsStandAlone = false;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_TRACE (0, L"DsRoleGetPrimaryDomainInformation () failed: 0x%x\n", dwErr);
|
|
}
|
|
|
|
if ( !bMachineIsStandAlone )
|
|
{
|
|
CDSBasePathsInfo dsInfo;
|
|
if ( SUCCEEDED (dsInfo.InitFromName (pInfo->DomainNameFlat)) )
|
|
{
|
|
if ( dsInfo.GetSchemaVersion () <= 0x0000000d )
|
|
{
|
|
g_bSchemaIsW2K = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( pInfo )
|
|
NetApiBufferFree (pInfo);
|
|
|
|
_TRACE (1, L"Entering CheckDomainVersion ()\n");
|
|
}
|
|
|
|
VOID DataToHex(PBYTE pSrc, CString & dest, int cb, bool bIncludeSpaces)
|
|
{
|
|
// _TRACE (1, L"Entering DataToHex\n");
|
|
ASSERT (pSrc);
|
|
if ( !pSrc )
|
|
return;
|
|
|
|
unsigned char ch = 0;
|
|
WCHAR szDest[3];
|
|
UINT uLen = 0;
|
|
|
|
dest.Empty ();
|
|
|
|
while (cb-- > 0)
|
|
{
|
|
#pragma warning (once: 4244)
|
|
ch = 0x00FF & (unsigned char) (*pSrc++);
|
|
// ISSUE - change to wsnprintf
|
|
// NTRAID Bug9 538774 Security: certmgr.dll : convert to strsafe string functions
|
|
wsprintf(szDest, _T("%02X"), ch);
|
|
dest += szDest;
|
|
uLen++;
|
|
if ( bIncludeSpaces && !(uLen % 2) && cb )
|
|
dest += _T(" ");
|
|
}
|
|
// _TRACE (-1, L"Leaving DataToHex\n");
|
|
}
|
|
|
|
|
|
BOOL GetCertificateChain (CERT_CONTEXT* pCertContext, CERT_CONTEXT_LIST& certChainList)
|
|
{
|
|
ASSERT (pCertContext);
|
|
if ( !pCertContext )
|
|
return FALSE;
|
|
|
|
// Clean up the cert context list
|
|
while (!certChainList.IsEmpty () )
|
|
{
|
|
pCertContext = certChainList.RemoveHead ();
|
|
if ( pCertContext )
|
|
::CertFreeCertificateContext (pCertContext);
|
|
}
|
|
|
|
|
|
CERT_CHAIN_PARA certChainPara;
|
|
// security review 2/26/2002 BryanWal ok
|
|
::ZeroMemory (&certChainPara, sizeof (certChainPara));
|
|
certChainPara.cbSize = sizeof (CERT_CHAIN_PARA);
|
|
certChainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
|
|
certChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = new LPSTR[1];
|
|
if ( !certChainPara.RequestedUsage.Usage.rgpszUsageIdentifier )
|
|
return FALSE; // E_OUTOFMEMORY;
|
|
certChainPara.RequestedUsage.Usage.rgpszUsageIdentifier[0] = szOID_EFS_RECOVERY;
|
|
|
|
PCCERT_CHAIN_CONTEXT pChainContext = 0;
|
|
BOOL bValidated = ::CertGetCertificateChain (
|
|
HCCE_LOCAL_MACHINE, // HCERTCHAINENGINE hChainEngine,
|
|
pCertContext,
|
|
0, // LPFILETIME pTime,
|
|
0, // HCERTSTORE hAdditionalStore,
|
|
&certChainPara,
|
|
0, // dwFlags,
|
|
0, // pvReserved,
|
|
&pChainContext);
|
|
if ( bValidated )
|
|
{
|
|
// Check to see if cert is self-signed
|
|
PCERT_SIMPLE_CHAIN pChain = pChainContext->rgpChain[pChainContext->cChain - 1];
|
|
if ( pChain )
|
|
{
|
|
PCERT_CHAIN_ELEMENT pElement = pChain->rgpElement[pChain->cElement - 1];
|
|
if ( pElement )
|
|
{
|
|
BOOL bSelfSigned = pElement->TrustStatus.dwInfoStatus & CERT_TRUST_IS_SELF_SIGNED;
|
|
|
|
DWORD dwErrorStatus = pChainContext->TrustStatus.dwErrorStatus;
|
|
|
|
bValidated = ((0 == dwErrorStatus) ||
|
|
(dwErrorStatus == CERT_TRUST_IS_UNTRUSTED_ROOT) && bSelfSigned);
|
|
if ( bValidated )
|
|
{
|
|
//
|
|
// Enumerate all certs in the chain
|
|
// Search for the cert in the global list
|
|
// If not found, then add to the end of the list
|
|
//
|
|
for (DWORD dwIndex = 0; dwIndex < pChainContext->cChain; dwIndex++)
|
|
{
|
|
DWORD i = 0;
|
|
while (i < pChainContext->rgpChain[dwIndex]->cElement)
|
|
{
|
|
PCCERT_CONTEXT pChainCertContext =
|
|
pChainContext->rgpChain[dwIndex]->rgpElement[i]->pCertContext;
|
|
certChainList.AddTail (
|
|
const_cast<CERT_CONTEXT*>
|
|
(::CertDuplicateCertificateContext (pChainCertContext)));
|
|
i++;
|
|
}
|
|
}
|
|
|
|
|
|
::CertFreeCertificateChain(pChainContext);
|
|
pChainContext = 0;
|
|
}
|
|
}
|
|
else
|
|
bValidated = FALSE;
|
|
}
|
|
else
|
|
bValidated = FALSE;
|
|
}
|
|
else
|
|
bValidated = FALSE;
|
|
|
|
if ( pChainContext )
|
|
::CertFreeCertificateChain(pChainContext);
|
|
|
|
delete [] certChainPara.RequestedUsage.Usage.rgpszUsageIdentifier;
|
|
|
|
return bValidated;
|
|
}
|