|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1999.
//
// File: N O T I F Y . C P P
//
// Contents: Implements the interface to a component's optional notify
// object. The object defined here is meant to be a member
// of CComponent. This object encapsulates all of its internal
// data in a separate allocation made only if the component
// actually has a notify object.
//
// Notes:
//
// Author: shaunco 15 Jan 1999
//
//----------------------------------------------------------------------------
#include <pch.h>
#pragma hdrstop
#include "diagctx.h"
#include "ibind.h"
#include "inetcfg.h"
#include "nceh.h"
#include "ncmisc.h"
#include "ncprsht.h"
#include "netcfg.h"
#include "notify.h"
//+---------------------------------------------------------------------------
// CNotifyObjectInterface -
//
HRESULT CNotifyObjectInterface::HrEnsureNotifyObjectInitialized ( IN CImplINetCfg* pINetCfg, IN BOOL fInstalling) { Assert (pINetCfg);
// If we've already been through initialization, return immediately.
//
if (m_fInitialized) { return S_OK; }
// Only perform initialization once, regardless of whether it succeeds
// or not.
//
m_fInitialized = TRUE;
// Get our containing component pointer so we can ask it what the
// CLSID for the notify object is. (If it has one.)
//
CComponent* pThis; pThis = CONTAINING_RECORD (this, CComponent, Notify);
// Don't bother if we can't have a notify object. Bailing here saves
// uneccesarily loading the external data for netclass components only
// to find that they won't have a notify object below.
//
if (FIsEnumerated (pThis->Class())) { return S_OK; }
HRESULT hrRet;
// Since the notify object clsid is part of the components external data,
// we have to make sure we've loaded this data.
//
hrRet = pThis->Ext.HrEnsureExternalDataLoaded (); if (S_OK != hrRet) { goto finished; }
// Don't bother if we don't have a notify object.
//
if (!pThis->Ext.FHasNotifyObject()) { return S_OK; }
// The component claims to have a notify object. Let's CoCreate it
// and see what we get.
//
HRESULT hr; INetCfgComponentControl* pCc;
hr = pINetCfg->HrCoCreateWrapper ( *(pThis->Ext.PNotifyObjectClsid()), NULL, CLSCTX_INPROC_SERVER | CLSCTX_NO_CODE_DOWNLOAD, IID_INetCfgComponentControl, (PVOID*)&pCc);
if (S_OK == hr) { // So far so good. The notify object implements the required
// INetCfgComponentControl interface.
//
// We now must get the INetCfgComponent interface that we'll
// pass to the notify object during Initialize below.
//
INetCfgComponent* pIComp; hrRet = pThis->HrGetINetCfgComponentInterface (pINetCfg, &pIComp); if (S_OK == hrRet) { // Allocate space for the various notify interfaces and QI for
// them.
//
hrRet = E_OUTOFMEMORY; m_pNod = (NOTIFY_OBJECT_DATA*) MemAlloc (sizeof(NOTIFY_OBJECT_DATA)); if (m_pNod) { hrRet = S_OK; ZeroMemory (m_pNod, sizeof(NOTIFY_OBJECT_DATA));
AddRefObj (pCc); m_pNod->pCc = pCc;
pCc->QueryInterface (IID_INetCfgComponentNotifyBinding, (PVOID*)&m_pNod->pNb);
pCc->QueryInterface (IID_INetCfgComponentPropertyUi, (PVOID*)&m_pNod->pCp);
pCc->QueryInterface (IID_INetCfgComponentSetup, (PVOID*)&m_pNod->pCs);
pCc->QueryInterface (IID_INetCfgComponentUpperEdge, (PVOID*)&m_pNod->pUe);
pCc->QueryInterface (IID_INetCfgComponentNotifyGlobal, (PVOID*)&m_pNod->pNg); if (m_pNod->pNg) { // Since it supports INetCfgComponentNotifyGlobal,
// get the mask that indicates which global notifications
// it is interested in.
//
hr = m_pNod->pNg->GetSupportedNotifications( &m_pNod->dwNotifyGlobalFlags); if (FAILED(hr)) { m_pNod->dwNotifyGlobalFlags = 0; } }
// We now need to initialize the notify object and indicate
// if we are installing its component or not.
//
pINetCfg->RaiseRpl (RPL_DISALLOW); NC_TRY { Assert (pIComp); Assert (pINetCfg); (VOID) pCc->Initialize (pIComp, pINetCfg, fInstalling); } NC_CATCH_ALL { ; // ignored
} pINetCfg->LowerRpl (RPL_DISALLOW); }
ReleaseObj (pIComp); }
ReleaseObj (pCc); }
finished: TraceHr (ttidError, FAL, hrRet, FALSE, "CNotifyObjectInterface::HrEnsureNotifyObjectInitialized"); return hrRet; }
VOID CNotifyObjectInterface::ApplyPnpChanges ( IN CImplINetCfg* pINetCfg, OUT BOOL* pfNeedReboot) const { HRESULT hr;
Assert (pINetCfg); Assert (pfNeedReboot); Assert (m_fInitialized);
*pfNeedReboot = FALSE;
if (!m_pNod) { return; }
Assert (m_pNod->pCc);
CComponent* pThis; pThis = CONTAINING_RECORD (this, CComponent, Notify);
pINetCfg->RaiseRpl (RPL_DISALLOW); NC_TRY { g_pDiagCtx->Printf (ttidBeDiag, " calling %S->ApplyPnpChanges\n", pThis->m_pszInfId);
hr = m_pNod->pCc->ApplyPnpChanges (pINetCfg);
if (FAILED(hr) || (NETCFG_S_REBOOT == hr)) { *pfNeedReboot = TRUE; } } NC_CATCH_ALL { *pfNeedReboot = TRUE; } pINetCfg->LowerRpl (RPL_DISALLOW); }
VOID CNotifyObjectInterface::ApplyRegistryChanges ( IN CImplINetCfg* pINetCfg, OUT BOOL* pfNeedReboot) const { HRESULT hr;
Assert (pINetCfg); Assert (pfNeedReboot); Assert (m_fInitialized);
*pfNeedReboot = FALSE;
if (!m_pNod) { return; }
Assert (m_pNod->pCc);
pINetCfg->RaiseRpl (RPL_DISALLOW); NC_TRY { hr = m_pNod->pCc->ApplyRegistryChanges ();
if (FAILED(hr) || (NETCFG_S_REBOOT == hr)) { *pfNeedReboot = TRUE; } } NC_CATCH_ALL { *pfNeedReboot = TRUE; } pINetCfg->LowerRpl (RPL_DISALLOW); }
HRESULT CNotifyObjectInterface::HrGetInterfaceIdsForAdapter ( IN CImplINetCfg* pINetCfg, IN const CComponent* pAdapter, OUT DWORD* pcInterfaces, OUT GUID** ppguidInterfaceIds) const { HRESULT hr;
Assert (pAdapter); Assert (pcInterfaces);
Assert (m_fInitialized);
*pcInterfaces = 0; if (ppguidInterfaceIds) { *ppguidInterfaceIds = NULL; }
if (!m_pNod || !m_pNod->pUe) { return S_FALSE; }
Assert (pAdapter->GetINetCfgComponentInterface());
pINetCfg->RaiseRpl (RPL_DISALLOW); NC_TRY { hr = m_pNod->pUe->GetInterfaceIdsForAdapter ( pAdapter->GetINetCfgComponentInterface(), pcInterfaces, ppguidInterfaceIds);
if (S_FALSE == hr) { *pcInterfaces = 0; if (ppguidInterfaceIds) { *ppguidInterfaceIds = NULL; } } } NC_CATCH_ALL { ; // ignored
} pINetCfg->LowerRpl (RPL_DISALLOW);
TraceHr (ttidError, FAL, hr, (S_FALSE == hr), "CNotifyObjectInterface::HrGetInterfaceIdsForAdapter"); return hr; }
HRESULT CNotifyObjectInterface::HrQueryPropertyUi ( IN CImplINetCfg* pINetCfg, IN IUnknown* punkContext OPTIONAL) { HRESULT hr; CComponent* pThis;
Assert (this); Assert (pINetCfg); Assert (m_fInitialized);
if (!m_pNod || !m_pNod->pCp) { return S_FALSE; }
pThis = CONTAINING_RECORD (this, CComponent, Notify); Assert (pThis);
if (!(pThis->m_dwCharacter & NCF_HAS_UI)) { return S_FALSE; }
hr = S_OK;
pINetCfg->RaiseRpl (RPL_DISALLOW); NC_TRY { Assert (m_pNod && m_pNod->pCp);
hr = m_pNod->pCp->QueryPropertyUi (punkContext); } NC_CATCH_ALL { hr = E_UNEXPECTED; } pINetCfg->LowerRpl (RPL_DISALLOW);
TraceHr (ttidError, FAL, hr, FALSE, "CNotifyObjectInterface::HrQueryPropertyUi"); return hr; }
HRESULT CNotifyObjectInterface::HrShowPropertyUi ( IN CImplINetCfg* pINetCfg, IN HWND hwndParent, IN IUnknown* punkContext OPTIONAL) { HRESULT hr; DWORD cDefPages; UINT cPages; HPROPSHEETPAGE* ahpsp; PCWSTR pszStartPage;
Assert (this); Assert (pINetCfg); Assert (m_fInitialized);
if (!m_pNod || !m_pNod->pCp) { return E_NOINTERFACE; }
Assert (m_pNod && m_pNod->pCp);
// If given a context, let the notify object know what it is.
//
if (punkContext) { SetUiContext (pINetCfg, punkContext); }
hr = S_OK; cDefPages = 0; ahpsp = NULL; cPages = 0; pszStartPage = NULL;
pINetCfg->RaiseRpl (RPL_DISALLOW); NC_TRY { hr = m_pNod->pCp->MergePropPages ( &cDefPages, (BYTE**)&ahpsp, &cPages, hwndParent, &pszStartPage); } NC_CATCH_ALL { hr = E_UNEXPECTED; } pINetCfg->LowerRpl (RPL_DISALLOW);
if ((S_OK == hr) && cPages) { PROPSHEETHEADER psh; CAPAGES caPages; CAINCP cai; CComponent* pThis;
pThis = CONTAINING_RECORD (this, CComponent, Notify); Assert (pThis);
ZeroMemory(&psh, sizeof(psh)); ZeroMemory(&caPages, sizeof(caPages)); ZeroMemory(&cai, sizeof(cai));
psh.dwSize = sizeof(psh); psh.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW; psh.hwndParent = hwndParent; psh.hInstance = _Module.GetModuleInstance(); psh.pszCaption = pThis->Ext.PszDescription();
caPages.nCount = cPages; caPages.ahpsp = ahpsp;
cai.nCount = 1; cai.apncp = &m_pNod->pCp;
hr = HrNetCfgPropertySheet (&psh, caPages, pszStartPage, cai);
// S_FALSE is returned if no changes were made.
//
if (S_OK == hr) { if (pINetCfg->m_WriteLock.FIsOwnedByMe ()) { pINetCfg->m_pNetConfig->ModifyCtx.HrBeginBatchOperation (); }
BOOL bCommitNow = FALSE;
// Call ApplyProperties
//
pINetCfg->RaiseRpl (RPL_ALLOW_INSTALL_REMOVE); NC_TRY { hr = m_pNod->pCp->ApplyProperties (); if(NETCFG_S_COMMIT_NOW == hr) { bCommitNow = TRUE; } } NC_CATCH_ALL { hr = E_UNEXPECTED; } pINetCfg->LowerRpl (RPL_ALLOW_INSTALL_REMOVE);
if (pINetCfg->m_WriteLock.FIsOwnedByMe ()) { // Set this component as dirty so we call its Apply method
// if INetCfg is applied.
//
hr = pINetCfg->m_pNetConfig->ModifyCtx.HrDirtyComponent( pThis);
// Notify other components that this component changed.
//
pINetCfg->m_pNetConfig->Notify.NgSysNotifyComponent ( NCN_PROPERTYCHANGE, pThis);
hr = pINetCfg->m_pNetConfig->ModifyCtx. HrEndBatchOperation (bCommitNow ? EBO_COMMIT_NOW : EBO_DEFER_COMMIT_UNTIL_APPLY); } } else { // Don't overwrite hr. It is what we need to return.
//
// Call CancelProperties
//
pINetCfg->RaiseRpl (RPL_DISALLOW); NC_TRY { (VOID) m_pNod->pCp->CancelProperties (); } NC_CATCH_ALL { hr = E_UNEXPECTED; } pINetCfg->LowerRpl (RPL_DISALLOW); } }
// This is outside the above if in case a notify object actually
// allocates it but returns zero pages.
//
CoTaskMemFree (ahpsp);
// If given a context, let the notify object know it is no longer valid.
//
if (punkContext) { SetUiContext (pINetCfg, NULL); }
TraceHr (ttidError, FAL, hr, (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr), "CNotifyObjectInterface::HrShowPropertyUi"); return hr; }
VOID CNotifyObjectInterface::SetUiContext ( IN CImplINetCfg* pINetCfg, IN IUnknown* punkContext) { Assert (m_fInitialized); Assert (m_pNod && m_pNod->pCp);
pINetCfg->RaiseRpl (RPL_DISALLOW); NC_TRY { (VOID) m_pNod->pCp->SetContext (punkContext); } NC_CATCH_ALL { ; // ignored
} pINetCfg->LowerRpl (RPL_DISALLOW); }
VOID CNotifyObjectInterface::NbQueryOrNotifyBindingPath ( IN CImplINetCfg* pINetCfg, IN QN_FLAG Flag, IN DWORD dwChangeFlag, IN INetCfgBindingPath* pIPath, OUT BOOL* pfDisabled) { RPL_FLAGS RplFlag;
Assert (pINetCfg); Assert ((QN_QUERY == Flag) || (QN_NOTIFY == Flag)); Assert (pIPath); Assert (FImplies(QN_QUERY == Flag, pfDisabled));
Assert (m_fInitialized);
if (pfDisabled) { *pfDisabled = FALSE; }
if (m_pNod && m_pNod->pNb) { RplFlag = (QN_NOTIFY == Flag) ? RPL_ALLOW_INSTALL_REMOVE : RPL_DISALLOW;
pINetCfg->RaiseRpl (RplFlag); NC_TRY { if (QN_QUERY == Flag) { HRESULT hr;
hr = m_pNod->pNb->QueryBindingPath (dwChangeFlag, pIPath);
if (NETCFG_S_DISABLE_QUERY == hr) { *pfDisabled = TRUE; } } else { (VOID) m_pNod->pNb->NotifyBindingPath (dwChangeFlag, pIPath); } } NC_CATCH_ALL { ; // ignored
} pINetCfg->LowerRpl (RplFlag); } }
HRESULT CNotifyObjectInterface::QueryNotifyObject ( IN CImplINetCfg* pINetCfg, IN REFIID riid, OUT VOID** ppvObject) { HRESULT hr;
*ppvObject = NULL;
hr = HrEnsureNotifyObjectInitialized (pINetCfg, FALSE); if (S_OK == hr) { if (m_pNod && m_pNod->pCc) { hr = m_pNod->pCc->QueryInterface (riid, ppvObject); } else { hr = E_NOINTERFACE; } } TraceHr (ttidError, FAL, hr, FALSE, "CNotifyObjectInterface::QueryNotifyObject"); return hr; }
VOID CNotifyObjectInterface::ReleaseNotifyObject ( IN CImplINetCfg* pINetCfg, IN BOOL fCancel) { Assert (FIff(pINetCfg, fCancel));
if (m_pNod) { // Tell the notify object to cancel if requested.
//
if (fCancel) { pINetCfg->RaiseRpl (RPL_DISALLOW); NC_TRY { (VOID) m_pNod->pCc->CancelChanges (); } NC_CATCH_ALL { ; // ignored
} pINetCfg->LowerRpl (RPL_DISALLOW); }
// Release all of the interfaces we are holding.
//
ReleaseObj (m_pNod->pCc); ReleaseObj (m_pNod->pNb); ReleaseObj (m_pNod->pCp); ReleaseObj (m_pNod->pCs); ReleaseObj (m_pNod->pUe); ReleaseObj (m_pNod->pNg);
MemFree (m_pNod); m_pNod = NULL; } m_fInitialized = FALSE; }
HRESULT CNotifyObjectInterface::NewlyAdded ( IN CImplINetCfg* pINetCfg, IN const NETWORK_INSTALL_PARAMS* pnip) { HRESULT hr;
//$REVIEW: Calling HrEnsureNotifyObjectInitialized is probably not needed
// because when we have the write lock and call notify objects, we always
// ensure they are loaded before we get here.
//
hr = HrEnsureNotifyObjectInitialized (pINetCfg, TRUE); if ((S_OK == hr) && m_pNod && m_pNod->pCs) { // Inform the notify object that its component is being installed
// and tell it to read the answerfile if we are using one.
//
DWORD dwSetupFlags;
if (pnip) { dwSetupFlags = pnip->dwSetupFlags; } else { dwSetupFlags = FInSystemSetup() ? NSF_PRIMARYINSTALL : NSF_POSTSYSINSTALL; }
// Raise the reentrancy protection level to only allow
// install or remove before calling the notify object's Install
// method.
//
pINetCfg->RaiseRpl (RPL_ALLOW_INSTALL_REMOVE); NC_TRY { hr = m_pNod->pCs->Install (dwSetupFlags);
if (SUCCEEDED(hr) && pnip && pnip->pszAnswerFile && pnip->pszAnswerSection) { // Raise the reentrancy protection level to disallow
// all reentrancy before calling the notify object's
// ReadAnswerFile method.
//
pINetCfg->RaiseRpl (RPL_DISALLOW); NC_TRY { hr = m_pNod->pCs->ReadAnswerFile ( pnip->pszAnswerFile, pnip->pszAnswerSection); } NC_FINALLY { pINetCfg->LowerRpl (RPL_DISALLOW); } } } NC_CATCH_ALL { ; } pINetCfg->LowerRpl (RPL_ALLOW_INSTALL_REMOVE);
hr = S_OK; }
TraceHr (ttidError, FAL, hr, FALSE, "CNotifyObjectInterface::NewlyAdded"); return hr; }
VOID CNotifyObjectInterface::Removed ( IN CImplINetCfg* pINetCfg) { Assert (m_fInitialized);
if (!m_pNod || !m_pNod->pCs) { return; }
// Raise the reentrancy protection level to only allow
// install or remove before calling the notify object's Install
// method.
//
pINetCfg->RaiseRpl (RPL_ALLOW_INSTALL_REMOVE); NC_TRY { // Inform the notify object that its component is being removed.
//
(VOID) m_pNod->pCs->Removing (); } NC_CATCH_ALL { ; } pINetCfg->LowerRpl (RPL_ALLOW_INSTALL_REMOVE); }
VOID CNotifyObjectInterface::Updated ( IN CImplINetCfg* pINetCfg, IN DWORD dwSetupFlags, IN DWORD dwUpgradeFromBuildNo) { Assert (m_fInitialized);
if (!m_pNod || !m_pNod->pCs) { return; }
// Raise the reentrancy protection level to only allow
// install or remove before calling the notify object's Install
// method.
//
pINetCfg->RaiseRpl (RPL_ALLOW_INSTALL_REMOVE); NC_TRY { HRESULT hrNotify;
// Inform the notify object that its component is being updated.
//
hrNotify = m_pNod->pCs->Upgrade (dwSetupFlags, dwUpgradeFromBuildNo);
// If Upgrade returns S_OK, it means they recognized and
// handled the event and are now dirty because of it.
//
if (S_OK == hrNotify) { CComponent* pThis;
pThis = CONTAINING_RECORD (this, CComponent, Notify); Assert (pThis);
(VOID) pINetCfg->m_pNetConfig->ModifyCtx. HrDirtyComponent (pThis); } } NC_CATCH_ALL { ; } pINetCfg->LowerRpl (RPL_ALLOW_INSTALL_REMOVE); }
//+---------------------------------------------------------------------------
// CGlobalNotifyInterface -
//
VOID CGlobalNotifyInterface::HoldINetCfg ( CImplINetCfg* pINetCfg) { AssertH (pINetCfg); AssertH (!m_pINetCfg);
AddRefObj (pINetCfg->GetUnknown()); m_pINetCfg = pINetCfg; }
VOID CGlobalNotifyInterface::ReleaseAllNotifyObjects ( IN CComponentList& Components, IN BOOL fCancel) { CComponentList::iterator iter; CComponent* pComponent; CImplINetCfg* pINetCfg;
// We need to pass a non-NULL pINetCfg if we are not cancelling.
//
pINetCfg = (fCancel) ? m_pINetCfg : NULL;
for (iter = Components.begin(); iter != Components.end(); iter++) { pComponent = *iter; Assert (pComponent);
pComponent->Notify.ReleaseNotifyObject (pINetCfg, fCancel); }
m_fInitialized = FALSE; }
VOID CGlobalNotifyInterface::ReleaseINetCfg () { // If we have a cached INetCfg interface, we need to tell it
// that we no longer exist. Then we need to release the interface,
// of course.
//
if (m_pINetCfg) { // Get our containing CNetConfig pointer.
//
CNetConfig* pThis; pThis = CONTAINING_RECORD(this, CNetConfig, Notify);
Assert (pThis == m_pINetCfg->m_pNetConfig); m_pINetCfg->m_pNetConfig = NULL; ReleaseObj (m_pINetCfg->GetUnknown()); m_pINetCfg = NULL; } }
HRESULT CGlobalNotifyInterface::HrEnsureNotifyObjectsInitialized () { // If we've already been through initialization, return immediately.
//
if (m_fInitialized) { return S_OK; }
// Only perform initialization once, regardless of whether it succeeds
// or not.
//
m_fInitialized = TRUE;
// Get our containing CNetConfig pointer so we can enumerate all components.
//
CNetConfig* pThis; pThis = CONTAINING_RECORD(this, CNetConfig, Notify);
HRESULT hr = S_OK;
// If we don't have an INetCfg interface pointer yet, it means we are
// creating one instead of it creating CNetConfig. If we had one, it
// would have been handed to us via HoldINetCfg which is called when
// CNetConfig is created by CImplINetCfg.
//
if (!m_pINetCfg) { hr = CImplINetCfg::HrCreateInstance (pThis, &m_pINetCfg); Assert (!m_pINetCfg->m_fOwnNetConfig); }
if (S_OK == hr) { Assert (m_pINetCfg);
CComponentList::iterator iter; CComponent* pComponent; for (iter = pThis->Core.Components.begin(); iter != pThis->Core.Components.end(); iter++) { pComponent = *iter; Assert (pComponent);
hr = pComponent->Notify.HrEnsureNotifyObjectInitialized (m_pINetCfg, FALSE); if (S_OK != hr) { break; } } }
TraceHr (ttidError, FAL, hr, FALSE, "CGlobalNotifyInterface::HrEnsureNotifyObjectsInitialized"); return hr; }
VOID CGlobalNotifyInterface::NgSysQueryOrNotifyBindingPath ( IN QN_FLAG Flag, IN DWORD dwChangeFlag, IN INetCfgBindingPath* pIPath, IN BOOL* pfDisabled) { RPL_FLAGS RplFlag; CNetConfig* pThis; CComponentList::iterator iter; CComponent* pComponent;
Assert (m_pINetCfg); Assert ((QN_QUERY == Flag) || (QN_NOTIFY == Flag)); Assert (pIPath); Assert (FImplies(QN_QUERY == Flag, pfDisabled));
Assert (m_fInitialized);
if (pfDisabled) { *pfDisabled = FALSE; }
// Get our containing CNetConfig pointer so we can enumerate
// all components.
//
pThis = CONTAINING_RECORD(this, CNetConfig, Notify);
RplFlag = (QN_NOTIFY == Flag) ? RPL_ALLOW_INSTALL_REMOVE : RPL_DISALLOW;
m_pINetCfg->RaiseRpl (RplFlag);
for (iter = pThis->Core.Components.begin(); iter != pThis->Core.Components.end(); iter++) { pComponent = *iter; Assert (pComponent);
if (!pComponent->Notify.m_pNod || !pComponent->Notify.m_pNod->pNg || !(pComponent->Notify.m_pNod->dwNotifyGlobalFlags & NCN_BINDING_PATH)) { continue; }
// If the component has not registered for what we are changing,
// (NCN_ADD, NCN_REMOVE, NCN_ENABLE, NCN_DISABLE) then
// skip it.
//
if (!(pComponent->Notify.m_pNod->dwNotifyGlobalFlags & dwChangeFlag)) { continue; }
NC_TRY { HRESULT hr;
if (QN_QUERY == Flag) { hr = pComponent->Notify.m_pNod->pNg-> SysQueryBindingPath (dwChangeFlag, pIPath);
if (NETCFG_S_DISABLE_QUERY == hr) { *pfDisabled = TRUE; break; } } else { hr = pComponent->Notify.m_pNod->pNg-> SysNotifyBindingPath (dwChangeFlag, pIPath);
// If SysNotifyBindingPath returns S_OK, it means they
// recognized and handled the event and are now dirty
// because of it. Because some notify objects let
// success codes such as NETCFG_S_REBOOT slip through,
// consider them dirty if they don't return S_FALSE.
//
if (S_FALSE != hr) { hr = m_pINetCfg->m_pNetConfig->ModifyCtx. HrDirtyComponent(pComponent); } } } NC_CATCH_ALL { ; } }
m_pINetCfg->LowerRpl (RplFlag); }
HRESULT CGlobalNotifyInterface::NgSysNotifyComponent ( IN DWORD dwChangeFlag, IN CComponent* pComponentOfInterest) { HRESULT hr; INetCfgComponent* pICompOfInterest;
// We should have called HrEnsureNotifyObjectsInitialized by now.
//
Assert (m_fInitialized);
// If the component of interest has not had its data loaded successfully,
// we shouldn't bother sending the notification. The notify objects are
// just going to call back on the interface to the component and fail
// if they call a method that requires this data.
//
if (!pComponentOfInterest->Ext.FLoadedOkayIfLoadedAtAll()) { return S_OK; }
hr = pComponentOfInterest->HrGetINetCfgComponentInterface ( m_pINetCfg, &pICompOfInterest);
if (S_OK == hr) { DWORD dwMask = 0; NETCLASS Class = pComponentOfInterest->Class(); CNetConfig* pThis; CComponentList::iterator iter; CComponent* pComponent;
if (FIsConsideredNetClass(Class)) { dwMask = NCN_NET; } else if (NC_NETTRANS == Class) { dwMask = NCN_NETTRANS; } else if (NC_NETCLIENT == Class) { dwMask = NCN_NETCLIENT; } else if (NC_NETSERVICE == Class) { dwMask = NCN_NETSERVICE; }
// Get our containing CNetConfig pointer so we can enumerate
// all components.
//
pThis = CONTAINING_RECORD(this, CNetConfig, Notify);
// Raise the reentrancy protection level to only allow
// install or remove before calling the notify object's
// SysNotifyComponent method.
//
m_pINetCfg->RaiseRpl (RPL_ALLOW_INSTALL_REMOVE);
for (iter = pThis->Core.Components.begin(); iter != pThis->Core.Components.end(); iter++) { pComponent = *iter; Assert (pComponent);
if (!pComponent->Notify.m_pNod || !pComponent->Notify.m_pNod->pNg) { continue; }
// If the component has not registered for one of NCN_NET,
// NCN_NETTRANS, etc. then skip it.
//
if (!(pComponent->Notify.m_pNod->dwNotifyGlobalFlags & dwMask)) { continue; }
// If the component has not registered for what we are changing,
// (NCN_ADD, NCN_REMOVE, NCN_UPDATE, NCN_PROPERTYCHANGE) then
// skip it.
//
if (!(pComponent->Notify.m_pNod->dwNotifyGlobalFlags & dwChangeFlag)) { continue; }
NC_TRY { HRESULT hrNotify;
hrNotify = pComponent->Notify.m_pNod->pNg->SysNotifyComponent ( dwMask | dwChangeFlag, pICompOfInterest);
// If SysNotifyComponent returns S_OK, it means they
// recognized and handled the event and are now dirty
// because of it. Because some notify objects let
// success codes such as NETCFG_S_REBOOT slip through,
// consider them dirty if they don't return S_FALSE.
//
if (S_FALSE != hrNotify) { hr = m_pINetCfg->m_pNetConfig->ModifyCtx. HrDirtyComponent(pComponent); } } NC_CATCH_ALL { ; } }
m_pINetCfg->LowerRpl (RPL_ALLOW_INSTALL_REMOVE);
ReleaseObj (pICompOfInterest); }
TraceHr (ttidError, FAL, hr, FALSE, "CGlobalNotifyInterface::NgSysNotifyComponent"); return hr; }
HRESULT CGlobalNotifyInterface::ComponentAdded ( IN CComponent* pComponent, IN const NETWORK_INSTALL_PARAMS* pnip) { HRESULT hr;
Assert (pComponent);
// Initialize the notify object for the component and call
// its Install method followed by ReadAnswerFile if we are installing
// with one.
//
hr = pComponent->Notify.NewlyAdded (m_pINetCfg, pnip); if (S_OK == hr) { // Notify all notify objects that are interested in component
// additions.
//
hr = NgSysNotifyComponent(NCN_ADD, pComponent); }
TraceHr (ttidError, FAL, hr, FALSE, "CGlobalNotifyInterface::ComponentAdded"); return hr; }
HRESULT CGlobalNotifyInterface::ComponentRemoved ( IN CComponent* pComponent) { HRESULT hr;
Assert (pComponent);
pComponent->Notify.Removed (m_pINetCfg);
hr = NgSysNotifyComponent(NCN_REMOVE, pComponent);
TraceHr (ttidError, FAL, hr, FALSE, "CGlobalNotifyInterface::ComponentRemoved"); return hr; }
HRESULT CGlobalNotifyInterface::ComponentUpdated ( IN CComponent* pComponent, IN DWORD dwSetupFlags, IN DWORD dwUpgradeFromBuildNo) { HRESULT hr;
Assert (pComponent);
pComponent->Notify.Updated (m_pINetCfg, dwSetupFlags, dwUpgradeFromBuildNo);
hr = NgSysNotifyComponent(NCN_UPDATE, pComponent);
TraceHr (ttidError, FAL, hr, FALSE, "CGlobalNotifyInterface::ComponentUpdated"); return hr; }
VOID CGlobalNotifyInterface::NotifyBindPath ( IN DWORD dwChangeFlag, IN CBindPath* pBindPath, IN INetCfgBindingPath* pIPath OPTIONAL) { HRESULT hr; CImplINetCfg* pINetCfg; CComponent* pOwner; BOOL fReleasePath;
Assert (m_fInitialized); Assert ((dwChangeFlag & NCN_ADD) || (dwChangeFlag & NCN_REMOVE) || (dwChangeFlag & NCN_ENABLE) || (dwChangeFlag & NCN_DISABLE)); Assert (FImplies(dwChangeFlag & NCN_REMOVE, !(dwChangeFlag & NCN_DISABLE))); Assert (FImplies(dwChangeFlag & NCN_ADD, !(dwChangeFlag & NCN_REMOVE))); Assert (FImplies(dwChangeFlag & NCN_REMOVE, !(dwChangeFlag & NCN_ADD))); Assert (pBindPath);
hr = S_OK; pINetCfg = PINetCfg(); pOwner = pBindPath->POwner(); fReleasePath = FALSE;
// Create an INetCfgBindingPath representation of the path for
// the notify objects if we were not given one.
//
if (!pIPath) { // If the bindpath contains components that have had a problem
// loading, we shouldn't bother sending the notification.
// The notify objects are just going to call back on the interface
// to the component and fail if they call a method that requires
// this data.
//
if (!pBindPath->FAllComponentsLoadedOkayIfLoadedAtAll()) { return; }
hr = CImplINetCfgBindingPath::HrCreateInstance ( pINetCfg, pBindPath, &pIPath);
fReleasePath = TRUE; }
if (S_OK == hr) { Assert (pIPath);
// If adding...
//
if (dwChangeFlag & NCN_ADD) { BOOL fDisabled;
fDisabled = FALSE;
// First, query the owner of the bindpath to see if he wants
// it disabled.
//
pOwner->Notify.NbQueryOrNotifyBindingPath ( pINetCfg, QN_QUERY, dwChangeFlag, pIPath, &fDisabled);
// If the owner doesn't want it disabled, see if any global
// notify objects do.
//
if (!fDisabled) { NgSysQueryOrNotifyBindingPath ( QN_QUERY, dwChangeFlag, pIPath, &fDisabled); }
// If someone wants it disabled, adjust the change flag
// for notify and add the bindpath to our disabled list.
//
if (fDisabled) { dwChangeFlag = NCN_ADD | NCN_DISABLE;
(VOID)pINetCfg->m_pNetConfig->Core.HrDisableBindPath (pBindPath); } }
//if (g_pDiagCtx->Flags() & DF_SHOW_CONSOLE_OUTPUT)
{ WCHAR pszBindPath [1024]; ULONG cch;
cch = celems(pszBindPath) - 1; if (pBindPath->FGetPathToken (pszBindPath, &cch)) { g_pDiagCtx->Printf (ttidBeDiag, " %S (%s)\n", pszBindPath, (dwChangeFlag & NCN_ENABLE) ? "enabled" : (dwChangeFlag & NCN_DISABLE) ? "disabled" : "removed"); } }
pOwner->Notify.NbQueryOrNotifyBindingPath ( pINetCfg, QN_NOTIFY, dwChangeFlag, pIPath, NULL);
NgSysQueryOrNotifyBindingPath ( QN_NOTIFY, dwChangeFlag, pIPath, NULL);
if (fReleasePath) { ReleaseObj (pIPath); } } }
HRESULT CGlobalNotifyInterface::QueryAndNotifyBindPaths ( IN DWORD dwBaseChangeFlag, IN CBindingSet* pBindSet, IN UINT cSkipFirstBindPaths) { CBindPath* pBindPath; DWORD dwChangeFlag; PCSTR pszDiagMsg;
// We should have called HrEnsureNotifyObjectsInitialized by now.
//
Assert (m_fInitialized); Assert ((dwBaseChangeFlag & NCN_ADD) || (dwBaseChangeFlag & NCN_REMOVE));
if (dwBaseChangeFlag & NCN_ADD) { dwChangeFlag = NCN_ADD | NCN_ENABLE; pszDiagMsg = "Query and notify the following bindings:\n"; } else { dwChangeFlag = NCN_REMOVE; pszDiagMsg = "Notify the following bindings are removed:\n"; }
g_pDiagCtx->Printf (ttidBeDiag, pszDiagMsg);
// Iterate the newly added bindpaths by picking up where the
// previous set ended and going to the end of the binding set.
// Note, because this may recurse, pBindSet may change during
// iteration, so a simple pointer increment through begin() to end()
// may fail if the bindset is reallocated or grown.
// Note too that we save off the current count of bindpaths in
// iStopAtBindPath. If we did not, when we come out of a recursion where
// the binding set grew, we'd re-notify the newly added bindpaths
// if we used a direct comparison of 'i < pBindSet->CountBindPaths()'.
//
UINT iStopAtBindPath = pBindSet->CountBindPaths();
for (UINT i = cSkipFirstBindPaths; i < iStopAtBindPath; i++) { pBindPath = pBindSet->PGetBindPathAtIndex(i);
NotifyBindPath (dwChangeFlag, pBindPath, NULL); }
return S_OK; }
|