////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2000-2001 Microsoft Corporation // // Module Name: // CStatusReport.h // // Description: // Header file for CStatusReport class. // // CStatusReport is a class the provides the functionality sending a // status report. // // Implementation File: // CStatusReport.cpp // // Maintained By: // David Potter (DavidP) 30-MAR-2001 // Vij Vasu (Vvasu) 05-JUN-2000 // ////////////////////////////////////////////////////////////////////////////// // Make sure that this file is included only once per compile path. #pragma once ////////////////////////////////////////////////////////////////////////////// // Include files ////////////////////////////////////////////////////////////////////////////// // A few common declarations #include "CommonDefs.h" // For the exceptions thrown by this class. #include "Exceptions.h" // For the CBCAInterface class #include "CBCAInterface.h" ////////////////////////////////////////////////////////////////////////////// //++ // // class CStatusReport // // Description: // CStatusReport is a class the provides the functionality sending a // status report. Each status report can have a number of steps. For // example, the task of creating the cluster service could have 4 steps, // // The user interface is so designed that if the first step of a report is // sent, the last one has to be sent as well, even if an error occurs after // sending the first one. This class queues the last status report for // sending in case and exception occurs and the last report has not been // sent yet. // // It is not possible to send the last, outstanding status report from the // destructor of this class since the error code contained in the exception // that is causing this object to be destroyed is not known. So, this last // status report is queued with the CBCAInterface object which will send this // report once the exception has been caught. // //-- ////////////////////////////////////////////////////////////////////////////// class CStatusReport { public: ////////////////////////////////////////////////////////////////////////// // Constructors and destructors ////////////////////////////////////////////////////////////////////////// // Constructor. CStatusReport( CBCAInterface * pbcaiInterfaceIn , const CLSID & clsidTaskMajorIn , const CLSID & clsidTaskMinorIn , ULONG ulMinIn , ULONG ulMaxIn , UINT idsDescriptionStringIdIn ) : m_pbcaiInterface( pbcaiInterfaceIn ) , m_clsidTaskMajor( clsidTaskMajorIn ) , m_clsidTaskMinor( clsidTaskMinorIn ) , m_ulMin( ulMinIn ) , m_ulMax( ulMaxIn ) , m_ulNext( ulMinIn ) , m_idsDescriptionStringId( idsDescriptionStringIdIn ) , m_idsReferenceStringId( 0 ) , m_fLastStepSent( false ) { TraceFunc( "" ); // Validate the parameters. if ( ( pbcaiInterfaceIn == NULL ) || ( ulMinIn > ulMaxIn ) ) { THR( E_INVALIDARG ); THROW_ASSERT( E_INVALIDARG, "The parameters for this status report are invalid." ); } // if: the parameters are invalid TraceFuncExit(); } //*** CStatusReport::CStatusReport // Constructor. CStatusReport( CBCAInterface * pbcaiInterfaceIn , const CLSID & clsidTaskMajorIn , const CLSID & clsidTaskMinorIn , ULONG ulMinIn , ULONG ulMaxIn , UINT idsDescriptionStringIdIn , UINT idsReferenceStringIdIn ) : m_pbcaiInterface( pbcaiInterfaceIn ) , m_clsidTaskMajor( clsidTaskMajorIn ) , m_clsidTaskMinor( clsidTaskMinorIn ) , m_ulMin( ulMinIn ) , m_ulMax( ulMaxIn ) , m_ulNext( ulMinIn ) , m_idsDescriptionStringId( idsDescriptionStringIdIn ) , m_idsReferenceStringId( idsReferenceStringIdIn ) , m_fLastStepSent( false ) { TraceFunc( "" ); // Validate the parameters. if ( ( pbcaiInterfaceIn == NULL ) || ( ulMinIn > ulMaxIn ) ) { THR( E_INVALIDARG ); THROW_ASSERT( E_INVALIDARG, "The parameters for this status report are invalid." ); } // if: the parameters are invalid TraceFuncExit(); } //*** CStatusReport::CStatusReport // Default destructor. ~CStatusReport( void ) { TraceFunc( "" ); // If the last step has not been sent, queue it for sending. This is most probably because // an exception has occurred (if no exception has occurred and the last step has not been // sent, then it is a programming error). if ( ! m_fLastStepSent ) { // The last step has not been sent. // Don't throw exceptions from destructor. An unwind may already be in progress. try { // Queue the last step for sending. The CBCAInterface object will fill in the // error code from the current exception and send this report. m_pbcaiInterface->QueueStatusReportCompletion( m_clsidTaskMajor , m_clsidTaskMinor , m_ulMin , m_ulMax , m_idsDescriptionStringId , m_idsReferenceStringId ); } catch( ... ) { // Catch all errors. Do not rethrow this exception - the app may be terminated due to // a collided unwind - so log the error. THR( E_UNEXPECTED ); LogMsg( "[BC] Caught an exception while trying to send the last step of a status report during cleanup." ); } } TraceFuncExit(); } //*** CStatusReport::~CStatusReport ////////////////////////////////////////////////////////////////////////// // Public methods ////////////////////////////////////////////////////////////////////////// // Send the next step of this report. void SendNextStep( HRESULT hrStatusIn, UINT idsDescriptionStringIdIn = 0, UINT idsReferenceStringIdIn = 0 ) { TraceFunc( "" ); if ( m_fLastStepSent ) { LogMsg( "[BC] The last step for this status report has already been sent! Throwing an exception." ); THR( E_INVALIDARG ); THROW_ASSERT( E_INVALIDARG, "The last step for this status report has already been sent." ); } // if: the last step has already been sent else { if ( idsDescriptionStringIdIn == 0 ) { idsDescriptionStringIdIn = m_idsDescriptionStringId; } if ( idsReferenceStringIdIn == 0 ) { idsReferenceStringIdIn = m_idsReferenceStringId; } m_pbcaiInterface->SendStatusReport( m_clsidTaskMajor , m_clsidTaskMinor , m_ulMin , m_ulMax , m_ulNext , hrStatusIn , idsDescriptionStringIdIn , idsReferenceStringIdIn ); ++m_ulNext; m_fLastStepSent = ( m_ulNext > m_ulMax ); } // else: the last step has not been sent TraceFuncExit(); } //*** CStatusReport::SendNextStep // Send the last step of this report, if it hasn't been sent already. void SendLastStep( HRESULT hrStatusIn, UINT idsDescriptionStringIdIn = 0, UINT idsReferenceStringIdIn = 0 ) { TraceFunc( "" ); if ( m_fLastStepSent ) { LogMsg( "[BC] The last step for this status report has already been sent! Throwing an exception." ); THR( E_INVALIDARG ); THROW_ASSERT( E_INVALIDARG, "The last step for this status report has already been sent." ); } // if: the last step has already been sent else { if ( idsDescriptionStringIdIn == 0 ) { idsDescriptionStringIdIn = m_idsDescriptionStringId; } if ( idsReferenceStringIdIn == 0 ) { idsReferenceStringIdIn = m_idsReferenceStringId; } m_pbcaiInterface->SendStatusReport( m_clsidTaskMajor , m_clsidTaskMinor , m_ulMin , m_ulMax , m_ulMax , hrStatusIn , idsDescriptionStringIdIn , idsReferenceStringIdIn ); m_fLastStepSent = true; } // else: the last step has not been sent TraceFuncExit(); } //*** CStatusReport::SendLastStep // Get the description string ID. UINT IdsGetDescriptionStringId( void ) { return m_idsDescriptionStringId; } // Set the description string ID. void SetDescriptionStringId( UINT idsDescriptionStringIdIn ) { m_idsDescriptionStringId = idsDescriptionStringIdIn; } // Get the reference string ID. UINT IdsGetReferenceStringId( void ) { return m_idsReferenceStringId; } // Set the reference string ID. void SetReferenceStringId( UINT idsReferenceStringIdIn ) { m_idsReferenceStringId = idsReferenceStringIdIn; } private: ////////////////////////////////////////////////////////////////////////// // Private data ////////////////////////////////////////////////////////////////////////// // Pointer to the interface class. CBCAInterface * m_pbcaiInterface; // The major and minor class id to be sent with this status report. CLSID m_clsidTaskMajor; CLSID m_clsidTaskMinor; // The range for this status report ULONG m_ulMin; ULONG m_ulMax; ULONG m_ulNext; // The string id of the description to be sent with this status report UINT m_idsDescriptionStringId; // The REF string id of the description to be sent with this status report UINT m_idsReferenceStringId; // Flag to indicate if the last step has been sent. bool m_fLastStepSent; }; //*** class CStatusReport