home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: SysTools / SysTools.zip / taman002.zip / TASKMANA.ZIP / src / kProcessContainer.cpp < prev    next >
C/C++ Source or Header  |  2000-04-29  |  17KB  |  554 lines

  1. /* $Id: kProcessContainer.cpp,v 1.1 2000/04/29 19:06:35 stknut Exp $
  2.  *
  3.  * kProcessContainer - General process container.
  4.  *
  5.  * Copyright (c) 2000 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
  6.  *
  7.  */
  8.  
  9. /*******************************************************************************
  10. *   Defined Constants And Macros                                               *
  11. *******************************************************************************/
  12. #define INCL_WIN
  13. #define INCL_GPI
  14. #define INCL_BASE
  15.  
  16.  
  17. /*******************************************************************************
  18. *   Header Files                                                               *
  19. *******************************************************************************/
  20. #include <os2.h>
  21. #ifdef USE_KLIB
  22.     #include <kAssert.h>
  23.     #include <kLog.h>
  24.     #include <kHeap.h>
  25. #else
  26.     #include <malloc.h>
  27. #endif
  28. #include <memory.h>
  29. #include <string.h>
  30. #include <stddef.h>
  31. #include <stdio.h>
  32.  
  33. #include "kBase.h"
  34. #include "kError.h"
  35. #include "kDlgBase.h"
  36. #include "kMenuBase.h"
  37. #include "kClickDlg.h"
  38. #include "kContainer.h"
  39. //#include "kAbout.h"
  40. #include "kNotebookBase.h"
  41. #include "kNotebookPageBase.h"
  42.  
  43. #include "kQuerySysState.h"
  44. #include "kDetailBase.h"
  45. #include "kThreadRecord.h"
  46. #include "kThreadContainer.h"
  47. #include "kProcessRecord.h"
  48. #include "kProcessContainer.h"
  49. #include "kProcessDetails.h"
  50. #include "kProcessPriority.h"
  51. #include "kTaskMgr.h"
  52. #include "kTaskMgr_defs.h"
  53.  
  54.  
  55.  
  56.  
  57. /**
  58.  * Updates the container. This update routine is for the container with all processes. (usPid = 0xFFFF)
  59.  * @returns   Success indicator.
  60.  * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
  61.  */
  62. BOOL    kProcessContainer::kUpdateAllProcesses()
  63. {
  64.     BOOL            fRet;
  65.     PPROCESSDATA    pCur;
  66.     kProcessRecord *apInvalidRecs[256];
  67.     unsigned        cpInvalidRecs = 0;
  68.     kProcessRecord *apDeadRecs[64];
  69.     unsigned        cpDeadRecs = 0;
  70.  
  71.     /*
  72.      * Update status information.
  73.      */
  74.     if (!QSUpdateStateData())
  75.         return FALSE;
  76.  
  77.     /*
  78.      * Loop thru the list of processes and update the container.
  79.      */
  80.     pCur = QSGetFirstProcessDataNode();
  81.     disableUpdate();
  82.     while (pCur != NULL)
  83.     {
  84.         kProcessRecord *pRec;
  85.         BOOL            fNew = FALSE;
  86.         PPROCESSDATA    pToFree = NULL;
  87.  
  88.         /*
  89.          * Find the record. If not found, create a new one.
  90.          */
  91.         pRec = (kProcessRecord *)pCur->pvRecordCore;
  92.         if (pRec == NULL)
  93.         {   /* new records */
  94.             pCur->pvRecordCore = pRec = (kProcessRecord*)allocMiniRec(sizeof(kProcessRecord));
  95.             if (pRec == NULL)
  96.                 break;
  97.             pRec->init();
  98.             fNew = TRUE;
  99.         }
  100.  
  101.         /*
  102.          * Update data?
  103.          */
  104.         if (pCur->fDirty)
  105.         {
  106.             /*
  107.              * Update record data.
  108.              */
  109.             pRec->set(pCur);
  110.  
  111.             /*
  112.              * Update container content.
  113.              *   If this is a new process we'll have to add it
  114.              *   If this is an existing process we'll have to refresh it.
  115.              */
  116.             if (fNew)
  117.                 insertAtBottom(pRec, 1);
  118.             else
  119.             {
  120.                 if (cpInvalidRecs >= 256)
  121.                 {
  122.                     fRet = invalidateRecords(CMA_TEXTCHANGED,
  123.                                              cpInvalidRecs,
  124.                                              (kCnrMiniRecord **)&apInvalidRecs);
  125.                     ASSERT(fRet);
  126.                     cpInvalidRecs = 0;
  127.                 }
  128.  
  129.                 apInvalidRecs[cpInvalidRecs++] = pRec;
  130.             }
  131.         }
  132.  
  133.         /*
  134.          * Dead? Remove it!
  135.          */
  136.         if (pCur->fDead)
  137.         {
  138.             if (cpDeadRecs >= 64)
  139.             {
  140.                 fRet = removeRecords((PPVOID)&apDeadRecs[0], cpDeadRecs);
  141.                 ASSERT(fRet);
  142.                 cpDeadRecs = 0;
  143.             }
  144.             apDeadRecs[cpDeadRecs++] = pRec;
  145.             pToFree = pCur;
  146.         }
  147.  
  148.  
  149.         /* next */
  150.         pCur = pCur->pNext;
  151.         if (pToFree != NULL)
  152.             QSRemoveProcessData(pToFree);
  153.     }
  154.  
  155.     /*
  156.      * Invalidate records
  157.      */
  158.     if (cpInvalidRecs != 0)
  159.     {
  160.         fRet = invalidateRecords(CMA_TEXTCHANGED,
  161.                                  cpInvalidRecs,
  162.                                  (kCnrMiniRecord **)&apInvalidRecs);
  163.         ASSERT(fRet);
  164.     }
  165.  
  166.     /*
  167.      * Dead records
  168.      */
  169.     if (cpDeadRecs != 0)
  170.     {
  171.         fRet = removeRecords((PPVOID)&apDeadRecs[0], cpDeadRecs);
  172.         ASSERT(fRet);
  173.     }
  174.     enableUpdate();
  175.  
  176.     return pCur == NULL;
  177. }
  178.  
  179.  
  180.  
  181. /**
  182.  * Updates the container with children if usPid.
  183.  * @returns   Success indicator.
  184.  * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
  185.  */
  186. BOOL    kProcessContainer::kUpdateChildProcesses()
  187. {
  188.     PPROCESSDATA        pCur;
  189.     kProcessRecord *    pCnrRecs,
  190.                    *    pCurCnrRec;
  191.     int                 cRecords;
  192.  
  193.     /*
  194.      * Update status information.
  195.      */
  196.     if (!QSUpdateStateData())
  197.         return FALSE;
  198.  
  199.     /*
  200.      * Remove all records in container.
  201.      */
  202.     this->removeAllRecords();
  203.  
  204.     /*
  205.      * Loop thru the list of processes and update the container.
  206.      */
  207.     cRecords = 0;
  208.     pCnrRecs = pCurCnrRec = NULL;
  209.     pCur = QSGetFirstProcessDataNode();
  210.     while (pCur != NULL)
  211.     {
  212.         if (pCur->pProcRec->ppid == usPid)
  213.         {
  214.             /*
  215.              * Allocate and set new process record
  216.              */
  217.             if (pCnrRecs == NULL)
  218.                 pCnrRecs = pCurCnrRec = (kProcessRecord*)allocMiniRec(sizeof(kProcessRecord));
  219.             else
  220.                 pCurCnrRec = (kProcessRecord*)pCurCnrRec->setNext(allocMiniRec(sizeof(kProcessRecord)));
  221.             if (pCurCnrRec == NULL)
  222.                 break;
  223.  
  224.             pCurCnrRec->init();
  225.             pCurCnrRec->set(pCur);
  226.             cRecords++;
  227.         }
  228.  
  229.         /* next */
  230.         pCur = pCur->pNext;
  231.     }
  232.  
  233.  
  234.     /*
  235.      * Insert records (if any) and return.
  236.      */
  237.     return cRecords > 0 ? insertAtBottom(pCnrRecs, cRecords) : TRUE;
  238. }
  239.  
  240.  
  241.  
  242.  
  243.  
  244. /**
  245.  * Menu is closing. Remove emphasis.
  246.  * @param     usMenuId  Menu id.
  247.  * @param     hwndMnu   Handle to menu window.
  248.  */
  249. VOID kProcessContainer::menuEnd(USHORT usMenuId, HWND hwndMnu)
  250. {
  251.     setRecordEmphasis(pCurRecord, FALSE, CRA_SOURCE);
  252.     hwndMnu = hwndMnu;
  253.     usMenuId = usMenuId;
  254. }
  255.  
  256.  
  257. /**
  258.  * Command events.
  259.  * @param     usCmd     Control id which send/posted the message.
  260.  * @param     usSource  Source id.
  261.  * @param     fPointer  Mouse pointer flag.
  262.  * @remark    dismisses the dialog if DID_OK or DID_CANCEL.
  263.  */
  264. VOID  kProcessContainer::command(USHORT usCmd, USHORT usSource, BOOL fPointer)
  265. {
  266.     ULONG   ulRet;                      /* Return value from WinMessageBox usually. */
  267.     APIRET  rc;                         /* Return code from Dos API. */
  268.     char    szBuffer[1024];             /* String buffer used for formating messages. */
  269.  
  270.     switch (usCmd)
  271.     {
  272.         case IDM_CNR_PROC_DETAILS:
  273.             if (pCurRecord != NULL)
  274.             {
  275.                 try
  276.                 {
  277.                     new kProcessDetails(pCurRecord->getPid(), hwndCnr)->show();
  278.                 }
  279.                 catch(kError err)
  280.                 {
  281.                     err.logError();
  282.                     err.showError(kTaskMgr::pszErrorTitle);
  283.                 }
  284.             }
  285.             break;
  286.  
  287.  
  288.         case IDM_CNR_PROC_KILL:
  289.             if (pCurRecord != NULL)
  290.             {
  291.                 sprintf(szBuffer, "Are you sure you like to kill the process '%s'(pid %#x)?",
  292.                         pCurRecord->getName(),
  293.                         pCurRecord->getPid());
  294.                 ulRet = WinMessageBox(HWND_DESKTOP,
  295.                                       hwndCnr,
  296.                                       szBuffer,
  297.                                       "kTaskMgr - Sure?",
  298.                                       0,
  299.                                       MB_YESNO|MB_CUAWARNING);
  300.                 if (ulRet == MBID_YES)
  301.                 {
  302.                     rc = DosKillProcess(DKP_PROCESS, pCurRecord->getPid());
  303.                     sprintf(szBuffer, "rc=%d", rc);
  304.                     WinMessageBox(HWND_DESKTOP,
  305.                                   hwndCnr,
  306.                                   szBuffer,
  307.                                   "kTaskMgr - debug",
  308.                                   0,
  309.                                   MB_OK);
  310.                 }
  311.             }
  312.             break;
  313.  
  314.         case IDM_CNR_PROC_KILLXF86:
  315.             if (pCurRecord != NULL)
  316.             {
  317.                 HFILE   hFastIO;
  318.                 ULONG   ulAction;
  319.  
  320.                 rc = DosOpen("/dev/fastio$",
  321.                              &hFastIO,
  322.                              &ulAction,
  323.                              (ULONG)0,
  324.                              FILE_SYSTEM,
  325.                              FILE_OPEN,
  326.                              OPEN_SHARE_DENYNONE | OPEN_FLAGS_NOINHERIT | OPEN_ACCESS_READONLY,
  327.                              NULL);
  328.                 if (rc == NO_ERROR)
  329.                 {
  330.                     sprintf(szBuffer, "Are you sure you like to kill the process '%s'(pid %#x)?",
  331.                             pCurRecord->getName(),
  332.                             pCurRecord->getPid()
  333.                             );
  334.                     ulRet = WinMessageBox(HWND_DESKTOP,
  335.                                           hwndCnr,
  336.                                           szBuffer,
  337.                                           "kTaskMgr- Sure?",
  338.                                           0,
  339.                                           MB_YESNO|MB_CUAWARNING);
  340.                     if (ulRet == MBID_YES)
  341.                     {
  342.                         ULONG   ulLen;
  343.                         USHORT  usPid = pCurRecord->getPid();
  344.                         rc = DosDevIOCtl(hFastIO,
  345.                                          (ULONG)0x76,
  346.                                          (ULONG)0x65,
  347.                                          &usPid, sizeof(usPid), &ulLen,
  348.                                          NULL, 0, NULL);
  349.                     }
  350.                     DosClose(hFastIO);
  351.                 }
  352.                 else
  353.                 {
  354.                     sprintf(szBuffer,
  355.                             "Failed to open fastio$, rc = %d.\r"
  356.                             "XF86SUP.SYS is probably not installed.",
  357.                             rc);
  358.                     WinMessageBox(HWND_DESKTOP,
  359.                                   hwndCnr,
  360.                                   szBuffer,
  361.                                   kTaskMgr::pszErrorTitle,
  362.                                   0,
  363.                                   MB_CUACRITICAL | MB_OK);
  364.                 }
  365.             }
  366.             break;
  367.  
  368.         case IDM_CNR_PROC_PRIORITY:
  369.             if (pCurRecord != NULL)
  370.             {
  371.                 try
  372.                 {
  373.                     kProcessPriority *pDlg = new kProcessPriority(pCurRecord->getPid(), hwndCnr);
  374.                     pDlg->showModal();
  375.                 }
  376.                 catch(kError err)
  377.                 {
  378.                     err.logError();
  379.                     err.showError(kTaskMgr::pszErrorTitle);
  380.                 }
  381.             }
  382.             break;
  383.  
  384.         case IDM_CNR_PROC_ALL_REFRESH:
  385.             update();
  386.             break;
  387.  
  388.         case IDM_CNR_PROC_ALL_SORT_PID:
  389.         case IDM_CNR_PROC_ALL_SORT_PPID:
  390.         case IDM_CNR_PROC_ALL_SORT_SYSTIME:
  391.         case IDM_CNR_PROC_ALL_SORT_USERTIME:
  392.         case IDM_CNR_PROC_ALL_SORT_NAME:
  393.             if (usSortId != usCmd)
  394.             {
  395.                 usSortId = usCmd;
  396.                 pMenuCnrAll->checkMenuItem(IDM_CNR_PROC_ALL_SORT_PID     , usCmd == IDM_CNR_PROC_ALL_SORT_PID);
  397.                 pMenuCnrAll->checkMenuItem(IDM_CNR_PROC_ALL_SORT_PPID    , usCmd == IDM_CNR_PROC_ALL_SORT_PPID);
  398.                 pMenuCnrAll->checkMenuItem(IDM_CNR_PROC_ALL_SORT_SYSTIME , usCmd == IDM_CNR_PROC_ALL_SORT_SYSTIME);
  399.                 pMenuCnrAll->checkMenuItem(IDM_CNR_PROC_ALL_SORT_USERTIME, usCmd == IDM_CNR_PROC_ALL_SORT_USERTIME);
  400.                 pMenuCnrAll->checkMenuItem(IDM_CNR_PROC_ALL_SORT_NAME    , usCmd == IDM_CNR_PROC_ALL_SORT_NAME);
  401.  
  402.                 /* resort container */
  403.                 enableSorting();
  404.             }
  405.             else
  406.             {
  407.                 usSortId = 0xFFFF;
  408.                 disableSorting();
  409.                 pMenuCnrAll->checkMenuItem(usCmd, FALSE);
  410.             }
  411.             break;
  412.     }
  413.  
  414.     usSource = usSource;
  415.     fPointer = fPointer;
  416. }
  417.  
  418.  
  419. /**
  420.  * Record sort callback function - compares two records.
  421.  * @returns   >  0  when pRecord1  >  pRecord2
  422.  *            <  0  when pRecord1  <  pRecord2
  423.  *            == 0  when pRecord1 ==  pRecord2
  424.  * @param     pRecord1  Pointer to first record.
  425.  * @param     pRecord2  Pointer to second record.
  426.  */
  427. SHORT  kProcessContainer::sortCallBack(kCnrMiniRecord *pRecord1, kCnrMiniRecord *pRecord2)
  428. {
  429.     kProcessRecord *    pRec1 = (kProcessRecord *)pRecord1;
  430.     kProcessRecord *    pRec2 = (kProcessRecord *)pRecord2;
  431.  
  432.     if (pRec1 != NULL && pRec2 != NULL)
  433.     {
  434.         int iTmp = 1;
  435.         switch (usSortId)
  436.         {
  437.             case IDM_CNR_PROC_ALL_SORT_PID:
  438.                 iTmp = pRec1->getPid() - pRec2->getPid();
  439.                 break;
  440.  
  441.             case IDM_CNR_PROC_ALL_SORT_PPID:
  442.                 iTmp = strcmp(pRec1->getPPid(), pRec2->getPPid());
  443.                 break;
  444.  
  445.             case IDM_CNR_PROC_ALL_SORT_SYSTIME:
  446.                 iTmp = strcmp(pRec1->getSysTime(), pRec2->getSysTime());
  447.                 break;
  448.  
  449.             case IDM_CNR_PROC_ALL_SORT_USERTIME:
  450.                 iTmp = strcmp(pRec1->getUserTime(), pRec2->getUserTime());
  451.                 break;
  452.  
  453.             case IDM_CNR_PROC_ALL_SORT_NAME:
  454.                 iTmp = strcmp(pRec1->getName(), pRec2->getName());
  455.                 break;
  456.         }
  457.         return (SHORT)((iTmp > 0) ? 1 : (iTmp < 0) ? -1 : 0);
  458.     }
  459.     return 1;
  460. }
  461.  
  462.  
  463. /**
  464.  * Constructor.
  465.  * @returns
  466.  * @param     hwndDlg   Handle to dialog window.
  467.  * @param     ulCnrId   ID of the container dialog item in hwndDlg.
  468.  * @param     usPid     usPid = 0xFFFF:  View all processes.
  469.  *                      usPid != 0:      View all children of the given process id.
  470.  * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
  471.  */
  472. kProcessContainer::kProcessContainer(HWND hwndDlg, ULONG ulCnrId, USHORT usPid/* = 0xFFFF*/) throw(kError)
  473.     : kDetailCnr(WinWindowFromID(hwndDlg, ulCnrId),
  474.                  0,
  475.                  usPid == 0xFFFF ? "Process Overview" : "Child Processes",
  476.                  kProcessRecord::cFieldInfo,
  477.                  (PFIELDINFO)&kProcessRecord::aFieldInfo[0]),
  478.     usPid(usPid), pCurRecord(NULL)
  479. {
  480.     /*
  481.      * Create menus.
  482.      */
  483.     pMenuProcess = new kMenuBase(IDM_CNR_PROCESS, NULLHANDLE, hwndCnr, TRUE);
  484.     pMenuCnrAll  = new kMenuBase(IDM_CNR_PROCESS_ALL,     NULLHANDLE, hwndCnr, TRUE);
  485.     enableSorting();
  486. }
  487.  
  488.  
  489. /**
  490.  * Destructor.
  491.  */
  492. kProcessContainer::~kProcessContainer()
  493. {
  494.     if (pMenuProcess != NULL)
  495.         delete pMenuProcess;
  496.     if (pMenuCnrAll != NULL)
  497.         delete pMenuCnrAll;
  498. }
  499.  
  500.  
  501. /**
  502.  * Displays the popup menu for the container.
  503.  * @param     usId     Container id.
  504.  * @param     pRecord  Pointer to the record which is selected by either the key
  505.  */
  506. VOID kProcessContainer::cnrContextMenu(USHORT usId, PRECORDCORE pRecord)
  507. {
  508.     if (pMenuProcess && pMenuCnrAll)
  509.     {
  510.         pCurRecord = (kProcessRecord*)pRecord;
  511.         setRecordEmphasis(pCurRecord, TRUE, CRA_SOURCE);
  512.         if (pRecord != NULL)
  513.             pMenuProcess->popup();
  514.         else
  515.             pMenuCnrAll->popup();
  516.     }
  517.     usId = usId;
  518. }
  519.  
  520.  
  521. /**
  522.  * Enter or double click on record in the container.
  523.  * This action will bring up the detail dialog for the record.
  524.  */
  525. VOID kProcessContainer::cnrEnter(USHORT usId, HWND hwndCnr, PRECORDCORE pRecord, ULONG fKey)
  526. {
  527.     if (pRecord != NULL)
  528.     {
  529.         pCurRecord = (kProcessRecord*)pRecord;
  530.         command(IDM_CNR_PROC_DETAILS, 0, 0);
  531.     }
  532.     usId = usId;
  533.     fKey = fKey;
  534.     hwndCnr = hwndCnr;
  535. }
  536.  
  537.  
  538.  
  539. /**
  540.  * Updates the contents of the container.
  541.  * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
  542.  */
  543. VOID  kProcessContainer::update()
  544. {
  545.     /*
  546.      * Insert records
  547.      */
  548.     if (usPid == 0xFFFF)
  549.         kUpdateAllProcesses();
  550.     else
  551.         kUpdateChildProcesses();
  552. }
  553.  
  554.