WindowsXP-SP1/admin/activec/nodemgr/doccnfg.cpp
2020-09-30 16:53:49 +02:00

552 lines
15 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1999 - 1999
//
// File: doccnfg.cpp
//
//--------------------------------------------------------------------------
#include "stdafx.h"
#include "doccnfg.h"
#include "comdbg.h"
/////////////////////////////////////////////////////////////////////////////
//
// external references
extern const wchar_t* AMCSnapInCacheStreamName;
/////////////////////////////////////////////////////////////////////////////
//
// Class CMMCDocConfig implementation
CMMCDocConfig::~CMMCDocConfig()
{
if (IsFileOpen())
CloseFile();
}
STDMETHODIMP CMMCDocConfig::InterfaceSupportsErrorInfo(REFIID riid)
{
return (InlineIsEqualGUID(IID_IDocConfig, riid)) ? S_OK : S_FALSE;
}
STDMETHODIMP CMMCDocConfig::OpenFile(BSTR bstrFilePath)
{
return ScOpenFile( bstrFilePath ).ToHr();
}
STDMETHODIMP CMMCDocConfig::CloseFile()
{
return ScCloseFile().ToHr();
}
STDMETHODIMP CMMCDocConfig::SaveFile(BSTR bstrFilePath)
{
return ScSaveFile(bstrFilePath).ToHr();
}
STDMETHODIMP CMMCDocConfig::EnableSnapInExtension(BSTR bstrSnapIn, BSTR bstrExt, VARIANT_BOOL bEnable)
{
return ScEnableSnapInExtension(bstrSnapIn, bstrExt, bEnable).ToHr();
}
/*+-------------------------------------------------------------------------*
* CMMCDocConfig::Dump
*
*
*--------------------------------------------------------------------------*/
STDMETHODIMP CMMCDocConfig::Dump (LPCTSTR pszDumpFilePath)
{
return ScDump (pszDumpFilePath).ToHr();
}
/*+-------------------------------------------------------------------------*
* CMMCDocConfig::CheckSnapinAvailability
*
*
*--------------------------------------------------------------------------*/
STDMETHODIMP CMMCDocConfig::CheckSnapinAvailability (CAvailableSnapinInfo& asi)
{
return ScCheckSnapinAvailability(asi).ToHr();
}
/***************************************************************************\
*
* METHOD: CMMCDocConfig::ScOpenFile
*
* PURPOSE: Opens the specified console file and reads snapin cache from it
*
* PARAMETERS:
* BSTR bstrFilePath [in] file name to read from
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CMMCDocConfig::ScOpenFile(BSTR bstrFilePath)
{
DECLARE_SC(sc, TEXT("CMMCDocConfig::ScOpenFile"));
// Close currently open file
if (IsFileOpen())
{
sc = ScCloseFile();
if (sc)
sc.TraceAndClear(); // report the error and ignore
}
// parameter check
if (bstrFilePath == NULL || SysStringLen(bstrFilePath) == 0)
return sc = E_INVALIDARG;
USES_CONVERSION;
LPCTSTR lpstrFilePath = OLE2CT(bstrFilePath);
// create object to load the snapins
CAutoPtr<CSnapInsCache> spSnapInsCache( new CSnapInsCache );
sc = ScCheckPointers( spSnapInsCache, E_OUTOFMEMORY );
if (sc)
return sc;
// load the data (use bas class method)
bool bXmlBased = false;
CXMLDocument xmlDocument;
IStoragePtr spStorage;
sc = ScLoadConsole( lpstrFilePath, bXmlBased, xmlDocument, &spStorage );
if (sc)
return sc;
// examine file type
if ( !bXmlBased )
{
// structured storage - based console
IStreamPtr spStream;
sc = OpenDebugStream(spStorage, AMCSnapInCacheStreamName,
STGM_SHARE_EXCLUSIVE | STGM_READWRITE, L"SnapInCache", &spStream);
if (sc)
return sc;
sc = spSnapInsCache->ScLoad(spStream);
if (sc)
return sc;
m_spStorage = spStorage;
}
else
{
// xml - based console
try // xml implementation throws sc's
{
// construct parent document
CXMLElement elemDoc = xmlDocument;
CPersistor persistorFile(xmlDocument, elemDoc);
// init
persistorFile.SetLoading(true);
// navigate to snapin cache
CPersistor persistorConsole ( persistorFile, XML_TAG_MMC_CONSOLE_FILE );
CPersistor persistorTree ( persistorConsole, XML_TAG_SCOPE_TREE );
// load
persistorTree.Persist(*spSnapInsCache);
// hold onto the persistor info
m_XMLDocument = persistorConsole.GetDocument();
m_XMLElemConsole = persistorConsole.GetCurrentElement();
m_XMLElemTree = persistorTree.GetCurrentElement();
}
catch(SC& sc_thrown)
{
return (sc = sc_thrown);
}
}
// keep on the pointer
m_spCache.Attach( spSnapInsCache.Detach() );
m_strFilePath = lpstrFilePath;
return sc;
}
/***************************************************************************\
*
* METHOD: CMMCDocConfig::ScCloseFile
*
* PURPOSE: closes open file
*
* PARAMETERS:
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CMMCDocConfig::ScCloseFile()
{
DECLARE_SC(sc, TEXT("CMMCDocConfig::ScCloseFile"));
if (!IsFileOpen())
return sc = E_UNEXPECTED;
// release everything
m_spStorage = NULL;
m_strFilePath.erase();
m_spCache.Delete();
m_XMLDocument = CXMLDocument();
m_XMLElemConsole = CXMLElement();
m_XMLElemTree = CXMLElement();
return sc;
}
/***************************************************************************\
*
* METHOD: ScFindAndTruncateChild
*
* PURPOSE: helper; locates the element by tag and removes all element's contents
* Doing so instead of deleting and recreating the element preserves all
* the formating and tag order in xml document
*
* PARAMETERS:
* CPersistor& parent [in] - parent persistor
* LPCTSTR strTag [in] - child's tag
* CXMLElement& child [out] - child's element
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC ScFindAndTruncateChild(CPersistor& parent, LPCTSTR strTag, CXMLElement& child)
{
DECLARE_SC(sc, TEXT("ScTruncateChild"));
try
{
// create persistor for the old cache tag
parent.SetLoading(true); // we want 'loading-alike' navigation
CPersistor persistorChild( parent, strTag );
parent.SetLoading(false); // restore saving behavior
// get the element
CXMLElement elChild = persistorChild.GetCurrentElement();
// get nodes under the element
CXMLElementCollection colChildren;
elChild.get_children( &colChildren );
long count = 0;
colChildren.get_count( &count );
// iterate and delete all the nodes
while (count > 0)
{
CXMLElement el;
colChildren.item( 0, &el);
elChild.removeChild(el);
--count;
}
// return the element
child = elChild;
}
catch(SC& sc_thrown)
{
return (sc = sc_thrown);
}
return sc;
}
/***************************************************************************\
*
* METHOD: CMMCDocConfig::ScSaveFile
*
* PURPOSE: Saves file to specified location
*
* PARAMETERS:
* BSTR bstrFilePath [in] file path to save to. NULL -> same as load
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CMMCDocConfig::ScSaveFile(BSTR bstrFilePath)
{
DECLARE_SC(sc, TEXT("CMMCDocConfig::ScSaveFile"));
if (!IsFileOpen() || m_spCache == NULL)
return sc = E_UNEXPECTED;
USES_CONVERSION;
// if new path specified, save local copy as new default
if ( bstrFilePath && SysStringLen(bstrFilePath) != 0)
m_strFilePath = OLE2CT(bstrFilePath);
// remove extensions marked for deletion
m_spCache->Purge(TRUE);
if ( m_spStorage != NULL ) // not the XML way?
{
// replace snapin cache stream with new cache contents
IStreamPtr spStream;
sc = CreateDebugStream(m_spStorage, AMCSnapInCacheStreamName,
STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, L"SnapInCache", &spStream);
if (sc)
return sc;
// save the cache
sc = m_spCache->ScSave(spStream, TRUE);
if (sc)
return sc;
// Create storage for the requested file
IStoragePtr spNewStorage;
sc = CreateDebugDocfile( T2COLE( m_strFilePath.c_str() ),
STGM_DIRECT | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE,
&spNewStorage);
if (sc)
return sc;
// copy the working storage to the new file
sc = m_spStorage->CopyTo(NULL, NULL, NULL, spNewStorage);
if (sc)
return sc;
// lets hold on the new one
m_spStorage = spNewStorage;
}
else
{
try // may throw
{
// save the data
CPersistor persistorTree( m_XMLDocument, m_XMLElemTree );
// this is more tricky than loading - we want to reuse the same tag
CXMLElement elCache;
sc = ScFindAndTruncateChild(persistorTree, m_spCache->GetXMLType(), elCache);
if (sc)
return sc;
// create persistor for the new cache tag
CPersistor persistorCache( persistorTree, elCache );
// now persist under the new tag
m_spCache->Persist(persistorCache);
// update documents guid to invalidate user data
GUID guidConsoleId;
sc = CoCreateGuid(&guidConsoleId);
if (sc)
return sc;
// persistor for console
CPersistor persistorConsole ( m_XMLDocument, m_XMLElemConsole );
persistorConsole.SetLoading(false);
CXMLElement elGuid;
sc = ScFindAndTruncateChild(persistorConsole, XML_TAG_CONSOLE_FILE_UID, elGuid);
if (sc)
return sc;
// create persistor for the new guid tag
CPersistor persistorGuid( persistorConsole, elGuid );
// now persist under the new tag
persistorGuid.PersistContents(guidConsoleId);
//save to file
sc = ScSaveConsole( m_strFilePath.c_str(), true/*bForAuthorMode*/, m_XMLDocument);
if (sc)
return sc;
}
catch(SC& sc_thrown)
{
return (sc = sc_thrown);
}
}
return sc;
}
/***************************************************************************\
*
* METHOD: CMMCDocConfig::ScEnableSnapInExtension
*
* PURPOSE: Enables extension in snapin cache
*
* PARAMETERS:
* BSTR bstrSnapIn [in] classid of the snapin
* BSTR bstrExt [in] classid of extension
* VARIANT_BOOL bEnable [in] enable/disable flag
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CMMCDocConfig::ScEnableSnapInExtension(BSTR bstrSnapIn, BSTR bstrExt, VARIANT_BOOL bEnable)
{
DECLARE_SC(sc, TEXT("CMMCDocConfig::ScEnableSnapInExtension"));
CLSID SnapInCLSID;
CLSID ExtCLSID;
CSnapInPtr spBaseSnapIn;
CSnapInPtr spExtSnapIn;
// convert input strings to CLSIDs
sc = CLSIDFromString(bstrSnapIn, &SnapInCLSID);
if (sc)
return sc;
sc = CLSIDFromString( bstrExt, &ExtCLSID);
if (sc)
return sc;
// Locate base snap-in in cache
sc = m_spCache->ScFindSnapIn(SnapInCLSID, &spBaseSnapIn);
if (sc)
return sc = E_INVALIDARG;
// Check if extension is enabled
CExtSI* pExt = spBaseSnapIn->GetExtensionSnapIn();
while (pExt != NULL)
{
if (pExt->GetSnapIn()->GetSnapInCLSID() == ExtCLSID)
break;
pExt = pExt->Next();
}
// if extension is present and not marked for deletion
if (pExt != NULL && !pExt->IsMarkedForDeletion())
{
// If should be disabled, just mark deleted
if (!bEnable)
pExt->MarkDeleted(TRUE);
}
else
{
// if should be enabled
if (bEnable)
{
// if extension is present, just undelete
if (pExt != NULL)
{
pExt->MarkDeleted(FALSE);
}
else
{
// Find or create cache entry for extension snapin
sc = m_spCache->ScGetSnapIn(ExtCLSID, &spExtSnapIn);
if (sc)
return sc;
// Add as extension to base snapin
spBaseSnapIn->AddExtension(spExtSnapIn);
}
}
}
return sc;
}
/***************************************************************************\
*
* METHOD: CMMCDocConfig::ScDump
*
* PURPOSE: dumps contents of snapin cache
*
* PARAMETERS:
* LPCTSTR pszDumpFilePath [in] file to dump to
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CMMCDocConfig::ScDump (LPCTSTR pszDumpFilePath)
{
DECLARE_SC(sc, TEXT("CMMCDocConfig::ScDump"));
/*
* validate input
*/
sc = ScCheckPointers (pszDumpFilePath);
if (sc)
return sc;
if (pszDumpFilePath[0] == 0)
return sc = E_INVALIDARG;
/*
* make sure a file is open
*/
if (!IsFileOpen())
return ((sc = E_UNEXPECTED).ToHr());
sc = ScCheckPointers (m_spCache, E_UNEXPECTED);
if (sc)
return (sc.ToHr());
return (m_spCache->Dump (pszDumpFilePath));
}
/***************************************************************************\
*
* METHOD: CMMCDocConfig::ScCheckSnapinAvailability
*
* PURPOSE:
*
* PARAMETERS:
* BOOL f32bit [in] // check 32-bit (vs. 64-bit) snap-ins?
* UINT& cTotalSnapins [out] // total number of snap-ins referenced in the console file
* UINT& cAvailableSnapins [out] // number of snap-ins available in the requested memory model
*
* RETURNS:
* SC - result code
*
\***************************************************************************/
SC CMMCDocConfig::ScCheckSnapinAvailability (CAvailableSnapinInfo& asi)
{
DECLARE_SC(sc, TEXT("CMMCDocConfig::ScCheckSnapinAvailability"));
/*
* make sure a file is open
*/
if (!IsFileOpen())
return ((sc = E_UNEXPECTED).ToHr());
sc = ScCheckPointers (m_spCache, E_UNEXPECTED);
if (sc)
return sc;
sc = m_spCache->ScCheckSnapinAvailability (asi);
if (sc)
return sc;
return sc;
}