|
|
//+-------------------------------------------------------------------------
//
// 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; }
|