|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1999.
//
// File: R E M O V E . C P P
//
// Contents: Implements actions related to removing components.
//
// Notes:
//
// Author: shaunco 15 Jan 1999
//
//----------------------------------------------------------------------------
#include <pch.h>
#pragma hdrstop
#include "ncreg.h"
#include "netcfg.h"
VOID CModifyContext::NotifyAndRemoveComponent ( IN CComponent* pComponent) { CNetConfig* pNetConfig; UINT cPreviousDeletedBindPaths;
Assert (this); Assert (S_OK == m_hr); Assert (pComponent);
pNetConfig = PNetConfig();
// Note the number of bindpaths currently in m_DeletedBindPaths.
// We need this so that when we add to the set, we only notify
// for the ones we add.
//
cPreviousDeletedBindPaths = m_DeletedBindPaths.CountBindPaths ();
// Get the bindpaths that involve the component we are removing.
// Add these to the deleted bindpaths we are keeping track of.
//
m_hr = pNetConfig->Core.HrGetBindingsInvolvingComponent ( pComponent, GBF_ADD_TO_BINDSET | GBF_ONLY_WHICH_CONTAIN_COMPONENT, &m_DeletedBindPaths); if (S_OK != m_hr) { Assert(FAILED(m_hr)); return; }
// Remove the component from the core.
//
pNetConfig->Core.RemoveComponentFromCore (pComponent);
// Notify that these bindpaths are being removed. We only need to do
// so if we added any new ones to the set. Existing ones in the set
// have already been notified.
//
// THIS MAY CAUSE RECURSION
//
if (m_DeletedBindPaths.CountBindPaths() > cPreviousDeletedBindPaths) { m_hr = pNetConfig->Notify.NotifyRemovedBindPaths ( &m_DeletedBindPaths, cPreviousDeletedBindPaths); if (S_OK != m_hr) { Assert(FAILED(m_hr)); return; } }
// Notify the component's notify object it is being removed.
// This also sends global notifications to other notify objects
// who may be interested.
//
// THIS MAY CAUSE RECURSION
//
m_hr = pNetConfig->Notify.ComponentRemoved (pComponent); if (S_OK != m_hr) { Assert(FAILED(m_hr)); return; }
// If we have a cached INetCfgComponent interface, we need to tell it
// that the component it represents is no longer valid.
//
pComponent->ReleaseINetCfgComponentInterface ();
// Remove (if not referenced) any components that this component
// required.
//
// THIS MAY CAUSE RECURSION
//
InstallOrRemoveRequiredComponents (pComponent, IOR_REMOVE); if (S_OK != m_hr) { Assert(FAILED(m_hr)); return; }
// Now that we've given a chance to notify objects to remove references
// to the component being removed, we need to ensure it is not
// referenced by anyone else.
// Check to see if the component we just removed is still
// referencing other components. If it is, it means it forgot
// to remove those components. We'll print what they are and
// remove the bogus reference (but not the components themselves)
// so that when we save the configuration binary we don't
// barf trying to lookup the index of this component we just
// removed.)
//
pNetConfig->Core.EnsureComponentNotReferencedByOthers (pComponent); }
HRESULT CModifyContext::HrRemoveComponentIfNotReferenced ( IN CComponent* pComponent, IN OBO_TOKEN* pOboToken OPTIONAL, OUT PWSTR* ppmszwRefs OPTIONAL) { CNetConfig* pNetConfig; BOOL fStillReferenced;
Assert (this); Assert (S_OK == m_hr); Assert (pComponent);
// If the caller is requesting removal on behalf of an obo token,
// (and its not obo the user) make sure the component is actually
// referenced by that obo token. If it is not, consider it an
// invalid argument.
//
// The reason we don't consider the obo user case is because the UI
// will show anything that is installed and allow the user to try to
// remove them. If the user hasn't actually installed it, we don't
// want to treat this as an invalid argument, rather, we want to let
// the code fall through to the case where we will return the multi-sz
// of descriptions of components still referencing the component.
//
// However, if there are no references (which can happen if we delete
// the configuration binary and then re-create it) we'll go ahead and
// allow removals by anyone). This is a safety-net.
//
// The overall purpose of the following 'if' is to catch programatic
// removals that are on behalf of other components or software that
// have previously installed the component being removed.
//
if (pOboToken && (OBO_USER != pOboToken->Type) && !pComponent->Refs.FIsReferencedByOboToken (pOboToken) && (pComponent->Refs.CountTotalReferencedBy() > 0)) { return E_INVALIDARG; }
pNetConfig = PNetConfig(); fStillReferenced = TRUE;
// Now that we actually are going to modify something, push a new
// recursion depth.
//
PushRecursionDepth (); Assert (S_OK == m_hr);
// If the component is NOT in the list of components we started with,
// it means someone had previously installed it during this modify
// context and now wants to remove it. This is tricky and should
// probably be implemented later. For now, return an error and throw
// up an assert so we can see who needs to do this.
//
if (!m_CoreStartedWith.Components.FComponentInList (pComponent)) { AssertSz (FALSE, "Whoa. Someone is trying to remove a " "component that was previously installed during this same " "modify context. We need to decide if we can support this."); m_hr = E_UNEXPECTED; }
if (pOboToken && (S_OK == m_hr)) { m_hr = pComponent->Refs.HrRemoveReferenceByOboToken (pOboToken); }
// If no obo token, or we removed the reference from it, actually
// remove it if it is not still referenced by anything else.
//
if (S_OK == m_hr) { if (0 == pComponent->Refs.CountTotalReferencedBy()) { fStillReferenced = FALSE;
NotifyAndRemoveComponent (pComponent); } else if (ppmszwRefs) { ULONG cb;
// Need to return the multi-sz of descriptions still referencing
// the component the caller tried to remove.
//
// Size the data first.
//
cb = 0; pComponent->Refs.GetReferenceDescriptionsAsMultiSz ( NULL, &cb);
Assert (cb);
// Allocate room to return the multi-sz.
//
Assert (S_OK == m_hr);
m_hr = HrCoTaskMemAlloc (cb, (VOID**)ppmszwRefs); if (S_OK == m_hr) { // Now get the multi-sz.
//
pComponent->Refs.GetReferenceDescriptionsAsMultiSz ( (BYTE*)(*ppmszwRefs), &cb);
Assert (fStillReferenced); } } }
HRESULT hr;
hr = HrPopRecursionDepth ();
if (fStillReferenced && SUCCEEDED(hr)) { // Still reference return code overrides other success codes like
// need reboot.
//
hr = NETCFG_S_STILL_REFERENCED; }
return hr; }
|