Leaked source code of windows server 2003
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

//////////////////////////////////////////////////////////////////////////////
//
// 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