⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inp.c

📁 Ps2_Keyboard_Polling 键盘接口截获键盘按键信息的源程序。
💻 C
字号:
/* inp.c
 *
 *
 *	- Blocking Interrupt -
 *
 *
 *
 *      University of Seoul, Computer Science
 *      2004920042 Chul-woong, Lee
 *
 * 	contact :: chpie@naver.com
 *                 http://chpie.tistory.com/
 *                 http://cafe.naver.com/inphook.cafe/
 *
 *
 *  2007. 12. 30. 
 */
#include <ntddk.h>
#include "inp.h"

// Function prototypes
VOID DrvUnload(IN PDRIVER_OBJECT);
NTSTATUS DriverEntry(IN PDRIVER_OBJECT, IN PUNICODE_STRING);
NTSTATUS IoDeviceControl(IN PDEVICE_OBJECT, IN PIRP);
NTSTATUS IoReadWrite(IN	PDEVICE_OBJECT, IN PIRP);
NTSTATUS IoDispatch(IN PDEVICE_OBJECT, IN PIRP);

//
// Apic related function
//
void InpIOAPICDisconnection(unsigned long **);
void InpIOAPICConnection(unsigned long **);
ULONG InpGetKeyboardInterruptVector(void);
void Inp_Mask_KeyboardInterrupt(void);
void Inp_Unmask_KeyboardInterrupt(void);

/*
 *
 *      Structures
 *
 */
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, DrvUnload)
#pragma alloc_text(PAGE, IoDeviceControl)
#pragma alloc_text(PAGE, IoReadWrite)
#pragma alloc_text(PAGE, IoDispatch)
#endif

#define NT_DEVICE_NAME  L"\\Device\\INP" // device name and symbolic link name
#define DOS_DEVICE_NAME L"\\DosDevices\\INP"
#define NT_KEYBOARD_NAME0 L"\\Device\\KeyboardClass0" // keyboard driver's name

#define IOCTL_REQUEST_DATA        CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_REGISTER_EVENT      CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)

#define OUTPUT_BUFFER_FULL 0x1
#define INPUT_BUFFER_FULL  0x2
#define MOUSE_OUTPUT_BUFFER_FULL 0x20
#define BUFFER_FULL   (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL)

/*
 *
 *
 *  	Global Variables.
 *
 */
PDEVICE_EXTENSION globalPdx; // backup pointer;
PULONG            IOAPICGate; // mapped physical 0xfec00000 by the InpIOAPICConnection()

// communication
PKEVENT pEvent = NULL;
UCHAR   data[2];


/*
 *
 *          	Codes
 *
 */
void Inp_Mask_KeyboardInterrupt(void)
{
	ULONG Buffer;

	IOAPICGate[0] = 0x10 + 2 * 1; // Open IRQ1's Redirection Table
	Buffer = IOAPICGate[4];

	_asm
	{
		bts Buffer, 16 // raise up bit offset 16 - Interrupt masked
	}

	IOAPICGate[0] = 0x10 + 2 * 1;
	IOAPICGate[4] = Buffer; // write
}

void Inp_Unmask_KeyboardInterrupt(void)
{
	ULONG Buffer;

	IOAPICGate[0] = 0x10 + 2 * 1; // Open IRQ1's Redirection Table
	Buffer = IOAPICGate[4];

	_asm
	{
		btr Buffer, 16 // clean up bit offset 16 - Interrupt is not masked
	}

	IOAPICGate[0] = 0x10 + 2 * 1;
	IOAPICGate[4] = Buffer; // write
}

void InpIOAPICConnection(unsigned long ** MappedVirtualVariable)
{
	PHYSICAL_ADDRESS IOAPIC_AREA;     // i/o apic mapped pointer
	
	//
	//  Connect physical memory 0xfec00000 to [MappedVirtualVariable]
	//
	
	IOAPIC_AREA = RtlConvertLongToLargeInteger(0xFEC00000);
	*MappedVirtualVariable = MmMapIoSpace(IOAPIC_AREA, 0x20, MmNonCached);
}

void InpIOAPICDisconnection(unsigned long ** MappedVirtualVariable)
{
	MmUnmapIoSpace(*MappedVirtualVariable, 0x20);
}

ULONG InpGetKeyboardInterruptVector(void)
{
	ULONG ReturnValue = 0;
	
	// IOREGSEL writing
	IOAPICGate[0] = 0x10 + 2 * 1; // 0x10 + 2 * IRQ, Keyboard's irq is 1
	// read IOWIN
	ReturnValue = IOAPICGate[4] & 0xFF;

	if (!ReturnValue)
	{
		DbgPrint("GetKeyboardInterruptVector() failed. i'll use the default vector 0x93.");
		ReturnValue = 0x93; // default ps/2 keyboard vector on wintelXP
	}
	
	return ReturnValue;
}

char ReadOutputBuffer(char * status, PKEVENT kill)
{
	LARGE_INTEGER delayTime = RtlConvertLongToLargeInteger(-6000); // (n * 100) nano-seconds
	int count;
	char dummy, ret = 0;

	for (count = 0; count < 0xA0000 && !KeReadStateEvent(kill); count++)
	{
		dummy = READ_PORT_UCHAR((PUCHAR)0x64);

		if ((dummy & BUFFER_FULL) == OUTPUT_BUFFER_FULL)
		{
			ret = READ_PORT_UCHAR((PUCHAR)0x60); // Read
			break;
		}

		KeDelayExecutionThread(KernelMode, FALSE, &delayTime);
	}

	if (count == 0xA0000)
	{
		*status = -1; // | Reject
	}
	else if (KeReadStateEvent(kill))
	{
		*status = -1;
		ret = -1;
	}
	else
	{
		*status = dummy;
	}

	return ret;
}

int GenerateScancode(char scancode)
{
	int count = 0xA0000;

	while(--count > 0 && (READ_PORT_UCHAR((PUCHAR)0x64) & INPUT_BUFFER_FULL));
	if (!count) return -1;
	WRITE_PORT_UCHAR((PUCHAR)0x64, 0xD2); // Generate a scancode

	count = 0xA0000;
	while(--count > 0 && (READ_PORT_UCHAR((PUCHAR)0x64) & INPUT_BUFFER_FULL));
	if (!count) return -1;
	WRITE_PORT_UCHAR((PUCHAR)0x60, scancode); // Put a Value

	// wait until drain
	while(!(READ_PORT_UCHAR((PUCHAR)0x64) & OUTPUT_BUFFER_FULL));

	return 0;
}

void ThreadProc(PDEVICE_EXTENSION pdx) // IRQL equals to PASSIVE_LEVEL
{
 	static unsigned char engine[] = { 0xCD, 0x00, 0xC3 }; // int xx, ret
 	unsigned char kccByte; // 0  XLATE  ME  KE  IGNLK  SYSF  MIE  KIE //
	LARGE_INTEGER delayTime = RtlConvertLongToLargeInteger(-6000); // (n * 100) nano-seconds

	//--------------------------------------------------------------------------
	// Write Keyboard controller RAM - disabling keyboard output buffer interrupt
	//
	kccByte = 0x46; // disable KIE bit

	while((READ_PORT_UCHAR((PUCHAR)0x64) & INPUT_BUFFER_FULL));
	WRITE_PORT_UCHAR((PUCHAR)0x64, 0x60); // Write KCCB

	while((READ_PORT_UCHAR((PUCHAR)0x64) & INPUT_BUFFER_FULL));
	WRITE_PORT_UCHAR((PUCHAR)0x60, kccByte);
	//--------------------------------------------------------------------------
	//Inp_Mask_KeyboardInterrupt(); // Double-Blocking

	//
	// Polling
	//
	while(!KeReadStateEvent(&pdx->kill))
	{
		if  (KeGetCurrentIrql() == PASSIVE_LEVEL)
		{
			if ((data[0] = ReadOutputBuffer(&data[1], &pdx->kill)) == -1) break;

			if (data[1] != -1)
			{
				if (pEvent)
					KeSetEvent(pEvent, 0, 0);

				if (GenerateScancode(data[0]))
					DbgPrint("inp :: GenerateScancode() Timeout");

				// Gate Firing - A Keyboard press event emulator
				// 
				//
				//  INT instruction
				//
				//  0xCD imm8 - Interrupt vector number specified by immediate byte.
				//
				engine[1] = (unsigned char)InpGetKeyboardInterruptVector();
				((void (*)(void))engine)(); // <-- Execute _asm INT InpGetKeyboardInterruptVector();
			}		

			KeDelayExecutionThread(KernelMode, FALSE, &delayTime);
		}
	}

	//Inp_Unmask_KeyboardInterrupt();
	//--------------------------------------------------------------------------
	// Write Keyboard controller RAM - enabling keyboard output buffer interrupt
	//
	kccByte = 0x47;

	while((READ_PORT_UCHAR((PUCHAR)0x64) & INPUT_BUFFER_FULL));
	WRITE_PORT_UCHAR((PUCHAR)0x64, 0x60); // Write KCCB

	while((READ_PORT_UCHAR((PUCHAR)0x64) & INPUT_BUFFER_FULL));
	WRITE_PORT_UCHAR((PUCHAR)0x60, kccByte);
	//--------------------------------------------------------------------------
		
	PsTerminateSystemThread(STATUS_SUCCESS);
}

void StopThread(PDEVICE_EXTENSION pdx)
{
	KeSetEvent(&pdx->kill, 0, FALSE);
	KeWaitForSingleObject(pdx->hThread, Executive, KernelMode, FALSE, NULL);
	ObDereferenceObject(pdx->hThread);
}

NTSTATUS StartPollThread(PDEVICE_EXTENSION pdx)
{
	//
	// Programming the Windows Driver Model - p. 764 : Polling device
	//
	NTSTATUS status;
	HANDLE hThread;
	OBJECT_ATTRIBUTES oa;

	KeInitializeEvent(&pdx->kill, NotificationEvent, FALSE);
	InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);

	status = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, &oa, NULL, NULL, (PKSTART_ROUTINE)ThreadProc, pdx);
	
	if (!NT_SUCCESS(status))
		return status;

	ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID*)&pdx->hThread, NULL);

	ZwClose(hThread);

	return STATUS_SUCCESS;
}

/*
 *
 *					 Driver Template
 *
 */

VOID DrvUnload(IN PDRIVER_OBJECT pDriverObject)
{
	PDEVICE_OBJECT pDeviceObject;
	UNICODE_STRING uniWin32NameString;

	StopThread(globalPdx);

	InpIOAPICDisconnection(&IOAPICGate);
	
	if (pEvent)
	{
		ObDereferenceObject(pEvent); // delete event reference
		pEvent = NULL;
	}
		
	pDeviceObject = pDriverObject->DeviceObject;

	RtlInitUnicodeString( &uniWin32NameString, DOS_DEVICE_NAME );
	IoDeleteSymbolicLink( &uniWin32NameString );
	IoDeleteDevice( pDriverObject->DeviceObject );
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath)
{
	PDEVICE_OBJECT pDeviceObject = NULL;
	NTSTATUS ntStatus;
	UNICODE_STRING uniNtNameString, uniWin32NameString;
	int i;

	RtlInitUnicodeString( &uniNtNameString, NT_DEVICE_NAME );
	ntStatus = IoCreateDevice (
		    pDriverObject,
		    sizeof(DEVICE_EXTENSION),	// DeviceExtensionSize
                    &uniNtNameString,
                    FILE_DEVICE_UNKNOWN,	// 
                    0,				// No standard device characteristics
                    FALSE,			// not exclusive device
                    &pDeviceObject
                    );
	if( !NT_SUCCESS(ntStatus) )
	{
		return ntStatus;
	}

	globalPdx = pDeviceObject->DeviceExtension;

	// create dispatch points for create/open, close, unload
	pDriverObject->DriverUnload = DrvUnload;

	RtlInitUnicodeString( &uniWin32NameString, DOS_DEVICE_NAME );
	ntStatus = IoCreateSymbolicLink( &uniWin32NameString, &uniNtNameString );
	if (!NT_SUCCESS(ntStatus))
	{
		IoDeleteDevice( pDriverObject->DeviceObject );
	}

	for( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++ )
		pDriverObject->MajorFunction[i] = IoDispatch;
	
	pDriverObject->MajorFunction[IRP_MJ_READ]	    = 
	pDriverObject->MajorFunction[IRP_MJ_WRITE]	    = IoReadWrite;
	pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IoDeviceControl;

	/////                            /////
	//                                  //
	//             Start!!!             //
	//                                  //
	/////                            /////
	InpIOAPICConnection(&IOAPICGate);
	StartPollThread(globalPdx);

	return STATUS_SUCCESS;
} //DriverEntry

NTSTATUS IoDispatch(IN PDEVICE_OBJECT pDeviceObject, IN	PIRP pIrp)
{
	NTSTATUS iStatus = STATUS_SUCCESS;

	pIrp->IoStatus.Status		= iStatus;
	pIrp->IoStatus.Information	= 0;
	IoCompleteRequest( pIrp, IO_NO_INCREMENT );
	return iStatus;
}

NTSTATUS IoDeviceControl(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
{
	NTSTATUS			iStatus = STATUS_SUCCESS;
	PIO_STACK_LOCATION		pStack;
	ULONG				iTransfered = 0;

	HANDLE hEvent;
	
  	pStack = IoGetCurrentIrpStackLocation(pIrp);
	
	switch( pStack->Parameters.DeviceIoControl.IoControlCode)
	{
		case IOCTL_REGISTER_EVENT:
			hEvent = * (PHANDLE) pIrp->AssociatedIrp.SystemBuffer;
			iStatus = ObReferenceObjectByHandle(hEvent, EVENT_MODIFY_STATE, *ExEventObjectType, pIrp->RequestorMode, (PVOID *)&pEvent, NULL);
			break;
			
		case IOCTL_REQUEST_DATA:
			memcpy( (void *)pIrp->AssociatedIrp.SystemBuffer, (const void *)data, sizeof(char [2]));
			iTransfered = sizeof(char [2]);
			break;

		default:
			iStatus = STATUS_INVALID_PARAMETER;
			break;
	}

	pIrp->IoStatus.Status		= iStatus;
	pIrp->IoStatus.Information	= iTransfered;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	
	return iStatus;
}

NTSTATUS IoReadWrite(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
{
	NTSTATUS			iStatus = STATUS_SUCCESS;
	PIO_STACK_LOCATION		pStack;
	ULONG				iTransfered = 0;

	pStack = IoGetCurrentIrpStackLocation(pIrp);
	
	pIrp->IoStatus.Status		= iStatus;
	pIrp->IoStatus.Information	= iTransfered;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	
	return iStatus;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -