home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************
- * MODULE NAME : killem.c AUTHOR: Rick Fishman *
- * DATE WRITTEN: 10-24-91 *
- * *
- * DESCRIPTION: *
- * *
- * This program kills the specified process(s). It uses the *
- * undocumented function DosQProcStatus to get a buffer filled with *
- * information related to the current state of the system. It then *
- * performs the following using the buffer: *
- * *
- * 1. Get the relevant process information for all active pids into *
- * an array. *
- * 2. Go thru the module information table. For each module found, *
- * see if the module name matches those given on the command *
- * line. If so, compare its module reference number against all *
- * module reference numbers associated with the active pids. If *
- * any match, issue a DosKillProcess against the matching pids. *
- * *
- * UPDATES: *
- * *
- * 5/21/92 - increased buffer to 32k from 16k because of Trap D *
- * on LAN. *
- * *
- * 5/21/92 - changed compare of process name to buffer so that if *
- * 'e' is specified on command line, processes that end *
- * in 'e' will not be killed. *
- * *
- **********************************************************************/
-
-
- /*********************************************************************/
- /*------- Include relevant sections of the OS/2 header files --------*/
- /*********************************************************************/
-
- #define INCL_DOSERRORS
- #define INCL_DOSPROCESS
-
- /**********************************************************************/
- /*----------------------------- INCLUDES -----------------------------*/
- /**********************************************************************/
-
- #include <os2.h>
- #include <process.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include "procstat.h"
-
- /*********************************************************************/
- /*------------------- APPLICATION DEFINITIONS -----------------------*/
- /*********************************************************************/
-
- #define COPYRIGHT_INFO "KillEm.exe, 32-bit, Version 2.0\n" \
- "Copyright (c) Code Blazers, Inc 1991. All " \
- "rights reserved.\n"
-
- #define USAGE_INFO "\nUsage: KillEm processname processname ...\n"
-
- #define OUT_OF_MEMORY_MSG "\nOut of memory!\n"
-
- #define BUFFER_SIZE 0x8000 //** 5/21/92 changed to 32k
-
- /**********************************************************************/
- /*---------------------------- STRUCTURES ----------------------------*/
- /**********************************************************************/
-
- typedef struct _ACTIVEPID // INFO ON AN ACTIVE PROCESS
- {
- USHORT hModRef; // It's module reference handle
- PID pid; // It's Process Id
-
- } ACTIVEPID, *PACTIVEPID;
-
-
- /**********************************************************************/
- /*----------------------- FUNCTION PROTOTYPES ------------------------*/
- /**********************************************************************/
-
- INT main ( INT argc, PSZ szArg[] );
- VOID KillEm ( USHORT usProcessesToKill );
- INT CompareActivePids( const void *pActivePid1, const void *pActivePid2 );
- BOOL ShouldBeKilled ( PSZ szProcessName, USHORT usProcessesToKill );
- VOID FindAndKill ( PMODINFO pmi );
- ULONG KillProcess ( PID pid, PSZ szProcessName );
- ULONG Init ( INT argc, PSZ szArg[] );
- ULONG CopyProcessName ( PSZ szProcessName, INT iArrayIndex );
- VOID UpCaseNames ( PMODINFO pmi );
- ULONG BuildActivePidTbl( PPROCESSINFO ppi );
- VOID Term ( ULONG ulExitCode, INT iProcNameEntries );
-
- /**********************************************************************/
- /*------------------------ GLOBAL VARIABLES --------------------------*/
- /**********************************************************************/
-
- USHORT usActiveProcesses; // Number of active processes
-
- ACTIVEPID *aActivePid; // Array of active processes
-
- PSZ *pszProcess; // Array of command-line process names
-
- PBUFFHEADER pbh; // Pointer to buffer header structure
-
- /**********************************************************************/
- /*------------------------------ MAIN --------------------------------*/
- /* */
- /* MAIN DRIVER FOR PROGRAM. */
- /* */
- /* INPUT: number of command-line arguments, */
- /* command-line argument array */
- /* */
- /* 1. Perform program initialization which will issue the */
- /* DosQProcStatus call and obtain the buffer of information. */
- /* 2. Use the buffer to kill processes that match the names given */
- /* on the command-line. */
- /* 3. Perform program termination. */
- /* */
- /* OUTPUT: nothing */
- /* */
- /*--------------------------------------------------------------------*/
- /**********************************************************************/
- INT main( INT argc, PSZ szArg[] )
- {
- USHORT usProcessesToKill = argc - 1;
- ULONG ulExitCode = Init( argc, szArg );
-
- if( ulExitCode == NO_ERROR )
- KillEm( usProcessesToKill );
-
- Term( ulExitCode, usProcessesToKill );
-
- return 0;
- }
-
- /**********************************************************************/
- /*------------------------------ KillEm ------------------------------*/
- /* */
- /* FIND PROCESSES NAMED ON COMMAND-LINE AND KILL THEM */
- /* */
- /* INPUT: number of processes to attempt to kill */
- /* */
- /* 1. Get the address of the beginning of the module info section. */
- /* 2. For each module information block, check if this is one's */
- /* module name matches any process names given on the command */
- /* line. If it does, kill all active pids whose module handle */
- /* matches its module handle. */
- /* */
- /* OUTPUT: nothing */
- /* */
- /*--------------------------------------------------------------------*/
- /**********************************************************************/
- VOID KillEm( USHORT usProcessesToKill )
- {
- PMODINFO pmi = pbh->pmi;
-
- while( pmi )
- {
- if( ShouldBeKilled( pmi->szModName, usProcessesToKill ) )
- FindAndKill( pmi );
-
- pmi = pmi->pNext;
- }
- }
-
- /**********************************************************************/
- /*------------------------- ShouldBeKilled ---------------------------*/
- /* */
- /* DETERMINE WHETHER OR NOT WE SHOULD KILL THIS PROCESS. */
- /* */
- /* INPUT: process name, */
- /* number of processes we are attempting to kill */
- /* */
- /* 1. For each process name given on the command line, see if it */
- /* is a substring of the process name passed as a parameter. */
- /* The passed module name could be a fully qualified file name. */
- /* */
- /* OUTPUT: TRUE if we should kill it, FALSE if not */
- /* */
- /*--------------------------------------------------------------------*/
- /**********************************************************************/
- BOOL ShouldBeKilled( PSZ szProcessName, USHORT usProcessesToKill )
- {
- BOOL fProcessFound = FALSE;
- PSZ szFound;
- register USHORT usIdx;
-
- for( usIdx = 0; usIdx < usProcessesToKill; usIdx++ )
- {
- //** 5/21/92 bug fix
-
- if( (szFound = strstr( szProcessName, pszProcess[ usIdx ] )) &&
- ( szFound == szProcessName || *(szFound - 1) == '\\' ) )
- {
- fProcessFound = TRUE;
-
- break;
- }
- }
-
- return fProcessFound;
- }
-
- /**********************************************************************/
- /*--------------------------- FindAndKill ----------------------------*/
- /* */
- /* FIND ALL PROCESSES FOR A MODULE HANDLE AND KILL THEM */
- /* */
- /* INPUT: pointer to module info block */
- /* */
- /* 1. For each active pid, match it's module handle against the */
- /* module handle of the passed module information block. If it */
- /* matches, kill that process. */
- /* */
- /* NOTE: The active array table is sorted in ascending module handle */
- /* order. */
- /* */
- /* OUTPUT: nothing */
- /* */
- /*--------------------------------------------------------------------*/
- /**********************************************************************/
- VOID FindAndKill( PMODINFO pmi )
- {
- USHORT usKilled = 0;
- register INT i;
-
- for( i = 0; i < usActiveProcesses; i++ )
- {
- if( aActivePid[ i ].hModRef > pmi->hMod )
- break;
-
- if( aActivePid[ i ].hModRef == pmi->hMod )
- if( KillProcess( aActivePid[ i ].pid, pmi->szModName ) == NO_ERROR )
- usKilled++;
- }
-
- if( !usKilled )
- printf( "\nCould not find PID for %s!\n", pmi->szModName );
- }
-
- /**********************************************************************/
- /*--------------------------- KillProcess ----------------------------*/
- /* */
- /* KILL A PROCESS BY PID */
- /* */
- /* INPUT: process id, */
- /* process name */
- /* */
- /* 1. Issue a DosKillProcess for the passed process id. */
- /* */
- /* OUTPUT: return code from DosKillProcess */
- /* */
- /*--------------------------------------------------------------------*/
- /**********************************************************************/
- ULONG KillProcess( PID pid, PSZ szProcessName )
- {
- ULONG ulRetCode = DosKillProcess( DKP_PROCESS, pid );
-
- if( ulRetCode )
- {
- if( ulRetCode != ERROR_INVALID_PROCID )
- printf( "\nFound %s (pid %u) but DosKillProcess failed (RC=%u)",
- szProcessName, pid, ulRetCode );
- }
- else
- printf( "\nFound %s (pid %u) and Killed it", szProcessName, pid );
-
- fflush( stdout );
-
- return ulRetCode;
- }
-
- /**********************************************************************/
- /*------------------------------ Init --------------------------------*/
- /* */
- /* PERFORM PROGRAM INITIALIZATION */
- /* */
- /* INPUT: number of command-line arguments, */
- /* command-line argument array */
- /* */
- /* 1. Print copyright notice. */
- /* 2. If no process names were specified on the command line, exit. */
- /* 3. Allocate memory for an array of pointers to process name */
- /* strings. We will use this array during the main program loop */
- /* to identify process names to kill. */
- /* 4. Allocate memory for each string in the array. */
- /* 5. Copy the process names from the command line into the memory */
- /* we just allocated. */
- /* 6. Alocate memory for the output from DosQProcStatus. */
- /* 7. Make the DosQProcStatus call. */
- /* 8. Uppercase the names in the module information section to make */
- /* string compares easier during main program logic. */
- /* 9. Build an array of information related to active processes. */
- /* */
- /* OUTPUT: exit code */
- /* */
- /*--------------------------------------------------------------------*/
- /**********************************************************************/
- ULONG Init( INT argc, PSZ szArg[] )
- {
- ULONG ulExitCode = NO_ERROR;
- USHORT usPszArraySize = (argc - 1) * sizeof( PSZ );
-
- (void) printf( COPYRIGHT_INFO );
-
- if( argc > 1 )
- {
- // Allocate memory for the array of ASCIIZ process names passed on the
- // command line. We can't just use the commandline because we may need
- // to add .EXE to the end of the process name. So we allocate our own
- // array of strings so we have enough room for that extension if
- // necessary.
-
- pszProcess = (PSZ *) malloc( usPszArraySize );
-
- if( pszProcess )
- {
- register INT i;
-
- (void) memset( pszProcess, 0, usPszArraySize );
-
- for( i = 1; i < argc && ulExitCode == NO_ERROR; i++ )
- ulExitCode = CopyProcessName( szArg[ i ], i - 1 );
- }
-
- if( ulExitCode == NO_ERROR )
- if( !(pbh = malloc( BUFFER_SIZE )) )
- {
- printf( OUT_OF_MEMORY_MSG );
-
- ulExitCode = ERROR_NOT_ENOUGH_MEMORY;
- }
-
- if( ulExitCode == NO_ERROR )
- {
- USHORT usRetCode = DosQProcStatus( pbh, BUFFER_SIZE );
-
- if( usRetCode )
- {
- printf( "\nDosQProcStatus failed. RC: %u.", usRetCode );
-
- ulExitCode = (ULONG) usRetCode;
- }
- }
-
- if( ulExitCode == NO_ERROR )
- {
- UpCaseNames( pbh->pmi );
-
- ulExitCode = BuildActivePidTbl( pbh->ppi );
- }
- }
- else
- {
- printf( USAGE_INFO );
-
- ulExitCode = ERROR_INVALID_PARAMETER;
- }
-
- return ulExitCode;
- }
-
- /**********************************************************************/
- /*-------------------------- CopyProcessName -------------------------*/
- /* */
- /* COPY A COMMANDLINE PROCESS NAME TO OUR ARRAY OF PROCESS NAMES. */
- /* */
- /* INPUT: pointer to commandline process name, */
- /* index into process-name array */
- /* */
- /* 1. Allocate memory for the process-name string. */
- /* 2. Copy the process name from the command line into the memory */
- /* we just allocated. If the process name has no .EXE extension, */
- /* force it on. */
- /* */
- /* OUTPUT: exit code */
- /* */
- /*--------------------------------------------------------------------*/
- /**********************************************************************/
- ULONG CopyProcessName( PSZ szProcessName, INT iArrayIndex )
- {
- ULONG ulExitCode = NO_ERROR;
- USHORT usStringLen;
- PCH pchExtension;
-
- // Calculate memory needed for the process name. Make sure the
- // memory size is large enough to include an EXE extension,
- // especially if we need to add one.
-
- usStringLen = strlen( szProcessName ) + 1;
-
- if( !(pchExtension = strchr( szProcessName, '.' )) )
- usStringLen += 4;
-
- pszProcess[ iArrayIndex ] = malloc( usStringLen );
-
- if( pszProcess[ iArrayIndex ] )
- {
- (void) strcpy( pszProcess[ iArrayIndex ], szProcessName );
-
- (void) strupr( pszProcess[ iArrayIndex ] );
-
- if( !pchExtension )
- (void) strcat( pszProcess[ iArrayIndex ], ".EXE" );
- }
- else
- {
- printf( OUT_OF_MEMORY_MSG );
-
- ulExitCode = ERROR_NOT_ENOUGH_MEMORY;
- }
-
- return ulExitCode;
- }
-
- /**********************************************************************/
- /*---------------------------- UpCaseNames ---------------------------*/
- /* */
- /* MAKE PROCESS NAMES IN MODULE TABLE UPPERCASE. */
- /* */
- /* INPUT: pointer to module table */
- /* */
- /* 1. Upcase all names in the module information section to make it */
- /* easy on the module name string compare. */
- /* */
- /* OUTPUT: nothing */
- /* */
- /*--------------------------------------------------------------------*/
- /**********************************************************************/
- VOID UpCaseNames( PMODINFO pmi )
- {
- while( pmi )
- {
- (void) strupr( pmi->szModName );
-
- pmi = pmi->pNext;
- }
- }
-
- /**********************************************************************/
- /*------------------------ BuildActivePidTbl -------------------------*/
- /* */
- /* BUILD AN ARRAY OF ACTIVE PROCESSES USING THE PROCESS INFO SECTION */
- /* OF THE DosQProcStatus BUFFER. */
- /* */
- /* INPUT: pointer to ProcessInfo section of buffer */
- /* */
- /* 1. Get a count of active processes. */
- /* 2. Allocate memory for the ActiveProcess table. */
- /* 3. Store information about each active process in the table. */
- /* 4. Sort the table in ascending module number order. */
- /* */
- /* OUTPUT: exit code */
- /* */
- /*--------------------------------------------------------------------*/
- /**********************************************************************/
- ULONG BuildActivePidTbl( PPROCESSINFO ppi )
- {
- PPROCESSINFO ppiLocal = ppi;
- ULONG ulExitCode = NO_ERROR;
-
- // Count the number of processes in the process info section. The process
- // count in the summary record is not reliable (2/17/92 - version 6.177)
-
- usActiveProcesses = 0;
-
- while( ppiLocal->ulEndIndicator != PROCESS_END_INDICATOR )
- {
- usActiveProcesses++;
-
- // Next PROCESSINFO struct found by taking the address of the first
- // thread control block of the current PROCESSINFO structure and
- // adding the size of a THREADINFO structure times the number of
- // threads
-
- ppiLocal = (PPROCESSINFO) (ppiLocal->ptiFirst+ppiLocal->usThreadCount );
- }
-
- if( !(aActivePid = malloc( usActiveProcesses * sizeof( ACTIVEPID ) )) )
- {
- printf( OUT_OF_MEMORY_MSG );
-
- ulExitCode = ERROR_NOT_ENOUGH_MEMORY;
- }
- else
- {
- register INT i;
-
- for( i = 0; i < usActiveProcesses; i++ )
- {
- aActivePid[ i ].hModRef = ppi->hModRef;
-
- aActivePid[ i ].pid = (PID) ppi->pid;
-
- ppi = (PPROCESSINFO) (ppi->ptiFirst + ppi->usThreadCount);
- }
-
- qsort( aActivePid, usActiveProcesses, sizeof( ACTIVEPID ),
- CompareActivePids );
- }
-
- return ulExitCode;
- }
-
- /**********************************************************************/
- /*------------------------ CompareActivePids -------------------------*/
- /* */
- /* COMPARE FUNCTION FOR THE QSORT OF THE ACTIVE PID ARRAY. SORTS */
- /* THE ARRAY IN MODULE HANDLE ORDER. */
- /* */
- /* INPUT: pointer to first element for compare, */
- /* pointer to second element of compare */
- /* */
- /* 1. Do the compare. */
- /* */
- /* OUTPUT: < 0 means first < second */
- /* = 0 means first = second */
- /* > 0 means first > second */
- /* */
- /*--------------------------------------------------------------------*/
- /**********************************************************************/
- INT CompareActivePids( const void *pActivePid1, const void *pActivePid2 )
- {
- if( ((PACTIVEPID)pActivePid1)->hModRef < ((PACTIVEPID)pActivePid2)->hModRef )
- return -1;
- else
- if( ((PACTIVEPID)pActivePid1)->hModRef > ((PACTIVEPID)pActivePid2)->hModRef )
- return +1;
- else
- return 0;
- }
-
- /**********************************************************************/
- /*------------------------------ Term --------------------------------*/
- /* */
- /* PERFORM PROGRAM TERMINATION */
- /* */
- /* INPUT: exit code, */
- /* number of process names entered on the command line */
- /* */
- /* 1. Free the array of process name strings that we allocated */
- /* during program initialization. */
- /* 2. Free the ActiveProcess array. */
- /* 3. Free the buffer allocated for the DosQProcStatus output. */
- /* 4. Return the exit code to the operating system. */
- /* */
- /* OUTPUT: nothing */
- /* */
- /*--------------------------------------------------------------------*/
- /**********************************************************************/
- VOID Term( ULONG ulExitCode, INT iProcessNameEntries )
- {
- if( pszProcess )
- {
- register INT i;
-
- for( i = 0; i < iProcessNameEntries; i++ )
- if( pszProcess[ i ] )
- free( pszProcess[ i ] );
-
- free( pszProcess );
- }
-
- if( aActivePid )
- free( aActivePid );
-
- if( pbh )
- free( pbh );
-
- DosExit( EXIT_PROCESS, ulExitCode );
- }
-
- /**********************************************************************
- * END OF SOURCE CODE *
- **********************************************************************/