home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / tlist / kill.c < prev    next >
C/C++ Source or Header  |  1996-10-08  |  8KB  |  313 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright (C) 1994-1996 Microsoft Corporation.
  5. *       All rights reserved. 
  6. *       This source code is only intended as a supplement to 
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the 
  9. *       Microsoft samples programs.
  10. \******************************************************************************/
  11.  
  12. /*++
  13.  
  14. Module Name:
  15.  
  16.     kill.c
  17.  
  18. Abstract:
  19.  
  20.     This module implements a task killer application.
  21.  
  22. --*/
  23.  
  24. #include <windows.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include "common.h"
  29.  
  30.  
  31. #define MAX_TASKS           256
  32.  
  33. BOOL        ForceKill;
  34. DWORD       pid;
  35. CHAR        pname[MAX_PATH];
  36. TASK_LIST   tlist[MAX_TASKS];
  37.  
  38.  
  39. VOID GetCommandLineArgs(VOID);
  40. VOID Usage(VOID);
  41.  
  42.  
  43.  
  44. int _cdecl
  45. main(
  46.     int argc,
  47.     char *argv[]
  48.     )
  49. {
  50.     DWORD             i;
  51.     DWORD             numTasks;
  52.     TASK_LIST_ENUM    te;
  53.     int               rval = 0;
  54.     char              tname[PROCESS_SIZE];
  55.     LPSTR             p;
  56.     DWORD             ThisPid;
  57.     OSVERSIONINFO     verInfo = {0};
  58.     LPGetTaskList     GetTaskList;
  59.     LPEnableDebugPriv EnableDebugPriv;
  60.  
  61.  
  62.     GetCommandLineArgs();
  63.  
  64.     if (pid == 0 && pname[0] == 0) {
  65.         printf( "missing pid or task name\n"
  66.                 "type kill /? for help\n");
  67.         return 1;
  68.     }
  69.  
  70.  
  71.     //
  72.     // Determine what system we're on and do the right thing
  73.     //
  74.     verInfo.dwOSVersionInfoSize = sizeof (verInfo);
  75.     GetVersionEx(&verInfo);
  76.  
  77.     switch (verInfo.dwPlatformId)
  78.     {
  79.     case VER_PLATFORM_WIN32_NT:
  80.        GetTaskList     = GetTaskListNT;
  81.        EnableDebugPriv = EnableDebugPrivNT;
  82.        break;
  83.  
  84.     case VER_PLATFORM_WIN32_WINDOWS:
  85.        GetTaskList = GetTaskList95;
  86.        EnableDebugPriv = EnableDebugPriv95;
  87.        break;
  88.  
  89.     default:
  90.        printf ("tlist requires Windows NT or Windows 95\n");
  91.        return 1;
  92.     }
  93.  
  94.  
  95.     //
  96.     // Obtain the ability to manipulate other processes
  97.     //
  98.     EnableDebugPriv();
  99.  
  100.     if (pid) {
  101.         tlist[0].dwProcessId = pid;
  102.         if (KillProcess( tlist, TRUE )) {
  103.             printf( "process #%d killed\n", pid );
  104.             return 0;
  105.         } else {
  106.             printf( "process #%d could not be killed\n", pid );
  107.             return 1;
  108.         }
  109.     }
  110.  
  111.     //
  112.     // get the task list for the system
  113.     //
  114.     numTasks = GetTaskList( tlist, MAX_TASKS );
  115.  
  116.     //
  117.     // enumerate all windows and try to get the window
  118.     // titles for each task
  119.     //
  120.     te.tlist = tlist;
  121.     te.numtasks = numTasks;
  122.     GetWindowTitles( &te );
  123.  
  124.     ThisPid = GetCurrentProcessId();
  125.  
  126.     for (i=0; i<numTasks; i++) {
  127.         //
  128.         // this prevents the user from killing KILL.EXE and
  129.         // it's parent cmd window too
  130.         //
  131.         if (ThisPid == tlist[i].dwProcessId) {
  132.             continue;
  133.         }
  134.         if (MatchPattern( tlist[i].WindowTitle, "*KILL*" )) {
  135.             continue;
  136.         }
  137.  
  138.         tname[0] = 0;
  139.         strcpy( tname, tlist[i].ProcessName );
  140.         p = strchr( tname, '.' );
  141.         if (p) {
  142.             p[0] = '\0';
  143.         }
  144.         if (MatchPattern( tname, pname )) {
  145.             tlist[i].flags = TRUE;
  146.         } else if (MatchPattern( tlist[i].ProcessName, pname )) {
  147.             tlist[i].flags = TRUE;
  148.         } else if (MatchPattern( tlist[i].WindowTitle, pname )) {
  149.             tlist[i].flags = TRUE;
  150.         }
  151.     }
  152.  
  153.     for (i=0; i<numTasks; i++) {
  154.         if (tlist[i].flags) {
  155.             if (KillProcess( &tlist[i], ForceKill )) {
  156.                 printf( "process #%d [%s] killed\n", tlist[i].dwProcessId, tlist[i].ProcessName );
  157.             } else {
  158.                 printf( "process #%d [%s] could not be killed\n", tlist[i].dwProcessId, tlist[i].ProcessName );
  159.                 rval = 1;
  160.             }
  161.         }
  162.     }
  163.  
  164.     return rval;
  165. }
  166.  
  167. VOID
  168. GetCommandLineArgs(
  169.     VOID
  170.     )
  171. {
  172.     char        *lpstrCmd;
  173.     UCHAR       ch;
  174.     char        *p = pname;
  175.  
  176.  
  177.     pid = 0;
  178.     *p = '\0';
  179.  
  180.     lpstrCmd = GetCommandLine();
  181.  
  182.     // skip over program name
  183.     do 
  184.     {
  185.        ch = *lpstrCmd++;
  186.     }
  187.     while (!isspace(ch));
  188.  
  189.     //  skip over any white space following the program name
  190.     while (isspace(ch)) 
  191.     {
  192.        ch = *lpstrCmd++;
  193.     }
  194.  
  195.  
  196.     // Follow this pattern strictly:
  197.     //  KILL [options] <<pid> | <pattern>>\n\n" 
  198.     //  where options is /f,
  199.     //  and PID is a positive or negative decimal number, and
  200.     //  pattern is a string of characters
  201.  
  202.     // Look for an option, which will be prefaced with '/'
  203.     if (ch == '/')
  204.     {
  205.        ch = *lpstrCmd++;
  206.   
  207.        switch (ch) 
  208.        {
  209.        case 'F':     // found "kill /f" so far
  210.        case 'f':
  211.           ForceKill = TRUE;
  212.           ch = *lpstrCmd++;
  213.           break;
  214.  
  215.        case '?':    // found "kill /?"
  216.           Usage();
  217.           return;   // don't do anything after printing usage
  218.           break;
  219.  
  220.        default:
  221.           printf ("%c is an invalid switch\n", ch);  // invalid switch
  222.           return;   
  223.        }
  224.     
  225.        // eat whitepace after option switch
  226.        while (isspace(ch)) 
  227.        {
  228.           ch = *lpstrCmd++;
  229.        }
  230.     }
  231.  
  232.     // In the 3 cases below, look for either a PID or a pattern 
  233.     // a PID could be a positive or negative decimal integer
  234.  
  235.     // Look for a negative PID
  236.     if (ch == '-')
  237.     {
  238.        ch = *lpstrCmd++;
  239.  
  240.        while (isdigit(ch)) 
  241.        {
  242.           pid = pid * 10 - ( ch - '0' );
  243.           ch = *lpstrCmd++;
  244.        }
  245.        return; // found "kill -pid" or "kill /f -pid" so we're done
  246.     }
  247.  
  248.     // Look for a postive PID
  249.     if (isdigit(ch)) 
  250.     {
  251.        while (isdigit(ch)) 
  252.        {
  253.           pid = pid * 10 + ch - '0';
  254.           ch = *lpstrCmd++;
  255.        }
  256.        return;  // found "kill pid" or "kill /f pid" so we're done
  257.     }
  258.  
  259.     // Look for a pattern
  260.     while (ch) 
  261.     {
  262.        *p++ = ch;
  263.        ch = *lpstrCmd++;
  264.     }
  265.     *p = '\0';
  266.     strupr(pname);
  267.  
  268.     return;  // found "kill pattern" or "kill /f pattern" so we're done
  269. }
  270.       
  271.  
  272.  
  273. VOID
  274. Usage(
  275.     VOID
  276.     )
  277.  
  278. /*++
  279.  
  280. Routine Description:
  281.  
  282.     Prints usage text for this tool.
  283.  
  284. Arguments:
  285.  
  286.     None.
  287.  
  288. Return Value:
  289.  
  290.     None.
  291.  
  292. --*/
  293.  
  294. {
  295.     fprintf( stderr, "Microsoft (R) Windows (TM) KILL\n" );
  296.     fprintf( stderr, "Copyright (C) 1994-1996 Microsoft Corp. All rights reserved\n\n" );
  297.     fprintf( stderr, "usage: KILL [options] <<pid> | <pattern>>\n\n" );
  298.     fprintf( stderr, "           [options]:\n" );
  299.     fprintf( stderr, "               /?     This help\n\n" );
  300.     fprintf( stderr, "               /f     Force process kill\n\n" );
  301.     fprintf( stderr, "           <pid>\n" );
  302.     fprintf( stderr, "              This is the process id for the task\n" );
  303.     fprintf( stderr, "               to be killed.  Use TLIST to get a\n" );
  304.     fprintf( stderr, "               valid pid\n\n" );
  305.     fprintf( stderr, "           <pattern>\n" );
  306.     fprintf( stderr, "              The pattern can be a complete task\n" );
  307.     fprintf( stderr, "              name or a regular expression pattern\n" );
  308.     fprintf( stderr, "              to use as a match.  Kill matches the\n" );
  309.     fprintf( stderr, "              supplied pattern against the task names\n" );
  310.     fprintf( stderr, "              and the window titles.\n" );
  311.     ExitProcess(0);
  312. }
  313.