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

Last change on this file since 35 was 14, checked in by umoeller, 25 years ago

Major updates; timers, LVM, miscellaneous.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 19.1 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 free(pInfo);
117}
118
119/*
120 *@@ prc16FindProcessFromName:
121 * searches the specified buffer for a process
122 * with the specified name and returns a pointer
123 * to its data within pInfo.
124 *
125 * Returns NULL if not found.
126 *
127 *@@added V0.9.3 (2000-05-05) [umoeller]
128 */
129
130PQPROCESS16 prc16FindProcessFromName(PQPROCSTAT16 pInfo, // in: from prc16GetInfo
131 const char *pcszName) // in: e.g. "pmshell.exe"
132{
133 PQPROCESS16 pProcess,
134 pReturn = NULL;
135 for ( pProcess = (PQPROCESS16)PTR(pInfo->ulProcesses, 0);
136 pProcess->ulType != 3;
137 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
138 pProcess->usThreads * sizeof(QTHREAD16))
139 )
140 {
141 CHAR szModuleName[CCHMAXPATH];
142 if (DosQueryModuleName(pProcess->usHModule,
143 sizeof(szModuleName),
144 szModuleName)
145 == NO_ERROR)
146 {
147 // the module name is fully qualified, so find the
148 // file name (after the last backslash)
149 PSZ pLastBackslash = strrchr(szModuleName, '\\');
150 if (pLastBackslash)
151 // found:
152 if (stricmp(pLastBackslash + 1, pcszName) == 0)
153 {
154 // matches:
155 pReturn = pProcess;
156 break;
157 }
158 }
159 }
160
161 return (pReturn);
162}
163
164/*
165 *@@ prc16FindProcessFromPID:
166 * searches the specified buffer for a process
167 * with the specified PID and returns a pointer
168 * to its data within pInfo.
169 *
170 * Returns NULL if not found.
171 *
172 *V0.9.5 (2000-09-29) [umoeller]
173 */
174
175PQPROCESS16 prc16FindProcessFromPID(PQPROCSTAT16 pInfo, // in: from prc16GetInfo
176 ULONG ulPID) // in: PID
177{
178 PQPROCESS16 pProcess,
179 pReturn = NULL;
180 for ( pProcess = (PQPROCESS16)PTR(pInfo->ulProcesses, 0);
181 pProcess->ulType != 3;
182 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
183 pProcess->usThreads * sizeof(QTHREAD16))
184 )
185 {
186 if (pProcess->usPID == ulPID)
187 {
188 pReturn = pProcess;
189 break;
190 }
191 }
192
193 return (pReturn);
194}
195
196/********************************************************************
197 *
198 * DosQProcStat (16-bit) helpers
199 *
200 ********************************************************************/
201
202/*
203 * prcReport16:
204 * fill PRCPROCESS structure
205 */
206
207VOID prcReport16(PQPROCESS16 pProcess, PPRCPROCESS pprcp)
208{
209 // USHORT usPriority = 0;
210 PQTHREAD16 pThread;
211 int i;
212
213 DosQueryModuleName(pProcess->usHModule,
214 sizeof(pprcp->szModuleName),
215 pprcp->szModuleName);
216 // DosGetPrty(PRTYS_PROCESS, &(pprcp->usPriority), pProcess->usPID);
217
218 // sum up CPU time for process
219 for (pprcp->ulCPU = 0,
220 i = 0,
221 pThread = (PQTHREAD16)PTR(pProcess->ulThreadList, 0);
222 i < pProcess->usThreads;
223 i++, pThread++ )
224 {
225 pprcp->ulCPU += (pThread->ulSysTime + pThread->ulUserTime);
226 }
227
228 pprcp->usPID = pProcess->usPID;
229 pprcp->usParentPID = pProcess->usParentPID;
230 pprcp->usThreads = pProcess->usThreads;
231 pprcp->ulSID = pProcess->ulSID;
232 pprcp->ulSessionType = pProcess->ulSessionType;
233 pprcp->ulStatus = pProcess->ulStatus;
234}
235
236/*
237 *@@ prc16QueryProcessInfo:
238 * this searches for a given process ID (usPID) and
239 * fills a given PRCPROCESS structure with lots of
240 * information about this process.
241 * Returns FALSE upon errors, e.g. if no process
242 * of that ID is found.
243 */
244
245BOOL prc16QueryProcessInfo(USHORT usPID, // in: PID to query
246 PPRCPROCESS pprcp) // out: process info
247{
248 BOOL rc = FALSE;
249 PQPROCESS16 pProcess;
250 PQPROCSTAT16 pps = (PQPROCSTAT16)malloc(0x8000);
251 DosQProcStatus(pps, 0x8000);
252
253 for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
254 pProcess->ulType != 3;
255 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
256 pProcess->usThreads * sizeof(QTHREAD16))
257 )
258 {
259 if (pProcess->usPID == usPID)
260 {
261 prcReport16(pProcess, pprcp);
262 rc = TRUE;
263 break;
264 }
265 }
266
267 free(pps);
268 return (rc);
269}
270
271/*
272 *@@ prc16ForEachProcess:
273 * this calls a given callback func for each running
274 * process. The callback must be a FNWP, which will be
275 * passed the following parameters for each call:
276 * -- HWND hwnd: like hwnd passed to this func
277 * -- ULONG msg: like msg passed to this func
278 * -- MPARAM mp1: like mp1 passed to this func
279 * -- PPRCPROCESS: mp2 pointer to a PRCPROCESS struct for each process
280 *
281 * This function returns the number of running processes on the
282 * system. If pfnwpCallback is NULL, only this number will be
283 * returned, so you can use this as a process counter too.
284 */
285
286ULONG prc16ForEachProcess(PFNWP pfnwpCallback, HWND hwnd, ULONG ulMsg, MPARAM mp1)
287{
288 ULONG ulrc = 0;
289 PQPROCESS16 pProcess;
290 PRCPROCESS prcp;
291 PQPROCSTAT16 pps = (PQPROCSTAT16)malloc(0x8000);
292 DosQProcStatus(pps, 0x8000);
293
294 for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
295 pProcess->ulType != 3;
296 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
297 pProcess->usThreads * sizeof(QTHREAD16))
298 )
299 {
300 if (pfnwpCallback)
301 {
302 prcReport16(pProcess, &prcp);
303 (*pfnwpCallback)(hwnd, ulMsg, mp1, &prcp);
304 }
305 ulrc++;
306 }
307
308 free(pps);
309 return (ulrc);
310}
311
312/*
313 *@@ prc16QueryThreadCount:
314 * returns the total number of running threads
315 * in the given process. If pid == 0, the
316 * total thread count for the system is returned.
317 */
318
319ULONG prc16QueryThreadCount(USHORT usPID)
320{
321 ULONG ulrc = 0;
322 PQPROCSTAT16 pps = (PQPROCSTAT16)malloc(0x8000);
323 DosQProcStatus(pps, 0x8000);
324
325 if (usPID)
326 {
327 // process query:
328 PQPROCESS16 pProcess;
329 for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
330 pProcess->ulType != 3;
331 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
332 pProcess->usThreads * sizeof(QTHREAD16))
333 )
334 {
335 if (pProcess->usPID == usPID)
336 {
337 ulrc = pProcess->usThreads;
338 break;
339 }
340 }
341 }
342 else
343 {
344 // global query:
345 PQGLOBAL16 pg;
346 pg = (PQGLOBAL16)PTR(pps->ulGlobal, 0);
347 ulrc = pg->ulThreads;
348 }
349
350 free(pps);
351 return (ulrc);
352}
353
354/*
355 *@@ prc16QueryThreadInfo:
356 * this searches for a given thread in a given process
357 * and fills a given PRCTHREAD structure with lots of
358 * information about that thread.
359 *
360 * Returns FALSE upon errors.
361 *
362 * Note: This function loops thru all processes which
363 * are currently running and is therefore not terribly
364 * fast. Use economically.
365 */
366
367BOOL prc16QueryThreadInfo(USHORT usPID, USHORT usTID, PPRCTHREAD pprct)
368{
369 BOOL brc = FALSE;
370 PQPROCSTAT16 pps = (PQPROCSTAT16)malloc(0x8000);
371 PQPROCESS16 pProcess;
372 DosQProcStatus(pps, 0x8000);
373
374 // find process:
375 for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
376 pProcess->ulType != 3;
377 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
378 pProcess->usThreads * sizeof(QTHREAD16))
379 )
380 {
381 if (pProcess->usPID == usPID)
382 {
383 PQTHREAD16 pThread;
384 int i;
385 // process found: find thread
386 for ( i = 0, pThread = (PQTHREAD16)PTR(pProcess->ulThreadList, 0);
387 i < pProcess->usThreads;
388 i++, pThread++ )
389 {
390 if (pThread->usTID == usTID)
391 {
392 // thread found:
393 pprct->usTID = pThread->usTID;
394 pprct->usThreadSlotID = pThread->usThreadSlotID;
395 pprct->ulBlockID = pThread->ulBlockID;
396 pprct->ulPriority = pThread->ulPriority;
397 pprct->ulSysTime = pThread->ulSysTime;
398 pprct->ulUserTime = pThread->ulUserTime;
399 pprct->ucStatus = pThread->ucStatus;
400
401 brc = TRUE;
402
403 break; // thread-for loop
404 }
405 } // end for thread
406 break; // process-for loop
407 }
408 } // end for process
409
410 free(pps);
411 return (brc);
412}
413
414/*
415 *@@ prcQueryPriority:
416 * shortcut to prc16QueryThreadInfo if you want the priority only.
417 *
418 * Returns -1 upon errors.
419 *
420 * Note: This function loops thru all processes which
421 * are currently running and is therefore not terribly
422 * fast. Use economically.
423 */
424
425ULONG prc16QueryThreadPriority(USHORT usPID,
426 USHORT usTID)
427{
428 PRCTHREAD prct;
429 ULONG ulrc = -1;
430 if (prc16QueryThreadInfo(usPID, usTID, &prct))
431 ulrc = prct.ulPriority;
432 return (ulrc);
433}
434
435/*
436 *@@category: Helpers\Control program helpers\Process status\32-bit DosQuerySysState
437 */
438
439/********************************************************************
440 *
441 * DosQuerySysState (32-bit) interface
442 *
443 ********************************************************************/
444
445/*
446 *@@ prc32GetInfo:
447 * nifty interface to DosQuerySysState,
448 * the 32-bit version of DosQProcStat.
449 * This returns the head of a newly
450 * allocated buffer which has plenty
451 * of pointers for subsequent browing.
452 *
453 * Use prc32FreeInfo to free the buffer.
454 *
455 *@@added V0.9.1 (2000-02-12) [umoeller]
456 *@@changed V0.9.3 (2000-05-01) [umoeller]: now using DosAllocMem
457 */
458
459PQTOPLEVEL32 prc32GetInfo(APIRET *parc) // out: error, ptr can be NULL
460{
461 #define BUFSIZE 128000l
462 PCHAR pBuf = NULL; // (PCHAR)malloc(BUFSIZE);
463
464 if (DosAllocMem((PVOID*)&pBuf,
465 BUFSIZE,
466 PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE)
467 == NO_ERROR)
468 if (pBuf)
469 {
470 APIRET arc = DosQuerySysState(0x1f,
471 0, 0, 0,
472 (PCHAR)pBuf,
473 BUFSIZE);
474 if (parc)
475 *parc = arc;
476
477 if (arc == NO_ERROR)
478 return ((PQTOPLEVEL32)pBuf);
479 else
480 DosFreeMem(pBuf);
481 }
482
483 return (NULL);
484}
485
486/*
487 *@@ prc32FreeInfo:
488 * frees the memory allocated by prc32GetInfo.
489 *
490 *@@added V0.9.1 (2000-02-12) [umoeller]
491 *@@changed V0.9.3 (2000-05-01) [umoeller]: now using DosAllocMem
492 */
493
494VOID prc32FreeInfo(PQTOPLEVEL32 pInfo)
495{
496 DosFreeMem(pInfo);;
497}
498
499/*
500 *@@ prc32FindProcessFromName:
501 *
502 *@@added V0.9.2 (2000-03-05) [umoeller]
503 */
504
505PQPROCESS32 prc32FindProcessFromName(PQTOPLEVEL32 pInfo,
506 const char *pcszName) // in: e.g. "pmshell.exe"
507{
508 PQPROCESS32 pProcThis = pInfo->pProcessData;
509 while (pProcThis && pProcThis->rectype == 1)
510 {
511 int i;
512 PQTHREAD32 t = pProcThis->pThreads;
513 PQMODULE32 pModule = prc32FindModule(pInfo,
514 pProcThis->usHModule);
515
516 if (pModule)
517 {
518 // the module name is fully qualified, so find the
519 // file name (after the last backslash)
520 if (pModule->pcName)
521 {
522 PSZ pLastBackslash = strrchr(pModule->pcName, '\\');
523 if (pLastBackslash)
524 // found:
525 if (stricmp(pLastBackslash + 1, pcszName) == 0)
526 // matches:
527 break;
528 }
529 }
530
531 // for next process, skip the threads info;
532 // the next process block comes after the
533 // threads
534 for (i=0;
535 i < pProcThis->usThreadCount;
536 i++,t++)
537 ;
538
539 pProcThis = (PQPROCESS32)t;
540 }
541
542 if (pProcThis->rectype == 1)
543 return (pProcThis);
544 else
545 return (NULL);
546}
547
548/*
549 *@@ prc32FindSem16:
550 * attempts to find the specified 16-bit semaphore
551 * in the specified info buffer.
552 *
553 * The return value points into the pInfo buffer.
554 * Returns NULL if not found.
555 *
556 *@@added V0.9.1 (2000-02-12) [umoeller]
557 */
558
559PQSEMA32 prc32FindSem16(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
560 USHORT usSemID) // in: as in QPROCESS32.pausSem16
561{
562 PQSEM16STRUC32 pSemData = pInfo->pSem16Data;
563 PQSEMA32 pSemThis = &pSemData->sema;
564 ULONG i = 0;
565
566 while (pSemThis)
567 {
568 _Pmpf(("prc32FindSem16: found usIndex 0x%lX", pSemThis->usIndex));
569 if (/* pSemThis->usIndex */ i == usSemID)
570 return (pSemThis);
571
572 i++;
573 pSemThis = pSemThis->pNext;
574 }
575
576 return (NULL);
577}
578
579/*
580 *@@ prc32FindSem32:
581 * attempts to find the specified 32-bit semaphore
582 * in the specified info buffer. This might fail
583 * because the data isn't always complete.
584 *
585 * The return value points into the pInfo buffer.
586 * Returns NULL if not found.
587 *
588 *@@added V0.9.1 (2000-02-12) [umoeller]
589 */
590
591PQSEM32STRUC32 prc32FindSem32(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
592 USHORT usSemID) // in: as in QPROCESS32.pausSem16
593{
594 // PQSEM32STRUC32 pSemThis = pInfo->pSem32Data;
595
596 /* while (pSemThis)
597 {
598 if (pSemThis->usIndex == usSemID)
599 return (pSemThis);
600
601 pSemThis = pSemThis->pNext;
602 } */
603
604 return (NULL);
605}
606
607/*
608 *@@ prc32FindShrMem:
609 * attempts to find the specified shared memory
610 * block description.
611 *
612 * The return value points into the pInfo buffer.
613 * Returns NULL if not found.
614 *
615 *@@added V0.9.1 (2000-02-12) [umoeller]
616 */
617
618PQSHRMEM32 prc32FindShrMem(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
619 USHORT usShrMemID) // in: as in QPROCESS32.pausShrMems
620{
621 PQSHRMEM32 pShrMem = pInfo->pShrMemData;
622 while (pShrMem)
623 {
624 if (pShrMem->usHandle == usShrMemID)
625 return (pShrMem);
626 pShrMem = pShrMem->pNext;
627 }
628
629 return (NULL);
630}
631
632/*
633 *@@ prc32FindModule:
634 * attempts to find the specified module description.
635 *
636 * The return value points into the pInfo buffer.
637 * Returns NULL if not found.
638 *
639 *@@added V0.9.1 (2000-02-12) [umoeller]
640 */
641
642PQMODULE32 prc32FindModule(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
643 USHORT usHModule)
644{
645 PQMODULE32 pModule = pInfo->pModuleData;
646 while (pModule)
647 {
648 if (pModule->usHModule == usHModule)
649 return (pModule);
650 pModule = pModule->pNext;
651 }
652
653 return (NULL);
654}
655
656/*
657 *@@ prc32FindFileData:
658 *
659 *
660 *@@added V0.9.1 (2000-02-12) [umoeller]
661 */
662
663PQFILEDATA32 prc32FindFileData(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
664 USHORT usFileID) // in: as in QPROCESS32.pausFds
665{
666 PQFILEDATA32 pFile = pInfo->pFileData;
667 while ( (pFile)
668 && (pFile->rectype == 8) // this is necessary, we'll crash otherwise!!
669 )
670 {
671 if (pFile->filedata->sfn == usFileID)
672 return (pFile);
673
674 pFile = pFile->pNext;
675 }
676
677 return (NULL);
678}
679
680
Note: See TracBrowser for help on using the repository browser.