//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1999. // // File: N E T C F G . H // // Contents: Defines the overall datatype for representing the network // bindings engine. This datatype, CNetConfig, is a // collection of components and their binding relationships // to each other. // // Notes: // // Author: shaunco 15 Jan 1999 // //---------------------------------------------------------------------------- #pragma once #include "complist.h" #include "diagctx.h" #include "install.h" #include "notify.h" #include "stable.h" #include "util.h" // Flags for HrGetBindingsXXX. // enum GB_FLAGS { GBF_DEFAULT = 0x00000000, GBF_ADD_TO_BINDSET = 0x00000001, GBF_PRUNE_DISABLED_BINDINGS = 0x00000002, GBF_ONLY_WHICH_CONTAIN_COMPONENT = 0x00000004, }; // Flags for FIsBindPathDisabled. // enum IBD_FLAGS { IBD_EXACT_MATCH_ONLY = 0x00000001, IBD_MATCH_SUBPATHS_TOO = 0x00000002, }; class CNetConfigCore : CNetCfgDebug { public: CComponentList Components; CStackTable StackTable; CBindingSet DisabledBindings; #if DBG private: BOOL m_fRemovedAComponent; #endif public: VOID Clear (); VOID Free (); BOOL FIsEmpty () const; BOOL FContainsFilterComponent () const; BOOL FIsBindPathDisabled ( IN const CBindPath* pBindPath, IN DWORD dwFlags /* IBD_FLAGS */) const; BOOL FIsLength2BindPathDisabled ( IN const CComponent* pUpper, IN const CComponent* pLower) const; VOID EnableBindPath ( IN const CBindPath* pBindPath) { TraceFileFunc(ttidNetCfgBind); DisabledBindings.RemoveBindPath (pBindPath); DbgVerifyBindingSet (&DisabledBindings); } VOID EnsureComponentNotReferencedByOthers ( IN const CComponent* pComponent); HRESULT HrDisableBindPath ( IN const CBindPath* pBindPath); HRESULT HrCopyCore ( IN const CNetConfigCore* pSourceCore); HRESULT HrGetBindingsInvolvingComponent ( IN const CComponent* pComponent, IN DWORD dwFlags, IN OUT CBindingSet* pBindSet); HRESULT HrGetComponentBindings ( IN const CComponent* pComponent, IN DWORD dwFlags /* GB_FLAGS */, OUT CBindingSet* pBindSet); HRESULT HrGetComponentUpperBindings ( IN const CComponent* pComponent, IN DWORD dwFlags, OUT CBindingSet* pBindSet); HRESULT HrGetFiltersEnabledForAdapter ( IN const CComponent* pAdapter, OUT CComponentList* pFilters); HRESULT HrAddComponentToCore ( IN CComponent* pComponent, IN DWORD dwFlags /* INS_FLAGS */); VOID RemoveComponentFromCore ( IN const CComponent* pComponent); #if DBG VOID DbgVerifyData () const; VOID DbgVerifyExternalDataLoadedForAllComponents () const; VOID DbgVerifyBindingSet ( const CBindingSet* pBindSet) const; #else VOID DbgVerifyData () const {} VOID DbgVerifyExternalDataLoadedForAllComponents () const {} VOID DbgVerifyBindingSet ( const CBindingSet* /*pBindSet*/) const {} #endif }; class CNetConfig; class CFilterDevices; class CRegistryBindingsContext : CNetCfgDebug { private: CNetConfig* m_pNetConfig; CBindingSet m_BindSet; CDynamicBuffer m_BindValue; CDynamicBuffer m_ExportValue; CDynamicBuffer m_RouteValue; public: HRESULT HrPrepare ( IN CNetConfig* pNetConfig); HRESULT HrGetAdapterUpperBindValue ( IN const CComponent* pAdapter); HRESULT HrWriteBindingsForComponent ( IN const CComponent* pComponent); HRESULT HrWriteBindingsForFilterDevices ( IN CFilterDevices* pFilterDevices); HRESULT HrDeleteBindingsForComponent ( IN const CComponent* pComponent); VOID PnpBindOrUnbindBindPaths ( IN UINT unOperation, IN const CBindingSet* pBindSet, OUT BOOL* pfRebootNeeded); }; enum IOR_ACTION { IOR_INSTALL, IOR_REMOVE, }; enum EBO_FLAG { EBO_COMMIT_NOW = 1, EBO_DEFER_COMMIT_UNTIL_APPLY, }; class CModifyContext : CNetCfgDebug { public: // This is the core data we started with before the modification began. // In the event the modification fails, we will revert to this data. // We also use this data when we apply the changes. We compare what // we started with to what we have as a result of the modification and // the differences represent the things we need to change. // CNetConfigCore m_CoreStartedWith; // These bindings are the added bindpaths (due to adding components) // These represent bindings that have been queried and notified to // notify objects. // CBindingSet m_AddedBindPaths; // These bindings are the deleted bindpaths (due to removing components) // These represent bindings that have been notified to notify objects. // CBindingSet m_DeletedBindPaths; // These components are all the components involved in m_AddedBindPaths // and m_DeletedBindPaths. As such, they are the components we need // to visit during Apply to write bindings for, delete bindings for, // or finish removal of depending on whether the components exist in // the core we started with. Components can get in this list if they // have had their bind order changed, or if they were involved in a // binding that has been enabled or disabled. // CComponentList m_DirtyComponents; // The purpose of the binding context is just to allow us to make one // allocation (and use it over and over) for the buffer which holds the // bind strings that get written to the registry. We make this allocation // up front when the modify context is prepared. Doing so minimizes the // risk of getting half-way through apply and then finding out we are so // low on memory that we cannot allocate a buffer to write the registry // bindings with. // CRegistryBindingsContext m_RegBindCtx; ULONG m_ulRecursionDepth; HRESULT m_hr; BOOLEAN m_fPrepared; // Set when a notify object says they need to reboot in order for changes // to take affect. Setting this will not REQUIRE us to reboot, it will // only cause NETCFG_S_REBOOT to be returned from the install or remove // operation. // BOOLEAN m_fRebootRecommended; // Set when a component that is being removed fails to stop. When it // does, its service will be marked as 'pending delete'. We cannot allow // any other config changes to happen when we are in this state because // if that service ever needs to be re-installed, we will fail. // BOOLEAN m_fRebootRequired; #if DBG // This flag indicates that we've dirtied a component outside of // ApplyChanges. We will do this when bind order changes, and when // INetCfgComponentPrivate::SetDirty or // INetCfgComponentPrivate::NotifyUpperEdgeConfigChange are called. // If this flag is TRUE, m_fDirtyComponents will not be empty upon // entering ApplyChanges. Normally, when this flag is FALSE, // m_fDirtyComponents should be empty when entering ApplyChanges. // If it were not, it would probably mean we forgot to empty it after // the last Apply or Cancel and are now risking applying changes to // components which really are not dirty. // BOOLEAN m_fComponentExplicitlyDirtied; #endif private: VOID PushRecursionDepth (); HRESULT HrPopRecursionDepth (); VOID ApplyChanges (); VOID InstallAndAddAndNotifyComponent ( IN const COMPONENT_INSTALL_PARAMS& Params, OUT CComponent** ppComponent); VOID InstallConvenienceComponentsForUser ( IN const CComponent* pComponent); VOID InstallOrRemoveRequiredComponents ( IN CComponent* pComponent, IN IOR_ACTION Action); VOID NotifyAndRemoveComponent ( IN CComponent* pComponent); HRESULT HrProcessWinsockRemove ( IN const CComponent* pComponent); public: CNetConfig* PNetConfig (); HRESULT HrBeginBatchOperation (); HRESULT HrEndBatchOperation ( IN EBO_FLAG Flag); HRESULT HrDirtyComponent ( IN const CComponent* pComponent); HRESULT HrDirtyComponentAndComponentsAbove ( IN const CComponent* pComponent); HRESULT HrApplyIfOkOrCancel ( IN BOOL fApply); HRESULT HrPrepare (); HRESULT HrEnableOrDisableBindPath ( IN DWORD dwChangeFlag, IN CBindPath* pBindPath, IN INetCfgBindingPath* pIPath OPTIONAL); HRESULT HrInstallNewOrReferenceExistingComponent ( IN const COMPONENT_INSTALL_PARAMS& Params, OUT CComponent** ppComponent); HRESULT HrRemoveComponentIfNotReferenced ( IN CComponent* pComponent, IN OBO_TOKEN* pOboToken OPTIONAL, OUT PWSTR* ppmszwRefs OPTIONAL); HRESULT HrUpdateComponent ( IN CComponent* pComponent, IN DWORD dwSetupFlags, IN DWORD dwUpgradeFromBuildNo); }; class CNetConfig : CNetCfgDebug { public: // This is the core data managed by this object. The reason it // is encapsulated by NETCFG_CORE is so that we can save it away before // we being any modify operation. (We save it into // CModifyContext.m_StartedWith.) In the event of a failure to modify // we restore the core data from what we started with. // CNetConfigCore Core; // The interface to all notify objects representing the components. // CGlobalNotifyInterface Notify; CModifyContext ModifyCtx; public: CNetConfig () { TraceFileFunc(ttidNetcfgBase); ZeroMemory (this, sizeof(*this)); } ~CNetConfig (); HRESULT HrEnsureExternalDataLoadedForAllComponents (); static HRESULT HrCreateInstance ( IN class CImplINetCfg* pINetCfg, OUT CNetConfig** ppNetConfig); };