home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1997 January / PCO0197.ISO / filesbbs / os2 / nwbeta99.arj / BEISPIEL / SLIP / KILLEMC.ZIP / KillEmC.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-07  |  32.2 KB  |  752 lines

  1. /**********************************************************************
  2.  * MODULE NAME :  killem.c               AUTHOR:  Rick Fishman        *
  3.  * DATE WRITTEN:  10-24-91                                            *
  4.  *                                                                    *
  5.  * DESCRIPTION:                                                       *
  6.  *                                                                    *
  7.  *  This program kills the specified process(s). It uses the          *
  8.  *  undocumented function DosQProcStatus to get a buffer filled with  *
  9.  *  information related to the current state of the system. It then   *
  10.  *  performs the following using the buffer:                          *
  11.  *                                                                    *
  12.  *  1. Get the relevant process information for all active pids into  *
  13.  *     an array.                                                      *
  14.  *  2. Go thru the module information table. For each module found,   *
  15.  *     see if the module name matches those given on the command      *
  16.  *     line. If so, compare its module reference number against all   *
  17.  *     module reference numbers associated with the active pids. If   *
  18.  *     any match, issue a DosKillProcess against the matching pids.   *
  19.  *                                                                    *
  20.  * UPDATES:                                                           *
  21.  *                                                                    *
  22.  *   5/21/92 - increased buffer to 32k from 16k because of Trap D     *
  23.  *             on LAN.                                                *
  24.  *   5/21/92 - changed compare of process name to buffer so that if   *
  25.  *             'e' is specified on command line, processes that end   *
  26.  *             in 'e' will not be killed.                             *
  27.  *   6/08/92 - added commandline support for process ids. Now Ver 2.1.*
  28.  *                                                                    *
  29.  **********************************************************************/
  30.  
  31.  
  32. /*********************************************************************/
  33. /*------- Include relevant sections of the OS/2 header files --------*/
  34. /*********************************************************************/
  35.  
  36. #define INCL_DOSERRORS
  37. #define INCL_DOSPROCESS
  38.  
  39. /**********************************************************************/
  40. /*----------------------------- INCLUDES -----------------------------*/
  41. /**********************************************************************/
  42.  
  43. #include <os2.h>
  44. #include <ctype.h>
  45. #include <process.h>
  46. #include <stdarg.h>
  47. #include <stdio.h>
  48. #include <string.h>
  49. #include <stdlib.h>
  50. #include "procstat.h"
  51.  
  52. /*********************************************************************/
  53. /*------------------- APPLICATION DEFINITIONS -----------------------*/
  54. /*********************************************************************/
  55.  
  56. #define COPYRIGHT_INFO         "KillEmC.exe, 32-bit, Version 2.1\n"             \
  57.                                "Copyright (c) Code Blazers, Inc 1991. All "    \
  58.                                "rights reserved.\n"
  59.  
  60. #define USAGE_INFO             "\nUsage: KillEmC processname-or-PID "           \
  61.                                "processname-or-PID ...\n"                      \
  62.                                "\n*** PID must be in decimal ***\n"
  63.  
  64. #define OUT_OF_MEMORY_MSG      "\nOut of memory!\n"
  65.  
  66. #define BUFFER_SIZE             0x8000   //** 5/21/92 changed to 32k
  67.  
  68. /**********************************************************************/
  69. /*---------------------------- STRUCTURES ----------------------------*/
  70. /**********************************************************************/
  71.  
  72. typedef struct _ACTIVEPID           // INFO ON AN ACTIVE PROCESS
  73. {
  74.     USHORT  hModRef;                // It's module reference handle
  75.     PID     pid;                    // It's Process Id
  76.  
  77. } ACTIVEPID, *PACTIVEPID;
  78.  
  79.  
  80. /**********************************************************************/
  81. /*----------------------- FUNCTION PROTOTYPES ------------------------*/
  82. /**********************************************************************/
  83.  
  84. INT    main             ( INT argc, PSZ szArg[] );
  85. VOID   KillEm           ( INT iProcessesToKill );
  86. INT    CompareActivePids( const void *pActivePid1, const void *pActivePid2 );
  87. BOOL   ShouldBeKilled   ( PSZ szProcessName, INT iProcessesToKill );
  88. VOID   FindAndKill      ( PMODINFO pmi );
  89. ULONG  KillProcess      ( PID pid, PSZ szProcessName );
  90. ULONG  Init             ( INT argc, PSZ szArg[], PINT piProcessesToKill );
  91. INT    StoreCmdLinePids ( INT argc, PSZ szArg[] );
  92. BOOL   IsStringNumeric  ( PSZ szString );
  93. ULONG  CopyProcessName  ( PSZ szProcessName, INT iArrayIndex );
  94. VOID   UpCaseNames      ( PMODINFO pmi );
  95. ULONG  BuildActivePidTbl( PPROCESSINFO ppi );
  96. VOID   Term             ( ULONG ulExitCode, INT iProcNameEntries );
  97.  
  98. /**********************************************************************/
  99. /*------------------------ GLOBAL VARIABLES --------------------------*/
  100. /**********************************************************************/
  101.  
  102. USHORT      usActiveProcesses;      // Number of active processes
  103.  
  104. INT         iPidCount;              // Number of commandline process ids
  105.  
  106. ACTIVEPID   *aActivePid;            // Array of active processes
  107.  
  108. PSZ         *pszProcess;            // Array of command-line process names
  109.  
  110. PID         apid[ 50 ];             // Array of cmdline process ids
  111.  
  112. PBUFFHEADER pbh;                    // Pointer to buffer header structure
  113.  
  114. /**********************************************************************/
  115. /*------------------------------ MAIN --------------------------------*/
  116. /*                                                                    */
  117. /*  MAIN DRIVER FOR PROGRAM.                                          */
  118. /*                                                                    */
  119. /*  INPUT: number of command-line arguments,                          */
  120. /*         command-line argument array                                */
  121. /*                                                                    */
  122. /*  1. Perform program initialization which will issue the            */
  123. /*     DosQProcStatus call and obtain the buffer of information.      */
  124. /*  2. Use the buffer to kill processes that match the names given    */
  125. /*     on the command-line.                                           */
  126. /*  3. Perform program termination.                                   */
  127. /*                                                                    */
  128. /*  OUTPUT: nothing                                                   */
  129. /*                                                                    */
  130. /*--------------------------------------------------------------------*/
  131. /**********************************************************************/
  132. INT main( INT argc, PSZ szArg[] )
  133. {
  134.     INT    iProcessesToKill;
  135.     ULONG  ulExitCode = Init( argc, szArg, &iProcessesToKill );
  136.  
  137.     if( ulExitCode == NO_ERROR )
  138.         KillEm( iProcessesToKill );
  139.  
  140.     Term( ulExitCode, iProcessesToKill );
  141.  
  142.     return 0;
  143. }
  144.  
  145.  
  146. /**********************************************************************/
  147. /*------------------------getParentIfCMD------------------------------*/
  148. /*                                                                    */
  149. /*    Sucht den Parentprozess und liefert falls cmd.exe den Zeiger    */
  150. /*                                                                    */
  151. /**********************************************************************/
  152. PMODINFO getParentIfCMD(PMODINFO pmi)
  153. {
  154. USHORT moduleHandle;   // Module handle
  155. PPROCESSINFO ppiLocal; 
  156. USHORT pidParent,pidChild;      // Parent's process ID
  157. register INT   i;
  158. char *childname;
  159.  
  160.   moduleHandle=pmi->hMod;
  161.  
  162.   if(!pbh)
  163.     return 0;
  164.   ppiLocal=pbh->ppi;
  165.  
  166.   // Jetzt die Parent Nummer holen
  167.  
  168.   while(ppiLocal->ulEndIndicator != PROCESS_END_INDICATOR) {
  169.     if(ppiLocal->hModRef==moduleHandle)
  170.       break;
  171.     ppiLocal = (PPROCESSINFO) (ppiLocal->ptiFirst+ppiLocal->usThreadCount );
  172.   }
  173.  
  174.   if(ppiLocal->ulEndIndicator == PROCESS_END_INDICATOR) 
  175.     return 0; // Kein Parent gefunden
  176.  
  177.   pidChild=ppiLocal->pid;
  178.   pidParent=ppiLocal->pidParent;
  179.   childname=pmi->szModName;
  180.  
  181. //  printf("PIDChild %hd\n",pidChild);
  182. //  printf("PIDParent %hd\n",pidParent);
  183.  
  184.   // Jetzt den ModulHandle des Parents suchen
  185.  
  186.   for(i=0; i<usActiveProcesses; i++) {
  187.     if(aActivePid[i].pid==pidParent)
  188.       break;
  189.   }
  190.   if(i>=usActiveProcesses)
  191.     return 0; // Kein ModuleHandle gefunden
  192.  
  193.   moduleHandle=aActivePid[i].hModRef;
  194.  
  195.   // Jetzt prüfen ob der Parent ein cmd.exe ist
  196.  
  197.   pmi = pbh->pmi;
  198.   while(pmi) {
  199.     if(pmi->hMod==moduleHandle) { // Module gefunden
  200.       if(strlen(pmi->szModName)<7)
  201.         return 0; // Kann nicht CMD.EXE sein
  202.       if(!strcmp(pmi->szModName+strlen(pmi->szModName)-7,"CMD.EXE")) { // Ist CMD.EXE
  203.         if(!KillProcess(pidChild,childname ) && !KillProcess(pidParent,pmi->szModName ))
  204.           return pmi; // gekillt
  205.         else        
  206.           return 0;
  207.       }
  208.       else
  209.         return 0;
  210.     }
  211.     pmi = pmi->pNext;
  212.   }
  213.   return 0;
  214. }
  215.  
  216. /**********************************************************************/
  217. /*------------------------------ KillEm ------------------------------*/
  218. /*                                                                    */
  219. /*  FIND PROCESSES NAMED ON COMMAND-LINE AND KILL THEM                */
  220. /*                                                                    */
  221. /*  INPUT: number of processes to attempt to kill                     */
  222. /*                                                                    */
  223. /*  1. Kill all process ids that were specified on the commandline.   */
  224. /*  2. If there were process names on the commandline:                */
  225. /*     A. Get the address of the beginning of the module info section.*/
  226. /*     B. For each module information block, check if this is one's   */
  227. /*        module name matches any process names given on the command  */
  228. /*        line. If it does, kill all active pids whose module handle  */
  229. /*        matches its module handle.                                  */
  230. /*                                                                    */
  231. /*  OUTPUT: nothing                                                   */
  232. /*                                                                    */
  233. /*--------------------------------------------------------------------*/
  234. /**********************************************************************/
  235. VOID KillEm( INT iProcessesToKill )
  236. {
  237.     PMODINFO pmi;
  238.     INT      i;
  239.     ULONG    ulRetCode;
  240.  
  241.     for( i = 0; i < iPidCount; i++ )
  242.     {
  243.         ulRetCode = DosKillProcess( DKP_PROCESS, apid[ i ] );
  244.  
  245.         if( ulRetCode )
  246.             if( ulRetCode == ERROR_INVALID_PROCID )
  247.                 printf( "\nPid %u not found", apid[ i ] );
  248.             else
  249.                 printf( "\nFound Pid %u but DosKillProcess failed (RC=%u)",
  250.                         apid[ i ], ulRetCode );
  251.         else
  252.             printf( "\nFound pid %u and Killed it", apid[ i ] );
  253.  
  254.         fflush( stdout );
  255.     }
  256.  
  257.     if( pbh )
  258.     {
  259.         pmi = pbh->pmi;
  260.  
  261.         while( pmi )
  262.         {
  263.             if( ShouldBeKilled( pmi->szModName, iProcessesToKill ) ) {
  264.                 PMODINFO pmi2=getParentIfCMD(pmi);
  265.                 if(pmi2) 
  266.                   break;
  267.             }
  268.             pmi = pmi->pNext;
  269.         }
  270.     }
  271. }
  272.  
  273. /**********************************************************************/
  274. /*------------------------- ShouldBeKilled ---------------------------*/
  275. /*                                                                    */
  276. /*  DETERMINE WHETHER OR NOT WE SHOULD KILL THIS PROCESS.             */
  277. /*                                                                    */
  278. /*  INPUT: process name,                                              */
  279. /*         number of processes we are attempting to kill              */
  280. /*                                                                    */
  281. /*  1. For each process name given on the command line, see if it     */
  282. /*     is a substring of the process name passed as a parameter.      */
  283. /*     The passed module name could be a fully qualified file name.   */
  284. /*                                                                    */
  285. /*  OUTPUT: TRUE if we should kill it, FALSE if not                   */
  286. /*                                                                    */
  287. /*--------------------------------------------------------------------*/
  288. /**********************************************************************/
  289. BOOL ShouldBeKilled( PSZ szProcessName, INT iProcessesToKill )
  290. {
  291.     BOOL fProcessFound = FALSE;
  292.     PSZ  szFound;
  293.     INT  i;
  294.  
  295.     for( i = 0; i < iProcessesToKill; i++ )
  296.     {
  297.         //** 5/21/92 bug fix
  298.  
  299.         if( (szFound = strstr( szProcessName, pszProcess[ i ] )) &&
  300.             ( szFound == szProcessName || *(szFound - 1) == '\\' ) )
  301.         {
  302.             fProcessFound = TRUE;
  303.  
  304.             break;
  305.         }
  306.     }
  307.  
  308.     return fProcessFound;
  309. }
  310.  
  311. #ifdef NICHTBENUTZT
  312. /**********************************************************************/
  313. /*--------------------------- FindAndKill ----------------------------*/
  314. /*                                                                    */
  315. /*  FIND ALL PROCESSES FOR A MODULE HANDLE AND KILL THEM              */
  316. /*                                                                    */
  317. /*  INPUT: pointer to module info block                               */
  318. /*                                                                    */
  319. /*  1. For each active pid, match it's module handle against the      */
  320. /*     module handle of the passed module information block. If it    */
  321. /*     matches, kill that process.                                    */
  322. /*                                                                    */
  323. /*  NOTE: The active array table is sorted in ascending module handle */
  324. /*        order.                                                      */
  325. /*                                                                    */
  326. /*  OUTPUT: nothing                                                   */
  327. /*                                                                    */
  328. /*--------------------------------------------------------------------*/
  329. /**********************************************************************/
  330. VOID FindAndKill( PMODINFO pmi )
  331. {
  332.     USHORT         usKilled = 0;
  333.     register INT   i;
  334.  
  335.     for( i = 0; i < usActiveProcesses; i++ )
  336.     {
  337.         if( aActivePid[ i ].hModRef > pmi->hMod )
  338.             break;
  339.  
  340.         if( aActivePid[ i ].hModRef == pmi->hMod )
  341.             if( KillProcess( aActivePid[ i ].pid, pmi->szModName ) == NO_ERROR )
  342.                 usKilled++;
  343.     }
  344.  
  345.     if( !usKilled )
  346.         printf( "\nCould not find PID for %s!\n", pmi->szModName );
  347. }
  348. #endif
  349.  
  350. /**********************************************************************/
  351. /*--------------------------- KillProcess ----------------------------*/
  352. /*                                                                    */
  353. /*  KILL A PROCESS BY PID                                             */
  354. /*                                                                    */
  355. /*  INPUT: process id,                                                */
  356. /*         process name                                               */
  357. /*                                                                    */
  358. /*  1. Issue a DosKillProcess for the passed process id.              */
  359. /*                                                                    */
  360. /*  OUTPUT: return code from DosKillProcess                           */
  361. /*                                                                    */
  362. /*--------------------------------------------------------------------*/
  363. /**********************************************************************/
  364. ULONG KillProcess( PID pid, PSZ szProcessName )
  365. {
  366.     ULONG ulRetCode = DosKillProcess( DKP_PROCESS, pid );
  367.  
  368.     if( ulRetCode )
  369.     {
  370.         if( ulRetCode != ERROR_INVALID_PROCID )
  371.             printf( "\nFound %s (pid %u) but DosKillProcess failed (RC=%u)",
  372.                     szProcessName, pid, ulRetCode );
  373.     }
  374.     else
  375.         printf( "\nFound %s (pid %u) and Killed it", szProcessName, pid );
  376.  
  377.     fflush( stdout );
  378.  
  379.     return ulRetCode;
  380. }
  381.  
  382. /**********************************************************************/
  383. /*------------------------------ Init --------------------------------*/
  384. /*                                                                    */
  385. /*  PERFORM PROGRAM INITIALIZATION                                    */
  386. /*                                                                    */
  387. /*  INPUT: number of command-line arguments,                          */
  388. /*         command-line argument array,                               */
  389. /*         address of int storing count of process names to kill      */
  390. /*                                                                    */
  391. /*  1. Print copyright notice.                                        */
  392. /*  2. If no process names were specified on the command line, exit.  */
  393. /*  3. Allocate memory for an array of pointers to process name       */
  394. /*     strings. We will use this array during the main program loop   */
  395. /*     to identify process names to kill.                             */
  396. /*  4. Allocate memory for each string in the array.                  */
  397. /*  5. Copy the process names from the command line into the memory   */
  398. /*     we just allocated.                                             */
  399. /*  6. Alocate memory for the output from DosQProcStatus.             */
  400. /*  7. Make the DosQProcStatus call.                                  */
  401. /*  8. Uppercase the names in the module information section to make  */
  402. /*     string compares easier during main program logic.              */
  403. /*  9. Build an array of information related to active processes.     */
  404. /*                                                                    */
  405. /*  OUTPUT: exit code                                                 */
  406. /*                                                                    */
  407. /*--------------------------------------------------------------------*/
  408. /**********************************************************************/
  409. ULONG Init( INT argc, PSZ szArg[], PINT piProcessNamesToKill )
  410. {
  411.     ULONG   ulExitCode = NO_ERROR;
  412.     INT     iPszCount = StoreCmdLinePids( argc, szArg );
  413.     INT     iPszArraySize = iPszCount * sizeof( PSZ );
  414.  
  415.     *piProcessNamesToKill = iPszCount;
  416.  
  417.     (void) printf( COPYRIGHT_INFO );
  418.  
  419.     if( iPszCount )
  420.     {
  421.         // Allocate memory for the array of ASCIIZ process names passed on the
  422.         // command line. We can't just use the commandline because we may need
  423.         // to add .EXE to the end of the process name. So we allocate our own
  424.         // array of strings so we have enough room for that extension if
  425.         // necessary.
  426.  
  427.         pszProcess = (PSZ *) malloc( iPszArraySize );
  428.  
  429.         if( pszProcess )
  430.         {
  431.             INT i, iNext = 0;
  432.  
  433.             (void) memset( pszProcess, 0, iPszArraySize );
  434.  
  435.             for( i = 1; i < argc && ulExitCode == NO_ERROR; i++ )
  436.                 if( !IsStringNumeric( szArg[ i ] ) )
  437.                 {
  438.                     ulExitCode = CopyProcessName( szArg[ i ], iNext );
  439.  
  440.                     iNext++;
  441.                 }
  442.         }
  443.  
  444.         if( ulExitCode == NO_ERROR )
  445.             if( !(pbh = malloc( BUFFER_SIZE )) )
  446.             {
  447.                 printf( OUT_OF_MEMORY_MSG );
  448.  
  449.                 ulExitCode = ERROR_NOT_ENOUGH_MEMORY;
  450.             }
  451.  
  452.         if( ulExitCode == NO_ERROR )
  453.         {
  454.             USHORT usRetCode = DosQProcStatus( pbh, BUFFER_SIZE );
  455.  
  456.             if( usRetCode )
  457.             {
  458.                 printf( "\nDosQProcStatus failed. RC: %u.", usRetCode );
  459.  
  460.                 ulExitCode = (ULONG) usRetCode;
  461.             }
  462.         }
  463.  
  464.         if( ulExitCode == NO_ERROR )
  465.         {
  466.             UpCaseNames( pbh->pmi );
  467.  
  468.             ulExitCode = BuildActivePidTbl( pbh->ppi );
  469.         }
  470.     }
  471.     else if( argc <= 1 )
  472.     {
  473.         printf( USAGE_INFO );
  474.  
  475.         ulExitCode = ERROR_INVALID_PARAMETER;
  476.     }
  477.  
  478.     return ulExitCode;
  479. }
  480.  
  481. /**********************************************************************/
  482. /*----------------------- StoreCmdLinePids ---------------------------*/
  483. /*                                                                    */
  484. /*  STORE THE PIDS FOUND ON THE COMMANDLINE.                          */
  485. /*                                                                    */
  486. /*  INPUT: number of command-line arguments,                          */
  487. /*         command-line argument array                                */
  488. /*                                                                    */
  489. /*  1. If the argument is numeric, store it in an array that          */
  490. /*     contains pids to kill. Otherwise increment the count of        */
  491. /*     process names found on the command line.                       */
  492. /*                                                                    */
  493. /*  OUTPUT: number of process names found on the command-line         */
  494. /*                                                                    */
  495. /*--------------------------------------------------------------------*/
  496. /**********************************************************************/
  497. INT StoreCmdLinePids( INT argc, PSZ szArg[] )
  498. {
  499.     INT i, iProcessNames = 0;
  500.  
  501.     if( argc > 1 )
  502.         for( i = 1; i < argc; i++ )
  503.             if( IsStringNumeric( szArg[ i ] ) )
  504.                 apid[ iPidCount++ ] = atoi( szArg[ i ] );
  505.             else
  506.                 iProcessNames++;
  507.  
  508.     return iProcessNames;
  509. }
  510.  
  511. /**********************************************************************/
  512. /*----------------------- IsStringNumeric  ---------------------------*/
  513. /*                                                                    */
  514. /*  CHECK IF A STRING IS NUMERIC.                                     */
  515. /*                                                                    */
  516. /*  INPUT: string                                                     */
  517. /*                                                                    */
  518. /*  1. Check if the string contains all digits.                       */
  519. /*                                                                    */
  520. /*  OUTPUT: TRUE or FALSE if numeric or not                           */
  521. /*                                                                    */
  522. /*--------------------------------------------------------------------*/
  523. /**********************************************************************/
  524. BOOL IsStringNumeric( PSZ szString )
  525. {
  526.     BOOL fNumeric = TRUE;
  527.  
  528.     while( *szString && fNumeric )
  529.     {
  530.         if( !isdigit( *szString ) )
  531.             fNumeric = FALSE;
  532.  
  533.         szString++;
  534.     }
  535.  
  536.     return fNumeric;
  537. }
  538.  
  539. /**********************************************************************/
  540. /*-------------------------- CopyProcessName -------------------------*/
  541. /*                                                                    */
  542. /*  COPY A COMMANDLINE PROCESS NAME TO OUR ARRAY OF PROCESS NAMES.    */
  543. /*                                                                    */
  544. /*  INPUT: pointer to commandline process name,                       */
  545. /*         index into process-name array                              */
  546. /*                                                                    */
  547. /*  1. Allocate memory for the process-name string.                   */
  548. /*  2. Copy the process name from the command line into the memory    */
  549. /*     we just allocated. If the process name has no .EXE extension,  */
  550. /*     force it on.                                                   */
  551. /*                                                                    */
  552. /*  OUTPUT: exit code                                                 */
  553. /*                                                                    */
  554. /*--------------------------------------------------------------------*/
  555. /**********************************************************************/
  556. ULONG CopyProcessName( PSZ szProcessName, INT iArrayIndex )
  557. {
  558.     ULONG   ulExitCode = NO_ERROR;
  559.     USHORT  usStringLen;
  560.     PCH     pchExtension;
  561.  
  562.     // Calculate memory needed for the process name. Make sure the
  563.     // memory size is large enough to include an EXE extension,
  564.     // especially if we need to add one.
  565.  
  566.     usStringLen = strlen( szProcessName ) + 1;
  567.  
  568.     if( !(pchExtension = strchr( szProcessName, '.' )) )
  569.         usStringLen += 4;
  570.  
  571.     pszProcess[ iArrayIndex ] = malloc( usStringLen );
  572.  
  573.     if( pszProcess[ iArrayIndex ] )
  574.     {
  575.         (void) strcpy( pszProcess[ iArrayIndex ], szProcessName );
  576.  
  577.         (void) strupr( pszProcess[ iArrayIndex ] );
  578.  
  579.         if( !pchExtension )
  580.             (void) strcat( pszProcess[ iArrayIndex ], ".EXE" );
  581.     }
  582.     else
  583.     {
  584.         printf( OUT_OF_MEMORY_MSG );
  585.  
  586.         ulExitCode = ERROR_NOT_ENOUGH_MEMORY;
  587.     }
  588.  
  589.     return ulExitCode;
  590. }
  591.  
  592. /**********************************************************************/
  593. /*---------------------------- UpCaseNames ---------------------------*/
  594. /*                                                                    */
  595. /*  MAKE PROCESS NAMES IN MODULE TABLE UPPERCASE.                     */
  596. /*                                                                    */
  597. /*  INPUT: pointer to module table                                    */
  598. /*                                                                    */
  599. /*  1. Upcase all names in the module information section to make it  */
  600. /*     easy on the module name string compare.                        */
  601. /*                                                                    */
  602. /*  OUTPUT: nothing                                                   */
  603. /*                                                                    */
  604. /*--------------------------------------------------------------------*/
  605. /**********************************************************************/
  606. VOID UpCaseNames( PMODINFO pmi )
  607. {
  608.     while( pmi )
  609.     {
  610.         (void) strupr( pmi->szModName );
  611.  
  612.         pmi = pmi->pNext;
  613.     }
  614. }
  615.  
  616. /**********************************************************************/
  617. /*------------------------ BuildActivePidTbl -------------------------*/
  618. /*                                                                    */
  619. /*  BUILD AN ARRAY OF ACTIVE PROCESSES USING THE PROCESS INFO SECTION */
  620. /*  OF THE DosQProcStatus BUFFER.                                     */
  621. /*                                                                    */
  622. /*  INPUT: pointer to ProcessInfo section of buffer                   */
  623. /*                                                                    */
  624. /*  1. Get a count of active processes.                               */
  625. /*  2. Allocate memory for the ActiveProcess table.                   */
  626. /*  3. Store information about each active process in the table.      */
  627. /*  4. Sort the table in ascending module number order.               */
  628. /*                                                                    */
  629. /*  OUTPUT: exit code                                                 */
  630. /*                                                                    */
  631. /*--------------------------------------------------------------------*/
  632. /**********************************************************************/
  633. ULONG BuildActivePidTbl( PPROCESSINFO ppi )
  634. {
  635.     PPROCESSINFO ppiLocal = ppi;
  636.     ULONG        ulExitCode = NO_ERROR;
  637.  
  638.     // Count the number of processes in the process info section. The process
  639.     // count in the summary record is not reliable (2/17/92 - version 6.177)
  640.  
  641.     usActiveProcesses = 0;
  642.  
  643.     while( ppiLocal->ulEndIndicator != PROCESS_END_INDICATOR )
  644.     {
  645.         usActiveProcesses++;
  646.  
  647.         // Next PROCESSINFO struct found by taking the address of the first
  648.         // thread control block of the current PROCESSINFO structure and
  649.         // adding the size of a THREADINFO structure times the number of
  650.         // threads
  651.  
  652.         ppiLocal = (PPROCESSINFO) (ppiLocal->ptiFirst+ppiLocal->usThreadCount );
  653.     }
  654.  
  655.     if( !(aActivePid = malloc( usActiveProcesses * sizeof( ACTIVEPID ) )) )
  656.     {
  657.         printf( OUT_OF_MEMORY_MSG );
  658.  
  659.         ulExitCode = ERROR_NOT_ENOUGH_MEMORY;
  660.     }
  661.     else
  662.     {
  663.         register INT i;
  664.  
  665.         for( i = 0; i < usActiveProcesses; i++ )
  666.         {
  667.             aActivePid[ i ].hModRef = ppi->hModRef;
  668.  
  669.             aActivePid[ i ].pid = (PID) ppi->pid;
  670.  
  671.             ppi = (PPROCESSINFO) (ppi->ptiFirst + ppi->usThreadCount);
  672.         }
  673.  
  674.         qsort( aActivePid, usActiveProcesses, sizeof( ACTIVEPID ),
  675.                CompareActivePids );
  676.     }
  677.  
  678.     return ulExitCode;
  679. }
  680.  
  681. /**********************************************************************/
  682. /*------------------------ CompareActivePids -------------------------*/
  683. /*                                                                    */
  684. /*  COMPARE FUNCTION FOR THE QSORT OF THE ACTIVE PID ARRAY. SORTS     */
  685. /*  THE ARRAY IN MODULE HANDLE ORDER.                                 */
  686. /*                                                                    */
  687. /*  INPUT: pointer to first element for compare,                      */
  688. /*         pointer to second element of compare                       */
  689. /*                                                                    */
  690. /*  1. Do the compare.                                                */
  691. /*                                                                    */
  692. /*  OUTPUT: < 0 means first < second                                  */
  693. /*          = 0 means first = second                                  */
  694. /*          > 0 means first > second                                  */
  695. /*                                                                    */
  696. /*--------------------------------------------------------------------*/
  697. /**********************************************************************/
  698. INT CompareActivePids( const void *pActivePid1, const void *pActivePid2 )
  699. {
  700.     if( ((PACTIVEPID)pActivePid1)->hModRef < ((PACTIVEPID)pActivePid2)->hModRef )
  701.         return -1;
  702.     else
  703.     if( ((PACTIVEPID)pActivePid1)->hModRef > ((PACTIVEPID)pActivePid2)->hModRef )
  704.         return +1;
  705.     else
  706.         return 0;
  707. }
  708.  
  709. /**********************************************************************/
  710. /*------------------------------ Term --------------------------------*/
  711. /*                                                                    */
  712. /*  PERFORM PROGRAM TERMINATION                                       */
  713. /*                                                                    */
  714. /*  INPUT: exit code,                                                 */
  715. /*         number of process names entered on the command line        */
  716. /*                                                                    */
  717. /*  1. Free the array of process name strings that we allocated       */
  718. /*     during program initialization.                                 */
  719. /*  2. Free the ActiveProcess array.                                  */
  720. /*  3. Free the buffer allocated for the DosQProcStatus output.       */
  721. /*  4. Return the exit code to the operating system.                  */
  722. /*                                                                    */
  723. /*  OUTPUT: nothing                                                   */
  724. /*                                                                    */
  725. /*--------------------------------------------------------------------*/
  726. /**********************************************************************/
  727. VOID Term( ULONG ulExitCode, INT iProcessNameEntries )
  728. {
  729.     if( pszProcess )
  730.     {
  731.         register INT i;
  732.  
  733.         for( i = 0; i < iProcessNameEntries; i++ )
  734.             if( pszProcess[ i ] )
  735.                 free( pszProcess[ i ] );
  736.  
  737.         free( pszProcess );
  738.     }
  739.  
  740.     if( aActivePid )
  741.         free( aActivePid );
  742.  
  743.     if( pbh )
  744.         free( pbh );
  745.  
  746.     DosExit( EXIT_PROCESS, ulExitCode );
  747. }
  748.  
  749. /**********************************************************************
  750.  *                       END OF SOURCE CODE                           *
  751.  **********************************************************************/ 
  752.