2025-04-27 07:49:33 -04:00

248 lines
8.5 KiB
C++

//////////////////////////////////////////////////////////////////////////////
//
// 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
//////////////////////////////////////////////////////////////////////////////
// For the logging and tracing functions
#include "BCATrace.h"
// 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_fLastStepSent( false )
{
BCATraceScope( "" );
// 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
} //*** CStatusReport::CStatusReport()
// Default destructor.
~CStatusReport( void )
{
BCATraceScope( "" );
// 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
);
}
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 );
TraceFlow( "Caught an exception while trying to send the last step of a status report." );
LogMsg( "An unexpected error has occurred trying to send a status report during cleanup." );
}
}
} //*** CStatusReport::~CStatusReport()
//////////////////////////////////////////////////////////////////////////
// Public methods
//////////////////////////////////////////////////////////////////////////
// Send the next step of this report.
void SendNextStep( HRESULT hrStatusIn, UINT idsDescriptionStringIdIn = 0 )
{
BCATraceScope( "" );
if ( m_fLastStepSent )
{
TraceFlow( "The last step for this status report has already been sent! Throwing exception." );
LogMsg( "The last step for this status report has already been sent!" );
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;
}
m_pbcaiInterface->SendStatusReport(
m_clsidTaskMajor
, m_clsidTaskMinor
, m_ulMin
, m_ulMax
, m_ulNext
, hrStatusIn
, idsDescriptionStringIdIn
);
++m_ulNext;
m_fLastStepSent = ( m_ulNext > m_ulMax );
} // else: the last step has not been sent
} //*** CStatusReport::SendNextStep()
// Send the last step of this report, if it hasn't been sent already.
void SendLastStep( HRESULT hrStatusIn, UINT idsDescriptionStringIdIn = 0 )
{
BCATraceScope( "" );
if ( m_fLastStepSent )
{
TraceFlow( "The last step for this status report has already been sent! Throwing exception." );
LogMsg( "The last step for this status report has already been sent!" );
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;
}
m_pbcaiInterface->SendStatusReport(
m_clsidTaskMajor
, m_clsidTaskMinor
, m_ulMin
, m_ulMax
, m_ulMax
, hrStatusIn
, idsDescriptionStringIdIn
);
m_fLastStepSent = true;
} // else: the last step has not been sent
} //*** CStatusReport::SendLastStep()
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;
// Flag to indicate if the last step has been sent.
bool m_fLastStepSent;
}; //*** class CStatusReport