/*
 * Tool name   : HandleProcesses
 * Description : Tool to list, suspend, resume and kill running processes.
 * Version     : 0.2
 *
 * Todo        : -
 *
 * Changes     : 2009.05.21 - Added suspend/resume option
 *
 */

#include <stdio.h>
#include <windows.h>
#include <Tlhelp32.h>

#define MAX_BUF_SIZE 1024




/*
 * Constants, data types and function forward declarations.
 *
 */

void listProcesses();
void killProcessByPID(int pPID);
void killProcessByName(char *pProcName);
void suspendProcessByPID(int pPID);
void resumeProcessByPID(int pPID);
void help(char *pToolName);





/*
 * Program entry point
 *
 */

int main(int argc, char **argv)
{
  int lRetVal = 0;


  if (argc == 1)
  {
    listProcesses();
  } else if (argc == 2 && !strcmp(argv[1], "-l")) {
    listProcesses();
  } else if (argc == 2 && !strcmp(argv[1], "-h")) {
    help(argv[0]);
  } else if (argc == 3 && !strcmp(argv[1], "-n")) {
    killProcessByName(argv[2]);
  } else if (argc == 3 && !strcmp(argv[1], "-p")) {
    killProcessByPID(atoi(argv[2]));
  } else if (argc == 3 && !strcmp(argv[1], "-s")) {
    suspendProcessByPID(atoi(argv[2]));
  } else if (argc == 3 && !strcmp(argv[1], "-r")) {
    resumeProcessByPID(atoi(argv[2]));
  } else {
    help(argv[0]);
  }

  return(lRetVal);
}





/*
 * List all process.
 *
 */

void listProcesses()
{
  HANDLE hProcessSnap = INVALID_HANDLE_VALUE;
  PROCESSENTRY32 pe32;


  if((hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) != INVALID_HANDLE_VALUE)
  {
    pe32.dwSize = sizeof(PROCESSENTRY32);

    if(Process32First(hProcessSnap, &pe32))
    {
      printf("\n\n  PID\t Process name\n\n");
      do
      {
        printf(" %4d\t %s\n", pe32.th32ProcessID, pe32.szExeFile);
      } while(Process32Next(hProcessSnap,&pe32));
    } // if(Process32First(hProcessS...
    CloseHandle(hProcessSnap);
  } // if((hProcessSnap = CreateT...
}



/*
 * Terminate a process by its process name.
 *
 */

void killProcessByName(char *pProcName)
{
  HANDLE hProcessSnap = INVALID_HANDLE_VALUE;
  HANDLE hProcess = INVALID_HANDLE_VALUE;
  PROCESSENTRY32 pe32;


  if((hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) != INVALID_HANDLE_VALUE)
  {
    pe32.dwSize = sizeof(PROCESSENTRY32);

    if(Process32First(hProcessSnap, &pe32))
    {
      do
      {
        if(strstr(pe32.szExeFile, pProcName))
        {
          if ((hProcess = OpenProcess(PROCESS_TERMINATE,0, pe32.th32ProcessID)) != INVALID_HANDLE_VALUE)
		  {
            TerminateProcess(hProcess,0);
            CloseHandle(hProcess);
		  } // if ((hProcess = OpenP...
        } // if(!strcmp(pe32.szExe...
      } while(Process32Next(hProcessSnap,&pe32));
    } // if(Process32First(hProcessS...
    CloseHandle(hProcessSnap);
  } // if((hProcessSnap = CreateT...
}



/*
 * Terminate a process by its process ID.
 *
 */

void killProcessByPID(int pPID)
{
  HANDLE lProcessHandle = INVALID_HANDLE_VALUE;

  if ((lProcessHandle = OpenProcess(PROCESS_TERMINATE, FALSE, pPID)) != INVALID_HANDLE_VALUE)
  {
    TerminateProcess(lProcessHandle, (DWORD) -1);
    CloseHandle(lProcessHandle);
  } // if ((lProcessHandle = OpenP...
}



/*
 * Suspend a process by its process ID
 *
 */

void suspendProcessByPID(int pPID)
{
  HANDLE hThreadSnap;
  THREADENTRY32 lTE32; // = {0};
  HANDLE hThread = INVALID_HANDLE_VALUE;
  DWORD lCPID = GetCurrentProcessId();


  if ((hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0)) != INVALID_HANDLE_VALUE)
  {
    lTE32.dwSize = sizeof(THREADENTRY32); 
    if (Thread32First(hThreadSnap, &lTE32)) 
    {
      do 
      {
        if (lTE32.th32OwnerProcessID == pPID)
        {
          if ((hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, lTE32.th32ThreadID)) != INVALID_HANDLE_VALUE)
          {
            SuspendThread(hThread);
            CloseHandle(hThread);
          } // if ((hThread = OpenThr...
        } // if (lTE32.th32O...
      } while (Thread32Next(hThreadSnap, &lTE32)); 
    } // if (Thread32First(hThr...
    CloseHandle (hThreadSnap);
  } // if ((hThreadSnap = Create...
}




/*
 * Resume a process by its process ID
 *
 */

void resumeProcessByPID(int pPID)
{
  HANDLE hThreadSnap;
  THREADENTRY32 lTE32; // = {0};
  HANDLE hThread = INVALID_HANDLE_VALUE;
  DWORD lCPID = GetCurrentProcessId();


  if ((hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0)) != INVALID_HANDLE_VALUE)
  {
    lTE32.dwSize = sizeof(THREADENTRY32); 
    if (Thread32First(hThreadSnap, &lTE32)) 
    {
      do 
      {
        if (lTE32.th32OwnerProcessID == pPID)
        {
          if ((hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, lTE32.th32ThreadID)) != INVALID_HANDLE_VALUE)
          {
            ResumeThread(hThread);
            CloseHandle(hThread);
          } // if ((hThread = OpenThr...
        } // if (lTE32.th32O...
      } while (Thread32Next(hThreadSnap, &lTE32)); 
    } // if (Thread32First(hThr...
    CloseHandle (hThreadSnap);
  } // if ((hThreadSnap = Create...
}




/*
 * Print tool usage.
 *
 */

void help(char *pToolName)
{
  printf("usage : %s [-h|-l|-r pid|-s pid|-p pid|-n name]\n\n", pToolName);
  printf("        %s -h\t\tprint help\n", pToolName);
  printf("        %s -l\t\tlist all processes\n", pToolName);
  printf("        %s -n name\tkill a process by its process name\n", pToolName);
  printf("        %s -r name\tresume a process by its process id\n", pToolName);
  printf("        %s -s name\tsuspend a process by its process id\n", pToolName);
  printf("        %s -p pid\tkill a process by its process id\n", pToolName);
}
