mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
857 lines
22 KiB
857 lines
22 KiB
/*++
|
|
|
|
Copyright (C) 1995-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
PERFCACH.CPP
|
|
|
|
Abstract:
|
|
|
|
Containes some classes which are used to cache NT performance data.
|
|
|
|
History:
|
|
|
|
a-davj 15-DEC-95 Created.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <wbemidl.h>
|
|
#include "perfcach.h"
|
|
#include <winperf.h>
|
|
#include <tchar.h>
|
|
|
|
//***************************************************************************
|
|
//
|
|
// BOOL CIndicyList::SetUse
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Indicates that an object type has just been used. If the object
|
|
// is already on the list, then its last accessed time is updated. New
|
|
// object types are added to the list
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// iObj Number. The acutally translates to the object number
|
|
// that perf monitor uses to identify objects.
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// always TRUE unless it was a new entry and there isnt enough memory
|
|
// to add.
|
|
//***************************************************************************
|
|
|
|
BOOL CIndicyList::SetUse(
|
|
IN int iObj)
|
|
{
|
|
int iNumEntries, iCnt;
|
|
|
|
// Go Through list and determine if there is an entry
|
|
|
|
Entry * pCurr;
|
|
iNumEntries = Entries.Size();
|
|
for(iCnt = 0; iCnt < iNumEntries; iCnt++)
|
|
{
|
|
pCurr = (Entry *)Entries.GetAt(iCnt);
|
|
if(iObj == pCurr->iObject) // found it!
|
|
break;
|
|
}
|
|
|
|
if(iCnt < iNumEntries)
|
|
{
|
|
|
|
// Found the entry. Set its last used to to the
|
|
// present unless it is a permanent entry
|
|
|
|
if(pCurr->dwLastUsed != PERMANENT)
|
|
pCurr->dwLastUsed = GetCurrentTime();
|
|
return TRUE;
|
|
}
|
|
else
|
|
|
|
// Entry not found, add to list
|
|
|
|
return bAdd(iObj,GetCurrentTime());
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// BOOL CIndicyList::bItemInList
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Checks if an item is in the list.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// iObj Number. The acutally translates to the object number
|
|
// that perf monitor uses to identify objects.
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// TRUE if the item is in the list
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL CIndicyList::bItemInList(
|
|
IN int iObj)
|
|
{
|
|
int iNumEntries, iCnt;
|
|
|
|
// Go Through list and determine if the entry is there
|
|
|
|
Entry * pCurr;
|
|
iNumEntries = Entries.Size();
|
|
for(iCnt = 0; iCnt < iNumEntries; iCnt++)
|
|
{
|
|
pCurr = (Entry *)Entries.GetAt(iCnt);
|
|
if(iObj == pCurr->iObject) // found it!
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// BOOL CIndicyList::bAdd
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Adds an object type to the list
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// iObj Number. The acutally translates to the object number
|
|
// that perf monitor uses to identify objects.
|
|
// dwTime Current system time
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// Returns TRUE if OK.
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL CIndicyList::bAdd(
|
|
IN int iObj,
|
|
IN DWORD dwTime)
|
|
{
|
|
Entry * pNew = new Entry;
|
|
if(pNew == NULL)
|
|
return FALSE;
|
|
pNew->iObject = iObj;
|
|
pNew->dwLastUsed = dwTime;
|
|
|
|
int iRet = Entries.Add(pNew);
|
|
if(iRet != CFlexArray::no_error)
|
|
{
|
|
delete pNew;
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// void CIndicyList::PruneOld
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Looks at the entries in the list and removes any that have
|
|
// not been used in a long time.
|
|
//
|
|
//***************************************************************************
|
|
|
|
void CIndicyList::PruneOld(void)
|
|
{
|
|
Entry * pCurr;
|
|
int iNumEntries, iCnt;
|
|
DWORD dwCurr = GetCurrentTime();
|
|
iNumEntries = Entries.Size();
|
|
for(iCnt = iNumEntries-1; iCnt >= 0; iCnt--)
|
|
{
|
|
pCurr = (Entry *)Entries.GetAt(iCnt);
|
|
if(pCurr->dwLastUsed != PERMANENT)
|
|
if((dwCurr - pCurr->dwLastUsed) > MAX_UNUSED_KEEP)
|
|
{
|
|
Entries.RemoveAt(iCnt);
|
|
delete pCurr;
|
|
}
|
|
}
|
|
// Entries.FreeExtra();
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// LPCTSTR CIndicyList::pGetAll
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Returns a pointer to a string containing the numbers of all the objects
|
|
// on the list. For example, if the list had objects 2,4, and 8; then
|
|
// the string "2 4 8" would be retrieved. Null is returned if there
|
|
// isnt enough memory.
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// see description
|
|
//
|
|
//***************************************************************************
|
|
|
|
LPCTSTR CIndicyList::pGetAll(void)
|
|
{
|
|
int iNumEntries, iCnt;
|
|
Entry * pCurr;
|
|
|
|
// Go Through list and add each object number to the string
|
|
|
|
sAll.Empty();
|
|
iNumEntries = Entries.Size();
|
|
for(iCnt = 0; iCnt < iNumEntries; iCnt++)
|
|
{
|
|
TCHAR pTemp[20];
|
|
pCurr = (Entry *)Entries.GetAt(iCnt);
|
|
sAll += _itot(pCurr->iObject,pTemp,10);
|
|
if(iCnt < iNumEntries-1)
|
|
sAll += TEXT(" ");
|
|
}
|
|
return sAll;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CIndicyList & CIndicyList::operator =
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Supports the assignment of one CIndicyList object to another
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// from Value to copy
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// reterence the "this" object
|
|
//***************************************************************************
|
|
|
|
CIndicyList & CIndicyList::operator = (
|
|
CIndicyList & from)
|
|
{
|
|
int iNumEntries, iCnt;
|
|
Entry * pCurr;
|
|
|
|
// Free existing list
|
|
|
|
FreeAll();
|
|
|
|
iNumEntries = from.Entries.Size();
|
|
for(iCnt = 0; iCnt < iNumEntries; iCnt++)
|
|
{
|
|
pCurr = (Entry *)from.Entries.GetAt(iCnt);
|
|
bAdd(pCurr->iObject, pCurr->dwLastUsed);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// void CIndicyList::FreeAll
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Purpose: Clears out the list and frees memory.
|
|
//
|
|
//***************************************************************************
|
|
|
|
void CIndicyList::FreeAll(void)
|
|
{
|
|
int iNumEntries, iCnt;
|
|
// Go Through list and determine if there is an entry
|
|
|
|
Entry * pCurr;
|
|
|
|
// delete each object in the list.
|
|
|
|
iNumEntries = Entries.Size();
|
|
for(iCnt = 0; iCnt < iNumEntries; iCnt++)
|
|
{
|
|
pCurr = (Entry *)Entries.GetAt(iCnt);
|
|
delete pCurr;
|
|
}
|
|
Entries.Empty();
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// DWORD PerfBuff::Read
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Read the perf monitor data.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// hKey Registry key for perf mon data
|
|
// iObj Number. The acutally translates to the object number
|
|
// that perf monitor uses to identify objects.
|
|
// bInitial Set to TRUE for first call
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// 0 All is well
|
|
// WBEM_E_OUT_OF_MEMORY
|
|
//
|
|
//***************************************************************************
|
|
|
|
DWORD PerfBuff::Read(
|
|
IN HKEY hKey,
|
|
IN int iObj,
|
|
IN BOOL bInitial)
|
|
{
|
|
DWORD dwRet;
|
|
LPCTSTR pRequest;
|
|
// Make sure there is a data buffer
|
|
|
|
if(dwSize == 0)
|
|
{
|
|
pData = new char[INITIAL_ALLOCATION];
|
|
if(pData == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
dwSize = INITIAL_ALLOCATION;
|
|
}
|
|
hKeyLastRead = hKey; // record the key that was used
|
|
|
|
// Make sure that the desired object is in the list of
|
|
// objects to be retrieved. Also set pRequest to the string that will
|
|
// be passed to retrieve the perf counter block. An initial read is done
|
|
// in order to establish the list of permanent object types which are
|
|
// always to be retrived and that includes the standard "global" types
|
|
// such as memory, processor, disk, etc.
|
|
|
|
if(!bInitial)
|
|
{
|
|
if(!List.SetUse(iObj))
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
List.PruneOld();
|
|
pRequest = List.pGetAll();
|
|
if(pRequest == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
pRequest = TEXT("Global");
|
|
|
|
// Read the data. Note that the read may be retried if the data
|
|
// block needs to be expanded
|
|
|
|
do
|
|
{
|
|
DWORD dwTempSize, dwType;
|
|
dwTempSize = dwSize;
|
|
try
|
|
{
|
|
dwRet = RegQueryValueEx (hKey,pRequest,NULL,&dwType,
|
|
(BYTE *)pData,&dwTempSize);
|
|
}
|
|
catch(...)
|
|
{
|
|
delete pData;
|
|
return WBEM_E_FAILED;
|
|
}
|
|
if(dwRet == ERROR_MORE_DATA)
|
|
{
|
|
delete pData;
|
|
dwSize += 5000;
|
|
pData = new char[dwSize];
|
|
if(pData == NULL)
|
|
{
|
|
dwSize = 0;
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
} while (dwRet == ERROR_MORE_DATA);
|
|
|
|
// Set the age of the data
|
|
|
|
if(dwRet == ERROR_SUCCESS)
|
|
{
|
|
PERF_DATA_BLOCK * pBlock = (PERF_DATA_BLOCK *)pData;
|
|
PerfTime = *(LONGLONG UNALIGNED *)(&pBlock->PerfTime);
|
|
PerfTime100nSec = *(LONGLONG UNALIGNED *)(&pBlock->PerfTime100nSec);
|
|
PerfFreq = *(LONGLONG UNALIGNED *)(&pBlock->PerfFreq);
|
|
dwBuffLastRead = GetCurrentTime();
|
|
}
|
|
else
|
|
dwBuffLastRead = 0;
|
|
|
|
// If this was an initial read of the default objects, add all the
|
|
// default objects to the list as permanent entries
|
|
|
|
if(bInitial && dwRet == ERROR_SUCCESS)
|
|
{
|
|
int iIndex;
|
|
PERF_DATA_BLOCK * pBlock = (PERF_DATA_BLOCK * )pData;
|
|
PPERF_OBJECT_TYPE pObj;
|
|
pObj = (PPERF_OBJECT_TYPE)((PBYTE)pBlock + pBlock->HeaderLength);
|
|
for(iIndex = 0; iIndex < (int)pBlock->NumObjectTypes; iIndex++)
|
|
{
|
|
//todo, check for errors on add.
|
|
if(!List.bAdd((int)pObj->ObjectNameTitleIndex,PERMANENT))
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
pObj = (PPERF_OBJECT_TYPE)((PBYTE)pObj + pObj->TotalByteLength);
|
|
}
|
|
}
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// LPSTR PerfBuff::Get
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Returns a pointer to the data and also indicates that the particular type
|
|
// was just used.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// iObj Number. The acutally translates to the object number
|
|
// that perf monitor uses to identify objects.
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// see description.
|
|
//***************************************************************************
|
|
|
|
LPSTR PerfBuff::Get(
|
|
int iObj)
|
|
{
|
|
List.SetUse(iObj);
|
|
return pData;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// void PerfBuff::Free
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Frees up the memory
|
|
//
|
|
//***************************************************************************
|
|
|
|
void PerfBuff::Free()
|
|
{
|
|
if(pData)
|
|
delete pData;
|
|
pData = NULL;
|
|
dwSize = 0;
|
|
hKeyLastRead = NULL;
|
|
dwBuffLastRead = 0;
|
|
List.FreeAll();
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// PerfBuff::PerfBuff
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Constructor.
|
|
//
|
|
//***************************************************************************
|
|
|
|
PerfBuff::PerfBuff()
|
|
{
|
|
dwSize = 0;
|
|
pData = NULL;
|
|
hKeyLastRead = NULL;
|
|
dwBuffLastRead = 0;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// BOOL PerfBuff::bOK
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Returns TRUE, if and only if the same registry key was used to read
|
|
// the data, the data isnt too old, and the particular object type is
|
|
// in the data block.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// hKey Registry key for reading data
|
|
// dwMaxAge Maximum acceptable age
|
|
// iObj Number. The acutally translates to the object number
|
|
// that perf monitor uses to identify objects.
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// see desription
|
|
//***************************************************************************
|
|
|
|
BOOL PerfBuff::bOK(
|
|
IN HKEY hKey,
|
|
IN DWORD dwMaxAge,
|
|
IN int iObj)
|
|
{
|
|
if(dwSize ==0)
|
|
return FALSE;
|
|
if(hKey != hKeyLastRead)
|
|
return FALSE;
|
|
if((GetCurrentTime() - dwBuffLastRead) > dwMaxAge)
|
|
return FALSE;
|
|
return List.bItemInList(iObj);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// PerfBuff & PerfBuff::operator =
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Allows assignment.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// from Assignment source
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// reference to "this" object.
|
|
//***************************************************************************
|
|
|
|
PerfBuff & PerfBuff::operator = (
|
|
IN PerfBuff & from)
|
|
{
|
|
// if the objects have different buffer sizes, free up the destinations
|
|
// buffer and reallocate on of the same size as the source.
|
|
|
|
if(from.dwSize != dwSize)
|
|
{
|
|
Free();
|
|
pData = new char[from.dwSize];
|
|
if(pData == NULL)
|
|
{
|
|
|
|
// failure in assignment isnt too serious since the buffer
|
|
// will just return null when asked for the data.
|
|
|
|
dwSize = 0;
|
|
dwBuffLastRead = 0;
|
|
return *this;
|
|
}
|
|
dwSize = from.dwSize;
|
|
}
|
|
|
|
// Copy the list of objects and times etc.
|
|
|
|
memcpy(pData,from.pData,dwSize);
|
|
List = from.List;
|
|
hKeyLastRead = from.hKeyLastRead;
|
|
dwBuffLastRead = from.dwBuffLastRead;
|
|
PerfTime = from.PerfTime;
|
|
PerfTime100nSec = from.PerfTime100nSec;
|
|
PerfFreq = from.PerfFreq;
|
|
return *this;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// void PerfCache::FreeOldBuffers
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Called by the house keeping thread to free up any buffers tool old to
|
|
// be of any use.
|
|
//
|
|
//***************************************************************************
|
|
|
|
void PerfCache::FreeOldBuffers(void)
|
|
{
|
|
if(Old.dwSize != 0 &&
|
|
(GetCurrentTime() - Old.dwBuffLastRead) > MAX_OLD_AGE)
|
|
Old.Free();
|
|
if(New.dwSize != 0 &&
|
|
(GetCurrentTime() - New.dwBuffLastRead) > MAX_OLD_AGE)
|
|
New.Free();
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// DWORD PerfCache::dwGetNew
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Sets a pointer to the most recently read data and will actually do a read
|
|
// if the data in the new buffer isnt fresh enough. The PLINESTRUCT data is
|
|
// also set.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pName Machine name
|
|
// iObj Number. The acutally translates to the object number
|
|
// that perf monitor uses to identify objects.
|
|
// pData Set to the object name
|
|
// pls Set to info used to do calculations.
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// 0 all is well
|
|
// WBEM_E_OUT_OF_MEMORY
|
|
// otherwise error from dwGetHandle, or Read.
|
|
//***************************************************************************
|
|
|
|
DWORD PerfCache::dwGetNew(
|
|
IN LPCTSTR pName,
|
|
IN int iObj,
|
|
OUT IN LPSTR * pData,
|
|
OUT IN PLINESTRUCT pls)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
// Get the handle
|
|
|
|
dwRet = dwGetHandle(pName);
|
|
if(hHandle == NULL || dwRet != 0)
|
|
return dwRet;
|
|
|
|
|
|
// If the new data is acceptable, then use it
|
|
|
|
if(New.bOK(hHandle,MAX_NEW_AGE, iObj))
|
|
{
|
|
// OutputDebugString(TEXT("\r\nCurrent New is OK"));
|
|
}
|
|
else
|
|
{
|
|
// If the new data has the correct type, AND either the old data
|
|
// is junk, or the new data has aged enough to be old, copy the
|
|
// new into the old.
|
|
|
|
if(New.bOK(hHandle,MAX_OLD_AGE, iObj) &&
|
|
(!Old.bOK(hHandle,MAX_OLD_AGE, iObj) ||
|
|
(GetCurrentTime() - New.dwBuffLastRead >= MIN_TIME_DIFF)))
|
|
{
|
|
// OutputDebugString("\r\nMoving New into Old in dwGetNew");
|
|
Old = New;
|
|
if(Old.dwSize == 0) // could happen in low memory
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
// Read the latest data.
|
|
|
|
dwRet = New.Read(hHandle, iObj, FALSE);
|
|
// OutputDebugString(TEXT("\r\nRead in New"));
|
|
if(dwRet != ERROR_SUCCESS)
|
|
return dwRet;
|
|
}
|
|
*pData = New.Get(iObj);
|
|
pls->lnNewTime = New.PerfTime;
|
|
pls->lnNewTime100Ns = New.PerfTime100nSec;
|
|
pls->lnPerfFreq = New.PerfFreq;
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// DWORD PerfCache::dwGetPair
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Sets a pointer to the most recently read data and to the old data so that
|
|
// time averaging can be done. This routine will ensure that the time
|
|
// difference between the old and new is sufficient. The dwGetNew
|
|
// routine should always be called first. The PLINESTRUCT data is
|
|
// also set.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pName Object Name
|
|
// iObj Number. The acutally translates to the object number
|
|
// that perf monitor uses to identify objects.
|
|
//
|
|
// pOldData Older data sample
|
|
// pNewData Newer data sample
|
|
// pls line struct data with things like frequency, age etc.
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// 0 if OK, otherwise retuns an error code.
|
|
//
|
|
//***************************************************************************
|
|
|
|
DWORD PerfCache::dwGetPair(
|
|
IN LPCTSTR pName,
|
|
IN int iObj,
|
|
OUT IN LPSTR * pOldData,
|
|
OUT IN LPSTR * pNewData,
|
|
OUT IN PLINESTRUCT pls)
|
|
{
|
|
DWORD dwRet;
|
|
BOOL bOldOK;
|
|
|
|
// Check to see if the old buffer is OK.
|
|
|
|
bOldOK = Old.bOK(hHandle,MAX_OLD_AGE, iObj);
|
|
|
|
// If both buffers are ok, then we are done
|
|
|
|
if(bOldOK)
|
|
{
|
|
*pOldData = Old.Get(iObj);
|
|
pls->lnOldTime = Old.PerfTime;
|
|
pls->lnOldTime100Ns = Old.PerfTime100nSec;
|
|
// OutputDebugString(TEXT("\r\nOld is OK"));
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
// Since the new buffer has already been read, use it as the old buffer
|
|
|
|
Old = New;
|
|
if(Old.dwSize == 0) // could happen in low memory
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
// OutputDebugString(TEXT("\r\nCopying New into Old in dwGetPair"));
|
|
|
|
// Possibly delay long enough so that there is a decent interval
|
|
|
|
DWORD dwAge = GetCurrentTime() - Old.dwBuffLastRead;
|
|
if(dwAge < MIN_TIME_DIFF)
|
|
{
|
|
DWORD dwSleep = MIN_TIME_DIFF - dwAge;
|
|
TCHAR temp[100];
|
|
wsprintf(temp,TEXT("\r\nsleeping %u ms"),dwSleep);
|
|
// OutputDebugString(temp);
|
|
Sleep(dwSleep);
|
|
}
|
|
|
|
// Read in the new buffer
|
|
|
|
dwRet = New.Read(hHandle, iObj, FALSE);
|
|
// OutputDebugString(TEXT("\r\ndoing raw read of new after delay"));
|
|
if(dwRet != ERROR_SUCCESS)
|
|
return dwRet;
|
|
|
|
*pNewData = New.Get(iObj);
|
|
*pOldData = Old.Get(iObj);
|
|
pls->lnOldTime = Old.PerfTime;
|
|
pls->lnOldTime100Ns = Old.PerfTime100nSec;
|
|
|
|
pls->lnNewTime = New.PerfTime;
|
|
pls->lnNewTime100Ns = New.PerfTime100nSec;
|
|
pls->lnPerfFreq = New.PerfFreq;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// PerfCache::PerfCache
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Constructor.
|
|
//
|
|
//***************************************************************************
|
|
|
|
PerfCache::PerfCache()
|
|
{
|
|
// Read in the standard counters. This builds a list containing
|
|
// those standards as well as providing immediate data for any
|
|
// request to come in the near future.
|
|
|
|
hHandle = HKEY_PERFORMANCE_DATA;
|
|
/// New.Read(hHandle, 0, TRUE);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// PerfCache::~PerfCache
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Destructor.
|
|
//
|
|
//***************************************************************************
|
|
|
|
PerfCache::~PerfCache()
|
|
{
|
|
// If the handle is to a remote machine, close it.
|
|
|
|
if(hHandle != NULL && hHandle != HKEY_PERFORMANCE_DATA)
|
|
RegCloseKey(hHandle);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// DWORD PerfCache::dwGetHandle
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Makes sure that hHandle is set correctly.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pMachine Machine name.
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// 0 all is well
|
|
// WBEM_E_OUT_OF_MEMORY
|
|
// WBEM_E_INVALID_PARAMETER bad argument
|
|
// otherwise error from RegConnectRegistry
|
|
//
|
|
//***************************************************************************
|
|
|
|
DWORD PerfCache::dwGetHandle(
|
|
LPCTSTR pMachine)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
// if the machines are the same, the just use the existing handle
|
|
|
|
if(pMachine == NULL)
|
|
return WBEM_E_INVALID_PARAMETER; // bad mapping string
|
|
|
|
if(!lstrcmpi(sMachine,pMachine) && hHandle != NULL)
|
|
return 0; // already got it!
|
|
|
|
// handle is needed for machine other that the local. Start
|
|
// by freeing the existing handle if it too is non local
|
|
|
|
if(hHandle != NULL && hHandle != HKEY_PERFORMANCE_DATA)
|
|
RegCloseKey(hHandle);
|
|
|
|
// save the machine name so that we dont reopen this
|
|
|
|
sMachine = pMachine;
|
|
|
|
if(lstrcmpi(pMachine,TEXT("local")))
|
|
{
|
|
|
|
LPTSTR pTemp = NULL;
|
|
int iLen = sMachine.Length() +1;
|
|
|
|
dwRet = RegConnectRegistry(sMachine,HKEY_PERFORMANCE_DATA,
|
|
&hHandle);
|
|
|
|
if(dwRet != ERROR_SUCCESS)
|
|
{ // could not remote connect
|
|
hHandle = NULL;
|
|
sMachine.Empty();
|
|
}
|
|
}
|
|
else
|
|
{ // local machine, use standard handle.
|
|
sMachine = TEXT("Local");
|
|
hHandle = HKEY_PERFORMANCE_DATA;
|
|
dwRet = 0;
|
|
}
|
|
return dwRet;
|
|
}
|
|
|