home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
xwphescr.zip
/
XWPH0208.ZIP
/
src
/
helpers
/
procstat.c
< prev
next >
Wrap
C/C++ Source or Header
|
2002-06-05
|
23KB
|
750 lines
/*
*@@sourcefile procstat.c:
* functions for querying process information.
* This is an easy-to-use interface to the
* messy 16-bit DosQProcStatus function.
*
* Usage: All OS/2 programs.
*
* Function prefixes (new with V0.81):
* -- prc* Query Process helper functions
*
* Based on Kai Uwe Rommel's "dosqproc" package
* available at Hobbes:
* Kai Uwe Rommel - Wed 25-Mar-1992
* Sat 13-Aug-1994
*
* Note: If you link against procstat.obj, you
* need to import the following in your .DEF file:
*
+ IMPORTS
+ DOSQPROCSTATUS = DOSCALLS.154
+ DosQuerySysState = DOSCALLS.368
*
* or linking will fail.
*
* Note: Version numbering in this file relates to XWorkplace version
* numbering.
*
*@@header "helpers\procstat.h"
*/
/*
* Copyright (C) 1992-1994 Kai Uwe Rommel.
* Copyright (C) 1998-2000 Ulrich Möller.
* This file is part of the "XWorkplace helpers" source package.
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, in version 2 as it comes in the
* "COPYING" file of the XWorkplace main distribution.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#define OS2EMX_PLAIN_CHAR
// this is needed for "os2emx.h"; if this is defined,
// emx will define PSZ as _signed_ char, otherwise
// as unsigned char
#define INCL_DOSMODULEMGR
#define INCL_DOSERRORS
#include <os2.h>
#include <stdlib.h> // already #include'd
#include <string.h> // already #include'd
#include <stdio.h>
#include "setup.h" // code generation and debugging options
#include "helpers\procstat.h"
#pragma hdrstop
/*
*@@category: Helpers\Control program helpers\Process status\16-bit DosQProcStat
*/
/********************************************************************
*
* DosQProcStat (16-bit) interface
*
********************************************************************/
/*
*@@ prc16GetInfo:
* nifty interface to DosQProcStat (16-bit).
* This returns the head of a newly
* allocated buffer which has plenty
* of pointers for subsequent browsing.
*
* Use prc16FreeInfo to free the buffer.
*
*@@added V0.9.3 (2000-05-05) [umoeller]
*@@changed V0.9.10 (2001-04-08) [umoeller]: this returned != NULL even though item was freed, fixed
*@@changed V0.9.10 (2001-04-08) [umoeller]: now using DosAllocMem, raised bufsize, changed prototype
*/
APIRET prc16GetInfo(PQPROCSTAT16 *ppps) // out: error, ptr can be NULL
{
APIRET arc = NO_ERROR;
PQPROCSTAT16 pps = NULL;
/* PQPROCSTAT16 pps = (PQPROCSTAT16)malloc(0x8000);
if (!pps)
arc = ERROR_NOT_ENOUGH_MEMORY;
else */
if (!ppps)
return (ERROR_INVALID_PARAMETER);
// changed allocation V0.9.10 (2001-04-08) [umoeller]:
// malloc didn't guarantee that the object did not
// cross a 64K boundary, which could cause DosQProcStat
// to fail...
#define BUF_SIZE 0xFFFF // raised from 0x8000
if (!(arc = DosAllocMem((VOID**)&pps,
BUF_SIZE,
PAG_READ | PAG_WRITE | PAG_COMMIT
| OBJ_TILE // 16-bit compatible, ignored really
)))
{
if (arc = DosQProcStatus(pps, BUF_SIZE))
{
// error:
DosFreeMem(pps); // V0.9.10 (2001-04-08) [umoeller]
// and even worse, I forgot to set the return ptr
// to NULL, so this was freed twice... I guess
// this produced the crashes in WarpIN with the
// KILLPROCESS attribute... V0.9.10 (2001-04-08) [umoeller]
pps = NULL;
}
}
*ppps = pps;
return arc;
}
/*
*@@ prc16FreeInfo:
* frees memory allocated by prc16GetInfo.
*
*@@added V0.9.3 (2000-05-05) [umoeller]
*@@changed V0.9.10 (2001-04-08) [umoeller]: now using DosFreeMem
*/
APIRET prc16FreeInfo(PQPROCSTAT16 pInfo)
{
if (!pInfo)
return ERROR_INVALID_PARAMETER;
return DosFreeMem(pInfo);
}
/*
*@@ prc16FindProcessFromName:
* searches the specified buffer for a process
* with the specified name and returns a pointer
* to its data within pInfo.
*
* Returns NULL if not found.
*
*@@added V0.9.3 (2000-05-05) [umoeller]
*/
PQPROCESS16 prc16FindProcessFromName(PQPROCSTAT16 pInfo, // in: from prc16GetInfo
const char *pcszName) // in: e.g. "pmshell.exe"
{
PQPROCESS16 pProcess,
pReturn = NULL;
if (pInfo)
{
for ( pProcess = (PQPROCESS16)PTR(pInfo->ulProcesses, 0);
pProcess->ulType != 3;
pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
pProcess->usThreads * sizeof(QTHREAD16))
)
{
CHAR szModuleName[CCHMAXPATH];
if (DosQueryModuleName(pProcess->usHModule,
sizeof(szModuleName),
szModuleName)
== NO_ERROR)
{
// the module name is fully qualified, so find the
// file name (after the last backslash)
PSZ pLastBackslash = strrchr(szModuleName, '\\');
if (pLastBackslash)
// found:
if (stricmp(pLastBackslash + 1, pcszName) == 0)
{
// matches:
pReturn = pProcess;
break;
}
}
}
}
return (pReturn);
}
/*
*@@ prc16FindProcessFromPID:
* searches the specified buffer for a process
* with the specified PID and returns a pointer
* to its data within pInfo.
*
* Returns NULL if not found.
*
*V0.9.5 (2000-09-29) [umoeller]
*/
PQPROCESS16 prc16FindProcessFromPID(PQPROCSTAT16 pInfo, // in: from prc16GetInfo
ULONG ulPID) // in: PID
{
PQPROCESS16 pProcess,
pReturn = NULL;
if (pInfo)
{
for ( pProcess = (PQPROCESS16)PTR(pInfo->ulProcesses, 0);
pProcess->ulType != 3;
pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
pProcess->usThreads * sizeof(QTHREAD16))
)
{
if (pProcess->usPID == ulPID)
{
pReturn = pProcess;
break;
}
}
}
return (pReturn);
}
/********************************************************************
*
* DosQProcStat (16-bit) helpers
*
********************************************************************/
/*
* prcReport16:
* fill PRCPROCESS structure
*/
VOID prcReport16(PQPROCESS16 pProcess, PPRCPROCESS pprcp)
{
if (pProcess)
{
PQTHREAD16 pThread;
int i;
DosQueryModuleName(pProcess->usHModule,
sizeof(pprcp->szModuleName),
pprcp->szModuleName);
// DosGetPrty(PRTYS_PROCESS, &(pprcp->usPriority), pProcess->usPID);
// sum up CPU time for process
for (pprcp->ulCPU = 0,
i = 0,
pThread = (PQTHREAD16)PTR(pProcess->ulThreadList, 0);
i < pProcess->usThreads;
i++, pThread++ )
{
pprcp->ulCPU += (pThread->ulSysTime + pThread->ulUserTime);
}
pprcp->usPID = pProcess->usPID;
pprcp->usParentPID = pProcess->usParentPID;
pprcp->usThreads = pProcess->usThreads;
pprcp->ulSID = pProcess->ulSID;
pprcp->ulSessionType = pProcess->ulSessionType;
pprcp->ulStatus = pProcess->ulStatus;
}
}
/*
*@@ prc16QueryProcessInfo:
* this searches for a given process ID (usPID) and
* fills a given PRCPROCESS structure with lots of
* information about this process.
* Returns FALSE upon errors, e.g. if no process
* of that ID is found.
*/
BOOL prc16QueryProcessInfo(PQPROCSTAT16 pps, // in: from prc16GetInfo
USHORT usPID, // in: PID to query
PPRCPROCESS pprcp) // out: process info
{
BOOL rc = FALSE;
if (pps)
{
PQPROCESS16 pProcess;
for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
pProcess->ulType != 3;
pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
pProcess->usThreads * sizeof(QTHREAD16))
)
{
if (pProcess->usPID == usPID)
{
prcReport16(pProcess, pprcp);
rc = TRUE;
break;
}
}
}
return (rc);
}
/*
*@@ prc16ForEachProcess:
* this calls a given callback func for each running
* process. The callback must be a FNWP, which will be
* passed the following parameters for each call:
* -- HWND hwnd: like hwnd passed to this func
* -- ULONG msg: like msg passed to this func
* -- MPARAM mp1: like mp1 passed to this func
* -- PPRCPROCESS: mp2 pointer to a PRCPROCESS struct for each process
*
* This function returns the number of running processes on the
* system. If pfnwpCallback is NULL, only this number will be
* returned, so you can use this as a process counter too.
*
*@@changed V0.9.10 (2001-04-16) [pr]: now using DosAllocMem
*/
ULONG prc16ForEachProcess(PFNWP pfnwpCallback, HWND hwnd, ULONG ulMsg, MPARAM mp1)
{
ULONG ulrc = 0;
PQPROCSTAT16 pps;
PQPROCESS16 pProcess;
PRCPROCESS prcp;
if (!DosAllocMem((PVOID*)&pps,
BUF_SIZE,
PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE))
{
if (!DosQProcStatus(pps, BUF_SIZE))
for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
pProcess->ulType != 3;
pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
pProcess->usThreads * sizeof(QTHREAD16))
)
{
if (pfnwpCallback)
{
prcReport16(pProcess, &prcp);
(*pfnwpCallback)(hwnd, ulMsg, mp1, &prcp);
}
ulrc++;
}
DosFreeMem(pps);
}
return (ulrc);
}
/*
*@@ prc16QueryThreadCount:
* returns the total number of running threads
* in the given process. If pid == 0, the
* total thread count for the system is returned.
*
*@@changed V0.9.9 (2001-03-07) [umoeller]: added pps param
*/
ULONG prc16QueryThreadCount(PQPROCSTAT16 pps, // in: from prc16GetInfo
USHORT usPID)
{
ULONG ulrc = 0;
if (pps)
{
if (usPID)
{
// process query:
PQPROCESS16 pProcess;
for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
pProcess->ulType != 3;
pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
pProcess->usThreads * sizeof(QTHREAD16))
)
{
if (pProcess->usPID == usPID)
{
ulrc = pProcess->usThreads;
break;
}
}
}
else
{
// global query:
PQGLOBAL16 pg;
pg = (PQGLOBAL16)PTR(pps->ulGlobal, 0);
ulrc = pg->ulThreads;
}
}
return (ulrc);
}
/*
*@@ prc16QueryThreadInfo:
* this searches for a given thread in a given process
* and fills a given PRCTHREAD structure with lots of
* information about that thread.
*
* Returns FALSE upon errors.
*
* Note: This function loops thru all processes which
* are currently running and is therefore not terribly
* fast. Use economically.
*
*@@changed V0.9.9 (2001-03-07) [umoeller]: added pps param
*/
BOOL prc16QueryThreadInfo(PQPROCSTAT16 pps, // in: from prc16GetInfo
USHORT usPID,
USHORT usTID,
PPRCTHREAD pprct)
{
BOOL brc = FALSE;
if (pps)
{
PQPROCESS16 pProcess;
// find process:
for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
pProcess->ulType != 3;
pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
pProcess->usThreads * sizeof(QTHREAD16))
)
{
if (pProcess->usPID == usPID)
{
PQTHREAD16 pThread;
int i;
// process found: find thread
for ( i = 0, pThread = (PQTHREAD16)PTR(pProcess->ulThreadList, 0);
i < pProcess->usThreads;
i++, pThread++ )
{
if (pThread->usTID == usTID)
{
// thread found:
pprct->usTID = pThread->usTID;
pprct->usThreadSlotID = pThread->usThreadSlotID;
pprct->ulBlockID = pThread->ulBlockID;
pprct->ulPriority = pThread->ulPriority;
pprct->ulSysTime = pThread->ulSysTime;
pprct->ulUserTime = pThread->ulUserTime;
pprct->ucStatus = pThread->ucStatus;
brc = TRUE;
break; // thread-for loop
}
} // end for thread
break; // process-for loop
}
} // end for process
}
return brc;
}
/*
*@@ prcQueryPriority:
* shortcut to prc16QueryThreadInfo if you want the priority only.
*
* Returns -1 upon errors.
*
* Note: This function loops thru all processes which
* are currently running and is therefore not terribly
* fast. Use economically.
*
*@@changed V0.9.9 (2001-03-07) [umoeller]: added pps param
*/
ULONG prc16QueryThreadPriority(PQPROCSTAT16 pps, // in: from prc16GetInfo
USHORT usPID,
USHORT usTID)
{
PRCTHREAD prct;
ULONG ulrc = -1;
if (prc16QueryThreadInfo(pps, usPID, usTID, &prct))
ulrc = prct.ulPriority;
return (ulrc);
}
/*
*@@category: Helpers\Control program helpers\Process status\32-bit DosQuerySysState
*/
/********************************************************************
*
* DosQuerySysState (32-bit) interface
*
********************************************************************/
/*
*@@ prc32GetInfo:
* nifty interface to DosQuerySysState,
* the 32-bit version of DosQProcStat.
* This returns the head of a newly
* allocated buffer which has plenty
* of pointers for subsequent browing.
*
* Use prc32FreeInfo to free the buffer.
*
*@@added V0.9.1 (2000-02-12) [umoeller]
*@@changed V0.9.3 (2000-05-01) [umoeller]: now using DosAllocMem
*@@changed V0.9.10 (2001-04-08) [umoeller]: fixed second QuerySysState param
*/
PQTOPLEVEL32 prc32GetInfo(APIRET *parc) // out: error, ptr can be NULL
{
#define BUFSIZE (256 * 1024) // 128000l
PCHAR pBuf = NULL; // (PCHAR)malloc(BUFSIZE);
if (DosAllocMem((PVOID*)&pBuf,
BUFSIZE,
PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE)
== NO_ERROR)
if (pBuf)
{
APIRET arc = DosQuerySysState(QS32_SUPPORTED,
QS32_SUPPORTED, // this was missing
// V0.9.10 (2001-04-08) [umoeller]
0, 0,
(PCHAR)pBuf,
BUFSIZE);
if (parc)
*parc = arc;
if (arc == NO_ERROR)
return ((PQTOPLEVEL32)pBuf);
else
DosFreeMem(pBuf);
}
return NULL;
}
/*
*@@ prc32FreeInfo:
* frees the memory allocated by prc32GetInfo.
*
*@@added V0.9.1 (2000-02-12) [umoeller]
*@@changed V0.9.3 (2000-05-01) [umoeller]: now using DosFreeMem
*/
VOID prc32FreeInfo(PQTOPLEVEL32 pInfo)
{
DosFreeMem(pInfo);
}
/*
*@@ prc32FindProcessFromName:
*
*@@added V0.9.2 (2000-03-05) [umoeller]
*/
PQPROCESS32 prc32FindProcessFromName(PQTOPLEVEL32 pInfo,
const char *pcszName) // in: e.g. "pmshell.exe"
{
PQPROCESS32 pProcThis = pInfo->pProcessData;
while (pProcThis && pProcThis->ulRecType == 1)
{
int i;
PQTHREAD32 t = pProcThis->pThreads;
PQMODULE32 pModule = prc32FindModule(pInfo,
pProcThis->usHModule);
if (pModule)
{
// the module name is fully qualified, so find the
// file name (after the last backslash)
if (pModule->pcName)
{
PSZ pLastBackslash = strrchr(pModule->pcName, '\\');
if (pLastBackslash)
// found:
if (stricmp(pLastBackslash + 1, pcszName) == 0)
// matches:
break;
}
}
// for next process, skip the threads info;
// the next process block comes after the
// threads
for (i=0;
i < pProcThis->usThreadCount;
i++,t++)
;
pProcThis = (PQPROCESS32)t;
}
if (pProcThis->ulRecType == 1)
return (pProcThis);
else
return NULL;
}
/*
*@@ prc32FindSem16:
* attempts to find the specified 16-bit semaphore
* in the specified info buffer.
*
* The return value points into the pInfo buffer.
* Returns NULL if not found.
*
*@@added V0.9.1 (2000-02-12) [umoeller]
*/
PQS32SEM16 prc32FindSem16(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
USHORT usSemID) // in: as in QPROCESS32.pausSem16
{
PQS32SEM16HEAD pSemHead = pInfo->pSem16Data;
PQS32SEM16 // pSemThis = &pSemData->sema;
pSemThis = &pSemHead->Sem16Rec;
ULONG i = 0;
while (pSemThis)
{
if (i == usSemID)
return (pSemThis);
i++;
pSemThis = pSemThis->pNext;
}
return NULL;
}
/*
*@@ prc32FindSem32:
* attempts to find the specified 32-bit semaphore
* in the specified info buffer. This might fail
* because the data isn't always complete.
*
* The return value points into the pInfo buffer.
* Returns NULL if not found.
*
*@@added V0.9.1 (2000-02-12) [umoeller]
*/
PQS32SEM32 prc32FindSem32(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
USHORT usSemID) // in: as in QPROCESS32.pausSem16
{
// PQSEM32STRUC32 pSemThis = pInfo->pSem32Data;
/* while (pSemThis)
{
if (pSemThis->usIndex == usSemID)
return (pSemThis);
pSemThis = pSemThis->pNext;
} */
return NULL;
}
/*
*@@ prc32FindShrMem:
* attempts to find the specified shared memory
* block description.
*
* The return value points into the pInfo buffer.
* Returns NULL if not found.
*
*@@added V0.9.1 (2000-02-12) [umoeller]
*/
PQSHRMEM32 prc32FindShrMem(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
USHORT usShrMemID) // in: as in QPROCESS32.pausShrMems
{
PQSHRMEM32 pShrMem = pInfo->pShrMemData;
while (pShrMem)
{
if (pShrMem->usHandle == usShrMemID)
return (pShrMem);
pShrMem = pShrMem->pNext;
}
return NULL;
}
/*
*@@ prc32FindModule:
* attempts to find the specified module description.
*
* The return value points into the pInfo buffer.
* Returns NULL if not found.
*
*@@added V0.9.1 (2000-02-12) [umoeller]
*/
PQMODULE32 prc32FindModule(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
USHORT usHModule)
{
PQMODULE32 pModule = pInfo->pModuleData;
while (pModule)
{
if (pModule->usHModule == usHModule)
return (pModule);
pModule = pModule->pNext;
}
return NULL;
}
/*
*@@ prc32FindFileData:
*
*
*@@added V0.9.1 (2000-02-12) [umoeller]
*/
PQFILEDATA32 prc32FindFileData(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
USHORT usFileID) // in: as in QPROCESS32.pausFds
{
PQFILEDATA32 pFile = pInfo->pFileData;
while ( (pFile)
&& (pFile->ulRecType == 8) // this is necessary, we'll crash otherwise!!
)
{
ULONG ul;
// for some reason, there is an array in the file struct,
// so search the array for the SFN
for (ul = 0;
ul < pFile->ulCFiles;
ul++)
{
if (pFile->paFiles[ul].usSFN == usFileID)
return (pFile);
}
pFile = pFile->pNext;
}
return NULL;
}