You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1018 lines
28 KiB
1018 lines
28 KiB
// 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 <sceattch.h>
|
|
#include "genpage.h"
|
|
|
|
#include <atlimpl.cpp>
|
|
|
|
#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<void**>(&m_pScope));
|
|
|
|
// add the images for the scope tree
|
|
::CBitmap bmp16x16;
|
|
LPIMAGELIST lpScopeImage;
|
|
|
|
hr = pUnknown->QueryInterface(IID_IConsole2, reinterpret_cast<void**>(&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<LONG_PTR *>(static_cast<HBITMAP>(bmp16x16)),
|
|
reinterpret_cast<LONG_PTR *>(static_cast<HBITMAP>(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<CSnapin>* pObject;
|
|
CComObject<CSnapin>::CreateInstance(&pObject);
|
|
ASSERT(pObject != NULL);
|
|
|
|
// Store IComponentData
|
|
pObject->SetIComponentData(this);
|
|
|
|
return pObject->QueryInterface(IID_IComponent,
|
|
reinterpret_cast<void**>(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<HANDLE>(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<LPOLESTR>(param);
|
|
if (pszNewName == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
CFolder* pFolder = reinterpret_cast<CFolder*>(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<LPARAM>(pFolder);
|
|
pFolder->SetCookie(reinterpret_cast<LONG_PTR>(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<LPOLESTR>(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<LPARAM>(pFolder);
|
|
pFolder->SetCookie(reinterpret_cast<LONG_PTR>(pFolder));
|
|
m_pScope->InsertItem(pFolder->m_pScopeItem);
|
|
pFolder = NULL;
|
|
}
|
|
|
|
::GlobalFree(reinterpret_cast<void*>(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<CFolder*>(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<HANDLE>(pA));
|
|
}
|
|
|
|
if(pB != NULL)
|
|
{
|
|
::GlobalFree(reinterpret_cast<HANDLE>(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<CFolder*>(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<CFolder*>(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<CFolder*>(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<CFolder*>(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;
|
|
}
|