source: trunk/src/helpers/procstat.c@ 45

Last change on this file since 45 was 44, checked in by umoeller, 24 years ago

Misc. changes.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 20.0 KB
Line 
1
2/*
3 *@@sourcefile procstat.c:
4 * functions for querying process information.
5 * This is an easy-to-use interface to the
6 * messy 16-bit DosQProcStatus function.
7 *
8 * Usage: All OS/2 programs.
9 *
10 * Function prefixes (new with V0.81):
11 * -- prc* Query Process helper functions
12 *
13 * Based on Kai Uwe Rommel's "dosqproc" package
14 * available at Hobbes:
15 * Kai Uwe Rommel - Wed 25-Mar-1992
16 * Sat 13-Aug-1994
17 *
18 * Note: If you link against procstat.obj, you
19 * need to import the following in your .DEF file:
20 *
21 + IMPORTS
22 + DOSQPROCSTATUS = DOSCALLS.154
23 + DosQuerySysState = DOSCALLS.368
24 *
25 * or linking will fail.
26 *
27 * Note: Version numbering in this file relates to XWorkplace version
28 * numbering.
29 *
30 *@@header "helpers\procstat.h"
31 */
32
33/*
34 * Copyright (C) 1992-1994 Kai Uwe Rommel.
35 * Copyright (C) 1998-2000 Ulrich M”ller.
36 * This file is part of the "XWorkplace helpers" source package.
37 * This is free software; you can redistribute it and/or modify
38 * it under the terms of the GNU General Public License as published
39 * by the Free Software Foundation, in version 2 as it comes in the
40 * "COPYING" file of the XWorkplace main distribution.
41 * This program is distributed in the hope that it will be useful,
42 * but WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44 * GNU General Public License for more details.
45 */
46
47#define OS2EMX_PLAIN_CHAR
48 // this is needed for "os2emx.h"; if this is defined,
49 // emx will define PSZ as _signed_ char, otherwise
50 // as unsigned char
51
52#define INCL_DOSMODULEMGR
53#define INCL_DOSERRORS
54#include <os2.h>
55
56#include <stdlib.h> // already #include'd
57#include <string.h> // already #include'd
58#include <stdio.h>
59
60#include "setup.h" // code generation and debugging options
61
62#include "helpers\procstat.h"
63
64#pragma hdrstop
65
66/*
67 *@@category: Helpers\Control program helpers\Process status\16-bit DosQProcStat
68 */
69
70/********************************************************************
71 *
72 * DosQProcStat (16-bit) interface
73 *
74 ********************************************************************/
75
76/*
77 *@@ prc16GetInfo:
78 * nifty interface to DosQProcStat (16-bit).
79 * This returns the head of a newly
80 * allocated buffer which has plenty
81 * of pointers for subsequent browsing.
82 *
83 * Use prc16FreeInfo to free the buffer.
84 *
85 *@@added V0.9.3 (2000-05-05) [umoeller]
86 */
87
88PQPROCSTAT16 prc16GetInfo(APIRET *parc) // out: error, ptr can be NULL
89{
90 APIRET arc = NO_ERROR;
91 PQPROCSTAT16 pps = (PQPROCSTAT16)malloc(0x8000);
92 if (!pps)
93 arc = ERROR_NOT_ENOUGH_MEMORY;
94 else
95 {
96 arc = DosQProcStatus(pps, 0x8000);
97 if (arc != NO_ERROR)
98 free(pps);
99 }
100
101 if (parc)
102 *parc = arc;
103
104 return (pps);
105}
106
107/*
108 *@@ prc16FreeInfo:
109 * frees memory allocated by prc16GetInfo.
110 *
111 *@@added V0.9.3 (2000-05-05) [umoeller]
112 */
113
114VOID prc16FreeInfo(PQPROCSTAT16 pInfo)
115{
116 if (pInfo)
117 free(pInfo);
118}
119
120/*
121 *@@ prc16FindProcessFromName:
122 * searches the specified buffer for a process
123 * with the specified name and returns a pointer
124 * to its data within pInfo.
125 *
126 * Returns NULL if not found.
127 *
128 *@@added V0.9.3 (2000-05-05) [umoeller]
129 */
130
131PQPROCESS16 prc16FindProcessFromName(PQPROCSTAT16 pInfo, // in: from prc16GetInfo
132 const char *pcszName) // in: e.g. "pmshell.exe"
133{
134 PQPROCESS16 pProcess,
135 pReturn = NULL;
136 if (pInfo)
137 {
138 for ( pProcess = (PQPROCESS16)PTR(pInfo->ulProcesses, 0);
139 pProcess->ulType != 3;
140 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
141 pProcess->usThreads * sizeof(QTHREAD16))
142 )
143 {
144 CHAR szModuleName[CCHMAXPATH];
145 if (DosQueryModuleName(pProcess->usHModule,
146 sizeof(szModuleName),
147 szModuleName)
148 == NO_ERROR)
149 {
150 // the module name is fully qualified, so find the
151 // file name (after the last backslash)
152 PSZ pLastBackslash = strrchr(szModuleName, '\\');
153 if (pLastBackslash)
154 // found:
155 if (stricmp(pLastBackslash + 1, pcszName) == 0)
156 {
157 // matches:
158 pReturn = pProcess;
159 break;
160 }
161 }
162 }
163 }
164
165 return (pReturn);
166}
167
168/*
169 *@@ prc16FindProcessFromPID:
170 * searches the specified buffer for a process
171 * with the specified PID and returns a pointer
172 * to its data within pInfo.
173 *
174 * Returns NULL if not found.
175 *
176 *V0.9.5 (2000-09-29) [umoeller]
177 */
178
179PQPROCESS16 prc16FindProcessFromPID(PQPROCSTAT16 pInfo, // in: from prc16GetInfo
180 ULONG ulPID) // in: PID
181{
182 PQPROCESS16 pProcess,
183 pReturn = NULL;
184 if (pInfo)
185 {
186 for ( pProcess = (PQPROCESS16)PTR(pInfo->ulProcesses, 0);
187 pProcess->ulType != 3;
188 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
189 pProcess->usThreads * sizeof(QTHREAD16))
190 )
191 {
192 if (pProcess->usPID == ulPID)
193 {
194 pReturn = pProcess;
195 break;
196 }
197 }
198 }
199
200 return (pReturn);
201}
202
203/********************************************************************
204 *
205 * DosQProcStat (16-bit) helpers
206 *
207 ********************************************************************/
208
209/*
210 * prcReport16:
211 * fill PRCPROCESS structure
212 */
213
214VOID prcReport16(PQPROCESS16 pProcess, PPRCPROCESS pprcp)
215{
216 if (pProcess)
217 {
218 PQTHREAD16 pThread;
219 int i;
220
221 DosQueryModuleName(pProcess->usHModule,
222 sizeof(pprcp->szModuleName),
223 pprcp->szModuleName);
224 // DosGetPrty(PRTYS_PROCESS, &(pprcp->usPriority), pProcess->usPID);
225
226 // sum up CPU time for process
227 for (pprcp->ulCPU = 0,
228 i = 0,
229 pThread = (PQTHREAD16)PTR(pProcess->ulThreadList, 0);
230 i < pProcess->usThreads;
231 i++, pThread++ )
232 {
233 pprcp->ulCPU += (pThread->ulSysTime + pThread->ulUserTime);
234 }
235
236 pprcp->usPID = pProcess->usPID;
237 pprcp->usParentPID = pProcess->usParentPID;
238 pprcp->usThreads = pProcess->usThreads;
239 pprcp->ulSID = pProcess->ulSID;
240 pprcp->ulSessionType = pProcess->ulSessionType;
241 pprcp->ulStatus = pProcess->ulStatus;
242 }
243}
244
245/*
246 *@@ prc16QueryProcessInfo:
247 * this searches for a given process ID (usPID) and
248 * fills a given PRCPROCESS structure with lots of
249 * information about this process.
250 * Returns FALSE upon errors, e.g. if no process
251 * of that ID is found.
252 */
253
254BOOL prc16QueryProcessInfo(PQPROCSTAT16 pps, // in: from prc16GetInfo
255 USHORT usPID, // in: PID to query
256 PPRCPROCESS pprcp) // out: process info
257{
258 BOOL rc = FALSE;
259 if (pps)
260 {
261 PQPROCESS16 pProcess;
262
263 for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
264 pProcess->ulType != 3;
265 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
266 pProcess->usThreads * sizeof(QTHREAD16))
267 )
268 {
269 if (pProcess->usPID == usPID)
270 {
271 prcReport16(pProcess, pprcp);
272 rc = TRUE;
273 break;
274 }
275 }
276 }
277
278 return (rc);
279}
280
281/*
282 *@@ prc16ForEachProcess:
283 * this calls a given callback func for each running
284 * process. The callback must be a FNWP, which will be
285 * passed the following parameters for each call:
286 * -- HWND hwnd: like hwnd passed to this func
287 * -- ULONG msg: like msg passed to this func
288 * -- MPARAM mp1: like mp1 passed to this func
289 * -- PPRCPROCESS: mp2 pointer to a PRCPROCESS struct for each process
290 *
291 * This function returns the number of running processes on the
292 * system. If pfnwpCallback is NULL, only this number will be
293 * returned, so you can use this as a process counter too.
294 */
295
296ULONG prc16ForEachProcess(PFNWP pfnwpCallback, HWND hwnd, ULONG ulMsg, MPARAM mp1)
297{
298 ULONG ulrc = 0;
299 PQPROCESS16 pProcess;
300 PRCPROCESS prcp;
301 PQPROCSTAT16 pps = (PQPROCSTAT16)malloc(0x8000);
302 DosQProcStatus(pps, 0x8000);
303
304 for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
305 pProcess->ulType != 3;
306 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
307 pProcess->usThreads * sizeof(QTHREAD16))
308 )
309 {
310 if (pfnwpCallback)
311 {
312 prcReport16(pProcess, &prcp);
313 (*pfnwpCallback)(hwnd, ulMsg, mp1, &prcp);
314 }
315 ulrc++;
316 }
317
318 free(pps);
319 return (ulrc);
320}
321
322/*
323 *@@ prc16QueryThreadCount:
324 * returns the total number of running threads
325 * in the given process. If pid == 0, the
326 * total thread count for the system is returned.
327 *
328 *@@changed V0.9.9 (2001-03-07) [umoeller]: added pps param
329 */
330
331ULONG prc16QueryThreadCount(PQPROCSTAT16 pps, // in: from prc16GetInfo
332 USHORT usPID)
333{
334 ULONG ulrc = 0;
335
336 if (pps)
337 {
338 if (usPID)
339 {
340 // process query:
341 PQPROCESS16 pProcess;
342 for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
343 pProcess->ulType != 3;
344 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
345 pProcess->usThreads * sizeof(QTHREAD16))
346 )
347 {
348 if (pProcess->usPID == usPID)
349 {
350 ulrc = pProcess->usThreads;
351 break;
352 }
353 }
354 }
355 else
356 {
357 // global query:
358 PQGLOBAL16 pg;
359 pg = (PQGLOBAL16)PTR(pps->ulGlobal, 0);
360 ulrc = pg->ulThreads;
361 }
362 }
363
364 return (ulrc);
365}
366
367/*
368 *@@ prc16QueryThreadInfo:
369 * this searches for a given thread in a given process
370 * and fills a given PRCTHREAD structure with lots of
371 * information about that thread.
372 *
373 * Returns FALSE upon errors.
374 *
375 * Note: This function loops thru all processes which
376 * are currently running and is therefore not terribly
377 * fast. Use economically.
378 *
379 *@@changed V0.9.9 (2001-03-07) [umoeller]: added pps param
380 */
381
382BOOL prc16QueryThreadInfo(PQPROCSTAT16 pps, // in: from prc16GetInfo
383 USHORT usPID,
384 USHORT usTID,
385 PPRCTHREAD pprct)
386{
387 BOOL brc = FALSE;
388 if (pps)
389 {
390 PQPROCESS16 pProcess;
391
392 // find process:
393 for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
394 pProcess->ulType != 3;
395 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
396 pProcess->usThreads * sizeof(QTHREAD16))
397 )
398 {
399 if (pProcess->usPID == usPID)
400 {
401 PQTHREAD16 pThread;
402 int i;
403 // process found: find thread
404 for ( i = 0, pThread = (PQTHREAD16)PTR(pProcess->ulThreadList, 0);
405 i < pProcess->usThreads;
406 i++, pThread++ )
407 {
408 if (pThread->usTID == usTID)
409 {
410 // thread found:
411 pprct->usTID = pThread->usTID;
412 pprct->usThreadSlotID = pThread->usThreadSlotID;
413 pprct->ulBlockID = pThread->ulBlockID;
414 pprct->ulPriority = pThread->ulPriority;
415 pprct->ulSysTime = pThread->ulSysTime;
416 pprct->ulUserTime = pThread->ulUserTime;
417 pprct->ucStatus = pThread->ucStatus;
418
419 brc = TRUE;
420
421 break; // thread-for loop
422 }
423 } // end for thread
424 break; // process-for loop
425 }
426 } // end for process
427 }
428
429 return (brc);
430}
431
432/*
433 *@@ prcQueryPriority:
434 * shortcut to prc16QueryThreadInfo if you want the priority only.
435 *
436 * Returns -1 upon errors.
437 *
438 * Note: This function loops thru all processes which
439 * are currently running and is therefore not terribly
440 * fast. Use economically.
441 *
442 *@@changed V0.9.9 (2001-03-07) [umoeller]: added pps param
443 */
444
445ULONG prc16QueryThreadPriority(PQPROCSTAT16 pps, // in: from prc16GetInfo
446 USHORT usPID,
447 USHORT usTID)
448{
449 PRCTHREAD prct;
450 ULONG ulrc = -1;
451 if (prc16QueryThreadInfo(pps, usPID, usTID, &prct))
452 ulrc = prct.ulPriority;
453 return (ulrc);
454}
455
456/*
457 *@@category: Helpers\Control program helpers\Process status\32-bit DosQuerySysState
458 */
459
460/********************************************************************
461 *
462 * DosQuerySysState (32-bit) interface
463 *
464 ********************************************************************/
465
466/*
467 *@@ prc32GetInfo:
468 * nifty interface to DosQuerySysState,
469 * the 32-bit version of DosQProcStat.
470 * This returns the head of a newly
471 * allocated buffer which has plenty
472 * of pointers for subsequent browing.
473 *
474 * Use prc32FreeInfo to free the buffer.
475 *
476 *@@added V0.9.1 (2000-02-12) [umoeller]
477 *@@changed V0.9.3 (2000-05-01) [umoeller]: now using DosAllocMem
478 */
479
480PQTOPLEVEL32 prc32GetInfo(APIRET *parc) // out: error, ptr can be NULL
481{
482 #define BUFSIZE 128000l
483 PCHAR pBuf = NULL; // (PCHAR)malloc(BUFSIZE);
484
485 if (DosAllocMem((PVOID*)&pBuf,
486 BUFSIZE,
487 PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE)
488 == NO_ERROR)
489 if (pBuf)
490 {
491 APIRET arc = DosQuerySysState(0x1f,
492 0, 0, 0,
493 (PCHAR)pBuf,
494 BUFSIZE);
495 if (parc)
496 *parc = arc;
497
498 if (arc == NO_ERROR)
499 return ((PQTOPLEVEL32)pBuf);
500 else
501 DosFreeMem(pBuf);
502 }
503
504 return (NULL);
505}
506
507/*
508 *@@ prc32FreeInfo:
509 * frees the memory allocated by prc32GetInfo.
510 *
511 *@@added V0.9.1 (2000-02-12) [umoeller]
512 *@@changed V0.9.3 (2000-05-01) [umoeller]: now using DosAllocMem
513 */
514
515VOID prc32FreeInfo(PQTOPLEVEL32 pInfo)
516{
517 DosFreeMem(pInfo);;
518}
519
520/*
521 *@@ prc32FindProcessFromName:
522 *
523 *@@added V0.9.2 (2000-03-05) [umoeller]
524 */
525
526PQPROCESS32 prc32FindProcessFromName(PQTOPLEVEL32 pInfo,
527 const char *pcszName) // in: e.g. "pmshell.exe"
528{
529 PQPROCESS32 pProcThis = pInfo->pProcessData;
530 while (pProcThis && pProcThis->rectype == 1)
531 {
532 int i;
533 PQTHREAD32 t = pProcThis->pThreads;
534 PQMODULE32 pModule = prc32FindModule(pInfo,
535 pProcThis->usHModule);
536
537 if (pModule)
538 {
539 // the module name is fully qualified, so find the
540 // file name (after the last backslash)
541 if (pModule->pcName)
542 {
543 PSZ pLastBackslash = strrchr(pModule->pcName, '\\');
544 if (pLastBackslash)
545 // found:
546 if (stricmp(pLastBackslash + 1, pcszName) == 0)
547 // matches:
548 break;
549 }
550 }
551
552 // for next process, skip the threads info;
553 // the next process block comes after the
554 // threads
555 for (i=0;
556 i < pProcThis->usThreadCount;
557 i++,t++)
558 ;
559
560 pProcThis = (PQPROCESS32)t;
561 }
562
563 if (pProcThis->rectype == 1)
564 return (pProcThis);
565 else
566 return (NULL);
567}
568
569/*
570 *@@ prc32FindSem16:
571 * attempts to find the specified 16-bit semaphore
572 * in the specified info buffer.
573 *
574 * The return value points into the pInfo buffer.
575 * Returns NULL if not found.
576 *
577 *@@added V0.9.1 (2000-02-12) [umoeller]
578 */
579
580PQSEMA32 prc32FindSem16(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
581 USHORT usSemID) // in: as in QPROCESS32.pausSem16
582{
583 PQSEM16STRUC32 pSemData = pInfo->pSem16Data;
584 PQSEMA32 pSemThis = &pSemData->sema;
585 ULONG i = 0;
586
587 while (pSemThis)
588 {
589 _Pmpf(("prc32FindSem16: found usIndex 0x%lX", pSemThis->usIndex));
590 if (/* pSemThis->usIndex */ i == usSemID)
591 return (pSemThis);
592
593 i++;
594 pSemThis = pSemThis->pNext;
595 }
596
597 return (NULL);
598}
599
600/*
601 *@@ prc32FindSem32:
602 * attempts to find the specified 32-bit semaphore
603 * in the specified info buffer. This might fail
604 * because the data isn't always complete.
605 *
606 * The return value points into the pInfo buffer.
607 * Returns NULL if not found.
608 *
609 *@@added V0.9.1 (2000-02-12) [umoeller]
610 */
611
612PQSEM32STRUC32 prc32FindSem32(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
613 USHORT usSemID) // in: as in QPROCESS32.pausSem16
614{
615 // PQSEM32STRUC32 pSemThis = pInfo->pSem32Data;
616
617 /* while (pSemThis)
618 {
619 if (pSemThis->usIndex == usSemID)
620 return (pSemThis);
621
622 pSemThis = pSemThis->pNext;
623 } */
624
625 return (NULL);
626}
627
628/*
629 *@@ prc32FindShrMem:
630 * attempts to find the specified shared memory
631 * block description.
632 *
633 * The return value points into the pInfo buffer.
634 * Returns NULL if not found.
635 *
636 *@@added V0.9.1 (2000-02-12) [umoeller]
637 */
638
639PQSHRMEM32 prc32FindShrMem(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
640 USHORT usShrMemID) // in: as in QPROCESS32.pausShrMems
641{
642 PQSHRMEM32 pShrMem = pInfo->pShrMemData;
643 while (pShrMem)
644 {
645 if (pShrMem->usHandle == usShrMemID)
646 return (pShrMem);
647 pShrMem = pShrMem->pNext;
648 }
649
650 return (NULL);
651}
652
653/*
654 *@@ prc32FindModule:
655 * attempts to find the specified module description.
656 *
657 * The return value points into the pInfo buffer.
658 * Returns NULL if not found.
659 *
660 *@@added V0.9.1 (2000-02-12) [umoeller]
661 */
662
663PQMODULE32 prc32FindModule(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
664 USHORT usHModule)
665{
666 PQMODULE32 pModule = pInfo->pModuleData;
667 while (pModule)
668 {
669 if (pModule->usHModule == usHModule)
670 return (pModule);
671 pModule = pModule->pNext;
672 }
673
674 return (NULL);
675}
676
677/*
678 *@@ prc32FindFileData:
679 *
680 *
681 *@@added V0.9.1 (2000-02-12) [umoeller]
682 */
683
684PQFILEDATA32 prc32FindFileData(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
685 USHORT usFileID) // in: as in QPROCESS32.pausFds
686{
687 PQFILEDATA32 pFile = pInfo->pFileData;
688 while ( (pFile)
689 && (pFile->rectype == 8) // this is necessary, we'll crash otherwise!!
690 )
691 {
692 if (pFile->filedata->sfn == usFileID)
693 return (pFile);
694
695 pFile = pFile->pNext;
696 }
697
698 return (NULL);
699}
700
701
Note: See TracBrowser for help on using the repository browser.