//====================================
// File: PERFCNTR.CPP
// Author: Matt Pietrek
// From: Microsoft Systems Journal
//       "Under the Hood", APRIL 1996
//====================================

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <winperf.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <tchar.h>
#pragma hdrstop
#include "perfcntr.h"

CPerfCounter::CPerfCounter( PTSTR const pszName, DWORD type,
							PBYTE const pData, DWORD cbData )
{
	m_pszName = _tcsdup( pszName );
	m_type = type;
	m_cbData = cbData;
	m_pData = new BYTE[m_cbData];
	memcpy( m_pData, pData, m_cbData );
}

CPerfCounter::~CPerfCounter( void )
{
	free( m_pszName );
	delete []m_pData;
}

BOOL
CPerfCounter::GetData( PBYTE pBuffer, DWORD cbBuffer, DWORD *pType )
{
	if ( cbBuffer < m_cbData )  // Make sure the buffer is big enough
		return FALSE;

	memcpy( pBuffer, m_pData, m_cbData );   // copy the data

	if ( pType )            // If the user wants the type, give it to them
		*pType = m_type;

	return TRUE;
}

BOOL
CPerfCounter::Format( PTSTR pszBuffer, DWORD nSize, BOOL fHex )
{
	// Do better formatting!!!  Check length!!!

	PTSTR pszPrefix = TEXT("");
	TCHAR szTemp[512];

	// First, ascertain the basic type (number, counter, text, or zero)
	switch ( m_type & 0x00000C00 )
	{
		case PERF_TYPE_ZERO:
		{
			wsprintf( pszBuffer, TEXT("ZERO") ); return TRUE;
		}
		case PERF_TYPE_TEXT:
		{
			wsprintf( pszBuffer, TEXT("text counter") ); return TRUE;
		}
		case PERF_TYPE_COUNTER:
		{
			switch( m_type & 0x00070000 )
			{
				case PERF_COUNTER_RATE:
					pszPrefix = TEXT("counter rate "); break;
				case PERF_COUNTER_FRACTION:
					pszPrefix = TEXT("counter fraction "); break;
				case PERF_COUNTER_BASE:
					pszPrefix = TEXT("counter base "); break;
				case PERF_COUNTER_ELAPSED:
					pszPrefix = TEXT("counter elapsed "); break;
				case PERF_COUNTER_QUEUELEN:
					pszPrefix = TEXT("counter queuelen "); break;
				case PERF_COUNTER_HISTOGRAM:
					pszPrefix = TEXT("counter histogram "); break;
				default:
					pszPrefix = TEXT("counter value "); break;
			}
		}
	}

	PTSTR pszFmt = fHex ? TEXT("%s%Xh") : TEXT("%s%u");

	switch ( m_cbData )
	{
		case 1: wsprintf(szTemp, pszFmt, pszPrefix, *(PBYTE)m_pData);
				break;
		case 2: wsprintf(szTemp, pszFmt, pszPrefix, *(PWORD)m_pData);
				break;
		case 4: wsprintf(szTemp, pszFmt, pszPrefix, *(PDWORD)m_pData);
				break;
		case 8: // Danger!  Assumes little-endian (X86) byte ordering
				wsprintf( szTemp, TEXT("%s%X%X"), pszPrefix,
						*(PDWORD)(m_pData+4), *(PDWORD)m_pData ); break;
				break;

		default: wsprintf( szTemp, TEXT("<unhandled size %u>"), m_cbData );
	}

	switch ( m_type & 0x70000000 )
	{
		case PERF_DISPLAY_SECONDS:
			_tcscat( szTemp, TEXT(" secs") ); break;
		case PERF_DISPLAY_PERCENT:
			_tcscat( szTemp, TEXT(" %") ); break;
		case PERF_DISPLAY_PER_SEC:
			_tcscat( szTemp, TEXT(" /sec") ); break;
	}

	lstrcpyn( pszBuffer, szTemp, nSize );

	return TRUE;
}