393 lines
8.5 KiB
C++
393 lines
8.5 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1996-1997 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// Barf.cpp
|
|
//
|
|
// Abstract:
|
|
// Implementation of the Basic Artifical Resource Failure classes.
|
|
//
|
|
// Author:
|
|
// David Potter (davidp) April 11, 1997
|
|
//
|
|
// Revision History:
|
|
//
|
|
// Notes:
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
|
|
#define _NO_BARF_DEFINITIONS_
|
|
|
|
#include "Barf.h"
|
|
#include "TraceTag.h"
|
|
#include "ExcOper.h"
|
|
|
|
#ifdef _USING_BARF_
|
|
#error BARF failures should be disabled!
|
|
#endif
|
|
|
|
#ifdef _DEBUG // The entire file!
|
|
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Global Variables
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL g_bFailOnNextBarf = FALSE;
|
|
|
|
CTraceTag g_tagBarf(_T("Debug"), _T("BARF Failures"), CTraceTag::tfDebug);
|
|
|
|
|
|
//*************************************************************************//
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CBarf
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL CBarf::s_bGlobalEnable = TRUE;
|
|
LONG CBarf::s_nSuspend = 0;
|
|
CBarf * CBarf::s_pbarfFirst = NULL;
|
|
PFNBARFPOSTUPDATE CBarf::s_pfnPostUpdate = NULL;
|
|
PVOID CBarf::s_pvSpecialMem = NULL;
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CBarf::CBarf
|
|
//
|
|
// Routine Description:
|
|
// Constructor.
|
|
//
|
|
// Arguments:
|
|
// pszName [IN] Name of the set of APIs to BARF.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CBarf::CBarf(IN LPCTSTR pszName)
|
|
{
|
|
ASSERT(pszName != NULL);
|
|
|
|
m_pszName = pszName;
|
|
|
|
m_bDisabled = FALSE;
|
|
m_bContinuous = FALSE;
|
|
m_nFail = 0;
|
|
m_nCurrent = 0;
|
|
|
|
m_pbarfNext = s_pbarfFirst;
|
|
s_pbarfFirst = this;
|
|
|
|
} //*** CBarf::CBarf()
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CBarf::Init
|
|
//
|
|
// Routine Description:
|
|
// Initializes the BARF counters instance by giving it its name and
|
|
// giving it a startup value (from the registry if possible).
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CBarf::Init(void)
|
|
{
|
|
CString strSection;
|
|
CString strValue;
|
|
|
|
strSection.Format(BARF_REG_SECTION_FMT, m_pszName);
|
|
|
|
m_bDisabled = AfxGetApp()->GetProfileInt(strSection, _T("Disabled"), FALSE);
|
|
m_bContinuous = AfxGetApp()->GetProfileInt(strSection, _T("Continuous"), FALSE);
|
|
m_nFail = AfxGetApp()->GetProfileInt(strSection, _T("Fail"), 0);
|
|
|
|
} //*** CBarf::Init()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CBarf::BFail
|
|
//
|
|
// Routine Description:
|
|
// Determines if the next call should artificially fail.
|
|
// Typical usage of this method is:
|
|
// BOOL BARFFoo( void )
|
|
// {
|
|
// if (barfMyApi.BFail())
|
|
// return FALSE;
|
|
// else
|
|
// return Foo();
|
|
// }
|
|
//
|
|
// Return value:
|
|
// bFail TRUE indicates the call should be made to
|
|
// artificially fail.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CBarf::BFail(void)
|
|
{
|
|
BOOL bFail = FALSE;
|
|
|
|
// If BARF is suspended, don't artificially fail.
|
|
// Otherwise, check the counters.
|
|
if (s_nSuspend == 0)
|
|
{
|
|
// Increment the call count.
|
|
m_nCurrent++;
|
|
|
|
// Call the post-update routine to allow UI to be updated.
|
|
if (PfnPostUpdate())
|
|
((*PfnPostUpdate())());
|
|
|
|
// If not disable and not globally disabled, keep checking.
|
|
if (!m_bDisabled && s_bGlobalEnable)
|
|
{
|
|
// If in continuous fail mode, check to see if the counters
|
|
// are above the specified range. Otherwise check to see if
|
|
// the counter is exactly the same as what was specified.
|
|
if (m_bContinuous)
|
|
{
|
|
if (m_nCurrent >= m_nFail)
|
|
bFail = TRUE;
|
|
} // if: in continuous fail mode
|
|
else
|
|
{
|
|
if (m_nCurrent == m_nFail)
|
|
bFail = TRUE;
|
|
} // else: not in continuous fail mode
|
|
|
|
// If this API set was marked to fail on the next (this) call,
|
|
// fail the call and reset the marker.
|
|
if (g_bFailOnNextBarf)
|
|
{
|
|
bFail = TRUE;
|
|
g_bFailOnNextBarf = FALSE;
|
|
} // if: counters marked to fail on next (this) call
|
|
} // if: not disabled and globally enabled
|
|
} // if: not suspended
|
|
|
|
return bFail;
|
|
|
|
} //*** CBarf::BFail()
|
|
|
|
|
|
//*************************************************************************//
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CBarfSuspend
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
CRITICAL_SECTION CBarfSuspend::s_critsec;
|
|
BOOL CBarfSuspend::s_bCritSecValid = FALSE;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CBarfSuspend::CBarfSuspend
|
|
//
|
|
// Routine Description:
|
|
// Constructor.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CBarfSuspend::CBarfSuspend(void)
|
|
{
|
|
if (BCritSecValid())
|
|
EnterCriticalSection(Pcritsec());
|
|
|
|
CBarf::s_nSuspend++;
|
|
|
|
if (BCritSecValid())
|
|
LeaveCriticalSection(Pcritsec());
|
|
|
|
} //*** CBarfSuspend::CBarfSuspend()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CBarfSuspend::~CBarfSuspend
|
|
//
|
|
// Routine Description:
|
|
// Destructor.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CBarfSuspend::~CBarfSuspend(void)
|
|
{
|
|
if (BCritSecValid())
|
|
EnterCriticalSection(Pcritsec());
|
|
|
|
CBarf::s_nSuspend--;
|
|
ASSERT(CBarf::s_nSuspend >= 0);
|
|
|
|
if (BCritSecValid())
|
|
LeaveCriticalSection(Pcritsec());
|
|
|
|
} //*** CBarfSuspend::~CBarfSuspend()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CBarfSuspend::Init
|
|
//
|
|
// Routine Description:
|
|
// Initialize the class.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CBarfSuspend::Init(void)
|
|
{
|
|
InitializeCriticalSection(Pcritsec());
|
|
s_bCritSecValid = TRUE;
|
|
|
|
} //*** CBarfSuspend::Init()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CBarfSuspend::Cleanup
|
|
//
|
|
// Routine Description:
|
|
// Initialize the class.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CBarfSuspend::Cleanup(void)
|
|
{
|
|
if (BCritSecValid())
|
|
{
|
|
DeleteCriticalSection(Pcritsec());
|
|
s_bCritSecValid = FALSE;
|
|
} // if: critical section is valid
|
|
|
|
} //*** CBarfSuspend::Cleanup()
|
|
|
|
|
|
//*************************************************************************//
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Global Functions
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// InitBarf
|
|
//
|
|
// Routine Description:
|
|
// Initializes all BARF counters in the BARF list.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void InitBarf(void)
|
|
{
|
|
CBarf * pbarf;
|
|
|
|
// Loop through the BARF counter list.
|
|
for (pbarf = CBarf::s_pbarfFirst ; pbarf != NULL ; pbarf = pbarf->m_pbarfNext)
|
|
pbarf->Init();
|
|
|
|
CBarfSuspend::Init();
|
|
|
|
} //*** InitBarf()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CleanupBarf
|
|
//
|
|
// Routine Description:
|
|
// Cleanup after BARF.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CleanupBarf(void)
|
|
{
|
|
CBarfSuspend::Cleanup();
|
|
|
|
} //*** CleanupBarf()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// EnableBarf
|
|
//
|
|
// Routine Description:
|
|
// Allows user code to enable/disable BARF for sections of code.
|
|
//
|
|
// Arguments:
|
|
// bEnable [IN] TRUE = enable BARF, FALSE = disable BARF.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void EnableBarf(IN BOOL bEnable)
|
|
{
|
|
if (bEnable)
|
|
Trace(g_tagBarf, _T("Artificial Failures enabled"));
|
|
else
|
|
Trace(g_tagBarf, _T("Artificial Failures disabled"));
|
|
|
|
CBarf::s_bGlobalEnable = bEnable;
|
|
|
|
} //*** EnableBarf()
|
|
|
|
#endif // _DEBUG
|