/****************************************************************************** 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 #include #include "perfdata.h" #include "pviewdat.h" #include "pviewdlg.h" #include #include #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); }