// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

#include "stdafx.h"

#ifdef AFX_CORE1_SEG
#pragma code_seg(AFX_CORE1_SEG)
#endif

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// Debug memory globals and implementation helpers

#ifdef _DEBUG       // most of this file is for debugging

void* __cdecl operator new(size_t nSize, int nType, LPCSTR lpszFileName, int nLine);

/////////////////////////////////////////////////////////////////////////////
// test allocation routines

void* PASCAL CObject::operator new(size_t nSize)
{
#ifdef _AFX_NO_DEBUG_CRT
	return ::operator new(nSize);
#else
	return ::operator new(nSize, _CLIENT_BLOCK, NULL, 0);
#endif // _AFX_NO_DEBUG_CRT
}

void PASCAL CObject::operator delete(void* p)
{
#ifdef _AFX_NO_DEBUG_CRT
	free(p);
#else
	_free_dbg(p, _CLIENT_BLOCK);
#endif
}

#if _MSC_VER >= 1200
void PASCAL CObject::operator delete(void* p, void*)
{
#ifdef _AFX_NO_DEBUG_CRT
	free(p);
#else
	_free_dbg(p, _CLIENT_BLOCK);
#endif
}
#endif

#ifndef _AFX_NO_DEBUG_CRT

void* AFX_CDECL operator new(size_t nSize, LPCSTR lpszFileName, int nLine)
{
	return ::operator new(nSize, _NORMAL_BLOCK, lpszFileName, nLine);
}

#if _MSC_VER >= 1200
void AFX_CDECL operator delete(void* pData, LPCSTR /* lpszFileName */,
	int /* nLine */)
{
	::operator delete(pData);
}
#endif

void* PASCAL
CObject::operator new(size_t nSize, LPCSTR lpszFileName, int nLine)
{
	return ::operator new(nSize, _CLIENT_BLOCK, lpszFileName, nLine);
}

#if _MSC_VER >= 1200
void PASCAL
CObject::operator delete(void *pObject, LPCSTR /* lpszFileName */,
	int /* nLine */)
{
#ifdef _AFX_NO_DEBUG_CRT
	free(pObject);
#else
	_free_dbg(pObject, _CLIENT_BLOCK);
#endif
}
#endif

void* AFXAPI AfxAllocMemoryDebug(size_t nSize, BOOL bIsObject,  LPCSTR lpszFileName, int nLine)
{
	return _malloc_dbg(nSize, bIsObject ? _CLIENT_BLOCK : _NORMAL_BLOCK,
		lpszFileName, nLine);
}

void AFXAPI AfxFreeMemoryDebug(void* pbData, BOOL bIsObject)
{
	_free_dbg(pbData, bIsObject ? _CLIENT_BLOCK : _NORMAL_BLOCK);
}

/////////////////////////////////////////////////////////////////////////////
// allocation failure hook, tracking turn on

BOOL AFXAPI _AfxDefaultAllocHook(size_t, BOOL, LONG)
	{ return TRUE; }

AFX_STATIC_DATA AFX_ALLOC_HOOK pfnAllocHook = _AfxDefaultAllocHook;

AFX_STATIC_DATA _CRT_ALLOC_HOOK pfnCrtAllocHook = NULL;
#if _MSC_VER >= 1200
int __cdecl _AfxAllocHookProxy(int nAllocType, void * pvData, size_t nSize,
	int nBlockUse, long lRequest, const unsigned char * szFilename, int nLine)
#else
int __cdecl _AfxAllocHookProxy(int nAllocType, void * pvData, size_t nSize,
	int nBlockUse, long lRequest, const char * szFilename, int nLine)
#endif
{
#if _MSC_VER >= 1200
	if (nAllocType != _HOOK_ALLOC)
		return (pfnCrtAllocHook)(nAllocType, pvData, nSize,
			nBlockUse, lRequest, (const unsigned char*) szFilename, nLine);
	if ((pfnAllocHook)(nSize, _BLOCK_TYPE(nBlockUse) == _CLIENT_BLOCK, lRequest))
		return (pfnCrtAllocHook)(nAllocType, pvData, nSize,
			nBlockUse, lRequest, (const unsigned char*) szFilename, nLine);
#else
	if (nAllocType != _HOOK_ALLOC)
		return (pfnCrtAllocHook)(nAllocType, pvData, nSize,
			nBlockUse, lRequest, szFilename, nLine);
	if ((pfnAllocHook)(nSize, _BLOCK_TYPE(nBlockUse) == _CLIENT_BLOCK, lRequest))
		return (pfnCrtAllocHook)(nAllocType, pvData, nSize,
			nBlockUse, lRequest, szFilename, nLine);
#endif
	return FALSE;
}

AFX_ALLOC_HOOK AFXAPI AfxSetAllocHook(AFX_ALLOC_HOOK pfnNewHook)
{
	if (pfnCrtAllocHook == NULL)
		pfnCrtAllocHook = _CrtSetAllocHook(_AfxAllocHookProxy);

	AFX_ALLOC_HOOK pfnOldHook = pfnAllocHook;
	pfnAllocHook = pfnNewHook;
	return pfnOldHook;
}

// This can be set to TRUE to override all AfxEnableMemoryTracking calls,
// allowing all allocations, even MFC internal allocations to be tracked.
BOOL _afxMemoryLeakOverride = FALSE;

BOOL AFXAPI AfxEnableMemoryTracking(BOOL bTrack)
{
	if (_afxMemoryLeakOverride)
		return TRUE;

	int nOldState = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
	if (bTrack)
		_CrtSetDbgFlag(nOldState | _CRTDBG_ALLOC_MEM_DF);
	else
		_CrtSetDbgFlag(nOldState & ~_CRTDBG_ALLOC_MEM_DF);
	return nOldState & _CRTDBG_ALLOC_MEM_DF;
}

/////////////////////////////////////////////////////////////////////////////
// stop on a specific memory request

// Obsolete API
void AFXAPI AfxSetAllocStop(LONG lRequestNumber)
{
	_CrtSetBreakAlloc(lRequestNumber);
}

BOOL AFXAPI AfxCheckMemory()
  // check all of memory (look for memory tromps)
{
	return _CrtCheckMemory();
}

// -- true if block of exact size, allocated on the heap
// -- set *plRequestNumber to request number (or 0)
BOOL AFXAPI AfxIsMemoryBlock(const void* pData, UINT nBytes,
		LONG* plRequestNumber)
{
	return _CrtIsMemoryBlock(pData, nBytes, plRequestNumber, NULL, NULL);
}

/////////////////////////////////////////////////////////////////////////////
// CMemoryState

CMemoryState::CMemoryState()
{
	memset(this, 0, sizeof(*this));
}

void CMemoryState::UpdateData()
{
	for(int i = 0; i < nBlockUseMax; i++)
	{
		m_lCounts[i] = m_memState.lCounts[i];
		m_lSizes[i] = m_memState.lSizes[i];
	}
	m_lHighWaterCount = m_memState.lHighWaterCount;
	m_lTotalCount = m_memState.lTotalCount;
}

// fills 'this' with the difference, returns TRUE if significant
BOOL CMemoryState::Difference(const CMemoryState& oldState,
		const CMemoryState& newState)
{
	int nResult = _CrtMemDifference(&m_memState, &oldState.m_memState, &newState.m_memState);
	UpdateData();
	return nResult != 0;
}

void CMemoryState::DumpStatistics() const
{
	_CrtMemDumpStatistics(&m_memState);
}

// -- fill with current memory state
void CMemoryState::Checkpoint()
{
	_CrtMemCheckpoint(&m_memState);
	UpdateData();
}

// Dump objects created after this memory state was checkpointed
// Will dump all objects if this memory state wasn't checkpointed
// Dump all objects, report about non-objects also
// List request number in {}
void CMemoryState::DumpAllObjectsSince() const
{
	_CrtMemDumpAllObjectsSince(&m_memState);
}

/////////////////////////////////////////////////////////////////////////////
// Enumerate all objects allocated in the diagnostic memory heap

struct _AFX_ENUM_CONTEXT
{
	void (*m_pfn)(CObject*,void*);
	void* m_pContext;
};

AFX_STATIC void _AfxDoForAllObjectsProxy(void* pObject, void* pContext)
{
	_AFX_ENUM_CONTEXT* p = (_AFX_ENUM_CONTEXT*)pContext;
	(*p->m_pfn)((CObject*)pObject, p->m_pContext);
}

void AFXAPI
AfxDoForAllObjects(void (AFX_CDECL *pfn)(CObject*, void*), void* pContext)
{
	_AFX_ENUM_CONTEXT context;
	context.m_pfn = pfn;
	context.m_pContext = pContext;
	_CrtDoForAllClientObjects(_AfxDoForAllObjectsProxy, &context);
}

/////////////////////////////////////////////////////////////////////////////
// Automatic debug memory diagnostics

BOOL AFXAPI AfxDumpMemoryLeaks()
{
	return _CrtDumpMemoryLeaks();
}

#endif // _AFX_NO_DEBUG_CRT
#endif // _DEBUG

/////////////////////////////////////////////////////////////////////////////
// Non-diagnostic memory routines

int AFX_CDECL AfxNewHandler(size_t /* nSize */)
{
	AfxThrowMemoryException();
	return 0;
}

#pragma warning(disable: 4273)

#ifndef _AFXDLL
AFX_COMDAT _PNH _afxNewHandler = &AfxNewHandler;
#endif

_PNH AFXAPI AfxGetNewHandler(void)
{
#ifdef _AFXDLL
	AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
	return pState->m_pfnNewHandler;
#else
	return _afxNewHandler;
#endif
}

_PNH AFXAPI AfxSetNewHandler(_PNH pfnNewHandler)
{
#ifdef _AFXDLL
	AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
	_PNH pfnOldHandler = pState->m_pfnNewHandler;
	pState->m_pfnNewHandler = pfnNewHandler;
	return pfnOldHandler;
#else
	_PNH pfnOldHandler = _afxNewHandler;
	_afxNewHandler = pfnNewHandler;
	return pfnOldHandler;
#endif
}

AFX_STATIC_DATA const _PNH _pfnUninitialized = (_PNH)-1;

void* __cdecl operator new(size_t nSize)
{
	void* pResult;
#ifdef _AFXDLL
	_PNH pfnNewHandler = _pfnUninitialized;
#endif
	for (;;)
	{
#if !defined(_AFX_NO_DEBUG_CRT) && defined(_DEBUG)
		pResult = _malloc_dbg(nSize, _NORMAL_BLOCK, NULL, 0);
#else
		pResult = malloc(nSize);
#endif
		if (pResult != NULL)
			return pResult;

#ifdef _AFXDLL
		if (pfnNewHandler == _pfnUninitialized)
		{
			AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
			pfnNewHandler = pState->m_pfnNewHandler;
		}
		if (pfnNewHandler == NULL || (*pfnNewHandler)(nSize) == 0)
			break;
#else
		if (_afxNewHandler == NULL || (*_afxNewHandler)(nSize) == 0)
			break;
#endif
	}
	return pResult;
}

void __cdecl operator delete(void* p)
{
#if !defined(_AFX_NO_DEBUG_CRT) && defined(_DEBUG)
		_free_dbg(p, _NORMAL_BLOCK);
#else
		free(p);
#endif
}

#ifdef _DEBUG

void* __cdecl operator new(size_t nSize, int nType, LPCSTR lpszFileName, int nLine)
{
#ifdef _AFX_NO_DEBUG_CRT
	UNUSED_ALWAYS(nType);
	UNUSED_ALWAYS(lpszFileName);
	UNUSED_ALWAYS(nLine);
	return ::operator new(nSize);
#else
	void* pResult;
#ifdef _AFXDLL
	_PNH pfnNewHandler = _pfnUninitialized;
#endif
	for (;;)
	{
		pResult = _malloc_dbg(nSize, nType, lpszFileName, nLine);
		if (pResult != NULL)
			return pResult;

#ifdef _AFXDLL
		if (pfnNewHandler == _pfnUninitialized)
		{
			AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
			pfnNewHandler = pState->m_pfnNewHandler;
		}
		if (pfnNewHandler == NULL || (*pfnNewHandler)(nSize) == 0)
			break;
#else
		if (_afxNewHandler == NULL || (*_afxNewHandler)(nSize) == 0)
			break;
#endif
	}
	return pResult;
#endif
}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
