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