[C++]PSAPIDEM.CPP

来源:互联网 发布:杰普软件 编辑:程序博客网 时间:2024/05/17 14:15
//=======================================// PSAPIDEM - Matt Pietrek 1996// Microsoft Systems Journal, August 1996// FILE: PSAPIDEM.CPP//=======================================#include <windows.h>#include <commctrl.h>#pragma hdrstop#include "psapi.h"#include "psapidem.h"// Helper function prototypesvoid Handle_WM_COMMAND(HWND hDlg, WPARAM wParam, LPARAM lParam);void Handle_WM_INITDIALOG(HWND hDlg);void Handle_WM_CLOSE(HWND hDlg);BOOL CALLBACK PSApiDemDlgProc(HWND, UINT, WPARAM, LPARAM);HTREEITEM TVAppendString(HWND hWnd, HTREEITEM hTi, PSTR psz);void GetSetPositionInfoFromRegistry(BOOL fSave, POINT *lppt);// ======================= String literals ===============================char gszRegistryKey[] = "Software//WheatyProductions//PSAPIDEM";char g_AboutMsgTxt[] =  "PSApiDem shows processes and device driver information obtained "  "with PSAPI.DLL, from the Win32 SDK";char g_AboutTitleTxt[] = "PSApiDem - Matt Pietrek 1996, for MSJ";// ======================= Start of code ===============================void AddProcessDetails(HWND hWnd, HTREEITEM hTreeItem, HANDLE hProcess){  //  // Fills in the details for one specific process  //  HMODULE hMods[1024];  DWORD cbNeeded;  //  // Get a list of all the HMODULEs in this process.  Add a "Module"  // subnode, and add the full path for each HMODULE to it.  //  if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))  {    HTREEITEM hTiModules = TVAppendString(hWnd, hTreeItem, "Modules");    for (unsigned i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)    {      char szModName[MAX_PATH];      char szItem[MAX_PATH + 64];      // Get the full path to the module's file      if (GetModuleFileNameEx(hProcess, hMods[i], szModName, sizeof(szModName)))      {        wsprintf(szItem, "%s (0x%08X)", szModName, hMods[i]);        TVAppendString(hWnd, hTiModules, szItem);      }    }  }  //  // Next, use PSAPI.DLL to collect information about the memory usage  // of the process.  Add a "Memory" node to the process, and add  // subnodes for each field in the PROCESS_MEMORY_COUNTERS structure.  //  PROCESS_MEMORY_COUNTERS pmc;  if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))  {    char szItem[128];    HTREEITEM hTiMem = TVAppendString(hWnd, hTreeItem, "Memory");    wsprintf(szItem, "%s 0x%08X", "PageFaultCount", pmc.PageFaultCount);    TVAppendString(hWnd, hTiMem, szItem);    wsprintf(szItem, "%s 0x%08X", "PeakWorkingSetSize", pmc.PeakWorkingSetSize);    TVAppendString(hWnd, hTiMem, szItem);    wsprintf(szItem, "%s 0x%08X", "WorkingSetSize", pmc.WorkingSetSize);    TVAppendString(hWnd, hTiMem, szItem);    wsprintf(szItem, "%s 0x%08X", "QuotaPeakPagedPoolUsage",      pmc.QuotaPeakPagedPoolUsage);    TVAppendString(hWnd, hTiMem, szItem);    wsprintf(szItem, "%s 0x%08X", "QuotaPagedPoolUsage",      pmc.QuotaPagedPoolUsage);    TVAppendString(hWnd, hTiMem, szItem);    wsprintf(szItem, "%s 0x%08X", "QuotaPeakNonPagedPoolUsage",      pmc.QuotaPeakNonPagedPoolUsage);    TVAppendString(hWnd, hTiMem, szItem);    wsprintf(szItem, "%s 0x%08X", "QuotaNonPagedPoolUsage",      pmc.QuotaNonPagedPoolUsage);    TVAppendString(hWnd, hTiMem, szItem);    wsprintf(szItem, "%s 0x%08X", "PagefileUsage", pmc.PagefileUsage);    TVAppendString(hWnd, hTiMem, szItem);    wsprintf(szItem, "%s 0x%08X", "PeakPagefileUsage", pmc.PeakPagefileUsage);    TVAppendString(hWnd, hTiMem, szItem);  }  //  // Finally, use the KERNEL32 GetProcessTimes function to see how much  // time the process has spent in user and kernel modes.  Add this  // information (in milliseconds) to the process node  //  FILETIME ftCreate, ftExit, ftKernel, ftUser;  if (GetProcessTimes(hProcess, &ftCreate, &ftExit, &ftKernel, &ftUser))    ;  {    // Horrible, disgusting hack!  The two lines below basically grab the    // contents of a FILETIME structure and store it in a 64 bit integer.    LONGLONG tUser64 = *(LONGLONG*) &ftUser;    LONGLONG tKernel64 = *(LONGLONG*) &ftKernel;    DWORD tUser, tKernel;    // The LONGLONGs contain the time in 100 nanosecond intervals (now    // there's a useful unit of measurement...).  Divide each of them by    // 10000 to convert into milliseconds, and store the results in a    // DWORD.  This means that the max time before overflowing is around    // 4 Million seconds (about 49 days)    tUser = (DWORD)(tUser64 / 10000);    tKernel = (DWORD)(tKernel64 / 10000);    // Format the user and kernel times, and add to the process node    char szItem[128];    wsprintf(szItem, "User mode: %u ms", tUser);    TVAppendString(hWnd, hTreeItem, szItem);    wsprintf(szItem, "Kernel mode: %u ms", tKernel);    TVAppendString(hWnd, hTreeItem, szItem);  }}void AddProcessToList(HWND hWnd, DWORD processID){  //  // Adds the process name and ID to the treeview control, then calls  // AddProcessDetails to fill in the details about the process  //  char szProcessName[MAX_PATH] = "unknown";  char szItemString[MAX_PATH + 64];  HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,    FALSE, processID);  if (hProcess)  {    HMODULE hMod;    DWORD cbNeeded;    if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))    {      GetModuleBaseName(hProcess, hMod, szProcessName, sizeof(szProcessName));    }  }  wsprintf(szItemString, "%s (ID:%u)", szProcessName, processID);  HTREEITEM hTiProcess = TVAppendString(hWnd, TVI_ROOT, szItemString);  if (hProcess && hTiProcess)    AddProcessDetails(hWnd, hTiProcess, hProcess);  CloseHandle(hProcess);}void UpdateProcessList(HWND hDlg){  //  // Clears the treeview, obtains a list of process IDs, and shows them  //  // Get the treeview's HWND, then clear it  HWND hWnd = GetDlgItem(hDlg, IDC_TREE_PROCESS);  TreeView_DeleteAllItems(hWnd);  // Get the list of process IDs  DWORD aProcesses[1024], cbNeeded;  if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))    return ;  // Calculate how many process IDs were returned  DWORD cProcesses = cbNeeded / sizeof(DWORD);  // Spit out the information for each ID  for (unsigned i = 0; i < cProcesses; i++)    AddProcessToList(hWnd, aProcesses[i]);}void UpdateDriverList(HWND hDlg){  //  // Clears the treeview, obtains a list of drivers, and shows them  //  // Get the treeview's HWND, then clear it  HWND hWnd = GetDlgItem(hDlg, IDC_TREE_DRIVERS);  TreeView_DeleteAllItems(hWnd);  // Get the list of device driver base addresses  PVOID aDrivers[1024];  DWORD cbNeeded;  if (!EnumDeviceDrivers(aDrivers, sizeof(aDrivers), &cbNeeded))    return ;  // Calculate how many drivers were returned  DWORD cDrivers = cbNeeded / sizeof(aDrivers[0]);  // Spit out the information for each driver  for (unsigned i = 0; i < cDrivers; i++)  {    char szBaseName[MAX_PATH] = "";    char szDriverFileName[MAX_PATH] = "";    // Get the driver's base name    if (GetDeviceDriverBaseName(aDrivers[i], szBaseName, sizeof(szBaseName)))    {      char szItem[MAX_PATH + 64];      wsprintf(szItem, "%s (0x%08X)", szBaseName, aDrivers[i]);      HTREEITEM hTiDriver = TVAppendString(hWnd, TVI_ROOT, szItem);      // Get the full path to the driver      GetDeviceDriverFileName(aDrivers[i], szDriverFileName, sizeof        (szDriverFileName));      TVAppendString(hWnd, hTiDriver, szDriverFileName);    }  }}void RefreshViews(HWND hDlg){  UpdateProcessList(hDlg); // Should be self-explanatory!  UpdateDriverList(hDlg);}// ======================= Start of UI code ===============================int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, PSTR lpszCmdLine,  int nCmdShow){  // Gotta do this for those lovely tree view controls  InitCommonControls();  // Bring up the user interface (A dialog box?  What a surprise!)  DialogBox(hInstance, MAKEINTRESOURCE(IDD_PSAPIDEM_DLG), 0, (DLGPROC)    PSApiDemDlgProc);  return 0;}BOOL CALLBACK PSApiDemDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam){  //  // The dialog procedure for the main window  //  switch (msg)  {    case WM_COMMAND:      Handle_WM_COMMAND(hDlg, wParam, lParam);      return TRUE;    case WM_INITDIALOG:      Handle_WM_INITDIALOG(hDlg);      return TRUE;    case WM_CLOSE:      Handle_WM_CLOSE(hDlg);      break;      // let everything else fall through  }  return FALSE;}void Handle_WM_COMMAND(HWND hDlg, WPARAM wParam, LPARAM lParam){  switch (LOWORD(wParam))  {    case IDC_BUTTON_REFRESH:      RefreshViews(hDlg);      break;    case IDC_BUTTON_EXIT:      Handle_WM_CLOSE(hDlg);      break;    case IDC_BUTTON_ABOUT:      MessageBox(hDlg, g_AboutMsgTxt, g_AboutTitleTxt, MB_OK);      break;  }}void Handle_WM_INITDIALOG(HWND hDlg){  // Get the window coordinates where the program was last running  // and move the window to that spot.  POINT pt;  GetSetPositionInfoFromRegistry(FALSE, &pt);  SetWindowPos(hDlg, 0, pt.x, pt.y, 0, 0, SWP_NOSIZE | SWP_NOREDRAW |    SWP_NOZORDER | SWP_NOACTIVATE);  RefreshViews(hDlg); // Fill tree views with initial values}void Handle_WM_CLOSE(HWND hDlg){  // Save off the window's X,Y coordinates for next time  RECT rect;  GetWindowRect(hDlg, &rect);  GetSetPositionInfoFromRegistry(TRUE, (LPPOINT) &rect);  EndDialog(hDlg, 0);}HTREEITEM TVAppendString(HWND hWnd, HTREEITEM hTi, PSTR psz){  //  // A helper function that appends a string to the end of the list  // of subnodes under a specified node (hTi).  //  TV_INSERTSTRUCT tvis;  memset(&tvis, 0, sizeof(tvis));  tvis.hParent = hTi;  tvis.hInsertAfter = TVI_LAST;  tvis.item.mask = TVIF_TEXT;  tvis.item.pszText = psz;  return TreeView_InsertItem(hWnd, &tvis);}void GetSetPositionInfoFromRegistry(BOOL fSave, POINT *lppt){  //  // Function that saves or restores the coordinates of a dialog box  // in the system registry.  Handles the case where there's nothing there.  //  HKEY hKey;  DWORD dataSize, err, disposition;  char szKeyName[] = "DlgCoordinates";  if (!fSave)  // In case the key's not there yet, we'll    lppt->x = lppt->y = 0;  // return 0,0 for the coordinates  // Open the registry key (or create it if the first time being used)  err = RegCreateKeyEx(HKEY_CURRENT_USER, gszRegistryKey, 0, 0,    REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0,  &hKey,  &disposition);  if (ERROR_SUCCESS != err)    return ;  if (fSave)  // Save out coordinates  {    RegSetValueEx(hKey, szKeyName, 0, REG_BINARY, (PBYTE)lppt, sizeof(*lppt));  }  else  // read in coordinates  {    dataSize = sizeof(*lppt);    RegQueryValueEx(hKey, szKeyName, 0, 0, (PBYTE)lppt, &dataSize);  }}