|
|
//depot/private/homenet/net/homenet/Config/CfgMgr/HNBridge.cpp#13 - edit change 5915 (text)
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997 - 2000
//
// File: H N B R I D G E . C P P
//
// Contents: CHNBridge implementation
//
// Notes:
//
// Author: jonburs 23 June 2000
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
//
// IHNetBridge Methods
//
STDMETHODIMP CHNBridge::EnumMembers( IEnumHNetBridgedConnections **ppEnum )
{ HRESULT hr; CComObject<CEnumHNetBridgedConnections> *pEnum; INetCfgComponent *pBridgeProtocol = NULL; INetCfg *pnetcfg; IHNetBridgedConnection **rgBridgedAdapters = NULL; ULONG ulCountAdapters = 0L;
if( NULL != ppEnum ) { *ppEnum = NULL;
hr = CoCreateInstance( CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_DISABLE_AAA, IID_PPV_ARG(INetCfg, &pnetcfg));
if( S_OK == hr ) { hr = pnetcfg->Initialize( NULL );
if( S_OK == hr ) { hr = pnetcfg->FindComponent( c_wszSBridgeSID, &pBridgeProtocol );
if( S_OK == hr ) { INetCfgComponentBindings *pnetcfgProtocolBindings;
// Get the ComponentBindings interface for the protocol component
hr = pBridgeProtocol->QueryInterface( IID_PPV_ARG(INetCfgComponentBindings, &pnetcfgProtocolBindings) );
if( S_OK == hr ) { const GUID guidDevClass = GUID_DEVCLASS_NET; IEnumNetCfgComponent *penumncfgcomp; INetCfgComponent *pnetcfgcomp;
//
// Get the list of NET (adapter) devices
//
hr = pnetcfg->EnumComponents( &guidDevClass, &penumncfgcomp );
if( S_OK == hr ) { ULONG ul;
//
// Examine each adapter to see if it's bound to the bridge protocol
//
while( (S_OK == hr) && (S_OK == penumncfgcomp->Next(1, &pnetcfgcomp, &ul)) ) { _ASSERT( 1L == ul ); hr = pnetcfgProtocolBindings->IsBoundTo(pnetcfgcomp);
if( S_OK == hr ) { IHNetBridgedConnection *pBridgedConnection;
//
// The bridge protocol is bound to this adapter. Turn the NetCfg component
// interface into an IHNetBridgedConnection.
//
hr = GetIHNetConnectionForNetCfgComponent( m_piwsHomenet, pnetcfgcomp, TRUE, IID_PPV_ARG(IHNetBridgedConnection, &pBridgedConnection) );
if( S_OK == hr ) { IHNetBridgedConnection **ppNewArray;
//
// Add the new IHNetBridgedConnection to our array
//
ppNewArray = reinterpret_cast<IHNetBridgedConnection**>(CoTaskMemRealloc( rgBridgedAdapters, (ulCountAdapters + 1) * sizeof(IHNetBridgedConnection*) ));
if( NULL == ppNewArray ) { hr = E_OUTOFMEMORY; // rgBridgedAdapters will be cleaned up below
} else { // Use the newly grown array
rgBridgedAdapters = ppNewArray; rgBridgedAdapters[ulCountAdapters] = pBridgedConnection; ulCountAdapters++; pBridgedConnection->AddRef(); }
pBridgedConnection->Release(); } } else if( S_FALSE == hr ) { // The bridge protocol is not bound to this adapter. Reset hr to success.
hr = S_OK; }
pnetcfgcomp->Release(); }
penumncfgcomp->Release(); }
pnetcfgProtocolBindings->Release(); }
pBridgeProtocol->Release(); }
pnetcfg->Uninitialize(); }
pnetcfg->Release(); }
//
// Turn the array of bridge members into an enumeration
//
if( S_OK == hr ) { hr = CComObject<CEnumHNetBridgedConnections>::CreateInstance(&pEnum);
if( SUCCEEDED(hr) ) { pEnum->AddRef();
hr = pEnum->Initialize(rgBridgedAdapters, ulCountAdapters);
if( SUCCEEDED(hr) ) { hr = pEnum-> QueryInterface( IID_PPV_ARG(IEnumHNetBridgedConnections, ppEnum) ); }
pEnum->Release(); } }
//
// The enumeration made a copy of the array and AddRef()ed the members.
// Ditch it now.
//
if( rgBridgedAdapters ) { ULONG i;
_ASSERT( ulCountAdapters );
for( i = 0; i < ulCountAdapters; i++ ) { _ASSERT( rgBridgedAdapters[i] ); rgBridgedAdapters[i]->Release(); }
CoTaskMemFree( rgBridgedAdapters ); } } else { hr = E_POINTER; }
return hr; }
STDMETHODIMP CHNBridge::AddMember( IHNetConnection *pConn, IHNetBridgedConnection **ppBridgedConn, INetCfg *pnetcfgExisting )
{ HRESULT hr = S_OK;
if (NULL == ppBridgedConn) { hr = E_POINTER; } else { *ppBridgedConn = NULL;
if (NULL == pConn) { hr = E_INVALIDARG; } }
if (ProhibitedByPolicy(NCPERM_AllowNetBridge_NLA)) { hr = HN_E_POLICY; }
//
// Make sure that it's permissible to add this connection
// to a bridge
//
if (S_OK == hr) { HNET_CONN_PROPERTIES *pProps;
hr = pConn->GetProperties(&pProps);
if (S_OK == hr) { if (!pProps->fCanBeBridged) { hr = E_UNEXPECTED; }
CoTaskMemFree(pProps); } }
//
// Bind the adapter to the bridge
//
if (S_OK == hr) { GUID *pguidAdapter;
hr = pConn->GetGuid (&pguidAdapter);
if (S_OK == hr) { hr = BindNewAdapter (pguidAdapter, pnetcfgExisting); CoTaskMemFree(pguidAdapter); } }
if (SUCCEEDED(hr)) { if( NULL != pnetcfgExisting ) { // Need to apply the changes for the next call to succeed
hr = pnetcfgExisting->Apply(); }
if( SUCCEEDED(hr) ) { // We should now be able to turn the provided connection into
// an IHNetBridgedConnection
hr = pConn->GetControlInterface( IID_PPV_ARG(IHNetBridgedConnection, ppBridgedConn) );
// There is no good way to recover if this last operation failed
_ASSERT( SUCCEEDED(hr) );
//
// Inform netman that something changed. Error doesn't matter.
//
UpdateNetman(); } }
return hr; }
STDMETHODIMP CHNBridge::Destroy( INetCfg *pnetcfgExisting )
{ HRESULT hr = S_OK; IEnumHNetBridgedConnections *pEnum; IHNetBridgedConnection *pConn; GUID *pGuid = NULL;
if (ProhibitedByPolicy(NCPERM_AllowNetBridge_NLA)) { hr = HN_E_POLICY; }
// Remember our connection GUID before we destroy it
hr = GetGuid( &pGuid );
if (SUCCEEDED(hr)) { //
// Get the enumeration of our members
//
hr = EnumMembers(&pEnum);
if (S_OK == hr) { ULONG ulCount;
//
// Remove each member from the bridge
//
do { hr = pEnum->Next( 1, &pConn, &ulCount );
if (SUCCEEDED(hr) && 1 == ulCount) { hr = pConn->RemoveFromBridge( pnetcfgExisting ); pConn->Release(); } } while (SUCCEEDED(hr) && 1 == ulCount);
pEnum->Release(); } } else { _ASSERT( NULL == pGuid ); }
if (SUCCEEDED(hr)) { //
// Remove the miniport
//
hr = RemoveMiniport( pnetcfgExisting ); }
if (SUCCEEDED(hr)) { //
// Delete the WMI objects
//
hr = m_piwsHomenet->DeleteInstance( m_bstrProperties, 0, NULL, NULL );
if (WBEM_S_NO_ERROR == hr) { hr = m_piwsHomenet->DeleteInstance( m_bstrConnection, 0, NULL, NULL ); } }
if (WBEM_S_NO_ERROR == hr) { //
// Inform netman that something changed. Error doesn't matter.
//
UpdateNetman();
// Refresh the UI to remove this connection
_ASSERT( NULL != pGuid ); SignalDeletedConnection( pGuid ); }
if( NULL != pGuid ) { CoTaskMemFree( pGuid ); }
return hr; }
HRESULT CHNBridge::RemoveMiniport( IN OPTIONAL INetCfg *pnetcfgExisting ) { HRESULT hr = S_OK; INetCfg *pnetcfg = NULL; INetCfgLock *pncfglock = NULL; GUID *pguid;
if( NULL == pnetcfgExisting ) { hr = InitializeNetCfgForWrite( &pnetcfg, &pncfglock );
// Bail out if we failed to get a netcfg context
if( FAILED(hr) ) { return hr; } } else { // Use the NetCfg context we were given
pnetcfg = pnetcfgExisting; }
// We must have a NetCfg context at this point
_ASSERT( pnetcfg != NULL );
hr = GetGuid( &pguid );
if ( SUCCEEDED(hr) ) { INetCfgComponent *pnetcfgcomp;
//
// Locate ourselves by GUID
//
hr = FindAdapterByGUID(pnetcfg, pguid, &pnetcfgcomp);
if ( SUCCEEDED(hr) ) { const GUID guidDevClass = GUID_DEVCLASS_NET; INetCfgClassSetup *pncfgsetup = NULL;
//
// Recover the NetCfgClassSetup interface
//
hr = pnetcfg->QueryNetCfgClass( &guidDevClass, IID_PPV_ARG(INetCfgClassSetup, &pncfgsetup) );
if ( SUCCEEDED(hr) ) { //
// Blow away this instance of the bridge
//
hr = pncfgsetup->DeInstall( pnetcfgcomp, NULL, NULL );
pncfgsetup->Release(); }
// Done with the bridge component
pnetcfgcomp->Release(); }
CoTaskMemFree(pguid); }
// If we created our own NetCfg context, shut it down now
if( NULL == pnetcfgExisting ) { // Apply everything if we succeeded, back out otherwise
if ( SUCCEEDED(hr) ) { hr = pnetcfg->Apply(); } else { // Don't want to lose the original error code
pnetcfg->Cancel(); }
UninitializeNetCfgForWrite( pnetcfg, pncfglock ); }
return hr; }
HRESULT CHNBridge::BindNewAdapter( IN GUID *pguid, IN OPTIONAL INetCfg *pnetcfgExisting ) { HRESULT hr = S_OK; INetCfg *pnetcfg = NULL; INetCfgLock *pncfglock = NULL; INetCfgComponent *pnetcfgcomp;
if( NULL == pnetcfgExisting ) { hr = InitializeNetCfgForWrite( &pnetcfg, &pncfglock );
// Bail out if we failed to get a netcfg context
if( FAILED(hr) ) { return hr; } } else { // Use the NetCfg context we were given
pnetcfg = pnetcfgExisting; }
// We must have a NetCfg context at this point
_ASSERT( pnetcfg != NULL );
hr = FindAdapterByGUID( pnetcfg, pguid, &pnetcfgcomp );
if ( SUCCEEDED(hr) ) { hr = BindOnlyToBridge( pnetcfgcomp ); pnetcfgcomp->Release(); }
// If we created our own NetCfg context, shut it down now
if( NULL == pnetcfgExisting ) { // Apply everything if we succeeded, back out otherwise
if ( SUCCEEDED(hr) ) { hr = pnetcfg->Apply();
// Redraw this connection
SignalModifiedConnection( pguid ); } else { // Don't want to lose the original error code
pnetcfg->Cancel(); }
UninitializeNetCfgForWrite( pnetcfg, pncfglock ); }
return hr; }
|