home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: SysTools
/
SysTools.zip
/
ktskmg2.zip
/
src
/
kProcessContainer.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2000-04-29
|
17KB
|
554 lines
/* $Id: kProcessContainer.cpp,v 1.1 2000/04/29 19:06:35 stknut Exp $
*
* kProcessContainer - General process container.
*
* Copyright (c) 2000 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
*
*/
/*******************************************************************************
* Defined Constants And Macros *
*******************************************************************************/
#define INCL_WIN
#define INCL_GPI
#define INCL_BASE
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <os2.h>
#ifdef USE_KLIB
#include <kAssert.h>
#include <kLog.h>
#include <kHeap.h>
#else
#include <malloc.h>
#endif
#include <memory.h>
#include <string.h>
#include <stddef.h>
#include <stdio.h>
#include "kBase.h"
#include "kError.h"
#include "kDlgBase.h"
#include "kMenuBase.h"
#include "kClickDlg.h"
#include "kContainer.h"
//#include "kAbout.h"
#include "kNotebookBase.h"
#include "kNotebookPageBase.h"
#include "kQuerySysState.h"
#include "kDetailBase.h"
#include "kThreadRecord.h"
#include "kThreadContainer.h"
#include "kProcessRecord.h"
#include "kProcessContainer.h"
#include "kProcessDetails.h"
#include "kProcessPriority.h"
#include "kTaskMgr.h"
#include "kTaskMgr_defs.h"
/**
* Updates the container. This update routine is for the container with all processes. (usPid = 0xFFFF)
* @returns Success indicator.
* @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
*/
BOOL kProcessContainer::kUpdateAllProcesses()
{
BOOL fRet;
PPROCESSDATA pCur;
kProcessRecord *apInvalidRecs[256];
unsigned cpInvalidRecs = 0;
kProcessRecord *apDeadRecs[64];
unsigned cpDeadRecs = 0;
/*
* Update status information.
*/
if (!QSUpdateStateData())
return FALSE;
/*
* Loop thru the list of processes and update the container.
*/
pCur = QSGetFirstProcessDataNode();
disableUpdate();
while (pCur != NULL)
{
kProcessRecord *pRec;
BOOL fNew = FALSE;
PPROCESSDATA pToFree = NULL;
/*
* Find the record. If not found, create a new one.
*/
pRec = (kProcessRecord *)pCur->pvRecordCore;
if (pRec == NULL)
{ /* new records */
pCur->pvRecordCore = pRec = (kProcessRecord*)allocMiniRec(sizeof(kProcessRecord));
if (pRec == NULL)
break;
pRec->init();
fNew = TRUE;
}
/*
* Update data?
*/
if (pCur->fDirty)
{
/*
* Update record data.
*/
pRec->set(pCur);
/*
* Update container content.
* If this is a new process we'll have to add it
* If this is an existing process we'll have to refresh it.
*/
if (fNew)
insertAtBottom(pRec, 1);
else
{
if (cpInvalidRecs >= 256)
{
fRet = invalidateRecords(CMA_TEXTCHANGED,
cpInvalidRecs,
(kCnrMiniRecord **)&apInvalidRecs);
ASSERT(fRet);
cpInvalidRecs = 0;
}
apInvalidRecs[cpInvalidRecs++] = pRec;
}
}
/*
* Dead? Remove it!
*/
if (pCur->fDead)
{
if (cpDeadRecs >= 64)
{
fRet = removeRecords((PPVOID)&apDeadRecs[0], cpDeadRecs);
ASSERT(fRet);
cpDeadRecs = 0;
}
apDeadRecs[cpDeadRecs++] = pRec;
pToFree = pCur;
}
/* next */
pCur = pCur->pNext;
if (pToFree != NULL)
QSRemoveProcessData(pToFree);
}
/*
* Invalidate records
*/
if (cpInvalidRecs != 0)
{
fRet = invalidateRecords(CMA_TEXTCHANGED,
cpInvalidRecs,
(kCnrMiniRecord **)&apInvalidRecs);
ASSERT(fRet);
}
/*
* Dead records
*/
if (cpDeadRecs != 0)
{
fRet = removeRecords((PPVOID)&apDeadRecs[0], cpDeadRecs);
ASSERT(fRet);
}
enableUpdate();
return pCur == NULL;
}
/**
* Updates the container with children if usPid.
* @returns Success indicator.
* @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
*/
BOOL kProcessContainer::kUpdateChildProcesses()
{
PPROCESSDATA pCur;
kProcessRecord * pCnrRecs,
* pCurCnrRec;
int cRecords;
/*
* Update status information.
*/
if (!QSUpdateStateData())
return FALSE;
/*
* Remove all records in container.
*/
this->removeAllRecords();
/*
* Loop thru the list of processes and update the container.
*/
cRecords = 0;
pCnrRecs = pCurCnrRec = NULL;
pCur = QSGetFirstProcessDataNode();
while (pCur != NULL)
{
if (pCur->pProcRec->ppid == usPid)
{
/*
* Allocate and set new process record
*/
if (pCnrRecs == NULL)
pCnrRecs = pCurCnrRec = (kProcessRecord*)allocMiniRec(sizeof(kProcessRecord));
else
pCurCnrRec = (kProcessRecord*)pCurCnrRec->setNext(allocMiniRec(sizeof(kProcessRecord)));
if (pCurCnrRec == NULL)
break;
pCurCnrRec->init();
pCurCnrRec->set(pCur);
cRecords++;
}
/* next */
pCur = pCur->pNext;
}
/*
* Insert records (if any) and return.
*/
return cRecords > 0 ? insertAtBottom(pCnrRecs, cRecords) : TRUE;
}
/**
* Menu is closing. Remove emphasis.
* @param usMenuId Menu id.
* @param hwndMnu Handle to menu window.
*/
VOID kProcessContainer::menuEnd(USHORT usMenuId, HWND hwndMnu)
{
setRecordEmphasis(pCurRecord, FALSE, CRA_SOURCE);
hwndMnu = hwndMnu;
usMenuId = usMenuId;
}
/**
* Command events.
* @param usCmd Control id which send/posted the message.
* @param usSource Source id.
* @param fPointer Mouse pointer flag.
* @remark dismisses the dialog if DID_OK or DID_CANCEL.
*/
VOID kProcessContainer::command(USHORT usCmd, USHORT usSource, BOOL fPointer)
{
ULONG ulRet; /* Return value from WinMessageBox usually. */
APIRET rc; /* Return code from Dos API. */
char szBuffer[1024]; /* String buffer used for formating messages. */
switch (usCmd)
{
case IDM_CNR_PROC_DETAILS:
if (pCurRecord != NULL)
{
try
{
new kProcessDetails(pCurRecord->getPid(), hwndCnr)->show();
}
catch(kError err)
{
err.logError();
err.showError(kTaskMgr::pszErrorTitle);
}
}
break;
case IDM_CNR_PROC_KILL:
if (pCurRecord != NULL)
{
sprintf(szBuffer, "Are you sure you like to kill the process '%s'(pid %#x)?",
pCurRecord->getName(),
pCurRecord->getPid());
ulRet = WinMessageBox(HWND_DESKTOP,
hwndCnr,
szBuffer,
"kTaskMgr - Sure?",
0,
MB_YESNO|MB_CUAWARNING);
if (ulRet == MBID_YES)
{
rc = DosKillProcess(DKP_PROCESS, pCurRecord->getPid());
sprintf(szBuffer, "rc=%d", rc);
WinMessageBox(HWND_DESKTOP,
hwndCnr,
szBuffer,
"kTaskMgr - debug",
0,
MB_OK);
}
}
break;
case IDM_CNR_PROC_KILLXF86:
if (pCurRecord != NULL)
{
HFILE hFastIO;
ULONG ulAction;
rc = DosOpen("/dev/fastio$",
&hFastIO,
&ulAction,
(ULONG)0,
FILE_SYSTEM,
FILE_OPEN,
OPEN_SHARE_DENYNONE | OPEN_FLAGS_NOINHERIT | OPEN_ACCESS_READONLY,
NULL);
if (rc == NO_ERROR)
{
sprintf(szBuffer, "Are you sure you like to kill the process '%s'(pid %#x)?",
pCurRecord->getName(),
pCurRecord->getPid()
);
ulRet = WinMessageBox(HWND_DESKTOP,
hwndCnr,
szBuffer,
"kTaskMgr- Sure?",
0,
MB_YESNO|MB_CUAWARNING);
if (ulRet == MBID_YES)
{
ULONG ulLen;
USHORT usPid = pCurRecord->getPid();
rc = DosDevIOCtl(hFastIO,
(ULONG)0x76,
(ULONG)0x65,
&usPid, sizeof(usPid), &ulLen,
NULL, 0, NULL);
}
DosClose(hFastIO);
}
else
{
sprintf(szBuffer,
"Failed to open fastio$, rc = %d.\r"
"XF86SUP.SYS is probably not installed.",
rc);
WinMessageBox(HWND_DESKTOP,
hwndCnr,
szBuffer,
kTaskMgr::pszErrorTitle,
0,
MB_CUACRITICAL | MB_OK);
}
}
break;
case IDM_CNR_PROC_PRIORITY:
if (pCurRecord != NULL)
{
try
{
kProcessPriority *pDlg = new kProcessPriority(pCurRecord->getPid(), hwndCnr);
pDlg->showModal();
}
catch(kError err)
{
err.logError();
err.showError(kTaskMgr::pszErrorTitle);
}
}
break;
case IDM_CNR_PROC_ALL_REFRESH:
update();
break;
case IDM_CNR_PROC_ALL_SORT_PID:
case IDM_CNR_PROC_ALL_SORT_PPID:
case IDM_CNR_PROC_ALL_SORT_SYSTIME:
case IDM_CNR_PROC_ALL_SORT_USERTIME:
case IDM_CNR_PROC_ALL_SORT_NAME:
if (usSortId != usCmd)
{
usSortId = usCmd;
pMenuCnrAll->checkMenuItem(IDM_CNR_PROC_ALL_SORT_PID , usCmd == IDM_CNR_PROC_ALL_SORT_PID);
pMenuCnrAll->checkMenuItem(IDM_CNR_PROC_ALL_SORT_PPID , usCmd == IDM_CNR_PROC_ALL_SORT_PPID);
pMenuCnrAll->checkMenuItem(IDM_CNR_PROC_ALL_SORT_SYSTIME , usCmd == IDM_CNR_PROC_ALL_SORT_SYSTIME);
pMenuCnrAll->checkMenuItem(IDM_CNR_PROC_ALL_SORT_USERTIME, usCmd == IDM_CNR_PROC_ALL_SORT_USERTIME);
pMenuCnrAll->checkMenuItem(IDM_CNR_PROC_ALL_SORT_NAME , usCmd == IDM_CNR_PROC_ALL_SORT_NAME);
/* resort container */
enableSorting();
}
else
{
usSortId = 0xFFFF;
disableSorting();
pMenuCnrAll->checkMenuItem(usCmd, FALSE);
}
break;
}
usSource = usSource;
fPointer = fPointer;
}
/**
* Record sort callback function - compares two records.
* @returns > 0 when pRecord1 > pRecord2
* < 0 when pRecord1 < pRecord2
* == 0 when pRecord1 == pRecord2
* @param pRecord1 Pointer to first record.
* @param pRecord2 Pointer to second record.
*/
SHORT kProcessContainer::sortCallBack(kCnrMiniRecord *pRecord1, kCnrMiniRecord *pRecord2)
{
kProcessRecord * pRec1 = (kProcessRecord *)pRecord1;
kProcessRecord * pRec2 = (kProcessRecord *)pRecord2;
if (pRec1 != NULL && pRec2 != NULL)
{
int iTmp = 1;
switch (usSortId)
{
case IDM_CNR_PROC_ALL_SORT_PID:
iTmp = pRec1->getPid() - pRec2->getPid();
break;
case IDM_CNR_PROC_ALL_SORT_PPID:
iTmp = strcmp(pRec1->getPPid(), pRec2->getPPid());
break;
case IDM_CNR_PROC_ALL_SORT_SYSTIME:
iTmp = strcmp(pRec1->getSysTime(), pRec2->getSysTime());
break;
case IDM_CNR_PROC_ALL_SORT_USERTIME:
iTmp = strcmp(pRec1->getUserTime(), pRec2->getUserTime());
break;
case IDM_CNR_PROC_ALL_SORT_NAME:
iTmp = strcmp(pRec1->getName(), pRec2->getName());
break;
}
return (SHORT)((iTmp > 0) ? 1 : (iTmp < 0) ? -1 : 0);
}
return 1;
}
/**
* Constructor.
* @returns
* @param hwndDlg Handle to dialog window.
* @param ulCnrId ID of the container dialog item in hwndDlg.
* @param usPid usPid = 0xFFFF: View all processes.
* usPid != 0: View all children of the given process id.
* @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
*/
kProcessContainer::kProcessContainer(HWND hwndDlg, ULONG ulCnrId, USHORT usPid/* = 0xFFFF*/) throw(kError)
: kDetailCnr(WinWindowFromID(hwndDlg, ulCnrId),
0,
usPid == 0xFFFF ? "Process Overview" : "Child Processes",
kProcessRecord::cFieldInfo,
(PFIELDINFO)&kProcessRecord::aFieldInfo[0]),
usPid(usPid), pCurRecord(NULL)
{
/*
* Create menus.
*/
pMenuProcess = new kMenuBase(IDM_CNR_PROCESS, NULLHANDLE, hwndCnr, TRUE);
pMenuCnrAll = new kMenuBase(IDM_CNR_PROCESS_ALL, NULLHANDLE, hwndCnr, TRUE);
enableSorting();
}
/**
* Destructor.
*/
kProcessContainer::~kProcessContainer()
{
if (pMenuProcess != NULL)
delete pMenuProcess;
if (pMenuCnrAll != NULL)
delete pMenuCnrAll;
}
/**
* Displays the popup menu for the container.
* @param usId Container id.
* @param pRecord Pointer to the record which is selected by either the key
*/
VOID kProcessContainer::cnrContextMenu(USHORT usId, PRECORDCORE pRecord)
{
if (pMenuProcess && pMenuCnrAll)
{
pCurRecord = (kProcessRecord*)pRecord;
setRecordEmphasis(pCurRecord, TRUE, CRA_SOURCE);
if (pRecord != NULL)
pMenuProcess->popup();
else
pMenuCnrAll->popup();
}
usId = usId;
}
/**
* Enter or double click on record in the container.
* This action will bring up the detail dialog for the record.
*/
VOID kProcessContainer::cnrEnter(USHORT usId, HWND hwndCnr, PRECORDCORE pRecord, ULONG fKey)
{
if (pRecord != NULL)
{
pCurRecord = (kProcessRecord*)pRecord;
command(IDM_CNR_PROC_DETAILS, 0, 0);
}
usId = usId;
fKey = fKey;
hwndCnr = hwndCnr;
}
/**
* Updates the contents of the container.
* @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
*/
VOID kProcessContainer::update()
{
/*
* Insert records
*/
if (usPid == 0xFFFF)
kUpdateAllProcesses();
else
kUpdateChildProcesses();
}