home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / pcmag / vol11n15.zip / SYSMON.C < prev    next >
C/C++ Source or Header  |  1992-06-20  |  31KB  |  837 lines

  1. // SysMon - System Monitor for Windows 3.1
  2. // Copyright (C) 1992 Ray Duncan
  3. // PC Magazine * Ziff Davis Publishing
  4.  
  5. #define dim(x) (sizeof(x) / sizeof(x[0]))   // returns no. of elements
  6. #define MAXLINES 4096                       // max lines to display
  7.  
  8. #include "stdlib.h"
  9. #include "windows.h"
  10. #include "toolhelp.h"
  11. #include "dos.h"
  12. #include "sysmon.h"
  13.  
  14. HANDLE hInst;                               // module instance handle
  15. HWND hFrame;                                // handle for frame window
  16. HFONT hFont;                                // handle for nonprop. font
  17.  
  18. int CharX, CharY;                           // character dimensions
  19. int LinesPerPage;                           // lines per page
  20. int CurLine = 0;                            // first line, current page
  21. int TotLines = 0;                           // total lines to display
  22. int TopLine = 0;                            // first line of last page
  23. int DisplayType = IDM_MODULE;               // type of info to display
  24.  
  25. char *LinePtr[MAXLINES];                    // holds pointers to lines
  26.  
  27. char szFrameClass[] = "SysMon";             // classname for frame window
  28. char szAppName[] = "System Monitor";        // long application name
  29. char szMenuName[] = "SysMonMenu";           // name of menu resource
  30. char szIcon[] = "SysMonIcon";                // name of icon resource
  31. char szIni[] = "sysmon.ini";                // name of private INI file
  32.  
  33. WNDPROC lpTimerProc;                        // timer callback thunk
  34.  
  35. //
  36. // Table of window messages supported by FrameWndProc()
  37. // and the functions which correspond to each message.
  38. //
  39. struct decodeMsg frameMsgs[] = {
  40.     WM_PAINT, DoPaint,
  41.     WM_SIZE, DoSize,
  42.     WM_COMMAND, DoCommand,
  43.     WM_SETFOCUS, DoSetFocus,
  44.     WM_CLOSE, DoClose,
  45.     WM_DESTROY, DoDestroy,
  46.     WM_VSCROLL, DoVScroll, } ;
  47.  
  48. //
  49. // Table of menubar item IDs and their corresponding functions.
  50. //
  51. struct decodeMsg menuitems[] = {
  52.     IDM_EXIT, DoMenuExit,
  53.     IDM_ABOUT, DoMenuAbout,
  54.     IDM_MODULE, DoDisplayType,
  55.     IDM_CLASS, DoDisplayType,
  56.     IDM_TASK, DoDisplayType,
  57.     IDM_GLOBHEAP, DoDisplayType,
  58.     IDM_SYSHEAP, DoDisplayType,
  59.     IDM_MEMMAN, DoDisplayType,
  60.     IDM_DISK, DoDisplayType,
  61.     IDM_REFRESH, DoRefresh, } ;
  62.  
  63. // 
  64. // Table of memory block types and descriptive strings
  65. //
  66. struct decodeUINT memType[] = {
  67.     GT_UNKNOWN,      "Unknown",
  68.     GT_DGROUP,       "DGROUP",
  69.     GT_DATA,         "Program Data",
  70.     GT_CODE,         "Program Code",
  71.     GT_TASK,         "Task Database",
  72.     GT_RESOURCE,     "Resource",
  73.     GT_MODULE,       "Module Database",
  74.     GT_FREE,         "Available",
  75.     GT_INTERNAL,     "Internal",
  76.     GT_SENTINEL,     "Sentinel",
  77.     GT_BURGERMASTER, "Arena Map", } ;
  78.  
  79. //
  80. // WinMain -- entry point for this application from Windows.
  81. //
  82. int APIENTRY WinMain(HANDLE hInstance,
  83.     HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  84. {
  85.     MSG msg;                                // scratch message storage
  86.     hInst = hInstance;                      // save this instance handle
  87.  
  88.     if(!hPrevInstance)                      // if first instance,
  89.         if(!InitApp(hInstance))             // register window class
  90.         {
  91.             MessageBox(hFrame, "Can't initialize SysMon!", szAppName,
  92.                 MB_ICONSTOP | MB_OK);
  93.             return(FALSE);
  94.         }
  95.  
  96.     if(!InitInstance(hInstance, nCmdShow))  // create this instance's window
  97.     {
  98.         MessageBox(hFrame, "Can't initialize SysMon!", szAppName,
  99.             MB_ICONSTOP | MB_OK);
  100.         return(FALSE);
  101.     }
  102.  
  103.     while(GetMessage(&msg, NULL, 0, 0))     // while message != WM_QUIT
  104.     {
  105.         TranslateMessage(&msg);             // translate virtual key codes
  106.         DispatchMessage(&msg);              // dispatch message to window
  107.     }
  108.  
  109.     TermInstance(hInstance);                // clean up for this instance
  110.     return(msg.wParam);                     // return code = WM_QUIT value
  111. }
  112.  
  113. //
  114. // InitApp --- global initialization code for this application.
  115. //
  116. BOOL InitApp(HANDLE hInstance)
  117. {
  118.     WNDCLASS  wc;                           // window class info
  119.  
  120.     // set parameters for frame window class
  121.     wc.style = CS_HREDRAW|CS_VREDRAW;       // class style
  122.     wc.lpfnWndProc = FrameWndProc;          // class callback function
  123.     wc.cbClsExtra = 0;                      // extra per-class data
  124.     wc.cbWndExtra = 0;                      // extra per-window data
  125.     wc.hInstance = hInstance;               // handle of class owner
  126.     wc.hIcon = LoadIcon(hInst, szIcon);       // application icon
  127.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);       // default cursor
  128.     wc.hbrBackground = GetStockObject(WHITE_BRUSH); // background color 
  129.     wc.lpszMenuName =  szMenuName;          // name of menu resource
  130.     wc.lpszClassName = szFrameClass;        // name of window class
  131.  
  132.     return(RegisterClass(&wc));             // register frame window class
  133. }
  134.  
  135. //
  136. // InitInstance --- instance initialization code for this application.
  137. //
  138. BOOL InitInstance(HANDLE hInstance, int nCmdShow)
  139. {
  140.     HDC hdc;                                // handle for device context
  141.     TEXTMETRIC tm;                          // info about font
  142.     RECT rect;                              // window position & size
  143.     int i;                                  // scratch variable
  144.  
  145.     for(i = 0; i < MAXLINES; i++)           // initialize all line
  146.         LinePtr[i] = NULL;                  // pointers
  147.  
  148.     hFrame = CreateWindow(                  // create frame window
  149.         szFrameClass,                       // window class name
  150.         szAppName,                          // text for title bar
  151.         WS_OVERLAPPEDWINDOW | WS_VSCROLL,   // window style
  152.         CW_USEDEFAULT, CW_USEDEFAULT,       // default position
  153.         CW_USEDEFAULT, CW_USEDEFAULT,       // default size
  154.         NULL,                               // no parent window
  155.         NULL,                               // use class default menu
  156.         hInstance,                          // window owner
  157.         NULL);                              // unused pointer
  158.  
  159.     if(!hFrame) return(FALSE);              // error, can't create window
  160.  
  161.     hdc = GetDC(hFrame);                    // get device context
  162.     hFont = GetStockObject(SYSTEM_FIXED_FONT);  // handle for nonprop. font
  163.     SelectObject(hdc, hFont);               // realize the font and get
  164.     GetTextMetrics(hdc, &tm);               // the character dimensions
  165.     CharX = tm.tmAveCharWidth;
  166.     CharY = tm.tmHeight + tm.tmExternalLeading;
  167.     ReleaseDC(hFrame, hdc);                 // release device context
  168.  
  169.     GetWindowRect(hFrame, &rect);           // current window pos & size
  170.  
  171.     // read profile for frame window from previous invocation, if any
  172.     rect.left   = GetPrivateProfileInt("Frame", "xul", rect.left, szIni);
  173.     rect.top    = GetPrivateProfileInt("Frame", "yul", rect.top, szIni);
  174.     rect.right  = GetPrivateProfileInt("Frame", "xlr", rect.right, szIni);
  175.     rect.bottom = GetPrivateProfileInt("Frame", "ylr", rect.bottom, szIni);
  176.  
  177.     MoveWindow(hFrame, rect.left, rect.top, // force window size & position
  178.         rect.right-rect.left, rect.bottom-rect.top, TRUE);
  179.  
  180.     // get display type from previous invocation, default to module list
  181.     DisplayType = GetPrivateProfileInt("Frame", "type", IDM_MODULE, szIni);
  182.  
  183.     ShowWindow(hFrame, nCmdShow);           // make frame window visible
  184.     UpdateWindow(hFrame);                   // force WM_PAINT message
  185.  
  186.     // allocate thunk for timer callback routine
  187.     lpTimerProc  = MakeProcInstance((WNDPROC) TimerProc, hInst);
  188.  
  189.     // set up our 10 sec. (10,000 msec) timer callback
  190.     if (!SetTimer(hFrame, 1, 10000, lpTimerProc))
  191.         return(FALSE);
  192.  
  193.     return(TRUE);                           // return success flag
  194. }
  195.  
  196. //
  197. // TermInstance -- instance termination code for this application.
  198. // Does nothing in this case, included for symmetry with InitInstance.
  199. //
  200. BOOL TermInstance(HANDLE hinstance)
  201. {
  202.     return(TRUE);                           // return success flag
  203. }
  204.  
  205. //
  206. // FrameWndProc --- callback function for application frame window.
  207. // Searches frameMsgs[] for message match, runs corresponding function.
  208. //
  209. LONG FAR APIENTRY FrameWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  210. {
  211.     int i;                                  // scratch variable
  212.  
  213.     for(i = 0; i < dim(frameMsgs); i++)     // decode window message and
  214.     {                                       // run corresponding function
  215.         if(wMsg == frameMsgs[i].Code)
  216.             return((*frameMsgs[i].Fxn)(hWnd, wMsg, wParam, lParam));
  217.     }
  218.  
  219.     return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  220. }
  221.  
  222. //
  223. // DoCommand -- process WM_COMMAND message for frame window by
  224. // decoding the menubar item with the menuitems[] array, then
  225. // running the corresponding function to process the command.
  226. // 
  227. LONG DoCommand(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  228. {
  229.     int i;                                  // scratch variable
  230.  
  231.     for(i = 0; i < dim(menuitems); i++)     // decode menu command and
  232.     {                                       // run corresponding function
  233.         if(wParam == menuitems[i].Code)
  234.             return((*menuitems[i].Fxn)(hWnd, wMsg, wParam, lParam));
  235.     }
  236.  
  237.     return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  238. }
  239.  
  240. //
  241. // DoDestroy -- process WM_DESTROY message for frame window.
  242. // 
  243. LONG DoDestroy(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  244. {
  245.     PostQuitMessage(0);                     // force WM_QUIT message to
  246.     return(0);                              // terminate the event loop
  247. }
  248.  
  249. //
  250. // DoClose -- process WM_CLOSE message for frame window.
  251. // 
  252. LONG DoClose(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  253. {
  254.     UpdateProfile();                        // save window size & position
  255.     DestroyWindow(hWnd);                    // then close down app
  256.     return(FALSE);                              
  257. }
  258.  
  259. //
  260. // DoVScroll -- process WM_VSCROLL message for frame window.
  261. // 
  262. LONG DoVScroll(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  263. {
  264.     RECT rect;
  265.  
  266.     switch(LOWORD(wParam))                  // LOWORD vital for Win32
  267.     {                                   
  268.         case SB_TOP:                        // go to top of output if
  269.             if(CurLine)                     // we aren't there already
  270.             {
  271.                 SetCurLine(0);
  272.                 Repaint();
  273.             }
  274.             break;
  275.  
  276.         case SB_BOTTOM:                     // go to bottom of output if
  277.             if(CurLine < TopLine)           // we aren't there already
  278.             {
  279.                 SetCurLine(TopLine);
  280.                 Repaint();
  281.             }
  282.             break;
  283.  
  284.         case SB_LINEUP:                     // scroll up by one line if
  285.             if(CurLine)                     // we aren't already at top
  286.             {   
  287.                 SetCurLine(CurLine - 1);
  288.                 ScrollWindow(hWnd, 0, CharY, NULL, NULL);
  289.                 UpdateWindow(hWnd);
  290.             }
  291.             break;
  292.  
  293.         case SB_LINEDOWN:                   // scroll down by one line if
  294.             if(CurLine < TopLine)           // we aren't already at bottom
  295.             {
  296.                 SetCurLine(CurLine + 1);
  297.                 ScrollWindow(hWnd, 0, -CharY, NULL, NULL);
  298.                 GetClientRect(hWnd, &rect);
  299.                 rect.top = max(0, (LinesPerPage-1) * CharY);
  300.                 InvalidateRect(hWnd, &rect, TRUE);
  301.                 UpdateWindow(hWnd);
  302.             }
  303.             break;
  304.  
  305.         case SB_PAGEUP:                     // scroll up by one page
  306.             SetCurLine(CurLine - LinesPerPage);
  307.             Repaint();
  308.             break;
  309.  
  310.         case SB_PAGEDOWN:                   // scroll down by one page
  311.             SetCurLine(CurLine + LinesPerPage);
  312.             Repaint();
  313.             break;
  314.  
  315.         case SB_THUMBPOSITION:              // scroll display according
  316.             SetCurLine(THUMBPOS);           // to new thumb position
  317.             Repaint();
  318.             break;
  319.     }
  320.     return(FALSE);                              
  321. }
  322.  
  323. //
  324. // DoPaint -- process WM_PAINT message for frame window.
  325. // 
  326. LONG DoPaint(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  327. {
  328.     HDC hdc;
  329.     PAINTSTRUCT ps;
  330.     int i;
  331.  
  332.     hdc = BeginPaint(hWnd, &ps);            // get device context
  333.     SelectObject(hdc, hFont);               // select non-prop. font
  334.  
  335.     for(i = 0; i < LinesPerPage; i++)       // paint lines of text
  336.         PaintLine(hdc, i);                  // in the window
  337.  
  338.     EndPaint(hWnd, &ps);                    // release device context
  339.     return(FALSE);
  340. }
  341.  
  342. //
  343. // DoSize -- process WM_SIZE message for frame window.  Recalculate
  344. // lines per page, if window has grown and at end of file may need to 
  345. // change first line in window and refresh it.
  346. //
  347. LONG DoSize(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  348. {
  349.     LinesPerPage = HIWORD(lParam) / CharY;  // window height / char height
  350.     ConfigWindow();                         // calc display parameters
  351.     if(CurLine > TopLine)                   // make sure window refilled
  352.         SetCurLine(TopLine);                // if window got bigger
  353.     return(FALSE);
  354. }
  355.  
  356. //
  357. // DoSetFocus -- process WM_SETFOCUS message for frame window.
  358. // Refresh display in case something has changed since last timer event.
  359. // This also gets called when app is launched after window is created.
  360. //
  361. LONG DoSetFocus(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  362. {
  363.     SendMessage(hFrame, WM_COMMAND, IDM_REFRESH, 0); 
  364.     return(FALSE);
  365. }
  366.  
  367. //
  368. // DoMenuExit -- process File-Exit command from menu bar.
  369. // 
  370. LONG DoMenuExit(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  371. {
  372.     SendMessage (hWnd, WM_CLOSE, 0, 0L);    // send window close message    
  373.     return(FALSE);                          // to shut down the app
  374. }
  375.  
  376. //
  377. // DoDisplayType -- process items on Display popup to select
  378. // the type of information to display, then force window update
  379. // 
  380. LONG DoDisplayType(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  381. {
  382.     HMENU hMenu;                            // scratch menu handle
  383.  
  384.     hMenu = GetMenu(hWnd);                  // update popup checkmark
  385.     CheckMenuItem(hMenu, DisplayType, MF_UNCHECKED);
  386.     DisplayType = wParam;                   
  387.     CheckMenuItem(hMenu, DisplayType, MF_CHECKED);
  388.     SendMessage(hWnd, WM_COMMAND, IDM_REFRESH, 0);  // update window
  389.     return(FALSE);
  390. }
  391.  
  392. //
  393. // DoRefresh -- rebuild the information for display according to
  394. // the currently selected display type, then refresh the window.
  395. // 
  396. LONG DoRefresh(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  397. {
  398.     EmptyLines();                           // discard previous output
  399.  
  400.     switch(DisplayType)                     // call the appropriate
  401.     {                                       // list walking routine
  402.         case IDM_MODULE:                    // according to display type
  403.             WalkModuleList();
  404.             SetWindowCaption("Modules");
  405.             break;
  406.  
  407.         case IDM_CLASS:
  408.             WalkClassList();
  409.             SetWindowCaption("Window Classes");
  410.             break;
  411.  
  412.         case IDM_TASK:
  413.             WalkTaskList();
  414.             SetWindowCaption("Active Tasks");
  415.             break;
  416.  
  417.         case IDM_GLOBHEAP:
  418.             WalkGlobalHeap();
  419.             SetWindowCaption("Global Heap");
  420.             break;
  421.  
  422.         case IDM_SYSHEAP:
  423.             ShowSystemHeap();
  424.             SetWindowCaption("System Heap");
  425.             break;
  426.  
  427.         case IDM_MEMMAN:
  428.             ShowMemManInfo();
  429.             SetWindowCaption("Memory Available");
  430.             break;
  431.  
  432.         case IDM_DISK:
  433.             ShowDiskSpace();
  434.             SetWindowCaption("Disk Space Available");
  435.             break;
  436.     }
  437.  
  438.     ConfigWindow();                         // configure scroll bar etc.
  439.     Repaint();                              // refresh the window
  440.  
  441.     return(FALSE);
  442. }
  443.  
  444. //
  445. // DoMenuAbout -- process File-About command from menu bar.
  446. // 
  447. LONG DoMenuAbout(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  448. {
  449.     WNDPROC lpAboutProc;                    // scratch far pointer
  450.  
  451.     // allocate a thunk for the dialog callback, then display dialog
  452.     lpAboutProc = MakeProcInstance((WNDPROC)AboutDlgProc, hInst);
  453.     DialogBox(hInst, "AboutBox", hWnd, lpAboutProc);         
  454.     FreeProcInstance(lpAboutProc);
  455.     return(FALSE);                              
  456. }
  457.  
  458. //
  459. // AboutDlgProc -- callback routine for About... dialog.  Basically
  460. // ignores all messages except for the OK button, which dismisses dialog.
  461. //
  462. BOOL FAR APIENTRY AboutDlgProc (HWND hwnd, UINT msg, UINT wParam, LONG lParam)
  463. {
  464.     if((msg == WM_COMMAND) && (wParam == IDOK)) 
  465.         EndDialog(hwnd, 0);                 // if OK button, destroy dialog
  466.     else return(FALSE);                     // otherwise ignore message
  467. }
  468.  
  469. // 
  470. // WalkModuleList -- uses ToolHelp functions to walk through
  471. // module list and build formatted output in LinePtr[] array.
  472. //
  473. VOID WalkModuleList(VOID)
  474. {
  475.     MODULEENTRY me;                         // receives module info
  476.     char temp[256];                         // scratch formatting buffer
  477.  
  478.     memset(&me, 0, sizeof(MODULEENTRY));    // initialize structure for
  479.     me.dwSize = sizeof(MODULEENTRY);        // return of module data
  480.     AddLine("Handle  Usage  Module    Pathname");   // format title
  481.     ModuleFirst(&me);                       // initialize to 1st module
  482.  
  483.     do {                                    // format module information
  484.         wsprintf(temp, "%04Xh   %4d   %-8.8s  %s", me.hModule, me.wcUsage,
  485.             (LPSTR) me.szModule, (LPSTR) me.szExePath);
  486.         AddLine(temp);                      // add to array for output
  487.     } while(ModuleNext(&me));               // get next module name
  488. }
  489.  
  490. // 
  491. // WalkClassList -- uses ToolHelp functions to walk through
  492. // window class list and build formatted output in LinePtr[] array.
  493. //
  494. VOID WalkClassList(VOID)
  495. {
  496.     CLASSENTRY ce;                          // receives window class info
  497.     MODULEENTRY me;                         // receives module info
  498.     char temp[256];                         // scratch formatting buffer
  499.  
  500.     memset(&ce, 0, sizeof(CLASSENTRY));     // initialize structure for
  501.     ce.dwSize = sizeof(CLASSENTRY);         // return of window class data
  502.     memset(&me, 0, sizeof(MODULEENTRY));    // initialize structure for
  503.     me.dwSize = sizeof(MODULEENTRY);        // return of module data
  504.     AddLine("Class Name        Owner Module");  // format title
  505.     ClassFirst(&ce);                        // initialize to 1st class
  506.  
  507.     do {                                    // format classname & owner
  508.         ModuleFindHandle(&me, ce.hInst);    // get module name
  509.         wsprintf(temp, "%-16.16s  %04Xh %s", (LPSTR) ce.szClassName,
  510.             ce.hInst, (LPSTR) me.szModule);
  511.         AddLine(temp);                      // add to array for output
  512.     } while(ClassNext(&ce));                // get next class name
  513. }
  514.  
  515. // 
  516. // WalkTaskList -- uses ToolHelp functions to walk through
  517. // task list and build formatted output in LinePtr[] array.
  518. //
  519. VOID WalkTaskList(VOID)
  520. {
  521.     TASKENTRY te;                           // receives task info
  522.     MODULEENTRY me;                         // receives module info
  523.     char temp[256];                         // scratch formatting buffer
  524.  
  525.     memset(&te, 0, sizeof(TASKENTRY));      // initialize structure for
  526.     te.dwSize = sizeof(TASKENTRY);          // return of task info
  527.     memset(&me, 0, sizeof(MODULEENTRY));    // initialize structure for
  528.     me.dwSize = sizeof(MODULEENTRY);        // return of module data
  529.     AddLine("Task     Parent   Instance   Module   Module     Module");
  530.     AddLine("Handle   Task     Handle     Handle   Name       Pathname");
  531.     TaskFirst(&te);                         // initialize to 1st task
  532.  
  533.     do {                                    // format task information
  534.         ModuleFindHandle(&me, te.hModule);  // get modulename & pathname
  535.         wsprintf(temp, "%04Xh    %04Xh    %04Xh      %04Xh    %-8.8s   %s",
  536.             te.hTask, te.hTaskParent, te.hInst, te.hModule,
  537.             (LPSTR) me.szModule, (LPSTR) me.szExePath);
  538.         AddLine(temp);                      // add to array for output
  539.     } while(TaskNext(&te));                 // get next task 
  540. }
  541.  
  542. // 
  543. // WalkGlobalHeap -- uses ToolHelp functions to walk through
  544. // global heap and build formatted output in LinePtr[] array.
  545. //
  546. VOID WalkGlobalHeap(VOID)
  547. {
  548.     GLOBALENTRY ge;                         // receives heap block info
  549.     TASKENTRY te;                           // receives task info
  550.     MODULEENTRY me;                         // receives module info
  551.     int i;                                  // scratch variable
  552.     char *p;                                // scratch string pointer
  553.     char temp[256];                         // scratch formatting buffer
  554.  
  555.     memset(&ge, 0, sizeof(GLOBALENTRY));    // initialize structure for
  556.     ge.dwSize = sizeof(GLOBALENTRY);        // return of heap block info
  557.     memset(&me, 0, sizeof(MODULEENTRY));    // initialize structure for
  558.     me.dwSize = sizeof(MODULEENTRY);        // return of module data
  559.     memset(&te, 0, sizeof(TASKENTRY));      // initialize structure for
  560.     te.dwSize = sizeof(TASKENTRY);          // return of task info
  561.     AddLine("Handle   Linear Addr    Size     Type             Owner");
  562.     GlobalFirst(&ge, GLOBAL_ALL);           // initialize to 1st block
  563.  
  564.     do {                                    
  565.         if(TaskFindHandle(&te, ge.hOwner))  // get block owner's name
  566.             ModuleFindHandle(&me, te.hModule);
  567.         else if(!ModuleFindHandle(&me, ge.hOwner))
  568.             me.szModule[0] = '\0';
  569.  
  570.         p = "Unknown";                      // decode memory block type
  571.         for(i = 0; i < dim(memType); i++) 
  572.             if(ge.wType == memType[i].Code)
  573.                 p = memType[i].Name;
  574.                                             // format heap block info
  575.         wsprintf(temp, "%04Xh     %08lXh   %08lXh  %-16.16s %04Xh %s",
  576.             ge.hBlock, ge.dwAddress, ge.dwBlockSize, (LPSTR) p, ge.hOwner,
  577.             (LPSTR) me.szModule);
  578.         AddLine(temp);                      // add to array for output
  579.     } while(GlobalNext(&ge, GLOBAL_ALL));   // get next class name
  580. }
  581.  
  582. // 
  583. // ShowMemManInfo -- uses ToolHelp function to display various
  584. // memory manager information.
  585. //
  586. VOID ShowMemManInfo(VOID)
  587. {
  588.     MEMMANINFO mmi;                         // receives memory info
  589.     char temp[256];                         // scratch formatting buffer
  590.  
  591.     memset(&mmi, 0, sizeof(MEMMANINFO));    // initialize structure for
  592.     mmi.dwSize = sizeof(MEMMANINFO);        // return of memory info
  593.     MemManInfo(&mmi);                       // now retrieve info
  594.  
  595.     wsprintf(temp, "Page size:                   %d bytes", 
  596.         mmi.wPageSize);
  597.     AddLine(temp);
  598.  
  599.     wsprintf(temp, "Total pages:                 %ld", 
  600.         mmi.dwTotalPages);
  601.     AddLine(temp);
  602.  
  603.     wsprintf(temp, "Swap file pages:             %ld", 
  604.         mmi.dwSwapFilePages);
  605.     AddLine(temp);
  606.  
  607.     wsprintf(temp, "Maximum pages available:     %ld", 
  608.         mmi.dwMaxPagesAvailable);
  609.     AddLine(temp);
  610.  
  611.     wsprintf(temp, "Maximum pages lockable:      %ld", 
  612.         mmi.dwMaxPagesLockable);
  613.     AddLine(temp);
  614.  
  615.     wsprintf(temp, "Total unlocked pages:        %ld", 
  616.         mmi.dwTotalUnlockedPages);
  617.     AddLine(temp);
  618.  
  619.     wsprintf(temp, "Pages not in use:            %ld", 
  620.         mmi.dwFreePages);
  621.     AddLine(temp);
  622.  
  623.     wsprintf(temp, "Total linear address space:  %ld bytes", 
  624.         mmi.dwTotalLinearSpace*mmi.wPageSize);
  625.     AddLine(temp);
  626.  
  627.     wsprintf(temp, "Free linear address space:   %ld bytes", 
  628.         mmi.dwFreeLinearSpace * mmi.wPageSize);
  629.     AddLine(temp);
  630.  
  631.     wsprintf(temp, "Largest free block:          %ld bytes", 
  632.         mmi.dwLargestFreeBlock);
  633.     AddLine(temp);
  634. }
  635.  
  636. // 
  637. // ShowSystemHeap -- uses ToolHelp function to display various
  638. // system heap information.
  639. //
  640. VOID ShowSystemHeap(VOID)
  641. {
  642.     SYSHEAPINFO si;                         // receives system heap info
  643.     char temp[256];                         // scratch formatting buffer
  644.  
  645.     memset(&si, 0, sizeof(SYSHEAPINFO));    // initialize structure for
  646.     si.dwSize = sizeof(SYSHEAPINFO);        // return of system heap info
  647.     SystemHeapInfo(&si);                    // now retrieve info
  648.  
  649.     wsprintf(temp, "User Heap Space Free:  %d%%", si.wUserFreePercent);
  650.     AddLine(temp);
  651.  
  652.     wsprintf(temp, "GDI Heap Space Free:   %d%%", si.wGDIFreePercent);
  653.     AddLine(temp);
  654.  
  655.     AddLine(" ");
  656.  
  657.     wsprintf(temp, "User Heap Handle:      %04Xh", si.hUserSegment);
  658.     AddLine(temp);
  659.  
  660.     wsprintf(temp, "GDI Heap Handle:       %04Xh", si.hGDISegment);
  661.     AddLine(temp);
  662. }
  663.  
  664. // 
  665. // ShowDiskSpace -- uses DOS Int 21H function to get & display free 
  666. // disk space for each valid drive.
  667. //
  668. VOID ShowDiskSpace(VOID)
  669. {
  670.     union REGS regs;                        // int 21h register contents
  671.     int status;                                // receives int86 status
  672.     int drive = 3;                            // start with C drive
  673.     char temp[256];                         // scratch formatting buffer
  674.  
  675.     AddLine("Drive  Total Bytes   Free Bytes");         // format titles
  676.  
  677.     while(TRUE)
  678.     {
  679.         regs.h.ah = 0x36;                       // function number
  680.         regs.h.dl = drive;                    // drive code (1=A, etc.)
  681.         status = intdos(®s, ®s);        // perform int 21h
  682.  
  683.         if(status == -1) break;                // quit if this drive invalid
  684.  
  685.         wsprintf(temp, "  %c    %10ld  %10ld",    // format drive info
  686.             drive + 'A' - 1,
  687.             (LONG) regs.x.ax * (LONG) regs.x.cx * (LONG) regs.x.dx,
  688.             (LONG) regs.x.ax * (LONG) regs.x.cx * (LONG) regs.x.bx);
  689.         AddLine(temp);
  690.  
  691.         drive++;                            // go to next drive
  692.     }
  693. }
  694.  
  695. //
  696. // SetCurLine - called to set CurLine to valid value, clamped to
  697. // the range (0...TopLine), and redraw thumb on scroll bar.
  698. //
  699. VOID SetCurLine(int NewLine)
  700. {
  701.     CurLine = min(max(NewLine, 0), TopLine);
  702.     SetScrollPos(hFrame, SB_VERT, CurLine, TRUE);
  703. }
  704.  
  705. //
  706. // ConfigWindow -- Configures various display parameters and scrollbar
  707. // according to total lines of output, current window size, and the
  708. // number of lines that will fit into the window.
  709. //
  710. VOID ConfigWindow(VOID)
  711. {
  712.     // calc line number of first line of last page
  713.     TopLine = max(TotLines - LinesPerPage,0);
  714.     
  715.     // update scroll bar range and thumb position
  716.     SetScrollRange(hFrame, SB_VERT, 0, TopLine, FALSE);
  717.     SetScrollPos(hFrame, SB_VERT, CurLine, TRUE);
  718. }
  719.  
  720. //
  721. // AddLine -- called with a pointer to an ASCIIZ string, allocates
  722. // memory from the heap to hold the string, puts the pointer
  723. // to the heap block into the next position in the LinePtr[] array,
  724. // and updates the total line count.
  725. //
  726. VOID AddLine(char * p)
  727. {
  728.     char * q;                               // scratch pointer
  729.  
  730.     if(TotLines == MAXLINES)                // bail out if line pointer
  731.         return;                             // array is already full
  732.     q = malloc(strlen(p)+1);                // allocate memory for line
  733.     if(q == 0)                              // bail out out if no 
  734.         return;                             // heap space available
  735.     strcpy(q, p);                           // copy string to heap
  736.     LinePtr[TotLines] = q;                  // put heap pointer into array
  737.     TotLines++;                             // count lines of output
  738. }
  739.  
  740. //
  741. // EmptyLines - releases all heap blocks in LinePtr[] array,
  742. // then zeros out the line pointers and the total line count
  743. //
  744. VOID EmptyLines(VOID)
  745. {
  746.     int i;                                  // scratch variable
  747.  
  748.     for(i = 0; i < MAXLINES; i++)
  749.     {
  750.         if(LinePtr[i])                      // if this position in
  751.         {                                   // the LinePtr array is
  752.             free(LinePtr[i]);               // nonzero, release the
  753.             LinePtr[i] = NULL;              // heap block, then zero
  754.         }                                   // out the LinePtr slot
  755.     }
  756.  
  757.     CurLine = 0;                            // initialize various
  758.     TotLines = 0;                           // other global variables
  759.     TopLine = 0;
  760. }
  761.  
  762. //
  763. // PaintLine -- paint a single line of text in the window.
  764. // The passed line number is relative to the window, NOT to the
  765. // total array of formatted output available to be painted.
  766. //
  767. VOID PaintLine(HDC hdc, INT RelLine)
  768. {
  769.     int Line = RelLine + CurLine;
  770.     if(LinePtr[Line])
  771.         TextOut(hdc, CharX, RelLine*CharY, LinePtr[Line], strlen(LinePtr[Line]));
  772. }
  773.  
  774. //
  775. // Repaint - force repaint of all formatted output in main window
  776. //
  777. VOID Repaint(VOID)
  778. {
  779.     InvalidateRect(hFrame, NULL, TRUE);     // force repaint entire window
  780. }
  781.  
  782. //
  783. // SetWindowCaption -- concatenate the application name with the
  784. // display type, then update the frame window's title bar.
  785. //
  786. VOID SetWindowCaption(char * szDisplayType)
  787. {
  788.     char szTemp[256];                       // scratch buffer
  789.  
  790.     strcpy(szTemp, szAppName);              // get application name
  791.     strcat(szTemp, " - ");                  // add separator
  792.     strcat(szTemp, szDisplayType);          // add information type
  793.     SetWindowText(hFrame, szTemp);          // put result into title bar
  794. }
  795.  
  796. //
  797. // UpdateProfile() --  saves the current window size and position
  798. // and display type in the application's private INI file.
  799. //
  800. VOID UpdateProfile(VOID)
  801. {
  802.     RECT rect;
  803.     char temp[20];
  804.  
  805.     if(IsIconic(hFrame) || IsZoomed(hFrame)) return;
  806.  
  807.     GetWindowRect(hFrame, &rect);           
  808.  
  809.     wsprintf(temp,"%d", rect.left);
  810.     WritePrivateProfileString("Frame", "xul", temp, szIni);
  811.  
  812.     wsprintf(temp,"%d", rect.top);
  813.     WritePrivateProfileString("Frame", "yul", temp, szIni);
  814.  
  815.     wsprintf(temp,"%d", rect.right);
  816.     WritePrivateProfileString("Frame", "xlr", temp, szIni);
  817.  
  818.     wsprintf(temp,"%d", rect.bottom);
  819.     WritePrivateProfileString("Frame", "ylr", temp, szIni);
  820.  
  821.     wsprintf(temp,"%d", DisplayType);
  822.     WritePrivateProfileString("Frame", "type", temp, szIni);
  823. }
  824.  
  825. //
  826. // TimerProc() -- Callback for 10 second timer. Refresh display
  827. // if window is not minimized and does not have the focus.
  828. // 
  829. WORD FAR APIENTRY TimerProc(HWND hwnd, WORD message, WORD wParam, LONG lParam)
  830. {
  831.     if((!IsIconic(hFrame)) && (hFrame != GetFocus()))
  832.         SendMessage(hFrame, WM_COMMAND, IDM_REFRESH, 0); 
  833.     return(FALSE);                          
  834. }
  835.  
  836.  
  837.