2100 lines
61 KiB
C++
2100 lines
61 KiB
C++
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1997 - 2001.
|
||
|
//
|
||
|
// 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)
|
||
|
|
||
|
#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";
|
||
|
|
||
|
//
|
||
|
// 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 ()
|
||
|
{
|
||
|
LPWSTR pszCommandLine = _wcsupr (::GetCommandLine ());
|
||
|
LPWSTR pszParam = L"/CERTMGR:FILENAME=";
|
||
|
size_t len = wcslen (pszParam);
|
||
|
|
||
|
LPWSTR pszArg = wcsstr (pszCommandLine, pszParam);
|
||
|
if ( !pszArg )
|
||
|
pszParam = L"-CERTMGR:FILENAME=";
|
||
|
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";
|
||
|
|
||
|
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;
|
||
|
::ZeroMemory (&oid, sizeof (CRYPT_OID_INFO));
|
||
|
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);
|
||
|
|
||
|
size_t len = strlen (VER_COMPANYNAME_STR);
|
||
|
len = mbstowcs (verProviderStr.GetBufferSetLength ((int) len),
|
||
|
VER_COMPANYNAME_STR, len);
|
||
|
rkCertMgrSnapin.SetString (L"Provider", verProviderStr);
|
||
|
|
||
|
len = strlen (VER_PRODUCTVERSION_STR);
|
||
|
len = mbstowcs (verVersionStr.GetBufferSetLength ((int)len),
|
||
|
VER_PRODUCTVERSION_STR, len);
|
||
|
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:
|
||
|
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
|
||
|
//
|
||
|
TCHAR achModuleFileName[MAX_PATH+20];
|
||
|
if (0 < ::GetModuleFileName(
|
||
|
AfxGetInstanceHandle(),
|
||
|
achModuleFileName,
|
||
|
sizeof(achModuleFileName)/sizeof(TCHAR) ))
|
||
|
{
|
||
|
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:
|
||
|
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:
|
||
|
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
|
||
|
//
|
||
|
TCHAR achModuleFileName[MAX_PATH+20];
|
||
|
if (0 < ::GetModuleFileName(
|
||
|
AfxGetInstanceHandle(),
|
||
|
achModuleFileName,
|
||
|
sizeof(achModuleFileName)/sizeof(TCHAR) ))
|
||
|
{
|
||
|
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:
|
||
|
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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TCHAR achModuleFileName[MAX_PATH+20];
|
||
|
if (0 < ::GetModuleFileName(
|
||
|
AfxGetInstanceHandle(),
|
||
|
achModuleFileName,
|
||
|
sizeof(achModuleFileName)/sizeof(TCHAR) ))
|
||
|
{
|
||
|
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;
|
||
|
|
||
|
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;
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int nLen = ::MultiByteToWideChar (CP_ACP, 0, pszObjId, -1, NULL, 0);
|
||
|
ASSERT (nLen);
|
||
|
if ( nLen )
|
||
|
{
|
||
|
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;
|
||
|
|
||
|
::ZeroMemory (&versionInfo, sizeof (OSVERSIONINFO));
|
||
|
versionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
|
||
|
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 )
|
||
|
{
|
||
|
::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++)
|
||
|
{
|
||
|
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) //////
|
||
|
|
||
|
//*************************************************************
|
||
|
//
|
||
|
// CheckSlash()
|
||
|
//
|
||
|
// Purpose: Checks for an ending slash and adds one if
|
||
|
// it is missing.
|
||
|
//
|
||
|
// Parameters: lpDir - directory
|
||
|
//
|
||
|
// Return: Pointer to the end of the string
|
||
|
//
|
||
|
// Comments:
|
||
|
//
|
||
|
// History: Date Author Comment
|
||
|
// 6/19/95 ericflo Created
|
||
|
//
|
||
|
//*************************************************************
|
||
|
LPWSTR CheckSlash (LPWSTR lpDir)
|
||
|
{
|
||
|
LPWSTR lpEnd = lpDir + lstrlen(lpDir);
|
||
|
|
||
|
if (*(lpEnd - 1) != TEXT('\\'))
|
||
|
{
|
||
|
*lpEnd = TEXT('\\');
|
||
|
lpEnd++;
|
||
|
*lpEnd = TEXT('\0');
|
||
|
}
|
||
|
|
||
|
return lpEnd;
|
||
|
}
|
||
|
|
||
|
//*************************************************************
|
||
|
//
|
||
|
// RegDelnodeRecurse()
|
||
|
//
|
||
|
// Purpose: Deletes a registry key and all it's subkeys / values.
|
||
|
// Called by RegDelnode
|
||
|
//
|
||
|
// Parameters: hKeyRoot - Root key
|
||
|
// lpSubKey - 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, LPWSTR lpSubKey)
|
||
|
{
|
||
|
//
|
||
|
// First, see if we can delete the key without having
|
||
|
// to recurse.
|
||
|
//
|
||
|
|
||
|
|
||
|
LONG lResult = RegDeleteKey(hKeyRoot, lpSubKey);
|
||
|
if (lResult == ERROR_SUCCESS)
|
||
|
{
|
||
|
return lResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
HKEY hKey = 0;
|
||
|
lResult = RegOpenKeyEx (hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);
|
||
|
if (lResult != ERROR_SUCCESS)
|
||
|
{
|
||
|
return lResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
LPWSTR lpEnd = CheckSlash(lpSubKey);
|
||
|
|
||
|
//
|
||
|
// Enumerate the keys
|
||
|
//
|
||
|
|
||
|
DWORD dwSize = MAX_PATH;
|
||
|
FILETIME ftWrite;
|
||
|
WCHAR szName[MAX_PATH];
|
||
|
lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
|
||
|
NULL, NULL, &ftWrite);
|
||
|
if (lResult == ERROR_SUCCESS)
|
||
|
{
|
||
|
do {
|
||
|
|
||
|
lstrcpy (lpEnd, szName);
|
||
|
|
||
|
if ( ERROR_SUCCESS != RegDelnodeRecurse(hKeyRoot, lpSubKey) )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Enumerate again
|
||
|
//
|
||
|
|
||
|
dwSize = MAX_PATH;
|
||
|
|
||
|
lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
|
||
|
NULL, NULL, &ftWrite);
|
||
|
|
||
|
|
||
|
} while (lResult == ERROR_SUCCESS);
|
||
|
}
|
||
|
|
||
|
lpEnd--;
|
||
|
*lpEnd = TEXT('\0');
|
||
|
|
||
|
|
||
|
RegCloseKey (hKey);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Try again to delete the key
|
||
|
//
|
||
|
|
||
|
lResult = RegDeleteKey(hKeyRoot, lpSubKey);
|
||
|
if (lResult == ERROR_SUCCESS)
|
||
|
{
|
||
|
return lResult;
|
||
|
}
|
||
|
|
||
|
return lResult;
|
||
|
}
|
||
|
|
||
|
//*************************************************************
|
||
|
//
|
||
|
// RegDelnode()
|
||
|
//
|
||
|
// Purpose: Deletes a registry key and all it's subkeys / values
|
||
|
//
|
||
|
// Parameters: hKeyRoot - Root key
|
||
|
// lpSubKey - 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, LPWSTR lpSubKey)
|
||
|
{
|
||
|
const size_t BUF_LEN = 2 * MAX_PATH;
|
||
|
WCHAR szDelKey[BUF_LEN];
|
||
|
|
||
|
::ZeroMemory (szDelKey, BUF_LEN * sizeof (WCHAR));
|
||
|
wcsncpy (szDelKey, lpSubKey, BUF_LEN - 1);
|
||
|
|
||
|
return RegDelnodeRecurse(hKeyRoot, szDelKey);
|
||
|
}
|
||
|
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
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;
|
||
|
unistr1.Length = (USHORT) (wcslen(ptsz1) * sizeof(WCHAR));
|
||
|
unistr1.MaximumLength = unistr1.Length;
|
||
|
unistr1.Buffer = (LPWSTR)ptsz1;
|
||
|
UNICODE_STRING unistr2;
|
||
|
unistr2.Length = (USHORT) (wcslen(ptsz2) * sizeof(WCHAR));
|
||
|
unistr2.MaximumLength = unistr2.Length;
|
||
|
unistr2.Buffer = (LPWSTR)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)
|
||
|
{
|
||
|
PROPSHEETPAGE_V3 sp_v3 = {0};
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
myDupString(
|
||
|
IN WCHAR const *pwszIn,
|
||
|
IN WCHAR **ppwszOut)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
size_t cb = (wcslen(pwszIn) + 1) * sizeof(WCHAR);
|
||
|
*ppwszOut = (WCHAR *) LocalAlloc(LMEM_FIXED, cb);
|
||
|
if (NULL == *ppwszOut)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
goto error;
|
||
|
}
|
||
|
CopyMemory(*ppwszOut, pwszIn, cb);
|
||
|
hr = S_OK;
|
||
|
|
||
|
error:
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
CAGetAuthoritativeDomainDn(
|
||
|
IN LDAP* LdapHandle,
|
||
|
OUT CString* pszDomainDn,
|
||
|
OUT CString* pszConfigDn
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine simply queries the operational attributes for the
|
||
|
domaindn and configdn.
|
||
|
|
||
|
The strings returned by this routine must be freed by the caller
|
||
|
using RtlFreeHeap() using the process heap.
|
||
|
|
||
|
Parameters:
|
||
|
|
||
|
LdapHandle : a valid handle to an ldap session
|
||
|
|
||
|
pszDomainDn : a pointer to a string to be allocated in this routine
|
||
|
|
||
|
pszConfigDn : a pointer to a string to be allocated in this routine
|
||
|
|
||
|
Return Values:
|
||
|
|
||
|
An error from the win32 error space.
|
||
|
|
||
|
ERROR_SUCCESS and
|
||
|
|
||
|
Other operation errors.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
|
||
|
DWORD WinError = ERROR_SUCCESS;
|
||
|
ULONG LdapError;
|
||
|
|
||
|
LDAPMessage *SearchResult = NULL;
|
||
|
LDAPMessage *Entry = NULL;
|
||
|
WCHAR *Attr = NULL;
|
||
|
BerElement *BerElement;
|
||
|
WCHAR **Values = NULL;
|
||
|
|
||
|
WCHAR *AttrArray[3];
|
||
|
|
||
|
WCHAR *DefaultNamingContext = L"defaultNamingContext";
|
||
|
WCHAR *ConfigNamingContext = L"configurationNamingContext";
|
||
|
WCHAR *ObjectClassFilter = L"objectClass=*";
|
||
|
|
||
|
//
|
||
|
// These must be present
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Set the out parameters to null
|
||
|
//
|
||
|
|
||
|
if ( pszDomainDn )
|
||
|
*pszDomainDn = L"";
|
||
|
if ( pszConfigDn )
|
||
|
*pszConfigDn = L"";
|
||
|
|
||
|
//
|
||
|
// Query for the ldap server oerational attributes to obtain the default
|
||
|
// naming context.
|
||
|
//
|
||
|
AttrArray[0] = DefaultNamingContext;
|
||
|
AttrArray[1] = ConfigNamingContext; // this is the sentinel
|
||
|
AttrArray[2] = NULL; // this is the sentinel
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
LdapError = ldap_search_sW(LdapHandle,
|
||
|
NULL,
|
||
|
LDAP_SCOPE_BASE,
|
||
|
ObjectClassFilter,
|
||
|
AttrArray,
|
||
|
FALSE,
|
||
|
&SearchResult);
|
||
|
|
||
|
WinError = LdapMapErrorToWin32(LdapError);
|
||
|
|
||
|
if (ERROR_SUCCESS == WinError) {
|
||
|
|
||
|
Entry = ldap_first_entry(LdapHandle, SearchResult);
|
||
|
|
||
|
if (Entry)
|
||
|
{
|
||
|
|
||
|
Attr = ldap_first_attributeW(LdapHandle, Entry, &BerElement);
|
||
|
|
||
|
while (Attr)
|
||
|
{
|
||
|
|
||
|
if (!_wcsicmp(Attr, DefaultNamingContext))
|
||
|
{
|
||
|
if ( pszDomainDn )
|
||
|
{
|
||
|
Values = ldap_get_values(LdapHandle, Entry, Attr);
|
||
|
|
||
|
if (Values && Values[0])
|
||
|
{
|
||
|
*pszDomainDn = Values[0];
|
||
|
}
|
||
|
ldap_value_free(Values);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else if (!_wcsicmp(Attr, ConfigNamingContext))
|
||
|
{
|
||
|
if ( pszConfigDn )
|
||
|
{
|
||
|
Values = ldap_get_values(LdapHandle, Entry, Attr);
|
||
|
|
||
|
if (Values && Values[0])
|
||
|
{
|
||
|
*pszConfigDn = Values[0];
|
||
|
}
|
||
|
ldap_value_free(Values);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Attr = ldap_next_attribute(LdapHandle, Entry, BerElement);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( pszDomainDn && pszDomainDn->IsEmpty () )
|
||
|
{
|
||
|
//
|
||
|
// We could get the default domain - bail out
|
||
|
//
|
||
|
WinError = ERROR_CANT_ACCESS_DOMAIN_INFO;
|
||
|
|
||
|
}
|
||
|
else if ( pszConfigDn && pszConfigDn->IsEmpty () )
|
||
|
{
|
||
|
//
|
||
|
// We could get the default domain - bail out
|
||
|
//
|
||
|
WinError = ERROR_CANT_ACCESS_DOMAIN_INFO;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
__except(WinError = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
// make sure we free this
|
||
|
if (SearchResult)
|
||
|
ldap_msgfree( SearchResult );
|
||
|
|
||
|
return WinError;
|
||
|
}
|
||
|
|
||
|
HRESULT myDoesDSExist(IN BOOL fRetry)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
static BOOL s_fKnowDSExists = FALSE;
|
||
|
static HRESULT s_hrDSExists = HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN);
|
||
|
static FILETIME s_ftNextTest = {0,0};
|
||
|
|
||
|
if (s_fKnowDSExists && (s_hrDSExists != S_OK) && fRetry)
|
||
|
// s_fKnowDSExists = FALSE; // force a retry
|
||
|
{
|
||
|
FILETIME ftCurrent;
|
||
|
GetSystemTimeAsFileTime(&ftCurrent);
|
||
|
|
||
|
// if Compare is < 0 (next < current), force retest
|
||
|
if (0 > CompareFileTime(&s_ftNextTest, &ftCurrent))
|
||
|
s_fKnowDSExists = FALSE;
|
||
|
}
|
||
|
|
||
|
if (!s_fKnowDSExists)
|
||
|
{
|
||
|
GetSystemTimeAsFileTime(&s_ftNextTest);
|
||
|
|
||
|
// set NEXT in 100ns increments
|
||
|
|
||
|
((LARGE_INTEGER *) &s_ftNextTest)->QuadPart +=
|
||
|
(__int64) (CVT_BASE * CVT_SECONDS * 60) * DS_RETEST_SECONDS;
|
||
|
|
||
|
// NetApi32 is delay loaded, so wrap to catch problems when it's not available
|
||
|
__try
|
||
|
{
|
||
|
DOMAIN_CONTROLLER_INFO *pDCI;
|
||
|
DSROLE_PRIMARY_DOMAIN_INFO_BASIC *pDsRole;
|
||
|
|
||
|
// ensure we're not standalone
|
||
|
pDsRole = NULL;
|
||
|
hr = DsRoleGetPrimaryDomainInformation( // Delayload wrapped
|
||
|
NULL,
|
||
|
DsRolePrimaryDomainInfoBasic,
|
||
|
(BYTE **) &pDsRole);
|
||
|
|
||
|
if (S_OK == hr &&
|
||
|
(pDsRole->MachineRole == DsRole_RoleStandaloneServer ||
|
||
|
pDsRole->MachineRole == DsRole_RoleStandaloneWorkstation))
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN);
|
||
|
}
|
||
|
|
||
|
if (NULL != pDsRole)
|
||
|
{
|
||
|
DsRoleFreeMemory(pDsRole); // Delayload wrapped
|
||
|
}
|
||
|
if (S_OK == hr)
|
||
|
{
|
||
|
// not standalone; return info on our DS
|
||
|
|
||
|
pDCI = NULL;
|
||
|
hr = DsGetDcName( // Delayload wrapped
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
DS_DIRECTORY_SERVICE_PREFERRED,
|
||
|
&pDCI);
|
||
|
|
||
|
if (S_OK == hr && 0 == (pDCI->Flags & DS_DS_FLAG))
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(ERROR_CANT_ACCESS_DOMAIN_INFO);
|
||
|
}
|
||
|
if (NULL != pDCI)
|
||
|
{
|
||
|
NetApiBufferFree(pDCI); // Delayload wrapped
|
||
|
}
|
||
|
}
|
||
|
s_fKnowDSExists = TRUE;
|
||
|
}
|
||
|
__except(hr = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
// else just allow users without netapi flounder with timeouts
|
||
|
// if ds not available...
|
||
|
|
||
|
s_hrDSExists = myHError(hr);
|
||
|
}
|
||
|
return(s_hrDSExists);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
HRESULT
|
||
|
myRobustLdapBindEx(
|
||
|
OUT LDAP ** ppldap,
|
||
|
OPTIONAL OUT LPWSTR* ppszForestDNSName,
|
||
|
IN BOOL fGC)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
BOOL fForceRediscovery = FALSE;
|
||
|
DWORD dwGetDCFlags = DS_RETURN_DNS_NAME;
|
||
|
PDOMAIN_CONTROLLER_INFO pDomainInfo = NULL;
|
||
|
LDAP *pld = NULL;
|
||
|
WCHAR const *pwszDomainControllerName = NULL;
|
||
|
ULONG ldaperr = 0;
|
||
|
|
||
|
if (fGC)
|
||
|
{
|
||
|
dwGetDCFlags |= DS_GC_SERVER_REQUIRED;
|
||
|
}
|
||
|
|
||
|
do {
|
||
|
if (fForceRediscovery)
|
||
|
{
|
||
|
dwGetDCFlags |= DS_FORCE_REDISCOVERY;
|
||
|
}
|
||
|
ldaperr = LDAP_SERVER_DOWN;
|
||
|
|
||
|
// netapi32!DsGetDcName is delay loaded, so wrap
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
// Get the GC location
|
||
|
hr = DsGetDcName(
|
||
|
NULL, // Delayload wrapped
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
dwGetDCFlags,
|
||
|
&pDomainInfo);
|
||
|
}
|
||
|
__except(hr = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
}
|
||
|
if (S_OK != hr)
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(hr);
|
||
|
if (fForceRediscovery)
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
fForceRediscovery = TRUE;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (NULL == pDomainInfo ||
|
||
|
(fGC && 0 == (DS_GC_FLAG & pDomainInfo->Flags)) ||
|
||
|
0 == (DS_DNS_CONTROLLER_FLAG & pDomainInfo->Flags) ||
|
||
|
NULL == pDomainInfo->DomainControllerName)
|
||
|
{
|
||
|
if (!fForceRediscovery)
|
||
|
{
|
||
|
fForceRediscovery = TRUE;
|
||
|
continue;
|
||
|
}
|
||
|
hr = HRESULT_FROM_WIN32(ERROR_CANT_ACCESS_DOMAIN_INFO);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
pwszDomainControllerName = pDomainInfo->DomainControllerName;
|
||
|
|
||
|
// skip past forward slashes (why are they there?)
|
||
|
|
||
|
while (L'\\' == *pwszDomainControllerName)
|
||
|
{
|
||
|
pwszDomainControllerName++;
|
||
|
}
|
||
|
|
||
|
// bind to ds
|
||
|
|
||
|
pld = ldap_init(
|
||
|
const_cast<WCHAR *>(pwszDomainControllerName),
|
||
|
fGC? LDAP_GC_PORT : LDAP_PORT);
|
||
|
if (NULL == pld)
|
||
|
{
|
||
|
ldaperr = LdapGetLastError();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// do this because we're explicitly setting DC name
|
||
|
|
||
|
ldaperr = ldap_set_option(pld, LDAP_OPT_AREC_EXCLUSIVE, LDAP_OPT_ON);
|
||
|
|
||
|
ldaperr = ldap_bind_s(pld, NULL, NULL, LDAP_AUTH_NEGOTIATE);
|
||
|
}
|
||
|
hr = myHError(LdapMapErrorToWin32(ldaperr));
|
||
|
|
||
|
if (fForceRediscovery)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
fForceRediscovery = TRUE;
|
||
|
|
||
|
} while (LDAP_SERVER_DOWN == ldaperr);
|
||
|
|
||
|
// everything's cool, party down
|
||
|
|
||
|
if (S_OK == hr)
|
||
|
{
|
||
|
if (NULL != ppszForestDNSName)
|
||
|
{
|
||
|
hr = myDupString(
|
||
|
pDomainInfo->DomainControllerName,
|
||
|
ppszForestDNSName);
|
||
|
|
||
|
if(S_OK != hr)
|
||
|
goto error;
|
||
|
}
|
||
|
*ppldap = pld;
|
||
|
pld = NULL;
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
if (NULL != pld)
|
||
|
{
|
||
|
ldap_unbind(pld);
|
||
|
}
|
||
|
|
||
|
// we know netapi32 was already loaded safely (that's where we got
|
||
|
// pDomainInfo), so no need to wrap
|
||
|
|
||
|
if (NULL != pDomainInfo)
|
||
|
{
|
||
|
NetApiBufferFree(pDomainInfo); // Delayload wrapped
|
||
|
}
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
myRobustLdapBind(
|
||
|
OUT LDAP ** ppldap,
|
||
|
IN BOOL fGC)
|
||
|
{
|
||
|
return(myRobustLdapBindEx(ppldap, NULL, fGC));
|
||
|
}
|
||
|
|
||
|
|
||
|
void CheckDomainVersion ()
|
||
|
{
|
||
|
_TRACE (1, L"Entering CheckDomainVersion()\n");
|
||
|
AFX_MANAGE_STATE (AfxGetStaticModuleState ());
|
||
|
HRESULT hr=S_OK;
|
||
|
DWORD dwErr=0;
|
||
|
ULONG ldaperr=0;
|
||
|
struct l_timeval timeout;
|
||
|
LPWSTR awszAttr[2];
|
||
|
|
||
|
LDAP *pld = NULL;
|
||
|
CString szConfig;
|
||
|
CString szDN;
|
||
|
LDAPMessage *SearchResult = NULL;
|
||
|
|
||
|
|
||
|
//*************************************************************
|
||
|
//
|
||
|
// check the schema version
|
||
|
//
|
||
|
_TRACE (0, L"Checking the schema version...\n");
|
||
|
//retrieve the ldap handle and the config string
|
||
|
if(S_OK != myDoesDSExist(TRUE))
|
||
|
{
|
||
|
_TRACE (0, L"No DS exists.\n");
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
if(S_OK != (hr = myRobustLdapBind(&pld, FALSE)))
|
||
|
{
|
||
|
_TRACE (0, L"Error: Failed to bind to the DS.\n");
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
dwErr = CAGetAuthoritativeDomainDn(pld, NULL, &szConfig);
|
||
|
if(ERROR_SUCCESS != dwErr)
|
||
|
{
|
||
|
_TRACE (0, L"Error: Failed to get the domain name.\n");
|
||
|
hr = HRESULT_FROM_WIN32(dwErr);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
szDN = SCHEMA_CONTAINER_NAME;
|
||
|
szDN += szConfig;
|
||
|
|
||
|
timeout.tv_sec = 300;
|
||
|
timeout.tv_usec = 0;
|
||
|
|
||
|
awszAttr[0]=L"cn";
|
||
|
awszAttr[1]=NULL;
|
||
|
|
||
|
ldaperr = ldap_search_stW(
|
||
|
pld,
|
||
|
const_cast <PWCHAR>((PCWSTR) szDN),
|
||
|
LDAP_SCOPE_ONELEVEL,
|
||
|
L"(cn=ms-PKI-Enrollment-Flag)",
|
||
|
awszAttr,
|
||
|
0,
|
||
|
&timeout,
|
||
|
&SearchResult);
|
||
|
|
||
|
if ( LDAP_SUCCESS != ldaperr )
|
||
|
{
|
||
|
_TRACE (0, L"We have W2K Schema. Exit\n");
|
||
|
g_bSchemaIsW2K = true;
|
||
|
hr = S_OK;
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
|
||
|
error:
|
||
|
|
||
|
|
||
|
if(SearchResult)
|
||
|
ldap_msgfree(SearchResult);
|
||
|
|
||
|
if (pld)
|
||
|
ldap_unbind(pld);
|
||
|
_TRACE (1, L"Entering CheckDomainVersion ()\n");
|
||
|
}
|
||
|
|
||
|
|