
/**
 * @file pproc.c
 *
 * Hlavni soubor programu pproc, ktery dovoluje pracovat s chranenymi procesy
 * z uzivatelskeho rezimu. Konkretne umoznuje menit priznak, ktery urcuje, zda
 * se ma system k danemu procesu chovat jako k procesu chranenemu.
 *
 * Syntax: pproc <Operace>
 * 
 * Mozne operace:
 * --list-protected            Vypise seznam chranenych procesu. Do seznamu
 *                             zaradi i takove procesy, kde pokus o zjisteni
 *                             priznaku chraneneho procesu skoncil chybou (tuto
 *                             skutecnost take vypise)
 *
 * --protect PID               Oznaci proces se zadanym PID za chraneny
 *
 * --unprotect PID             Oznaci proces se zadanym PID jako normalni
 *                             proces (odstrani priznak chraneneho procesu).
 *
 * --do-process-tests PID      Otestuje moznosti ziskani pristupu s ruznym
 *                             opravnenim k procesu se zadanym PID a jeho 
 *                             vlaknum
 *
 * --do-thread-tests TID       Otestuje, jaka pristupova prava lze ziskat k
 *                             vlaknu se zadanym TID.
 */

#include <stdio.h>
#include <windows.h>
#include <TlHelp32.h>
#include "../../shared\common.h"
#include "scmDrivers.h"
#include "protect.h"
#include "tests.h"


/** Inicializuje vsechny soucasti programu.
 *
 *  Rutina take ziska opravneni SeDebugPrivilege.
 *
 *  @return Funkce vrati TRUE v pripade uspechu a FALSE v pripade neuspechu.
 */
BOOL ModulesInit(VOID)
{
  BOOL Ret = FALSE;

  Ret = CommonInit();
  if (Ret) {
    Ret = EnablePrivilege(L"SeDebugPrivilege");
    if (Ret) {
      Ret = scmInit();
      if (Ret) {
        Ret = ProtectModuleInit();
        if (!Ret) {
          scmFinit();
          CommonFinit();
        }
	  } else CommonFinit();
    } else CommonFinit();
  }

  return Ret;
}


/** Zajisti uklid po vsech soucastech programu.
 */
VOID ModulesFinit(VOID)
{
  ProtectModuleFinit();
  scmFinit();
  CommonFinit();

  return;
}


/** Vytiskne seznam chranenych procesu a procesu, u kterych pri zjistovani
 *  "chraneneho" priznaku doslo k chybe.
 */
VOID PrintProtectedProcesses(VOID)
{
  BOOL Ret = FALSE;
  BOOL Protected = FALSE;
  PROCESSENTRY32W pe;
  HANDLE hSnap = INVALID_HANDLE_VALUE;
  DebugMsg(("pproc.c: PrintProtectedProcesses()\n"));

  hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if (hSnap != INVALID_HANDLE_VALUE) {
    pe.dwSize = sizeof(pe);
    if (Process32FirstW(hSnap, &pe)) {
      do {
        if (pe.th32ProcessID == 0)
          continue;

        Ret = IsProtectedProcess((HANDLE)pe.th32ProcessID, &Protected);
        if (!Ret)
          printf("%S\t%u\tChyba\n", pe.szExeFile, pe.th32ProcessID);
		else if (Protected)
          printf("%S\t%u\tChraneny\n", pe.szExeFile, pe.th32ProcessID);
      } while (Process32NextW(hSnap, &pe));
    } else printf("Nepodarilo se ziskat informace o pervnim procesu v seznamu. Chyba %u\n", GetLastError());

    CloseHandle(hSnap);
  } else printf("Nepodarilo se zjistit seznam procesu. Chyba %u\n", GetLastError());

  DebugMsg(("pproc.c: PrintProtectedProcesses(-)\n"));
  return;
}



/** Hlavni funkce programu.
 *
 * Rutina se na zaklade zadanych argumentu prikazove radky rozhodne a provede
 * prislusnou akci. jejich popis naleznete v popisu k souboru pproc.c.
 *
 * @param argc Pocet argumentu prikazove radky (vcetne argumentu s plnym nazvem
 * souboru programu).
 * @param argv Hodnoty jednotlivych argumentu.
 *
 * @param Funkce vzdy vraci nulu.
 */
int main(int argc, char **argv)
{
  DWORD OID = 0;
  BOOL Ret = FALSE;
  BOOL Protected = FALSE;

  Ret = ModulesInit();
  if (Ret) {
    if (argc == 3) {
      OID = strtoul(argv[2], NULL, 0);
      if (OID != ULONG_MAX) {
        if (strncmp(argv[1], "--protect", strlen("--protect")) == 0) {
          Ret = ProtectProcess((HANDLE)OID);
          printf("%s\n", Ret ? "Operace skoncila uspechem" : "Operace se nezdarila");
        } else if (strncmp(argv[1], "--unprotect", strlen("--unprotect")) == 0) {
          Ret = UnprotectProcess((HANDLE)OID);
          printf("%s\n", Ret ? "Operace skoncila uspechem" : "Operace se nezdarila");
        } else if (strncmp(argv[1], "--is-protected", strlen("--is-protected")) == 0) {
          Ret = IsProtectedProcess((HANDLE)OID, &Protected);
          if (Ret)
            printf("Proces %u %s chranenym procesem\n", OID, Protected ? "je" : "neni");
		  else printf("Operace se nezdarila\n");
        } else if (strncmp(argv[1], "--do-thread-tests", strlen("--do-thread-tests")) == 0) {
          DoThreadTests(OID);
        } else if (strncmp(argv[1], "--do-process-tests", strlen("--do-process-tests")) == 0) {
          DoProcessTests(OID);
        } else printf("Neznamy prikaz\n");
      } else printf("Neplatne PID/TID\n");
    } else if (argc == 2) {
      if (strncmp(argv[1], "--list-protected", strlen("--list-protected")) == 0)
        PrintProtectedProcesses();
    } else printf("Spatny pocet parametru\n");

    ModulesFinit();
  } else printf("Chyba pri inicializaci\n");

  return 0;
}
