// 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 // database error #include #include #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 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(&m_pScope)); _JumpIfError(hr, Ret, "QueryInterface IID_IConsoleNameSpace2"); // add the images for the scope tree hr = pUnknown->QueryInterface(IID_IConsole2, reinterpret_cast(&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(static_cast(bmpResultStrip16x16)), reinterpret_cast(static_cast(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* pObject; CComObject::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(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(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; im_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; iGetCA()->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(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(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(pFolder); pFolder->SetCookie(reinterpret_cast(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(pFolder); pFolder->SetCookie(reinterpret_cast(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(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; iGetCaCount(); 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(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; }