You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
720 lines
19 KiB
720 lines
19 KiB
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 2000-2002 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// TaskPollingCallback.cpp
|
|
//
|
|
// Description:
|
|
// CTaskPollingCallback implementation.
|
|
//
|
|
// Maintained By:
|
|
// Galen Barbee (GalenB) 10-JUL-2000
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "Pch.h"
|
|
#include <ClusCfgPrivate.h>
|
|
#include "TaskPollingCallback.h"
|
|
|
|
DEFINE_THISCLASS("CTaskPollingCallback")
|
|
|
|
// ************************************************************************
|
|
//
|
|
// Constructor / Destructor
|
|
//
|
|
// ************************************************************************
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// HRESULT
|
|
// CTaskPollingCallback::S_HrCreateInstance(
|
|
// IUnknown ** ppunkOut
|
|
// )
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CTaskPollingCallback::S_HrCreateInstance(
|
|
IUnknown ** ppunkOut
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr = S_OK;
|
|
CTaskPollingCallback * ptpc = NULL;
|
|
|
|
Assert( ppunkOut != NULL );
|
|
if ( ppunkOut == NULL )
|
|
{
|
|
hr = THR( E_POINTER );
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
ptpc = new CTaskPollingCallback;
|
|
if ( ptpc == NULL )
|
|
{
|
|
hr = THR( E_OUTOFMEMORY );
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
hr = THR( ptpc->HrInit() );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
hr = THR( ptpc->TypeSafeQI( IUnknown, ppunkOut ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
TraceMoveToMemoryList( *ppunkOut, g_GlobalMemoryList );
|
|
|
|
Cleanup:
|
|
|
|
if ( ptpc != NULL )
|
|
{
|
|
ptpc->Release();
|
|
} // if:
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CTaskPollingCallback::S_HrCreateInstance
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CTaskPollingCallback::CTaskPollingCallback
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CTaskPollingCallback::CTaskPollingCallback( void )
|
|
: m_cRef( 1 )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
InterlockedIncrement( &g_cObjects );
|
|
|
|
Assert( m_fStop == false );
|
|
Assert( m_dwRemoteServerObjectGITCookie == 0 );
|
|
Assert( m_cookieLocalServerObject == 0 );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CTaskPollingCallback::CTaskPollingCallback
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// STDMETHODIMP
|
|
// CTaskPollingCallback::HrInit
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CTaskPollingCallback::HrInit( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// IUnknown
|
|
Assert( m_cRef == 1 );
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CTaskPollingCallback::HrInit
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CTaskPollingCallback::~CTaskPollingCallback
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CTaskPollingCallback::~CTaskPollingCallback( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
TraceMoveFromMemoryList( this, g_GlobalMemoryList );
|
|
|
|
InterlockedDecrement( &g_cObjects );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CTaskPollingCallback::~CTaskPollingCallback
|
|
|
|
|
|
// ************************************************************************
|
|
//
|
|
// IUnknown
|
|
//
|
|
// ************************************************************************
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CTaskPollingCallback::QueryInterface
|
|
//
|
|
// Description:
|
|
// Query this object for the passed in interface.
|
|
//
|
|
// Arguments:
|
|
// riidIn
|
|
// Id of interface requested.
|
|
//
|
|
// ppvOut
|
|
// Pointer to the requested interface.
|
|
//
|
|
// Return Value:
|
|
// S_OK
|
|
// If the interface is available on this object.
|
|
//
|
|
// E_NOINTERFACE
|
|
// If the interface is not available.
|
|
//
|
|
// E_POINTER
|
|
// ppvOut was NULL.
|
|
//
|
|
// Remarks:
|
|
// None.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CTaskPollingCallback::QueryInterface(
|
|
REFIID riidIn
|
|
, LPVOID * ppvOut
|
|
)
|
|
{
|
|
TraceQIFunc( riidIn, ppvOut );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Validate arguments.
|
|
//
|
|
|
|
Assert( ppvOut != NULL );
|
|
if ( ppvOut == NULL )
|
|
{
|
|
hr = THR( E_POINTER );
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
//
|
|
// Handle known interfaces.
|
|
//
|
|
|
|
if ( IsEqualIID( riidIn, IID_IUnknown ) )
|
|
{
|
|
*ppvOut = static_cast< ITaskPollingCallback * >( this );
|
|
} // if: IUnknown
|
|
else if ( IsEqualIID( riidIn, IID_ITaskPollingCallback ) )
|
|
{
|
|
*ppvOut = TraceInterface( __THISCLASS__, ITaskPollingCallback, this, 0 );
|
|
} // else if: ITaskPollingCallback
|
|
else if ( IsEqualIID( riidIn, IID_IDoTask ) )
|
|
{
|
|
*ppvOut = TraceInterface( __THISCLASS__, IDoTask, this, 0 );
|
|
} // else if: IDoTask
|
|
else
|
|
{
|
|
*ppvOut = NULL;
|
|
hr = E_NOINTERFACE;
|
|
} // else:
|
|
|
|
//
|
|
// Add a reference to the interface if successful.
|
|
//
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
((IUnknown *) *ppvOut)->AddRef();
|
|
} // if: success
|
|
|
|
Cleanup:
|
|
|
|
QIRETURN_IGNORESTDMARSHALLING( hr, riidIn );
|
|
|
|
} //*** CTaskPollingCallback::QueryInterface
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// STDMETHODIMP_( ULONG )
|
|
// CTaskPollingCallback::AddRef
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_( ULONG )
|
|
CTaskPollingCallback::AddRef( void )
|
|
{
|
|
TraceFunc( "[IUnknown]" );
|
|
|
|
InterlockedIncrement( &m_cRef );
|
|
|
|
CRETURN( m_cRef );
|
|
|
|
} //*** CTaskPollingCallback::AddRef
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// STDMETHODIMP_( ULONG )
|
|
// CTaskPollingCallback::Release
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_( ULONG )
|
|
CTaskPollingCallback::Release( void )
|
|
{
|
|
TraceFunc( "[IUnknown]" );
|
|
|
|
LONG cRef;
|
|
|
|
cRef = InterlockedDecrement( &m_cRef );
|
|
|
|
if ( cRef == 0 )
|
|
{
|
|
TraceDo( delete this );
|
|
} // if:
|
|
|
|
CRETURN( cRef );
|
|
|
|
} //*** CTaskPollingCallback::Release
|
|
|
|
|
|
//****************************************************************************
|
|
//
|
|
// ITaskPollingCallback
|
|
//
|
|
//****************************************************************************
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// STDMETHODIMP
|
|
// CTaskPollingCallback::BeginTask( void )
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CTaskPollingCallback::BeginTask( void )
|
|
{
|
|
TraceFunc( "[IDoTask]" );
|
|
|
|
HRESULT hr = S_OK;
|
|
BSTR bstrNodeName = NULL;
|
|
BSTR bstrLastNodeName = NULL;
|
|
BSTR bstrReference = NULL;
|
|
BSTR bstrDescription = NULL;
|
|
BSTR bstrNodeConnectedTo = NULL;
|
|
CLSID clsidTaskMajor;
|
|
CLSID clsidTaskMinor;
|
|
ULONG ulMin;
|
|
ULONG ulMax;
|
|
ULONG ulCurrent;
|
|
HRESULT hrStatus;
|
|
FILETIME ft;
|
|
IGlobalInterfaceTable * pgit = NULL;
|
|
IClusCfgServer * pccs = NULL;
|
|
IClusCfgPollingCallback * piccpc = NULL;
|
|
IClusCfgPollingCallbackInfo * piccpci = NULL;
|
|
IServiceProvider * psp = NULL;
|
|
IConnectionPointContainer * pcpc = NULL;
|
|
IConnectionPoint * pcp = NULL;
|
|
IClusCfgCallback * pcccb = NULL;
|
|
DWORD cRetries = 0;
|
|
IObjectManager * pom = NULL;
|
|
|
|
//
|
|
// Collect the manager we need to complete this task.
|
|
//
|
|
|
|
hr = THR( CoCreateInstance( CLSID_ServiceManager, NULL, CLSCTX_INPROC_SERVER, TypeSafeParams( IServiceProvider, &psp ) ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
hr = THR( psp->TypeSafeQS( CLSID_NotificationManager, IConnectionPointContainer, &pcpc ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
hr = THR( psp->TypeSafeQS( CLSID_ObjectManager, IObjectManager, &pom ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
hr = THR( pcpc->FindConnectionPoint( IID_IClusCfgCallback, &pcp ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
hr = THR( pcp->TypeSafeQI( IClusCfgCallback, &pcccb ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
psp->Release();
|
|
psp = NULL;
|
|
|
|
//
|
|
// Create the GIT.
|
|
//
|
|
|
|
hr = THR( CoCreateInstance(
|
|
CLSID_StdGlobalInterfaceTable
|
|
, NULL
|
|
, CLSCTX_INPROC_SERVER
|
|
, IID_IGlobalInterfaceTable
|
|
, reinterpret_cast< void ** >( &pgit )
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
} // if
|
|
|
|
//
|
|
// Get the ClusCfgServer interface from the GIT.
|
|
//
|
|
|
|
Assert( m_dwRemoteServerObjectGITCookie != 0 );
|
|
|
|
hr = THR( pgit->GetInterfaceFromGlobal( m_dwRemoteServerObjectGITCookie, IID_IClusCfgServer, reinterpret_cast< void ** >( &pccs ) ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
} // if
|
|
|
|
//
|
|
// Get the PollingCallback object from the server.
|
|
//
|
|
|
|
hr = THR( pccs->TypeSafeQI( IClusCfgPollingCallbackInfo, &piccpci ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
} // if
|
|
|
|
hr = THR( piccpci->GetCallback( &piccpc ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
} // if
|
|
|
|
hr = THR( HrRetrieveCookiesName( pom, m_cookieLocalServerObject, &bstrNodeConnectedTo ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
} // if
|
|
|
|
pom->Release();
|
|
pom = NULL;
|
|
|
|
//
|
|
// Begin polling for SendStatusReports.
|
|
//
|
|
|
|
while ( m_fStop == FALSE )
|
|
{
|
|
//
|
|
// When the we cannot get a service manager pointer then it's time to
|
|
// leave...
|
|
//
|
|
// Don't wrap with THR because we are expecting an error.
|
|
//
|
|
|
|
hr = CServiceManager::S_HrGetManagerPointer( &psp );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
break;
|
|
} // if:
|
|
|
|
psp->Release();
|
|
psp = NULL;
|
|
|
|
if ( bstrNodeName != NULL )
|
|
{
|
|
TraceSysFreeString( bstrLastNodeName );
|
|
bstrLastNodeName = NULL;
|
|
|
|
//
|
|
// Give up ownership
|
|
//
|
|
|
|
bstrLastNodeName = bstrNodeName;
|
|
bstrNodeName = NULL;
|
|
} // if:
|
|
|
|
TraceSysFreeString( bstrDescription );
|
|
bstrDescription = NULL;
|
|
|
|
TraceSysFreeString( bstrReference );
|
|
bstrReference = NULL;
|
|
|
|
hr = STHR( piccpc->GetStatusReport(
|
|
&bstrNodeName
|
|
, &clsidTaskMajor
|
|
, &clsidTaskMinor
|
|
, &ulMin
|
|
, &ulMax
|
|
, &ulCurrent
|
|
, &hrStatus
|
|
, &bstrDescription
|
|
, &ft
|
|
, &bstrReference
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
HRESULT hr2;
|
|
BSTR bstrNotification = NULL;
|
|
BSTR bstrRef = NULL;
|
|
|
|
LogMsg( L"[TaskPollingCallback] GetStatusReport() failed for node %ws. (hr = %#08x)", bstrNodeConnectedTo, hr );
|
|
|
|
THR( HrFormatStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_POLLING_CONNECTION_FAILURE, &bstrNotification, bstrNodeConnectedTo ) );
|
|
THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_POLLING_CONNECTION_FAILURE_REF, &bstrRef ) );
|
|
|
|
//
|
|
// Don't show this in the UI as a failure since it may succeed later and we don't want a
|
|
// red X and a green status bar at the end.
|
|
//
|
|
|
|
hr2 = THR( pcccb->SendStatusReport(
|
|
bstrLastNodeName
|
|
, TASKID_Major_Establish_Connection
|
|
, TASKID_Minor_Polling_Connection_Failure
|
|
, 0
|
|
, 1
|
|
, 1
|
|
, MAKE_HRESULT( SEVERITY_SUCCESS, HRESULT_FACILITY( hr ), HRESULT_CODE( hr ) )
|
|
, bstrNotification
|
|
, NULL
|
|
, bstrRef
|
|
) );
|
|
|
|
TraceSysFreeString( bstrNotification );
|
|
TraceSysFreeString( bstrRef );
|
|
|
|
if ( hr2 == E_ABORT )
|
|
{
|
|
LogMsg( L"[TaskPollingCallback] UI layer returned E_ABORT..." );
|
|
} // if:
|
|
|
|
//
|
|
// If we had an error then sleep for a little more time before
|
|
// trying again.
|
|
//
|
|
|
|
Sleep( TPC_WAIT_AFTER_FAILURE );
|
|
|
|
//
|
|
// Increment the retry count.
|
|
//
|
|
|
|
cRetries++;
|
|
|
|
//
|
|
// If we are exceeding our max retry count then it's time to leave
|
|
// and notify the UI that we are have lost connection to the
|
|
// server...
|
|
//
|
|
|
|
if ( cRetries >= TPC_MAX_RETRIES_ON_FAILURE )
|
|
{
|
|
BSTR bstrDesc = NULL;
|
|
BSTR bstrTempRef = NULL;
|
|
|
|
THR( HrFormatStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_DISCONNECTING_FROM_SERVER, &bstrDesc, bstrNodeConnectedTo ) );
|
|
THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_DISCONNECTING_FROM_SERVER_REF, &bstrTempRef ) );
|
|
|
|
LogMsg( L"[TaskPollingCallback] GetStatusReport() failed for node %ws too many times and has timed out. Aborting polling. (hr = %#08x)", bstrNodeConnectedTo, hr );
|
|
THR( pcccb->SendStatusReport(
|
|
bstrNodeConnectedTo
|
|
, TASKID_Major_Find_Devices
|
|
, TASKID_Minor_Disconnecting_From_Server
|
|
, 1
|
|
, 1
|
|
, 1
|
|
, hr
|
|
, bstrDesc
|
|
, NULL
|
|
, bstrTempRef
|
|
) );
|
|
|
|
TraceSysFreeString( bstrDesc );
|
|
TraceSysFreeString( bstrTempRef );
|
|
|
|
goto Cleanup;
|
|
} // if:
|
|
} // if: GetStatusReport() failed
|
|
else if ( hr == S_OK )
|
|
{
|
|
HRESULT hrTmp;
|
|
|
|
TraceMemoryAddBSTR( bstrNodeName );
|
|
TraceMemoryAddBSTR( bstrDescription );
|
|
TraceMemoryAddBSTR( bstrReference );
|
|
|
|
hr = THR( pcccb->SendStatusReport(
|
|
bstrNodeName
|
|
, clsidTaskMajor
|
|
, clsidTaskMinor
|
|
, ulMin
|
|
, ulMax
|
|
, ulCurrent
|
|
, hrStatus
|
|
, bstrDescription
|
|
, &ft
|
|
, bstrReference
|
|
) );
|
|
|
|
if ( hr == E_ABORT )
|
|
{
|
|
LogMsg( L"[TaskPollingCallback] UI layer returned E_ABORT and it is being sent to the server." );
|
|
} // if:
|
|
|
|
hrTmp = hr;
|
|
hr = THR( piccpc->SetHResult( hrTmp ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
LogMsg( L"[TaskPollingCallback] SetHResult() failed. hr = 0x%08x", hr );
|
|
} // if:
|
|
|
|
//
|
|
// Need to reset the retry count when we successfully round trip a status report.
|
|
//
|
|
|
|
cRetries = 0;
|
|
} // else if: GetStatusReport() retrieved an item
|
|
else
|
|
{
|
|
//
|
|
// Need to reset the retry count when we successfully round trip a status report.
|
|
//
|
|
|
|
cRetries = 0;
|
|
|
|
Sleep( TPC_POLL_INTERVAL );
|
|
} // else: GetStatusReport() didn't find and item waiting
|
|
} // while:
|
|
|
|
Cleanup:
|
|
|
|
if ( pom != NULL )
|
|
{
|
|
pom->Release();
|
|
} // if:
|
|
|
|
if ( psp != NULL )
|
|
{
|
|
psp->Release();
|
|
} // if:
|
|
|
|
if ( pgit != NULL )
|
|
{
|
|
pgit->Release();
|
|
} // if:
|
|
|
|
if ( pccs != NULL )
|
|
{
|
|
pccs->Release();
|
|
} // if:
|
|
|
|
if ( piccpc != NULL )
|
|
{
|
|
piccpc->Release();
|
|
} // if:
|
|
|
|
if ( piccpci != NULL )
|
|
{
|
|
piccpci->Release();
|
|
} // if:
|
|
|
|
if ( pcpc != NULL )
|
|
{
|
|
pcpc->Release();
|
|
} // if:
|
|
|
|
if ( pcp != NULL )
|
|
{
|
|
pcp->Release();
|
|
} // if:
|
|
|
|
if ( pcccb != NULL )
|
|
{
|
|
pcccb->Release();
|
|
} // if:
|
|
|
|
TraceSysFreeString( bstrNodeName );
|
|
TraceSysFreeString( bstrDescription );
|
|
TraceSysFreeString( bstrReference );
|
|
TraceSysFreeString( bstrLastNodeName );
|
|
TraceSysFreeString( bstrNodeConnectedTo );
|
|
|
|
LogMsg( L"[MT] Polling callback task exiting. It %ws cancelled.", m_fStop == FALSE ? L"was not" : L"was" );
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CTaskPollingCallback::BeginTask
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// STDMETHODIMP
|
|
// CTaskPollingCallback::StopTask( void )
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CTaskPollingCallback::StopTask( void )
|
|
{
|
|
TraceFunc( "[IDoTask]" );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
m_fStop = true;
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CTaskPollingCallback::StopTask
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// STDMETHODIMP
|
|
// CTaskPollingCallback::SetServerInfo(
|
|
// DWORD dwRemoteServerObjectGITCookieIn
|
|
// , OBJECTCOOKIE cookieLocalServerObjectIn
|
|
// )
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CTaskPollingCallback::SetServerInfo(
|
|
DWORD dwRemoteServerObjectGITCookieIn
|
|
, OBJECTCOOKIE cookieLocalServerObjectIn
|
|
)
|
|
{
|
|
TraceFunc( "[ITaskPollingCallback]" );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
m_dwRemoteServerObjectGITCookie = dwRemoteServerObjectGITCookieIn;
|
|
m_cookieLocalServerObject = cookieLocalServerObjectIn;
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CTaskPollingCallback::SetServerInfo
|