|
|
/*--------------------------------------------------------------------------*
* * Microsoft Windows * Copyright (C) Microsoft Corporation, 1992 - 1999 * * File: siprop.cpp * * Contents: Implementation file for CSnapInPropertiesRoot, et al * * History: 04-Nov-99 jeffro Created * *--------------------------------------------------------------------------*/
#include "stdafx.h"
#include "siprop.h"
#include "variant.h"
#include "mtnode.h"
#ifdef DBG
CTraceTag tagSnapInProps(_T("Snap-in Properties"), _T("Snap-in Properties")); #endif
/*+=========================================================================*/ /* */ /* CSnapinPropertyComObject */ /* */ /*==========================================================================*/
/*+-------------------------------------------------------------------------*
* CSnapinPropertyComObject * * This is the COM object that exposes the Property object model interface. *--------------------------------------------------------------------------*/
class CSnapinPropertyComObject : public CMMCIDispatchImpl<Property>, // the Property interface
public CTiedComObject<CSnapinProperties> { typedef CSnapinProperties CMyTiedObject;
public: BEGIN_MMC_COM_MAP(CSnapinPropertyComObject) END_MMC_COM_MAP()
public: // Property interface
MMC_METHOD1_PARAM (get_Value, VARIANT* /*pvarValue*/, m_key); MMC_METHOD1_PARAM (put_Value, VARIANT /*varValue*/, m_key);
STDMETHODIMP get_Name (BSTR* pbstrName) { DECLARE_SC (sc, _T("CSnapinPropertyComObject::get_Name"));
/*
* validate parameters */ sc = ScCheckPointers (pbstrName); if (sc) return (sc.ToHr());
/*
* copy the name */ *pbstrName = SysAllocString (m_key.data()); if (*pbstrName == NULL) return ((sc = E_OUTOFMEMORY).ToHr());
return (sc.ToHr()); }
void SetKey (const CSnapinProperties::CPropertyKey& key) { m_key = key; }
private: CSnapinProperties::CPropertyKey m_key; };
/*+=========================================================================*/ /* */ /* CSnapinProperties implementation */ /* */ /*==========================================================================*/
/*+-------------------------------------------------------------------------*
* CSnapinProperties::FromInterface * * Returns a pointer to the CSnapinProperties object that implements * the given interface, or NULL if the implementing object is not a * CSnapinProperties. *--------------------------------------------------------------------------*/
CSnapinProperties* CSnapinProperties::FromInterface (IUnknown* pUnk) { CSnapinProperties* pProps;
/*
* dynamic_cast will throw if pUnk is junk (i.e. not a real interface * pointer and not NULL), so do it in an exception frame. */ try { pProps = dynamic_cast<CSnapinProperties*>(pUnk); } catch (...) { pProps = NULL; }
return (pProps); }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::Item * * Returns an interface to a property identified by bstrName, which must * be released by the caller. If the collection doesn't contain a property * with the given name, a new property with the given name (initialized to * VT_EMPTY) is added to the collection. * * Returns: * S_OK the property was successfully returned * S_FALSE the property was successfully returned, but didn't * exist in the collection beforehand, so a new one * was added * E_INVALIDARG the property name wasn't valid (i.e. empty) or * ppProperty was NULL * E_OUTOFMEMORY not enough memory to perform the operation * E_UNEXPECTED something dire happened *--------------------------------------------------------------------------*/
STDMETHODIMP CSnapinProperties::Item ( BSTR bstrName, /* I:name of property to get */ PPPROPERTY ppProperty) /* O:interface to property */ { DECLARE_SC (sc, _T("CSnapinProperties::Item"));
/*
* validate the parameters */ sc = ScCheckPointers (bstrName, ppProperty); if (sc) return (sc.ToHr());
const std::wstring strName = bstrName; if (strName.empty()) return ((sc = E_INVALIDARG).ToHr());
bool fPropWasAdded = false;
/*
* Look up the property. If it's not there yet, add a new one (maybe). */ if (m_PropMap.find(strName) == m_PropMap.end()) { /*
* Fail without implicitly adding if we're not attached to a snap-in. * This will prevent us from adding properties that weren't * registered with AddPropertyName */ if (m_spSnapinProps != NULL) return ((sc = ScFromMMC(MMC_E_UnrecognizedProperty)).ToHr());
/*
* put an empty property in the map with the given name */ m_PropMap[strName] = CSnapinProperty(); fPropWasAdded = true; }
/*
* get a COM object tied to the new property */ sc = ScGetPropertyComObject (strName, *ppProperty); if (sc) return (sc.ToHr());
if (*ppProperty == NULL) return ((sc = E_UNEXPECTED).ToHr());
/*
* if we had to add the property, return S_FALSE so the caller can * tell (if he cares) */ if (fPropWasAdded) sc = S_FALSE;
return (sc.ToHr()); }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::get_Count * * Returns the number of properties in the collection in *pCount. * * Returns: * * S_OK success * E_INVALIDARG pCount is NULL *--------------------------------------------------------------------------*/
STDMETHODIMP CSnapinProperties::get_Count ( PLONG pCount) /* O:number of items in the collection */ { DECLARE_SC (sc, _T("CSnapinProperties::get_Count"));
/*
* validate the parameters */ sc = ScCheckPointers (pCount); if (sc) return (sc.ToHr());
/*
* return the number of elements in the property map */ *pCount = m_PropMap.size();
return (sc.ToHr()); }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::Remove * * Removes a property from the collection. * * Returns: * S_OK the property was successfully removed * S_FALSE the property didn't exist in the collection * E_INVALIDARG the property name wasn't valid (i.e. empty) * E_UNEXPECTED something dire happened *--------------------------------------------------------------------------*/
STDMETHODIMP CSnapinProperties::Remove ( BSTR bstrName) /* I:name of property to remove */ { DECLARE_SC (sc, _T("CSnapinProperties::Remove")); Trace (tagSnapInProps, _T("Snap-in Properties"));
/*
* validate the parameters */ sc = ScCheckPointers (bstrName); if (sc) return (sc.ToHr());
/*
* find the item to remove */ CPropertyIterator itProp = m_PropMap.find (bstrName); if (itProp == m_PropMap.end()) return ((sc = S_FALSE).ToHr());
/*
* see if we can remove it */ if ( itProp->second.IsInitialized() && (itProp->second.GetFlags() & MMC_PROP_REMOVABLE) == 0) return ((sc = ScFromMMC(MMC_E_CannotRemoveProperty)).ToHr());
/*
* Inform snapin before we remove the property about removal. */ sc = ScNotifyPropertyChange(itProp, itProp->second.GetValue(), MMC_PROPACT_DELETING); if (sc) return sc.ToHr();
/*
* the snap-in approved the change, remove the property */ m_PropMap.erase (itProp);
return (sc.ToHr()); }
/*+-------------------------------------------------------------------------*
* * CSnapinProperties::ScEnumNext * * PURPOSE: Returns the next Property interface. * * PARAMETERS: * _Position & key : * PDISPATCH & pDispatch : * * RETURNS: * SC * *+-------------------------------------------------------------------------*/ SC CSnapinProperties::ScEnumNext (CPropertyKey &key, PDISPATCH & pDispatch) { DECLARE_SC (sc, _T("CSnapinProperties::ScEnumNext")); Trace (tagSnapInProps, _T("Snap-in Properties"));
/*
* get the next element */ CPropertyIterator it = IteratorFromKey (key, false);
if(it == m_PropMap.end()) return (sc = S_FALSE); // out of elements.
/*
* get the Properties COM object for this property */ PropertyPtr spProperty; sc = ScGetPropertyComObject (it->first, *&spProperty); if (sc) return (sc);
if (spProperty == NULL) return (sc = E_UNEXPECTED);
/*
* return the IDispatch for the object and leave a ref on it for the client */ pDispatch = spProperty.Detach();
// remember the enumeration key for next time
key = it->first;
return (sc); }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::ScEnumSkip * * Skips the next celt elements in the properties collection. *--------------------------------------------------------------------------*/
SC CSnapinProperties::ScEnumSkip ( unsigned long celt, /* I:number of items to skip */ unsigned long& celtSkipped, /* O:number of items skipped */ CPropertyKey& key) /* I/O:enumeration key */ { DECLARE_SC (sc, _T("CSnapinProperties::ScEnumSkip")); Trace (tagSnapInProps, _T("Snap-in Properties"));
/*
* skip the next celt properties */ CPropertyIterator it = IteratorFromKey (key, false);
for (celtSkipped = 0; (celtSkipped < celt) && (it != m_PropMap.end()); ++celtSkipped, ++it) { /*
* remember the enumeration key for next time */ key = it->first; }
/*
* if we advanced less than the requested number, return S_FALSE */ if (celtSkipped < celt) sc = S_FALSE;
return (sc); }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::ScEnumReset * * Resets a CPropertyKey so that the next item it will return is the * first item in the properties collection. *--------------------------------------------------------------------------*/
SC CSnapinProperties::ScEnumReset ( CPropertyKey& key) /* I/O:enumeration key to reset */ { DECLARE_SC (sc, _T("CSnapinProperties::ScEnumReset"));
key.erase(); return (sc); }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::get__NewEnum * * Creates returns an interface that can be queried for IEnumVARIANT *--------------------------------------------------------------------------*/
STDMETHODIMP CSnapinProperties::get__NewEnum (IUnknown** ppUnk) { DECLARE_SC (sc, _T("CSnapinProperties::get__NewEnum")); Trace (tagSnapInProps, _T("Snap-in Properties"));
// validate the parameter
sc = ScCheckPointers (ppUnk); if (sc) return (sc.ToHr());
*ppUnk = NULL;
// typedef the enumerator
typedef CComObject<CMMCEnumerator<CSnapinProperties, CPropertyKey> > CEnumerator;
// create an instance of the enumerator
CEnumerator *pEnum = NULL; sc = CEnumerator::CreateInstance (&pEnum); if (sc) return (sc.ToHr());
if(!pEnum) return ((sc = E_UNEXPECTED).ToHr());
// create a connection between the enumerator and ourselves
sc = ScCreateConnection(*pEnum, *this); if(sc) return (sc.ToHr());
// initialize the position using the Reset function
sc = ScEnumReset (pEnum->m_position); if(sc) return (sc.ToHr());
// get the IUnknown to return
sc = pEnum->QueryInterface (IID_IUnknown, (void**) ppUnk); if (sc) return (sc.ToHr());
return (sc.ToHr()); }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::IteratorFromKey * * Returns the iterator in the property map corresponding to the first * element following the one designated by key. * * The caller might be interested in an exact match or the nearest match. * The nearest match would be suitable when the key is used in an * enumeration. Let's say that the collection consists of "Alpha", "Bravo", * and "Charlie". The first request for an item will return "Alpha" and * the key will hold "Alpha" (see comments for CPropertyKey). Let's * assume that "Alpha" is removed from the collection and then the enumeration * continues. We want to return the one after the last one we got back * ("Alpha") which would be "Bravo". All is well. * * An exact match would be required when trying to find a CSnapinProperty * for a CSnapinPropertyComObject. The COM object will refer to a specific * property, which we want to be sure to find every time. A close match * isn't sufficient. *--------------------------------------------------------------------------*/
CSnapinProperties::CPropertyIterator CSnapinProperties::IteratorFromKey ( const CPropertyKey& key, /* I:key to convert */ bool fExactMatch) /* I:match key exactly? */ { CPropertyIterator it;
/*
* need an exact match? */ if (fExactMatch) { /*
* nothing matches an empty key */ if (key.empty()) it = m_PropMap.end();
/*
* the key's not empty, look up the property */ else it = m_PropMap.find (key); }
/*
* nearest match */ else { /*
* the beginning of the map is nearest an empty key */ if (key.empty()) it = m_PropMap.begin();
/*
* otherwise, find the nearest one greater than the key */ else it = m_PropMap.upper_bound (key); }
return (it); }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::ScInitialize * * Initializes a CSnapinProperties. This function will return an error if * psip is NULL, or if there's an error copying the initial properties. *--------------------------------------------------------------------------*/
SC CSnapinProperties::ScInitialize ( ISnapinProperties* psip, /* I:snap-in's ISnapinProperties iface */ Properties* pInitProps_, /* I:initial properties for the snap-in */ CMTSnapInNode* pMTSnapInNode) /* I:snap-in these properties belong to */ { DECLARE_SC (sc, _T("CSnapinProperties::ScInitialize"));
/*
* validate the parameters */ sc = ScCheckPointers (psip); if (sc) return (sc);
/*
* pInitProps_ is optional, but if it was given, it should be the * one implemented by CSnapinProperties */ CSnapinProperties* pInitProps = FromInterface (pInitProps_); if ((pInitProps_ != NULL) && (pInitProps == NULL)) return (sc = E_INVALIDARG);
/*
* keep the the snap-in and the snap-in's interface */ m_pMTSnapInNode = pMTSnapInNode; m_spSnapinProps = psip;
/*
* get the names of the properties recognized by the snap-in */ sc = psip->QueryPropertyNames (this); if (sc) return (sc);
/*
* If we're reloading a snap-in's properties from the console file, * weed out entries that the snap-in registered last time but didn't * register this time. */ if (pInitProps == this) { CPropertyIterator itProp = m_PropMap.begin();
while (itProp != m_PropMap.end()) { /*
* snap-in registered? keep it */ if (itProp->second.IsRegisteredBySnapin()) ++itProp;
/*
* snap-in didn't register, toss it */ else itProp = m_PropMap.erase (itProp); } }
/*
* Otherwise, if we got initial properties, find each property * that the snap-in registered in set of initial properties and * copy them to the snap-in's collection. */ else if (pInitProps != NULL) { sc = ScMergeProperties (*pInitProps); if (sc) return (sc); }
/*
* initialize the ISnapinProperties interface */ sc = psip->Initialize (this); if (sc) return (sc);
/*
* give the ISnapinProperties its initial property values */ if (!m_PropMap.empty()) { /*
* Build an array of CSmartProperty objects to pass to * ISnapinProperties::PropertiesChanged. CSmartProperty objects * look just like MMC_SNAPIN_PROPERTY structures, but use a * CComVariant instead of VARIANT for automatic resource management. * See the definition of CSmartProperty. */ CAutoArrayPtr<CSmartProperty> spInitialProps ( new (std::nothrow) CSmartProperty[m_PropMap.size()]);
if (spInitialProps == NULL) return (sc = E_OUTOFMEMORY);
CPropertyIterator it = m_PropMap.begin(); for (int i = 0; it != m_PropMap.end(); ++it, ++i) { spInitialProps[i].pszPropName = it->first.data(); spInitialProps[i].varValue = it->second.GetValue(); spInitialProps[i].eAction = MMC_PROPACT_INITIALIZED; }
/*
* we don't want to trace a failure here, so use a local SC */ SC scLocal = ScNotifyPropertyChange (spInitialProps, m_PropMap.size()); if (scLocal) return (scLocal); }
return (sc); }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::ScSetSnapInNode * * Attaches this properties collection to a CMTSnapInNode. *--------------------------------------------------------------------------*/
SC CSnapinProperties::ScSetSnapInNode (CMTSnapInNode* pMTSnapInNode) { DECLARE_SC (sc, _T("CSnapinProperties::ScSetSnapInNode"));
m_pMTSnapInNode = pMTSnapInNode;
return (sc); }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::ScMergeProperties * * Merges the properties from another property collection into this one. * Only properties that already exist in the destination collection are * copied from the source. *--------------------------------------------------------------------------*/
SC CSnapinProperties::ScMergeProperties (const CSnapinProperties& other) { DECLARE_SC (sc, _T("CSnapinProperties::ScMergeProperties"));
/*
* for each property in the other collection... */ CConstPropertyIterator itOtherProp;
for (itOtherProp = other.m_PropMap.begin(); (itOtherProp != other.m_PropMap.end()) && !sc.IsError(); ++itOtherProp) { /*
* look for a corresponding property in the our set */ CPropertyIterator itProp = m_PropMap.find (itOtherProp->first);
/*
* if it's in our set, copy its value */ if (itProp != m_PropMap.end()) sc = itProp->second.ScSetValue (itOtherProp->second.GetValue()); }
return (sc); }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::AddPropertyName * * This method is called by the snap-in from its implementation of * ISnapinProperties::QueryPropertyNames to register the properties it * recognizes. *--------------------------------------------------------------------------*/
STDMETHODIMP CSnapinProperties::AddPropertyName ( LPCOLESTR pszPropName, /* I:property name */ DWORD dwFlags) /* I:flags for this property */ { DECLARE_SC (sc, _T("CSnapinProperties::AddPropertyName"));
/*
* validate the parameters */ sc = ScCheckPointers (pszPropName); if (sc) return (sc.ToHr());
const std::wstring strName = pszPropName; if (strName.empty()) return ((sc = E_INVALIDARG).ToHr());
/*
* make sure no undocumented flags were passed in */ if ((dwFlags & ~CSnapinProperty::PublicFlags) != 0) return ((sc = E_INVALIDARG).ToHr());
/*
* if the property already exists (from a persisted collection), * just update the flags; otherwise add a property with the given * name and flags */ CPropertyIterator itProp = m_PropMap.find (strName);
if (itProp != m_PropMap.end()) itProp->second.InitializeFlags (dwFlags); else { m_PropMap[strName] = CSnapinProperty(dwFlags); m_PropMap[strName].SetRegisteredBySnapin(); }
return (sc.ToHr()); }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::ScNotifyPropertyChange * * Notifies the snap-in that owns this collection of a change to it's * properties. This function delegates the heavy lifting to * * ScNotifyPropertyChange (CSmartProperty*, ULONG); * *--------------------------------------------------------------------------*/
SC CSnapinProperties::ScNotifyPropertyChange ( CPropertyIterator itProp, /* I:changing property */ const VARIANT& varValue, /* I:if action is remove then this is current value
else if action is set then this is the proposed value */ MMC_PROPERTY_ACTION eAction) /* I:what's happening to the prop? */ { DECLARE_SC (sc, _T("CSnapinProperties::ScNotifyPropertyChange"));
ASSERT(eAction == MMC_PROPACT_CHANGING || eAction == MMC_PROPACT_DELETING); /*
* validate the parameters */ if (itProp == m_PropMap.end()) return (sc = E_INVALIDARG);
/*
* make sure we're allowed to change the property */ if ( itProp->second.IsInitialized() && (itProp->second.GetFlags() & MMC_PROP_MODIFIABLE) == 0) return (sc = ScFromMMC (MMC_E_CannotChangeProperty));
/*
* if this property change will affect the UI, and the snap-in * isn't awake yet, wake him up */ if ((itProp->second.GetFlags() & MMC_PROP_CHANGEAFFECTSUI) && (m_pMTSnapInNode != NULL) && !m_pMTSnapInNode->IsInitialized()) { sc = m_pMTSnapInNode->Init(); if (sc) return (sc); }
/*
* we don't want to trace failures here, so don't assign to sc */ CSmartProperty SmartProp (itProp->first.data(), varValue, eAction); SC scNoTrace = ScNotifyPropertyChange (&SmartProp, 1); if (scNoTrace.ToHr() != S_OK) return (scNoTrace);
return (sc); }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::ScNotifyPropertyChange * * Notifies the snap-in that owns this collection of a change to it's * properties. * * The snap-in will return: * S_OK change was successful * S_FALSE change was ignored * E_INVALIDARG a changed property was invalid (e.g. a malformed * computer name) * E_FAIL a changed property was valid, but couldn't be used * (e.g. a valid name for a computer that couldn't be * located) *--------------------------------------------------------------------------*/
SC CSnapinProperties::ScNotifyPropertyChange ( CSmartProperty* pProps, /* I:changing props */ ULONG cProps) /* I:how many are there? */ { DECLARE_SC (sc, _T("CSnapinProperties::ScNotifyPropertyChange"));
/*
* if we're not connected to a snap-in, short out */ if (m_spSnapinProps == NULL) return (sc);
/*
* validate the parameters */ sc = ScCheckPointers (pProps, E_UNEXPECTED); if (sc) return (sc);
if (cProps == 0) return (sc = E_UNEXPECTED);
/*
* we don't want to trace failures here, so don't assign to sc */ return (m_spSnapinProps->PropertiesChanged ( cProps, reinterpret_cast<MMC_SNAPIN_PROPERTY*>(pProps))); }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::Scget_Value * * Returns the value of the property. *--------------------------------------------------------------------------*/
SC CSnapinProperties::Scget_Value (VARIANT* pvarValue, const CPropertyKey& key) { DECLARE_SC (sc, _T("CSnapinProperties::Scget_Value"));
/*
* validate parameters */ pvarValue = ConvertByRefVariantToByValue (pvarValue); sc = ScCheckPointers (pvarValue); if (sc) return (sc);
/*
* get the iterator for the requested property */ CPropertyIterator itProp = IteratorFromKey (key, true); if (itProp == m_PropMap.end()) return (sc = E_INVALIDARG);
/*
* give it to the caller */ const VARIANT& varValue = itProp->second.GetValue(); sc = VariantCopy (pvarValue, const_cast<VARIANT*>(&varValue)); if (sc) return (sc);
return (sc); }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::Scput_Value * * Changes the value of the property. *--------------------------------------------------------------------------*/
SC CSnapinProperties::Scput_Value (VARIANT varValue, const CPropertyKey& key) { DECLARE_SC (sc, _T("CSnapinProperties::Scput_Value"));
/*
* convert possible by-ref VARIANT */ VARIANT* pvarValue = ConvertByRefVariantToByValue (&varValue); sc = ScCheckPointers (pvarValue); if (sc) return (sc);
/*
* make sure this is of the type we can persist */ if (!CXMLVariant::IsPersistable(pvarValue)) return (sc = E_INVALIDARG);
/*
* get the iterator for the requested property */ CPropertyIterator itProp = IteratorFromKey (key, true); if (itProp == m_PropMap.end()) return (sc = E_INVALIDARG);
/*
* Notify the snap-in of the proposed change. */ sc = ScNotifyPropertyChange (itProp, *pvarValue, MMC_PROPACT_CHANGING); if (sc) return sc;
/*
* the snap-in approved the change, update the property value */ sc = itProp->second.ScSetValue (*pvarValue); if (sc) return (sc);
return sc; }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::ScGetPropertyComObject * * Returns a Property interface on a COM object tied to property identified * by key. The returned interface is a tear-off interface. The collection * will not hold a reference to it, but instead will generate a new object * for each request for a Property. *--------------------------------------------------------------------------*/
SC CSnapinProperties::ScGetPropertyComObject ( const CPropertyKey& key, /* I:the key for this property */ Property*& rpProperty) /* O:the Property interface */ { DECLARE_SC (sc, _T("CSnapinProperties::ScGetPropertyComObject"));
/*
* create a CSnapinPropertyComObject if necessary */ CSnapinPropertyComObject* pComObj = NULL; typedef CTiedComObjectCreator<CSnapinPropertyComObject> ObjectCreator; sc = ObjectCreator::ScCreateAndConnect (*this, pComObj); if (sc) return (sc);
if (pComObj == NULL) return (sc = E_UNEXPECTED);
/*
* tell the object what its key is */ pComObj->SetKey (key);
/*
* put a ref on for the caller (note that the collection will *not* * hold a reference to the property) */ rpProperty = pComObj; rpProperty->AddRef();
return (sc); }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::Persist * * Persists the property collection to/from an XML persistor. *--------------------------------------------------------------------------*/
void CSnapinProperties::Persist (CPersistor &persistor) { if (persistor.IsStoring()) { for (CPropertyIterator it = m_PropMap.begin(); it != m_PropMap.end(); ++it) { if (it->second.GetFlags() & MMC_PROP_PERSIST) PersistWorker (persistor, it); } } else { /*
* clear out any existing properties */ m_PropMap.clear();
// let the base class do the job
// it will call OnNewElement for every element found
XMLListCollectionBase::Persist(persistor); } }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::PersistWorker * * Persists an individual element of the CPropertyMap to/from an XML * persistor. It exists solely to prevent CSnapinProperties::Persist from * calling W2CT (which implicitly calls _alloca) in a loop. *--------------------------------------------------------------------------*/
void CSnapinProperties::PersistWorker (CPersistor& persistor, CPropertyIterator it) { USES_CONVERSION; persistor.Persist (it->second, W2CT(it->first.data())); }
/*+-------------------------------------------------------------------------*
* CSnapinProperties::OnNewElement * * XMLListCollectionBase::Persist will call this method for every element * to be read from the persistor. *--------------------------------------------------------------------------*/
void CSnapinProperties::OnNewElement(CPersistor& persistor) { /*
* read the property name */ std::wstring strName; persistor.PersistAttribute (XML_ATTR_SNAPIN_PROP_NAME, strName);
/*
* read the property itself */ USES_CONVERSION; CSnapinProperty prop; persistor.Persist (prop, W2CT(strName.data()));
/*
* put the property in the map */ m_PropMap[strName] = prop; }
/*+=========================================================================*/ /* */ /* CSnapinProperty implementation */ /* */ /*==========================================================================*/
/*+-------------------------------------------------------------------------*
* CSnapinProperty::Persist * * Persists the property to/from an XML persistor. *--------------------------------------------------------------------------*/
void CSnapinProperty::Persist (CPersistor &persistor) { /*
* persist the value and flags (but not the private ones) */ DWORD dwFlags;
if (persistor.IsStoring()) dwFlags = m_dwFlags & ~PrivateFlags;
persistor.Persist (m_varValue); persistor.PersistAttribute (XML_ATTR_SNAPIN_PROP_FLAGS, dwFlags);
if (persistor.IsLoading()) m_dwFlags = dwFlags; }
|