windows-nt/Source/XPSP1/NT/ds/security/services/ca/certmmc/compdata.cpp
2020-09-26 16:20:57 +08:00

2820 lines
82 KiB
C++

// 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 <atlimpl.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},
};
// 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
};
// 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,
},
{
{
L"", L"",
IDC_STOPSERVER, CCM_INSERTIONPOINTID_PRIMARY_TASK, 0, 0
},
IDS_TASKMENU_STOPSERVICE,
IDS_TASKMENU_STATUSBAR_STOPSERVICE,
},
{
{ 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_CRL,
ENUM_TASK_DUMP_ASN_ISS,
ENUM_TASK_DUMP_ASN_PEND,
ENUM_TASK_DUMP_ASN_FAIL,
ENUM_TASK_DUMP_ASN_ALIEN,
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,
}
},
/////////////////////
// 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,
}
},
{ 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,
}
},
{ 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,
}
},
{ 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,
}
},
// 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,
}
},
{ 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,
}
},
{ 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,
}
},
{ 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,
}
},
{ 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,
}
},
// 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,
}
},
{ 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,
}
},
{ 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,
}
},
{ 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,
}
},
{ 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,
}
},
// 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,
}
},
{ SERVER_INSTANCE,
TASKITEM_FLAG_LOCALONLY,
{
{
L"", L"",
IDC_RESTORE_CA, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
},
IDS_TASKMENU_RESTORE,
IDS_TASKMENU_STATUSBAR_RESTORE,
}
},
// 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,
}
},
{ SERVER_INSTANCE,
0,
{
{
L"", L"",
IDC_REQUEST_CA, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
},
IDS_TASKMENU_REQUEST_CA,
IDS_TASKMENU_STATUSBAR_REQUEST_CA,
}
},
{ SERVER_INSTANCE,
TASKITEM_FLAG_LOCALONLY,
{
{
L"", L"",
IDC_ROLLOVER_CA, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_GRAYED, 0
},
IDS_TASKMENU_ROLLOVER,
IDS_TASKMENU_STATUSBAR_ROLLOVER,
}
},
{ 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,
}
},
{ 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,
}
},
{ 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,
}
},
{
MACHINE_INSTANCE,
0,
{
{
L"", L"",
IDC_RETARGET_SNAPIN, CCM_INSERTIONPOINTID_PRIMARY_TOP, MF_ENABLED, 0
},
IDS_RETARGET_SNAPIN,
IDS_STATUSBAR_RETARGET_SNAPIN,
}
},
{ NONE,
0,
{
{ NULL, NULL, 0, 0, 0 },
IDS_EMPTY,
IDS_EMPTY,
}
}
};
///////////////////////////////////////////////////////////////////////////////
// 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
// 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;
// Load resources
if (!g_cResources.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 %s)
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 %s)
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, -1, 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;
DWORD dwParticularCA;
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++)
{
DWORD dwNumFolders=0;
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;
}
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);
_PrintIfError(hr, "SelectScopeItem");
hr = m_pScope->DeleteItem(m_pStaticRoot, FALSE); // remove everything from UI
_PrintIfError(hr, "DeleteItem");
// 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;
CFolder* pFolder;
pCA = m_pCertMachine->GetCaAtPos(dwKnownCAs);
if (NULL == pCA)
{
hr = E_POINTER;
_JumpError(hr, Ret, "m_pCertMachine->GetCaAtPos(iCAPos)");
}
if (pCA->FDoesSecurityNeedUpgrade())
{
BOOL fIsDomainAdmin = FALSE;
CString cstrMsg, cstrTitle;
cstrMsg.LoadString(IDS_W2K_SECURITY_UPGRADE_DESCR);
cstrTitle.LoadString(IDS_W2K_UPGRADE_DETECTED_TITLE);
hr = IsUserDomainAdministrator(&fIsDomainAdmin);
_JumpIfError(hr, Ret, "IsUserDomainAdministrator");
if (fIsDomainAdmin)
{
// 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 = csiUpgradeCertSrvSecurity(
pCA->m_strCommonName,
IsEnterpriseCA(pCA->GetCAType()), // likely always enterprise, tho
TRUE, // write it to the DS
CS_UPGRADE_WIN2000);
_JumpIfError(hr, error, "csiUpgradeCertSrvSecurity");
hr = AddCAMachineToCertPublishers();
_JumpIfError(hr, error, "AddCAMachineToCertPublishers");
if (RestartService(hwndMain, pCA->m_pParentMachine))
{
// notify views: refresh service toolbar buttons
m_pConsole->UpdateAllViews(
lpDataObject,
0,
0);
}
error:
if (hr != S_OK)
DisplayGenericCertSrvError(m_pConsole, hr);
}
}
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;
// 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;
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
{
DisplayGenericCertSrvError(hwnd, hr);
}
}
}
}
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
{
// audit 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 advanced server
if(pFolder->m_pCertCA->m_pParentMachine->FIsWhistlerMachine() && pFolder->m_pCertCA->FIsAdvancedServer())
{
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;
// 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)
{
TASKITEM* pm = 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 (; pm->myitem.item.strName; pm++)
{
// does it match scope/result type?
if (fResultItem != ((pm->dwFlags & TASKITEM_FLAG_RESULTITEM) != 0) )
continue;
// does it match area it should be in?
// for each task, insert if matches the current folder
if ((pm->type != SERVERFUNC_ALL_FOLDERS) && (folderType != pm->type))
continue;
hr = pContextMenuCallback->AddItem(&pm->myitem.item);
_JumpIfError(hr, Ret, "AddItem");
}
}
}
// 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
TASKITEM* pm = taskItems;
BOOL fRunningLocally = m_pCertMachine->IsLocalMachine();
BOOL fSvcRunning = m_pCertMachine->IsCertSvrServiceRunning();
if ( IsAllowedStartStop(pFolder, m_pCertMachine) )
AddStartStopTasks(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 = IsCurrentUserBuiltinAdmin(&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;
// insert all other tasks per folder
for (; pm->myitem.item.strName; pm++)
{
// does it match scope/result type?
if (fResultItem != ((pm->dwFlags & TASKITEM_FLAG_RESULTITEM) != 0))
continue;
// are we remote, and is it marked localonly? (not yes/no like other tests here)
if (((pm->dwFlags & TASKITEM_FLAG_LOCALONLY)) && (!fRunningLocally))
continue;
// does it match area it should be in?
// for each task, insert if matches the current folder
if ((pm->type != SERVERFUNC_ALL_FOLDERS) && (folderType != pm->type))
continue;
// is this task supposed to be hidden?
if (MFS_HIDDEN == pm->myitem.item.fFlags)
continue;
hr = pContextMenuCallback->AddItem(&pm->myitem.item);
_JumpIfError(hr, Ret, "AddItem");
}
}
Ret:
FREE_DATA(pInternal);
return hr;
}
BOOL CComponentDataImpl::AddStartStopTasks(
LPCONTEXTMENUCALLBACK pContextMenuCallback,
BOOL fSvcRunning)
{
HRESULT hr;
MY_CONTEXTMENUITEM* pm = taskStartStop;
pm[ENUM_TASK_START].item.fFlags = fSvcRunning ? MF_GRAYED : MF_ENABLED;
hr = pContextMenuCallback->AddItem(&pm[ENUM_TASK_START].item);
_JumpIfError(hr, Ret, "AddItem");
pm[ENUM_TASK_STOP].item.fFlags = fSvcRunning ? 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"%s\\certreq.exe -config \"%s\"", 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;
}