790 lines
19 KiB
C++
790 lines
19 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1999-2001 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// ConnectionManager.cpp
|
|
//
|
|
// Description:
|
|
// Connection Manager implementation.
|
|
//
|
|
// Maintained By:
|
|
// Galen Barbee (GalenB) 22-NOV-1999
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "pch.h"
|
|
#include "ConnectionManager.h"
|
|
|
|
DEFINE_THISCLASS("CConnectionManager")
|
|
#define THISCLASS CConnectionManager
|
|
|
|
// ************************************************************************
|
|
//
|
|
// Constructor / Destructor
|
|
//
|
|
// ************************************************************************
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HRESULT
|
|
// CConnectionManager::S_HrCreateInstance(
|
|
// IUnknown ** ppunkOut
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CConnectionManager::S_HrCreateInstance(
|
|
IUnknown ** ppunkOut
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
Assert( ppunkOut != NULL );
|
|
|
|
HRESULT hr;
|
|
|
|
CConnectionManager * pcm = new CConnectionManager();
|
|
if ( pcm != NULL )
|
|
{
|
|
hr = THR( pcm->Init() );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = THR( pcm->TypeSafeQI( IUnknown, ppunkOut ) );
|
|
} // if: success
|
|
|
|
pcm->Release();
|
|
|
|
} // if: got object
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
} // else: out of memory
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CConnectionManager::S_HrCreateInstance();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CConnectionManager::CConnectionManager( void )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CConnectionManager::CConnectionManager( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
InterlockedIncrement( &g_cObjects );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CConnectionManager::CConnectionManager()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP
|
|
// CConnectionManager::Init( void )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CConnectionManager::Init( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
// IUnknown stuff
|
|
Assert( m_cRef == 0 );
|
|
AddRef();
|
|
|
|
HRETURN( S_OK );
|
|
|
|
} //*** CConnectionManager::Init()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CConnectionManager::~CConnectionManager()
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CConnectionManager::~CConnectionManager()
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
InterlockedDecrement( &g_cObjects );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CConnectionManager::~CConnectionManager()
|
|
|
|
|
|
// ************************************************************************
|
|
//
|
|
// IUnknown
|
|
//
|
|
// ************************************************************************
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP
|
|
// CConnectionManager::QueryInterface(
|
|
// REFIID riid,
|
|
// LPVOID * ppv
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CConnectionManager::QueryInterface(
|
|
REFIID riid,
|
|
LPVOID * ppv
|
|
)
|
|
{
|
|
TraceQIFunc( riid, ppv );
|
|
|
|
HRESULT hr = E_NOINTERFACE;
|
|
|
|
if ( IsEqualIID( riid, IID_IUnknown ) )
|
|
{
|
|
*ppv = static_cast< IConnectionManager * >( this );
|
|
hr = S_OK;
|
|
} // if: IUnknown
|
|
else if ( IsEqualIID( riid, IID_IConnectionManager ) )
|
|
{
|
|
*ppv = TraceInterface( __THISCLASS__, IConnectionManager, this, 0 );
|
|
hr = S_OK;
|
|
} // else if: IConnectionManager
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
((IUnknown*) *ppv)->AddRef();
|
|
} // if: success
|
|
|
|
QIRETURN_IGNORESTDMARSHALLING( hr, riid );
|
|
|
|
} //*** CConnectionManager::QueryInterface()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP_( ULONG )
|
|
// CConnectionManager::AddRef( void )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_( ULONG )
|
|
CConnectionManager::AddRef( void )
|
|
{
|
|
TraceFunc( "[IUnknown]" );
|
|
|
|
InterlockedIncrement( &m_cRef );
|
|
|
|
RETURN( m_cRef );
|
|
|
|
} //*** CConnectionManager::AddRef()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP_( ULONG )
|
|
// CConnectionManager::Release( void )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_( ULONG )
|
|
CConnectionManager::Release( void )
|
|
{
|
|
TraceFunc( "[IUnknown]" );
|
|
|
|
InterlockedDecrement( &m_cRef );
|
|
|
|
if ( m_cRef )
|
|
RETURN( m_cRef );
|
|
|
|
TraceDo( delete this );
|
|
|
|
RETURN( 0 );
|
|
|
|
} //*** CConnectionManager::Release()
|
|
|
|
// ************************************************************************
|
|
//
|
|
// IConnectionManager
|
|
//
|
|
// ************************************************************************
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP
|
|
// CConnectionManager::GetConnectionToObject(
|
|
// OBJECTCOOKIE cookieIn,
|
|
// IUnknown ** ppunkOut
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CConnectionManager::GetConnectionToObject(
|
|
OBJECTCOOKIE cookieIn,
|
|
IUnknown ** ppunkOut
|
|
)
|
|
{
|
|
TraceFunc1( "[IConnectionManager] cookieIn = %#x", cookieIn );
|
|
|
|
HRESULT hr;
|
|
CLSID clsid;
|
|
|
|
OBJECTCOOKIE cookieParent;
|
|
|
|
IServiceProvider * psp;
|
|
|
|
BSTR bstrName = NULL;
|
|
IUnknown * punk = NULL;
|
|
IObjectManager * pom = NULL;
|
|
IConnectionInfo * pci = NULL;
|
|
IConnectionInfo * pciParent = NULL;
|
|
IStandardInfo * psi = NULL;
|
|
IConfigurationConnection * pcc = NULL;
|
|
|
|
//
|
|
// Validate parameters
|
|
//
|
|
if ( cookieIn == NULL )
|
|
goto InvalidArg;
|
|
|
|
if ( ppunkOut == NULL )
|
|
goto InvalidPointer;
|
|
|
|
//
|
|
// Collect the managers needed to complete this method.
|
|
//
|
|
|
|
hr = THR( CoCreateInstance( CLSID_ServiceManager,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
TypeSafeParams( IServiceProvider, &psp )
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
hr = THR( psp->TypeSafeQS( CLSID_ObjectManager,
|
|
IObjectManager,
|
|
&pom
|
|
) );
|
|
psp->Release();
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
//
|
|
// Check to see if we already have a connection cached.
|
|
//
|
|
|
|
//
|
|
// Get the connection info for this cookie.
|
|
//
|
|
|
|
hr = THR( pom->GetObject( DFGUID_ConnectionInfoFormat,
|
|
cookieIn,
|
|
&punk
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
hr = THR( punk->TypeSafeQI( IConnectionInfo, &pci ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
pci = TraceInterface( L"ConnectionManager!IConnectionInfo", IConnectionInfo, pci, 1 );
|
|
|
|
punk->Release();
|
|
punk = NULL;
|
|
|
|
//
|
|
// See if there is a current connection.
|
|
//
|
|
|
|
hr = STHR( pci->GetConnection( &pcc ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
if ( hr == S_FALSE )
|
|
{
|
|
//
|
|
// Check to see if the parent has a connection.
|
|
//
|
|
|
|
//
|
|
// Get the standard info for this cookie.
|
|
//
|
|
|
|
hr = THR( pom->GetObject( DFGUID_StandardInfo,
|
|
cookieIn,
|
|
&punk
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
hr = THR( punk->TypeSafeQI( IStandardInfo, &psi ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
psi = TraceInterface( L"ConnectionManager!IStandardInfo", IStandardInfo, psi, 1 );
|
|
|
|
punk->Release();
|
|
punk = NULL;
|
|
|
|
hr = STHR( psi->GetType( &clsid ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
if ( !IsEqualIID( clsid, CLSID_NodeType )
|
|
&& !IsEqualIID( clsid, CLSID_ClusterConfigurationType )
|
|
)
|
|
{
|
|
hr = STHR( psi->GetParent( &cookieParent ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
// Release it.
|
|
psi->Release();
|
|
psi = NULL;
|
|
|
|
//
|
|
// If there is a parent, follow it.
|
|
//
|
|
|
|
if ( hr == S_OK )
|
|
{
|
|
//
|
|
// Get the connection info for this cookie.
|
|
//
|
|
|
|
hr = THR( pom->GetObject( DFGUID_ConnectionInfoFormat,
|
|
cookieParent,
|
|
&punk
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
hr = THR( punk->TypeSafeQI( IConnectionInfo, &pciParent ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
pciParent = TraceInterface( L"ConnectionManager!IConnectionInfo", IConnectionInfo, pciParent, 1 );
|
|
|
|
punk->Release();
|
|
punk = NULL;
|
|
|
|
//
|
|
// See if there is a current connection.
|
|
//
|
|
|
|
hr = STHR( pciParent->GetConnection( &pcc ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
//
|
|
// TODO: gpease 08-MAR-2000
|
|
// Find a better error code.
|
|
//
|
|
//if ( hr == S_FALSE )
|
|
// goto InvalidArg;
|
|
|
|
} // if: parent found
|
|
} // if: not a node or cluster
|
|
else
|
|
{
|
|
psi->Release();
|
|
psi = NULL;
|
|
}
|
|
|
|
} // if: no established connection
|
|
|
|
//
|
|
// Did we have to contact the parent to get to the child?
|
|
//
|
|
|
|
if ( pcc != NULL )
|
|
{
|
|
//
|
|
// Reuse the existing connection.
|
|
//
|
|
hr = THR( pcc->QueryInterface( IID_IUnknown, reinterpret_cast< void ** >( ppunkOut ) ) );
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Need to build a connection to the object because the object doesn't
|
|
// have a parent and it doesn't currently have a connection.
|
|
//
|
|
|
|
//
|
|
// Find out what type of object it is.
|
|
//
|
|
|
|
hr = THR( pom->GetObject( DFGUID_StandardInfo,
|
|
cookieIn,
|
|
&punk
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
hr = THR( punk->TypeSafeQI( IStandardInfo, &psi ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
psi = TraceInterface( L"ConnectionManager!IStandardInfo", IStandardInfo, psi, 1 );
|
|
|
|
punk->Release();
|
|
punk = NULL;
|
|
|
|
hr = THR( psi->GetType( &clsid ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
//
|
|
// Create the appropriate connection for that type of object.
|
|
//
|
|
|
|
if ( IsEqualIID( clsid, CLSID_NodeType ) )
|
|
{
|
|
hr = THRE( HrGetConfigurationConnection( cookieIn, pci, ppunkOut ), HR_S_RPC_S_CLUSTER_NODE_DOWN );
|
|
} // if: node
|
|
else if ( IsEqualIID( clsid, CLSID_ClusterConfigurationType ) )
|
|
{
|
|
hr = THRE( HrGetConfigurationConnection( cookieIn, pci, ppunkOut ), HR_S_RPC_S_SERVER_UNAVAILABLE );
|
|
} // if: cluster
|
|
else
|
|
{
|
|
//
|
|
// TODO: gpease 07-MAR-2000
|
|
// Find a better error code.
|
|
//
|
|
hr = THR( E_FAIL );
|
|
goto Cleanup;
|
|
|
|
} // else: no connection support
|
|
|
|
Cleanup:
|
|
if ( punk != NULL )
|
|
{
|
|
punk->Release();
|
|
}
|
|
|
|
TraceSysFreeString( bstrName );
|
|
|
|
if ( pci != NULL )
|
|
{
|
|
pci->Release();
|
|
} // if: pci
|
|
|
|
if ( pom != NULL )
|
|
{
|
|
pom->Release();
|
|
} // if: pom
|
|
|
|
if ( psi != NULL )
|
|
{
|
|
psi->Release();
|
|
} // if: psi
|
|
|
|
if ( pciParent != NULL )
|
|
{
|
|
pciParent->Release();
|
|
} // if: pciParent
|
|
|
|
if ( pcc != NULL )
|
|
{
|
|
pcc->Release();
|
|
} // if: pcc
|
|
|
|
HRETURN( hr );
|
|
|
|
InvalidArg:
|
|
hr = THR( E_INVALIDARG );
|
|
goto Cleanup;
|
|
|
|
InvalidPointer:
|
|
hr = THR( E_POINTER );
|
|
goto Cleanup;
|
|
|
|
} //*** CConnectionManager::GetConnectionToObject()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HRESULT
|
|
// CConnectionManager::HrGetConfigurationConnection(
|
|
// OBJECTCOOKIE cookieIn,
|
|
// IConnectionInfo * pciIn,
|
|
// IUnknown ** ppunkOut
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CConnectionManager::HrGetConfigurationConnection(
|
|
OBJECTCOOKIE cookieIn,
|
|
IConnectionInfo * pciIn,
|
|
IUnknown ** ppunkOut
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr;
|
|
|
|
IConfigurationConnection * pccNode = NULL;
|
|
IConfigurationConnection * pccCluster = NULL;
|
|
IConfigurationConnection * pcc = NULL;
|
|
|
|
// Try and connect to the node using the new server.
|
|
hr = HrGetNodeConnection( cookieIn, &pccNode );
|
|
if ( hr == HR_S_RPC_S_CLUSTER_NODE_DOWN )
|
|
{
|
|
Assert( *ppunkOut == NULL );
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
// Try and connect to the node using the W2K object.
|
|
if ( hr == HRESULT_FROM_WIN32( REGDB_E_CLASSNOTREG ) )
|
|
{
|
|
HRESULT hrCluster = THR( HrGetClusterConnection( cookieIn, &pccCluster ) );
|
|
|
|
if ( hrCluster == S_OK )
|
|
{
|
|
Assert( pccCluster != NULL );
|
|
Assert( pcc == NULL );
|
|
|
|
pcc = pccCluster;
|
|
pccCluster = NULL;
|
|
|
|
hr = hrCluster;
|
|
} // if:
|
|
} // if: failed to get a node connection
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
THR( hr );
|
|
goto Cleanup;
|
|
}
|
|
|
|
if ( pcc == NULL )
|
|
{
|
|
Assert( pccNode != NULL );
|
|
pcc = pccNode;
|
|
pccNode = NULL;
|
|
}
|
|
|
|
//
|
|
// VERY IMPORTANT: Store the connection and retrieve the IUnknown pointer
|
|
// only if the result is S_OK.
|
|
//
|
|
|
|
if ( hr == S_OK )
|
|
{
|
|
THR( HrStoreConnection( pciIn, pcc, ppunkOut ) );
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if ( pcc )
|
|
{
|
|
pcc->Release();
|
|
}
|
|
|
|
if ( pccNode != NULL )
|
|
{
|
|
pccNode->Release();
|
|
}
|
|
|
|
if ( pccCluster != NULL )
|
|
{
|
|
pccCluster->Release();
|
|
}
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CConnectionManager::HrGetConfigurationConnection()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HRESULT
|
|
// CConnectionManager::HrGetNodeConnection(
|
|
// OBJECTCOOKIE cookieIn,
|
|
// IConfigurationConnection ** ppccOut
|
|
// )
|
|
//
|
|
// This connection may be valid even if the ConnectTo call fails.
|
|
// -That means that there is no cluster installed on the target node.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CConnectionManager::HrGetNodeConnection(
|
|
OBJECTCOOKIE cookieIn,
|
|
IConfigurationConnection ** ppccOut
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr;
|
|
IConfigurationConnection * pcc = NULL;
|
|
|
|
// Check the pointers in.
|
|
Assert( ppccOut != NULL );
|
|
Assert( *ppccOut == NULL );
|
|
|
|
hr = CoCreateInstance( CLSID_ConfigurationConnection,
|
|
NULL,
|
|
CLSCTX_SERVER,
|
|
TypeSafeParams( IConfigurationConnection, &pcc )
|
|
);
|
|
if ( FAILED( hr ) )
|
|
{
|
|
THR( hr );
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Don't wrap - we want to handle some of the failures.
|
|
hr = pcc->ConnectTo( cookieIn );
|
|
|
|
switch( hr )
|
|
{
|
|
// Known valid return codes.
|
|
case HR_S_RPC_S_SERVER_UNAVAILABLE:
|
|
break;
|
|
|
|
// Known error codes.
|
|
case HRESULT_FROM_WIN32( REGDB_E_CLASSNOTREG ):
|
|
// This means the ClusCfg server is not available.
|
|
goto Cleanup;
|
|
|
|
case HR_S_RPC_S_CLUSTER_NODE_DOWN:
|
|
// This means the service is not running on that node.
|
|
Assert( *ppccOut == NULL );
|
|
goto Cleanup;
|
|
|
|
default:
|
|
if( FAILED( hr ) )
|
|
{
|
|
THR( hr );
|
|
goto Cleanup;
|
|
}
|
|
} // switch:
|
|
|
|
// Return the connection.
|
|
*ppccOut = pcc;
|
|
pcc = NULL;
|
|
|
|
Cleanup:
|
|
|
|
if ( pcc )
|
|
{
|
|
pcc->Release();
|
|
}
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CConnectionManager::HrGetNodeConnection()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HRESULT
|
|
// CConnectionManager::HrGetClusterConnection(
|
|
// OBJECTCOOKIE cookieIn,
|
|
// IConfigurationConnection ** ppccOut
|
|
// )
|
|
//
|
|
//
|
|
// This connection must succeede completely to return a valid object.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CConnectionManager::HrGetClusterConnection(
|
|
OBJECTCOOKIE cookieIn,
|
|
IConfigurationConnection ** ppccOut
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr;
|
|
IConfigurationConnection * pcc = NULL;
|
|
|
|
// Check the pointers in.
|
|
Assert( ppccOut != NULL );
|
|
Assert( *ppccOut == NULL );
|
|
|
|
//
|
|
// Should be a downlevel cluster.
|
|
//
|
|
hr = THR( CoCreateInstance( CLSID_ConfigClusApi,
|
|
NULL,
|
|
CLSCTX_SERVER,
|
|
TypeSafeParams( IConfigurationConnection, &pcc )
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
// Don't wrap - we want to handle some of the failures.
|
|
hr = pcc->ConnectTo( cookieIn );
|
|
if ( hr == HR_S_RPC_S_CLUSTER_NODE_DOWN )
|
|
{
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
// Handle the expected error messages.
|
|
|
|
// If the cluster service is not running, then the endpoint
|
|
// is unavailable and we cannot connect to it.
|
|
if ( hr == HRESULT_FROM_WIN32( EPT_S_NOT_REGISTERED ) )
|
|
goto Cleanup;
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
THR( hr );
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
// Return the connection.
|
|
*ppccOut = pcc;
|
|
pcc = NULL;
|
|
|
|
Cleanup:
|
|
|
|
if ( pcc )
|
|
{
|
|
pcc->Release();
|
|
}
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CConnectionManager::HrGetClusterConnection()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HRESULT
|
|
// CConnectionManager::HrStoreConnection(
|
|
// IConnectionInfo * pciIn,
|
|
// IConfigurationConnection * pccIn,
|
|
// IUnknown ** ppunkOut
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CConnectionManager::HrStoreConnection(
|
|
IConnectionInfo * pciIn,
|
|
IConfigurationConnection * pccIn,
|
|
IUnknown ** ppunkOut
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Save it away to be used next time.
|
|
//
|
|
// TODO: gpease 08-MAR-2000
|
|
// If we failed to save away the connection, does
|
|
// the caller need to know this? I don't think so.
|
|
//
|
|
THR( pciIn->SetConnection( pccIn ) );
|
|
|
|
hr = THR( pccIn->QueryInterface( IID_IUnknown,
|
|
reinterpret_cast< void ** >( ppunkOut )
|
|
) );
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CConnectionManager::HrStoreConnection()
|