extern "C"
{

#include "hooking.h"
#include "hooked_proc.h"
#include "debug.h"

int hooking_hook(void);
int hooking_unhook(void);

//import of SDT
__declspec(dllimport) SERVICE_DESCRIPTOR_ENTRY KeServiceDescriptorTable;
} //extern "C"

//global hooking flag
int hook_active=FALSE;


/*
 this function installs SDT hook and returns TRUE if succeeded
*/
int hooking_hook(void)
{
  DbgMsg("hooking.cpp: hooking_hook()");
  if (hook_active)
  {
    DbgMsg("hooking.cpp: hooking_hook error: hook is already active");
    DbgMsg("hooking.cpp: hooking_hook(-):FALSE");
    return FALSE;
  }

  /*
   now we are changing SDT
   we have to use atomic operations because of multiprocessor machines

   we also have to disable WP bit for WXP SP2 and higher
   to be able to write to SDT
  */

  _asm                                          //disable WP bit
  {
    mov eax,cr0                                 //move CR0 register into EAX
    and eax,not 000010000h                      //disable WP bit 
    mov cr0,eax                                 //write register back
  }

  OldZwOpenProcess=(ZW_OPEN_PROCESS)InterlockedExchange((PLONG)&SYSTEM_SERVICE(ZwOpenProcess),(ULONG)NewZwOpenProcess);

  _asm                                          //enable WP bit
  {
    mov eax,cr0                                 //move CR0 register into EAX
    or eax,000010000h                           //enable WP bit         
    mov cr0,eax                                 //write register back           
  }

  DbgMsg("OldZwOpenProcess=0x%.8X",OldZwOpenProcess);
  DbgMsg("ZwOpenProcess=0x%.8X",SYSTEM_SERVICE(ZwOpenProcess));

  hook_active=TRUE;
  DbgMsg("hooking.cpp: hooking_hook(-):TRUE");
  return TRUE;
}


/*
 this function uninstalls SDT hook and returns TRUE if succeeded
*/

int hooking_unhook(void)
{
  DbgMsg("hooking.cpp: hooking_unhook()");
  if (!hook_active)
  {
    DbgMsg("hooking.cpp: hooking_unhook error: hook is not active");
    DbgMsg("hooking.cpp: hooking_unhook(-):FALSE");
    return FALSE;
  }

  DbgMsg("NewZwOpenProcess=0x%.8X",(ULONG)NewZwOpenProcess);


  /*
   similar actions as in hooking_hook()
  */
  _asm                                          //disable WP bit
  {
    mov eax,cr0                                 //move CR0 register into EAX
    and eax,not 000010000h                      //disable WP bit 
    mov cr0,eax                                 //write register back
  }

  InterlockedExchange((PLONG)&SYSTEM_SERVICE(ZwOpenProcess),(ULONG)OldZwOpenProcess);

  _asm                                          //enable WP bit
  {
    mov eax,cr0                                 //move CR0 register into EAX
    or eax,000010000h                           //enable WP bit         
    mov cr0,eax                                 //write register back           
  }

  DbgMsg("ZwOpenProcess=0x%.8X",SYSTEM_SERVICE(ZwOpenProcess));

  hook_active=FALSE;
  DbgMsg("hooking.cpp: hooking_unhook(-):TRUE");
  return TRUE;
}