PVIEWDAT.C


/******************************************************************************\
* This is a part of the Microsoft Source Code Samples.
* Copyright 1993 - 1998 Microsoft Corporation.
* All rights reserved.
* This source code is only intended as a supplement to
* Microsoft Development Tools and/or WinHelp documentation.
* See these sources for detailed information regarding the
* Microsoft samples programs.
\******************************************************************************/


/******************************************************************************

P V I E W D A T A

Name: pviewdat.c

Description:
This module collects the data to be displayed in pview.

******************************************************************************/

#include <windows.h>
#include <winperf.h>
#include "perfdata.h"
#include "pviewdat.h"
#include "pviewdlg.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>


#define NODATA TEXT("--------")





void FormatTimeFields
(double fTime,
PTIME_FIELD pTimeFld);

DWORD PutCounterDWKB
(HWND hWnd,
DWORD dwItemID,
PPERF_INSTANCE pInst,
PPERF_OBJECT pObj,
DWORD dwCounterIdx);

DWORD PutCounterHEX
(HWND hWnd,
DWORD dwItemID,
PPERF_INSTANCE pInst,
PPERF_OBJECT pObj,
DWORD dwCounterIdx);

DWORD PutCounterDW
(HWND hWnd,
DWORD dwItemID,
PPERF_INSTANCE pInst,
PPERF_OBJECT pObj,
DWORD dwCounterIdx);

void PaintAddressSpace
(HWND hMemDlg,
PPERF_INSTANCE pInst,
PPERF_OBJECT pObj,
DWORD TotalID,
DWORD NoAccessID,
DWORD NoAccessIndex,
DWORD ReadOnlyID,
DWORD ReadOnlyIndex,
DWORD ReadWriteID,
DWORD ReadWriteIndex,
DWORD WriteCopyID,
DWORD WriteCopyIndex,
DWORD ExecuteID,
DWORD ExecuteIndex1,
DWORD ExecuteIndex2,
DWORD ExecuteIndex3,
DWORD ExecuteIndex4);

void PaintMemDlgAddrData
(HWND hMemDlg,
PPERF_INSTANCE pInst,
PPERF_OBJECT pObj);

void PaintMemDlgVMData
(HWND hMemDlg,
PPERF_INSTANCE pInst,
PPERF_OBJECT pObj);

void PaintPviewDlgMemoryData
(HWND hPviewDlg,
PPERF_INSTANCE pInst,
PPERF_OBJECT pObj);

void RefreshMemoryDlgImageList
(HWND hImageList,
DWORD ParentIndex,
PPERF_OBJECT pImageObj);

WORD ProcessPriority
(PPERF_OBJECT pObject,
PPERF_INSTANCE pInstance);

void SetProcessListText
(PPERF_INSTANCE pInst,
PPERF_COUNTER pCPU,
PPERF_COUNTER pPRIV,
PPERF_COUNTER pProcID,
double fTime,
LPTSTR str);

void SetThreadListText
(PPERF_INSTANCE pInst,
PPERF_COUNTER pCPU,
PPERF_COUNTER pPRIV,
double fTime,
LPTSTR str);




//*********************************************************************
//
// FormatTimeFields
//
// Formats a double value to time fields.
//
void FormatTimeFields (double fTime,
PTIME_FIELD pTimeFld)
{
INT i;
double f;

f = fTime/3600;

pTimeFld->Hours = i = (int)f;

f = f - i;
pTimeFld->Mins = i = (int)(f = f * 60);

f = f - i;
pTimeFld->Secs = i = (int)(f = f * 60);

f = f - i;
pTimeFld->mSecs = (int)(f * 1000);
}




//*********************************************************************
//
// PutCounterDWKB
//
// Display a DWORD counter's data in KB units.
//
DWORD PutCounterDWKB (HWND hWnd,
DWORD dwItemID,
PPERF_INSTANCE pInst,
PPERF_OBJECT pObj,
DWORD dwCounterIdx)
{
PPERF_COUNTER pCounter;
DWORD *pdwData;
TCHAR szTemp[20];

if (pCounter = FindCounter (pObj, dwCounterIdx))
{
pdwData = (DWORD *) CounterData (pInst, pCounter);
wsprintf (szTemp, TEXT("%ld KB"), *pdwData/1024);
SetDlgItemText (hWnd, dwItemID, szTemp);

return *pdwData;
}
else
{
SetDlgItemText (hWnd, dwItemID, NODATA);
return 0;
}

}




//*********************************************************************
//
// PutCounterHEX
//
// Display a DWORD counter's data in hex.
//
DWORD PutCounterHEX (HWND hWnd,
DWORD dwItemID,
PPERF_INSTANCE pInst,
PPERF_OBJECT pObj,
DWORD dwCounterIdx)
{
PPERF_COUNTER pCounter;
DWORD *pdwData;
TCHAR szTemp[20];

if (pCounter = FindCounter (pObj, dwCounterIdx))
{
pdwData = (DWORD *) CounterData (pInst, pCounter);
wsprintf (szTemp, TEXT("0x%08x"), *pdwData);
SetDlgItemText (hWnd, dwItemID, szTemp);

return *pdwData;
}
else
{
SetDlgItemText (hWnd, dwItemID, NODATA);
return 0;
}

}




//*********************************************************************
//
// PutCounterDWKB
//
// Display a DWORD counter's data.
//
DWORD PutCounterDW (HWND hWnd,
DWORD dwItemID,
PPERF_INSTANCE pInst,
PPERF_OBJECT pObj,
DWORD dwCounterIdx)
{
PPERF_COUNTER pCounter;
DWORD *pdwData;

if (pCounter = FindCounter (pObj, dwCounterIdx))
{
pdwData = (DWORD *) CounterData (pInst, pCounter);
SetDlgItemInt (hWnd, dwItemID, *pdwData, FALSE);

return *pdwData;
}
else
{
SetDlgItemText (hWnd, dwItemID, NODATA);
return 0;
}

}




//*********************************************************************
//
// PaintAddressSpace
//
//
void PaintAddressSpace (HWND hMemDlg,
PPERF_INSTANCE pInst,
PPERF_OBJECT pObj,
DWORD TotalID,
DWORD NoAccessID,
DWORD NoAccessIndex,
DWORD ReadOnlyID,
DWORD ReadOnlyIndex,
DWORD ReadWriteID,
DWORD ReadWriteIndex,
DWORD WriteCopyID,
DWORD WriteCopyIndex,
DWORD ExecuteID,
DWORD ExecuteIndex1,
DWORD ExecuteIndex2,
DWORD ExecuteIndex3,
DWORD ExecuteIndex4)
{
PPERF_COUNTER pCounter;
DWORD *pdwData;
TCHAR szTemp[20];

DWORD dwTotal = 0;
DWORD dwExecute = 0;
BOOL bCounter = FALSE;


dwTotal += PutCounterDWKB (hMemDlg, NoAccessID, pInst, pObj, NoAccessIndex);
dwTotal += PutCounterDWKB (hMemDlg, ReadOnlyID, pInst, pObj, ReadOnlyIndex);
dwTotal += PutCounterDWKB (hMemDlg, ReadWriteID, pInst, pObj, ReadWriteIndex);
dwTotal += PutCounterDWKB (hMemDlg, WriteCopyID, pInst, pObj, WriteCopyIndex);


// execute is the sum of the following
//
if (pCounter = FindCounter (pObj, ExecuteIndex1))
{
pdwData = (DWORD *) CounterData (pInst, pCounter);
dwTotal += *pdwData;
dwExecute += *pdwData;
bCounter = TRUE;
}

if (pCounter = FindCounter (pObj, ExecuteIndex2))
{
pdwData = (DWORD *) CounterData (pInst, pCounter);
dwTotal += *pdwData;
dwExecute += *pdwData;
bCounter = TRUE;
}

if (pCounter = FindCounter (pObj, ExecuteIndex3))
{
pdwData = (DWORD *) CounterData (pInst, pCounter);
dwTotal += *pdwData;
dwExecute += *pdwData;
bCounter = TRUE;
}

if (pCounter = FindCounter (pObj, ExecuteIndex4))
{
pdwData = (DWORD *) CounterData (pInst, pCounter);
dwTotal += *pdwData;
dwExecute += *pdwData;
bCounter = TRUE;
}

if (bCounter)
{
wsprintf (szTemp, TEXT("%ld KB"), dwExecute/1024);
SetDlgItemText (hMemDlg, ExecuteID, szTemp);
}
else
SetDlgItemText (hMemDlg, ExecuteID, NODATA);

wsprintf (szTemp, TEXT("%ld KB"), dwTotal/1024);
SetDlgItemText (hMemDlg, TotalID, szTemp);

}




//*********************************************************************
//
// PaintMemDlgAddrData
//
// Paint the memory dialog address space data.
//
void PaintMemDlgAddrData(HWND hMemDlg,
PPERF_INSTANCE pInst,
PPERF_OBJECT pObj)
{
PaintAddressSpace (hMemDlg, pInst, pObj,
MEMORY_TOTALPRIVATE_COMMIT,
MEMORY_PRIVATE_NOACCESS, PX_PROCESS_PRIVATE_NOACCESS,
MEMORY_PRIVATE_READONLY, PX_PROCESS_PRIVATE_READONLY,
MEMORY_PRIVATE_READWRITE, PX_PROCESS_PRIVATE_READWRITE,
MEMORY_PRIVATE_WRITECOPY, PX_PROCESS_PRIVATE_WRITECOPY,
MEMORY_PRIVATE_EXECUTE, PX_PROCESS_PRIVATE_EXECUTABLE,
PX_PROCESS_PRIVATE_EXE_READONLY,
PX_PROCESS_PRIVATE_EXE_READWRITE,
PX_PROCESS_PRIVATE_EXE_WRITECOPY);

PaintAddressSpace (hMemDlg, pInst, pObj,
MEMORY_TOTALMAPPED_COMMIT,
MEMORY_MAPPED_NOACCESS, PX_PROCESS_MAPPED_NOACCESS,
MEMORY_MAPPED_READONLY, PX_PROCESS_MAPPED_READONLY,
MEMORY_MAPPED_READWRITE, PX_PROCESS_MAPPED_READWRITE,
MEMORY_MAPPED_WRITECOPY, PX_PROCESS_MAPPED_WRITECOPY,
MEMORY_MAPPED_EXECUTE, PX_PROCESS_MAPPED_EXECUTABLE,
PX_PROCESS_MAPPED_EXE_READONLY,
PX_PROCESS_MAPPED_EXE_READWRITE,
PX_PROCESS_MAPPED_EXE_WRITECOPY);

PaintAddressSpace (hMemDlg, pInst, pObj,
MEMORY_TOTALIMAGE_COMMIT,
MEMORY_IMAGE_NOACCESS, PX_PROCESS_IMAGE_NOACCESS,
MEMORY_IMAGE_READONLY, PX_PROCESS_IMAGE_READONLY,
MEMORY_IMAGE_READWRITE, PX_PROCESS_IMAGE_READWRITE,
MEMORY_IMAGE_WRITECOPY, PX_PROCESS_IMAGE_WRITECOPY,
MEMORY_IMAGE_EXECUTE, PX_PROCESS_IMAGE_EXECUTABLE,
PX_PROCESS_IMAGE_EXE_READONLY,
PX_PROCESS_IMAGE_EXE_READWRITE,
PX_PROCESS_IMAGE_EXE_WRITECOPY);
}




//*********************************************************************
//
// PaintMemDlgVMData
//
// Paint the memory dialog Virtual Memory data.
//
void PaintMemDlgVMData (HWND hMemDlg,
PPERF_INSTANCE pInst,
PPERF_OBJECT pObj)
{

PutCounterDWKB (hMemDlg, MEMORY_WS, pInst, pObj, PX_PROCESS_WORKING_SET);
PutCounterDWKB (hMemDlg, MEMORY_PEAK_WS, pInst, pObj, PX_PROCESS_PEAK_WS);
PutCounterDWKB (hMemDlg, MEMORY_PRIVATE_PAGE, pInst, pObj, PX_PROCESS_PRIVATE_PAGE);
PutCounterDWKB (hMemDlg, MEMORY_VSIZE, pInst, pObj, PX_PROCESS_VIRTUAL_SIZE);
PutCounterDWKB (hMemDlg, MEMORY_PEAK_VSIZE, pInst, pObj, PX_PROCESS_PEAK_VS);
PutCounterDWKB (hMemDlg, MEMORY_PFCOUNT, pInst, pObj, PX_PROCESS_FAULT_COUNT);

}




//*********************************************************************
//
// PaintPviewDlgMemoryData
//
// Paint the memory data for pview dialog.
//
void PaintPviewDlgMemoryData (HWND hPviewDlg,
PPERF_INSTANCE pInst,
PPERF_OBJECT pObj)
{
PPERF_COUNTER pCounter;
TCHAR str[20];
DWORD *pdwData;
DWORD dwData = 0;
BOOL bCounter = FALSE;


if (pCounter = FindCounter (pObj, PX_PROCESS_PRIVATE_NOACCESS))
{
pdwData = (DWORD *) CounterData (pInst, pCounter);
dwData += *pdwData;
bCounter = TRUE;
}

if (pCounter = FindCounter (pObj, PX_PROCESS_PRIVATE_READONLY))
{
pdwData = (DWORD *) CounterData (pInst, pCounter);
dwData += *pdwData;
bCounter = TRUE;
}

if (pCounter = FindCounter (pObj, PX_PROCESS_PRIVATE_READWRITE))
{
pdwData = (DWORD *) CounterData (pInst, pCounter);
dwData += *pdwData;
bCounter = TRUE;
}

if (pCounter = FindCounter (pObj, PX_PROCESS_PRIVATE_WRITECOPY))
{
pdwData = (DWORD *) CounterData (pInst, pCounter);
dwData += *pdwData;
bCounter = TRUE;
}

if (pCounter = FindCounter (pObj, PX_PROCESS_PRIVATE_EXECUTABLE))
{
pdwData = (DWORD *) CounterData (pInst, pCounter);
dwData += *pdwData;
bCounter = TRUE;
}

if (pCounter = FindCounter (pObj, PX_PROCESS_PRIVATE_EXE_READONLY))
{
pdwData = (DWORD *) CounterData (pInst, pCounter);
dwData += *pdwData;
bCounter = TRUE;
}

if (pCounter = FindCounter (pObj, PX_PROCESS_PRIVATE_EXE_READWRITE))
{
pdwData = (DWORD *) CounterData (pInst, pCounter);
dwData += *pdwData;
bCounter = TRUE;
}

if (pCounter = FindCounter (pObj, PX_PROCESS_PRIVATE_EXE_WRITECOPY))
{
pdwData = (DWORD *) CounterData (pInst, pCounter);
dwData += *pdwData;
bCounter = TRUE;
}

if (bCounter)
{
wsprintf (str, TEXT("%ld KB"), dwData/1024);
SetDlgItemText (hPviewDlg, PVIEW_TOTALPRIVATE_COMMIT, str);
}
else
SetDlgItemText (hPviewDlg, PVIEW_TOTALPRIVATE_COMMIT, NODATA);

}




//*********************************************************************
//
// RefreshMemoryDlg
//
// Refresh the memory detail dialog.
//
BOOL RefreshMemoryDlg (HWND hMemDlg,
PPERF_INSTANCE pProcessInstance,
PPERF_OBJECT pProcessObject,
PPERF_OBJECT pAddressObject,
PPERF_OBJECT pImageObject)
{
DWORD *pProcessID1;
DWORD *pProcessID2;
PPERF_COUNTER pCounter1;
PPERF_COUNTER pCounter2;
PPERF_INSTANCE pAddressInstance;
HWND hImageList;
TCHAR szTemp[40];
BOOL bStat = FALSE;
INT InstIndex = 0;


if ((pCounter1 = FindCounter (pProcessObject, PX_PROCESS_ID)) &&
(pCounter2 = FindCounter (pAddressObject, PX_PROCESS_ID)))
{
pProcessID1 = (DWORD *) CounterData (pProcessInstance, pCounter1);

wsprintf (szTemp, TEXT("%s (%#x)"), InstanceName (pProcessInstance), *pProcessID1);
SetDlgItemText (hMemDlg, MEMORY_PROCESS_ID, szTemp);

pAddressInstance = FirstInstance (pAddressObject);

while (pAddressInstance && InstIndex < pAddressObject->NumInstances)
{
pProcessID2 = (DWORD *) CounterData (pAddressInstance, pCounter2);

if (*pProcessID1 == *pProcessID2)
{
PaintMemDlgAddrData (hMemDlg, pAddressInstance, pAddressObject);
PaintMemDlgVMData (hMemDlg, pProcessInstance, pProcessObject);

hImageList = GetDlgItem (hMemDlg, MEMORY_IMAGE);
RefreshMemoryDlgImageList (hImageList, InstIndex, pImageObject);

bStat = TRUE;
break;
}

pAddressInstance = NextInstance (pAddressInstance);
InstIndex++;
}
}

return bStat;

}




//*********************************************************************
//
// RefreshMemoryDlgImageList
//
// Refresh the image list for memory dialog.
//
void RefreshMemoryDlgImageList (HWND hImageList,
DWORD ParentIndex,
PPERF_OBJECT pImageObj)
{
PPERF_INSTANCE pImageInst;
INT ListIndex;
INT InstIndex = 0;


ListIndex = SendMessage (hImageList, CB_ADDSTRING, 0, (DWORD)TEXT(" Total Commit"));
SendMessage (hImageList, CB_SETITEMDATA, ListIndex, 0xFFFFFFFF);

if (pImageObj)
{
pImageInst = FirstInstance (pImageObj);

while (pImageInst && InstIndex < pImageObj->NumInstances)
{
if (ParentIndex == pImageInst->ParentObjectInstance)
{
ListIndex = SendMessage (hImageList,
CB_ADDSTRING,
0,
(DWORD)InstanceName(pImageInst));
SendMessage (hImageList, CB_SETITEMDATA, ListIndex, InstIndex);
}

pImageInst = NextInstance (pImageInst);
InstIndex++;
}
}
}




//*********************************************************************
//
// RefreshMemoryDlgImage
//
//
void RefreshMemoryDlgImage (HWND hMemDlg,
DWORD dwIndex,
PPERF_OBJECT pImageObject)
{
PPERF_INSTANCE pInst;

if (pInst = FindInstanceN (pImageObject, dwIndex))
PaintAddressSpace (hMemDlg, pInst, pImageObject,
MEMORY_TOTALIMAGE_COMMIT,
MEMORY_IMAGE_NOACCESS, PX_IMAGE_NOACCESS,
MEMORY_IMAGE_READONLY, PX_IMAGE_READONLY,
MEMORY_IMAGE_READWRITE, PX_IMAGE_READWRITE,
MEMORY_IMAGE_WRITECOPY, PX_IMAGE_WRITECOPY,
MEMORY_IMAGE_EXECUTE, PX_IMAGE_EXECUTABLE,
PX_IMAGE_EXE_READONLY,
PX_IMAGE_EXE_READWRITE,
PX_IMAGE_EXE_WRITECOPY);
}


//*********************************************************************
//
// RefreshPviewDlgMemoryData
//
// Update the memory data for pview dialog. This should be done
// after the ghCostlyData is collected and is not refreshing.
//
void RefreshPviewDlgMemoryData (HWND hPviewDlg,
PPERF_INSTANCE pProcessInstance,
PPERF_OBJECT pProcessObject,
PPERF_OBJECT pAddressObject)
{
DWORD *pProcessID1;
DWORD *pProcessID2;
PPERF_COUNTER pCounter1;
PPERF_COUNTER pCounter2;
PPERF_INSTANCE pAddressInstance;
INT i = 0;


if ((pCounter1 = FindCounter (pProcessObject, PX_PROCESS_ID)) &&
(pCounter2 = FindCounter (pAddressObject, PX_PROCESS_ID)))
{
pProcessID1 = (DWORD *) CounterData (pProcessInstance, pCounter1);

pAddressInstance = FirstInstance (pAddressObject);

while (pAddressInstance && i < pAddressObject->NumInstances)
{
pProcessID2 = (DWORD *) CounterData (pAddressInstance, pCounter2);

if (*pProcessID1 == *pProcessID2)
{
PaintPviewDlgMemoryData (hPviewDlg, pAddressInstance, pAddressObject);
break;
}

pAddressInstance = NextInstance (pAddressInstance);
i++;
}
}
}




//*********************************************************************
//
// RefreshPviewDlgThreadPC
//
// Update the thread PC value. This should be done after the ghCostlyData
// is collected and is no refreshing.
//
void RefreshPviewDlgThreadPC (HWND hPviewDlg,
LPTSTR szProcessName,
LPTSTR szThreadName,
PPERF_OBJECT pThreadDetailsObject,
PPERF_DATA pCostlyData)
{
PPERF_COUNTER pCounter;
PPERF_INSTANCE pInstance;
PPERF_INSTANCE pParent;
LPTSTR szInstanceName;
LPTSTR szParentName;
TCHAR str[20];
DWORD *pdwData;
INT i = 0;


if (pCounter = FindCounter (pThreadDetailsObject, PX_THREAD_PC))
{
pInstance = FirstInstance (pThreadDetailsObject);

while (pInstance && i < pThreadDetailsObject->NumInstances)
{
if (!(szInstanceName = InstanceName (pInstance)))
// can't find name
;
else if (lstrcmp (szThreadName, szInstanceName))
// the thread name is different
;
else if (!(pParent = FindInstanceParent (pInstance, pCostlyData)))
// can't find parent
;
else if (!(szParentName = InstanceName (pParent)))
// can't find parent's name
;
else if (!lstrcmp (szProcessName, szParentName))
{
// Parent's name matches, this is the right one.
//

pdwData = CounterData (pInstance, pCounter);
wsprintf (str, TEXT("0x%08x"), *pdwData);
SetDlgItemText (hPviewDlg, PVIEW_THREAD_PC, str);

return;
}

pInstance = NextInstance (pInstance);
i++;
}
}


// We are here only because we can't find the data to display.
//

SetDlgItemText (hPviewDlg, PVIEW_THREAD_PC, NODATA);

}




//*********************************************************************
//
// ProcessPriority
//
// Returns the process priority dialog item id.
//
WORD ProcessPriority (PPERF_OBJECT pObject,
PPERF_INSTANCE pInstance)
{
PPERF_COUNTER pCounter;
DWORD *pdwData;


if (pCounter = FindCounter (pObject, PX_PROCESS_PRIO))
{
pdwData = (DWORD *) CounterData (pInstance, pCounter);

if (*pdwData < 7)
return PVIEW_PRIORITY_IDL;
else if (*pdwData < 10)
return PVIEW_PRIORITY_NORMAL;
else
return PVIEW_PRIORITY_HIGH;
}
else
return PVIEW_PRIORITY_NORMAL;

}




//*********************************************************************
//
// RefreshPerfData
//
// Get a new set of performance data. pData should be NULL initially.
//
PPERF_DATA RefreshPerfData (HKEY hPerfKey,
LPTSTR szObjectIndex,
PPERF_DATA pData,
DWORD *pDataSize)
{
if (GetPerfData (hPerfKey, szObjectIndex, &pData, pDataSize) == ERROR_SUCCESS)
return pData;
else
return NULL;
}




//*********************************************************************
//
// SetProcessListText
//
// Format the process list text.
//
void SetProcessListText (PPERF_INSTANCE pInst,
PPERF_COUNTER pCPU,
PPERF_COUNTER pPRIV,
PPERF_COUNTER pProcID,
double fTime,
LPTSTR str)
{
DWORD *pdwProcID;
LARGE_INTEGER *liCPU;
LARGE_INTEGER *liPRIV;
double fCPU = 0;
double fPRIV = 0;
INT PcntPRIV = 0;
INT PcntUSER = 0;
TIME_FIELD TimeFld;
TCHAR szTemp[100];


if (pCPU)
{
liCPU = (LARGE_INTEGER *) CounterData (pInst, pCPU);
fCPU = Li2Double (*liCPU);
}

if (pPRIV)
{
liPRIV = (LARGE_INTEGER *) CounterData (pInst, pPRIV);
fPRIV = Li2Double (*liPRIV);
}

if (fCPU > 0)
{
PcntPRIV = (INT)(fPRIV / fCPU * 100 + 0.5);
PcntUSER = 100 - PcntPRIV;
}



if (pProcID)
{
pdwProcID = (DWORD *) CounterData (pInst, pProcID);
wsprintf (szTemp, TEXT("%ls (%#x)"), InstanceName(pInst), *pdwProcID);
}
else
wsprintf (szTemp, TEXT("%ls"), InstanceName(pInst));



FormatTimeFields (fCPU/1.0e7, &TimeFld);

wsprintf (str,
TEXT("%s\t%3ld:%02ld:%02ld.%03ld\t%3ld%%\t%3ld%%"),
szTemp,
TimeFld.Hours,
TimeFld.Mins,
TimeFld.Secs,
TimeFld.mSecs,
PcntPRIV,
PcntUSER);
}




//*********************************************************************
//
// RefreshProcessList
//
// Find all process and update the process list.
//
void RefreshProcessList (HWND hProcessList,
PPERF_OBJECT pObject)
{
PPERF_INSTANCE pInstance;
TCHAR szListText[256];
INT ListIndex;

PPERF_COUNTER pCounterCPU;
PPERF_COUNTER pCounterPRIV;
PPERF_COUNTER pCounterProcID;
double fObjectFreq;
double fObjectTime;
double fTime;

INT InstanceIndex = 0;
INT err;


if (pObject)
{
if ((pCounterCPU = FindCounter (pObject, PX_PROCESS_CPU)) &&
(pCounterPRIV = FindCounter (pObject, PX_PROCESS_PRIV)) &&
(pCounterProcID = FindCounter (pObject, PX_PROCESS_ID)))
{

fObjectFreq = Li2Double (pObject->PerfFreq);
fObjectTime = Li2Double (pObject->PerfTime);
fTime = fObjectTime / fObjectFreq;

pInstance = FirstInstance (pObject);

while (pInstance && InstanceIndex < pObject->NumInstances)
{
SetProcessListText (pInstance,
pCounterCPU,
pCounterPRIV,
pCounterProcID,
fTime,
szListText);

ListIndex = SendMessage (hProcessList, LB_ADDSTRING, 0, (DWORD)szListText);
err = SendMessage (hProcessList, LB_SETITEMDATA, ListIndex, InstanceIndex);

pInstance = NextInstance (pInstance);
InstanceIndex++;
}
}
}
}




//*********************************************************************
//
// RefreshProcessData
//
// Find data for a given process and update.
//
void RefreshProcessData (HWND hWnd,
PPERF_OBJECT pObject,
DWORD ProcessIndex)
{
PPERF_INSTANCE pInstance;


if (pInstance = FindInstanceN (pObject, ProcessIndex))

{ 
PutCounterDWKB (hWnd, PVIEW_WS, pInstance, pObject, PX_PROCESS_WORKING_SET);


SetDlgItemText (hWnd, PVIEW_TOTALPRIVATE_COMMIT, NODATA);

// set priority
//
CheckRadioButton (hWnd,
PVIEW_PRIORITY_HIGH,
PVIEW_PRIORITY_IDL,
ProcessPriority (pObject, pInstance));
}
}




//*********************************************************************
//
// SetThreadListText
//
// Format the thread list text.
//
void SetThreadListText (PPERF_INSTANCE pInst,
PPERF_COUNTER pCPU,
PPERF_COUNTER pPRIV,
double fTime,
LPTSTR str)
{
LARGE_INTEGER *liCPU;
LARGE_INTEGER *liPRIV;
double fCPU = 0;
double fPRIV = 0;
INT PcntPRIV = 0;
INT PcntUSER = 0;
TIME_FIELD TimeFld;
TCHAR szTemp[100];


if (pCPU)
{
liCPU = (LARGE_INTEGER *) CounterData (pInst, pCPU);
fCPU = Li2Double (*liCPU);
}

if (pPRIV)
{
liPRIV = (LARGE_INTEGER *) CounterData (pInst, pPRIV);
fPRIV = Li2Double (*liPRIV);
}

if (fCPU > 0)
{
PcntPRIV = (INT)(fPRIV / fCPU * 100 + 0.5);
PcntUSER = 100 - PcntPRIV;
}



if (pInst->UniqueID != PERF_NO_UNIQUE_ID)
wsprintf (szTemp, TEXT("%ls (%#x)"), InstanceName(pInst), pInst->UniqueID);
else
wsprintf (szTemp, TEXT("%ls"), InstanceName(pInst));




FormatTimeFields (fCPU/1.0e7, &TimeFld);

wsprintf (str,
TEXT("%s\t%3ld:%02ld:%02ld.%03ld\t%3ld%%\t%3ld %%"),
szTemp,
TimeFld.Hours,
TimeFld.Mins,
TimeFld.Secs,
TimeFld.mSecs,
PcntPRIV,
PcntUSER);

}




//*********************************************************************
//
// RefreshThreadList
//
// Find all threads for a given process and update the thread list.
//
void RefreshThreadList (HWND hThreadList,
PPERF_OBJECT pObject,
DWORD ParentIndex)
{
PPERF_INSTANCE pInstance;
TCHAR szListText[256];
INT ListIndex;

PPERF_COUNTER pCounterCPU;
PPERF_COUNTER pCounterPRIV;
double fObjectFreq;
double fObjectTime;
double fTime;

INT InstanceIndex = 0;
INT err;


if (pObject)
{
if ((pCounterCPU = FindCounter (pObject, PX_THREAD_CPU)) &&
(pCounterPRIV = FindCounter (pObject, PX_THREAD_PRIV)))
{

fObjectFreq = Li2Double (pObject->PerfFreq);
fObjectTime = Li2Double (pObject->PerfTime);
fTime = fObjectTime / fObjectFreq;


pInstance = FirstInstance (pObject);

while (pInstance && InstanceIndex < pObject->NumInstances)
{
if (ParentIndex == pInstance->ParentObjectInstance)
{
SetThreadListText (pInstance,
pCounterCPU,
pCounterPRIV,
fTime,
szListText);

ListIndex = SendMessage (hThreadList,
LB_INSERTSTRING,
(WPARAM)-1,
(DWORD)szListText);
err = SendMessage (hThreadList, LB_SETITEMDATA, ListIndex, InstanceIndex);
}

pInstance = NextInstance (pInstance);
InstanceIndex++;
}
}
}

}




//*********************************************************************
//
// RefreshThreadData
//
// Find data for a given thread and update.
//
void RefreshThreadData (HWND hWnd,
PPERF_OBJECT pThreadObj,
DWORD ThreadIndex,
PPERF_OBJECT pProcessObj,
PPERF_INSTANCE pProcessInst)
{
PPERF_INSTANCE pInstance;
PPERF_COUNTER pCounter;
DWORD *pdwData;
DWORD *pdwProcPrio;
BOOL bPrioCounter = TRUE;



if (pInstance = FindInstanceN (pThreadObj, ThreadIndex))
{
SetDlgItemText (hWnd, PVIEW_THREAD_PC, NODATA);

PutCounterHEX (hWnd, PVIEW_THREAD_START, pInstance, pThreadObj, PX_THREAD_START);
PutCounterDW (hWnd, PVIEW_THREAD_SWITCHES, pInstance, pThreadObj, PX_THREAD_SWITCHES);
PutCounterDW (hWnd, PVIEW_THREAD_DYNAMIC, pInstance, pThreadObj, PX_THREAD_PRIO);
}




if (pInstance)
{
// get thread base priority
//

if (pCounter = FindCounter (pThreadObj, PX_THREAD_BASE_PRIO))
pdwData = CounterData (pInstance, pCounter);
else
bPrioCounter = FALSE;


// get process priority
//

if (pCounter = FindCounter (pProcessObj, PX_PROCESS_PRIO))
pdwProcPrio = CounterData (pProcessInst, pCounter);
else
bPrioCounter = FALSE;
}
else
bPrioCounter = FALSE;





// set thread base priority
//

if (!bPrioCounter)
CheckRadioButton (hWnd,
PVIEW_THREAD_HIGHEST,
PVIEW_THREAD_LOWEST,
PVIEW_THREAD_NORMAL);
else
{
switch (*pdwData - *pdwProcPrio)
{
case 2:
CheckRadioButton (hWnd,
PVIEW_THREAD_HIGHEST,
PVIEW_THREAD_LOWEST,
PVIEW_THREAD_HIGHEST);
break;

case 1:
CheckRadioButton (hWnd,
PVIEW_THREAD_HIGHEST,
PVIEW_THREAD_LOWEST,
PVIEW_THREAD_ABOVE);
break;

case -1:
CheckRadioButton (hWnd,
PVIEW_THREAD_HIGHEST,
PVIEW_THREAD_LOWEST,
PVIEW_THREAD_BELOW);
break;

case -2:
CheckRadioButton (hWnd,
PVIEW_THREAD_HIGHEST,
PVIEW_THREAD_LOWEST,
PVIEW_THREAD_LOWEST);
break;

case 0:
default:
CheckRadioButton (hWnd,
PVIEW_THREAD_HIGHEST,
PVIEW_THREAD_LOWEST,
PVIEW_THREAD_NORMAL);
break;
}
}
}