source: branches/branch-1-0/src/helpers/procstat.c

Last change on this file was 420, checked in by pr, 11 years ago

Add prc32KillProcessTree.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 24.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-2014 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#define INCL_DOSPROCESS
55#include <os2.h>
56
57#include <stdlib.h> // already #include'd
58#include <string.h> // already #include'd
59#include <stdio.h>
60
61#include "setup.h" // code generation and debugging options
62
63#include "helpers\procstat.h"
64
65#pragma hdrstop
66
67/*
68 *@@category: Helpers\Control program helpers\Process status\16-bit DosQProcStat
69 */
70
71/********************************************************************
72 *
73 * DosQProcStat (16-bit) interface
74 *
75 ********************************************************************/
76
77/*
78 *@@ prc16GetInfo:
79 * nifty interface to DosQProcStat (16-bit).
80 * This returns the head of a newly
81 * allocated buffer which has plenty
82 * of pointers for subsequent browsing.
83 *
84 * Use prc16FreeInfo to free the buffer.
85 *
86 *@@added V0.9.3 (2000-05-05) [umoeller]
87 *@@changed V0.9.10 (2001-04-08) [umoeller]: this returned != NULL even though item was freed, fixed
88 *@@changed V0.9.10 (2001-04-08) [umoeller]: now using DosAllocMem, raised bufsize, changed prototype
89 */
90
91APIRET prc16GetInfo(PQPROCSTAT16 *ppps) // out: error, ptr can be NULL
92{
93 APIRET arc = NO_ERROR;
94 PQPROCSTAT16 pps = NULL;
95
96 if (!ppps)
97 return ERROR_INVALID_PARAMETER;
98
99 // changed allocation V0.9.10 (2001-04-08) [umoeller]:
100 // malloc didn't guarantee that the object did not
101 // cross a 64K boundary, which could cause DosQProcStat
102 // to fail...
103 #define BUF_SIZE 0xFFFF // raised from 0x8000
104
105 if (!(arc = DosAllocMem((VOID**)&pps,
106 BUF_SIZE,
107 PAG_READ | PAG_WRITE | PAG_COMMIT
108 | OBJ_TILE // 16-bit compatible, ignored really
109 )))
110 {
111 if (arc = DosQProcStatus(pps, BUF_SIZE))
112 {
113 // error:
114 DosFreeMem(pps); // V0.9.10 (2001-04-08) [umoeller]
115
116 // and even worse, I forgot to set the return ptr
117 // to NULL, so this was freed twice... I guess
118 // this produced the crashes in WarpIN with the
119 // KILLPROCESS attribute... V0.9.10 (2001-04-08) [umoeller]
120 pps = NULL;
121 }
122 }
123
124 *ppps = pps;
125
126 return arc;
127}
128
129/*
130 *@@ prc16FreeInfo:
131 * frees memory allocated by prc16GetInfo.
132 *
133 *@@added V0.9.3 (2000-05-05) [umoeller]
134 *@@changed V0.9.10 (2001-04-08) [umoeller]: now using DosFreeMem
135 */
136
137APIRET prc16FreeInfo(PQPROCSTAT16 pInfo)
138{
139 if (!pInfo)
140 return ERROR_INVALID_PARAMETER;
141
142 return DosFreeMem(pInfo);
143}
144
145/*
146 *@@ prc16FindProcessFromName:
147 * searches the specified buffer for a process
148 * with the specified name and returns a pointer
149 * to its data within pInfo.
150 *
151 * Returns NULL if not found.
152 *
153 *@@added V0.9.3 (2000-05-05) [umoeller]
154 */
155
156PQPROCESS16 prc16FindProcessFromName(PQPROCSTAT16 pInfo, // in: from prc16GetInfo
157 const char *pcszName) // in: e.g. "pmshell.exe"
158{
159 PQPROCESS16 pProcess,
160 pReturn = NULL;
161 if (pInfo)
162 {
163 for ( pProcess = (PQPROCESS16)PTR(pInfo->ulProcesses, 0);
164 pProcess->ulType != 3;
165 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
166 pProcess->usThreads * sizeof(QTHREAD16))
167 )
168 {
169 CHAR szModuleName[CCHMAXPATH];
170 if (DosQueryModuleName(pProcess->usHModule,
171 sizeof(szModuleName),
172 szModuleName)
173 == NO_ERROR)
174 {
175 // the module name is fully qualified, so find the
176 // file name (after the last backslash)
177 PSZ pLastBackslash = strrchr(szModuleName, '\\');
178 if (pLastBackslash)
179 // found:
180 if (stricmp(pLastBackslash + 1, pcszName) == 0)
181 {
182 // matches:
183 pReturn = pProcess;
184 break;
185 }
186 }
187 }
188 }
189
190 return pReturn;
191}
192
193/*
194 *@@ prc16FindProcessFromPID:
195 * searches the specified buffer for a process
196 * with the specified PID and returns a pointer
197 * to its data within pInfo.
198 *
199 * Returns NULL if not found.
200 *
201 *V0.9.5 (2000-09-29) [umoeller]
202 */
203
204PQPROCESS16 prc16FindProcessFromPID(PQPROCSTAT16 pInfo, // in: from prc16GetInfo
205 ULONG ulPID) // in: PID
206{
207 PQPROCESS16 pProcess,
208 pReturn = NULL;
209 if (pInfo)
210 {
211 for ( pProcess = (PQPROCESS16)PTR(pInfo->ulProcesses, 0);
212 pProcess->ulType != 3;
213 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
214 pProcess->usThreads * sizeof(QTHREAD16))
215 )
216 {
217 if (pProcess->usPID == ulPID)
218 {
219 pReturn = pProcess;
220 break;
221 }
222 }
223 }
224
225 return pReturn;
226}
227
228/********************************************************************
229 *
230 * DosQProcStat (16-bit) helpers
231 *
232 ********************************************************************/
233
234/*
235 * prcReport16:
236 * fill PRCPROCESS structure
237 */
238
239VOID prcReport16(PQPROCESS16 pProcess, PPRCPROCESS pprcp)
240{
241 if (pProcess)
242 {
243 PQTHREAD16 pThread;
244 int i;
245
246 DosQueryModuleName(pProcess->usHModule,
247 sizeof(pprcp->szModuleName),
248 pprcp->szModuleName);
249 // DosGetPrty(PRTYS_PROCESS, &(pprcp->usPriority), pProcess->usPID);
250
251 // sum up CPU time for process
252 for (pprcp->ulCPU = 0,
253 i = 0,
254 pThread = (PQTHREAD16)PTR(pProcess->ulThreadList, 0);
255 i < pProcess->usThreads;
256 i++, pThread++ )
257 {
258 pprcp->ulCPU += (pThread->ulSysTime + pThread->ulUserTime);
259 }
260
261 pprcp->usPID = pProcess->usPID;
262 pprcp->usParentPID = pProcess->usParentPID;
263 pprcp->usThreads = pProcess->usThreads;
264 pprcp->ulSID = pProcess->ulSID;
265 pprcp->ulSessionType = pProcess->ulSessionType;
266 pprcp->ulStatus = pProcess->ulStatus;
267 }
268}
269
270/*
271 *@@ prc16QueryProcessInfo:
272 * this searches for a given process ID (usPID) and
273 * fills a given PRCPROCESS structure with lots of
274 * information about this process.
275 * Returns FALSE upon errors, e.g. if no process
276 * of that ID is found.
277 */
278
279BOOL prc16QueryProcessInfo(PQPROCSTAT16 pps, // in: from prc16GetInfo
280 USHORT usPID, // in: PID to query
281 PPRCPROCESS pprcp) // out: process info
282{
283 BOOL rc = FALSE;
284 if (pps)
285 {
286 PQPROCESS16 pProcess;
287
288 for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
289 pProcess->ulType != 3;
290 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
291 pProcess->usThreads * sizeof(QTHREAD16))
292 )
293 {
294 if (pProcess->usPID == usPID)
295 {
296 prcReport16(pProcess, pprcp);
297 rc = TRUE;
298 break;
299 }
300 }
301 }
302
303 return rc;
304}
305
306/*
307 *@@ prc16ForEachProcess:
308 * this calls a given callback func for each running
309 * process. The callback must be a FNWP, which will be
310 * passed the following parameters for each call:
311 * -- HWND hwnd: like hwnd passed to this func
312 * -- ULONG msg: like msg passed to this func
313 * -- MPARAM mp1: like mp1 passed to this func
314 * -- PPRCPROCESS: mp2 pointer to a PRCPROCESS struct for each process
315 *
316 * This function returns the number of running processes on the
317 * system. If pfnwpCallback is NULL, only this number will be
318 * returned, so you can use this as a process counter too.
319 *
320 *@@changed V0.9.10 (2001-04-16) [pr]: now using DosAllocMem
321 */
322
323ULONG prc16ForEachProcess(PFNWP pfnwpCallback, HWND hwnd, ULONG ulMsg, MPARAM mp1)
324{
325 ULONG ulrc = 0;
326 PQPROCSTAT16 pps;
327 PQPROCESS16 pProcess;
328 PRCPROCESS prcp;
329
330 if (!DosAllocMem((PVOID*)&pps,
331 BUF_SIZE,
332 PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE))
333 {
334 if (!DosQProcStatus(pps, BUF_SIZE))
335 for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
336 pProcess->ulType != 3;
337 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
338 pProcess->usThreads * sizeof(QTHREAD16))
339 )
340 {
341 if (pfnwpCallback)
342 {
343 prcReport16(pProcess, &prcp);
344 (*pfnwpCallback)(hwnd, ulMsg, mp1, &prcp);
345 }
346 ulrc++;
347 }
348
349 DosFreeMem(pps);
350 }
351
352 return ulrc;
353}
354
355/*
356 *@@ prc16QueryThreadCount:
357 * returns the total number of running threads
358 * in the given process. If pid == 0, the
359 * total thread count for the system is returned.
360 *
361 *@@changed V0.9.9 (2001-03-07) [umoeller]: added pps param
362 */
363
364ULONG prc16QueryThreadCount(PQPROCSTAT16 pps, // in: from prc16GetInfo
365 USHORT usPID)
366{
367 ULONG ulrc = 0;
368
369 if (pps)
370 {
371 if (usPID)
372 {
373 // process query:
374 PQPROCESS16 pProcess;
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 ulrc = pProcess->usThreads;
384 break;
385 }
386 }
387 }
388 else
389 {
390 // global query:
391 PQGLOBAL16 pg;
392 pg = (PQGLOBAL16)PTR(pps->ulGlobal, 0);
393 ulrc = pg->ulThreads;
394 }
395 }
396
397 return ulrc;
398}
399
400/*
401 *@@ prc16QueryThreadInfo:
402 * this searches for a given thread in a given process
403 * and fills a given PRCTHREAD structure with lots of
404 * information about that thread.
405 *
406 * Returns FALSE upon errors.
407 *
408 * Note: This function loops thru all processes which
409 * are currently running and is therefore not terribly
410 * fast. Use economically.
411 *
412 *@@changed V0.9.9 (2001-03-07) [umoeller]: added pps param
413 */
414
415BOOL prc16QueryThreadInfo(PQPROCSTAT16 pps, // in: from prc16GetInfo
416 USHORT usPID,
417 USHORT usTID,
418 PPRCTHREAD pprct)
419{
420 BOOL brc = FALSE;
421 if (pps)
422 {
423 PQPROCESS16 pProcess;
424
425 // find process:
426 for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
427 pProcess->ulType != 3;
428 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
429 pProcess->usThreads * sizeof(QTHREAD16))
430 )
431 {
432 if (pProcess->usPID == usPID)
433 {
434 PQTHREAD16 pThread;
435 int i;
436 // process found: find thread
437 for ( i = 0, pThread = (PQTHREAD16)PTR(pProcess->ulThreadList, 0);
438 i < pProcess->usThreads;
439 i++, pThread++ )
440 {
441 if (pThread->usTID == usTID)
442 {
443 // thread found:
444 pprct->usTID = pThread->usTID;
445 pprct->usThreadSlotID = pThread->usThreadSlotID;
446 pprct->ulBlockID = pThread->ulBlockID;
447 pprct->ulPriority = pThread->ulPriority;
448 pprct->ulSysTime = pThread->ulSysTime;
449 pprct->ulUserTime = pThread->ulUserTime;
450 pprct->ucStatus = pThread->ucStatus;
451
452 brc = TRUE;
453
454 break; // thread-for loop
455 }
456 } // end for thread
457 break; // process-for loop
458 }
459 } // end for process
460 }
461
462 return brc;
463}
464
465/*
466 *@@ prcQueryPriority:
467 * shortcut to prc16QueryThreadInfo if you want the priority only.
468 *
469 * Returns -1 upon errors.
470 *
471 * Note: This function loops thru all processes which
472 * are currently running and is therefore not terribly
473 * fast. Use economically.
474 *
475 *@@changed V0.9.9 (2001-03-07) [umoeller]: added pps param
476 */
477
478ULONG prc16QueryThreadPriority(PQPROCSTAT16 pps, // in: from prc16GetInfo
479 USHORT usPID,
480 USHORT usTID)
481{
482 PRCTHREAD prct;
483 ULONG ulrc = -1;
484 if (prc16QueryThreadInfo(pps, usPID, usTID, &prct))
485 ulrc = prct.ulPriority;
486 return ulrc;
487}
488
489/*
490 *@@category: Helpers\Control program helpers\Process status\32-bit DosQuerySysState
491 */
492
493/********************************************************************
494 *
495 * DosQuerySysState (32-bit) interface
496 *
497 ********************************************************************/
498
499/*
500 *@@ prc32GetInfo2:
501 * nifty interface to DosQuerySysState, the 32-bit
502 * version of DosQProcStat.
503 *
504 * This returns the head of a newly allocated buffer
505 * which has plenty of pointers for subsequent browing.
506 *
507 * As opposed to prc32GetInfo, with this call you can
508 * specify the information that would like to retrieve.
509 *
510 * Use prc32FreeInfo to free the buffer.
511 *
512 *@@added V1.0.1 (2003-01-10) [umoeller]
513 */
514
515PQTOPLEVEL32 prc32GetInfo2(ULONG fl, // in: QS32_* flags
516 APIRET *parc) // out: error, ptr can be NULL
517{
518 APIRET arc;
519 PQTOPLEVEL32 pReturn = NULL;
520
521 #define BUFSIZE (1024 * 1024) // 1 meg
522
523 if (!(arc = DosAllocMem((PVOID*)&pReturn,
524 BUFSIZE,
525 PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE)))
526 {
527 if (arc = DosQuerySysState(fl,
528 fl, // this was missing V0.9.10 (2001-04-08) [umoeller]
529 0, 0,
530 (PCHAR)pReturn,
531 BUFSIZE))
532 {
533 DosFreeMem(pReturn);
534 pReturn = NULL;
535 }
536 }
537
538 if (parc)
539 *parc = arc;
540
541 return pReturn;
542}
543
544/*
545 *@@ prc32GetInfo:
546 * nifty interface to DosQuerySysState, the 32-bit
547 * version of DosQProcStat.
548 *
549 * This returns the head of a newly allocated buffer
550 * which has plenty of pointers for subsequent browing.
551 *
552 * Use prc32FreeInfo to free the buffer.
553 *
554 *@@added V0.9.1 (2000-02-12) [umoeller]
555 *@@changed V0.9.3 (2000-05-01) [umoeller]: now using DosAllocMem
556 *@@changed V0.9.10 (2001-04-08) [umoeller]: fixed second QuerySysState param
557 */
558
559PQTOPLEVEL32 prc32GetInfo(APIRET *parc) // out: error, ptr can be NULL
560{
561 return prc32GetInfo2(QS32_SUPPORTED,
562 parc);
563}
564
565/*
566 *@@ prc32FreeInfo:
567 * frees the memory allocated by prc32GetInfo.
568 *
569 *@@added V0.9.1 (2000-02-12) [umoeller]
570 *@@changed V0.9.3 (2000-05-01) [umoeller]: now using DosFreeMem
571 */
572
573VOID prc32FreeInfo(PQTOPLEVEL32 pInfo)
574{
575 DosFreeMem(pInfo);
576}
577
578/*
579 *@@ prc32FindProcessFromName:
580 *
581 *@@added V0.9.2 (2000-03-05) [umoeller]
582 *@@changed V1.0.0 (2002-08-16) [pr]: optimized
583 */
584
585PQPROCESS32 prc32FindProcessFromName(PQTOPLEVEL32 pInfo,
586 const char *pcszName) // in: e.g. "pmshell.exe"
587{
588 PQPROCESS32 pProcThis = pInfo->pProcessData;
589 while (pProcThis && pProcThis->ulRecType == 1)
590 {
591 PQTHREAD32 t = pProcThis->pThreads;
592 PQMODULE32 pModule;
593
594 if (pModule = prc32FindModule(pInfo,
595 pProcThis->usHModule))
596 {
597 // the module name is fully qualified, so find the
598 // file name (after the last backslash)
599 if (pModule->pcName)
600 {
601 PSZ pLastBackslash;
602 if (pLastBackslash = strrchr(pModule->pcName, '\\'))
603 // found:
604 if (stricmp(pLastBackslash + 1, pcszName) == 0)
605 // matches:
606 break;
607 }
608 }
609
610 // for next process, skip the threads info;
611 // the next process block comes after the
612 // threads
613 t += pProcThis->usThreadCount;
614 pProcThis = (PQPROCESS32)t;
615 }
616
617 if (pProcThis->ulRecType == 1)
618 return pProcThis;
619
620 return NULL;
621}
622
623/*
624 *@@ prc32FindProcessFromPID:
625 *
626 *@@added V1.0.0 (2002-08-12) [umoeller]
627 *@@changed V1.0.0 (2002-08-16) [pr]: optimized
628 */
629
630PQPROCESS32 prc32FindProcessFromPID(PQTOPLEVEL32 pInfo,
631 ULONG pid)
632{
633 PQPROCESS32 pProcThis = pInfo->pProcessData;
634 while (pProcThis && pProcThis->ulRecType == 1)
635 {
636 PQTHREAD32 t = pProcThis->pThreads;
637
638 if (pProcThis->usPID == pid)
639 return pProcThis;
640
641 // for next process, skip the threads info;
642 // the next process block comes after the
643 // threads
644 t += pProcThis->usThreadCount;
645 pProcThis = (PQPROCESS32)t;
646 }
647
648 return NULL;
649}
650
651/*
652 *@@ prc32FindSem16:
653 * attempts to find the specified 16-bit semaphore
654 * in the specified info buffer.
655 *
656 * The return value points into the pInfo buffer.
657 * Returns NULL if not found.
658 *
659 *@@added V0.9.1 (2000-02-12) [umoeller]
660 */
661
662PQS32SEM16 prc32FindSem16(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
663 USHORT usSemID) // in: as in QPROCESS32.pausSem16
664{
665 PQS32SEM16HEAD pSemHead = pInfo->pSem16Data;
666 PQS32SEM16 // pSemThis = &pSemData->sema;
667 pSemThis = &pSemHead->Sem16Rec;
668 ULONG i = 0;
669
670 while (pSemThis)
671 {
672 if (i == usSemID)
673 return pSemThis;
674
675 i++;
676 pSemThis = pSemThis->pNext;
677 }
678
679 return NULL;
680}
681
682/*
683 *@@ prc32FindSem32:
684 * attempts to find the specified 32-bit semaphore
685 * in the specified info buffer. This might fail
686 * because the data isn't always complete.
687 *
688 * The return value points into the pInfo buffer.
689 * Returns NULL if not found.
690 *
691 *@@added V0.9.1 (2000-02-12) [umoeller]
692 */
693
694PQS32SEM32 prc32FindSem32(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
695 USHORT usSemID) // in: as in QPROCESS32.pausSem16
696{
697 // PQSEM32STRUC32 pSemThis = pInfo->pSem32Data;
698
699 /* while (pSemThis)
700 {
701 if (pSemThis->usIndex == usSemID)
702 return pSemThis;
703
704 pSemThis = pSemThis->pNext;
705 } */
706
707 return NULL;
708}
709
710/*
711 *@@ prc32FindShrMem:
712 * attempts to find the specified shared memory
713 * block description.
714 *
715 * The return value points into the pInfo buffer.
716 * Returns NULL if not found.
717 *
718 *@@added V0.9.1 (2000-02-12) [umoeller]
719 */
720
721PQSHRMEM32 prc32FindShrMem(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
722 USHORT usShrMemID) // in: as in QPROCESS32.pausShrMems
723{
724 PQSHRMEM32 pShrMem = pInfo->pShrMemData;
725 while (pShrMem)
726 {
727 if (pShrMem->usHandle == usShrMemID)
728 return pShrMem;
729 pShrMem = pShrMem->pNext;
730 }
731
732 return NULL;
733}
734
735/*
736 *@@ prc32FindModule:
737 * attempts to find the specified module description.
738 *
739 * The return value points into the pInfo buffer.
740 * Returns NULL if not found.
741 *
742 *@@added V0.9.1 (2000-02-12) [umoeller]
743 */
744
745PQMODULE32 prc32FindModule(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
746 USHORT usHModule)
747{
748 PQMODULE32 pModule = pInfo->pModuleData;
749 while (pModule)
750 {
751 if (pModule->usHModule == usHModule)
752 return pModule;
753
754 pModule = pModule->pNext;
755 }
756
757 return NULL;
758}
759
760/*
761 *@@ prc32FindFileData:
762 *
763 *
764 *@@added V0.9.1 (2000-02-12) [umoeller]
765 */
766
767PQFILEDATA32 prc32FindFileData(PQTOPLEVEL32 pInfo, // in: as returned by prc32GetInfo
768 USHORT usFileID) // in: as in QPROCESS32.pausFds
769{
770 PQFILEDATA32 pFile = pInfo->pFileData;
771 while ( (pFile)
772 && (pFile->ulRecType == 8) // this is necessary, we'll crash otherwise!!
773 )
774 {
775 ULONG ul;
776 // for some reason, there is an array in the file struct,
777 // so search the array for the SFN
778 for (ul = 0;
779 ul < pFile->ulCFiles;
780 ul++)
781 {
782 if (pFile->paFiles[ul].usSFN == usFileID)
783 return pFile;
784 }
785
786 pFile = pFile->pNext;
787 }
788
789 return NULL;
790}
791
792/*
793 *@@ prc32KillProcessTree:
794 *
795 *@@added XWP V1.0.10 (2014-12-07) [pr]
796 */
797
798void prc32KillProcessTree(ULONG pid)
799{
800 APIRET arc;
801 PQTOPLEVEL32 pInfo = prc32GetInfo2(QS32_PROCESS, &arc);
802
803 if (arc == NO_ERROR)
804 {
805 prc32KillProcessTree2(pInfo->pProcessData, pid);
806 DosKillProcess(DKP_PROCESS, pid);
807 prc32FreeInfo(pInfo);
808 }
809}
810
811/*
812 *@@ prc32KillProcessTree2:
813 *
814 *@@added XWP V1.0.10 (2014-12-07) [pr]
815 */
816
817void prc32KillProcessTree2(PQPROCESS32 pProcThis, ULONG pid)
818{
819 while (pProcThis && pProcThis->ulRecType == 1)
820 {
821 PQTHREAD32 t = pProcThis->pThreads;
822
823 if (pProcThis->usPPID == pid)
824 {
825 prc32KillProcessTree2(pProcThis, pProcThis->usPID);
826 DosKillProcess(DKP_PROCESS, pProcThis->usPID);
827 }
828
829 // for next process, skip the threads info;
830 // the next process block comes after the threads
831 t += pProcThis->usThreadCount;
832 pProcThis = (PQPROCESS32)t;
833 }
834}
835
Note: See TracBrowser for help on using the repository browser.