|
|
// This is a part of the Microsoft Management Console.
// Copyright (C) Microsoft Corporation, 1995 - 1999
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Management Console and related
// electronic documentation provided with the interfaces.
#include "stdafx.h"
#include "setupids.h"
#include "resource.h"
#include "genpage.h"
#include "chooser.h"
#include "misc.h"
#include "csdisp.h" // picker
#include <esent.h> // database error
#include <aclui.h>
#include <winldap.h>
#include "csldap.h"
#include <atlimpl.cpp>
#define __dwFILE__ __dwFILE_CERTMMC_COMPDATA_CPP__
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
struct FOLDER_DATA { FOLDER_TYPES type; UINT iNameRscID; }; static FOLDER_DATA SvrFuncFolderData[] = { {SERVERFUNC_CRL_PUBLICATION, IDS_CERTS_REVOKED}, {SERVERFUNC_ISSUED_CERTIFICATES, IDS_CERTS_ISSUED}, {SERVERFUNC_PENDING_CERTIFICATES, IDS_CERTS_PENDING}, {SERVERFUNC_FAILED_CERTIFICATES, IDS_CERTS_FAILED}, {SERVERFUNC_ALIEN_CERTIFICATES, IDS_CERTS_IMPORTED}, {SERVERFUNC_ISSUED_CRLS, IDS_CRL_TITLE}, }; // keep this enum in synch with SvrFuncFolderData[]
enum ENUM_FOLDERS { ENUM_FOLDER_CRL=0, ENUM_FOLDER_ISSUED, ENUM_FOLDER_PENDING, ENUM_FOLDER_FAILED, ENUM_FOLDER_ALIEN, ENUM_FOLDER_CRLS, };
// Array of view items to be inserted into the context menu.
// keep this enum in synch with viewItems[]
enum ENUM_TASK_STARTSTOP_ITEMS { ENUM_TASK_START=0, ENUM_TASK_STOP, ENUM_TASK_SEPERATOR, };
MY_CONTEXTMENUITEM taskStartStop[] = { { { L"", L"", IDC_STARTSERVER, CCM_INSERTIONPOINTID_PRIMARY_TASK, 0, 0 }, IDS_TASKMENU_STARTSERVICE, IDS_TASKMENU_STATUSBAR_STARTSERVICE, CA_ACCESS_ADMIN, },
{ { L"", L"", IDC_STOPSERVER, CCM_INSERTIONPOINTID_PRIMARY_TASK, 0, 0 }, IDS_TASKMENU_STOPSERVICE, IDS_TASKMENU_STATUSBAR_STOPSERVICE, CA_ACCESS_ADMIN, },
{ { NULL, NULL, 0, 0, 0 }, IDS_EMPTY, IDS_EMPTY, }, };
// Array of view items to be inserted into the context menu.
// WARNING: keep this enum in synch with taskItems[]
enum ENUM_TASK_ITEMS { ENUM_TASK_CRLPUB=0, ENUM_TASK_ATTREXTS_CRL, ENUM_TASK_ATTREXTS_ISS, ENUM_TASK_ATTREXTS_PEND, ENUM_TASK_ATTREXTS_FAIL, ENUM_TASK_DUMP_ASN_CRLPUB, ENUM_TASK_DUMP_ASN_ISS, ENUM_TASK_DUMP_ASN_PEND, ENUM_TASK_DUMP_ASN_FAIL, ENUM_TASK_DUMP_ASN_ALIEN, ENUM_TASK_DUMP_ASN_CRL, ENUM_TASK_SEPERATOR1, ENUM_TASK_SEPERATOR4, ENUM_TASK_SUBMIT_REQUEST, ENUM_TASK_REVOKECERT, ENUM_TASK_RESUBMITREQ, ENUM_TASK_DENYREQ, ENUM_TASK_RESUBMITREQ2, ENUM_TASK_SEPERATOR2, ENUM_TASK_BACKUP, ENUM_TASK_RESTORE, ENUM_TASK_SEPERATOR3, ENUM_TASK_INSTALL, ENUM_TASK_REQUEST, ENUM_TASK_ROLLOVER, };
TASKITEM taskItems[] = {
{ SERVERFUNC_CRL_PUBLICATION, 0, { { L"", L"", IDC_PUBLISHCRL, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_PUBLISHCRL, IDS_TASKMENU_STATUSBAR_PUBLISHCRL, CA_ACCESS_ADMIN, } },
/////////////////////
// BEGIN ATTR/EXT
{ SERVERFUNC_CRL_PUBLICATION, // where
TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", IDC_VIEW_ATTR_EXT, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_VIEWATTREXT, IDS_TASKMENU_STATUSBAR_VIEWATTREXT, CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
} }, { SERVERFUNC_ISSUED_CERTIFICATES, // where
TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", IDC_VIEW_ATTR_EXT, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_VIEWATTREXT, IDS_TASKMENU_STATUSBAR_VIEWATTREXT, CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
} }, { SERVERFUNC_PENDING_CERTIFICATES, // where
TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", IDC_VIEW_ATTR_EXT, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_VIEWATTREXT, IDS_TASKMENU_STATUSBAR_VIEWATTREXT, CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
} }, { SERVERFUNC_FAILED_CERTIFICATES, // where
TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", IDC_VIEW_ATTR_EXT, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_VIEWATTREXT, IDS_TASKMENU_STATUSBAR_VIEWATTREXT, CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
} },
// END ATTR/EXT
/////////////////////
/////////////////////
// BEGIN ENUM_TASK_DUMP_ASN*
{ SERVERFUNC_CRL_PUBLICATION, // where
TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", IDC_DUMP_ASN, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_DUMPASN, IDS_TASKMENU_STATUSBAR_DUMPASN, CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
} }, { SERVERFUNC_ISSUED_CERTIFICATES, // where
TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", IDC_DUMP_ASN, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_DUMPASN, IDS_TASKMENU_STATUSBAR_DUMPASN, CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
} }, { SERVERFUNC_PENDING_CERTIFICATES, // where
TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", IDC_DUMP_ASN, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_DUMPASN, IDS_TASKMENU_STATUSBAR_DUMPASN, CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
} }, { SERVERFUNC_FAILED_CERTIFICATES, // where
TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", IDC_DUMP_ASN, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_DUMPASN, IDS_TASKMENU_STATUSBAR_DUMPASN, CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
} }, { SERVERFUNC_ALIEN_CERTIFICATES, // where
TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", IDC_DUMP_ASN, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_DUMPASN, IDS_TASKMENU_STATUSBAR_DUMPASN, CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
} }, { SERVERFUNC_ISSUED_CRLS, // where
TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", IDC_DUMP_ASN, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_DUMPASN, IDS_TASKMENU_STATUSBAR_DUMPASN, CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
} }, // END ENUM_TASK_DUMP_ASN*
/////////////////////
// seperator
{ SERVERFUNC_ALL_FOLDERS, TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", 0, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, CCM_SPECIAL_SEPARATOR }, IDS_EMPTY, IDS_EMPTY, } },
// seperator
{ SERVER_INSTANCE, 0, // dwFlags
{ { L"", L"", 0, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, CCM_SPECIAL_SEPARATOR }, IDS_EMPTY, IDS_EMPTY, } },
{ SERVER_INSTANCE, 0, { { L"", L"", IDC_SUBMITREQUEST, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_SUBMITREQUEST, IDS_TASKMENU_STATUSBAR_SUBMITREQUEST, CA_ACCESS_ENROLL, } },
{ SERVERFUNC_ISSUED_CERTIFICATES, TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", IDC_REVOKECERT, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_REVOKECERT, IDS_TASKMENU_STATUSBAR_REVOKECERT, CA_ACCESS_OFFICER, } },
{ SERVERFUNC_PENDING_CERTIFICATES, TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", IDC_RESUBMITREQUEST, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_RESUBMIT, IDS_TASKMENU_STATUSBAR_RESUBMIT, CA_ACCESS_OFFICER, } },
{ SERVERFUNC_PENDING_CERTIFICATES, TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", IDC_DENYREQUEST, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_DENYREQUEST, IDS_TASKMENU_STATUSBAR_DENYREQUEST, CA_ACCESS_OFFICER, } },
{ SERVERFUNC_FAILED_CERTIFICATES, TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", IDC_RESUBMITREQUEST, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_RESUBMIT, IDS_TASKMENU_STATUSBAR_RESUBMIT, CA_ACCESS_OFFICER, } },
// seperator
{ SERVERFUNC_ALL_FOLDERS, 0, // dwFlags
{ { L"", L"", 0, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, CCM_SPECIAL_SEPARATOR }, IDS_EMPTY, IDS_EMPTY, } },
{ SERVER_INSTANCE, TASKITEM_FLAG_LOCALONLY, { { L"", L"", IDC_BACKUP_CA, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_BACKUP, IDS_TASKMENU_STATUSBAR_BACKUP, CA_ACCESS_OPERATOR, } },
{ SERVER_INSTANCE, TASKITEM_FLAG_LOCALONLY, { { L"", L"", IDC_RESTORE_CA, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_RESTORE, IDS_TASKMENU_STATUSBAR_RESTORE, CA_ACCESS_OPERATOR, } },
// seperator
{ SERVER_INSTANCE, 0, { { L"", L"", 0, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, CCM_SPECIAL_SEPARATOR }, IDS_EMPTY, IDS_EMPTY, } },
{ SERVER_INSTANCE, 0, { { L"", L"", IDC_INSTALL_CA, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_INSTALL_CA, IDS_TASKMENU_STATUSBAR_INSTALL_CA, CA_ACCESS_MASKROLES|CA_ACCESS_READ, // not based on roles, enable for all roles
} },
{ SERVER_INSTANCE, 0, { { L"", L"", IDC_REQUEST_CA, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0 }, IDS_TASKMENU_REQUEST_CA, IDS_TASKMENU_STATUSBAR_REQUEST_CA, CA_ACCESS_MASKROLES|CA_ACCESS_READ, // not based on roles, enable for all roles
} },
{ SERVER_INSTANCE, TASKITEM_FLAG_LOCALONLY, { { L"", L"", IDC_ROLLOVER_CA, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_GRAYED, 0 }, IDS_TASKMENU_ROLLOVER, IDS_TASKMENU_STATUSBAR_ROLLOVER, CA_ACCESS_MASKROLES|CA_ACCESS_READ, // not based on roles, enable for all roles
} },
{ NONE, FALSE, { { NULL, NULL, 0, 0, 0 }, IDS_EMPTY, IDS_EMPTY, } } };
// Array of view items to be inserted into the context menu.
// keep this enum in synch with topItems[]
enum ENUM_TOP_ITEMS { ENUM_TOP_REVOKEDOPEN=0, ENUM_TOP_ISSUEDOPEN, ENUM_TOP_ALIENOPEN, ENUM_RETARGET_SNAPIN, };
TASKITEM topItems[] = {
{ SERVERFUNC_CRL_PUBLICATION, TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", IDC_VIEW_CERT_PROPERTIES, CCM_INSERTIONPOINTID_PRIMARY_TOP, MF_ENABLED, CCM_SPECIAL_DEFAULT_ITEM }, IDS_TOPMENU_OPEN, IDS_TOPMENU_STATUSBAR_OPEN, CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
} },
{ SERVERFUNC_ISSUED_CERTIFICATES, TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", IDC_VIEW_CERT_PROPERTIES, CCM_INSERTIONPOINTID_PRIMARY_TOP, MF_ENABLED, CCM_SPECIAL_DEFAULT_ITEM }, IDS_TOPMENU_OPEN, IDS_TOPMENU_STATUSBAR_OPEN, CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
} },
{ SERVERFUNC_ALIEN_CERTIFICATES, TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", IDC_VIEW_CERT_PROPERTIES, CCM_INSERTIONPOINTID_PRIMARY_TOP, MF_ENABLED, CCM_SPECIAL_DEFAULT_ITEM }, IDS_TOPMENU_OPEN, IDS_TOPMENU_STATUSBAR_OPEN, CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
} },
{ SERVERFUNC_ISSUED_CRLS, TASKITEM_FLAG_RESULTITEM, // dwFlags
{ { L"", L"", IDC_VIEW_CERT_PROPERTIES, CCM_INSERTIONPOINTID_PRIMARY_TOP, MF_ENABLED, CCM_SPECIAL_DEFAULT_ITEM }, IDS_TOPMENU_OPEN, IDS_TOPMENU_STATUSBAR_OPEN, CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
} },
{ MACHINE_INSTANCE, 0, { { L"", L"", IDC_RETARGET_SNAPIN, CCM_INSERTIONPOINTID_PRIMARY_TOP, MF_ENABLED, 0 }, IDS_RETARGET_SNAPIN, IDS_STATUSBAR_RETARGET_SNAPIN, CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
} },
{ NONE, 0, { { NULL, NULL, 0, 0, 0 }, IDS_EMPTY, IDS_EMPTY, } } };
BOOL g_fCertViewOnly = TRUE;
///////////////////////////////////////////////////////////////////////////////
// IComponentData implementation
DEBUG_DECLARE_INSTANCE_COUNTER(CComponentDataImpl);
CComponentDataImpl::CComponentDataImpl() : m_bIsDirty(TRUE), m_pScope(NULL), m_pConsole(NULL) #if DBG
, m_bInitializedCD(false), m_bDestroyedCD(false) #endif
{ DEBUG_INCREMENT_INSTANCE_COUNTER(CComponentDataImpl);
m_dwFlagsPersist = 0; m_pStaticRoot = NULL; m_pCurSelFolder = NULL;
m_fScopeAlreadyEnumerated = FALSE; m_fSchemaWasResolved = FALSE; // resolve schema once per load
m_fCertView = TRUE;
// checked in ::Initialize, ::CreatePropertyPages
m_pCertMachine = new CertSvrMachine;
m_cLastKnownSchema = 0; m_rgcstrLastKnownSchema = NULL; m_rgltypeLastKnownSchema = NULL; m_rgfindexedLastKnownSchema = NULL;
m_dwNextViewIndex = 0; }
CComponentDataImpl::~CComponentDataImpl() { DEBUG_DECREMENT_INSTANCE_COUNTER(CComponentDataImpl);
ASSERT(m_pScope == NULL); ASSERT(!m_bInitializedCD || m_bDestroyedCD);
// Delete enumerated scope items
// note: we don't own pCA memory, m_pCertMachine does
POSITION pos = m_scopeItemList.GetHeadPosition(); while (pos) delete m_scopeItemList.GetNext(pos); m_scopeItemList.RemoveAll();
m_pCurSelFolder = NULL; m_fScopeAlreadyEnumerated = FALSE;
if (m_pCertMachine) m_pCertMachine->Release();
m_cLastKnownSchema = 0; if (m_rgcstrLastKnownSchema) delete [] m_rgcstrLastKnownSchema; if (m_rgltypeLastKnownSchema) delete [] m_rgltypeLastKnownSchema; if (m_rgfindexedLastKnownSchema) delete [] m_rgfindexedLastKnownSchema; }
STDMETHODIMP_(ULONG) CComponentDataImpl::AddRef() { return InterlockedIncrement((LONG *) &_cRefs); }
STDMETHODIMP_(ULONG) CComponentDataImpl::Release() { ULONG cRefsTemp;
cRefsTemp = InterlockedDecrement((LONG *)&_cRefs);
if (0 == cRefsTemp) { delete this; }
return cRefsTemp; }
int CComponentDataImpl::FindColIdx(IN LPCWSTR szHeading) { for (DWORD dw=0; dw<m_cLastKnownSchema; dw++) { if (m_rgcstrLastKnownSchema[dw].IsEqual(szHeading)) return dw; } return -1; }
HRESULT CComponentDataImpl::GetDBSchemaEntry( IN int iIndex, OUT OPTIONAL LPCWSTR* pszHeading, OUT OPTIONAL LONG* plType, OUT OPTIONAL BOOL* pfIndexed) { if (m_cLastKnownSchema<= (DWORD)iIndex) return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX);
if (pszHeading) *pszHeading = m_rgcstrLastKnownSchema[iIndex]; if (plType) *plType = m_rgltypeLastKnownSchema[iIndex]; if (pfIndexed) *pfIndexed = m_rgfindexedLastKnownSchema[iIndex];
return S_OK; }
HRESULT CComponentDataImpl::SetDBSchema( IN CString* rgcstr, LONG* rgtype, BOOL* rgfIndexed, DWORD cEntries) { if (m_rgcstrLastKnownSchema) delete [] m_rgcstrLastKnownSchema; m_rgcstrLastKnownSchema = rgcstr;
if (m_rgltypeLastKnownSchema) delete [] m_rgltypeLastKnownSchema; m_rgltypeLastKnownSchema = rgtype;
if (m_rgfindexedLastKnownSchema) delete [] m_rgfindexedLastKnownSchema; m_rgfindexedLastKnownSchema = rgfIndexed;
m_cLastKnownSchema = cEntries;
return S_OK; }
STDMETHODIMP CComponentDataImpl::Initialize(LPUNKNOWN pUnknown) { // NOTA BENE: Init is called when a snap-in is being
// created and has items to enumerate in the scope pane ... NOT BEFORE
// Example: Add/Remove snapin, Add...
// -> CComponentDataImpl will get called for CreatePropertyPages() before ::Initialize is called
#if DBG
m_bInitializedCD = true; #endif
ASSERT(pUnknown != NULL); HRESULT hr;
LPIMAGELIST lpScopeImage = NULL; CBitmap bmpResultStrip16x16, bmpResultStrip32x32;
g_pResources = new CLocalizedResources; if (NULL == g_pResources) { hr = E_OUTOFMEMORY; _JumpError(hr, Ret, "Alloc Resources"); }
// Load resources
if (!g_pResources->Load()) { hr = GetLastError(); _JumpError(hr, Ret, "Load Resources"); }
// create a per-instance id (failure not fatal)
ResetPersistedColumnInformation();
// MMC should only call ::Initialize once!
// m_pCertMachine created in constructor, but verified here
ASSERT(m_pCertMachine != NULL); _JumpIfOutOfMemory(hr, Ret, m_pCertMachine); // MMC should only call ::Initialize once!
ASSERT(m_pScope == NULL); hr = pUnknown->QueryInterface(IID_IConsoleNameSpace2, reinterpret_cast<void**>(&m_pScope)); _JumpIfError(hr, Ret, "QueryInterface IID_IConsoleNameSpace2");
// add the images for the scope tree
hr = pUnknown->QueryInterface(IID_IConsole2, reinterpret_cast<void**>(&m_pConsole)); ASSERT(hr == S_OK); _JumpIfError(hr, Ret, "QueryInterface IID_IConsole2");
hr = m_pConsole->QueryScopeImageList(&lpScopeImage); ASSERT(hr == S_OK); _JumpIfError(hr, Ret, "QueryScopeImageList");
if ( (NULL == bmpResultStrip16x16.LoadBitmap(IDB_16x16)) || (NULL == bmpResultStrip32x32.LoadBitmap(IDB_32x32)) ) { hr = S_FALSE; _JumpError(hr, Ret, "LoadBitmap"); }
// Load the bitmaps from the dll
lpScopeImage->ImageListSetStrip(reinterpret_cast<LONG_PTR *>(static_cast<HBITMAP>(bmpResultStrip16x16)), reinterpret_cast<LONG_PTR *>(static_cast<HBITMAP>(bmpResultStrip32x32)), 0, RGB(255, 0, 255)); _JumpIfError(hr, Ret, "ImageListSetStrip");
Ret: if (lpScopeImage) lpScopeImage->Release(); return hr; }
STDMETHODIMP CComponentDataImpl::Destroy() { // release all references to the console here
ASSERT(m_bInitializedCD); #if DBG
m_bDestroyedCD = true; #endif
SAFE_RELEASE(m_pScope); SAFE_RELEASE(m_pConsole);
return S_OK; }
STDMETHODIMP CComponentDataImpl::CreateComponent(LPCOMPONENT* ppComponent) { HRESULT hr = S_OK; ASSERT(ppComponent != NULL);
CComObject<CSnapin>* pObject; CComObject<CSnapin>::CreateInstance(&pObject); ASSERT(pObject != NULL); _JumpIfOutOfMemory(hr, Ret, pObject);
// Store IComponentData
pObject->SetIComponentData(this); pObject->SetViewID(m_dwNextViewIndex++);
hr = pObject->QueryInterface(IID_IComponent, reinterpret_cast<void**>(ppComponent)); Ret: return hr; }
STDMETHODIMP CComponentDataImpl::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param) { ASSERT(m_pScope != NULL); HRESULT hr = S_OK; INTERNAL* pInternal = NULL; MMC_COOKIE cookie = NULL;
// handle events with (NULL == lpDataObject)
switch(event) { case MMCN_PROPERTY_CHANGE: { // Notification from property page "notify change"
//
// arg == fIsScopeItem
// lParam == page param value
// return value unused
if (param == CERTMMC_PROPERTY_CHANGE_REFRESHVIEWS) { m_pConsole->UpdateAllViews( lpDataObject, 0, 0); }
goto Ret; }
default: // all others
break; }
pInternal = ExtractInternalFormat(lpDataObject); if (pInternal == NULL) { return S_OK; }
cookie = pInternal->m_cookie; FREE_DATA(pInternal);
switch(event) { case MMCN_PASTE: DBGPRINT((DBG_SS_CERTMMC, "CComponentDataImpl::MMCN_PASTE")); break; case MMCN_DELETE: hr = OnDelete(cookie); break;
case MMCN_REMOVE_CHILDREN: hr = OnRemoveChildren(arg); break;
case MMCN_RENAME: hr = OnRename(cookie, arg, param); break;
case MMCN_EXPAND: hr = OnExpand(lpDataObject, arg, param); break;
case MMCN_PRELOAD: { if (NULL == cookie) { // base node
// this call gave us time to load our dynamic base nodename (Certification Authority on %ws)
DisplayProperRootNodeName((HSCOPEITEM)arg); } }
default: break; }
Ret: return hr; }
HRESULT CComponentDataImpl::DisplayProperRootNodeName(HSCOPEITEM hRoot) { // hRoot not optional
if (hRoot == NULL) return E_POINTER;
// if static root not yet set, save it (CASE: load from file)
if (m_pStaticRoot == NULL) m_pStaticRoot = hRoot;
// let us have time to load our dynamic base nodename (Certification Authority on %ws)
SCOPEDATAITEM item; item.mask = SDI_STR; item.ID = hRoot;
CString cstrMachineName; CString cstrDisplayStr, cstrFormatStr, cstrMachine;
cstrFormatStr.LoadString(IDS_NODENAME_FORMAT); if (m_pCertMachine->m_strMachineName.IsEmpty()) cstrMachine.LoadString(IDS_LOCALMACHINE); else cstrMachine = m_pCertMachine->m_strMachineName; if (!cstrFormatStr.IsEmpty()) { cstrMachineName.Format(cstrFormatStr, cstrMachine); item.displayname = (LPWSTR)(LPCWSTR)cstrMachineName; } else { // protect against null formatstring
item.displayname = (LPWSTR)(LPCWSTR)cstrMachine; } m_pScope->SetItem (&item); return S_OK; }
STDMETHODIMP CComponentDataImpl::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject) { #ifdef _DEBUG
if (cookie == 0) { ASSERT(type != CCT_RESULT); } else { ASSERT(type == CCT_SCOPE); DWORD dwItemType = *reinterpret_cast<DWORD*>(cookie); ASSERT((dwItemType == SCOPE_LEVEL_ITEM) || (dwItemType == CA_LEVEL_ITEM)); } #endif
return _QueryDataObject(cookie, type, MAXDWORD, this, ppDataObject); }
///////////////////////////////////////////////////////////////////////////////
//// ISnapinHelp interface
STDMETHODIMP CComponentDataImpl::GetHelpTopic(LPOLESTR* lpCompiledHelpFile) { if (lpCompiledHelpFile == NULL) return E_POINTER;
UINT cbWindows = 0; WCHAR szWindows[MAX_PATH]; szWindows[0] = L'\0';
cbWindows = GetSystemWindowsDirectory(szWindows, MAX_PATH); if (cbWindows == 0) return S_FALSE; cbWindows++; // include null term
cbWindows *= sizeof(WCHAR); // make this bytes, not chars
*lpCompiledHelpFile = (LPOLESTR) CoTaskMemAlloc(sizeof(HTMLHELP_COLLECTION_FILENAME) + cbWindows); if (*lpCompiledHelpFile == NULL) return E_OUTOFMEMORY; myRegisterMemFree(*lpCompiledHelpFile, CSM_COTASKALLOC); // this is freed by mmc, not our tracking
USES_CONVERSION; wcscpy(*lpCompiledHelpFile, T2OLE(szWindows)); wcscat(*lpCompiledHelpFile, T2OLE(HTMLHELP_COLLECTION_FILENAME));
return S_OK; }
// tells of other topics my chm links to
STDMETHODIMP CComponentDataImpl::GetLinkedTopics(LPOLESTR* lpCompiledHelpFiles) { if (lpCompiledHelpFiles == NULL) return E_POINTER;
UINT cbWindows = 0; WCHAR szWindows[MAX_PATH]; szWindows[0] = L'\0';
cbWindows = GetSystemWindowsDirectory(szWindows, MAX_PATH); if (cbWindows == 0) return S_FALSE; cbWindows++; // include null term
cbWindows *= sizeof(WCHAR); // make this bytes, not chars
*lpCompiledHelpFiles = (LPOLESTR) CoTaskMemAlloc(sizeof(HTMLHELP_COLLECTIONLINK_FILENAME) + cbWindows); if (*lpCompiledHelpFiles == NULL) return E_OUTOFMEMORY; myRegisterMemFree(*lpCompiledHelpFiles, CSM_COTASKALLOC); // this is freed by mmc, not our tracking
USES_CONVERSION; wcscpy(*lpCompiledHelpFiles, T2OLE(szWindows)); wcscat(*lpCompiledHelpFiles, T2OLE(HTMLHELP_COLLECTIONLINK_FILENAME));
return S_OK; }
///////////////////////////////////////////////////////////////////////////////
//// IPersistStream interface members
STDMETHODIMP CComponentDataImpl::GetClassID(CLSID *pClassID) { ASSERT(pClassID != NULL);
// Copy the CLSID for this snapin
*pClassID = CLSID_Snapin;
return S_OK; }
STDMETHODIMP CComponentDataImpl::IsDirty() { // Always save / Always dirty.
return ThisIsDirty() ? S_OK : S_FALSE; }
STDMETHODIMP CComponentDataImpl::Load(IStream *pStm) { ASSERT(pStm); ASSERT(m_bInitializedCD);
// Read the string
BOOL fMachineOverrideFound = FALSE; DWORD dwVer;
CertSvrCA* pDummyCA = NULL; HRESULT hr;
// read version
hr = ReadOfSize(pStm, &dwVer, sizeof(DWORD)); _JumpIfError(hr, Ret, "Read dwVer");
// flags is version-dependent
if (VER_CCOMPDATA_SAVE_STREAM_3 == dwVer) { // version 3 includes file flags
hr = ReadOfSize(pStm, &m_dwFlagsPersist, sizeof(DWORD)); _JumpIfError(hr, Ret, "Read m_dwFlagsPersist"); } else if (VER_CCOMPDATA_SAVE_STREAM_2 != dwVer) { // not version 2 or 3
return STG_E_OLDFORMAT; }
// load machine data
hr = m_pCertMachine->Load(pStm); _JumpIfError(hr, Ret, "Load m_pCertMachine")
if (m_dwFlagsPersist & CCOMPDATAIMPL_FLAGS_ALLOW_MACHINE_OVERRIDE) { // override m_pCertMachine->m_strMachineName (not to be persisted)
LPWSTR lpCommandLine = GetCommandLine(); // no need to free
DBGPRINT((DBG_SS_CERTMMC, "CComponentData::Load: Command line switch override enabled. Searching command line(%ws)\n", lpCommandLine));
LPWSTR pszMachineStart, pszMachineEnd;
// search for "/machine" in cmd line
_wcsupr(lpCommandLine); // convert to uppercase
pszMachineStart = wcsstr(lpCommandLine, WSZ_MACHINE_OVERRIDE_SWITCH);
do // not a loop
{ if (NULL == pszMachineStart) // user did not override
break;
pszMachineStart += WSZARRAYSIZE(WSZ_MACHINE_OVERRIDE_SWITCH); // skip past "/machine:"
//
// Found the hint switch
//
pszMachineEnd = wcschr(pszMachineStart, L' '); // look for first space char, call this end
if (NULL == pszMachineEnd) pszMachineEnd = &pszMachineStart[wcslen(pszMachineStart)]; // space not found in this string;
m_pCertMachine->m_strMachineName = pszMachineStart; m_pCertMachine->m_strMachineName.SetAt(SAFE_SUBTRACT_POINTERS(pszMachineEnd, pszMachineStart), L'\0');
DBGPRINT((DBG_SS_CERTMMC, "CComponentData::Load: Found machinename (%ws)\n", m_pCertMachine->m_strMachineName)); fMachineOverrideFound = TRUE;
} while (0); }
if (!fMachineOverrideFound) { // Get CA count
DWORD dwNumCAs; hr = ReadOfSize(pStm, &dwNumCAs, sizeof(DWORD)); _JumpIfError(hr, Ret, "Load dwNumCAs");
// for each CA, get folder data
for (DWORD dwCA=0; dwCA< dwNumCAs; dwCA++) { CString cstrThisCA;
hr = CStringLoad(cstrThisCA, pStm); _JumpIfError(hr, Ret, "CStringLoad"); // create a dummy CA with the correct common name; we'll fix this later (see Synch CA)
pDummyCA = new CertSvrCA(m_pCertMachine); _JumpIfOutOfMemory(hr, Ret, pDummyCA);
pDummyCA->m_strCommonName = cstrThisCA;
if (VER_CCOMPDATA_SAVE_STREAM_2 < dwVer) { m_fSchemaWasResolved = FALSE; // resolve schema once per CComponentData load
// LOAD last known schema
hr = ReadOfSize(pStm, &m_cLastKnownSchema, sizeof(DWORD)); _JumpIfError(hr, Ret, "Load m_cLastKnownSchema"); // alloc
if (m_cLastKnownSchema != 0) { m_rgcstrLastKnownSchema = new CString[m_cLastKnownSchema]; _JumpIfOutOfMemory(hr, Ret, m_rgcstrLastKnownSchema); for (unsigned int i=0; i<m_cLastKnownSchema; i++) { hr = CStringLoad(m_rgcstrLastKnownSchema[i], pStm); _JumpIfError(hr, Ret, "Load m_rgcstrLastKnownSchema");
} } }
// find out how many folders are in the stream under this CA
DWORD dwNumFolders=0; hr = ReadOfSize(pStm, &dwNumFolders, sizeof(DWORD)); _JumpIfError(hr, Ret, "Load dwNumFolders");
// load each of these
for(DWORD dwCount=0; dwCount<dwNumFolders; dwCount++) { CFolder* pFolder = new CFolder(); _JumpIfOutOfMemory(hr, Ret, pFolder); // point at previously constructed dummy ca; we'll fix this later
pFolder->m_pCertCA = pDummyCA;
hr = pFolder->Load(pStm); _JumpIfError(hr, Ret, "Load CFolder");
m_scopeItemList.AddTail(pFolder); } pDummyCA = NULL; // owned by at least one folder
} } // version-dependent info
if (VER_CCOMPDATA_SAVE_STREAM_2 < dwVer) { // per-instance guid for identifying columns uniquely
hr = ReadOfSize(pStm, &m_guidInstance, sizeof(GUID)); _JumpIfError(hr, Ret, "ReadOfSize instance guid");
hr = ReadOfSize(pStm, &m_dwNextViewIndex, sizeof(DWORD)); _JumpIfError(hr, Ret, "ReadOfSize view index"); } Ret: if (pDummyCA) delete pDummyCA;
ClearDirty();
return hr; }
STDMETHODIMP CComponentDataImpl::Save(IStream *pStm, BOOL fClearDirty) { ASSERT(pStm); ASSERT(m_bInitializedCD);
HRESULT hr; DWORD dwVer; DWORD dwCA; DWORD dwNumCAs;
#if DBG_CERTSRV
bool fSaveConsole = false;
LPWSTR lpCommandLine = GetCommandLine(); // no need to free
_wcsupr(lpCommandLine); // convert to uppercase
fSaveConsole = (NULL!=wcsstr(lpCommandLine, L"/certsrv_saveconsole")); #endif
// Write the version
dwVer = VER_CCOMPDATA_SAVE_STREAM_3; hr = WriteOfSize(pStm, &dwVer, sizeof(DWORD)); _JumpIfError(hr, Ret, "Save dwVer");
// write dwFlags (a VERSION 3 addition)
hr = WriteOfSize(pStm, &m_dwFlagsPersist, sizeof(DWORD)); _JumpIfError(hr, Ret, "pStm->Write m_dwFlagsPersist");
#if DBG_CERTSRV
if(fSaveConsole) m_pCertMachine->m_strMachineNamePersist.Empty(); #endif
hr = m_pCertMachine->Save(pStm, fClearDirty); _JumpIfError(hr, Ret, "Save m_pCertMachine");
// save CA count
dwNumCAs = m_pCertMachine->GetCaCount(); hr = WriteOfSize(pStm, &dwNumCAs, sizeof(DWORD)); _JumpIfError(hr, Ret, "pStm->Write dwNumCAs");
// for each CA, save folder info
for (dwCA=0; dwCA < dwNumCAs; dwCA++) { DWORD dwNumFolders=0; CString cstrThisCA, cstrThisCASave; cstrThisCASave = cstrThisCA = m_pCertMachine->GetCaCommonNameAtPos(dwCA);
#if DBG_CERTSRV
if(fSaveConsole) cstrThisCASave.Empty(); #endif
hr = CStringSave(cstrThisCASave, pStm, fClearDirty); _JumpIfError(hr, Ret, "CStringSave");
// SAVE last known schema
hr = WriteOfSize(pStm, &m_cLastKnownSchema, sizeof(DWORD)); _JumpIfError(hr, Ret, "pStm->Write m_cLastKnownSchema");
for (unsigned int i=0; i<m_cLastKnownSchema; i++) { hr = CStringSave(m_rgcstrLastKnownSchema[i], pStm, fClearDirty); _JumpIfError(hr, Ret, "CStringSave"); }
// walk through every folder, find how many folders to save
POSITION pos = m_scopeItemList.GetHeadPosition(); while(pos) { CFolder* pFolder = m_scopeItemList.GetNext(pos); if (pFolder->GetCA()->m_strCommonName.IsEqual(cstrThisCA)) dwNumFolders++; }
// write how many folders under this CA
hr = WriteOfSize(pStm, &dwNumFolders, sizeof(DWORD)); _JumpIfError(hr, Ret, "pStm->Write dwNumFolders");
pos = m_scopeItemList.GetHeadPosition(); while(pos) { CFolder* pFolder = m_scopeItemList.GetNext(pos); if (pFolder->GetCA()->m_strCommonName.IsEqual(cstrThisCA)) { hr = pFolder->Save(pStm, fClearDirty); _JumpIfError(hr, Ret, "Save CFolder"); } } }
// per-instance guid for identifying columns uniquely
hr = WriteOfSize(pStm, &m_guidInstance, sizeof(GUID)); _JumpIfError(hr, Ret, "WriteOfSize instance guid");
hr = WriteOfSize(pStm, &m_dwNextViewIndex, sizeof(DWORD)); _JumpIfError(hr, Ret, "WriteOfSize view index"); Ret: if (fClearDirty) ClearDirty();
return hr; }
STDMETHODIMP CComponentDataImpl::GetSizeMax(ULARGE_INTEGER *pcbSize) { ASSERT(pcbSize);
int iTotalSize=0;
// version
iTotalSize = sizeof(DWORD) + sizeof(m_dwFlagsPersist);
// machine info
int iSize; m_pCertMachine->GetSizeMax(&iSize); iTotalSize += iSize;
// CA count
iTotalSize += sizeof(DWORD);
DWORD dwNumCAs = m_pCertMachine->GetCaCount(); for (DWORD dwCA=0; dwCA < dwNumCAs; dwCA++) { CString cstrThisCA; cstrThisCA = m_pCertMachine->GetCaCommonNameAtPos(dwCA); CStringGetSizeMax(cstrThisCA, &iSize); iTotalSize += iSize;
// Number of folders under this CA
iTotalSize += sizeof(DWORD);
// walk through every folder, find how many folders to save
POSITION pos = m_scopeItemList.GetHeadPosition(); while(pos) { CFolder* pFolder = m_scopeItemList.GetNext(pos); if (pFolder->GetCA()->m_strCommonName.IsEqual(cstrThisCA)) { // folder size
pFolder->GetSizeMax(&iSize); iTotalSize += iSize; } } }
// per-instance guid for identifying columns uniquely
iTotalSize += sizeof(GUID); // next View Index to assign
iTotalSize += sizeof(DWORD);
// size of string to be saved
pcbSize->QuadPart = iTotalSize;
return S_OK; }
///////////////////////////////////////////////////////////////////////////////
//// Notify handlers for IComponentData
HRESULT CComponentDataImpl::OnDelete( MMC_COOKIE /* cookie */ ) { return S_OK; }
HRESULT CComponentDataImpl::OnRemoveChildren( LPARAM /* arg */ ) { return S_OK; }
VOID SetCertView() { LPWSTR lpCommandLine = GetCommandLine(); // no need to free
LPWSTR pwsz; DWORD dw; static BOOL s_fFirst = TRUE; #define wszCOMMANDLINEE L"/E"
if (s_fFirst) { // search for "/e" in cmd line
_wcsupr(lpCommandLine); // convert to uppercase
pwsz = wcsstr(lpCommandLine, wszCOMMANDLINEE);
do // not a loop
{ if (NULL == pwsz) // user did not override
break;
pwsz += WSZARRAYSIZE(wszCOMMANDLINEE); // skip past "/e"
if (L'\0' != *pwsz && L' ' != *pwsz) break; g_fCertViewOnly = FALSE; } while (0); if (g_fCertViewOnly && NULL != getenv("certsrv_crl")) g_fCertViewOnly = FALSE; if (g_fCertViewOnly && S_OK == myGetCertRegDWValue(NULL, NULL, NULL, L"CRL", &dw) && 0 != dw) g_fCertViewOnly = FALSE; s_fFirst = FALSE; } }
HRESULT CComponentDataImpl::OnRename(MMC_COOKIE cookie, LPARAM arg, LPARAM param) { // cookie is cookie
// arg is fRenamed (ask for permission/notify of rename)
// param (szNewName)
CFolder* pFolder = reinterpret_cast<CFolder*>(cookie); BOOL fRenamed = (BOOL)arg;
if (!fRenamed) { if (pFolder) return S_FALSE; // don't allow children to be renamed
else return S_OK; // allow root to be renamed
}
LPOLESTR pszNewName = reinterpret_cast<LPOLESTR>(param); if (pszNewName == NULL) return E_INVALIDARG;
if (pFolder) { ASSERT(pFolder != NULL); if (pFolder == NULL) return E_INVALIDARG;
pFolder->SetName(pszNewName); } return S_OK; }
HRESULT CComponentDataImpl::OnExpand(LPDATAOBJECT lpDataObject, LPARAM arg, LPARAM param) { if (arg == TRUE) { // Did Initialize get called?
ASSERT(m_pScope != NULL);
EnumerateScopePane(lpDataObject, param); }
return S_OK; }
HRESULT CComponentDataImpl::SynchDisplayedCAList(LPDATAOBJECT lpDataObject) { HRESULT hr; BOOL fFound; POSITION pos, nextpos; DWORD dwKnownCAs;
m_fScopeAlreadyEnumerated = TRUE; // don't need to refresh view automagically from enum if we get here
// should never get here otherwise
ASSERT(m_pStaticRoot); if (NULL == m_pStaticRoot) return E_POINTER;
// select root node, delete all items in UI underneath (we'll readd if necessary)
hr = m_pConsole->SelectScopeItem(m_pStaticRoot); _PrintIfError2(hr, "SelectScopeItem", hr);
hr = m_pScope->DeleteItem(m_pStaticRoot, FALSE); // remove everything from UI
_PrintIfError2(hr, "DeleteItem", hr);
// build knowledge of current CAs
// note: this may orphan some pCAs, but we'll catch it during cleanup
HWND hwndMain = NULL; hr = m_pConsole->GetMainWindow(&hwndMain); if (hr != S_OK) hwndMain = NULL; // this should work
// this hr gets returned after we're done
hr = m_pCertMachine->PrepareData(hwndMain);
// don't fail out if PrepareData fails -- we still need to
// make the snapin state reflect no known nodes!
ASSERT((hr == S_OK) || (0 == m_pCertMachine->GetCaCount()) ); // make sure m_pCertMachine zeros itself
// Tasks
// #1: Remove folders in m_scopeItemList for CAs that no longer exist in m_pCertMachine.m_rgpCAList[]
// #2: Add folders to m_scopeItemList for CAs that now exist in m_pCertMachine.m_rgpCAList[]
// Task #1
// scour m_scopeItemList for entries we already know about, delete stale folders
for (pos = m_scopeItemList.GetHeadPosition(); (NULL != pos); ) { // ASSERTION: every folder has an associated m_pCertCA
ASSERT(NULL != m_scopeItemList.GetAt(pos)->m_pCertCA);
nextpos = pos; // save next position off
fFound = FALSE;
// for each scope item, walk through m_rgpCAList looking for current
for (dwKnownCAs=0; dwKnownCAs<(DWORD)m_pCertMachine->m_CAList.GetSize(); dwKnownCAs++) { if (m_scopeItemList.GetAt(pos)->m_pCertCA->m_strCommonName.IsEqual(m_pCertMachine->GetCaCommonNameAtPos(dwKnownCAs))) { fFound = TRUE; break; } }
CFolder* pFolder = m_scopeItemList.GetAt(pos); ASSERT(pFolder); // this should never happen
if (pFolder == NULL) { hr = E_POINTER; _JumpError(hr, Ret, "GetAt"); }
if (fFound) { // always point to latest pCA:
// NOTE: this allows for load to populate us with dummy CAs!
pFolder->m_pCertCA = m_pCertMachine->GetCaAtPos(dwKnownCAs);
// if base node, do insert (other nodes get inserted during Expand() notification)
if (SERVER_INSTANCE == pFolder->GetType()) BaseFolderInsertIntoScope(pFolder, pFolder->m_pCertCA);
// fwd to next elt
m_scopeItemList.GetNext(pos); } else // !fFound
{ // delete immediately from m_scopeItemList
m_scopeItemList.GetNext(nextpos);
delete pFolder; // destroy the elt
m_scopeItemList.RemoveAt(pos);
pos = nextpos; // restore next position
} }
// Task #2
// scour m_pCertMachine[] for new entries, create default folders
for (dwKnownCAs=0; dwKnownCAs<(DWORD)m_pCertMachine->m_CAList.GetSize(); dwKnownCAs++) { fFound = FALSE; for (pos = m_scopeItemList.GetHeadPosition(); (NULL != pos); m_scopeItemList.GetNext(pos)) { if (m_scopeItemList.GetAt(pos)->m_pCertCA->m_strCommonName.IsEqual(m_pCertMachine->GetCaCommonNameAtPos(dwKnownCAs))) { fFound = TRUE; break; // if matches something in the refreshed list, we're fine
} }
// found?
if (!fFound) { CertSvrCA* pCA; CFolder* pFolder;
pCA = m_pCertMachine->GetCaAtPos(dwKnownCAs); if (NULL == pCA) { hr = E_POINTER; _JumpError(hr, Ret, "m_pCertMachine->GetCaAtPos(iCAPos)"); }
// create base node, add to list, insert into scope pane
pFolder = new CFolder(); _JumpIfOutOfMemory(hr, Ret, pFolder);
m_scopeItemList.AddTail(pFolder); hr = BaseFolderInsertIntoScope(pFolder, pCA); _JumpIfError(hr, Ret, "BaseFolderInsertIntoScope");
// and create all template folders underneath
hr = CreateTemplateFolders(pCA); _JumpIfError(hr, Ret, "CreateTemplateFolders"); } else { // no need to do anything, ca is already known & inserted into scope
} }
// BOGDANT
// Task #3
// for each CA, offer to do any one-time per-CA upgrades
for (dwKnownCAs=0; dwKnownCAs<(DWORD)m_pCertMachine->m_CAList.GetSize(); dwKnownCAs++) { CertSvrCA* pCA;
pCA = m_pCertMachine->GetCaAtPos(dwKnownCAs); if (NULL == pCA) { hr = E_POINTER; _JumpError(hr, Ret, "m_pCertMachine->GetCaAtPos(iCAPos)"); }
if (pCA->FDoesSecurityNeedUpgrade()) { bool fUserHasWriteAccess = false; CString cstrMsg, cstrTitle; cstrMsg.LoadString(IDS_W2K_SECURITY_UPGRADE_DESCR); cstrTitle.LoadString(IDS_W2K_UPGRADE_DETECTED_TITLE);
hr = CurrentUserCanInstallCA(fUserHasWriteAccess); _JumpIfError(hr, Ret, "IsUserDomainAdministrator");
if (fUserHasWriteAccess) { // ask to upgrade security
// confirm this action
CString cstrTmp; cstrTmp.LoadString(IDS_CONFIRM_W2K_SECURITY_UPGRADE); cstrMsg += cstrTmp;
int iRet; if ((S_OK == m_pConsole->MessageBox(cstrMsg, cstrTitle, MB_YESNO, &iRet)) && (iRet == IDYES)) { // do stuff
hr = pCA->FixEnrollmentObject(); _JumpIfError(hr, error, "FixEnrollmentObject");
hr = AddCAMachineToCertPublishers(); _JumpIfError(hr, error, "AddCAMachineToCertPublishers");
if(pCA->FIsAdvancedServer()) { hr = AddCAMachineToPreWin2kGroup(); _JumpIfError(hr, error, "AddCAMachineToPreWin2kGroup"); }
if(RestartService(hwndMain, pCA->m_pParentMachine)) m_pConsole->UpdateAllViews( lpDataObject, 0, 0);
error: if (hr != S_OK) DisplayGenericCertSrvError(m_pConsole, hr); else { hr = pCA->CleanSetupStatusBits( SETUP_W2K_SECURITY_NOT_UPGRADED_FLAG); _PrintIfError(hr, "Failed to clear SETUP_W2K_SECURITY_NOT_UPGRADED_FLAG setup flag"); hr = S_OK; } } } else { // just warn
CString cstrTmp; cstrTmp.LoadString(IDS_BLOCK_W2K_SECURITY_UPGRADE); cstrMsg += cstrTmp;
m_pConsole->MessageBoxW(cstrMsg, cstrTitle, MB_OK, NULL); } } }
Ret:
return hr; }
HRESULT CComponentDataImpl::BaseFolderInsertIntoScope(CFolder* pFolder, CertSvrCA* pCA) { HRESULT hr = S_OK; int nImage; HSCOPEITEM pParent = m_pStaticRoot; // we'll always be initialized by this time if parent exists
ASSERT(m_pStaticRoot); if (NULL == m_pStaticRoot) { hr = E_POINTER; _JumpError(hr, Ret, "m_pStaticRoot"); }
if ((NULL == pFolder) || (NULL == pCA)) { hr = E_POINTER; _JumpError(hr, Ret, "NULL ptr"); }
if (pCA->m_strCommonName.IsEmpty()) { hr = E_POINTER; _JumpError(hr, Ret, "m_strCommonName"); }
if (m_pCertMachine->IsCertSvrServiceRunning()) nImage = IMGINDEX_CERTSVR_RUNNING; else nImage = IMGINDEX_CERTSVR_STOPPED;
pFolder->SetScopeItemInformation(nImage, nImage); pFolder->SetProperties( pCA->m_strCommonName, SCOPE_LEVEL_ITEM, SERVER_INSTANCE, TRUE);
pFolder->m_pCertCA = pCA; // fill this in as root
// Set the parent
pFolder->m_ScopeItem.mask |= SDI_PARENT; pFolder->m_ScopeItem.relativeID = pParent;
// Set the folder as the cookie
pFolder->m_ScopeItem.mask |= SDI_PARAM; pFolder->m_ScopeItem.lParam = reinterpret_cast<LPARAM>(pFolder); pFolder->SetCookie(reinterpret_cast<MMC_COOKIE>(pFolder));
// insert SCOPE_LEVEL_ITEM into scope pane
m_pScope->InsertItem(&pFolder->m_ScopeItem);
// Note - On return, the ID member of 'm_ScopeItem'
// contains the handle to the newly inserted item!
ASSERT(pFolder->m_ScopeItem.ID != NULL); Ret:
return hr; }
HRESULT CComponentDataImpl::CreateTemplateFolders(CertSvrCA* pCA) { HRESULT hr = S_OK;
SetCertView();
// add all template folders under it
for (int iUnder=0; iUnder < ARRAYLEN(SvrFuncFolderData); iUnder++) { // skip alien if svr doesn't support
if ((iUnder==ENUM_FOLDER_ALIEN) && !pCA->FDoesServerAllowForeignCerts()) continue;
if ((iUnder==ENUM_FOLDER_CRLS) && g_fCertViewOnly) continue;
CString cstrRsc; cstrRsc.LoadString(SvrFuncFolderData[iUnder].iNameRscID);
CFolder* pFolder; pFolder = new CFolder(); _JumpIfOutOfMemory(hr, Ret, pFolder);
pFolder->m_pCertCA = pCA; pFolder->SetScopeItemInformation(IMGINDEX_FOLDER, IMGINDEX_FOLDER_OPEN); pFolder->SetProperties( cstrRsc, CA_LEVEL_ITEM, SvrFuncFolderData[iUnder].type, FALSE);
m_scopeItemList.AddTail(pFolder); }
Ret: return hr; }
void CComponentDataImpl::EnumerateScopePane(LPDATAOBJECT lpDataObject, HSCOPEITEM pParent) { ASSERT(m_pScope != NULL); // make sure we QI'ed for the interface
ASSERT(lpDataObject != NULL);
INTERNAL* pInternal = ExtractInternalFormat(lpDataObject); if (pInternal == NULL) return;
MMC_COOKIE cookie = pInternal->m_cookie;
FREE_DATA(pInternal);
// Enumerate the scope pane
// return the folder object that represents the cookie
// Note - for large list, use dictionary
CFolder* pStatic = FindObject(cookie); if (pStatic) ASSERT(!pStatic->IsEnumerated());
if (NULL == cookie) { if (!m_fScopeAlreadyEnumerated) // if base node and we've never inserted nodes
{ // TASK: expand machine node
// Note - Each cookie in the scope pane represents a folder.
// Cache the HSCOPEITEM of the static root.
ASSERT(pParent != NULL); m_pStaticRoot = pParent; // add/remove: EXPAND case
// synch folder list if asking to expand machine node
// SyncDisplayedCAList adds all necessary folders
HRESULT hr = SynchDisplayedCAList(lpDataObject); if (hr != S_OK) { HWND hwnd; DWORD dwErr2 = m_pConsole->GetMainWindow(&hwnd); ASSERT(dwErr2 == ERROR_SUCCESS); if (dwErr2 != ERROR_SUCCESS) hwnd = NULL; // should work
if (((HRESULT)RPC_S_SERVER_UNAVAILABLE) == hr) { DisplayCertSrvErrorWithContext(hwnd, hr, IDS_SERVER_UNAVAILABLE); } else if(HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION)==hr || ((HRESULT)ERROR_OLD_WIN_VERSION)==hr) { DisplayCertSrvErrorWithContext(hwnd, hr, IDS_OLD_CA); } else { DisplayCertSrvErrorWithContext(hwnd, hr, IDS_CANNOT_OPEN_CERT_SERVICES); } } } } else { // TASK: expand non-machine node
if (NULL == pStatic) return;
switch(pStatic->GetType()) { case SERVER_INSTANCE: { // TASK: expand CA instance node
POSITION pos = m_scopeItemList.GetHeadPosition(); while(pos) { CFolder* pFolder; pFolder = m_scopeItemList.GetNext(pos); if (pFolder==NULL) break;
// only expand folders that belong under the SERVER_INSTANCE
if (pFolder->m_itemType != CA_LEVEL_ITEM) continue;
// and only those under the correct CA
if (pFolder->m_pCertCA != pStatic->m_pCertCA) continue;
// Set the parent
pFolder->m_ScopeItem.relativeID = pParent;
// Set the folder as the cookie
pFolder->m_ScopeItem.mask |= SDI_PARAM; pFolder->m_ScopeItem.lParam = reinterpret_cast<LPARAM>(pFolder); pFolder->SetCookie(reinterpret_cast<MMC_COOKIE>(pFolder)); m_pScope->InsertItem(&pFolder->m_ScopeItem);
// Note - On return, the ID member of 'm_ScopeItem'
// contains the handle to the newly inserted item!
ASSERT(pFolder->m_ScopeItem.ID != NULL); } } break; default: // TASK: expand nodes with no folders under them
break; } } }
CFolder* CComponentDataImpl::FindObject(MMC_COOKIE cookie) { CFolder* pFolder = NULL; POSITION pos = m_scopeItemList.GetHeadPosition();
while(pos) { pFolder = m_scopeItemList.GetNext(pos);
if (*pFolder == cookie) return pFolder; }
return NULL; }
STDMETHODIMP CComponentDataImpl::GetDisplayInfo(SCOPEDATAITEM* pScopeDataItem) { ASSERT(pScopeDataItem != NULL); if (pScopeDataItem == NULL) return E_POINTER;
CFolder* pFolder = reinterpret_cast<CFolder*>(pScopeDataItem->lParam);
if ((pScopeDataItem->mask & SDI_STR) && (pFolder != NULL)) { pScopeDataItem->displayname = pFolder->m_pszName; }
// I was told by Ravi Rudrappa that these notifications
// would never be given. If it is given, move UpdateScopeIcons()
// functionality here!!!
ASSERT(0 == (pScopeDataItem->mask & SDI_IMAGE)); ASSERT(0 == (pScopeDataItem->mask & SDI_OPENIMAGE));
return S_OK; }
STDMETHODIMP CComponentDataImpl::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB) { if (lpDataObjectA == NULL || lpDataObjectB == NULL) return E_POINTER;
HRESULT hr = S_FALSE;
// Make sure both data object are mine
INTERNAL* pA = ExtractInternalFormat(lpDataObjectA); INTERNAL* pB = ExtractInternalFormat(lpDataObjectA);
if (pA != NULL && pB != NULL) hr = (*pA == *pB) ? S_OK : S_FALSE;
FREE_DATA(pA); FREE_DATA(pB);
return hr; }
/////////////////////////////////////////////////////////////////////////////
// IExtendPropertySheet Implementation
STDMETHODIMP CComponentDataImpl::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider, LONG_PTR handle, LPDATAOBJECT lpIDataObject) { HRESULT hr = S_OK;
// Look at the data object and determine if this an extension or a primary
ASSERT(lpIDataObject != NULL);
PropertyPage* pBasePage;
INTERNAL* pInternal = ExtractInternalFormat(lpIDataObject); if (pInternal == NULL) return S_OK; switch (pInternal->m_type) { case CCT_SNAPIN_MANAGER: { CChooseMachinePropPage* pPage = new CChooseMachinePropPage(); _JumpIfOutOfMemory(hr, Ret, pPage);
// this alloc might have failed (should be in ctor)
_JumpIfOutOfMemory(hr, Ret, m_pCertMachine);
pPage->SetCaption(IDS_SCOPE_MYCOMPUTER);
// Initialize state of object
pPage->InitMachineName(NULL); // point to our member vars
pPage->SetOutputBuffers( &m_pCertMachine->m_strMachineNamePersist, &m_pCertMachine->m_strMachineName, &m_dwFlagsPersist);
pBasePage = pPage;
// Object gets deleted when the page is destroyed
ASSERT(lpProvider != NULL);
ASSERT(pBasePage != NULL); HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp); if (hPage == NULL) { hr = myHLastError(); _JumpError(hr, Ret, "CreatePropertySheetPage"); }
lpProvider->AddPage(hPage);
break; } case CCT_SCOPE: { // if not base scope
if (0 != pInternal->m_cookie) { // switch on folder type
CFolder* pFolder = GetParentFolder(pInternal); ASSERT(pFolder != NULL); if (pFolder == NULL) { hr = E_POINTER; _JumpError(hr, Ret, "GetParentFolder"); }
switch(pFolder->m_type) { case SERVER_INSTANCE: { //1
CSvrSettingsGeneralPage* pControlPage = new CSvrSettingsGeneralPage(pFolder->m_pCertCA); if (pControlPage != NULL) { pControlPage->m_hConsoleHandle = handle; // only do this on primary
pBasePage = pControlPage; HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp); if (hPage == NULL) { hr = myHLastError(); _JumpError(hr, Ret, "CreatePropertySheetPage"); } lpProvider->AddPage(hPage); }
//2
{ CSvrSettingsPolicyPage* pPage = new CSvrSettingsPolicyPage(pControlPage); if (pPage != NULL) { pBasePage = pPage; HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp); if (hPage == NULL) { hr = myHLastError(); _JumpError(hr, Ret, "CreatePropertySheetPage"); } lpProvider->AddPage(hPage); } }
//3
{ CSvrSettingsExitPage* pPage = new CSvrSettingsExitPage(pControlPage); if (pPage != NULL) { pBasePage = pPage; HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp); if (hPage == NULL) { hr = myHLastError(); _JumpError(hr, Ret, "CreatePropertySheetPage"); } lpProvider->AddPage(hPage); } } //4
{ // Centralized extensions page available only in whistler
if (pFolder->m_pCertCA->m_pParentMachine->FIsWhistlerMachine()) {
CSvrSettingsExtensionPage* pPage = new CSvrSettingsExtensionPage(pFolder->m_pCertCA, pControlPage); if (pPage != NULL) { pBasePage = pPage; HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp); if (hPage == NULL) { hr = myHLastError(); _JumpError(hr, Ret, "CreatePropertySheetPage"); } lpProvider->AddPage(hPage); } } }
//5
{ CSvrSettingsStoragePage* pPage = new CSvrSettingsStoragePage(pControlPage); if (pPage != NULL) { pBasePage = pPage; HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp); if (hPage == NULL) { hr = myHLastError(); _JumpError(hr, Ret, "CreatePropertySheetPage"); } lpProvider->AddPage(hPage); } } //6
{ // restricted officers available only in whistler advanced server
if(pFolder->m_pCertCA->m_pParentMachine->FIsWhistlerMachine() && pFolder->m_pCertCA->FIsAdvancedServer()) { CSvrSettingsCertManagersPage* pPage = new CSvrSettingsCertManagersPage(pControlPage); if (pPage != NULL) { pBasePage = pPage; HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp); if (hPage == NULL) { hr = myHLastError(); _JumpError(hr, Ret, "CreatePropertySheetPage"); } lpProvider->AddPage(hPage); } } } //7
{ // audit available only in whistler
if(pFolder->m_pCertCA->m_pParentMachine->FIsWhistlerMachine()) { CSvrSettingsAuditFilterPage* pPage = new CSvrSettingsAuditFilterPage(pControlPage); if (pPage != NULL) { pBasePage = pPage; HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp); if (hPage == NULL) { hr = myHLastError(); _JumpError(hr, Ret, "CreatePropertySheetPage"); } lpProvider->AddPage(hPage); } } } //8
{ // audit available only in whistler advanced server, enterprise
if(pFolder->m_pCertCA->m_pParentMachine->FIsWhistlerMachine() && pFolder->m_pCertCA->FIsAdvancedServer() && IsEnterpriseCA(pFolder->m_pCertCA->GetCAType()) ) { CSvrSettingsKRAPage* pPage = new CSvrSettingsKRAPage( pFolder->m_pCertCA, pControlPage); if (pPage != NULL) { pBasePage = pPage; HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp); if (hPage == NULL) { hr = myHLastError(); _JumpError(hr, Ret, "CreatePropertySheetPage"); } lpProvider->AddPage(hPage); } } } //9
{ // if error, don't display this page
LPSECURITYINFO pCASecurity = NULL;
hr = CreateCASecurityInfo(pFolder->m_pCertCA, &pCASecurity); _PrintIfError(hr, "CreateCASecurityInfo"); if (hr == S_OK) { // allow proppages to clean up security info
pControlPage->SetAllocedSecurityInfo(pCASecurity); HPROPSHEETPAGE hPage = CreateSecurityPage(pCASecurity); if (hPage == NULL) { hr = myHLastError(); _JumpError(hr, Ret, "CreatePropertySheetPage"); } lpProvider->AddPage(hPage); } }
hr = S_OK; break; }// end case SERVER_INSTANCE
case SERVERFUNC_CRL_PUBLICATION: { //1
CCRLPropPage* pControlPage = new CCRLPropPage(pFolder->m_pCertCA); if (pControlPage != NULL) { pControlPage->m_hConsoleHandle = handle; pBasePage = pControlPage;
// Object gets deleted when the page is destroyed
ASSERT(lpProvider != NULL); ASSERT(pBasePage != NULL); HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp); if (hPage == NULL) { hr = myHLastError(); _JumpError(hr, Ret, "CreatePropertySheetPage"); }
lpProvider->AddPage(hPage); } //2
{ CCRLViewPage* pPage = new CCRLViewPage(pControlPage); if (pPage != NULL) { pBasePage = pPage; HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp); if (hPage == NULL) { hr = myHLastError(); _JumpError(hr, Ret, "CreatePropertySheetPage"); }
lpProvider->AddPage(hPage); } } break; } default: break; } // end switch(pFolder->m_type)
} // end switch(scope)
} break; default: break; }
Ret: FREE_DATA(pInternal); return hr; }
STDMETHODIMP CComponentDataImpl::QueryPagesFor(LPDATAOBJECT lpDataObject) { BOOL bResult = FALSE;
INTERNAL* pInternal = ExtractInternalFormat(lpDataObject); if (NULL == pInternal) return S_FALSE;
if (pInternal->m_cookie != NULL) { CFolder* pFolder = GetParentFolder(pInternal); if (pFolder != NULL) { switch(pFolder->m_type) { case SERVER_INSTANCE: case SERVERFUNC_CRL_PUBLICATION: bResult = TRUE; default: break; } } } else { // say YES to snapin manager
if (CCT_SNAPIN_MANAGER == pInternal->m_type) bResult = TRUE; } FREE_DATA(pInternal); return (bResult) ? S_OK : S_FALSE;
// Look at the data object and see if it an item in the scope pane
// return IsScopePaneNode(lpDataObject) ? S_OK : S_FALSE;
}
///////////////////////////////////////////////////////////////////////////////
// IExtendContextMenu implementation
//
STDMETHODIMP CComponentDataImpl::AddMenuItems(LPDATAOBJECT pDataObject, LPCONTEXTMENUCALLBACK pContextMenuCallback, LONG *pInsertionAllowed) { HRESULT hr = S_OK; TASKITEM* pm = NULL;
// Note - snap-ins need to look at the data object and determine
// in what context, menu items need to be added. They must also
// observe the insertion allowed flags to see what items can be
// added.
INTERNAL* pInternal = ExtractInternalFormat(pDataObject); if (NULL == pInternal) return S_OK;
BOOL fResultItem = (pInternal->m_type == CCT_RESULT); BOOL fMultiSel = IsMMCMultiSelectDataObject(pDataObject);
CFolder* pFolder; if (!fResultItem) pFolder = GetParentFolder(pInternal); else { // GetParent might work, but doesn't for virtual items...
ASSERT(m_pCurSelFolder); pFolder = m_pCurSelFolder; }
FOLDER_TYPES folderType = NONE; if (pFolder == NULL) folderType = MACHINE_INSTANCE; else folderType = pFolder->GetType();
// Loop through and add each of the "topItems"
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP) { // don't do for multisel
if (!fMultiSel) { pm = (TASKITEM*) LocalAlloc(LMEM_FIXED, sizeof(topItems)); _JumpIfAllocFailed(pm, Ret);
memcpy(pm, topItems, sizeof(topItems));
// Disable retarget if we haven't yet clicked on the static root. Otherwise,
// DisplayProperRootNodeName handles load-from-file
// MMCN_EXPAND handles add/remove and expanded
pm[ENUM_RETARGET_SNAPIN].myitem.item.fFlags = m_pStaticRoot ? MFS_ENABLED : MFS_GRAYED;
for (TASKITEM* pm1=pm; pm1->myitem.item.strName; pm1++) { // does it match scope/result type?
if (fResultItem != ((pm1->dwFlags & TASKITEM_FLAG_RESULTITEM) != 0) ) continue;
// does it match area it should be in?
// for each task, insert if matches the current folder
if ((pm1->type != SERVERFUNC_ALL_FOLDERS) && (folderType != pm1->type)) continue;
hr = pContextMenuCallback->AddItem(&pm1->myitem.item); _JumpIfError(hr, Ret, "AddItem"); }
LocalFree(pm); pm = NULL; } }
// this is the end of the line if folder nonexistant
if (pFolder == NULL) goto Ret;
// Loop through and add each of the view items
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_VIEW) { }
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TASK) { // ptr to tasks
pm = (TASKITEM*) LocalAlloc(LMEM_FIXED, sizeof(taskItems)); _JumpIfAllocFailed(pm, Ret);
memcpy(pm, taskItems, sizeof(taskItems));
BOOL fRunningLocally = m_pCertMachine->IsLocalMachine(); BOOL fSvcRunning = m_pCertMachine->IsCertSvrServiceRunning(); if ( IsAllowedStartStop(pFolder, m_pCertMachine) ) AddStartStopTasks(pFolder, pContextMenuCallback, fSvcRunning);
// only fixup on server instance
if (folderType == SERVER_INSTANCE) { // fixup entries depending on install type/state
if (IsRootCA(pFolder->GetCA()->GetCAType())) // root ca?
{ pm[ENUM_TASK_INSTALL].myitem.item.fFlags = MFS_HIDDEN; // not available
pm[ENUM_TASK_REQUEST].myitem.item.fFlags = MFS_HIDDEN; // not available
pm[ENUM_TASK_ROLLOVER].myitem.item.fFlags = MFS_ENABLED; } else // sub ca
{ if (pFolder->GetCA()->FIsRequestOutstanding()) pm[ENUM_TASK_INSTALL].myitem.item.fFlags = MFS_ENABLED; else pm[ENUM_TASK_INSTALL].myitem.item.fFlags = MFS_HIDDEN; if (pFolder->GetCA()->FIsIncompleteInstallation()) // incomplete
{ pm[ENUM_TASK_REQUEST].myitem.item.fFlags = MFS_ENABLED; pm[ENUM_TASK_ROLLOVER].myitem.item.fFlags = MFS_HIDDEN; // not available
} else // complete install
{ pm[ENUM_TASK_REQUEST].myitem.item.fFlags = MFS_HIDDEN; // not available
pm[ENUM_TASK_ROLLOVER].myitem.item.fFlags = MFS_ENABLED; } }
static bool fIsMember; static bool fIsMemberChecked = false;
if(!fIsMemberChecked) { hr = myIsCurrentUserBuiltinAdmin(&fIsMember); if(S_OK==hr) { fIsMemberChecked = true; } }
// Hide renew/install CA cert item if not local admin or if we
// failed to figure it out. Ignore the error.
// !!! Post Whistler when we get renew CA cert to work for non
// local admin we should change the code here to hide the item
// based on the role that is allowed to do it.
if(S_OK != hr || !fIsMember) { pm[ENUM_TASK_ROLLOVER].myitem.item.fFlags = MFS_HIDDEN; hr = S_OK; } }
// don't allow properties on multisel
pm[ENUM_TASK_ATTREXTS_CRL].myitem.item.fFlags = fMultiSel ? MFS_HIDDEN : MFS_ENABLED; pm[ENUM_TASK_ATTREXTS_ISS].myitem.item.fFlags = fMultiSel ? MFS_HIDDEN : MFS_ENABLED; pm[ENUM_TASK_ATTREXTS_PEND].myitem.item.fFlags = fMultiSel ? MFS_HIDDEN : MFS_ENABLED; pm[ENUM_TASK_ATTREXTS_FAIL].myitem.item.fFlags = fMultiSel ? MFS_HIDDEN : MFS_ENABLED;
// disable based on roles
for(TASKITEM* pm1=pm; pm1->myitem.item.strName; pm1++) { if((pm1->myitem.item.fFlags == MFS_ENABLED) && !((pm1->myitem.dwRoles) & (pFolder->m_pCertCA->GetMyRoles()))) pm1->myitem.item.fFlags = MFS_GRAYED; }
// insert all other tasks per folder
for (TASKITEM* pm1=pm; pm1->myitem.item.strName; pm1++) { // does it match scope/result type?
if (fResultItem != ((pm1->dwFlags & TASKITEM_FLAG_RESULTITEM) != 0)) continue;
// are we remote, and is it marked localonly? (not yes/no like other tests here)
if (((pm1->dwFlags & TASKITEM_FLAG_LOCALONLY)) && (!fRunningLocally)) continue;
// does it match area it should be in?
// for each task, insert if matches the current folder
if ((pm1->type != SERVERFUNC_ALL_FOLDERS) && (folderType != pm1->type)) continue;
// is this task supposed to be hidden?
if (MFS_HIDDEN == pm1->myitem.item.fFlags) continue;
hr = pContextMenuCallback->AddItem(&pm1->myitem.item); _JumpIfError(hr, Ret, "AddItem"); }
LocalFree(pm); pm = NULL; }
Ret: LOCAL_FREE(pm); FREE_DATA(pInternal); return hr; }
BOOL CComponentDataImpl::AddStartStopTasks( CFolder *pFolder, LPCONTEXTMENUCALLBACK pContextMenuCallback, BOOL fSvcRunning) { HRESULT hr; MY_CONTEXTMENUITEM* pm = taskStartStop;
bool fUserCanStart = (pm[ENUM_TASK_START].dwRoles) & (pFolder->m_pCertCA->GetMyRoles())? true:false; bool fUserCanStop = (pm[ENUM_TASK_STOP].dwRoles) & (pFolder->m_pCertCA->GetMyRoles())? true:false;
pm[ENUM_TASK_START].item.fFlags = (fSvcRunning || !fUserCanStart)? MF_GRAYED : MF_ENABLED; hr = pContextMenuCallback->AddItem(&pm[ENUM_TASK_START].item); _JumpIfError(hr, Ret, "AddItem");
pm[ENUM_TASK_STOP].item.fFlags = (fSvcRunning && fUserCanStop)? MF_ENABLED : MF_GRAYED; hr = pContextMenuCallback->AddItem(&pm[ENUM_TASK_STOP].item); _JumpIfError(hr, Ret, "AddItem");
Ret: return (hr == ERROR_SUCCESS); }
STDMETHODIMP CComponentDataImpl::Command(LONG nCommandID, LPDATAOBJECT pDataObject) { // Note - snap-ins need to look at the data object and determine
// in what context the command is being called.
HRESULT dwErr = S_OK;
INTERNAL* pInternal = ExtractInternalFormat(pDataObject); ASSERT(pInternal); if (NULL == pInternal) return S_OK;
BOOL fMustRefresh = FALSE; BOOL fPopup = TRUE;
CFolder* pFolder = GetParentFolder(pInternal);
// Handle each of the commands.
switch (nCommandID) { case IDC_STOPSERVER: { HWND hwndMain; dwErr = m_pConsole->GetMainWindow(&hwndMain);
if (dwErr == S_OK) dwErr = m_pCertMachine->CertSvrStartStopService(hwndMain, FALSE);
// notify views: refresh service toolbar buttons
fMustRefresh = TRUE; break; } case IDC_STARTSERVER: { HWND hwndMain; dwErr = m_pConsole->GetMainWindow(&hwndMain); if (S_OK == dwErr) dwErr = m_pCertMachine->CertSvrStartStopService(hwndMain, TRUE);
// check for ERROR_INSTALL_SUSPEND or HR(ERROR_INSTALL_SUSPEND)!!
if ((((HRESULT)ERROR_INSTALL_SUSPEND) == dwErr) || (HRESULT_FROM_WIN32(ERROR_INSTALL_SUSPEND) == dwErr)) { CString cstrMsg, cstrTitle; cstrMsg.LoadString(IDS_COMPLETE_HIERARCHY_INSTALL_MSG); cstrTitle.LoadString(IDS_MSG_TITLE);
CertSvrCA* pCA;
for (DWORD i=0; i<m_pCertMachine->GetCaCount(); i++) { pCA = m_pCertMachine->GetCaAtPos(i);
// search for any/all incomplete hierarchies
if (pCA->FIsIncompleteInstallation()) { int iRet; WCHAR sz[512]; wsprintf(sz, (LPCWSTR)cstrMsg, (LPCWSTR)pCA->m_strCommonName, (LPCWSTR)pCA->m_strServer);
m_pConsole->MessageBox( sz, cstrTitle, MB_YESNO, &iRet); if (IDYES != iRet) break;
dwErr = CARequestInstallHierarchyWizard(pCA, hwndMain, FALSE, FALSE); if (dwErr != S_OK) { // fPopup = FALSE;// sometimes no notification -- better to have 2 dlgs
break; } } }
// my responsibility to start the service again
if (dwErr == S_OK) dwErr = m_pCertMachine->CertSvrStartStopService(hwndMain, TRUE); } else if ((((HRESULT)ERROR_FILE_NOT_FOUND) == dwErr) || (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == dwErr)) { // file not found error could be related to policy module
WCHAR const *pwsz = myGetErrorMessageText(dwErr, TRUE); CString cstrFullMessage = pwsz; if (NULL != pwsz) { LocalFree(const_cast<WCHAR *>(pwsz)); } cstrFullMessage += L"\n\n";
CString cstrHelpfulMessage; cstrHelpfulMessage.LoadString(IDS_POSSIBLEERROR_NO_POLICY_MODULE); cstrFullMessage += cstrHelpfulMessage;
CString cstrTitle; cstrTitle.LoadString(IDS_MSG_TITLE);
int iRet; m_pConsole->MessageBox( cstrFullMessage, cstrTitle, MB_OK, &iRet);
dwErr = ERROR_SUCCESS; }
// notify views: refresh service toolbar buttons
fMustRefresh = TRUE; break; } case IDC_PUBLISHCRL: { ASSERT(pInternal->m_type != CCT_RESULT); if (NULL == pFolder) break;
HWND hwnd; dwErr = m_pConsole->GetMainWindow(&hwnd); ASSERT(dwErr == ERROR_SUCCESS); if (dwErr != ERROR_SUCCESS) hwnd = NULL; // should work
dwErr = PublishCRLWizard(pFolder->m_pCertCA, hwnd); break;
// no refresh
} case IDC_BACKUP_CA: { HWND hwnd; dwErr = m_pConsole->GetMainWindow(&hwnd); // NULL should work
if (S_OK != dwErr) hwnd = NULL;
if (NULL == pFolder) break;
dwErr = CABackupWizard(pFolder->GetCA(), hwnd);
// refresh the status of the CA -- may have started it during this operation
fMustRefresh = TRUE; break; } case IDC_RESTORE_CA: { HWND hwnd; dwErr = m_pConsole->GetMainWindow(&hwnd); // NULL should work
if (S_OK != dwErr) hwnd = NULL;
if (NULL == pFolder) break; dwErr = CARestoreWizard(pFolder->GetCA(), hwnd);
if ((myJetHResult(JET_errDatabaseDuplicate) == dwErr) || HRESULT_FROM_WIN32(ERROR_DIR_NOT_EMPTY) == dwErr) { DisplayCertSrvErrorWithContext(hwnd, dwErr, IDS_ERR_RESTORE_OVER_EXISTING_DATABASE); dwErr = S_OK; }
if (HRESULT_FROM_WIN32(ERROR_DIRECTORY) == dwErr) { DisplayCertSrvErrorWithContext(hwnd, dwErr, IDS_ERR_RESTORE_OUT_OF_ORDER); dwErr = S_OK; }
// refresh after restore
fMustRefresh = TRUE;
break; } case IDC_SUBMITREQUEST: { HWND hwnd; WCHAR szCmdLine[MAX_PATH], szSysDir[MAX_PATH];
STARTUPINFO sStartup; ZeroMemory(&sStartup, sizeof(sStartup)); PROCESS_INFORMATION sProcess; ZeroMemory(&sProcess, sizeof(sProcess)); sStartup.cb = sizeof(sStartup);
dwErr = m_pConsole->GetMainWindow(&hwnd); // NULL should work
if (S_OK != dwErr) hwnd = NULL;
if (NULL == pFolder) break;
if (0 == GetSystemDirectory(szSysDir, ARRAYSIZE(szSysDir))) { dwErr = GetLastError(); break; }
// exec "certutil -dump szReqFile szTempFile"
wsprintf(szCmdLine, L"%ws\\certreq.exe -config \"%ws\"", szSysDir, (LPCWSTR)pFolder->GetCA()->m_strConfig); wcscat(szSysDir, L"\\certreq.exe");
if (!CreateProcess( szSysDir, // exe
szCmdLine, // full cmd line
NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &sStartup, &sProcess)) { dwErr = GetLastError(); break; }
dwErr = S_OK; break; } case IDC_INSTALL_CA: case IDC_REQUEST_CA: case IDC_ROLLOVER_CA: { HWND hwnd; dwErr = m_pConsole->GetMainWindow(&hwnd); // NULL should work
if (S_OK != dwErr) hwnd = NULL;
if (NULL == pFolder) { dwErr = E_UNEXPECTED; break; } dwErr = CARequestInstallHierarchyWizard(pFolder->GetCA(), hwnd, (nCommandID==IDC_ROLLOVER_CA), TRUE); if (S_OK != dwErr) { // low level lib had popup
// fPopup = FALSE; // sometimes no notification -- better to have 2 dlgs
}
// notify views: refresh service toolbar buttons
fMustRefresh = TRUE;
break; } case IDC_RETARGET_SNAPIN: { HWND hwnd; dwErr = m_pConsole->GetMainWindow(&hwnd); // NULL should work
if (S_OK != dwErr) hwnd = NULL;
// this should be base folder ONLY
if(pFolder != NULL) { dwErr = E_POINTER; break; }
CString strMachineNamePersist, strMachineName; CChooseMachinePropPage* pPage = new CChooseMachinePropPage(); // autodelete proppage -- don't delete
if (pPage == NULL) { dwErr = E_OUTOFMEMORY; break; }
pPage->SetCaption(IDS_SCOPE_MYCOMPUTER);
// Initialize state of object
pPage->InitMachineName(NULL); // populate UI
strMachineNamePersist = m_pCertMachine->m_strMachineNamePersist; strMachineName = m_pCertMachine->m_strMachineName;
// point to our member vars
pPage->SetOutputBuffers( &strMachineNamePersist, &strMachineName, &m_dwFlagsPersist);
ASSERT(pPage != NULL); HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pPage->m_psp); if (hPage == NULL) { dwErr = E_UNEXPECTED; break; }
PROPSHEETHEADER sPsh; ZeroMemory(&sPsh, sizeof(sPsh)); sPsh.dwSize = sizeof(sPsh); sPsh.dwFlags = PSH_WIZARD; sPsh.hwndParent = hwnd; sPsh.hInstance = g_hInstance; sPsh.nPages = 1; sPsh.phpage = &hPage;
dwErr = (DWORD) PropertySheet(&sPsh); if (dwErr == (HRESULT)-1) { // error
dwErr = GetLastError(); break; } if (dwErr == (HRESULT)0) { // cancel
break; }
// we've grabbed the user's choice by now, finish retargetting
CertSvrMachine* pOldMachine = m_pCertMachine; m_pCertMachine = new CertSvrMachine; if (NULL == m_pCertMachine) { m_pCertMachine = pOldMachine; break; // bail!
}
// copy to machine object
m_pCertMachine->m_strMachineNamePersist = strMachineNamePersist; m_pCertMachine->m_strMachineName = strMachineName;
dwErr = DisplayProperRootNodeName(m_pStaticRoot); // fix display
_PrintIfError(dwErr, "DisplayProperRootNodeName");
dwErr = SynchDisplayedCAList(pDataObject); // add/remove folders
_PrintIfError(dwErr, "SynchDisplayedCAList"); // after Synch, we remove old machine -- there are no references left to it
if (pOldMachine) pOldMachine->Release();
fMustRefresh = TRUE; // update folder icons, descriptions
break; } default: ASSERT(FALSE); // Unknown command!
break; }
FREE_DATA(pInternal);
if ((dwErr != ERROR_SUCCESS) && (dwErr != ERROR_CANCELLED) && (dwErr != HRESULT_FROM_WIN32(ERROR_CANCELLED)) && (dwErr != HRESULT_FROM_WIN32(ERROR_NOT_READY)) && fPopup) { HWND hwnd; DWORD dwErr2 = m_pConsole->GetMainWindow(&hwnd); ASSERT(dwErr2 == ERROR_SUCCESS); if (dwErr2 != ERROR_SUCCESS) hwnd = NULL; // should work
if (((HRESULT)RPC_S_SERVER_UNAVAILABLE) == dwErr) { DisplayCertSrvErrorWithContext(hwnd, dwErr, IDS_SERVER_UNAVAILABLE); } else if(HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION)==dwErr || ((HRESULT)ERROR_OLD_WIN_VERSION)==dwErr) { DisplayCertSrvErrorWithContext(hwnd, dwErr, IDS_OLD_CA); } else { DisplayGenericCertSrvError(hwnd, dwErr); } }
// only do this once
if (fMustRefresh) { // notify views: refresh service toolbar buttons
m_pConsole->UpdateAllViews( pDataObject, 0, 0); }
return S_OK; }
void CComponentDataImpl::UpdateScopeIcons() { CFolder* pFolder; POSITION pos; int nImage; // walk through our internal list, modify, and resend to scope
pos = m_scopeItemList.GetHeadPosition(); while(pos) { pFolder = m_scopeItemList.GetNext(pos); ASSERT(pFolder); if (NULL == pFolder) break;
// only modify server instances
if (pFolder->GetType() != SERVER_INSTANCE) continue;
if (pFolder->m_pCertCA->m_pParentMachine->IsCertSvrServiceRunning()) nImage = IMGINDEX_CERTSVR_RUNNING; else nImage = IMGINDEX_CERTSVR_STOPPED;
// folder currently has these values defined, right?
ASSERT(pFolder->m_ScopeItem.mask & SDI_IMAGE); ASSERT(pFolder->m_ScopeItem.mask & SDI_OPENIMAGE);
// These are the only values we wish to reset
pFolder->m_ScopeItem.mask = SDI_IMAGE | SDI_OPENIMAGE; pFolder->m_ScopeItem.nImage = nImage; pFolder->m_ScopeItem.nOpenImage = nImage;
// and send these changes back to scope
m_pScope->SetItem(&pFolder->m_ScopeItem); }
return; }
|