// 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 #include "genpage.h" #include #define __dwFILE__ __dwFILE_CAPESNPN_COMPDATA_CPP__ // Array of menu item commands to be inserted into the contest menu. // Note - the first item is the menu text, // CCM_SPECIAL_DEFAULT_ITEM // the second item is the status string /////////////////////////////////////////////////////////////////////////////// // 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 m_fAdvancedServer(false), m_hrCreateFolder(S_OK) { DEBUG_INCREMENT_INSTANCE_COUNTER(CComponentDataImpl); #ifdef _DEBUG m_cDataObjects = 0; #endif } CComponentDataImpl::~CComponentDataImpl() { DEBUG_DECREMENT_INSTANCE_COUNTER(CComponentDataImpl); ASSERT(m_pScope == NULL); ASSERT(!m_bInitializedCD || m_bDestroyedCD); // Some snap-in is hanging on to data objects. // If they access, it will crash!!! ASSERT(m_cDataObjects <= 1); } STDMETHODIMP CComponentDataImpl::Initialize(LPUNKNOWN pUnknown) { DBX_PRINT(_T(" ---------- CComponentDataImpl::Initialize<0x08x>\n"), this); #if DBG m_bInitializedCD = true; #endif ASSERT(pUnknown != NULL); HRESULT hr; AFX_MANAGE_STATE(AfxGetStaticModuleState()); // MMC should only call ::Initialize once! ASSERT(m_pScope == NULL); pUnknown->QueryInterface(IID_IConsoleNameSpace, reinterpret_cast(&m_pScope)); // add the images for the scope tree ::CBitmap bmp16x16; LPIMAGELIST lpScopeImage; hr = pUnknown->QueryInterface(IID_IConsole2, reinterpret_cast(&m_pConsole)); ASSERT(hr == S_OK); hr = m_pConsole->QueryScopeImageList(&lpScopeImage); ASSERT(hr == S_OK); // Load the bitmaps from the dll bmp16x16.LoadBitmap(IDB_16x16); // Set the images lpScopeImage->ImageListSetStrip(reinterpret_cast(static_cast(bmp16x16)), reinterpret_cast(static_cast(bmp16x16)), 0, RGB(255, 0, 255)); lpScopeImage->Release(); // Add any init code here NOT based on info from .MSC file return S_OK; } STDMETHODIMP CComponentDataImpl::CreateComponent(LPCOMPONENT* ppComponent) { ASSERT(ppComponent != NULL); CComObject* pObject; CComObject::CreateInstance(&pObject); ASSERT(pObject != NULL); // Store IComponentData pObject->SetIComponentData(this); return pObject->QueryInterface(IID_IComponent, reinterpret_cast(ppComponent)); } STDMETHODIMP CComponentDataImpl::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param) { ASSERT(m_pScope != NULL); HRESULT hr = S_OK; HWND hwndConsole; AFX_MANAGE_STATE(AfxGetStaticModuleState()); INTERNAL* pInternal; MMC_COOKIE cookie; // Since it's my folder it has an internal format. // Design Note: for extension. I can use the fact, that the data object doesn't have // my internal format and I should look at the node type and see how to extend it. // switch on events where we don't care about pInternal->m_cookie switch(event) { case MMCN_PROPERTY_CHANGE: hr = OnProperties(param); goto Ret; case MMCN_EXPAND: hr = OnExpand(lpDataObject, arg, param); goto Ret; default: break; } // handle cases where we do care about pInternal->m_cookie pInternal = ExtractInternalFormat(lpDataObject); if (pInternal == NULL) return S_OK; cookie = pInternal->m_cookie; ::GlobalFree(reinterpret_cast(pInternal)); switch(event) { case 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; default: break; } Ret: return hr; } STDMETHODIMP CComponentDataImpl::Destroy() { DBX_PRINT(_T(" ---------- CComponentDataImpl::Destroy<0x08x>\n"), this); ASSERT(m_bInitializedCD); #if DBG m_bDestroyedCD = true; #endif // Delete enumerated scope items DeleteList(); SAFE_RELEASE(m_pScope); SAFE_RELEASE(m_pConsole); 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 = GetItemType(cookie); ASSERT(dwItemType == SCOPE_LEVEL_ITEM); //ASSERT((dwItemType == SCOPE_LEVEL_ITEM) || (dwItemType == CA_LEVEL_ITEM)); } #endif return _QueryDataObject(cookie, type, this, ppDataObject); } /////////////////////////////////////////////////////////////////////////////// //// ISnapinHelp interface STDMETHODIMP CComponentDataImpl::GetHelpTopic(LPOLESTR* lpCompiledHelpFile) { if (lpCompiledHelpFile == NULL) return E_POINTER; UINT cbWindows = 0; WCHAR szWindows[MAX_PATH+1]; cbWindows = GetSystemWindowsDirectory(szWindows, MAX_PATH); if (cbWindows == 0) return S_FALSE; cbWindows += wcslen(HTMLHELP_COLLECTION_FILENAME); cbWindows++; // include null term cbWindows *= sizeof(WCHAR); // make this bytes, not chars *lpCompiledHelpFile = (LPOLESTR) CoTaskMemAlloc(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+1]; cbWindows = GetSystemWindowsDirectory(szWindows, MAX_PATH); if (cbWindows == 0) return S_FALSE; cbWindows += wcslen(HTMLHELP_COLLECTIONLINK_FILENAME); cbWindows++; // include null term cbWindows *= sizeof(WCHAR); // make this bytes, not chars *lpCompiledHelpFiles = (LPOLESTR) CoTaskMemAlloc(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_CAPolicyExtensionSnapIn; return E_NOTIMPL; } */ STDMETHODIMP CComponentDataImpl::IsDirty() { // Always save / Always dirty. return ThisIsDirty() ? S_OK : S_FALSE; } STDMETHODIMP CComponentDataImpl::Load(IStream *pStm) { DBX_PRINT(_T(" ---------- CComponentDataImpl::Load<0x08x>\n"), this); ASSERT(pStm); ASSERT(m_bInitializedCD); // Read the string DWORD dwVer; ULONG nBytesRead; HRESULT hr = pStm->Read(&dwVer, sizeof(DWORD), &nBytesRead); // Verify that the read succeeded ASSERT(SUCCEEDED(hr) && nBytesRead == sizeof(DWORD)); // check to see if this is the correct version if (dwVer != 0x1) { return STG_E_OLDFORMAT; } ClearDirty(); return SUCCEEDED(hr) ? S_OK : E_FAIL; } STDMETHODIMP CComponentDataImpl::Save(IStream *pStm, BOOL fClearDirty) { DBX_PRINT(_T(" ---------- CComponentDataImpl::Save<0x08x>\n"), this); ASSERT(pStm); ASSERT(m_bInitializedCD); // Write the string ULONG nBytesWritten; DWORD dwVer = 0x1; HRESULT hr = pStm->Write(&dwVer, sizeof(DWORD), &nBytesWritten); // Verify that the write operation succeeded ASSERT(SUCCEEDED(hr) && nBytesWritten == sizeof(DWORD)); if (FAILED(hr)) return STG_E_CANTSAVE; if (fClearDirty) ClearDirty(); return S_OK; } STDMETHODIMP CComponentDataImpl::GetSizeMax(ULARGE_INTEGER *pcbSize) { ASSERT(pcbSize); DWORD cbSize; cbSize = sizeof(DWORD); // version // Set the size of the string to be saved ULISet32(*pcbSize, cbSize); 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) { if (arg == 0) return S_OK; LPOLESTR pszNewName = reinterpret_cast(param); if (pszNewName == NULL) return E_INVALIDARG; CFolder* pFolder = reinterpret_cast(cookie); ASSERT(pFolder != NULL); if (pFolder == NULL) return E_INVALIDARG; pFolder->SetName(pszNewName); return S_OK; } HRESULT CComponentDataImpl::OnExpand(LPDATAOBJECT lpDataObject, LPARAM arg, LPARAM param) { HRESULT hr = S_OK; GUID* pNodeGUID = NULL; CFolder* pFolder=NULL; bool fInsertFolder = false; STGMEDIUM stgmediumNodeType = { TYMED_HGLOBAL, NULL }; STGMEDIUM stgmediumCAType = { TYMED_HGLOBAL, NULL }; STGMEDIUM stgmediumCAName = { TYMED_HGLOBAL, NULL }; STGMEDIUM stgmediumCARoles = { TYMED_HGLOBAL, NULL }; LPWSTR pszDSName = NULL; if (arg == TRUE) { // Did Initialize get called? ASSERT(m_pScope != NULL); // // get the guid of the current node // UINT s_cfNodeType; s_cfNodeType = RegisterClipboardFormat(W2T(CCF_NODETYPE)); FORMATETC formatetcNodeType = { (CLIPFORMAT)s_cfNodeType, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; hr = lpDataObject->GetDataHere(&formatetcNodeType, &stgmediumNodeType); _JumpIfError(hr, Ret, "GetDataHere NodeType"); pNodeGUID = (GUID*) GlobalLock(stgmediumNodeType.hGlobal); if (pNodeGUID == NULL) { hr = E_UNEXPECTED; _JumpError(hr, Ret, "GlobalLock failed"); } // // if this is the parents node then add our node undeneath it // // CA Manager parent if (memcmp(pNodeGUID, (void *)&cCAManagerParentNodeID, sizeof(GUID)) == 0) { fInsertFolder = true; CString szFolderName; // Only add node under ENT ROOT, ENT SUB UINT cfCAType = RegisterClipboardFormat(W2T((LPWSTR)SNAPIN_CA_INSTALL_TYPE)); FORMATETC formatetcCAType = { (CLIPFORMAT)cfCAType, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; hr = lpDataObject->GetDataHere(&formatetcCAType, &stgmediumCAType); _JumpIfError(hr, Ret, "GetDataHere CAType"); PDWORD rgdw = (DWORD*)GlobalLock(stgmediumCAType.hGlobal); ENUM_CATYPES caType = (ENUM_CATYPES)rgdw[0]; DBGPRINT((DBG_SS_CERTMMC, "CA Type: %d\n", caType)); // return immediately if we're not an ENT {ROOT | SUB} if ((caType != ENUM_ENTERPRISE_SUBCA) && (caType != ENUM_ENTERPRISE_ROOTCA)) { hr = S_OK; goto Ret; } m_fAdvancedServer = (rgdw[1]!=0)?true:false; DBGPRINT((DBG_SS_CERTMMC, "Advanced Server: %hs\n", m_fAdvancedServer?"yes":"no")); VERIFY(szFolderName.LoadString(IDS_POLICYSETTINGS)); pFolder = new CFolder(); if(pFolder == NULL) { hr = E_OUTOFMEMORY; goto Ret; } pFolder->Create( (LPWSTR)((LPCTSTR)szFolderName), IMGINDEX_FOLDER, IMGINDEX_FOLDER_OPEN, SCOPE_LEVEL_ITEM, POLICYSETTINGS, FALSE); m_scopeItemList.AddTail(pFolder); pFolder->m_pScopeItem->relativeID = param; // Set the folder as the cookie pFolder->m_pScopeItem->mask |= SDI_PARAM; pFolder->m_pScopeItem->lParam = reinterpret_cast(pFolder); pFolder->SetCookie(reinterpret_cast(pFolder)); // get the name of the CA that we are administering LPWSTR pCAName = NULL; // nab CA Name UINT cfCAName = RegisterClipboardFormat(W2T((LPWSTR)CA_SANITIZED_NAME)); FORMATETC formatetcCAName = { (CLIPFORMAT)cfCAName, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; hr = lpDataObject->GetDataHere(&formatetcCAName, &stgmediumCAName); _JumpIfError(hr, Ret, "GetDataHere CAName"); pCAName = (LPWSTR)GlobalLock(stgmediumCAName.hGlobal); if (pCAName == NULL) { hr = E_UNEXPECTED; _JumpError(hr, Ret, "GlobalLock"); } pFolder->m_szCAName = pCAName; hr = mySanitizedNameToDSName(pCAName, &pszDSName); _JumpIfError(hr, Ret, "mySanitizedNameToDSName"); // Get current user's roles DWORD* pdwRoles; UINT cfCARoles = RegisterClipboardFormat(W2T((LPWSTR)CA_ROLES)); FORMATETC formatetcCARoles = { (CLIPFORMAT)cfCARoles, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; hr = lpDataObject->GetDataHere(&formatetcCARoles, &stgmediumCARoles); _JumpIfError(hr, Ret, "GetDataHere CAName"); pdwRoles = (DWORD*)GlobalLock(stgmediumCARoles.hGlobal); if (pdwRoles == NULL) { hr = E_UNEXPECTED; _JumpError(hr, Ret, "GlobalLock"); } pFolder->m_dwRoles = *pdwRoles; DBGPRINT((DBG_SS_CERTMMC, "Roles: 0x%08x\n", *pdwRoles)); // // get a handle to the CA based on the name // hr = CAFindByName( pszDSName, NULL, CA_FIND_INCLUDE_UNTRUSTED, &pFolder->m_hCAInfo); _JumpIfErrorStr(hr, Ret, "CAFindByName", pszDSName); // if we made it here then everything is initialized, so add the folder } } // Note - On return, the ID member of 'm_pScopeItem' // contains the handle to the newly inserted item! ASSERT(pFolder->m_pScopeItem->ID != NULL); Ret: // undo fix to add folder under all circumstances -- we were // inserting a NULL ptr! if(fInsertFolder && (NULL != pFolder)) { m_hrCreateFolder = hr; m_pScope->InsertItem(pFolder->m_pScopeItem); } if (stgmediumNodeType.hGlobal) { GlobalUnlock(stgmediumNodeType.hGlobal); ReleaseStgMedium(&stgmediumNodeType); } if (stgmediumCAType.hGlobal) { GlobalUnlock(stgmediumCAType.hGlobal); ReleaseStgMedium(&stgmediumCAType); } if (stgmediumCAName.hGlobal) { GlobalUnlock(stgmediumCAName.hGlobal); ReleaseStgMedium(&stgmediumCAName); } if (stgmediumCARoles.hGlobal) { GlobalUnlock(stgmediumCARoles.hGlobal); ReleaseStgMedium(&stgmediumCARoles); } if (pszDSName) LocalFree(pszDSName); return hr; } HRESULT CComponentDataImpl::OnSelect(MMC_COOKIE cookie, LPARAM arg, LPARAM param) { return E_UNEXPECTED; } HRESULT CComponentDataImpl::OnProperties(LPARAM param) { HRESULT hr = S_OK; CFolder* pItem = NULL; CFolder* pFolder = NULL; POSITION pos = 0; if (param == NULL) { goto error; } ASSERT(param != NULL); pFolder = new CFolder(); if(pFolder == NULL) { hr = E_OUTOFMEMORY; goto error; } // Create a new folder object pFolder->Create( reinterpret_cast(param), 0, 0, SCOPE_LEVEL_ITEM, STATIC, FALSE); // The static folder in the last item in the list pos = m_scopeItemList.GetTailPosition(); ASSERT(pos); // Add it to the internal list if (pos) { pItem = m_scopeItemList.GetAt(pos); if(pItem == NULL) { hr = E_OUTOFMEMORY; goto error; } m_scopeItemList.AddTail(pFolder); if((pFolder->m_pScopeItem == NULL) || (pItem->m_pScopeItem == NULL)) { hr = E_POINTER; goto error; } pFolder->m_pScopeItem->relativeID = pItem->m_pScopeItem->relativeID; // Set the folder as the cookie pFolder->m_pScopeItem->mask |= SDI_PARAM; pFolder->m_pScopeItem->lParam = reinterpret_cast(pFolder); pFolder->SetCookie(reinterpret_cast(pFolder)); m_pScope->InsertItem(pFolder->m_pScopeItem); pFolder = NULL; } ::GlobalFree(reinterpret_cast(param)); error: if(pFolder) { delete pFolder; } return hr; } void CComponentDataImpl::DeleteList() { POSITION pos = m_scopeItemList.GetHeadPosition(); while (pos) delete m_scopeItemList.GetNext(pos); m_scopeItemList.RemoveAll(); } 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) { // // if this is certtype folder, and it is for the second column, then add usages string // if (FALSE)//(pFolder->m_hCertType != NULL) && (pScopeDataItem-> == )) { } else { pScopeDataItem->displayname = pFolder->m_pszName; } } if (pScopeDataItem->mask & SDI_IMAGE) pScopeDataItem->nImage = pFolder->m_pScopeItem->nImage; if (pScopeDataItem->mask & SDI_OPENIMAGE) pScopeDataItem->nOpenImage = pFolder->m_pScopeItem->nOpenImage; return S_OK; } STDMETHODIMP CComponentDataImpl::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB) { if (lpDataObjectA == NULL || lpDataObjectB == NULL) return E_POINTER; // Make sure both data object are mine INTERNAL* pA; INTERNAL* pB; HRESULT hr = S_FALSE; pA = ExtractInternalFormat(lpDataObjectA); pB = ExtractInternalFormat(lpDataObjectA); if (pA != NULL && pB != NULL) hr = (*pA == *pB) ? S_OK : S_FALSE; if(pA != NULL) { ::GlobalFree(reinterpret_cast(pA)); } if(pB != NULL) { ::GlobalFree(reinterpret_cast(pB)); } return hr; } ///////////////////////////////////////////////////////////////////////////// // IExtendPropertySheet Implementation STDMETHODIMP CComponentDataImpl::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider, LONG_PTR handle, LPDATAOBJECT lpIDataObject) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); // Look at the data object and determine if this an extension or a primary ASSERT(lpIDataObject != NULL); #if DBG CLSID* pCoClassID = ExtractClassID(lpIDataObject); if(pCoClassID == NULL) { ASSERT(FALSE); return E_UNEXPECTED; } // Which page is needed? (determined by which node is active) ASSERT(IsEqualCLSID(*pCoClassID, GetCoClassID())); FREE_DATA(pCoClassID); #endif PropertyPage* pBasePage; INTERNAL* pInternal = ExtractInternalFormat(lpIDataObject); if (pInternal == NULL) { return S_OK; } ASSERT(pInternal->m_type == CCT_SCOPE); ASSERT(pInternal->m_cookie); CFolder* pFolder = reinterpret_cast(pInternal->m_cookie); ASSERT(pFolder != NULL); if (pFolder == NULL) return E_INVALIDARG; // switch (pFolder->m_type) return S_OK; } STDMETHODIMP CComponentDataImpl::QueryPagesFor(LPDATAOBJECT lpDataObject) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); // Get the node type and see if it's one of mine BOOL bResult = FALSE; INTERNAL* pInternal = ExtractInternalFormat(lpDataObject); if (pInternal == NULL) { return S_OK; } ASSERT(pInternal); ASSERT(pInternal->m_cookie); CFolder* pFolder = reinterpret_cast(pInternal->m_cookie); switch(pFolder->m_type) { case POLICYSETTINGS: case SCE_EXTENSION: bResult = TRUE; break; default: bResult = FALSE; break; } FREE_DATA(pInternal); return (bResult) ? S_OK : S_FALSE; } /////////////////////////////////////////////////////////////////////////////// // IExtendContextMenu implementation // STDMETHODIMP CComponentDataImpl::AddMenuItems(LPDATAOBJECT pDataObject, LPCONTEXTMENUCALLBACK pContextMenuCallback, long *pInsertionAllowed) { HRESULT hr = S_OK; CONTEXTMENUITEM menuItem; CString szMenu; CString szHint; AFX_MANAGE_STATE(AfxGetStaticModuleState()); // 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. if (IsMMCMultiSelectDataObject(pDataObject) == TRUE) return S_FALSE; INTERNAL* pInternal = ExtractInternalFormat(pDataObject); if (pInternal == NULL) { return S_OK; } CFolder* pFolder = reinterpret_cast(pInternal->m_cookie); if (*pInsertionAllowed & CCM_INSERTIONALLOWED_NEW) { ::ZeroMemory (&menuItem, sizeof (menuItem)); menuItem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_NEW; menuItem.fFlags = 0; menuItem.fSpecialFlags = 0; switch(pFolder->m_type) { case POLICYSETTINGS: VERIFY (szMenu.LoadString (IDS_CERTIFICATE_TYPE)); menuItem.strName = (LPTSTR)(LPCTSTR) szMenu; VERIFY (szHint.LoadString (IDS_CERTIFICATE_TYPE_HINT)); menuItem.strStatusBarText = (LPTSTR)(LPCTSTR) szHint; menuItem.lCommandID = IDM_NEW_CERTTYPE; // only CA admins or user with DS write access // can modify CA template list if(!(CA_ACCESS_ADMIN & pFolder->GetRoles()) && !g_fCurrentUserHasDSWriteAccess) menuItem.fFlags = MFS_GRAYED; // bug 462320: for SUB CA, right after installing the CA cert, CA info is unavailable, // so there is no way to enable new certs. if(!pFolder->m_hCAInfo) menuItem.fFlags = MFS_GRAYED; hr = pContextMenuCallback->AddItem (&menuItem); ASSERT (SUCCEEDED (hr)); break; default: break; } } if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP) { ::ZeroMemory (&menuItem, sizeof (menuItem)); menuItem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TOP; menuItem.fFlags = 0; menuItem.fSpecialFlags = 0; switch(pFolder->m_type) { case POLICYSETTINGS: VERIFY (szMenu.LoadString (IDS_MANAGETASK)); menuItem.strName = (LPTSTR)(LPCTSTR) szMenu; VERIFY (szHint.LoadString (IDS_MANAGETASK_HINT)); menuItem.strStatusBarText = (LPTSTR)(LPCTSTR) szHint; menuItem.lCommandID = IDM_MANAGE; hr = pContextMenuCallback->AddItem (&menuItem); ASSERT (SUCCEEDED (hr)); break; } } return hr; } 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. DWORD dwErr; HCERTTYPE hNewCertType; HWND hwndConsole; AFX_MANAGE_STATE(AfxGetStaticModuleState()); INTERNAL* pi = ExtractInternalFormat(pDataObject); if(pi == NULL) { return E_POINTER; } ASSERT(pi); ASSERT(pi->m_type == CCT_SCOPE); CFolder* pFolder = reinterpret_cast(pi->m_cookie); // Handle each of the commands. switch (nCommandID) { case IDM_NEW_CERTTYPE: { if (pFolder) { switch(pFolder->m_type) { case POLICYSETTINGS: { // NOMFC CCertTemplateSelectDialog TemplateSelectDialog; TemplateSelectDialog.SetCA(pFolder->m_hCAInfo, m_fAdvancedServer); // if fails, NULL will work HWND hWnd = NULL; m_pConsole->GetMainWindow(&hWnd); DialogBoxParam( g_hInstance, MAKEINTRESOURCE(IDD_SELECT_CERTIFICATE_TEMPLATE), hWnd, SelectCertTemplateDialogProc, (LPARAM)&TemplateSelectDialog); break; } default: break; } } m_pConsole->UpdateAllViews(pDataObject, 0, 0); break; } case IDM_MANAGE: if (pFolder && pFolder->m_type == POLICYSETTINGS) { StartCertificateTemplatesSnapin(); } break; default: ASSERT(FALSE); // Unknown command! break; } return S_OK; } HRESULT CComponentDataImpl::StartCertificateTemplatesSnapin() { HRESULT hr = S_OK; SHELLEXECUTEINFO shi; HWND hwnd = NULL; m_pConsole->GetMainWindow(&hwnd); ZeroMemory(&shi, sizeof(shi)); shi.cbSize = sizeof(shi); shi.hwnd = hwnd; shi.lpVerb = SZ_VERB_OPEN; shi.lpFile = SZ_CERTTMPL_MSC; shi.fMask = SEE_MASK_FLAG_NO_UI; if(!ShellExecuteEx(&shi)) { hr = myHLastError(); _JumpError(hr, error, "ShellExecuteEx"); } error: return hr; }