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 >
C/C++ Source or Header  |  2002-06-05  |  23KB  |  750 lines

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