/*
InterruptHook
Copyright (C) 2003  Alexander M.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#include <ntddk.h>
#include "hook.h"

VOID
LoadIDT(
		OUT	PIDT		pIdt )
{
	__asm
	{
		MOV EAX, [pIdt]
		SIDT [EAX]
	}
}

VOID
LoadINTVector(
		IN	PIDT		pIdt,
		IN	UCHAR		iVector,
		OUT	PINT_VECTOR	pVector )
{
	__try
	{
		DWORD dwBase = pIdt->dwBase + iVector * sizeof(INT_VECTOR);
		memcpy( pVector, (const void *)dwBase, sizeof(INT_VECTOR) );
	}
	__except( 1 )
	{
		KdPrint( ( "LoadINTVector: Exception\n" ));
	}

//	KdPrint( ( "LoadINTVector: Vector 0x%.2X successfully dumped\n", iVector ));
}

VOID
SaveINTVector(
		IN	PIDT		pIdt,
		IN	UCHAR		iVector,
		IN	PINT_VECTOR	pVector )
{
	__try
	{
		DWORD dwBase = pIdt->dwBase + iVector * sizeof(INT_VECTOR);
		__asm{ PUSHFD };
		__asm{ CLI };
		memcpy( (void *)dwBase, pVector, sizeof(INT_VECTOR) );
		__asm{ POPFD };
	}
	__except( 1 )
	{
		KdPrint( ( "SaveINTVector: Exception\n" ));
	}

//	KdPrint( ( "SaveINTVector: Vector 0x%.2X successfully set\n", iVector ));
}

VOID
HookInterrupt(UCHAR iVec, void (*InterruptHandler)( void ), WORD selector)
{
	IDT			Idt;
	INT_VECTOR	Vec;
	ULONG		i;

	LoadIDT( &Idt );

	LoadINTVector(
			&Idt,
			iVec,
			&Vec);

	KdPrint( ( "HookInterrupt: Vector - %.2X, 0x%.8X, 0x%.8X\n", iVec, VEC_OFFSET_TO_DWORD( Vec ), InterruptHandler));
	DWORD_TO_VEC_OFFSET( Vec, InterruptHandler);

	Vec.wSelector = selector;

	SaveINTVector(
			&Idt,
			iVec,
			&Vec );

}

VOID
BackupInterrupt(UCHAR iVec, OUT PINT_VECTOR Vec)
{
	IDT			Idt;
	ULONG		i;

	LoadIDT( &Idt );

	LoadINTVector(
			&Idt,
			iVec,
			Vec);
}

VOID
RestoreInterrupt(UCHAR iVec, IN PINT_VECTOR Vec)
{
	IDT			Idt;
	ULONG		i;

	LoadIDT( &Idt );

	SaveINTVector(
			&Idt,
			iVec,
			Vec);
}

VOID
CopyInterrupt(UCHAR fromVec, UCHAR toVec)
{
	IDT			Idt;
	INT_VECTOR	Vec;
	ULONG		i;

	LoadIDT( &Idt );

	LoadINTVector(
			&Idt,
			fromVec,
			&Vec);

	KdPrint( ( "CopyInterrupt: Vector, 0x%.8X\n", VEC_OFFSET_TO_DWORD( Vec )));

	SaveINTVector(
			&Idt,
			toVec,
			&Vec );

}
