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.
1412 lines
43 KiB
1412 lines
43 KiB
|
|
/******************************************************************************
|
|
|
|
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 = TRUE;
|
|
|
|
|
|
|
|
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);
|
|
}
|