windows-nt/Source/XPSP1/NT/sdktools/pviewer/pviewer.c

1413 lines
41 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/******************************************************************************
P R O C E S S V I E W E R
Name: pviewer.c
Description:
This program demonstrates the usage of special registry APIs
for collecting performance data.
C files used in this app:
pviewer.c - this file
pviewdat.c - updates the dialog
perfdata.c - gets performance data structures
objdata.c - access performance data objects
instdata.c - access performance data instances
cntrdata.c - access performance data counters
******************************************************************************/
#include <windows.h>
#include <winperf.h>
#include "perfdata.h"
#include "pviewdat.h"
#include "pviewdlg.h"
#include <string.h>
#include <stdio.h>
#define INDEX_STR_LEN 10
#define MACHINE_NAME_LEN MAX_COMPUTERNAME_LENGTH+2
#define MACHINE_NAME_SIZE MACHINE_NAME_LEN+1
/****
Globals
****/
TCHAR INDEX_PROCTHRD_OBJ[2*INDEX_STR_LEN];
TCHAR INDEX_COSTLY_OBJ[3*INDEX_STR_LEN];
TCHAR gszMachineName[MACHINE_NAME_SIZE];
TCHAR gszCurrentMachine[MACHINE_NAME_SIZE];
DWORD gPerfDataSize = 50*1024; // start with 50K
PPERF_DATA gpPerfData;
DWORD gCostlyDataSize = 100*1024; // start wiih 100K
PPERF_DATA gpCostlyData;
PPERF_OBJECT gpProcessObject; // pointer to process objects
PPERF_OBJECT gpThreadObject; // pointer to thread objects
PPERF_OBJECT gpThreadDetailsObject; // pointer to thread detail objects
PPERF_OBJECT gpAddressSpaceObject; // pointer to address space objects
PPERF_OBJECT gpImageObject; // pointer to image objects
HKEY ghPerfKey = HKEY_PERFORMANCE_DATA; // get perf data from this key
HKEY ghMachineKey = HKEY_LOCAL_MACHINE; // get title index from this key
HCURSOR ghCursor[2]; // 0 = arrow, 1 = hourglass
HANDLE ghMemUpdateEvent; // to signal a refresh of mem stats
HANDLE ghMemUpdateMutex; // to restrict overlapping refreshes
HINSTANCE ghInstance; // handle for pviewer app
/****
Prototypes
****/
INT_PTR CALLBACK PviewDlgProc (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
void PviewDlgRefresh (HWND hWnd);
void PviewDlgRefreshCostlyData (HWND hPviewDlg);
void PviewDlgRefreshProcess (HWND hWnd);
void PviewDlgRefreshThread (HWND hWnd);
void PviewDlgRefreshCurSelProcess (HWND hWnd);
void PviewDlgRefreshCurSelThread (HWND hWnd);
WORD PviewDlgGetCurSelPriority (HWND hWnd);
BOOL PviewDlgChangePriority (HWND hWnd, WPARAM wParam, WORD wItem);
BOOL PviewDlgTerminateProcess (HWND hPviewDlg);
INT_PTR CALLBACK MemDlgProc (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
void MemDlgUpdateThread (HWND hWnd);
void MemDlgRefresh (HWND hWnd, HWND hPviewDlg);
void MemDlgRefreshCurSelImage (HWND hMemDlg, HWND hPviewDlg);
INT GetCurSelText (HWND hList, LPTSTR str);
DWORD GetCurSelData (HWND hWnd, DWORD dwList);
INT ReSelectText (HWND hList, INT StartIndex, LPTSTR str);
void SetPerfIndexes (HWND hWnd);
DWORD GetTitleIdx (HWND hWnd, LPTSTR TitleSz[], DWORD LastIndex, LPTSTR Name);
void SetListBoxTabStops (HWND hWnd);
void SetLocalMachine (void);
BOOL ConnectComputer (HWND hWnd);
void DisableControls (HWND hPviewDlg);
void EnableControls (HWND hPviewDlg);
//********************************************************
//
// WinMain --
//
// Build Up: create the program's dialog box,
// load the desired icons, enter the message
// loop.
//
// Tear Down: free up the memory allocated by the
// dialog box proc, and exit.
//
int WINAPI WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HANDLE hWndDialog;
MSG msg;
ghInstance = hInstance;
// load our default cursors
//
ghCursor[0] = LoadCursor (0, IDC_ARROW);
ghCursor[1] = LoadCursor (0, IDC_WAIT);
// open our dialog box
//
hWndDialog = CreateDialogParam (hInstance,
MAKEINTRESOURCE (PVIEW_DLG),
NULL,
PviewDlgProc,
0);
// the almighty Windows message loop:
//
while (GetMessage (&msg, NULL, 0, 0))
if (!IsDialogMessage (hWndDialog, &msg)) {
TranslateMessage (&msg);
DispatchMessage (&msg);
}
// close up shop
//
DestroyWindow (hWndDialog);
LocalFree (gpPerfData);
return 0;
}
/*****************
PviewDlg functions
*****************/
//********************************************************
//
// PviewDlgProc --
//
// Pview dialog procedure
//
INT_PTR CALLBACK PviewDlgProc (HWND hWnd,
UINT wMsg,
WPARAM wParam,
LPARAM lParam)
{
WORD wItem;
MSG Msg;
switch (wMsg) {
case WM_INITDIALOG:
SetClassLongPtr (hWnd, GCLP_HICON, (LONG_PTR)LoadIcon(ghInstance, TEXT("VIEWPICON")) );
SetListBoxTabStops (hWnd);
SendDlgItemMessage (hWnd, PVIEW_COMPUTER, EM_LIMITTEXT, MACHINE_NAME_LEN, 0);
PostMessage (hWnd, WM_COMMAND, PVIEW_REFRESH, 0);
break;
case WM_CLOSE:
PostQuitMessage (0);
break;
case WM_COMMAND:
//
// handle our app-specific controls:
//
switch (LOWORD (wParam)) {
// works just like "close"
//
case PVIEW_EXIT:
PostQuitMessage (0);
break;
// if somebody moved the highlight in the thread list,
// update the view
//
case PVIEW_THREAD_LIST:
if (HIWORD(wParam) == LBN_DBLCLK || HIWORD(wParam) == LBN_SELCHANGE) {
PviewDlgRefreshCurSelThread (hWnd);
PostMessage (hWnd, WM_COMMAND, PVIEW_REFRESH_COSTLY_DATA, 0);
}
break;
// if somebody clicked on a new process, update all of the
// affected information.
//
case PVIEW_PROCESS_LIST:
if (HIWORD(wParam) == CBN_DBLCLK || HIWORD(wParam) == CBN_SELCHANGE) {
PviewDlgRefreshCurSelProcess (hWnd);
PostMessage (hWnd, WM_COMMAND, PVIEW_REFRESH_COSTLY_DATA, 0);
if (HIWORD(wParam) == CBN_DBLCLK)
PostMessage (hWnd, WM_COMMAND, PVIEW_MEMORY_DETAIL, 0);
}
break;
// the user wishes to view the memory stats in detail:
//
case PVIEW_MEMORY_DETAIL:
//
// check to see if we can get exclusive access
// to the memory statistics
//
if (WaitForSingleObject (ghMemUpdateMutex, 0))
// we can't, so just return.
//
return FALSE;
else {
// we have exclusive access, so start up the
// memory statistics dialog.
//
// release the mutex first so the dialog can use it.
//
ReleaseMutex (ghMemUpdateMutex);
DialogBoxParam (NULL,
MAKEINTRESOURCE (MEMORY_DLG),
hWnd,
MemDlgProc,
(LPARAM)hWnd);
}
break;
// somebody clicked one of the priority radio
// buttons. Find out which one was selected...
//
case PVIEW_PRIORITY_HIGH:
case PVIEW_PRIORITY_NORMAL:
case PVIEW_PRIORITY_IDL:
if (SendDlgItemMessage (hWnd, PVIEW_PRIORITY_HIGH, BM_GETCHECK, 0, 0))
wItem = PVIEW_PRIORITY_HIGH;
else if (SendDlgItemMessage (hWnd, PVIEW_PRIORITY_NORMAL, BM_GETCHECK, 0, 0))
wItem = PVIEW_PRIORITY_NORMAL;
else
wItem = PVIEW_PRIORITY_IDL;
// if the user actually clicked on a NEW state,
// do the change.
//
if (LOWORD(wParam) != wItem) {
// of course, if it's a remote machine, disallow
// the modification.
//
if (lstrcmp (gszCurrentMachine, gszMachineName)) {
SendDlgItemMessage (hWnd, wItem, BM_SETCHECK, 1, 0);
SetFocus (GetDlgItem (hWnd, wItem));
MessageBox (hWnd,
TEXT("Cannot change process priority on remote machine"),
TEXT("Set priority"),
MB_ICONEXCLAMATION|MB_OK);
}
// at this point, we know we are affecting the local
// machine, and a change has to be made.
// Just Do It(TM).
//
else if (PviewDlgChangePriority (hWnd, wParam, wItem))
PviewDlgRefresh (hWnd);
}
break;
case PVIEW_THREAD_HIGHEST:
case PVIEW_THREAD_ABOVE:
case PVIEW_THREAD_NORMAL:
case PVIEW_THREAD_BELOW:
case PVIEW_THREAD_LOWEST:
//
// this selection hasn't been fleshed out yet.
//
PviewDlgRefreshCurSelThread (hWnd);
break;
// terminate the selected process
//
case PVIEW_TERMINATE:
if (PviewDlgTerminateProcess (hWnd))
PviewDlgRefresh (hWnd);
break;
// if the text has changed, we want to connect and
// view another system's processes...
//
case PVIEW_COMPUTER:
if (HIWORD(wParam) == EN_CHANGE)
EnableWindow (GetDlgItem (hWnd, PVIEW_CONNECT), TRUE);
else
return FALSE;
break;
// we were told to connect, go ahead and try...
//
case PVIEW_CONNECT:
if (ConnectComputer (hWnd)) {
SetPerfIndexes (hWnd);
PviewDlgRefresh (hWnd);
}
break;
// refresh the current information displayed
//
case PVIEW_REFRESH:
if (ConnectComputer (hWnd))
SetPerfIndexes (hWnd);
PviewDlgRefresh (hWnd);
break;
// refresh the currently updated costly
// statistics
//
case PVIEW_REFRESH_COSTLY_DATA:
if (WaitForSingleObject (ghMemUpdateMutex, 0))
return FALSE;
PviewDlgRefreshCostlyData (hWnd);
ReleaseMutex (ghMemUpdateMutex);
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//********************************************************
//
// PviewDlgRefresh --
//
// Refresh the pview dialog.
//
void PviewDlgRefresh (HWND hWnd)
{
static HANDLE hMemUpdateThread = NULL;
static DWORD MemUpdateThreadID;
MSG Msg;
SetCursor (ghCursor[1]);
if (hMemUpdateThread) // get memory data
SetEvent (ghMemUpdateEvent);
else
hMemUpdateThread = CreateThread (NULL,
0,
(LPTHREAD_START_ROUTINE)MemDlgUpdateThread,
(LPVOID)hWnd,
0,
&MemUpdateThreadID);
// get performance data
//
gpPerfData = RefreshPerfData (ghPerfKey, INDEX_PROCTHRD_OBJ, gpPerfData, &gPerfDataSize);
gpProcessObject = FindObject (gpPerfData, PX_PROCESS);
gpThreadObject = FindObject (gpPerfData, PX_THREAD);
// refresh
//
PviewDlgRefreshProcess (hWnd);
PviewDlgRefreshThread (hWnd);
// Remove all mouse and key messages. They are not accepted
// while the cursor is a hourglass.
//
while (PeekMessage (&Msg, hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE));
while (PeekMessage (&Msg, hWnd, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE));
SetCursor (ghCursor[0]);
}
//********************************************************
//
// PviewDlgRefreshCostlyData --
//
// Refresh the costly data.
//
void PviewDlgRefreshCostlyData (HWND hPviewDlg)
{
LPTSTR szProcessName;
LPTSTR szThreadName;
PPERF_INSTANCE pInstance;
DWORD dwIndex;
dwIndex = GetCurSelData (hPviewDlg, PVIEW_PROCESS_LIST);
pInstance = FindInstanceN (gpProcessObject, dwIndex);
szProcessName = InstanceName (pInstance);
RefreshPviewDlgMemoryData (hPviewDlg,
pInstance,
gpProcessObject,
gpAddressSpaceObject);
dwIndex = GetCurSelData (hPviewDlg, PVIEW_THREAD_LIST);
pInstance = FindInstanceN (gpThreadObject, dwIndex);
szThreadName = InstanceName (pInstance);
RefreshPviewDlgThreadPC (hPviewDlg,
szProcessName,
szThreadName ? szThreadName : TEXT("UNKNOWN"),
gpThreadDetailsObject,
gpCostlyData);
}
//********************************************************
//
// PviewDlgRefreshProcess --
//
// Refresh the process list and data in pview dialog.
//
void PviewDlgRefreshProcess (HWND hWnd)
{
TCHAR szProcessString[256];
INT nProcess;
INT nIndex;
HWND hProcessList;
DWORD dwProcessIndex;
// refresh process list
//
hProcessList = GetDlgItem (hWnd, PVIEW_PROCESS_LIST);
nProcess = GetCurSelText (hProcessList, szProcessString);
SendMessage (hProcessList, WM_SETREDRAW, FALSE, 0);
SendMessage (hProcessList, LB_RESETCONTENT, 0, 0);
SendMessage (hProcessList, LB_SETITEMDATA, 0, 0);
RefreshProcessList (hProcessList, gpProcessObject);
// refresh process data
//
if (nProcess != LB_ERR)
nIndex = ReSelectText (hProcessList, nProcess, szProcessString);
else
nIndex = 0;
dwProcessIndex = (DWORD)SendMessage (hProcessList, LB_GETITEMDATA, nIndex, 0);
RefreshProcessData (hWnd, gpProcessObject, dwProcessIndex);
SendMessage (hProcessList, WM_SETREDRAW, TRUE, 0);
}
//********************************************************
//
// PviewDlgRefreshThread --
//
// Refresh the thread list and data in pview dialog.
//
void PviewDlgRefreshThread (HWND hWnd)
{
TCHAR szThreadString[256];
INT nThread;
INT nIndex;
HWND hThreadList;
DWORD dwThreadIndex;
PPERF_INSTANCE pProcessInstance;
DWORD dwProcessIndex;
// get process info
//
dwProcessIndex = GetCurSelData (hWnd, PVIEW_PROCESS_LIST);
pProcessInstance = FindInstanceN (gpProcessObject, dwProcessIndex);
// refresh thread list
//
hThreadList = GetDlgItem (hWnd, PVIEW_THREAD_LIST);
nThread = GetCurSelText (hThreadList, szThreadString);
SendMessage (hThreadList, WM_SETREDRAW, FALSE, 0);
SendMessage (hThreadList, LB_RESETCONTENT, 0, 0);
SendMessage (hThreadList, LB_SETITEMDATA, 0, 0);
RefreshThreadList (hThreadList, gpThreadObject, dwProcessIndex);
// refresh thread data
//
if (nThread != LB_ERR)
nIndex = ReSelectText (hThreadList, nThread, szThreadString);
else
nIndex = 0;
dwThreadIndex = (DWORD)SendMessage (hThreadList, LB_GETITEMDATA, nIndex, 0);
RefreshThreadData (hWnd,
gpThreadObject,
dwThreadIndex,
gpProcessObject,
pProcessInstance);
SendMessage (hThreadList, WM_SETREDRAW, TRUE, 0);
}
//********************************************************
//
// PviewDlgGetCurSelPriority --
//
// Get the process priority of currently selected process.
//
WORD PviewDlgGetCurSelPriority (HWND hWnd)
{
DWORD dwIndex;
PPERF_INSTANCE pInst;
dwIndex = GetCurSelData (hWnd, PVIEW_PROCESS_LIST);
pInst = FindInstanceN (gpProcessObject, dwIndex);
return ProcessPriority (gpProcessObject, pInst);
}
//********************************************************
//
// PviewDlgRefreshCurSelProcess --
//
// Refresh the data of currently selected process.
//
void PviewDlgRefreshCurSelProcess (HWND hWnd)
{
DWORD dwIndex;
dwIndex = GetCurSelData (hWnd, PVIEW_PROCESS_LIST);
RefreshProcessData (hWnd, gpProcessObject, dwIndex);
PviewDlgRefreshThread (hWnd);
}
//********************************************************
//
// PviewDlgRefreshCurSelThread --
//
// Refresh the data of currently selected thread.
//
void PviewDlgRefreshCurSelThread (HWND hWnd)
{
PPERF_INSTANCE pProcessInstance;
DWORD dwIndex;
dwIndex = GetCurSelData (hWnd, PVIEW_PROCESS_LIST);
pProcessInstance = FindInstanceN (gpProcessObject, dwIndex);
dwIndex = GetCurSelData (hWnd, PVIEW_THREAD_LIST);
RefreshThreadData (hWnd,
gpThreadObject,
dwIndex,
gpProcessObject,
pProcessInstance);
}
//********************************************************
//
// PviewDlgChangePriority --
//
// Change process priority.
//
BOOL PviewDlgChangePriority (HWND hWnd, WPARAM wParam, WORD wItem)
{
DWORD dwIndex;
PPERF_INSTANCE pInst;
PPERF_COUNTER pCountID;
DWORD *pProcessID;
DWORD ProcessID = 0;
HANDLE hProcess;
BOOL bStat;
dwIndex = GetCurSelData (hWnd, PVIEW_PROCESS_LIST);
pInst = FindInstanceN (gpProcessObject, dwIndex);
if (pCountID = FindCounter (gpProcessObject, PX_PROCESS_ID)) {
pProcessID = (DWORD *) CounterData (pInst, pCountID);
if (pProcessID) {
ProcessID = *pProcessID;
}
} else {
SendDlgItemMessage (hWnd, wItem, BM_SETCHECK, 1, 0);
SetFocus (GetDlgItem (hWnd, wItem));
MessageBox (hWnd,
TEXT("Cannot find ID for this process"),
TEXT("Set priority"),
MB_ICONEXCLAMATION|MB_OK);
return FALSE;
}
hProcess = OpenProcess (PROCESS_SET_INFORMATION, FALSE, ProcessID);
if (!hProcess) {
SendDlgItemMessage (hWnd, wItem, BM_SETCHECK, 1, 0);
SetFocus (GetDlgItem (hWnd, wItem));
MessageBox (hWnd,
TEXT("Unable to open the process; Priority not changed"),
TEXT("Set priority"),
MB_ICONEXCLAMATION|MB_OK);
return FALSE;
}
switch (wParam) {
case PVIEW_PRIORITY_HIGH:
bStat = SetPriorityClass (hProcess, HIGH_PRIORITY_CLASS);
break;
case PVIEW_PRIORITY_NORMAL:
bStat = SetPriorityClass (hProcess, NORMAL_PRIORITY_CLASS);
break;
case PVIEW_PRIORITY_IDL:
bStat = SetPriorityClass (hProcess, IDLE_PRIORITY_CLASS);
break;
default:
break;
}
CloseHandle (hProcess);
if (!bStat) {
SendDlgItemMessage (hWnd, wItem, BM_SETCHECK, 1, 0);
SetFocus (GetDlgItem (hWnd, wItem));
MessageBox (hWnd,
TEXT("Unable to change priority"),
TEXT("Set priority"),
MB_ICONEXCLAMATION|MB_OK);
return FALSE;
}
return TRUE;
}
//********************************************************
//
// PviewDlgTerminateProcess --
//
// Terminate the current selected process.
//
BOOL PviewDlgTerminateProcess (HWND hPviewDlg)
{
DWORD dwIndex;
PPERF_INSTANCE pInst;
PPERF_COUNTER pCountID;
DWORD *pProcessID;
DWORD ProcessID;
HANDLE hProcess;
TCHAR szTemp[50];
dwIndex = GetCurSelData (hPviewDlg, PVIEW_PROCESS_LIST);
pInst = FindInstanceN (gpProcessObject, dwIndex);
if (pCountID = FindCounter (gpProcessObject, PX_PROCESS_ID)) {
pProcessID = (DWORD *) CounterData (pInst, pCountID);
if (pProcessID) {
ProcessID = *pProcessID;
}
} else {
MessageBox (hPviewDlg,
TEXT("Cannot find ID for this process"),
TEXT("Terminate Process"),
MB_ICONEXCLAMATION|MB_OK);
return FALSE;
}
wsprintf (szTemp, TEXT("Terminate process %s (ID %#x)?"),
InstanceName (pInst), ProcessID);
if (MessageBox (hPviewDlg, szTemp, TEXT("Terminate Process"), MB_ICONSTOP|MB_OKCANCEL) != IDOK)
return FALSE;
hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, ProcessID);
if (!hProcess) {
MessageBox (hPviewDlg,
TEXT("Unable to open the process; Process not terminated"),
TEXT("Terminate Process"),
MB_ICONEXCLAMATION|MB_OK);
return FALSE;
}
if (!TerminateProcess (hProcess, 99)) {
MessageBox (hPviewDlg,
TEXT("Unable to terminate the process."),
TEXT("Terminate Process"),
MB_ICONEXCLAMATION|MB_OK);
CloseHandle (hProcess);
return FALSE;
}
CloseHandle (hProcess);
return TRUE;
}
/***************
MemDlg functions
***************/
//********************************************************
//
// MemDlgProc --
//
// MemoryDlg procedure
//
INT_PTR CALLBACK MemDlgProc (HWND hWnd,
UINT wMsg,
WPARAM wParam,
LPARAM lParam)
{
static HWND hPviewDlg;
switch (wMsg) {
case WM_INITDIALOG:
hPviewDlg = (HWND)lParam;
PostMessage (hWnd, WM_COMMAND, MEMORY_REFRESH, 0);
break;
case WM_QUIT:
case WM_CLOSE:
EndDialog (hWnd, TRUE);
break;
case WM_COMMAND:
switch (LOWORD (wParam)) {
// get the memory statistics for the currently selected
// process/thread
//
case MEMORY_IMAGE:
if (HIWORD(wParam) == CBN_DBLCLK || HIWORD(wParam) == CBN_SELCHANGE) {
if (WaitForSingleObject (ghMemUpdateMutex, 0))
return FALSE;
MemDlgRefreshCurSelImage (hWnd, hPviewDlg);
ReleaseMutex (ghMemUpdateMutex);
} else
return FALSE;
break;
// refresh the current memory statistics,
// retry if we can't get the mutex
//
case MEMORY_REFRESH:
if (WaitForSingleObject (ghMemUpdateMutex, 1000)) {
// can't get the mutex, retry...
//
PostMessage (hWnd, WM_COMMAND, MEMORY_REFRESH, 0);
return FALSE;
}
MemDlgRefresh (hWnd, hPviewDlg);
ReleaseMutex (ghMemUpdateMutex);
break;
case IDCANCEL:
case IDOK:
EndDialog (hWnd, TRUE);
break;
default:
return FALSE;
}
default:
return FALSE;
}
return TRUE;
}
//********************************************************
//
// MemDlgUpdateThread --
//
// This function runs in a separate thread to collect memory data.
//
void MemDlgUpdateThread (HWND hPviewDlg)
{
ghMemUpdateMutex = CreateMutex (NULL, TRUE, NULL);
ghMemUpdateEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
while (TRUE) {
EnableWindow (GetDlgItem (hPviewDlg, PVIEW_MEMORY_DETAIL), FALSE);
gpCostlyData = RefreshPerfData (ghPerfKey,
INDEX_COSTLY_OBJ,
gpCostlyData,
&gCostlyDataSize);
gpAddressSpaceObject = FindObject (gpCostlyData, PX_PROCESS_ADDRESS_SPACE);
gpThreadDetailsObject = FindObject (gpCostlyData, PX_THREAD_DETAILS);
gpImageObject = FindObject (gpCostlyData, PX_IMAGE);
EnableWindow (GetDlgItem (hPviewDlg, PVIEW_MEMORY_DETAIL), TRUE);
ReleaseMutex (ghMemUpdateMutex);
PostMessage (hPviewDlg, WM_COMMAND, PVIEW_REFRESH_COSTLY_DATA, 0);
WaitForSingleObject (ghMemUpdateEvent, INFINITE);
WaitForSingleObject (ghMemUpdateMutex, INFINITE);
}
}
//********************************************************
//
// MemDlgRefresh --
//
// Refresh the memory dialog.
//
void MemDlgRefresh (HWND hMemDlg, HWND hPviewDlg)
{
HWND hImageList;
DWORD dwIndex;
BOOL bStat;
PPERF_INSTANCE pInstance;
hImageList = GetDlgItem (hMemDlg, MEMORY_IMAGE);
SendMessage (hImageList, WM_SETREDRAW, FALSE, 0);
SendMessage (hImageList, CB_RESETCONTENT, 0, 0);
SendMessage (hImageList, CB_SETITEMDATA, 0, 0);
dwIndex = GetCurSelData (hPviewDlg, PVIEW_PROCESS_LIST);
pInstance = FindInstanceN (gpProcessObject, dwIndex);
bStat = RefreshMemoryDlg (hMemDlg,
pInstance,
gpProcessObject,
gpAddressSpaceObject,
gpImageObject);
SendMessage (hImageList, WM_SETREDRAW, TRUE, 0);
SendMessage (hImageList, CB_SETCURSEL, 0, 0);
if (!bStat) {
MessageBox (hMemDlg,
TEXT("Unable to retrieve memory detail"),
TEXT("Memory detail"),
MB_ICONSTOP|MB_OK);
PostMessage (hMemDlg, WM_CLOSE, 0, 0);
}
}
//********************************************************
//
// MemDlgRefreshCurSelImage --
//
// Refresh the current selected image for memory dialog.
//
void MemDlgRefreshCurSelImage (HWND hMemDlg, HWND hPviewDlg)
{
HWND hList;
INT nIndex;
DWORD dwIndex;
hList = GetDlgItem (hMemDlg, MEMORY_IMAGE);
nIndex = (INT)SendMessage (hList, CB_GETCURSEL, 0, 0);
if (nIndex == CB_ERR)
nIndex = 0;
dwIndex = (DWORD)SendMessage (hList, CB_GETITEMDATA, nIndex, 0);
if (dwIndex == 0xFFFFFFFF)
MemDlgRefresh (hMemDlg, hPviewDlg);
else
RefreshMemoryDlgImage (hMemDlg, dwIndex, gpImageObject);
}
/****************
utility functions
****************/
//********************************************************
//
// GetCurSelText --
//
// Get the text of current selection. Used for later ReSelectText().
//
INT GetCurSelText (HWND hList, LPTSTR str)
{
INT Index;
INT Length;
Index = (INT)SendMessage (hList, LB_GETCURSEL, 0, 0);
SendMessage (hList, LB_GETTEXT, Index, (LPARAM)str);
return Index;
}
//********************************************************
//
// GetCurSelData --
//
// Get the data associated with the current selection.
//
DWORD GetCurSelData (HWND hWnd, DWORD dwList)
{
HWND hList;
INT nIndex;
DWORD dwIndex;
hList = GetDlgItem (hWnd, dwList);
nIndex = (INT)SendMessage (hList, LB_GETCURSEL, 0, 0);
if (nIndex == LB_ERR)
nIndex = 0;
dwIndex = (DWORD)SendMessage (hList, LB_GETITEMDATA, nIndex, 0);
return dwIndex;
}
//********************************************************
//
// ReSelectText --
//
// Reselect the line specified by str. Returns the new index. If cannot
// find the line or any error, then 0 is returned.
//
INT ReSelectText (HWND hList, INT StartIndex, LPTSTR str)
{
INT_PTR Index;
INT Length;
TCHAR SaveChar = TEXT('\0');
Index = SendMessage (hList, LB_FINDSTRING, StartIndex, (LPARAM)str);
if (Index == LB_ERR) {
Length = lstrlen (str);
while (Index == LB_ERR && Length) {
SaveChar = str[Length-1];
str[Length-1] = TEXT('\0');
Index = SendMessage (hList, LB_FINDSTRING, StartIndex, (LPARAM)str);
str[Length-1] = SaveChar;
Length--;
}
}
if (Index == LB_ERR)
return 0;
else {
SendMessage (hList, LB_SETCURSEL, Index, 0);
return (INT)Index;
}
}
//********************************************************
//
// SetPerfIndexes
//
// Setup the perf data indexes.
//
void SetPerfIndexes (HWND hWnd)
{
LPTSTR TitleBuffer;
LPTSTR *Title;
DWORD Last;
TCHAR szTemp[50];
DWORD dwR;
dwR = GetPerfTitleSz (ghMachineKey, ghPerfKey, &TitleBuffer, &Title, &Last);
if (dwR != ERROR_SUCCESS) {
wsprintf (szTemp, TEXT("Unable to retrieve counter indexes, ERROR -> %#x"), dwR);
MessageBox (hWnd, szTemp, TEXT("Pviewer"), MB_OK|MB_ICONEXCLAMATION);
return;
}
PX_PROCESS = GetTitleIdx (hWnd, Title, Last, PN_PROCESS);
PX_PROCESS_CPU = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_CPU);
PX_PROCESS_PRIV = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_PRIV);
PX_PROCESS_USER = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_USER);
PX_PROCESS_WORKING_SET = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_WORKING_SET);
PX_PROCESS_PEAK_WS = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_PEAK_WS);
PX_PROCESS_PRIO = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_PRIO);
PX_PROCESS_ELAPSE = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_ELAPSE);
PX_PROCESS_ID = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_ID);
PX_PROCESS_PRIVATE_PAGE = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_PRIVATE_PAGE);
PX_PROCESS_VIRTUAL_SIZE = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_VIRTUAL_SIZE);
PX_PROCESS_PEAK_VS = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_PEAK_VS);
PX_PROCESS_FAULT_COUNT = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_FAULT_COUNT);
PX_THREAD = GetTitleIdx (hWnd, Title, Last, PN_THREAD);
PX_THREAD_CPU = GetTitleIdx (hWnd, Title, Last, PN_THREAD_CPU);
PX_THREAD_PRIV = GetTitleIdx (hWnd, Title, Last, PN_THREAD_PRIV);
PX_THREAD_USER = GetTitleIdx (hWnd, Title, Last, PN_THREAD_USER);
PX_THREAD_START = GetTitleIdx (hWnd, Title, Last, PN_THREAD_START);
PX_THREAD_SWITCHES = GetTitleIdx (hWnd, Title, Last, PN_THREAD_SWITCHES);
PX_THREAD_PRIO = GetTitleIdx (hWnd, Title, Last, PN_THREAD_PRIO);
PX_THREAD_BASE_PRIO = GetTitleIdx (hWnd, Title, Last, PN_THREAD_BASE_PRIO);
PX_THREAD_ELAPSE = GetTitleIdx (hWnd, Title, Last, PN_THREAD_ELAPSE);
PX_THREAD_DETAILS = GetTitleIdx (hWnd, Title, Last, PN_THREAD_DETAILS);
PX_THREAD_PC = GetTitleIdx (hWnd, Title, Last, PN_THREAD_PC);
PX_IMAGE = GetTitleIdx (hWnd, Title, Last, PN_IMAGE);
PX_IMAGE_NOACCESS = GetTitleIdx (hWnd, Title, Last, PN_IMAGE_NOACCESS);
PX_IMAGE_READONLY = GetTitleIdx (hWnd, Title, Last, PN_IMAGE_READONLY);
PX_IMAGE_READWRITE = GetTitleIdx (hWnd, Title, Last, PN_IMAGE_READWRITE);
PX_IMAGE_WRITECOPY = GetTitleIdx (hWnd, Title, Last, PN_IMAGE_WRITECOPY);
PX_IMAGE_EXECUTABLE = GetTitleIdx (hWnd, Title, Last, PN_IMAGE_EXECUTABLE);
PX_IMAGE_EXE_READONLY = GetTitleIdx (hWnd, Title, Last, PN_IMAGE_EXE_READONLY);
PX_IMAGE_EXE_READWRITE = GetTitleIdx (hWnd, Title, Last, PN_IMAGE_EXE_READWRITE);
PX_IMAGE_EXE_WRITECOPY = GetTitleIdx (hWnd, Title, Last, PN_IMAGE_EXE_WRITECOPY);
PX_PROCESS_ADDRESS_SPACE = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_ADDRESS_SPACE);
PX_PROCESS_PRIVATE_NOACCESS = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_PRIVATE_NOACCESS);
PX_PROCESS_PRIVATE_READONLY = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_PRIVATE_READONLY);
PX_PROCESS_PRIVATE_READWRITE = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_PRIVATE_READWRITE);
PX_PROCESS_PRIVATE_WRITECOPY = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_PRIVATE_WRITECOPY);
PX_PROCESS_PRIVATE_EXECUTABLE = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_PRIVATE_EXECUTABLE);
PX_PROCESS_PRIVATE_EXE_READONLY = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_PRIVATE_EXE_READONLY);
PX_PROCESS_PRIVATE_EXE_READWRITE = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_PRIVATE_EXE_READWRITE);
PX_PROCESS_PRIVATE_EXE_WRITECOPY = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_PRIVATE_EXE_WRITECOPY);
PX_PROCESS_MAPPED_NOACCESS = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_MAPPED_NOACCESS);
PX_PROCESS_MAPPED_READONLY = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_MAPPED_READONLY);
PX_PROCESS_MAPPED_READWRITE = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_MAPPED_READWRITE);
PX_PROCESS_MAPPED_WRITECOPY = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_MAPPED_WRITECOPY);
PX_PROCESS_MAPPED_EXECUTABLE = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_MAPPED_EXECUTABLE);
PX_PROCESS_MAPPED_EXE_READONLY = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_MAPPED_EXE_READONLY);
PX_PROCESS_MAPPED_EXE_READWRITE = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_MAPPED_EXE_READWRITE);
PX_PROCESS_MAPPED_EXE_WRITECOPY = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_MAPPED_EXE_WRITECOPY);
PX_PROCESS_IMAGE_NOACCESS = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_IMAGE_NOACCESS);
PX_PROCESS_IMAGE_READONLY = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_IMAGE_READONLY);
PX_PROCESS_IMAGE_READWRITE = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_IMAGE_READWRITE);
PX_PROCESS_IMAGE_WRITECOPY = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_IMAGE_WRITECOPY);
PX_PROCESS_IMAGE_EXECUTABLE = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_IMAGE_EXECUTABLE);
PX_PROCESS_IMAGE_EXE_READONLY = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_IMAGE_EXE_READONLY);
PX_PROCESS_IMAGE_EXE_READWRITE = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_IMAGE_EXE_READWRITE);
PX_PROCESS_IMAGE_EXE_WRITECOPY = GetTitleIdx (hWnd, Title, Last, PN_PROCESS_IMAGE_EXE_WRITECOPY);
wsprintf (INDEX_PROCTHRD_OBJ, TEXT("%ld %ld"), PX_PROCESS, PX_THREAD);
wsprintf (INDEX_COSTLY_OBJ, TEXT("%ld %ld %ld"),
PX_PROCESS_ADDRESS_SPACE, PX_IMAGE, PX_THREAD_DETAILS);
LocalFree (TitleBuffer);
LocalFree (Title);
}
//********************************************************
//
// GetTitleIdx
//
// Searches Titles[] for Name. Returns the index found.
//
DWORD GetTitleIdx (HWND hWnd, LPTSTR Title[], DWORD LastIndex, LPTSTR Name)
{
DWORD Index;
for (Index = 0; Index <= LastIndex; Index++)
if (Title[Index])
if (!lstrcmpi (Title[Index], Name))
return Index;
MessageBox (hWnd, Name, TEXT("Pviewer cannot find index"), MB_OK);
return 0;
}
//********************************************************
//
// SetListBoxTabStops --
//
// Set tab stops in the two list boxes.
//
void SetListBoxTabStops (HWND hWnd)
{
HWND hListBox;
INT Tabs[4] = {22*4, 36*4, 44*4};
hListBox = GetDlgItem (hWnd, PVIEW_PROCESS_LIST);
SendMessage (hListBox, LB_SETTABSTOPS, 3, (DWORD_PTR)Tabs);
hListBox = GetDlgItem (hWnd, PVIEW_THREAD_LIST);
SendMessage (hListBox, LB_SETTABSTOPS, 3, (DWORD_PTR)Tabs);
}
//********************************************************
//
// SetLocalMachine --
//
// Set local machine as performance data focus.
//
// Sets ghPerfKey
// ghMachineKey
// gszMachineName
// gszCurrentMachine
//
void SetLocalMachine (void)
{
TCHAR szName[MACHINE_NAME_SIZE];
DWORD dwSize = MACHINE_NAME_SIZE;
// close remote connections, if any
//
if (ghPerfKey != HKEY_PERFORMANCE_DATA)
RegCloseKey (ghPerfKey);
if (ghMachineKey != HKEY_LOCAL_MACHINE)
RegCloseKey (ghMachineKey);
// set to registry keys on local machine
//
ghPerfKey = HKEY_PERFORMANCE_DATA;
ghMachineKey = HKEY_LOCAL_MACHINE;
// get computer name
GetComputerName (szName, &dwSize);
if (szName[0] != '\\' || szName[1] != '\\') { // must have two '\\'
wsprintf (gszMachineName, TEXT("\\\\%s"), szName);
lstrcpy (gszCurrentMachine, gszMachineName);
} else {
lstrcpy (gszMachineName, szName);
lstrcpy (gszCurrentMachine, gszMachineName);
}
}
//********************************************************
//
// ConnectComputer --
//
// Connect to a computer with name entered in PVIEW_COMPUTER.
// If a new connection is made, then return TRUE else return FALSE.
//
// Sets gszCurrentMachine
// ghPerfKey
// ghMachineKey
//
BOOL ConnectComputer (HWND hWnd)
{
DWORD dwR;
HKEY hKey;
TCHAR szTemp[MACHINE_NAME_SIZE];
TCHAR szTemp2[MACHINE_NAME_SIZE+100];
BOOL bResult = TRUE;
MSG Msg;
SetCursor (ghCursor[1]);
if (!GetDlgItemText (hWnd, PVIEW_COMPUTER, szTemp, sizeof (szTemp)/sizeof(TCHAR))) {
SetLocalMachine ();
SetDlgItemText (hWnd, PVIEW_COMPUTER, gszCurrentMachine);
}
else if (!lstrcmpi (szTemp, gszCurrentMachine)) // didn't change name
bResult = FALSE;
else if (!lstrcmpi (szTemp, gszMachineName)) { // local machine
SetLocalMachine ();
EnableControls (hWnd);
}
else {
// a remote machine, connect to it
//
dwR = RegConnectRegistry (szTemp, HKEY_PERFORMANCE_DATA, &hKey);
if (dwR != ERROR_SUCCESS) {
wsprintf (szTemp2, TEXT("Cannot connect to computer %s"), szTemp);
MessageBox (hWnd, szTemp2, TEXT(""), MB_ICONEXCLAMATION|MB_OK);
SetDlgItemText (hWnd, PVIEW_COMPUTER, gszCurrentMachine);
bResult = FALSE;
} else {
// connected
//
lstrcpy (gszCurrentMachine, szTemp);
if (ghPerfKey != HKEY_PERFORMANCE_DATA)
RegCloseKey (ghPerfKey);
ghPerfKey = hKey;
DisableControls (hWnd);
// we also need to get the remote machine's title indexes.
//
dwR = RegConnectRegistry (gszCurrentMachine, HKEY_LOCAL_MACHINE, &hKey);
if (ghMachineKey != HKEY_LOCAL_MACHINE)
RegCloseKey (ghMachineKey);
if (dwR == ERROR_SUCCESS)
ghMachineKey = hKey;
else
// unable to connect, so we'll use our own indexes.
//
ghMachineKey = HKEY_LOCAL_MACHINE;
}
}
// Remove all mouse and key messages. They are not accepted
// while the cursor is a hourglass.
//
while (PeekMessage (&Msg, hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE));
while (PeekMessage (&Msg, hWnd, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE));
SetCursor (ghCursor[0]);
EnableWindow (GetDlgItem (hWnd, PVIEW_CONNECT), FALSE);
return bResult;
}
//********************************************************
//
// DisableControls --
//
// Disable controls that don't make sense on remote machine
//
void DisableControls (HWND hPviewDlg)
{
EnableWindow (GetDlgItem (hPviewDlg, PVIEW_TERMINATE), FALSE);
EnableWindow (GetDlgItem (hPviewDlg, PVIEW_PRIORITY_HIGH), FALSE);
EnableWindow (GetDlgItem (hPviewDlg, PVIEW_PRIORITY_NORMAL), FALSE);
EnableWindow (GetDlgItem (hPviewDlg, PVIEW_PRIORITY_IDL), FALSE);
}
//********************************************************
//
// EnableControls --
//
// Enable controls disabled by DisableControl().
//
void EnableControls (HWND hPviewDlg)
{
EnableWindow (GetDlgItem (hPviewDlg, PVIEW_TERMINATE), TRUE);
EnableWindow (GetDlgItem (hPviewDlg, PVIEW_PRIORITY_HIGH), TRUE);
EnableWindow (GetDlgItem (hPviewDlg, PVIEW_PRIORITY_NORMAL), TRUE);
EnableWindow (GetDlgItem (hPviewDlg, PVIEW_PRIORITY_IDL), TRUE);
}